@karnstack/kino 0.1.0

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.
@@ -0,0 +1,969 @@
1
+ .kino {
2
+ /* theme tokens (overridable via inline style or a theme prop) */
3
+ --kino-accent: oklch(50.8% 0.118 165.612);
4
+ --kino-radius: 12px;
5
+ --kino-surface: color-mix(in oklab, black 55%, transparent);
6
+ --kino-surface-strong: color-mix(in oklab, black 70%, transparent);
7
+ --kino-border: color-mix(in oklab, white 14%, transparent);
8
+ --kino-text: oklch(98% 0 0);
9
+ --kino-text-dim: color-mix(in oklab, white 65%, transparent);
10
+ --kino-blur: 18px;
11
+ --kino-shadow: 0 8px 40px rgba(0, 0, 0, 0.45);
12
+ --kino-ease: cubic-bezier(0.22, 1, 0.36, 1);
13
+ --kino-mono:
14
+ ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono",
15
+ monospace;
16
+
17
+ position: relative;
18
+ width: 100%;
19
+ height: 100%;
20
+ color: var(--kino-text);
21
+ font-family: ui-sans-serif, system-ui, sans-serif;
22
+ background: black;
23
+ overflow: hidden;
24
+ /* container queries so captions/flash scale with the player, not the page */
25
+ container-type: inline-size;
26
+ }
27
+ .kino * {
28
+ box-sizing: border-box;
29
+ }
30
+ .kino mux-video,
31
+ .kino video {
32
+ position: absolute;
33
+ inset: 0;
34
+ width: 100%;
35
+ height: 100%;
36
+ }
37
+ .kino .kino-video-host {
38
+ position: absolute;
39
+ inset: 0;
40
+ z-index: 0;
41
+ }
42
+ .kino .kino-overlay {
43
+ position: absolute;
44
+ inset: 0;
45
+ pointer-events: none;
46
+ }
47
+ .kino .kino-overlay > * {
48
+ pointer-events: auto;
49
+ }
50
+ .kino .kino-glass {
51
+ background: var(--kino-surface);
52
+ backdrop-filter: blur(var(--kino-blur));
53
+ -webkit-backdrop-filter: blur(var(--kino-blur));
54
+ border: 1px solid var(--kino-border);
55
+ border-radius: var(--kino-radius);
56
+ box-shadow: var(--kino-shadow);
57
+ }
58
+ .kino .kino-scrubber {
59
+ position: relative;
60
+ width: 100%;
61
+ padding: 8px 0;
62
+ touch-action: none;
63
+ cursor: pointer;
64
+ }
65
+ .kino .kino-track {
66
+ position: relative;
67
+ width: 100%;
68
+ height: 4px;
69
+ border-radius: 999px;
70
+ background: color-mix(in oklab, white 18%, transparent);
71
+ transition: height 0.15s var(--kino-ease);
72
+ }
73
+ .kino .kino-scrubber:hover .kino-track {
74
+ height: 6px;
75
+ }
76
+ .kino .kino-buffered {
77
+ position: absolute;
78
+ top: 0;
79
+ height: 100%;
80
+ border-radius: 999px;
81
+ background: color-mix(in oklab, white 25%, transparent);
82
+ pointer-events: none;
83
+ }
84
+ .kino .kino-progress {
85
+ position: absolute;
86
+ top: 0;
87
+ left: 0;
88
+ height: 100%;
89
+ border-radius: 999px;
90
+ background: var(--kino-accent);
91
+ pointer-events: none;
92
+ }
93
+ .kino .kino-thumb {
94
+ position: absolute;
95
+ top: 50%;
96
+ width: 12px;
97
+ height: 12px;
98
+ border-radius: 999px;
99
+ background: var(--kino-text);
100
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
101
+ transform: translate(-50%, -50%);
102
+ opacity: 0;
103
+ transition: opacity 0.15s var(--kino-ease);
104
+ pointer-events: none;
105
+ }
106
+ .kino .kino-scrubber:hover .kino-thumb {
107
+ opacity: 1;
108
+ }
109
+ .kino .kino-preview {
110
+ position: absolute;
111
+ bottom: calc(100% + 4px);
112
+ transform: translateX(-50%) scale(0.72);
113
+ transform-origin: bottom center;
114
+ display: flex;
115
+ flex-direction: column;
116
+ align-items: center;
117
+ gap: 4px;
118
+ padding: 6px;
119
+ pointer-events: none;
120
+ z-index: 2;
121
+ }
122
+ .kino .kino-preview-img {
123
+ border-radius: 6px;
124
+ background-repeat: no-repeat;
125
+ overflow: hidden;
126
+ }
127
+ .kino .kino-preview-time {
128
+ padding: 5px 4px 4px;
129
+ font-family: var(--kino-mono);
130
+ font-size: 13px;
131
+ font-weight: 500;
132
+ font-variant-numeric: tabular-nums;
133
+ color: var(--kino-text);
134
+ }
135
+ /* macOS-clock rolling digits for the scrub preview time */
136
+ .kino .kino-roll {
137
+ display: inline-flex;
138
+ align-items: stretch;
139
+ line-height: 1;
140
+ font-variant-numeric: tabular-nums;
141
+ }
142
+ .kino .kino-roll-digit {
143
+ display: inline-block;
144
+ height: 1em;
145
+ overflow: hidden;
146
+ }
147
+ .kino .kino-roll-col {
148
+ display: flex;
149
+ flex-direction: column;
150
+ transition: transform 0.3s var(--kino-ease);
151
+ will-change: transform;
152
+ }
153
+ .kino .kino-roll-cell {
154
+ display: flex;
155
+ height: 1em;
156
+ align-items: center;
157
+ justify-content: center;
158
+ }
159
+ .kino .kino-roll-sep {
160
+ display: inline-block;
161
+ }
162
+ .kino .kino-idle {
163
+ position: absolute;
164
+ inset: 0;
165
+ z-index: 12;
166
+ display: flex;
167
+ flex-direction: column;
168
+ align-items: center;
169
+ justify-content: center;
170
+ gap: max(16px, 2.2cqw);
171
+ }
172
+ .kino .kino-idle-play {
173
+ display: grid;
174
+ place-items: center;
175
+ width: max(76px, 9cqw);
176
+ height: max(76px, 9cqw);
177
+ padding: 0;
178
+ color: #fff;
179
+ background: rgba(0, 0, 0, 0.34);
180
+ border: none;
181
+ border-radius: 999px;
182
+ backdrop-filter: blur(8px);
183
+ -webkit-backdrop-filter: blur(8px);
184
+ cursor: pointer;
185
+ transition:
186
+ transform 0.2s var(--kino-ease),
187
+ background 0.2s var(--kino-ease);
188
+ }
189
+ .kino .kino-idle-play svg {
190
+ width: max(32px, 3.8cqw);
191
+ height: max(32px, 3.8cqw);
192
+ fill: #fff;
193
+ }
194
+ /* hovering anywhere over the video darkens + grows the play button */
195
+ .kino .kino-idle:hover .kino-idle-play,
196
+ .kino .kino-idle-play:hover {
197
+ transform: scale(1.06);
198
+ background: rgba(0, 0, 0, 0.5);
199
+ }
200
+ /* Floated below the centered play button (absolute, so it doesn't shift the
201
+ play button off-center). Sitting below center is fine — only the play button
202
+ needs to be dead-center. */
203
+ .kino .kino-idle-speeds {
204
+ position: absolute;
205
+ left: 50%;
206
+ top: calc(50% + max(54px, 7cqw));
207
+ display: flex;
208
+ align-items: center;
209
+ gap: max(6px, 0.8cqw);
210
+ padding: max(8px, 1cqw) max(14px, 1.8cqw);
211
+ background: rgba(0, 0, 0, 0.26);
212
+ border: none;
213
+ border-radius: 999px;
214
+ backdrop-filter: blur(10px);
215
+ -webkit-backdrop-filter: blur(10px);
216
+ opacity: 0;
217
+ transform: translate(-50%, 8px);
218
+ transition:
219
+ opacity 0.2s var(--kino-ease),
220
+ transform 0.2s var(--kino-ease);
221
+ }
222
+ .kino .kino-idle:hover .kino-idle-speeds,
223
+ .kino .kino-idle:focus-within .kino-idle-speeds {
224
+ opacity: 1;
225
+ transform: translate(-50%, 0);
226
+ }
227
+ .kino .kino-speed-chip {
228
+ display: inline-flex;
229
+ align-items: center;
230
+ gap: 3px;
231
+ padding: 4px 7px;
232
+ font-size: max(15px, 1.6cqw);
233
+ font-weight: 600;
234
+ font-variant-numeric: tabular-nums;
235
+ color: color-mix(in oklab, white 52%, transparent);
236
+ background: transparent;
237
+ border: none;
238
+ border-radius: 8px;
239
+ cursor: pointer;
240
+ transition:
241
+ color 0.15s var(--kino-ease),
242
+ transform 0.15s var(--kino-ease);
243
+ }
244
+ .kino .kino-speed-chip:hover,
245
+ .kino .kino-speed-chip[data-active="true"] {
246
+ color: #fff;
247
+ }
248
+ .kino .kino-speed-chip:hover {
249
+ transform: scale(1.15);
250
+ }
251
+ /* chips slide in left-to-right each time the pill reveals */
252
+ .kino .kino-idle:hover .kino-speed-chip,
253
+ .kino .kino-idle:focus-within .kino-speed-chip {
254
+ animation: kino-chip-in 0.32s var(--kino-ease) backwards;
255
+ animation-delay: calc(var(--i, 0) * 45ms);
256
+ }
257
+ @keyframes kino-chip-in {
258
+ from {
259
+ opacity: 0;
260
+ transform: translateX(-10px);
261
+ }
262
+ to {
263
+ opacity: 1;
264
+ transform: none;
265
+ }
266
+ }
267
+ .kino .kino-speed-chip[data-max="true"] {
268
+ color: color-mix(in oklab, white 82%, transparent);
269
+ }
270
+ .kino .kino-speed-chip[data-max="true"][data-active="true"] {
271
+ color: #fff;
272
+ }
273
+ .kino .kino-bolt {
274
+ font-size: 0.85em;
275
+ line-height: 1;
276
+ }
277
+ .kino .kino-popover-root {
278
+ position: relative;
279
+ display: inline-flex;
280
+ }
281
+ .kino .kino-ctrl {
282
+ display: inline-flex;
283
+ align-items: center;
284
+ gap: 6px;
285
+ height: 36px;
286
+ padding: 0 10px;
287
+ color: var(--kino-text);
288
+ background: transparent;
289
+ border: none;
290
+ border-radius: 8px;
291
+ cursor: pointer;
292
+ transition: background 0.12s var(--kino-ease);
293
+ }
294
+ .kino .kino-ctrl:hover {
295
+ background: color-mix(in oklab, white 12%, transparent);
296
+ }
297
+ .kino .kino-ctrl svg {
298
+ width: 22px;
299
+ height: 22px;
300
+ }
301
+ .kino .kino-ctrl-label {
302
+ font-size: 13px;
303
+ font-variant-numeric: tabular-nums;
304
+ }
305
+ .kino .kino-speed-label {
306
+ font-size: 15px;
307
+ font-weight: 500;
308
+ }
309
+ .kino .kino-quality-badge {
310
+ display: inline-flex;
311
+ align-items: center;
312
+ justify-content: center;
313
+ padding: 1px 5px;
314
+ font-size: 10px;
315
+ font-weight: 600;
316
+ line-height: 1.3;
317
+ border: 1px solid currentColor;
318
+ border-radius: 3px;
319
+ }
320
+ .kino .kino-tip {
321
+ position: absolute;
322
+ bottom: calc(100% + 8px);
323
+ left: 50%;
324
+ display: inline-flex;
325
+ align-items: center;
326
+ gap: 6px;
327
+ padding: 6px 8px;
328
+ white-space: nowrap;
329
+ font-size: 12px;
330
+ color: var(--kino-text);
331
+ transform: translateX(-50%);
332
+ pointer-events: none;
333
+ opacity: 0;
334
+ transition: opacity 0.12s var(--kino-ease);
335
+ z-index: 20;
336
+ }
337
+ .kino .kino-tip kbd svg {
338
+ display: block;
339
+ width: 15px;
340
+ height: 15px;
341
+ }
342
+ /* edge-aware anchoring so tips near a player edge don't get clipped */
343
+ .kino .kino-tip-start {
344
+ left: 0;
345
+ right: auto;
346
+ transform: none;
347
+ }
348
+ .kino .kino-tip-center {
349
+ left: 50%;
350
+ right: auto;
351
+ transform: translateX(-50%);
352
+ }
353
+ .kino .kino-tip-end {
354
+ left: auto;
355
+ right: 0;
356
+ transform: none;
357
+ }
358
+ /* keycap that taps itself on a loop */
359
+ .kino .kino-key {
360
+ display: inline-flex;
361
+ align-items: center;
362
+ justify-content: center;
363
+ border-radius: 5px;
364
+ color: var(--kino-text);
365
+ background: linear-gradient(
366
+ color-mix(in oklab, white 26%, transparent),
367
+ color-mix(in oklab, white 12%, transparent)
368
+ );
369
+ border: 1px solid color-mix(in oklab, white 30%, transparent);
370
+ box-shadow: 0 2px 0 color-mix(in oklab, black 40%, transparent);
371
+ animation: kino-key-press 1.8s var(--kino-ease) infinite;
372
+ }
373
+ .kino .kino-key-space {
374
+ align-items: flex-end;
375
+ width: 30px;
376
+ height: 16px;
377
+ padding-bottom: 3px;
378
+ }
379
+ .kino .kino-key-space-bar {
380
+ width: 14px;
381
+ height: 2px;
382
+ border-radius: 2px;
383
+ background: var(--kino-text);
384
+ opacity: 0.85;
385
+ }
386
+ .kino .kino-key-arrow {
387
+ width: 18px;
388
+ height: 18px;
389
+ }
390
+ .kino .kino-key-arrow svg {
391
+ display: block;
392
+ width: 12px;
393
+ height: 12px;
394
+ }
395
+ @keyframes kino-key-press {
396
+ 0%,
397
+ 68%,
398
+ 100% {
399
+ transform: translateY(0);
400
+ box-shadow: 0 2px 0 color-mix(in oklab, black 40%, transparent);
401
+ }
402
+ 80% {
403
+ transform: translateY(2px);
404
+ box-shadow: 0 0 0 color-mix(in oklab, black 40%, transparent);
405
+ }
406
+ }
407
+ .kino .kino-popover-root:hover .kino-tip {
408
+ opacity: 1;
409
+ }
410
+ .kino .kino-tip kbd {
411
+ display: inline-flex;
412
+ align-items: center;
413
+ justify-content: center;
414
+ min-width: 20px;
415
+ padding: 1px 6px;
416
+ font-family: inherit;
417
+ font-size: 11px;
418
+ font-weight: 500;
419
+ line-height: 1.5;
420
+ color: var(--kino-text);
421
+ background: color-mix(in oklab, white 22%, transparent);
422
+ border: 1px solid color-mix(in oklab, white 28%, transparent);
423
+ border-radius: 6px;
424
+ box-shadow: 0 1px 0 color-mix(in oklab, black 40%, transparent);
425
+ }
426
+ .kino .kino-menu {
427
+ position: absolute;
428
+ bottom: calc(100% + 6px);
429
+ left: 50%;
430
+ display: flex;
431
+ flex-direction: column;
432
+ gap: 2px;
433
+ min-width: 150px;
434
+ padding: 6px;
435
+ transform: translateX(-50%);
436
+ transform-origin: bottom;
437
+ transition:
438
+ opacity 0.12s,
439
+ transform 0.12s;
440
+ z-index: 20;
441
+ }
442
+ /* invisible bridge so the pointer can travel from button to menu without
443
+ crossing a dead zone */
444
+ .kino .kino-menu::before {
445
+ content: "";
446
+ position: absolute;
447
+ top: 100%;
448
+ left: 0;
449
+ right: 0;
450
+ height: 8px;
451
+ }
452
+ .kino .kino-menu-start {
453
+ left: 0;
454
+ right: auto;
455
+ transform: none;
456
+ }
457
+ .kino .kino-menu-center {
458
+ left: 50%;
459
+ right: auto;
460
+ transform: translateX(-50%);
461
+ }
462
+ .kino .kino-menu-end {
463
+ left: auto;
464
+ right: 0;
465
+ transform: none;
466
+ }
467
+ .kino .kino-menu-item {
468
+ display: flex;
469
+ align-items: center;
470
+ justify-content: space-between;
471
+ padding: 7px 10px;
472
+ font-size: 13px;
473
+ font-variant-numeric: tabular-nums;
474
+ text-align: left;
475
+ color: var(--kino-text);
476
+ background: transparent;
477
+ border: none;
478
+ border-radius: 7px;
479
+ cursor: pointer;
480
+ transition: background 0.12s var(--kino-ease);
481
+ }
482
+ .kino .kino-menu-item:hover {
483
+ background: color-mix(in oklab, white 12%, transparent);
484
+ }
485
+ .kino .kino-menu-item[aria-checked="true"] {
486
+ color: var(--kino-text);
487
+ background: color-mix(in oklab, black 34%, transparent);
488
+ }
489
+ .kino .kino-menu-item[aria-checked="true"]::after {
490
+ content: "✓";
491
+ margin-left: 14px;
492
+ font-size: 13px;
493
+ opacity: 0.85;
494
+ }
495
+ /* quality rows: keyword headline + dim pixel height */
496
+ .kino .kino-menu-q {
497
+ padding: 9px 12px;
498
+ }
499
+ .kino .kino-q-label {
500
+ display: inline-flex;
501
+ align-items: baseline;
502
+ gap: 8px;
503
+ }
504
+ .kino .kino-q-key {
505
+ font-size: 15px;
506
+ font-weight: 600;
507
+ }
508
+ .kino .kino-q-px {
509
+ font-size: 12px;
510
+ color: var(--kino-text-dim);
511
+ }
512
+ .kino .kino-controls {
513
+ position: absolute;
514
+ left: 0;
515
+ right: 0;
516
+ bottom: 0;
517
+ z-index: 10;
518
+ padding: 0 12px 6px;
519
+ background: linear-gradient(
520
+ to top,
521
+ color-mix(in oklab, black 78%, transparent) 0%,
522
+ color-mix(in oklab, black 45%, transparent) 38%,
523
+ transparent 100%
524
+ );
525
+ opacity: 0;
526
+ transform: translateY(8px);
527
+ transition:
528
+ opacity 0.2s var(--kino-ease),
529
+ transform 0.2s var(--kino-ease);
530
+ pointer-events: none;
531
+ }
532
+ .kino .kino-controls.is-visible {
533
+ opacity: 1;
534
+ transform: none;
535
+ pointer-events: auto;
536
+ }
537
+ /* Click-to-toggle layer + center play/pause pulse */
538
+ .kino .kino-gesture {
539
+ position: absolute;
540
+ inset: 0;
541
+ z-index: 1;
542
+ display: grid;
543
+ place-items: center;
544
+ cursor: default;
545
+ }
546
+ .kino .kino-flash {
547
+ display: grid;
548
+ place-items: center;
549
+ width: max(80px, 10cqw);
550
+ height: max(80px, 10cqw);
551
+ color: #fff;
552
+ background: rgba(0, 0, 0, 0.4);
553
+ border-radius: 999px;
554
+ backdrop-filter: blur(6px);
555
+ -webkit-backdrop-filter: blur(6px);
556
+ pointer-events: none;
557
+ animation: kino-flash 0.75s var(--kino-ease) forwards;
558
+ }
559
+ .kino .kino-flash svg {
560
+ width: max(32px, 4cqw);
561
+ height: max(32px, 4cqw);
562
+ fill: #fff;
563
+ }
564
+ /* zoom-blow-out: scale up while fading away */
565
+ @keyframes kino-flash {
566
+ from {
567
+ opacity: 0.85;
568
+ transform: scale(0.6);
569
+ }
570
+ to {
571
+ opacity: 0;
572
+ transform: scale(1.3);
573
+ }
574
+ }
575
+ /* Custom caption box */
576
+ .kino .kino-captions {
577
+ position: absolute;
578
+ inset: 0;
579
+ z-index: 2;
580
+ display: flex;
581
+ flex-wrap: wrap;
582
+ align-content: flex-end;
583
+ align-items: center;
584
+ justify-content: center;
585
+ padding: 5cqw 4cqw 2.5cqw;
586
+ text-align: center;
587
+ pointer-events: none;
588
+ /* Resting low; lifts clear of the control bar when it appears, settles back
589
+ down as the controls fade. */
590
+ transform: translateY(0);
591
+ transition: transform 0.32s var(--kino-ease);
592
+ }
593
+ .kino .kino-captions.is-raised {
594
+ /* Lift just clears the control bar, which is px-sized (near-constant). Plain
595
+ cqw would balloon in fullscreen where the container is far wider, so clamp
596
+ it to the bar's height. */
597
+ transform: translateY(calc(-1 * clamp(44px, 6cqw, 72px)));
598
+ }
599
+ .kino .kino-caption-text {
600
+ /* Cap line length for readability on wide players; long cues wrap instead of
601
+ stretching edge to edge. Author hard breaks (\n) are honored via pre-line,
602
+ while over-long lines still wrap and unbreakable tokens don't overflow. */
603
+ max-width: min(100%, 80ch);
604
+ padding: 10px 22px;
605
+ font-size: max(13px, 1.7cqw);
606
+ font-weight: 500;
607
+ line-height: 1.32;
608
+ white-space: pre-line;
609
+ overflow-wrap: break-word;
610
+ text-wrap: balance;
611
+ color: #d2d7dd;
612
+ background: rgba(0, 0, 0, 0.42);
613
+ border-radius: 8px;
614
+ backdrop-filter: blur(8px);
615
+ -webkit-backdrop-filter: blur(8px);
616
+ animation: kino-fade-in 0.2s var(--kino-ease);
617
+ }
618
+ @keyframes kino-fade-in {
619
+ from {
620
+ opacity: 0;
621
+ }
622
+ to {
623
+ opacity: 1;
624
+ }
625
+ }
626
+ .kino .kino-controls-row {
627
+ display: flex;
628
+ align-items: center;
629
+ gap: 4px;
630
+ padding: 2px 4px 4px;
631
+ }
632
+ .kino .kino-controls-group {
633
+ display: flex;
634
+ flex: 1;
635
+ align-items: center;
636
+ gap: 2px;
637
+ min-width: 0;
638
+ }
639
+ .kino .kino-controls-group-end {
640
+ justify-content: flex-end;
641
+ }
642
+ .kino .kino-time {
643
+ padding: 0 8px;
644
+ font-family: var(--kino-mono);
645
+ font-size: 13px;
646
+ font-weight: 500;
647
+ font-variant-numeric: tabular-nums;
648
+ white-space: nowrap;
649
+ color: var(--kino-text);
650
+ }
651
+ .kino .kino-time-dur {
652
+ color: var(--kino-text-dim);
653
+ }
654
+ /* Volume: just the icon by default, pill slider expands on hover (Image #4) */
655
+ .kino .kino-volume {
656
+ display: inline-flex;
657
+ align-items: center;
658
+ }
659
+ .kino .kino-volume input[type="range"] {
660
+ -webkit-appearance: none;
661
+ appearance: none;
662
+ width: 0;
663
+ height: 6px;
664
+ margin: 0;
665
+ border-radius: 999px;
666
+ background: color-mix(in oklab, white 28%, transparent);
667
+ opacity: 0;
668
+ cursor: pointer;
669
+ transition:
670
+ width 0.18s var(--kino-ease),
671
+ opacity 0.18s var(--kino-ease),
672
+ margin 0.18s var(--kino-ease);
673
+ }
674
+ .kino .kino-volume:hover input[type="range"],
675
+ .kino .kino-volume:focus-within input[type="range"] {
676
+ width: 80px;
677
+ margin: 0 10px 0 2px;
678
+ opacity: 1;
679
+ }
680
+ .kino .kino-volume input[type="range"]::-webkit-slider-thumb {
681
+ -webkit-appearance: none;
682
+ appearance: none;
683
+ width: 15px;
684
+ height: 15px;
685
+ border-radius: 999px;
686
+ background: #fff;
687
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
688
+ cursor: pointer;
689
+ }
690
+ .kino .kino-volume input[type="range"]::-moz-range-thumb {
691
+ width: 15px;
692
+ height: 15px;
693
+ border: none;
694
+ border-radius: 999px;
695
+ background: #fff;
696
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
697
+ cursor: pointer;
698
+ }
699
+ .kino .kino-volume input[type="range"]::-moz-range-track {
700
+ height: 6px;
701
+ border-radius: 999px;
702
+ background: color-mix(in oklab, white 28%, transparent);
703
+ }
704
+ /* Skip buttons: small dim "5" tucked in the corner of the curved arrow */
705
+ .kino .kino-ctrl-skip {
706
+ position: relative;
707
+ }
708
+ .kino .kino-ctrl-skip-num {
709
+ position: absolute;
710
+ bottom: 5px;
711
+ font-size: 9px;
712
+ font-weight: 700;
713
+ font-variant-numeric: tabular-nums;
714
+ color: var(--kino-text-dim);
715
+ pointer-events: none;
716
+ }
717
+ .kino .kino-ctrl-skip[aria-label*="Back"] .kino-ctrl-skip-num {
718
+ left: 8px;
719
+ }
720
+ .kino .kino-ctrl-skip[aria-label*="Forward"] .kino-ctrl-skip-num {
721
+ right: 8px;
722
+ }
723
+ /* No focus rings on buttons; keep a subtle one on the scrubber slider only */
724
+ .kino button:focus,
725
+ .kino button:focus-visible {
726
+ outline: none;
727
+ }
728
+ .kino .kino-ctrl:active {
729
+ transform: scale(0.95);
730
+ }
731
+ .kino [role="slider"]:focus-visible {
732
+ outline: 2px solid var(--kino-accent);
733
+ outline-offset: 4px;
734
+ }
735
+ /* ============================================================
736
+ Compact / touch UI (narrow players)
737
+ Centered control cluster + bottom seek bar + settings sheet.
738
+ ============================================================ */
739
+ .kino .kino-mcontrols {
740
+ position: absolute;
741
+ inset: 0;
742
+ z-index: 10;
743
+ pointer-events: none;
744
+ opacity: 0;
745
+ transition: opacity 0.2s var(--kino-ease);
746
+ }
747
+ .kino .kino-mcontrols.is-visible {
748
+ opacity: 1;
749
+ }
750
+ /* only capture taps when shown — otherwise let them fall through to the
751
+ gesture layer so a tap reveals the controls */
752
+ .kino .kino-mcontrols.is-visible .kino-mcluster,
753
+ .kino .kino-mcontrols.is-visible .kino-mbottom,
754
+ .kino .kino-mcontrols.is-visible .kino-mtop .kino-mbtn {
755
+ pointer-events: auto;
756
+ }
757
+
758
+ /* top scrim: settings gear, top-right. The strip itself stays click-through so
759
+ a tap on empty space still toggles the controls — only the gear is live. */
760
+ .kino .kino-mtop {
761
+ position: absolute;
762
+ top: 0;
763
+ left: 0;
764
+ right: 0;
765
+ display: flex;
766
+ justify-content: flex-end;
767
+ padding: 8px 10px;
768
+ pointer-events: none;
769
+ background: linear-gradient(
770
+ to bottom,
771
+ color-mix(in oklab, black 52%, transparent) 0%,
772
+ transparent 100%
773
+ );
774
+ }
775
+
776
+ /* flat icon button on a scrim (settings gear, fullscreen) */
777
+ .kino .kino-mbtn {
778
+ display: grid;
779
+ place-items: center;
780
+ width: 40px;
781
+ height: 40px;
782
+ padding: 0;
783
+ color: #fff;
784
+ background: transparent;
785
+ border: none;
786
+ border-radius: 999px;
787
+ cursor: pointer;
788
+ transition: transform 0.15s var(--kino-ease);
789
+ }
790
+ .kino .kino-mbtn svg {
791
+ width: 24px;
792
+ height: 24px;
793
+ }
794
+ .kino .kino-mbtn:active {
795
+ transform: scale(0.9);
796
+ }
797
+
798
+ /* center transport: [back] [play/pause] [forward] */
799
+ .kino .kino-mcluster {
800
+ position: absolute;
801
+ top: 50%;
802
+ left: 50%;
803
+ display: flex;
804
+ align-items: center;
805
+ gap: max(28px, 9cqw);
806
+ transform: translate(-50%, -50%);
807
+ }
808
+ .kino .kino-mtransport {
809
+ position: relative;
810
+ display: grid;
811
+ place-items: center;
812
+ width: 52px;
813
+ height: 52px;
814
+ padding: 0;
815
+ color: #fff;
816
+ background: transparent;
817
+ border: none;
818
+ border-radius: 999px;
819
+ cursor: pointer;
820
+ transition: transform 0.15s var(--kino-ease);
821
+ }
822
+ .kino .kino-mtransport svg {
823
+ width: 30px;
824
+ height: 30px;
825
+ }
826
+ .kino .kino-mtransport:active {
827
+ transform: scale(0.9);
828
+ }
829
+ .kino .kino-mctrl-play {
830
+ display: grid;
831
+ place-items: center;
832
+ width: 66px;
833
+ height: 66px;
834
+ padding: 0;
835
+ color: #fff;
836
+ background: rgba(0, 0, 0, 0.42);
837
+ border: none;
838
+ border-radius: 999px;
839
+ backdrop-filter: blur(8px);
840
+ -webkit-backdrop-filter: blur(8px);
841
+ cursor: pointer;
842
+ transition:
843
+ transform 0.15s var(--kino-ease),
844
+ background 0.15s var(--kino-ease);
845
+ }
846
+ .kino .kino-mctrl-play svg {
847
+ width: 32px;
848
+ height: 32px;
849
+ fill: #fff;
850
+ }
851
+ .kino .kino-mctrl-play:active {
852
+ transform: scale(0.94);
853
+ }
854
+
855
+ /* bottom bar: time + seek + duration + fullscreen */
856
+ .kino .kino-mbottom {
857
+ position: absolute;
858
+ left: 0;
859
+ right: 0;
860
+ bottom: 0;
861
+ display: flex;
862
+ align-items: center;
863
+ gap: 10px;
864
+ padding: 0 6px 6px 14px;
865
+ background: linear-gradient(
866
+ to top,
867
+ color-mix(in oklab, black 72%, transparent) 0%,
868
+ transparent 100%
869
+ );
870
+ }
871
+ .kino .kino-mbottom .kino-scrubber {
872
+ flex: 1;
873
+ min-width: 0;
874
+ }
875
+ .kino .kino-mtime {
876
+ padding: 0;
877
+ font-size: 12px;
878
+ }
879
+ .kino .kino-mbottom .kino-mbtn {
880
+ flex: none;
881
+ width: 36px;
882
+ height: 36px;
883
+ }
884
+ .kino .kino-mbottom .kino-mbtn svg {
885
+ width: 22px;
886
+ height: 22px;
887
+ }
888
+
889
+ /* settings bottom sheet */
890
+ .kino .kino-sheet-backdrop {
891
+ position: absolute;
892
+ inset: 0;
893
+ z-index: 30;
894
+ background: rgba(0, 0, 0, 0.32);
895
+ opacity: 0;
896
+ pointer-events: none;
897
+ transition: opacity 0.22s var(--kino-ease);
898
+ }
899
+ .kino .kino-sheet-backdrop.is-open {
900
+ opacity: 1;
901
+ pointer-events: auto;
902
+ }
903
+ .kino .kino-sheet {
904
+ position: absolute;
905
+ left: 0;
906
+ right: 0;
907
+ bottom: 0;
908
+ max-height: 58%;
909
+ overflow-y: auto;
910
+ padding: 2px 14px 14px;
911
+ border-radius: var(--kino-radius) var(--kino-radius) 0 0;
912
+ transform: translateY(101%);
913
+ transition: transform 0.26s var(--kino-ease);
914
+ }
915
+ .kino .kino-sheet-backdrop.is-open .kino-sheet {
916
+ transform: none;
917
+ }
918
+ .kino .kino-sheet-grip {
919
+ width: 34px;
920
+ height: 4px;
921
+ margin: 8px auto 12px;
922
+ border-radius: 999px;
923
+ background: color-mix(in oklab, white 32%, transparent);
924
+ }
925
+ .kino .kino-sheet-section + .kino-sheet-section {
926
+ margin-top: 12px;
927
+ }
928
+ .kino .kino-sheet-title {
929
+ margin: 0 0 7px;
930
+ font-size: 10px;
931
+ font-weight: 600;
932
+ text-transform: uppercase;
933
+ letter-spacing: 0.05em;
934
+ color: var(--kino-text-dim);
935
+ }
936
+ .kino .kino-sheet-chips {
937
+ display: flex;
938
+ flex-wrap: wrap;
939
+ gap: 6px;
940
+ }
941
+ .kino .kino-sheet-chip {
942
+ padding: 6px 12px;
943
+ font-size: 13px;
944
+ font-weight: 600;
945
+ font-variant-numeric: tabular-nums;
946
+ color: var(--kino-text);
947
+ background: color-mix(in oklab, white 10%, transparent);
948
+ border: 1px solid transparent;
949
+ border-radius: 999px;
950
+ cursor: pointer;
951
+ transition:
952
+ background 0.12s var(--kino-ease),
953
+ color 0.12s var(--kino-ease);
954
+ }
955
+ .kino .kino-sheet-chip:active {
956
+ transform: scale(0.96);
957
+ }
958
+ .kino .kino-sheet-chip[data-active="true"] {
959
+ color: #fff;
960
+ background: var(--kino-accent);
961
+ }
962
+
963
+ @media (prefers-reduced-motion: reduce) {
964
+ .kino *,
965
+ .kino *::before,
966
+ .kino *::after {
967
+ transition-duration: 0.01ms !important;
968
+ }
969
+ }