harii66 commited on
Commit
56eed10
·
verified ·
1 Parent(s): fb22294

Update static/css/style.css

Browse files
Files changed (1) hide show
  1. static/css/style.css +1188 -1156
static/css/style.css CHANGED
@@ -1,1157 +1,1189 @@
1
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
2
-
3
- @keyframes shimmer {
4
- 0% { background-position: -468px 0; }
5
- 100% { background-position: 468px 0; }
6
- }
7
-
8
- .skeleton {
9
- background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
10
- background-size: 468px 100%;
11
- animation: shimmer 1.2s ease-in-out infinite;
12
- border-radius: 8px;
13
- }
14
-
15
- .skeleton-text { height: 16px; margin-bottom: 8px; }
16
- .skeleton-title { height: 24px; width: 60%; margin-bottom: 12px; }
17
-
18
- /* 性能优化 */
19
- .notification, .modal-overlay, .loading-overlay {
20
- will-change: opacity, transform;
21
- transform: translateZ(0);
22
- }
23
-
24
- .channel-item, .epg-item {
25
- contain: layout style paint;
26
- }
27
-
28
- /* 优化动画 */
29
- .fab-button {
30
- transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
31
- }
32
-
33
- .fab-button:hover {
34
- transform: translateY(-4px);
35
- }
36
-
37
- :root {
38
- --primary: #6366f1;
39
- --primary-dark: #4f46e5;
40
- --success: #10b981;
41
- --warning: #f59e0b;
42
- --danger: #ef4444;
43
- --dark: #1e293b;
44
- --light: #f8fafc;
45
- --border: #e2e8f0;
46
- --shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
47
- }
48
-
49
- * {
50
- margin: 0;
51
- padding: 0;
52
- box-sizing: border-box;
53
- }
54
-
55
- body {
56
- font-family: 'Inter', -apple-system, sans-serif;
57
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
58
- background-attachment: fixed;
59
- min-height: 100vh;
60
- line-height: 1.5;
61
- font-size: 14px;
62
- color: var(--dark);
63
- -webkit-font-smoothing: antialiased;
64
- }
65
-
66
- *, *::before, *::after {
67
- animation: none !important;
68
- transition: none !important;
69
- }
70
-
71
- .notification,
72
- .login-overlay,
73
- .epg-video-modal {
74
- transition: opacity 0.15s ease !important;
75
- }
76
-
77
- .app-container {
78
- display: flex;
79
- flex-direction: column;
80
- min-height: 100vh;
81
- max-width: 1600px;
82
- margin: 20px auto;
83
- background: rgba(255, 255, 255, 0.95);
84
- border-radius: 20px;
85
- box-shadow: var(--shadow);
86
- overflow: hidden;
87
- contain: layout style paint;
88
- }
89
-
90
- .app-body {
91
- flex: 1;
92
- padding: 20px 30px;
93
- transform: translateZ(0);
94
- will-change: scroll-position;
95
- }
96
-
97
- .header {
98
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
99
- color: white;
100
- padding: 20px 30px;
101
- contain: layout style paint;
102
- }
103
-
104
- .header-top {
105
- display: flex;
106
- justify-content: space-between;
107
- align-items: center;
108
- margin-bottom: 15px;
109
- gap: 15px;
110
- flex-wrap: wrap;
111
- }
112
-
113
- .header h1 {
114
- font-size: 1.8em;
115
- font-weight: 700;
116
- margin-bottom: 5px;
117
- }
118
-
119
- .subtitle {
120
- font-size: 0.9em;
121
- opacity: 0.9;
122
- }
123
-
124
- .status-bar {
125
- display: flex;
126
- justify-content: center;
127
- gap: 20px;
128
- flex-wrap: wrap;
129
- font-size: 0.85em;
130
- }
131
-
132
- .status-item {
133
- background: rgba(255, 255, 255, 0.2);
134
- padding: 8px 15px;
135
- border-radius: 20px;
136
- display: flex;
137
- align-items: center;
138
- gap: 8px;
139
- border: 1px solid rgba(255, 255, 255, 0.3);
140
- }
141
-
142
- .btn-logout {
143
- padding: 10px 20px;
144
- background: rgba(255, 255, 255, 0.2);
145
- color: white;
146
- border: 2px solid rgba(255, 255, 255, 0.5);
147
- border-radius: 20px;
148
- cursor: pointer;
149
- font-size: 0.9em;
150
- font-weight: 600;
151
- }
152
-
153
- .btn-logout:hover {
154
- background: rgba(255, 255, 255, 0.3);
155
- }
156
-
157
- .user-type-badge {
158
- display: inline-block;
159
- padding: 3px 10px;
160
- border-radius: 15px;
161
- font-size: 0.7em;
162
- font-weight: 700;
163
- margin-left: 8px;
164
- }
165
-
166
- .user-type-badge.admin {
167
- background: linear-gradient(135deg, #f59e0b 0%, #ef4444 100%);
168
- color: white;
169
- }
170
-
171
- .user-type-badge.user {
172
- background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
173
- color: white;
174
- }
175
-
176
- .tabs {
177
- display: flex;
178
- background: rgba(248, 250, 252, 0.8);
179
- border-bottom: 1px solid var(--border);
180
- overflow-x: auto;
181
- scrollbar-width: none;
182
- contain: layout style;
183
- }
184
-
185
- .tabs::-webkit-scrollbar {
186
- display: none;
187
- }
188
-
189
- .tab-button {
190
- flex: 1;
191
- padding: 15px 18px;
192
- background: transparent;
193
- border: none;
194
- cursor: pointer;
195
- font-size: 0.9em;
196
- color: var(--dark);
197
- font-weight: 500;
198
- text-decoration: none;
199
- text-align: center;
200
- min-width: 120px;
201
- border-bottom: 3px solid transparent;
202
- }
203
-
204
- .tab-button:hover {
205
- background: rgba(99, 102, 241, 0.05);
206
- }
207
-
208
- .tab-button.active {
209
- background: white;
210
- font-weight: 600;
211
- color: var(--primary);
212
- border-bottom-color: var(--primary);
213
- }
214
-
215
- .btn {
216
- padding: 10px 20px;
217
- border: none;
218
- border-radius: 10px;
219
- cursor: pointer;
220
- font-size: 0.9em;
221
- font-weight: 600;
222
- contain: layout style paint;
223
- }
224
-
225
- .btn:hover:not(:disabled) {
226
- opacity: 0.9;
227
- }
228
-
229
- .btn:disabled {
230
- opacity: 0.6;
231
- cursor: not-allowed;
232
- }
233
-
234
- .btn-primary {
235
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
236
- color: white;
237
- }
238
-
239
- .btn-success {
240
- background: linear-gradient(135deg, #10b981 0%, #059669 100%);
241
- color: white;
242
- }
243
-
244
- .btn-warning {
245
- background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
246
- color: white;
247
- }
248
-
249
- .btn-danger {
250
- background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
251
- color: white;
252
- }
253
-
254
- .form-control {
255
- width: 100%;
256
- padding: 12px 15px;
257
- border: 2px solid var(--border);
258
- border-radius: 10px;
259
- font-size: 0.9em;
260
- background: white;
261
- font-family: inherit;
262
- }
263
-
264
- .form-control:focus {
265
- outline: none;
266
- border-color: var(--primary);
267
- }
268
-
269
- .form-group {
270
- margin-bottom: 15px;
271
- }
272
-
273
- .form-group label {
274
- display: block;
275
- margin-bottom: 6px;
276
- font-weight: 600;
277
- color: var(--dark);
278
- font-size: 0.85em;
279
- }
280
-
281
- .section-header {
282
- display: flex;
283
- justify-content: space-between;
284
- align-items: center;
285
- margin-bottom: 20px;
286
- gap: 15px;
287
- flex-wrap: wrap;
288
- }
289
-
290
- .stats-box {
291
- background: rgba(99, 102, 241, 0.1);
292
- padding: 12px 20px;
293
- border-radius: 12px;
294
- margin-bottom: 20px;
295
- font-size: 0.9em;
296
- border: 1px solid rgba(99, 102, 241, 0.2);
297
- }
298
-
299
- .channel-grid {
300
- display: grid;
301
- grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
302
- gap: 15px;
303
- content-visibility: auto;
304
- }
305
-
306
- .channel-card {
307
- background: white;
308
- border: 2px solid transparent;
309
- border-radius: 15px;
310
- padding: 20px 15px;
311
- cursor: pointer;
312
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
313
- contain: layout style paint;
314
- content-visibility: auto;
315
- }
316
-
317
- .channel-card:hover {
318
- border-color: var(--primary);
319
- box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2);
320
- }
321
-
322
- .channel-name {
323
- font-size: 1em;
324
- color: var(--dark);
325
- margin-bottom: 12px;
326
- font-weight: 600;
327
- text-align: center;
328
- min-height: 45px;
329
- display: flex;
330
- align-items: center;
331
- justify-content: center;
332
- }
333
-
334
- .channel-actions {
335
- display: flex;
336
- gap: 8px;
337
- }
338
-
339
- .channel-actions .btn {
340
- flex: 1;
341
- padding: 8px;
342
- font-size: 0.85em;
343
- }
344
-
345
- .player-page {
346
- display: flex;
347
- flex-direction: column;
348
- gap: 15px;
349
- }
350
-
351
- .player-controls {
352
- display: grid;
353
- grid-template-columns: 1fr auto;
354
- gap: 12px;
355
- align-items: end;
356
- }
357
-
358
- .video-wrapper {
359
- position: relative;
360
- background: #1e293b;
361
- border-radius: 15px;
362
- overflow: hidden;
363
- aspect-ratio: 16 / 9;
364
- max-height: 550px;
365
- contain: layout style;
366
- }
367
-
368
- video {
369
- width: 100%;
370
- height: 100%;
371
- display: block;
372
- object-fit: contain;
373
- }
374
-
375
- .video-placeholder {
376
- position: absolute;
377
- top: 0;
378
- left: 0;
379
- width: 100%;
380
- height: 100%;
381
- background: #1e293b;
382
- display: flex;
383
- align-items: center;
384
- justify-content: center;
385
- color: white;
386
- }
387
-
388
- .video-placeholder.hidden {
389
- display: none;
390
- }
391
-
392
- .placeholder-icon {
393
- font-size: 50px;
394
- margin-bottom: 12px;
395
- opacity: 0.6;
396
- }
397
-
398
- .stream-info-panel {
399
- display: grid;
400
- grid-template-columns: 1fr 1fr;
401
- gap: 15px;
402
- }
403
-
404
- .info-section,
405
- .record-section {
406
- background: rgba(255, 255, 255, 0.95);
407
- padding: 20px;
408
- border-radius: 15px;
409
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
410
- contain: layout style paint;
411
- }
412
-
413
- .info-section h3,
414
- .record-section h3 {
415
- margin-bottom: 12px;
416
- color: var(--dark);
417
- font-size: 1em;
418
- font-weight: 700;
419
- }
420
-
421
- .info-content {
422
- background: #f8fafc;
423
- padding: 12px;
424
- border-radius: 10px;
425
- font-family: 'Courier New', monospace;
426
- font-size: 0.8em;
427
- line-height: 1.5;
428
- white-space: pre-wrap;
429
- word-break: break-all;
430
- min-height: 100px;
431
- max-height: 250px;
432
- overflow-y: auto;
433
- border: 1px solid #e2e8f0;
434
- color: var(--dark);
435
- }
436
-
437
- .btn-record {
438
- width: 100%;
439
- padding: 14px;
440
- background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
441
- color: white;
442
- border: none;
443
- border-radius: 12px;
444
- cursor: pointer;
445
- font-size: 0.95em;
446
- font-weight: 700;
447
- }
448
-
449
- .btn-record:hover:not(:disabled) {
450
- opacity: 0.9;
451
- }
452
-
453
- .btn-record:disabled {
454
- background: linear-gradient(135deg, #94a3b8 0%, #64748b 100%);
455
- cursor: not-allowed;
456
- }
457
-
458
- .record-status {
459
- margin-top: 12px;
460
- padding: 12px;
461
- border-radius: 10px;
462
- font-size: 0.85em;
463
- text-align: center;
464
- display: none;
465
- }
466
-
467
- .record-status.show {
468
- display: block;
469
- }
470
-
471
- .record-status.recording {
472
- background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
473
- color: #92400e;
474
- border: 2px solid #fbbf24;
475
- }
476
-
477
- .record-status.success {
478
- background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
479
- color: #065f46;
480
- border: 2px solid #10b981;
481
- }
482
-
483
- .record-status.error {
484
- background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
485
- color: #991b1b;
486
- border: 2px solid #ef4444;
487
- }
488
-
489
- .record-info {
490
- background: rgba(219, 234, 254, 0.5);
491
- padding: 12px;
492
- border-radius: 10px;
493
- margin-top: 12px;
494
- font-size: 0.85em;
495
- line-height: 1.5;
496
- }
497
-
498
- .epg-page {
499
- display: flex;
500
- flex-direction: column;
501
- gap: 15px;
502
- }
503
-
504
- .epg-controls {
505
- display: grid;
506
- grid-template-columns: 1fr 1fr auto;
507
- gap: 12px;
508
- align-items: end;
509
- }
510
-
511
- .epg-list {
512
- max-height: 550px;
513
- overflow-y: auto;
514
- background: rgba(248, 250, 252, 0.5);
515
- border-radius: 15px;
516
- padding: 15px;
517
- content-visibility: auto;
518
- }
519
-
520
- .epg-item {
521
- background: white;
522
- padding: 15px;
523
- margin-bottom: 12px;
524
- border-radius: 12px;
525
- border-left: 4px solid var(--primary);
526
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
527
- contain: layout style paint;
528
- content-visibility: auto;
529
- }
530
-
531
- .epg-item:hover {
532
- box-shadow: 0 4px 12px rgba(99, 102, 241, 0.15);
533
- }
534
-
535
- .epg-time {
536
- font-weight: 700;
537
- color: var(--primary);
538
- margin-bottom: 6px;
539
- font-size: 0.9em;
540
- display: flex;
541
- align-items: center;
542
- gap: 8px;
543
- }
544
-
545
- .epg-title {
546
- font-size: 1em;
547
- color: var(--dark);
548
- margin-bottom: 6px;
549
- font-weight: 600;
550
- }
551
-
552
- .epg-description {
553
- color: #64748b;
554
- font-size: 0.85em;
555
- line-height: 1.4;
556
- margin-top: 6px;
557
- padding: 10px;
558
- background: #f8fafc;
559
- border-radius: 8px;
560
- }
561
-
562
- .epg-item.current {
563
- border-left-color: var(--success);
564
- background: linear-gradient(135deg, #d1fae5 0%, white 100%);
565
- }
566
-
567
- .epg-item.current .epg-time {
568
- color: var(--success);
569
- }
570
-
571
- .epg-item.past {
572
- opacity: 0.7;
573
- }
574
-
575
- .epg-actions {
576
- margin-top: 10px;
577
- display: flex;
578
- gap: 8px;
579
- }
580
-
581
- .epg-actions .btn {
582
- flex: 1;
583
- padding: 8px 12px;
584
- font-size: 0.85em;
585
- }
586
-
587
- .epg-video-modal {
588
- display: none;
589
- position: fixed;
590
- top: 0;
591
- left: 0;
592
- width: 100%;
593
- height: 100%;
594
- background: rgba(30, 41, 59, 0.95);
595
- z-index: 9999;
596
- align-items: center;
597
- justify-content: center;
598
- padding: 20px;
599
- }
600
-
601
- .epg-video-modal.show {
602
- display: flex;
603
- }
604
-
605
- .epg-video-container {
606
- background: white;
607
- border-radius: 20px;
608
- max-width: 1100px;
609
- width: 100%;
610
- max-height: 90vh;
611
- overflow: hidden;
612
- box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
613
- }
614
-
615
- .epg-video-header {
616
- padding: 15px 25px;
617
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
618
- color: white;
619
- display: flex;
620
- justify-content: space-between;
621
- align-items: center;
622
- }
623
-
624
- .epg-video-header h3 {
625
- font-size: 1.2em;
626
- font-weight: 700;
627
- margin: 0;
628
- }
629
-
630
- .epg-video-close {
631
- background: rgba(255, 255, 255, 0.2);
632
- border: none;
633
- color: white;
634
- font-size: 1.4em;
635
- width: 35px;
636
- height: 35px;
637
- border-radius: 50%;
638
- cursor: pointer;
639
- display: flex;
640
- align-items: center;
641
- justify-content: center;
642
- }
643
-
644
- .epg-video-close:hover {
645
- background: rgba(255, 255, 255, 0.3);
646
- }
647
-
648
- .epg-video-body {
649
- padding: 0;
650
- }
651
-
652
- .epg-video-wrapper {
653
- position: relative;
654
- background: #000;
655
- aspect-ratio: 16 / 9;
656
- max-height: 65vh;
657
- }
658
-
659
- .epg-video-wrapper video {
660
- width: 100%;
661
- height: 100%;
662
- display: block;
663
- }
664
-
665
- .epg-video-info {
666
- padding: 15px 25px;
667
- background: #f8fafc;
668
- }
669
-
670
- .epg-video-info p {
671
- margin: 6px 0;
672
- color: var(--dark);
673
- font-size: 0.9em;
674
- }
675
-
676
- .cache-grid {
677
- display: grid;
678
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
679
- gap: 15px;
680
- margin-bottom: 25px;
681
- }
682
-
683
- .cache-card {
684
- background: white;
685
- padding: 20px;
686
- border-radius: 15px;
687
- border-left: 4px solid var(--primary);
688
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
689
- contain: layout style paint;
690
- }
691
-
692
- .cache-card h3 {
693
- color: var(--dark);
694
- margin-bottom: 12px;
695
- font-size: 1em;
696
- font-weight: 700;
697
- }
698
-
699
- .cache-detail {
700
- display: flex;
701
- justify-content: space-between;
702
- padding: 8px 0;
703
- border-bottom: 1px solid var(--border);
704
- font-size: 0.85em;
705
- }
706
-
707
- .cache-detail:last-child {
708
- border-bottom: none;
709
- }
710
-
711
- .cache-label {
712
- font-weight: 600;
713
- color: #64748b;
714
- }
715
-
716
- .cache-value {
717
- font-family: 'Courier New', monospace;
718
- color: var(--dark);
719
- font-weight: 600;
720
- }
721
-
722
- .cache-actions {
723
- background: rgba(255, 255, 255, 0.95);
724
- padding: 20px;
725
- border-radius: 15px;
726
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
727
- }
728
-
729
- .button-group {
730
- display: flex;
731
- flex-wrap: wrap;
732
- gap: 10px;
733
- }
734
-
735
- .footer {
736
- background: rgba(248, 250, 252, 0.8);
737
- padding: 15px;
738
- text-align: center;
739
- border-top: 1px solid var(--border);
740
- color: #64748b;
741
- font-size: 0.85em;
742
- }
743
-
744
- .footer a {
745
- color: var(--primary);
746
- text-decoration: none;
747
- font-weight: 600;
748
- }
749
-
750
- .notification {
751
- position: fixed;
752
- top: 20px;
753
- right: 20px;
754
- padding: 12px 20px;
755
- border-radius: 12px;
756
- z-index: 10000;
757
- color: white;
758
- font-weight: 600;
759
- font-size: 0.9em;
760
- display: flex;
761
- align-items: center;
762
- gap: 10px;
763
- opacity: 1;
764
- }
765
-
766
- .notification.notification-success {
767
- background: linear-gradient(135deg, #10b981 0%, #059669 100%);
768
- }
769
-
770
- .notification.notification-error {
771
- background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
772
- }
773
-
774
- .notification.notification-info {
775
- background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
776
- }
777
-
778
- .login-overlay {
779
- display: flex;
780
- position: fixed;
781
- top: 0;
782
- left: 0;
783
- width: 100%;
784
- height: 100%;
785
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
786
- z-index: 99999;
787
- align-items: center;
788
- justify-content: center;
789
- padding: 20px;
790
- }
791
-
792
- .login-overlay.hide {
793
- display: none !important;
794
- }
795
-
796
- .login-box {
797
- background: rgba(255, 255, 255, 0.95);
798
- border-radius: 25px;
799
- box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
800
- overflow: hidden;
801
- max-width: 420px;
802
- width: 100%;
803
- }
804
-
805
- .login-box-header {
806
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
807
- color: white;
808
- padding: 30px 25px;
809
- text-align: center;
810
- }
811
-
812
- .login-box-header h1 {
813
- font-size: 2em;
814
- font-weight: 700;
815
- margin-bottom: 8px;
816
- }
817
-
818
- .login-box-body {
819
- padding: 30px 25px;
820
- }
821
-
822
- .login-form-group {
823
- margin-bottom: 20px;
824
- }
825
-
826
- .login-form-group label {
827
- display: block;
828
- margin-bottom: 8px;
829
- font-weight: 600;
830
- color: var(--dark);
831
- font-size: 0.9em;
832
- }
833
-
834
- .login-form-group input {
835
- width: 100%;
836
- padding: 12px 15px;
837
- border: 2px solid var(--border);
838
- border-radius: 10px;
839
- font-size: 0.9em;
840
- }
841
-
842
- .login-form-group input:focus {
843
- outline: none;
844
- border-color: var(--primary);
845
- }
846
-
847
- .login-btn {
848
- width: 100%;
849
- padding: 14px;
850
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
851
- color: white;
852
- border: none;
853
- border-radius: 10px;
854
- font-size: 1em;
855
- font-weight: 700;
856
- cursor: pointer;
857
- }
858
-
859
- .login-btn:hover:not(:disabled) {
860
- opacity: 0.9;
861
- }
862
-
863
- .login-btn:disabled {
864
- opacity: 0.7;
865
- cursor: not-allowed;
866
- }
867
-
868
- .login-error {
869
- background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
870
- color: #991b1b;
871
- padding: 12px;
872
- border-radius: 10px;
873
- margin-bottom: 15px;
874
- display: none;
875
- border: 2px solid #fca5a5;
876
- font-size: 0.85em;
877
- }
878
-
879
- .login-error.show {
880
- display: block;
881
- }
882
-
883
- .login-info {
884
- background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
885
- color: #1e40af;
886
- padding: 12px;
887
- border-radius: 10px;
888
- margin-bottom: 15px;
889
- font-size: 0.85em;
890
- border: 1px solid #93c5fd;
891
- }
892
-
893
- .password-toggle-login {
894
- position: relative;
895
- }
896
-
897
- .password-toggle-btn-login {
898
- position: absolute;
899
- right: 12px;
900
- top: 50%;
901
- transform: translateY(-50%);
902
- background: none;
903
- border: none;
904
- cursor: pointer;
905
- color: #64748b;
906
- font-size: 1.1em;
907
- padding: 5px;
908
- }
909
-
910
- .login-type-switch {
911
- text-align: center;
912
- margin-top: 12px;
913
- padding-top: 12px;
914
- border-top: 1px solid var(--border);
915
- }
916
-
917
- .login-type-switch a {
918
- color: var(--primary);
919
- text-decoration: none;
920
- font-weight: 600;
921
- cursor: pointer;
922
- font-size: 0.85em;
923
- }
924
-
925
- .loading-overlay {
926
- position: fixed;
927
- top: 0;
928
- left: 0;
929
- width: 100%;
930
- height: 100%;
931
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
932
- display: flex;
933
- flex-direction: column;
934
- align-items: center;
935
- justify-content: center;
936
- z-index: 99999;
937
- }
938
-
939
- .loading-overlay.hide {
940
- display: none !important;
941
- }
942
-
943
- .loading-spinner-large {
944
- width: 50px;
945
- height: 50px;
946
- border: 4px solid rgba(255,255,255,.2);
947
- border-radius: 50%;
948
- border-top-color: #fff;
949
- animation: spin 1s linear infinite !important;
950
- }
951
-
952
- @keyframes spin {
953
- to { transform: rotate(360deg); }
954
- }
955
-
956
- .loading-text {
957
- color: white;
958
- margin-top: 15px;
959
- font-size: 1em;
960
- font-weight: 600;
961
- }
962
-
963
- .loading-spinner {
964
- text-align: center;
965
- padding: 40px;
966
- color: var(--primary);
967
- }
968
-
969
- .badge {
970
- padding: 5px 12px;
971
- border-radius: 15px;
972
- font-size: 0.75em;
973
- font-weight: 700;
974
- display: inline-block;
975
- }
976
-
977
- .badge-success {
978
- background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
979
- color: #065f46;
980
- border: 1px solid #6ee7b7;
981
- }
982
-
983
- .badge-danger {
984
- background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
985
- color: #991b1b;
986
- border: 1px solid #fca5a5;
987
- }
988
-
989
- .empty-state {
990
- text-align: center;
991
- padding: 60px 30px;
992
- color: #94a3b8;
993
- }
994
-
995
- .empty-state-icon {
996
- font-size: 60px;
997
- margin-bottom: 15px;
998
- opacity: 0.5;
999
- }
1000
-
1001
- .empty-state-text {
1002
- font-size: 1em;
1003
- margin-bottom: 8px;
1004
- font-weight: 600;
1005
- }
1006
-
1007
- .search-box {
1008
- position: relative;
1009
- }
1010
-
1011
- .search-box input {
1012
- width: 100%;
1013
- padding: 12px 15px 12px 40px;
1014
- border: 2px solid var(--border);
1015
- border-radius: 12px;
1016
- font-size: 0.9em;
1017
- }
1018
-
1019
- .search-box input:focus {
1020
- border-color: var(--primary);
1021
- }
1022
-
1023
- .search-box::before {
1024
- content: '🔍';
1025
- position: absolute;
1026
- left: 12px;
1027
- top: 50%;
1028
- transform: translateY(-50%);
1029
- font-size: 1.1em;
1030
- opacity: 0.5;
1031
- }
1032
-
1033
- .skeleton {
1034
- background: #e0e0e0;
1035
- border-radius: 8px;
1036
- }
1037
-
1038
- .skeleton-card {
1039
- height: 180px;
1040
- }
1041
-
1042
- @media (max-width: 768px) {
1043
- .app-container {
1044
- margin: 10px;
1045
- border-radius: 15px;
1046
- }
1047
-
1048
- .app-body {
1049
- padding: 15px 20px;
1050
- }
1051
-
1052
- .header {
1053
- padding: 15px 20px;
1054
- }
1055
-
1056
- .header h1 {
1057
- font-size: 1.5em;
1058
- }
1059
-
1060
- .header-top {
1061
- flex-direction: column;
1062
- }
1063
-
1064
- .status-bar {
1065
- flex-direction: column;
1066
- gap: 10px;
1067
- }
1068
-
1069
- .status-item {
1070
- width: 100%;
1071
- justify-content: space-between;
1072
- }
1073
-
1074
- .tab-button {
1075
- min-width: 100px;
1076
- padding: 12px 14px;
1077
- }
1078
-
1079
- .channel-grid {
1080
- grid-template-columns: 1fr;
1081
- }
1082
-
1083
- .epg-controls {
1084
- grid-template-columns: 1fr;
1085
- }
1086
-
1087
- .player-controls {
1088
- grid-template-columns: 1fr;
1089
- }
1090
-
1091
- .stream-info-panel {
1092
- grid-template-columns: 1fr;
1093
- }
1094
-
1095
- .cache-grid {
1096
- grid-template-columns: 1fr;
1097
- }
1098
-
1099
- .button-group {
1100
- flex-direction: column;
1101
- }
1102
-
1103
- .epg-video-container {
1104
- max-height: 95vh;
1105
- }
1106
- }
1107
-
1108
- ::-webkit-scrollbar {
1109
- width: 8px;
1110
- height: 8px;
1111
- }
1112
-
1113
- ::-webkit-scrollbar-track {
1114
- background: #f1f5f9;
1115
- }
1116
-
1117
- ::-webkit-scrollbar-thumb {
1118
- background: #cbd5e1;
1119
- border-radius: 4px;
1120
- }
1121
-
1122
- ::-webkit-scrollbar-thumb:hover {
1123
- background: #94a3b8;
1124
- }
1125
-
1126
- .hidden {
1127
- display: none !important;
1128
- }
1129
-
1130
- .text-center {
1131
- text-align: center;
1132
- }
1133
-
1134
- .admin-only {
1135
- display: none;
1136
- }
1137
-
1138
- .channel-card,
1139
- .epg-item,
1140
- .cache-card {
1141
- transform: translateZ(0);
1142
- backface-visibility: hidden;
1143
- }
1144
-
1145
- @media print {
1146
- body {
1147
- background: white;
1148
- }
1149
-
1150
- .header,
1151
- .tabs,
1152
- .btn,
1153
- .footer,
1154
- .notification {
1155
- display: none;
1156
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1157
  }
 
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
2
+
3
+ @keyframes shimmer {
4
+ 0% { background-position: -468px 0; }
5
+ 100% { background-position: 468px 0; }
6
+ }
7
+
8
+ .skeleton {
9
+ background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
10
+ background-size: 468px 100%;
11
+ animation: shimmer 1.2s ease-in-out infinite;
12
+ border-radius: 8px;
13
+ }
14
+
15
+ .skeleton-text { height: 16px; margin-bottom: 8px; }
16
+ .skeleton-title { height: 24px; width: 60%; margin-bottom: 12px; }
17
+
18
+ /* 性能优化 */
19
+ .notification, .modal-overlay, .loading-overlay {
20
+ will-change: opacity, transform;
21
+ transform: translateZ(0);
22
+ }
23
+
24
+ .channel-item, .epg-item {
25
+ contain: layout style paint;
26
+ }
27
+
28
+ /* 优化动画 */
29
+ .fab-button {
30
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
31
+ }
32
+
33
+ .fab-button:hover {
34
+ transform: translateY(-4px);
35
+ }
36
+
37
+ :root {
38
+ --primary: #6366f1;
39
+ --primary-dark: #4f46e5;
40
+ --success: #10b981;
41
+ --warning: #f59e0b;
42
+ --danger: #ef4444;
43
+ --dark: #1e293b;
44
+ --light: #f8fafc;
45
+ --border: #e2e8f0;
46
+ --shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
47
+ }
48
+
49
+ * {
50
+ margin: 0;
51
+ padding: 0;
52
+ box-sizing: border-box;
53
+ }
54
+
55
+ body {
56
+ font-family: 'Inter', -apple-system, sans-serif;
57
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
58
+ background-attachment: fixed;
59
+ min-height: 100vh;
60
+ line-height: 1.5;
61
+ font-size: 14px;
62
+ color: var(--dark);
63
+ -webkit-font-smoothing: antialiased;
64
+ }
65
+
66
+ *, *::before, *::after {
67
+ animation: none !important;
68
+ transition: none !important;
69
+ }
70
+
71
+ .notification,
72
+ .login-overlay,
73
+ .epg-video-modal {
74
+ transition: opacity 0.15s ease !important;
75
+ }
76
+
77
+ .app-container {
78
+ display: flex;
79
+ flex-direction: column;
80
+ min-height: 100vh;
81
+ max-width: 1600px;
82
+ margin: 20px auto;
83
+ background: rgba(255, 255, 255, 0.95);
84
+ border-radius: 20px;
85
+ box-shadow: var(--shadow);
86
+ overflow: hidden;
87
+ contain: layout style paint;
88
+ }
89
+
90
+ .app-body {
91
+ flex: 1;
92
+ padding: 20px 30px;
93
+ transform: translateZ(0);
94
+ will-change: scroll-position;
95
+ }
96
+
97
+ .header {
98
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
99
+ color: white;
100
+ padding: 20px 30px;
101
+ contain: layout style paint;
102
+ }
103
+
104
+ .header-top {
105
+ display: flex;
106
+ justify-content: space-between;
107
+ align-items: center;
108
+ margin-bottom: 15px;
109
+ gap: 15px;
110
+ flex-wrap: wrap;
111
+ }
112
+
113
+ .header h1 {
114
+ font-size: 1.8em;
115
+ font-weight: 700;
116
+ margin-bottom: 5px;
117
+ }
118
+
119
+ .subtitle {
120
+ font-size: 0.9em;
121
+ opacity: 0.9;
122
+ }
123
+
124
+ .status-bar {
125
+ display: flex;
126
+ justify-content: center;
127
+ gap: 20px;
128
+ flex-wrap: wrap;
129
+ font-size: 0.85em;
130
+ }
131
+
132
+ .status-item {
133
+ background: rgba(255, 255, 255, 0.2);
134
+ padding: 8px 15px;
135
+ border-radius: 20px;
136
+ display: flex;
137
+ align-items: center;
138
+ gap: 8px;
139
+ border: 1px solid rgba(255, 255, 255, 0.3);
140
+ }
141
+
142
+ .btn-logout {
143
+ padding: 10px 20px;
144
+ background: rgba(255, 255, 255, 0.2);
145
+ color: white;
146
+ border: 2px solid rgba(255, 255, 255, 0.5);
147
+ border-radius: 20px;
148
+ cursor: pointer;
149
+ font-size: 0.9em;
150
+ font-weight: 600;
151
+ }
152
+
153
+ .btn-logout:hover {
154
+ background: rgba(255, 255, 255, 0.3);
155
+ }
156
+
157
+ .user-type-badge {
158
+ display: inline-block;
159
+ padding: 3px 10px;
160
+ border-radius: 15px;
161
+ font-size: 0.7em;
162
+ font-weight: 700;
163
+ margin-left: 8px;
164
+ }
165
+
166
+ .user-type-badge.admin {
167
+ background: linear-gradient(135deg, #f59e0b 0%, #ef4444 100%);
168
+ color: white;
169
+ }
170
+
171
+ .user-type-badge.user {
172
+ background: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
173
+ color: white;
174
+ }
175
+
176
+ .tabs {
177
+ display: flex;
178
+ background: rgba(248, 250, 252, 0.8);
179
+ border-bottom: 1px solid var(--border);
180
+ overflow-x: auto;
181
+ scrollbar-width: none;
182
+ contain: layout style;
183
+ }
184
+
185
+ .tabs::-webkit-scrollbar {
186
+ display: none;
187
+ }
188
+
189
+ .tab-button {
190
+ flex: 1;
191
+ padding: 15px 18px;
192
+ background: transparent;
193
+ border: none;
194
+ cursor: pointer;
195
+ font-size: 0.9em;
196
+ color: var(--dark);
197
+ font-weight: 500;
198
+ text-decoration: none;
199
+ text-align: center;
200
+ min-width: 120px;
201
+ border-bottom: 3px solid transparent;
202
+ }
203
+
204
+ .tab-button:hover {
205
+ background: rgba(99, 102, 241, 0.05);
206
+ }
207
+
208
+ .tab-button.active {
209
+ background: white;
210
+ font-weight: 600;
211
+ color: var(--primary);
212
+ border-bottom-color: var(--primary);
213
+ }
214
+
215
+ .btn {
216
+ padding: 10px 20px;
217
+ border: none;
218
+ border-radius: 10px;
219
+ cursor: pointer;
220
+ font-size: 0.9em;
221
+ font-weight: 600;
222
+ contain: layout style paint;
223
+ }
224
+
225
+ .btn:hover:not(:disabled) {
226
+ opacity: 0.9;
227
+ }
228
+
229
+ .btn:disabled {
230
+ opacity: 0.6;
231
+ cursor: not-allowed;
232
+ }
233
+
234
+ .btn-primary {
235
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
236
+ color: white;
237
+ }
238
+
239
+ .btn-success {
240
+ background: linear-gradient(135deg, #10b981 0%, #059669 100%);
241
+ color: white;
242
+ }
243
+
244
+ .btn-warning {
245
+ background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
246
+ color: white;
247
+ }
248
+
249
+ .btn-danger {
250
+ background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
251
+ color: white;
252
+ }
253
+
254
+ .form-control {
255
+ width: 100%;
256
+ padding: 12px 15px;
257
+ border: 2px solid var(--border);
258
+ border-radius: 10px;
259
+ font-size: 0.9em;
260
+ background: white;
261
+ font-family: inherit;
262
+ }
263
+
264
+ .form-control:focus {
265
+ outline: none;
266
+ border-color: var(--primary);
267
+ }
268
+
269
+ .form-group {
270
+ margin-bottom: 15px;
271
+ }
272
+
273
+ .form-group label {
274
+ display: block;
275
+ margin-bottom: 6px;
276
+ font-weight: 600;
277
+ color: var(--dark);
278
+ font-size: 0.85em;
279
+ }
280
+
281
+ .section-header {
282
+ display: flex;
283
+ justify-content: space-between;
284
+ align-items: center;
285
+ margin-bottom: 20px;
286
+ gap: 15px;
287
+ flex-wrap: wrap;
288
+ }
289
+
290
+ .stats-box {
291
+ background: rgba(99, 102, 241, 0.1);
292
+ padding: 12px 20px;
293
+ border-radius: 12px;
294
+ margin-bottom: 20px;
295
+ font-size: 0.9em;
296
+ border: 1px solid rgba(99, 102, 241, 0.2);
297
+ }
298
+
299
+ .channel-grid {
300
+ display: grid;
301
+ grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
302
+ gap: 15px;
303
+ content-visibility: auto;
304
+ }
305
+
306
+ .channel-card {
307
+ background: white;
308
+ border: 2px solid transparent;
309
+ border-radius: 15px;
310
+ padding: 20px 15px;
311
+ cursor: pointer;
312
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
313
+ contain: layout style paint;
314
+ content-visibility: auto;
315
+ }
316
+
317
+ .channel-card:hover {
318
+ border-color: var(--primary);
319
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2);
320
+ }
321
+
322
+ .channel-name {
323
+ font-size: 1em;
324
+ color: var(--dark);
325
+ margin-bottom: 12px;
326
+ font-weight: 600;
327
+ text-align: center;
328
+ min-height: 45px;
329
+ display: flex;
330
+ align-items: center;
331
+ justify-content: center;
332
+ }
333
+
334
+ .channel-actions {
335
+ display: flex;
336
+ gap: 8px;
337
+ }
338
+
339
+ .channel-actions .btn {
340
+ flex: 1;
341
+ padding: 8px;
342
+ font-size: 0.85em;
343
+ }
344
+
345
+ .player-page {
346
+ display: flex;
347
+ flex-direction: column;
348
+ gap: 15px;
349
+ }
350
+
351
+ .player-controls {
352
+ display: grid;
353
+ grid-template-columns: 1fr auto;
354
+ gap: 12px;
355
+ align-items: end;
356
+ }
357
+
358
+ .video-wrapper {
359
+ position: relative;
360
+ background: #1e293b;
361
+ border-radius: 15px;
362
+ overflow: hidden;
363
+ aspect-ratio: 16 / 9;
364
+ max-height: 550px;
365
+ contain: layout style;
366
+ }
367
+
368
+ video {
369
+ width: 100%;
370
+ height: 100%;
371
+ display: block;
372
+ object-fit: contain;
373
+ }
374
+
375
+ .video-placeholder {
376
+ position: absolute;
377
+ top: 0;
378
+ left: 0;
379
+ width: 100%;
380
+ height: 100%;
381
+ background: #1e293b;
382
+ display: flex;
383
+ align-items: center;
384
+ justify-content: center;
385
+ color: white;
386
+ }
387
+
388
+ .video-placeholder.hidden {
389
+ display: none;
390
+ }
391
+
392
+ .placeholder-icon {
393
+ font-size: 50px;
394
+ margin-bottom: 12px;
395
+ opacity: 0.6;
396
+ }
397
+
398
+ .stream-info-panel {
399
+ display: grid;
400
+ grid-template-columns: 1fr 1fr;
401
+ gap: 15px;
402
+ }
403
+
404
+ .info-section,
405
+ .record-section {
406
+ background: rgba(255, 255, 255, 0.95);
407
+ padding: 20px;
408
+ border-radius: 15px;
409
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
410
+ contain: layout style paint;
411
+ }
412
+
413
+ .info-section h3,
414
+ .record-section h3 {
415
+ margin-bottom: 12px;
416
+ color: var(--dark);
417
+ font-size: 1em;
418
+ font-weight: 700;
419
+ }
420
+
421
+ .info-content {
422
+ background: #f8fafc;
423
+ padding: 12px;
424
+ border-radius: 10px;
425
+ font-family: 'Courier New', monospace;
426
+ font-size: 0.8em;
427
+ line-height: 1.5;
428
+ white-space: pre-wrap;
429
+ word-break: break-all;
430
+ min-height: 100px;
431
+ max-height: 250px;
432
+ overflow-y: auto;
433
+ border: 1px solid #e2e8f0;
434
+ color: var(--dark);
435
+ }
436
+
437
+ .btn-record {
438
+ width: 100%;
439
+ padding: 14px;
440
+ background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
441
+ color: white;
442
+ border: none;
443
+ border-radius: 12px;
444
+ cursor: pointer;
445
+ font-size: 0.95em;
446
+ font-weight: 700;
447
+ }
448
+
449
+ .btn-record:hover:not(:disabled) {
450
+ opacity: 0.9;
451
+ }
452
+
453
+ .btn-record:disabled {
454
+ background: linear-gradient(135deg, #94a3b8 0%, #64748b 100%);
455
+ cursor: not-allowed;
456
+ }
457
+
458
+ .record-status {
459
+ margin-top: 12px;
460
+ padding: 12px;
461
+ border-radius: 10px;
462
+ font-size: 0.85em;
463
+ text-align: center;
464
+ display: none;
465
+ }
466
+
467
+ .record-status.show {
468
+ display: block;
469
+ }
470
+
471
+ .record-status.recording {
472
+ background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
473
+ color: #92400e;
474
+ border: 2px solid #fbbf24;
475
+ }
476
+
477
+ .record-status.success {
478
+ background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
479
+ color: #065f46;
480
+ border: 2px solid #10b981;
481
+ }
482
+
483
+ .record-status.error {
484
+ background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
485
+ color: #991b1b;
486
+ border: 2px solid #ef4444;
487
+ }
488
+
489
+ .record-info {
490
+ background: rgba(219, 234, 254, 0.5);
491
+ padding: 12px;
492
+ border-radius: 10px;
493
+ margin-top: 12px;
494
+ font-size: 0.85em;
495
+ line-height: 1.5;
496
+ }
497
+
498
+ .epg-page {
499
+ display: flex;
500
+ flex-direction: column;
501
+ gap: 15px;
502
+ }
503
+
504
+ .epg-controls {
505
+ display: grid;
506
+ grid-template-columns: 1fr 1fr auto;
507
+ gap: 12px;
508
+ align-items: end;
509
+ }
510
+
511
+ .epg-list {
512
+ max-height: 550px;
513
+ overflow-y: auto;
514
+ background: rgba(248, 250, 252, 0.5);
515
+ border-radius: 15px;
516
+ padding: 15px;
517
+ content-visibility: auto;
518
+ }
519
+
520
+ .epg-item {
521
+ background: white;
522
+ padding: 15px;
523
+ margin-bottom: 12px;
524
+ border-radius: 12px;
525
+ border-left: 4px solid var(--primary);
526
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
527
+ contain: layout style paint;
528
+ content-visibility: auto;
529
+ }
530
+
531
+ .epg-item:hover {
532
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.15);
533
+ }
534
+
535
+ .epg-time {
536
+ font-weight: 700;
537
+ color: var(--primary);
538
+ margin-bottom: 6px;
539
+ font-size: 0.9em;
540
+ display: flex;
541
+ align-items: center;
542
+ gap: 8px;
543
+ }
544
+
545
+ .epg-title {
546
+ font-size: 1em;
547
+ color: var(--dark);
548
+ margin-bottom: 6px;
549
+ font-weight: 600;
550
+ }
551
+
552
+ .epg-description {
553
+ color: #64748b;
554
+ font-size: 0.85em;
555
+ line-height: 1.4;
556
+ margin-top: 6px;
557
+ padding: 10px;
558
+ background: #f8fafc;
559
+ border-radius: 8px;
560
+ }
561
+
562
+ .epg-item.current {
563
+ border-left-color: var(--success);
564
+ background: linear-gradient(135deg, #d1fae5 0%, white 100%);
565
+ }
566
+
567
+ .epg-item.current .epg-time {
568
+ color: var(--success);
569
+ }
570
+
571
+ .epg-item.past {
572
+ opacity: 0.7;
573
+ }
574
+
575
+ .epg-actions {
576
+ margin-top: 10px;
577
+ display: flex;
578
+ gap: 8px;
579
+ }
580
+
581
+ .epg-actions .btn {
582
+ flex: 1;
583
+ padding: 8px 12px;
584
+ font-size: 0.85em;
585
+ }
586
+
587
+ .epg-video-modal {
588
+ display: none;
589
+ position: fixed;
590
+ top: 0;
591
+ left: 0;
592
+ width: 100%;
593
+ height: 100%;
594
+ background: rgba(30, 41, 59, 0.95);
595
+ z-index: 9999;
596
+ align-items: center;
597
+ justify-content: center;
598
+ padding: 20px;
599
+ }
600
+
601
+ .epg-video-modal.show {
602
+ display: flex;
603
+ }
604
+
605
+ .epg-video-container {
606
+ background: white;
607
+ border-radius: 20px;
608
+ max-width: 1100px;
609
+ width: 100%;
610
+ max-height: 90vh;
611
+ overflow: hidden;
612
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
613
+ }
614
+
615
+ .epg-video-header {
616
+ padding: 15px 25px;
617
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
618
+ color: white;
619
+ display: flex;
620
+ justify-content: space-between;
621
+ align-items: center;
622
+ }
623
+
624
+ .epg-video-header h3 {
625
+ font-size: 1.2em;
626
+ font-weight: 700;
627
+ margin: 0;
628
+ }
629
+
630
+ .epg-video-close {
631
+ background: rgba(255, 255, 255, 0.2);
632
+ border: none;
633
+ color: white;
634
+ font-size: 1.4em;
635
+ width: 35px;
636
+ height: 35px;
637
+ border-radius: 50%;
638
+ cursor: pointer;
639
+ display: flex;
640
+ align-items: center;
641
+ justify-content: center;
642
+ }
643
+
644
+ .epg-video-close:hover {
645
+ background: rgba(255, 255, 255, 0.3);
646
+ }
647
+
648
+ .epg-video-body {
649
+ padding: 0;
650
+ }
651
+
652
+ .epg-video-wrapper {
653
+ position: relative;
654
+ background: #000;
655
+ aspect-ratio: 16 / 9;
656
+ max-height: 65vh;
657
+ }
658
+
659
+ .epg-video-wrapper video {
660
+ width: 100%;
661
+ height: 100%;
662
+ display: block;
663
+ }
664
+
665
+ .epg-video-info {
666
+ padding: 15px 25px;
667
+ background: #f8fafc;
668
+ }
669
+
670
+ .epg-video-info p {
671
+ margin: 6px 0;
672
+ color: var(--dark);
673
+ font-size: 0.9em;
674
+ }
675
+
676
+ .cache-grid {
677
+ display: grid;
678
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
679
+ gap: 15px;
680
+ margin-bottom: 25px;
681
+ }
682
+
683
+ .cache-card {
684
+ background: white;
685
+ padding: 20px;
686
+ border-radius: 15px;
687
+ border-left: 4px solid var(--primary);
688
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
689
+ contain: layout style paint;
690
+ }
691
+
692
+ .cache-card h3 {
693
+ color: var(--dark);
694
+ margin-bottom: 12px;
695
+ font-size: 1em;
696
+ font-weight: 700;
697
+ }
698
+
699
+ .cache-detail {
700
+ display: flex;
701
+ justify-content: space-between;
702
+ padding: 8px 0;
703
+ border-bottom: 1px solid var(--border);
704
+ font-size: 0.85em;
705
+ }
706
+
707
+ .cache-detail:last-child {
708
+ border-bottom: none;
709
+ }
710
+
711
+ .cache-label {
712
+ font-weight: 600;
713
+ color: #64748b;
714
+ }
715
+
716
+ .cache-value {
717
+ font-family: 'Courier New', monospace;
718
+ color: var(--dark);
719
+ font-weight: 600;
720
+ }
721
+
722
+ .cache-actions {
723
+ background: rgba(255, 255, 255, 0.95);
724
+ padding: 20px;
725
+ border-radius: 15px;
726
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
727
+ }
728
+
729
+ .button-group {
730
+ display: flex;
731
+ flex-wrap: wrap;
732
+ gap: 10px;
733
+ }
734
+
735
+ .footer {
736
+ background: rgba(248, 250, 252, 0.8);
737
+ padding: 15px;
738
+ text-align: center;
739
+ border-top: 1px solid var(--border);
740
+ color: #64748b;
741
+ font-size: 0.85em;
742
+ }
743
+
744
+ .footer a {
745
+ color: var(--primary);
746
+ text-decoration: none;
747
+ font-weight: 600;
748
+ }
749
+
750
+ .notification {
751
+ position: fixed;
752
+ top: 20px;
753
+ right: 20px;
754
+ padding: 12px 20px;
755
+ border-radius: 12px;
756
+ z-index: 10000;
757
+ color: white;
758
+ font-weight: 600;
759
+ font-size: 0.9em;
760
+ display: flex;
761
+ align-items: center;
762
+ gap: 10px;
763
+ opacity: 1;
764
+ }
765
+
766
+ .notification.notification-success {
767
+ background: linear-gradient(135deg, #10b981 0%, #059669 100%);
768
+ }
769
+
770
+ .notification.notification-error {
771
+ background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
772
+ }
773
+
774
+ .notification.notification-info {
775
+ background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
776
+ }
777
+
778
+ .login-overlay {
779
+ display: flex;
780
+ position: fixed;
781
+ top: 0;
782
+ left: 0;
783
+ width: 100%;
784
+ height: 100%;
785
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
786
+ z-index: 99999;
787
+ align-items: center;
788
+ justify-content: center;
789
+ padding: 20px;
790
+ }
791
+
792
+ .login-overlay.hide {
793
+ display: none !important;
794
+ }
795
+
796
+ .login-box {
797
+ background: rgba(255, 255, 255, 0.95);
798
+ border-radius: 25px;
799
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
800
+ overflow: hidden;
801
+ max-width: 420px;
802
+ width: 100%;
803
+ }
804
+
805
+ .login-box-header {
806
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
807
+ color: white;
808
+ padding: 30px 25px;
809
+ text-align: center;
810
+ }
811
+
812
+ .login-box-header h1 {
813
+ font-size: 2em;
814
+ font-weight: 700;
815
+ margin-bottom: 8px;
816
+ }
817
+
818
+ .login-box-body {
819
+ padding: 30px 25px;
820
+ }
821
+
822
+ .login-form-group {
823
+ margin-bottom: 20px;
824
+ }
825
+
826
+ .login-form-group label {
827
+ display: block;
828
+ margin-bottom: 8px;
829
+ font-weight: 600;
830
+ color: var(--dark);
831
+ font-size: 0.9em;
832
+ }
833
+
834
+ .login-form-group input {
835
+ width: 100%;
836
+ padding: 12px 15px;
837
+ border: 2px solid var(--border);
838
+ border-radius: 10px;
839
+ font-size: 0.9em;
840
+ }
841
+
842
+ .login-form-group input:focus {
843
+ outline: none;
844
+ border-color: var(--primary);
845
+ }
846
+
847
+ .login-btn {
848
+ width: 100%;
849
+ padding: 14px;
850
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
851
+ color: white;
852
+ border: none;
853
+ border-radius: 10px;
854
+ font-size: 1em;
855
+ font-weight: 700;
856
+ cursor: pointer;
857
+ }
858
+
859
+ .login-btn:hover:not(:disabled) {
860
+ opacity: 0.9;
861
+ }
862
+
863
+ .login-btn:disabled {
864
+ opacity: 0.7;
865
+ cursor: not-allowed;
866
+ }
867
+
868
+ .login-error {
869
+ background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
870
+ color: #991b1b;
871
+ padding: 12px;
872
+ border-radius: 10px;
873
+ margin-bottom: 15px;
874
+ display: none;
875
+ border: 2px solid #fca5a5;
876
+ font-size: 0.85em;
877
+ }
878
+
879
+ .login-error.show {
880
+ display: block;
881
+ }
882
+
883
+ .login-info {
884
+ background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
885
+ color: #1e40af;
886
+ padding: 12px;
887
+ border-radius: 10px;
888
+ margin-bottom: 15px;
889
+ font-size: 0.85em;
890
+ border: 1px solid #93c5fd;
891
+ }
892
+
893
+ .password-toggle-login {
894
+ position: relative;
895
+ }
896
+
897
+ .password-toggle-btn-login {
898
+ position: absolute;
899
+ right: 12px;
900
+ top: 50%;
901
+ transform: translateY(-50%);
902
+ background: none;
903
+ border: none;
904
+ cursor: pointer;
905
+ color: #64748b;
906
+ font-size: 1.1em;
907
+ padding: 5px;
908
+ }
909
+
910
+ .login-type-switch {
911
+ text-align: center;
912
+ margin-top: 12px;
913
+ padding-top: 12px;
914
+ border-top: 1px solid var(--border);
915
+ }
916
+
917
+ .login-type-switch a {
918
+ color: var(--primary);
919
+ text-decoration: none;
920
+ font-weight: 600;
921
+ cursor: pointer;
922
+ font-size: 0.85em;
923
+ }
924
+
925
+ .loading-overlay {
926
+ position: fixed;
927
+ top: 0;
928
+ left: 0;
929
+ width: 100%;
930
+ height: 100%;
931
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
932
+ display: flex;
933
+ flex-direction: column;
934
+ align-items: center;
935
+ justify-content: center;
936
+ z-index: 99999;
937
+ }
938
+
939
+ .loading-overlay.hide {
940
+ display: none !important;
941
+ }
942
+
943
+ .loading-spinner-large {
944
+ width: 50px;
945
+ height: 50px;
946
+ border: 4px solid rgba(255,255,255,.2);
947
+ border-radius: 50%;
948
+ border-top-color: #fff;
949
+ animation: spin 1s linear infinite !important;
950
+ }
951
+
952
+ @keyframes spin {
953
+ to { transform: rotate(360deg); }
954
+ }
955
+
956
+ .loading-text {
957
+ color: white;
958
+ margin-top: 15px;
959
+ font-size: 1em;
960
+ font-weight: 600;
961
+ }
962
+
963
+ .loading-spinner {
964
+ text-align: center;
965
+ padding: 40px;
966
+ color: var(--primary);
967
+ }
968
+
969
+ .badge {
970
+ padding: 5px 12px;
971
+ border-radius: 15px;
972
+ font-size: 0.75em;
973
+ font-weight: 700;
974
+ display: inline-block;
975
+ }
976
+
977
+ .badge-success {
978
+ background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
979
+ color: #065f46;
980
+ border: 1px solid #6ee7b7;
981
+ }
982
+
983
+ .badge-danger {
984
+ background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
985
+ color: #991b1b;
986
+ border: 1px solid #fca5a5;
987
+ }
988
+
989
+ .empty-state {
990
+ text-align: center;
991
+ padding: 60px 30px;
992
+ color: #94a3b8;
993
+ }
994
+
995
+ .empty-state-icon {
996
+ font-size: 60px;
997
+ margin-bottom: 15px;
998
+ opacity: 0.5;
999
+ }
1000
+
1001
+ .empty-state-text {
1002
+ font-size: 1em;
1003
+ margin-bottom: 8px;
1004
+ font-weight: 600;
1005
+ }
1006
+
1007
+ .search-box {
1008
+ position: relative;
1009
+ }
1010
+
1011
+ .search-box input {
1012
+ width: 100%;
1013
+ padding: 12px 15px 12px 40px;
1014
+ border: 2px solid var(--border);
1015
+ border-radius: 12px;
1016
+ font-size: 0.9em;
1017
+ }
1018
+
1019
+ .search-box input:focus {
1020
+ border-color: var(--primary);
1021
+ }
1022
+
1023
+ .search-box::before {
1024
+ content: '🔍';
1025
+ position: absolute;
1026
+ left: 12px;
1027
+ top: 50%;
1028
+ transform: translateY(-50%);
1029
+ font-size: 1.1em;
1030
+ opacity: 0.5;
1031
+ }
1032
+
1033
+ .skeleton {
1034
+ background: #e0e0e0;
1035
+ border-radius: 8px;
1036
+ }
1037
+
1038
+ .skeleton-card {
1039
+ height: 180px;
1040
+ }
1041
+
1042
+ @media (max-width: 768px) {
1043
+ .app-container {
1044
+ margin: 10px;
1045
+ border-radius: 15px;
1046
+ }
1047
+
1048
+ .app-body {
1049
+ padding: 15px 20px;
1050
+ }
1051
+
1052
+ .header {
1053
+ padding: 15px 20px;
1054
+ }
1055
+
1056
+ .header h1 {
1057
+ font-size: 1.5em;
1058
+ }
1059
+
1060
+ .header-top {
1061
+ flex-direction: column;
1062
+ }
1063
+
1064
+ .status-bar {
1065
+ flex-direction: column;
1066
+ gap: 10px;
1067
+ }
1068
+
1069
+ .status-item {
1070
+ width: 100%;
1071
+ justify-content: space-between;
1072
+ }
1073
+
1074
+ .tab-button {
1075
+ min-width: 100px;
1076
+ padding: 12px 14px;
1077
+ }
1078
+
1079
+ .channel-grid {
1080
+ grid-template-columns: 1fr;
1081
+ }
1082
+
1083
+ .epg-controls {
1084
+ grid-template-columns: 1fr;
1085
+ }
1086
+
1087
+ .player-controls {
1088
+ grid-template-columns: 1fr;
1089
+ }
1090
+
1091
+ .stream-info-panel {
1092
+ grid-template-columns: 1fr;
1093
+ }
1094
+
1095
+ .cache-grid {
1096
+ grid-template-columns: 1fr;
1097
+ }
1098
+
1099
+ .button-group {
1100
+ flex-direction: column;
1101
+ }
1102
+
1103
+ .epg-video-container {
1104
+ max-height: 95vh;
1105
+ }
1106
+ }
1107
+
1108
+ ::-webkit-scrollbar {
1109
+ width: 8px;
1110
+ height: 8px;
1111
+ }
1112
+
1113
+ ::-webkit-scrollbar-track {
1114
+ background: #f1f5f9;
1115
+ }
1116
+
1117
+ ::-webkit-scrollbar-thumb {
1118
+ background: #cbd5e1;
1119
+ border-radius: 4px;
1120
+ }
1121
+
1122
+ ::-webkit-scrollbar-thumb:hover {
1123
+ background: #94a3b8;
1124
+ }
1125
+
1126
+ .hidden {
1127
+ display: none !important;
1128
+ }
1129
+
1130
+ .text-center {
1131
+ text-align: center;
1132
+ }
1133
+
1134
+ .admin-only {
1135
+ display: none;
1136
+ }
1137
+
1138
+ .channel-card,
1139
+ .epg-item,
1140
+ .cache-card {
1141
+ transform: translateZ(0);
1142
+ backface-visibility: hidden;
1143
+ }
1144
+
1145
+ @media print {
1146
+ body {
1147
+ background: white;
1148
+ }
1149
+
1150
+ .header,
1151
+ .tabs,
1152
+ .btn,
1153
+ .footer,
1154
+ .notification {
1155
+ display: none;
1156
+ }
1157
+ }
1158
+ .epg-page {
1159
+ height: 100%;
1160
+ display: flex;
1161
+ flex-direction: column;
1162
+ }
1163
+
1164
+ .epg-list-container {
1165
+ flex: 1;
1166
+ overflow-y: auto;
1167
+ -webkit-overflow-scrolling: touch;
1168
+ contain: strict;
1169
+ padding-bottom: 80px;
1170
+ }
1171
+
1172
+ .epg-list-container::-webkit-scrollbar {
1173
+ width: 6px;
1174
+ }
1175
+
1176
+ .epg-list-container::-webkit-scrollbar-thumb {
1177
+ background: var(--primary-light);
1178
+ border-radius: 4px;
1179
+ }
1180
+
1181
+ .epg-controls-panel {
1182
+ position: sticky;
1183
+ top: 0;
1184
+ z-index: 10;
1185
+ background: rgba(255, 255, 255, 0.9);
1186
+ backdrop-filter: blur(10px);
1187
+ -webkit-backdrop-filter: blur(10px);
1188
+ border-bottom: 1px solid var(--border);
1189
  }