@frameset/plex-player 1.0.6 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1651 +0,0 @@
1
- /* =====================================================
2
- PLEX Video Player - Main Styles
3
- ===================================================== */
4
-
5
- /* CSS Variables - scoped to player */
6
- .plex-player,
7
- .plex-player-container {
8
- --plex-primary: #e5a00d;
9
- --plex-primary-hover: #f5b82e;
10
- --plex-bg-dark: #1a1a1a;
11
- --plex-bg-darker: #0d0d0d;
12
- --plex-bg-overlay: rgba(0, 0, 0, 0.85);
13
- --plex-text-primary: #ffffff;
14
- --plex-text-secondary: #a0a0a0;
15
- --plex-border: rgba(255, 255, 255, 0.1);
16
- --plex-gradient: linear-gradient(to top, rgba(0, 0, 0, 0.9) 0%, transparent 100%);
17
- --plex-gradient-top: linear-gradient(to bottom, rgba(0, 0, 0, 0.7) 0%, transparent 100%);
18
- --plex-transition-fast: 0.15s ease;
19
- --plex-transition-normal: 0.25s ease;
20
- --plex-transition-slow: 0.4s ease;
21
- --plex-radius-sm: 4px;
22
- --plex-radius-md: 8px;
23
- --plex-radius-lg: 12px;
24
- --plex-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
25
- --plex-z-video: 1;
26
- --plex-z-overlay: 10;
27
- --plex-z-controls: 20;
28
- --plex-z-panel: 30;
29
- --plex-z-modal: 40;
30
- --plex-z-toast: 50;
31
- }
32
-
33
- /* Scoped Reset - only inside player */
34
- .plex-player *,
35
- .plex-player *::before,
36
- .plex-player *::after {
37
- box-sizing: border-box;
38
- margin: 0;
39
- padding: 0;
40
- }
41
-
42
- /* Player Container Wrapper */
43
- .plex-player-container {
44
- position: relative;
45
- width: 100%;
46
- aspect-ratio: 16 / 9;
47
- background: var(--plex-bg-darker);
48
- border-radius: var(--plex-radius-md);
49
- overflow: hidden;
50
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
51
- -webkit-font-smoothing: antialiased;
52
- -moz-osx-font-smoothing: grayscale;
53
- }
54
-
55
- /* Player Container */
56
- .plex-player {
57
- position: relative;
58
- width: 100%;
59
- height: 100%;
60
- background: var(--plex-bg-darker);
61
- overflow: hidden;
62
- user-select: none;
63
- -webkit-user-select: none;
64
- -webkit-tap-highlight-color: transparent;
65
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
66
- color: var(--plex-text-primary);
67
- }
68
-
69
- .plex-player.plex-fullscreen {
70
- position: fixed;
71
- top: 0;
72
- left: 0;
73
- width: 100vw;
74
- height: 100vh;
75
- z-index: 9999;
76
- border-radius: 0;
77
- }
78
-
79
- /* Video Container */
80
- .video-container {
81
- position: relative;
82
- width: 100%;
83
- height: 100%;
84
- display: flex;
85
- align-items: center;
86
- justify-content: center;
87
- background: #000;
88
- z-index: var(--plex-z-video);
89
- }
90
-
91
- .video-container video {
92
- width: 100%;
93
- height: 100%;
94
- max-width: 100%;
95
- max-height: 100%;
96
- object-fit: contain;
97
- background: #000;
98
- }
99
-
100
- /* Controls Visibility */
101
- .plex-player.controls-visible .top-controls,
102
- .plex-player.controls-visible .bottom-controls {
103
- opacity: 1;
104
- visibility: visible;
105
- transform: translateY(0);
106
- }
107
-
108
- .plex-player:not(.controls-visible) .top-controls,
109
- .plex-player:not(.controls-visible) .bottom-controls {
110
- opacity: 0;
111
- visibility: hidden;
112
- }
113
-
114
- .plex-player:not(.controls-visible) .top-controls {
115
- transform: translateY(-100%);
116
- }
117
-
118
- .plex-player:not(.controls-visible) .bottom-controls {
119
- transform: translateY(100%);
120
- }
121
-
122
- /* Cursor hiding */
123
- .plex-player.hide-cursor {
124
- cursor: none;
125
- }
126
-
127
- .plex-player.hide-cursor video {
128
- cursor: none;
129
- }
130
-
131
- /* Loading Spinner */
132
- .loading-spinner {
133
- position: absolute;
134
- top: 50%;
135
- left: 50%;
136
- transform: translate(-50%, -50%);
137
- z-index: var(--plex-z-overlay);
138
- }
139
-
140
- .loading-spinner .spinner {
141
- width: 60px;
142
- height: 60px;
143
- border: 4px solid rgba(255, 255, 255, 0.2);
144
- border-top-color: var(--plex-primary);
145
- border-radius: 50%;
146
- animation: spin 1s linear infinite;
147
- }
148
-
149
- @keyframes spin {
150
- to {
151
- transform: rotate(360deg);
152
- }
153
- }
154
-
155
- /* Big Play Button */
156
- .big-play-btn {
157
- position: absolute;
158
- top: 50%;
159
- left: 50%;
160
- transform: translate(-50%, -50%) scale(1);
161
- width: 80px;
162
- height: 80px;
163
- background: var(--plex-primary);
164
- border-radius: 50%;
165
- display: flex;
166
- align-items: center;
167
- justify-content: center;
168
- cursor: pointer;
169
- z-index: var(--plex-z-overlay);
170
- transition: all var(--plex-transition-normal);
171
- box-shadow: 0 4px 30px rgba(229, 160, 13, 0.4);
172
- }
173
-
174
- .big-play-btn:hover {
175
- transform: translate(-50%, -50%) scale(1.1);
176
- background: var(--plex-primary-hover);
177
- }
178
-
179
- .big-play-btn .material-icons {
180
- font-size: 48px;
181
- color: #000;
182
- margin-left: 4px;
183
- }
184
-
185
- .big-play-btn.hidden {
186
- opacity: 0;
187
- visibility: hidden;
188
- transform: translate(-50%, -50%) scale(0.8);
189
- }
190
-
191
- /* Gesture Overlay */
192
- .gesture-overlay {
193
- position: absolute;
194
- top: 0;
195
- left: 0;
196
- width: 100%;
197
- height: 100%;
198
- display: flex;
199
- z-index: var(--plex-z-overlay);
200
- pointer-events: none;
201
- }
202
-
203
- .gesture-left,
204
- .gesture-right {
205
- flex: 1;
206
- display: flex;
207
- align-items: center;
208
- justify-content: center;
209
- }
210
-
211
- .gesture-center {
212
- flex: 1;
213
- }
214
-
215
- .gesture-indicator {
216
- display: flex;
217
- flex-direction: column;
218
- align-items: center;
219
- gap: 8px;
220
- padding: 20px;
221
- background: rgba(0, 0, 0, 0.7);
222
- border-radius: var(--plex-radius-lg);
223
- opacity: 0;
224
- transform: scale(0.8);
225
- transition: all var(--plex-transition-fast);
226
- }
227
-
228
- .gesture-indicator.active {
229
- opacity: 1;
230
- transform: scale(1);
231
- }
232
-
233
- .gesture-indicator .material-icons {
234
- font-size: 48px;
235
- color: var(--plex-text-primary);
236
- }
237
-
238
- .gesture-indicator .gesture-text {
239
- font-size: 14px;
240
- font-weight: 600;
241
- color: var(--plex-text-primary);
242
- }
243
-
244
- /* Volume/Brightness Indicators */
245
- .volume-indicator,
246
- .brightness-indicator {
247
- position: absolute;
248
- top: 50%;
249
- left: 50%;
250
- transform: translate(-50%, -50%);
251
- display: flex;
252
- flex-direction: column;
253
- align-items: center;
254
- gap: 12px;
255
- padding: 24px;
256
- background: rgba(0, 0, 0, 0.8);
257
- border-radius: var(--plex-radius-lg);
258
- z-index: var(--plex-z-overlay);
259
- transition: opacity var(--plex-transition-fast);
260
- }
261
-
262
- .volume-indicator .material-icons,
263
- .brightness-indicator .material-icons {
264
- font-size: 36px;
265
- color: var(--plex-text-primary);
266
- }
267
-
268
- .volume-indicator-bar,
269
- .brightness-indicator-bar {
270
- width: 120px;
271
- height: 4px;
272
- background: rgba(255, 255, 255, 0.2);
273
- border-radius: 2px;
274
- overflow: hidden;
275
- }
276
-
277
- .volume-indicator-fill,
278
- .brightness-indicator-fill {
279
- height: 100%;
280
- background: var(--plex-primary);
281
- border-radius: 2px;
282
- transition: width var(--plex-transition-fast);
283
- }
284
-
285
- /* Subtitles Container */
286
- .subtitles-container {
287
- position: absolute;
288
- bottom: 80px;
289
- left: 50%;
290
- transform: translateX(-50%);
291
- width: 80%;
292
- max-width: 800px;
293
- text-align: center;
294
- z-index: var(--plex-z-overlay);
295
- pointer-events: none;
296
- }
297
-
298
- .subtitle-line {
299
- display: inline-block;
300
- padding: 8px 16px;
301
- margin: 4px 0;
302
- background: rgba(0, 0, 0, 0.75);
303
- border-radius: var(--plex-radius-sm);
304
- font-size: 24px;
305
- line-height: 1.4;
306
- color: #fff;
307
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
308
- }
309
-
310
- /* Cast Overlay */
311
- .cast-overlay {
312
- position: absolute;
313
- top: 0;
314
- left: 0;
315
- width: 100%;
316
- height: 100%;
317
- background: var(--plex-bg-darker);
318
- display: flex;
319
- align-items: center;
320
- justify-content: center;
321
- z-index: var(--plex-z-overlay);
322
- }
323
-
324
- .cast-overlay.hidden {
325
- display: none;
326
- }
327
-
328
- .cast-overlay-content {
329
- text-align: center;
330
- animation: castPulse 2s ease-in-out infinite;
331
- }
332
-
333
- .cast-overlay .cast-icon {
334
- font-size: 80px;
335
- color: var(--plex-primary);
336
- margin-bottom: 24px;
337
- }
338
-
339
- .cast-overlay .cast-title {
340
- font-size: 18px;
341
- color: var(--plex-text-secondary);
342
- margin-bottom: 8px;
343
- }
344
-
345
- .cast-overlay .cast-device {
346
- font-size: 28px;
347
- font-weight: 600;
348
- color: var(--plex-text-primary);
349
- margin-bottom: 16px;
350
- }
351
-
352
- .cast-overlay .cast-video {
353
- font-size: 16px;
354
- color: var(--plex-text-secondary);
355
- max-width: 300px;
356
- white-space: nowrap;
357
- overflow: hidden;
358
- text-overflow: ellipsis;
359
- }
360
-
361
- @keyframes castPulse {
362
- 0%, 100% { opacity: 1; }
363
- 50% { opacity: 0.7; }
364
- }
365
-
366
- /* Utility Classes */
367
- .hidden {
368
- display: none !important;
369
- }
370
-
371
- .visually-hidden {
372
- opacity: 0;
373
- visibility: hidden;
374
- }
375
-
376
- /* Toast Notification */
377
- .toast {
378
- position: absolute;
379
- bottom: 100px;
380
- left: 50%;
381
- transform: translateX(-50%) translateY(20px);
382
- background: var(--plex-bg-overlay);
383
- padding: 12px 24px;
384
- border-radius: var(--plex-radius-md);
385
- z-index: var(--plex-z-toast);
386
- opacity: 0;
387
- visibility: hidden;
388
- transition: all var(--plex-transition-normal);
389
- }
390
-
391
- .toast.show {
392
- opacity: 1;
393
- visibility: visible;
394
- transform: translateX(-50%) translateY(0);
395
- }
396
-
397
- .toast-message {
398
- font-size: 14px;
399
- font-weight: 500;
400
- color: var(--plex-text-primary);
401
- }
402
-
403
- /* Context Menu */
404
- .context-menu {
405
- position: fixed;
406
- min-width: 200px;
407
- background: var(--plex-bg-dark);
408
- border: 1px solid var(--plex-border);
409
- border-radius: var(--plex-radius-md);
410
- box-shadow: var(--plex-shadow);
411
- z-index: var(--plex-z-modal);
412
- overflow: hidden;
413
- }
414
-
415
- .context-menu-item {
416
- display: flex;
417
- align-items: center;
418
- gap: 12px;
419
- padding: 12px 16px;
420
- cursor: pointer;
421
- transition: background var(--plex-transition-fast);
422
- }
423
-
424
- .context-menu-item:hover {
425
- background: rgba(255, 255, 255, 0.1);
426
- }
427
-
428
- .context-menu-item .material-icons {
429
- font-size: 20px;
430
- color: var(--plex-text-secondary);
431
- }
432
-
433
- .context-menu-item span:last-child {
434
- font-size: 14px;
435
- color: var(--plex-text-primary);
436
- }
437
-
438
- .context-menu-divider {
439
- height: 1px;
440
- background: var(--plex-border);
441
- margin: 4px 0;
442
- }
443
-
444
- /* Stats Overlay */
445
- .stats-overlay {
446
- position: absolute;
447
- top: 80px;
448
- left: 20px;
449
- width: 280px;
450
- background: var(--plex-bg-overlay);
451
- border-radius: var(--plex-radius-md);
452
- z-index: var(--plex-z-panel);
453
- overflow: hidden;
454
- }
455
-
456
- .stats-header {
457
- display: flex;
458
- align-items: center;
459
- justify-content: space-between;
460
- padding: 12px 16px;
461
- background: rgba(255, 255, 255, 0.05);
462
- border-bottom: 1px solid var(--plex-border);
463
- font-size: 14px;
464
- font-weight: 600;
465
- }
466
-
467
- .stats-content {
468
- padding: 12px 16px;
469
- }
470
-
471
- .stat-item {
472
- display: flex;
473
- justify-content: space-between;
474
- padding: 8px 0;
475
- font-size: 13px;
476
- border-bottom: 1px solid var(--plex-border);
477
- }
478
-
479
- .stat-item:last-child {
480
- border-bottom: none;
481
- }
482
-
483
- .stat-label {
484
- color: var(--plex-text-secondary);
485
- }
486
-
487
- .stat-value {
488
- color: var(--plex-text-primary);
489
- font-weight: 500;
490
- }
491
-
492
- /* Responsive */
493
- @media (max-width: 768px) {
494
- .big-play-btn {
495
- width: 64px;
496
- height: 64px;
497
- }
498
-
499
- .big-play-btn .material-icons {
500
- font-size: 36px;
501
- }
502
-
503
- .subtitle-line {
504
- font-size: 18px;
505
- padding: 6px 12px;
506
- }
507
-
508
- .subtitles-container {
509
- width: 90%;
510
- bottom: 70px;
511
- }
512
-
513
- .gesture-indicator .material-icons {
514
- font-size: 36px;
515
- }
516
-
517
- .stats-overlay {
518
- top: 60px;
519
- left: 10px;
520
- width: 240px;
521
- }
522
- }
523
-
524
- @media (max-width: 480px) {
525
- .big-play-btn {
526
- width: 56px;
527
- height: 56px;
528
- }
529
-
530
- .big-play-btn .material-icons {
531
- font-size: 32px;
532
- }
533
-
534
- .subtitle-line {
535
- font-size: 16px;
536
- }
537
- }
538
-
539
- /* Touch Device Optimizations */
540
- @media (hover: none) and (pointer: coarse) {
541
- .control-btn {
542
- min-width: 44px;
543
- min-height: 44px;
544
- }
545
-
546
- .volume-slider-container {
547
- display: none;
548
- }
549
- }
550
-
551
- /* Animations */
552
- @keyframes fadeIn {
553
- from {
554
- opacity: 0;
555
- }
556
- to {
557
- opacity: 1;
558
- }
559
- }
560
-
561
- @keyframes slideUp {
562
- from {
563
- opacity: 0;
564
- transform: translateY(20px);
565
- }
566
- to {
567
- opacity: 1;
568
- transform: translateY(0);
569
- }
570
- }
571
-
572
- @keyframes pulse {
573
- 0%, 100% {
574
- transform: translate(-50%, -50%) scale(1);
575
- }
576
- 50% {
577
- transform: translate(-50%, -50%) scale(1.05);
578
- }
579
- }
580
-
581
- /* =====================================================
582
- PLEX Video Player - Controls Styles (NPM Package)
583
- ===================================================== */
584
-
585
- /* Video Element */
586
- .plex-video {
587
- width: 100%;
588
- height: 100%;
589
- object-fit: contain;
590
- background: #000;
591
- }
592
-
593
- /* Controls Container */
594
- .plex-controls {
595
- position: absolute;
596
- bottom: 0;
597
- left: 0;
598
- right: 0;
599
- padding: 0 16px 16px;
600
- background: var(--plex-gradient);
601
- z-index: var(--plex-z-controls);
602
- transition: opacity var(--plex-transition-normal), visibility var(--plex-transition-normal);
603
- opacity: 1;
604
- visibility: visible;
605
- }
606
-
607
- .plex-player:not(.plex-controls-visible) .plex-controls {
608
- opacity: 0;
609
- visibility: hidden;
610
- }
611
-
612
- /* Progress Container */
613
- .plex-progress-container {
614
- position: relative;
615
- width: 100%;
616
- height: 24px;
617
- display: flex;
618
- align-items: center;
619
- cursor: pointer;
620
- padding: 8px 0;
621
- }
622
-
623
- .plex-progress-bar {
624
- position: relative;
625
- width: 100%;
626
- height: 4px;
627
- background: rgba(255, 255, 255, 0.2);
628
- border-radius: 2px;
629
- overflow: visible;
630
- transition: height var(--plex-transition-fast);
631
- }
632
-
633
- .plex-progress-container:hover .plex-progress-bar {
634
- height: 6px;
635
- }
636
-
637
- .plex-progress-buffered {
638
- position: absolute;
639
- top: 0;
640
- left: 0;
641
- height: 100%;
642
- background: rgba(255, 255, 255, 0.35);
643
- border-radius: 2px;
644
- pointer-events: none;
645
- width: 0;
646
- }
647
-
648
- .plex-progress-played {
649
- position: absolute;
650
- top: 0;
651
- left: 0;
652
- height: 100%;
653
- background: var(--plex-primary);
654
- border-radius: 2px;
655
- pointer-events: none;
656
- width: 0;
657
- }
658
-
659
- .plex-progress-handle {
660
- position: absolute;
661
- top: 50%;
662
- left: 0;
663
- width: 14px;
664
- height: 14px;
665
- background: var(--plex-primary);
666
- border-radius: 50%;
667
- transform: translate(-50%, -50%) scale(0);
668
- transition: transform var(--plex-transition-fast);
669
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
670
- pointer-events: none;
671
- }
672
-
673
- .plex-progress-container:hover .plex-progress-handle {
674
- transform: translate(-50%, -50%) scale(1);
675
- }
676
-
677
- /* Progress Preview */
678
- .plex-progress-preview {
679
- position: absolute;
680
- bottom: 100%;
681
- left: 0;
682
- margin-bottom: 8px;
683
- padding: 6px 10px;
684
- background: var(--plex-bg-dark);
685
- border-radius: var(--plex-radius-sm);
686
- opacity: 0;
687
- visibility: hidden;
688
- transform: translateX(-50%);
689
- transition: opacity var(--plex-transition-fast);
690
- pointer-events: none;
691
- z-index: 50;
692
- }
693
-
694
- .plex-progress-container:hover .plex-progress-preview {
695
- opacity: 1;
696
- visibility: visible;
697
- }
698
-
699
- .plex-preview-time {
700
- font-size: 13px;
701
- font-weight: 600;
702
- color: var(--plex-text-primary);
703
- white-space: nowrap;
704
- }
705
-
706
- /* Controls Bar */
707
- .plex-controls-bar {
708
- display: flex;
709
- align-items: center;
710
- justify-content: space-between;
711
- margin-top: 8px;
712
- }
713
-
714
- .plex-controls-left,
715
- .plex-controls-right {
716
- display: flex;
717
- align-items: center;
718
- gap: 4px;
719
- }
720
-
721
- /* Control Button */
722
- .plex-btn {
723
- position: relative;
724
- display: flex;
725
- align-items: center;
726
- justify-content: center;
727
- width: 40px;
728
- height: 40px;
729
- padding: 0;
730
- background: transparent;
731
- border: none;
732
- border-radius: var(--plex-radius-sm);
733
- cursor: pointer;
734
- transition: all var(--plex-transition-fast);
735
- color: var(--plex-text-primary);
736
- }
737
-
738
- .plex-btn:hover {
739
- background: rgba(255, 255, 255, 0.1);
740
- }
741
-
742
- .plex-btn:active {
743
- transform: scale(0.95);
744
- }
745
-
746
- .plex-btn svg {
747
- width: 24px;
748
- height: 24px;
749
- fill: currentColor;
750
- }
751
-
752
- .plex-btn:focus-visible {
753
- outline: 2px solid var(--plex-primary);
754
- outline-offset: 2px;
755
- }
756
-
757
- /* Play Button States */
758
- .plex-player.plex-playing .plex-play-btn .plex-icon-play {
759
- display: none;
760
- }
761
-
762
- .plex-player.plex-playing .plex-play-btn .plex-icon-pause {
763
- display: block;
764
- }
765
-
766
- .plex-player:not(.plex-playing) .plex-play-btn .plex-icon-play {
767
- display: block;
768
- }
769
-
770
- .plex-player:not(.plex-playing) .plex-play-btn .plex-icon-pause {
771
- display: none;
772
- }
773
-
774
- /* Volume Container */
775
- .plex-volume-container {
776
- display: flex;
777
- align-items: center;
778
- gap: 4px;
779
- }
780
-
781
- .plex-volume-slider {
782
- position: relative;
783
- width: 0;
784
- overflow: hidden;
785
- transition: width var(--plex-transition-normal);
786
- }
787
-
788
- .plex-volume-container:hover .plex-volume-slider {
789
- width: 80px;
790
- }
791
-
792
- .plex-volume-track {
793
- position: relative;
794
- width: 80px;
795
- height: 4px;
796
- background: rgba(255, 255, 255, 0.2);
797
- border-radius: 2px;
798
- cursor: pointer;
799
- }
800
-
801
- .plex-volume-level {
802
- position: absolute;
803
- top: 0;
804
- left: 0;
805
- height: 100%;
806
- background: var(--plex-primary);
807
- border-radius: 2px;
808
- pointer-events: none;
809
- width: 100%;
810
- }
811
-
812
- .plex-volume-handle {
813
- position: absolute;
814
- top: 50%;
815
- right: 0;
816
- width: 12px;
817
- height: 12px;
818
- background: var(--plex-primary);
819
- border-radius: 50%;
820
- transform: translateY(-50%);
821
- cursor: pointer;
822
- opacity: 0;
823
- transition: opacity var(--plex-transition-fast);
824
- }
825
-
826
- .plex-volume-container:hover .plex-volume-handle {
827
- opacity: 1;
828
- }
829
-
830
- /* Volume Button States */
831
- .plex-player.plex-muted .plex-icon-volume-high,
832
- .plex-player.plex-muted .plex-icon-volume-low {
833
- display: none;
834
- }
835
-
836
- .plex-player.plex-muted .plex-icon-volume-mute {
837
- display: block;
838
- }
839
-
840
- .plex-player:not(.plex-muted) .plex-icon-volume-mute {
841
- display: none;
842
- }
843
-
844
- .plex-player:not(.plex-muted) .plex-icon-volume-high {
845
- display: block;
846
- }
847
-
848
- .plex-player:not(.plex-muted) .plex-icon-volume-low {
849
- display: none;
850
- }
851
-
852
- /* Time Display */
853
- .plex-time {
854
- display: flex;
855
- align-items: center;
856
- gap: 4px;
857
- margin-left: 8px;
858
- font-size: 13px;
859
- font-weight: 500;
860
- color: var(--plex-text-primary);
861
- }
862
-
863
- .plex-time-current,
864
- .plex-time-duration {
865
- font-variant-numeric: tabular-nums;
866
- }
867
-
868
- .plex-time-separator {
869
- color: var(--plex-text-secondary);
870
- }
871
-
872
- /* Fullscreen Button States */
873
- .plex-player.plex-fullscreen .plex-icon-fullscreen {
874
- display: none;
875
- }
876
-
877
- .plex-player.plex-fullscreen .plex-icon-fullscreen-exit {
878
- display: block;
879
- }
880
-
881
- .plex-player:not(.plex-fullscreen) .plex-icon-fullscreen {
882
- display: block;
883
- }
884
-
885
- .plex-player:not(.plex-fullscreen) .plex-icon-fullscreen-exit {
886
- display: none;
887
- }
888
-
889
- /* Big Play Button */
890
- .plex-big-play {
891
- position: absolute;
892
- top: 50%;
893
- left: 50%;
894
- transform: translate(-50%, -50%) scale(1);
895
- width: 72px;
896
- height: 72px;
897
- background: var(--plex-primary);
898
- border-radius: 50%;
899
- display: flex;
900
- align-items: center;
901
- justify-content: center;
902
- cursor: pointer;
903
- z-index: var(--plex-z-overlay);
904
- transition: all var(--plex-transition-normal);
905
- box-shadow: 0 4px 30px rgba(229, 160, 13, 0.4);
906
- }
907
-
908
- .plex-big-play:hover {
909
- transform: translate(-50%, -50%) scale(1.1);
910
- background: var(--plex-primary-hover);
911
- }
912
-
913
- .plex-big-play svg {
914
- width: 40px;
915
- height: 40px;
916
- fill: #000;
917
- margin-left: 4px;
918
- }
919
-
920
- .plex-player.plex-playing .plex-big-play {
921
- opacity: 0;
922
- visibility: hidden;
923
- transform: translate(-50%, -50%) scale(0.8);
924
- }
925
-
926
- /* Loader */
927
- .plex-loader {
928
- position: absolute;
929
- top: 50%;
930
- left: 50%;
931
- transform: translate(-50%, -50%);
932
- z-index: var(--plex-z-overlay);
933
- display: none;
934
- }
935
-
936
- .plex-player.plex-loading .plex-loader {
937
- display: block;
938
- }
939
-
940
- .plex-player.plex-loading .plex-big-play {
941
- display: none;
942
- }
943
-
944
- .plex-spinner {
945
- width: 48px;
946
- height: 48px;
947
- border: 4px solid rgba(255, 255, 255, 0.2);
948
- border-top-color: var(--plex-primary);
949
- border-radius: 50%;
950
- animation: plex-spin 1s linear infinite;
951
- }
952
-
953
- @keyframes plex-spin {
954
- to {
955
- transform: rotate(360deg);
956
- }
957
- }
958
-
959
- /* Responsive */
960
- @media (max-width: 768px) {
961
- .plex-controls {
962
- padding: 0 12px 12px;
963
- }
964
-
965
- .plex-btn {
966
- width: 36px;
967
- height: 36px;
968
- }
969
-
970
- .plex-btn svg {
971
- width: 22px;
972
- height: 22px;
973
- }
974
-
975
- .plex-time {
976
- font-size: 12px;
977
- }
978
-
979
- .plex-big-play {
980
- width: 60px;
981
- height: 60px;
982
- }
983
-
984
- .plex-big-play svg {
985
- width: 32px;
986
- height: 32px;
987
- }
988
- }
989
-
990
- @media (max-width: 480px) {
991
- .plex-controls-left,
992
- .plex-controls-right {
993
- gap: 0;
994
- }
995
-
996
- .plex-btn {
997
- width: 32px;
998
- height: 32px;
999
- }
1000
-
1001
- .plex-btn svg {
1002
- width: 20px;
1003
- height: 20px;
1004
- }
1005
-
1006
- .plex-prev-btn,
1007
- .plex-next-btn,
1008
- .plex-cast-btn {
1009
- display: none;
1010
- }
1011
-
1012
- .plex-big-play {
1013
- width: 56px;
1014
- height: 56px;
1015
- }
1016
-
1017
- .plex-big-play svg {
1018
- width: 28px;
1019
- height: 28px;
1020
- }
1021
- }
1022
-
1023
- /* Controls Visibility */
1024
- .plex-player.plex-controls-visible .plex-controls {
1025
- opacity: 1;
1026
- visibility: visible;
1027
- }
1028
-
1029
- /* Cursor hiding when controls hidden */
1030
- .plex-player:not(.plex-controls-visible) {
1031
- cursor: none;
1032
- }
1033
-
1034
- .plex-player:not(.plex-controls-visible) .plex-video {
1035
- cursor: none;
1036
- }
1037
-
1038
- /* =====================================================
1039
- PLEX Video Player - Playlist Styles
1040
- ===================================================== */
1041
-
1042
- /* Playlist Panel */
1043
- .playlist-panel {
1044
- position: absolute;
1045
- top: 0;
1046
- right: 0;
1047
- width: 360px;
1048
- height: 100%;
1049
- background: var(--plex-bg-dark);
1050
- border-left: 1px solid var(--plex-border);
1051
- z-index: var(--plex-z-panel);
1052
- display: flex;
1053
- flex-direction: column;
1054
- transform: translateX(100%);
1055
- transition: transform var(--plex-transition-normal);
1056
- }
1057
-
1058
- .playlist-panel.visible {
1059
- transform: translateX(0);
1060
- }
1061
-
1062
- /* Playlist Header */
1063
- .playlist-header {
1064
- display: flex;
1065
- align-items: center;
1066
- justify-content: space-between;
1067
- padding: 16px 20px;
1068
- background: rgba(255, 255, 255, 0.03);
1069
- border-bottom: 1px solid var(--plex-border);
1070
- flex-shrink: 0;
1071
- }
1072
-
1073
- .playlist-title {
1074
- font-size: 16px;
1075
- font-weight: 600;
1076
- color: var(--plex-text-primary);
1077
- }
1078
-
1079
- .playlist-header-actions {
1080
- display: flex;
1081
- align-items: center;
1082
- gap: 4px;
1083
- }
1084
-
1085
- /* Playlist Content */
1086
- .playlist-content {
1087
- flex: 1;
1088
- overflow-y: auto;
1089
- overflow-x: hidden;
1090
- padding: 12px;
1091
- }
1092
-
1093
- .playlist-content::-webkit-scrollbar {
1094
- width: 6px;
1095
- }
1096
-
1097
- .playlist-content::-webkit-scrollbar-track {
1098
- background: transparent;
1099
- }
1100
-
1101
- .playlist-content::-webkit-scrollbar-thumb {
1102
- background: rgba(255, 255, 255, 0.2);
1103
- border-radius: 3px;
1104
- }
1105
-
1106
- .playlist-content::-webkit-scrollbar-thumb:hover {
1107
- background: rgba(255, 255, 255, 0.3);
1108
- }
1109
-
1110
- /* Playlist Empty State */
1111
- .playlist-empty {
1112
- display: flex;
1113
- flex-direction: column;
1114
- align-items: center;
1115
- justify-content: center;
1116
- height: 100%;
1117
- padding: 40px;
1118
- text-align: center;
1119
- }
1120
-
1121
- .playlist-empty .material-icons {
1122
- font-size: 64px;
1123
- color: var(--plex-text-secondary);
1124
- margin-bottom: 16px;
1125
- opacity: 0.5;
1126
- }
1127
-
1128
- .playlist-empty-title {
1129
- font-size: 18px;
1130
- font-weight: 600;
1131
- color: var(--plex-text-primary);
1132
- margin-bottom: 8px;
1133
- }
1134
-
1135
- .playlist-empty-text {
1136
- font-size: 14px;
1137
- color: var(--plex-text-secondary);
1138
- line-height: 1.5;
1139
- }
1140
-
1141
- /* Playlist Item */
1142
- .playlist-item {
1143
- display: flex;
1144
- align-items: center;
1145
- gap: 12px;
1146
- padding: 10px 12px;
1147
- background: rgba(255, 255, 255, 0.02);
1148
- border-radius: var(--plex-radius-md);
1149
- cursor: pointer;
1150
- transition: all var(--plex-transition-fast);
1151
- margin-bottom: 8px;
1152
- position: relative;
1153
- }
1154
-
1155
- .playlist-item:hover {
1156
- background: rgba(255, 255, 255, 0.08);
1157
- }
1158
-
1159
- .playlist-item.active {
1160
- background: rgba(229, 160, 13, 0.15);
1161
- border: 1px solid rgba(229, 160, 13, 0.3);
1162
- }
1163
-
1164
- .playlist-item.playing {
1165
- background: rgba(229, 160, 13, 0.2);
1166
- }
1167
-
1168
- .playlist-item.dragging {
1169
- opacity: 0.5;
1170
- transform: scale(0.98);
1171
- }
1172
-
1173
- /* Playlist Item Thumbnail */
1174
- .playlist-item-thumbnail {
1175
- position: relative;
1176
- width: 100px;
1177
- height: 56px;
1178
- background: var(--plex-bg-darker);
1179
- border-radius: var(--plex-radius-sm);
1180
- overflow: hidden;
1181
- flex-shrink: 0;
1182
- }
1183
-
1184
- .playlist-item-thumbnail img {
1185
- width: 100%;
1186
- height: 100%;
1187
- object-fit: cover;
1188
- }
1189
-
1190
- .playlist-item-thumbnail .placeholder-icon {
1191
- position: absolute;
1192
- top: 50%;
1193
- left: 50%;
1194
- transform: translate(-50%, -50%);
1195
- font-size: 32px;
1196
- color: var(--plex-text-secondary);
1197
- opacity: 0.5;
1198
- }
1199
-
1200
- .playlist-item-duration {
1201
- position: absolute;
1202
- bottom: 4px;
1203
- right: 4px;
1204
- padding: 2px 6px;
1205
- background: rgba(0, 0, 0, 0.8);
1206
- border-radius: 3px;
1207
- font-size: 11px;
1208
- font-weight: 600;
1209
- color: var(--plex-text-primary);
1210
- }
1211
-
1212
- /* Playing Indicator */
1213
- .playlist-item-playing-indicator {
1214
- position: absolute;
1215
- top: 50%;
1216
- left: 50%;
1217
- transform: translate(-50%, -50%);
1218
- display: none;
1219
- align-items: flex-end;
1220
- justify-content: center;
1221
- gap: 2px;
1222
- width: 24px;
1223
- height: 20px;
1224
- }
1225
-
1226
- .playlist-item.playing .playlist-item-playing-indicator {
1227
- display: flex;
1228
- }
1229
-
1230
- .playlist-item-playing-indicator span {
1231
- width: 4px;
1232
- background: var(--plex-primary);
1233
- border-radius: 1px;
1234
- animation: equalizer 0.5s ease-in-out infinite alternate;
1235
- }
1236
-
1237
- .playlist-item-playing-indicator span:nth-child(1) {
1238
- height: 60%;
1239
- animation-delay: 0s;
1240
- }
1241
-
1242
- .playlist-item-playing-indicator span:nth-child(2) {
1243
- height: 100%;
1244
- animation-delay: 0.15s;
1245
- }
1246
-
1247
- .playlist-item-playing-indicator span:nth-child(3) {
1248
- height: 40%;
1249
- animation-delay: 0.3s;
1250
- }
1251
-
1252
- @keyframes equalizer {
1253
- from {
1254
- transform: scaleY(0.5);
1255
- }
1256
- to {
1257
- transform: scaleY(1);
1258
- }
1259
- }
1260
-
1261
- /* Playlist Item Info */
1262
- .playlist-item-info {
1263
- flex: 1;
1264
- min-width: 0;
1265
- display: flex;
1266
- flex-direction: column;
1267
- gap: 4px;
1268
- }
1269
-
1270
- .playlist-item-title {
1271
- font-size: 14px;
1272
- font-weight: 500;
1273
- color: var(--plex-text-primary);
1274
- white-space: nowrap;
1275
- overflow: hidden;
1276
- text-overflow: ellipsis;
1277
- }
1278
-
1279
- .playlist-item-meta {
1280
- font-size: 12px;
1281
- color: var(--plex-text-secondary);
1282
- display: flex;
1283
- align-items: center;
1284
- gap: 8px;
1285
- }
1286
-
1287
- /* Playlist Item Actions */
1288
- .playlist-item-actions {
1289
- display: flex;
1290
- align-items: center;
1291
- gap: 4px;
1292
- opacity: 0;
1293
- transition: opacity var(--plex-transition-fast);
1294
- }
1295
-
1296
- .playlist-item:hover .playlist-item-actions {
1297
- opacity: 1;
1298
- }
1299
-
1300
- .playlist-item-action {
1301
- display: flex;
1302
- align-items: center;
1303
- justify-content: center;
1304
- width: 28px;
1305
- height: 28px;
1306
- background: transparent;
1307
- border: none;
1308
- border-radius: var(--plex-radius-sm);
1309
- cursor: pointer;
1310
- color: var(--plex-text-secondary);
1311
- transition: all var(--plex-transition-fast);
1312
- }
1313
-
1314
- .playlist-item-action:hover {
1315
- background: rgba(255, 255, 255, 0.1);
1316
- color: var(--plex-text-primary);
1317
- }
1318
-
1319
- .playlist-item-action .material-icons {
1320
- font-size: 18px;
1321
- }
1322
-
1323
- /* Drag Handle */
1324
- .playlist-item-drag-handle {
1325
- display: flex;
1326
- align-items: center;
1327
- justify-content: center;
1328
- width: 20px;
1329
- cursor: grab;
1330
- color: var(--plex-text-secondary);
1331
- opacity: 0;
1332
- transition: opacity var(--plex-transition-fast);
1333
- }
1334
-
1335
- .playlist-item:hover .playlist-item-drag-handle {
1336
- opacity: 1;
1337
- }
1338
-
1339
- .playlist-item-drag-handle:active {
1340
- cursor: grabbing;
1341
- }
1342
-
1343
- .playlist-item-drag-handle .material-icons {
1344
- font-size: 18px;
1345
- }
1346
-
1347
- /* Playlist Footer */
1348
- .playlist-footer {
1349
- padding: 16px;
1350
- border-top: 1px solid var(--plex-border);
1351
- flex-shrink: 0;
1352
- }
1353
-
1354
- .playlist-add-btn {
1355
- display: flex;
1356
- align-items: center;
1357
- justify-content: center;
1358
- gap: 8px;
1359
- width: 100%;
1360
- padding: 12px;
1361
- background: rgba(255, 255, 255, 0.05);
1362
- border: 2px dashed var(--plex-border);
1363
- border-radius: var(--plex-radius-md);
1364
- color: var(--plex-text-secondary);
1365
- font-size: 14px;
1366
- font-weight: 500;
1367
- cursor: pointer;
1368
- transition: all var(--plex-transition-fast);
1369
- }
1370
-
1371
- .playlist-add-btn:hover {
1372
- background: rgba(255, 255, 255, 0.08);
1373
- border-color: var(--plex-primary);
1374
- color: var(--plex-primary);
1375
- }
1376
-
1377
- .playlist-add-btn .material-icons {
1378
- font-size: 20px;
1379
- }
1380
-
1381
- /* Playlist Stats */
1382
- .playlist-stats {
1383
- display: flex;
1384
- align-items: center;
1385
- justify-content: space-between;
1386
- padding: 12px 16px;
1387
- background: rgba(0, 0, 0, 0.3);
1388
- border-top: 1px solid var(--plex-border);
1389
- font-size: 12px;
1390
- color: var(--plex-text-secondary);
1391
- }
1392
-
1393
- /* Queue Next Indicator */
1394
- .playlist-item-queue-next {
1395
- position: absolute;
1396
- top: 4px;
1397
- left: 4px;
1398
- padding: 2px 6px;
1399
- background: var(--plex-primary);
1400
- border-radius: 3px;
1401
- font-size: 9px;
1402
- font-weight: 700;
1403
- color: #000;
1404
- text-transform: uppercase;
1405
- }
1406
-
1407
- /* Responsive Playlist */
1408
- @media (max-width: 768px) {
1409
- .playlist-panel {
1410
- width: 100%;
1411
- max-width: 100%;
1412
- }
1413
-
1414
- .playlist-item-thumbnail {
1415
- width: 80px;
1416
- height: 45px;
1417
- }
1418
-
1419
- .playlist-item-title {
1420
- font-size: 13px;
1421
- }
1422
-
1423
- .playlist-item-actions {
1424
- opacity: 1;
1425
- }
1426
- }
1427
-
1428
- @media (max-width: 480px) {
1429
- .playlist-header {
1430
- padding: 12px 16px;
1431
- }
1432
-
1433
- .playlist-content {
1434
- padding: 8px;
1435
- }
1436
-
1437
- .playlist-item {
1438
- padding: 8px;
1439
- gap: 10px;
1440
- }
1441
-
1442
- .playlist-item-thumbnail {
1443
- width: 70px;
1444
- height: 40px;
1445
- }
1446
-
1447
- .playlist-item-drag-handle {
1448
- display: none;
1449
- }
1450
- }
1451
-
1452
- /* Drag and Drop States */
1453
- .playlist-content.drag-over {
1454
- background: rgba(229, 160, 13, 0.05);
1455
- }
1456
-
1457
- .playlist-item.drop-target-above::before {
1458
- content: '';
1459
- position: absolute;
1460
- top: -4px;
1461
- left: 0;
1462
- right: 0;
1463
- height: 2px;
1464
- background: var(--plex-primary);
1465
- border-radius: 1px;
1466
- }
1467
-
1468
- .playlist-item.drop-target-below::after {
1469
- content: '';
1470
- position: absolute;
1471
- bottom: -4px;
1472
- left: 0;
1473
- right: 0;
1474
- height: 2px;
1475
- background: var(--plex-primary);
1476
- border-radius: 1px;
1477
- }
1478
-
1479
- /* =====================================================
1480
- PLEX Video Player - Settings Styles (NPM Package)
1481
- ===================================================== */
1482
-
1483
- /* Settings Panel */
1484
- .plex-settings-panel {
1485
- position: absolute;
1486
- bottom: 80px;
1487
- right: 16px;
1488
- width: 280px;
1489
- max-height: 400px;
1490
- background: var(--plex-bg-dark);
1491
- border: 1px solid var(--plex-border);
1492
- border-radius: var(--plex-radius-lg);
1493
- box-shadow: var(--plex-shadow);
1494
- z-index: var(--plex-z-panel);
1495
- overflow: hidden;
1496
- opacity: 0;
1497
- visibility: hidden;
1498
- transform: scale(0.95) translateY(10px);
1499
- transform-origin: bottom right;
1500
- transition: all var(--plex-transition-fast);
1501
- }
1502
-
1503
- .plex-settings-panel.plex-settings-open {
1504
- opacity: 1;
1505
- visibility: visible;
1506
- transform: scale(1) translateY(0);
1507
- }
1508
-
1509
- /* Settings Header */
1510
- .plex-settings-header {
1511
- display: flex;
1512
- align-items: center;
1513
- justify-content: space-between;
1514
- padding: 12px 16px;
1515
- background: rgba(255, 255, 255, 0.03);
1516
- border-bottom: 1px solid var(--plex-border);
1517
- }
1518
-
1519
- .plex-settings-title {
1520
- font-size: 15px;
1521
- font-weight: 600;
1522
- color: var(--plex-text-primary);
1523
- }
1524
-
1525
- .plex-settings-close {
1526
- display: flex;
1527
- align-items: center;
1528
- justify-content: center;
1529
- width: 28px;
1530
- height: 28px;
1531
- padding: 0;
1532
- background: transparent;
1533
- border: none;
1534
- border-radius: var(--plex-radius-sm);
1535
- cursor: pointer;
1536
- color: var(--plex-text-secondary);
1537
- transition: all var(--plex-transition-fast);
1538
- }
1539
-
1540
- .plex-settings-close:hover {
1541
- background: rgba(255, 255, 255, 0.1);
1542
- color: var(--plex-text-primary);
1543
- }
1544
-
1545
- .plex-settings-close svg {
1546
- width: 18px;
1547
- height: 18px;
1548
- fill: currentColor;
1549
- }
1550
-
1551
- /* Settings Content */
1552
- .plex-settings-content {
1553
- padding: 8px 0;
1554
- }
1555
-
1556
- /* Settings Item */
1557
- .plex-settings-item {
1558
- display: flex;
1559
- align-items: center;
1560
- justify-content: space-between;
1561
- padding: 12px 16px;
1562
- cursor: pointer;
1563
- transition: background var(--plex-transition-fast);
1564
- }
1565
-
1566
- .plex-settings-item:hover {
1567
- background: rgba(255, 255, 255, 0.05);
1568
- }
1569
-
1570
- .plex-settings-label {
1571
- font-size: 14px;
1572
- color: var(--plex-text-primary);
1573
- }
1574
-
1575
- .plex-settings-value {
1576
- font-size: 13px;
1577
- color: var(--plex-text-secondary);
1578
- }
1579
-
1580
- /* Settings Submenu */
1581
- .plex-settings-submenu {
1582
- padding: 8px 0;
1583
- }
1584
-
1585
- .plex-settings-back {
1586
- display: flex;
1587
- align-items: center;
1588
- gap: 8px;
1589
- padding: 12px 16px;
1590
- font-size: 14px;
1591
- font-weight: 600;
1592
- color: var(--plex-text-primary);
1593
- cursor: pointer;
1594
- border-bottom: 1px solid var(--plex-border);
1595
- transition: background var(--plex-transition-fast);
1596
- }
1597
-
1598
- .plex-settings-back:hover {
1599
- background: rgba(255, 255, 255, 0.05);
1600
- }
1601
-
1602
- .plex-settings-back svg {
1603
- width: 18px;
1604
- height: 18px;
1605
- fill: currentColor;
1606
- }
1607
-
1608
- /* Speed Options */
1609
- .plex-speed-options {
1610
- display: flex;
1611
- flex-direction: column;
1612
- padding: 8px 0;
1613
- }
1614
-
1615
- .plex-speed-option {
1616
- display: flex;
1617
- align-items: center;
1618
- justify-content: center;
1619
- padding: 10px 16px;
1620
- background: transparent;
1621
- border: none;
1622
- font-size: 14px;
1623
- color: var(--plex-text-primary);
1624
- cursor: pointer;
1625
- transition: all var(--plex-transition-fast);
1626
- }
1627
-
1628
- .plex-speed-option:hover {
1629
- background: rgba(255, 255, 255, 0.05);
1630
- }
1631
-
1632
- .plex-speed-option.active {
1633
- color: var(--plex-primary);
1634
- font-weight: 600;
1635
- }
1636
-
1637
- .plex-speed-option.active::before {
1638
- content: '✓';
1639
- margin-right: 8px;
1640
- }
1641
-
1642
- /* Responsive */
1643
- @media (max-width: 480px) {
1644
- .plex-settings-panel {
1645
- width: calc(100% - 32px);
1646
- left: 16px;
1647
- right: 16px;
1648
- }
1649
- }
1650
-
1651
- /*# sourceMappingURL=plex-player.css.map */