@videojs/react 10.0.0-beta.7 → 10.0.0-beta.9

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.
Files changed (118) hide show
  1. package/dist/default/media/simple-hls-video/index.js.map +1 -1
  2. package/dist/default/presets/audio/minimal-skin.css +161 -141
  3. package/dist/default/presets/audio/minimal-skin.js +110 -100
  4. package/dist/default/presets/audio/minimal-skin.js.map +1 -1
  5. package/dist/default/presets/audio/minimal-skin.tailwind.js +120 -111
  6. package/dist/default/presets/audio/minimal-skin.tailwind.js.map +1 -1
  7. package/dist/default/presets/audio/skin.css +164 -132
  8. package/dist/default/presets/audio/skin.js +101 -91
  9. package/dist/default/presets/audio/skin.js.map +1 -1
  10. package/dist/default/presets/audio/skin.tailwind.js +111 -102
  11. package/dist/default/presets/audio/skin.tailwind.js.map +1 -1
  12. package/dist/default/presets/{video/error-dialog.js → error-dialog.js} +18 -18
  13. package/dist/default/presets/error-dialog.js.map +1 -0
  14. package/dist/default/presets/video/minimal-skin.css +224 -192
  15. package/dist/default/presets/video/minimal-skin.js +58 -62
  16. package/dist/default/presets/video/minimal-skin.js.map +1 -1
  17. package/dist/default/presets/video/minimal-skin.tailwind.js +70 -78
  18. package/dist/default/presets/video/minimal-skin.tailwind.js.map +1 -1
  19. package/dist/default/presets/video/skin.css +238 -189
  20. package/dist/default/presets/video/skin.js +58 -62
  21. package/dist/default/presets/video/skin.js.map +1 -1
  22. package/dist/default/presets/video/skin.tailwind.js +69 -77
  23. package/dist/default/presets/video/skin.tailwind.js.map +1 -1
  24. package/dist/default/skins/dist/default/default/tailwind/audio.tailwind.js +5 -4
  25. package/dist/default/skins/dist/default/default/tailwind/audio.tailwind.js.map +1 -1
  26. package/dist/default/skins/dist/default/default/tailwind/components/button.js +4 -3
  27. package/dist/default/skins/dist/default/default/tailwind/components/button.js.map +1 -1
  28. package/dist/default/skins/dist/default/default/tailwind/components/error.js +2 -2
  29. package/dist/default/skins/dist/default/default/tailwind/components/error.js.map +1 -1
  30. package/dist/default/skins/dist/default/default/tailwind/components/overlay.js +1 -1
  31. package/dist/default/skins/dist/default/default/tailwind/components/overlay.js.map +1 -1
  32. package/dist/default/skins/dist/default/default/tailwind/components/popup.js +1 -1
  33. package/dist/default/skins/dist/default/default/tailwind/components/popup.js.map +1 -1
  34. package/dist/default/skins/dist/default/default/tailwind/components/seek.js +1 -1
  35. package/dist/default/skins/dist/default/default/tailwind/components/seek.js.map +1 -1
  36. package/dist/default/skins/dist/default/default/tailwind/video.tailwind.js +5 -3
  37. package/dist/default/skins/dist/default/default/tailwind/video.tailwind.js.map +1 -1
  38. package/dist/default/skins/dist/default/minimal/tailwind/audio.tailwind.js +9 -4
  39. package/dist/default/skins/dist/default/minimal/tailwind/audio.tailwind.js.map +1 -1
  40. package/dist/default/skins/dist/default/minimal/tailwind/components/button.js +4 -3
  41. package/dist/default/skins/dist/default/minimal/tailwind/components/button.js.map +1 -1
  42. package/dist/default/skins/dist/default/minimal/tailwind/components/error.js +2 -2
  43. package/dist/default/skins/dist/default/minimal/tailwind/components/error.js.map +1 -1
  44. package/dist/default/skins/dist/default/minimal/tailwind/components/overlay.js +1 -1
  45. package/dist/default/skins/dist/default/minimal/tailwind/components/overlay.js.map +1 -1
  46. package/dist/default/skins/dist/default/minimal/tailwind/components/popup.js +1 -1
  47. package/dist/default/skins/dist/default/minimal/tailwind/components/popup.js.map +1 -1
  48. package/dist/default/skins/dist/default/minimal/tailwind/components/root.js +1 -1
  49. package/dist/default/skins/dist/default/minimal/tailwind/components/root.js.map +1 -1
  50. package/dist/default/skins/dist/default/minimal/tailwind/components/seek.js +1 -1
  51. package/dist/default/skins/dist/default/minimal/tailwind/components/seek.js.map +1 -1
  52. package/dist/default/skins/dist/default/minimal/tailwind/video.tailwind.js +10 -4
  53. package/dist/default/skins/dist/default/minimal/tailwind/video.tailwind.js.map +1 -1
  54. package/dist/dev/media/simple-hls-video/index.d.ts.map +1 -1
  55. package/dist/dev/media/simple-hls-video/index.js.map +1 -1
  56. package/dist/dev/presets/audio/minimal-skin.css +161 -141
  57. package/dist/dev/presets/audio/minimal-skin.d.ts.map +1 -1
  58. package/dist/dev/presets/audio/minimal-skin.js +110 -100
  59. package/dist/dev/presets/audio/minimal-skin.js.map +1 -1
  60. package/dist/dev/presets/audio/minimal-skin.tailwind.d.ts.map +1 -1
  61. package/dist/dev/presets/audio/minimal-skin.tailwind.js +120 -111
  62. package/dist/dev/presets/audio/minimal-skin.tailwind.js.map +1 -1
  63. package/dist/dev/presets/audio/skin.css +164 -132
  64. package/dist/dev/presets/audio/skin.d.ts.map +1 -1
  65. package/dist/dev/presets/audio/skin.js +101 -91
  66. package/dist/dev/presets/audio/skin.js.map +1 -1
  67. package/dist/dev/presets/audio/skin.tailwind.d.ts.map +1 -1
  68. package/dist/dev/presets/audio/skin.tailwind.js +111 -102
  69. package/dist/dev/presets/audio/skin.tailwind.js.map +1 -1
  70. package/dist/dev/presets/{video/error-dialog.js → error-dialog.js} +18 -18
  71. package/dist/dev/presets/error-dialog.js.map +1 -0
  72. package/dist/dev/presets/video/minimal-skin.css +224 -192
  73. package/dist/dev/presets/video/minimal-skin.d.ts.map +1 -1
  74. package/dist/dev/presets/video/minimal-skin.js +58 -62
  75. package/dist/dev/presets/video/minimal-skin.js.map +1 -1
  76. package/dist/dev/presets/video/minimal-skin.tailwind.d.ts.map +1 -1
  77. package/dist/dev/presets/video/minimal-skin.tailwind.js +70 -78
  78. package/dist/dev/presets/video/minimal-skin.tailwind.js.map +1 -1
  79. package/dist/dev/presets/video/skin.css +238 -189
  80. package/dist/dev/presets/video/skin.d.ts.map +1 -1
  81. package/dist/dev/presets/video/skin.js +58 -62
  82. package/dist/dev/presets/video/skin.js.map +1 -1
  83. package/dist/dev/presets/video/skin.tailwind.d.ts.map +1 -1
  84. package/dist/dev/presets/video/skin.tailwind.js +69 -77
  85. package/dist/dev/presets/video/skin.tailwind.js.map +1 -1
  86. package/dist/dev/skins/dist/default/default/tailwind/audio.tailwind.js +5 -4
  87. package/dist/dev/skins/dist/default/default/tailwind/audio.tailwind.js.map +1 -1
  88. package/dist/dev/skins/dist/default/default/tailwind/components/button.js +4 -3
  89. package/dist/dev/skins/dist/default/default/tailwind/components/button.js.map +1 -1
  90. package/dist/dev/skins/dist/default/default/tailwind/components/error.js +2 -2
  91. package/dist/dev/skins/dist/default/default/tailwind/components/error.js.map +1 -1
  92. package/dist/dev/skins/dist/default/default/tailwind/components/overlay.js +1 -1
  93. package/dist/dev/skins/dist/default/default/tailwind/components/overlay.js.map +1 -1
  94. package/dist/dev/skins/dist/default/default/tailwind/components/popup.js +1 -1
  95. package/dist/dev/skins/dist/default/default/tailwind/components/popup.js.map +1 -1
  96. package/dist/dev/skins/dist/default/default/tailwind/components/seek.js +1 -1
  97. package/dist/dev/skins/dist/default/default/tailwind/components/seek.js.map +1 -1
  98. package/dist/dev/skins/dist/default/default/tailwind/video.tailwind.js +5 -3
  99. package/dist/dev/skins/dist/default/default/tailwind/video.tailwind.js.map +1 -1
  100. package/dist/dev/skins/dist/default/minimal/tailwind/audio.tailwind.js +9 -4
  101. package/dist/dev/skins/dist/default/minimal/tailwind/audio.tailwind.js.map +1 -1
  102. package/dist/dev/skins/dist/default/minimal/tailwind/components/button.js +4 -3
  103. package/dist/dev/skins/dist/default/minimal/tailwind/components/button.js.map +1 -1
  104. package/dist/dev/skins/dist/default/minimal/tailwind/components/error.js +2 -2
  105. package/dist/dev/skins/dist/default/minimal/tailwind/components/error.js.map +1 -1
  106. package/dist/dev/skins/dist/default/minimal/tailwind/components/overlay.js +1 -1
  107. package/dist/dev/skins/dist/default/minimal/tailwind/components/overlay.js.map +1 -1
  108. package/dist/dev/skins/dist/default/minimal/tailwind/components/popup.js +1 -1
  109. package/dist/dev/skins/dist/default/minimal/tailwind/components/popup.js.map +1 -1
  110. package/dist/dev/skins/dist/default/minimal/tailwind/components/root.js +1 -1
  111. package/dist/dev/skins/dist/default/minimal/tailwind/components/root.js.map +1 -1
  112. package/dist/dev/skins/dist/default/minimal/tailwind/components/seek.js +1 -1
  113. package/dist/dev/skins/dist/default/minimal/tailwind/components/seek.js.map +1 -1
  114. package/dist/dev/skins/dist/default/minimal/tailwind/video.tailwind.js +10 -4
  115. package/dist/dev/skins/dist/default/minimal/tailwind/video.tailwind.js.map +1 -1
  116. package/package.json +7 -7
  117. package/dist/default/presets/video/error-dialog.js.map +0 -1
  118. package/dist/dev/presets/video/error-dialog.js.map +0 -1
@@ -1,103 +1,3 @@
1
- /* ==========================================================================
2
- Icon State Visibility for Video Skins
3
-
4
- Data-attribute-driven visibility rules for multi-state icon buttons.
5
- Uses :is() with both element selectors (for HTML custom element wrappers)
6
- and class selectors (for React rendered SVG elements).
7
- ========================================================================== */
8
-
9
- /* --- All icons hidden by default --- */
10
-
11
- .media-button--play .media-icon--restart,
12
- .media-button--play .media-icon--play,
13
- .media-button--play .media-icon--pause,
14
- .media-button--mute .media-icon--volume-off,
15
- .media-button--mute .media-icon--volume-low,
16
- .media-button--mute .media-icon--volume-high,
17
- .media-button--fullscreen .media-icon--fullscreen-enter,
18
- .media-button--fullscreen .media-icon--fullscreen-exit,
19
- .media-button--pip .media-icon--pip-enter,
20
- .media-button--pip .media-icon--pip-exit,
21
- .media-button--captions .media-icon--captions-off,
22
- .media-button--captions .media-icon--captions-on {
23
- display: none;
24
- opacity: 0;
25
- }
26
-
27
- /* --- Active icon per state --- */
28
-
29
- /* Play: ended → restart */
30
- .media-button--play[data-ended] .media-icon--restart,
31
- /* Play: paused (not ended) → play */
32
- .media-button--play:not([data-ended])[data-paused] .media-icon--play,
33
- /* Play: playing (not paused, not ended) → pause */
34
- .media-button--play:not([data-paused]):not([data-ended]) .media-icon--pause,
35
- /* Mute: muted → volume off */
36
- .media-button--mute[data-muted] .media-icon--volume-off,
37
- /* Mute: volume low (not muted) → volume low */
38
- .media-button--mute:not([data-muted])[data-volume-level="low"] .media-icon--volume-low,
39
- /* Mute: volume high (not muted, not low) → volume high */
40
- .media-button--mute:not([data-muted]):not([data-volume-level="low"]) .media-icon--volume-high,
41
- /* Fullscreen: not fullscreen → enter */
42
- .media-button--fullscreen:not([data-fullscreen]) .media-icon--fullscreen-enter,
43
- /* Fullscreen: fullscreen → exit */
44
- .media-button--fullscreen[data-fullscreen] .media-icon--fullscreen-exit,
45
- /* Picture-in-Picture: not active → enter */
46
- .media-button--pip:not([data-pip]) .media-icon--pip-enter,
47
- /* Picture-in-Picture: active → exit */
48
- .media-button--pip[data-pip] .media-icon--pip-exit,
49
- /* Captions: not active → captions off */
50
- .media-button--captions:not([data-active]) .media-icon--captions-off,
51
- /* Captions: active → captions on */
52
- .media-button--captions[data-active] .media-icon--captions-on {
53
- display: block;
54
- opacity: 1;
55
- }
56
-
57
- /* ==========================================================================
58
- Tooltip Label State Visibility for Video Skins
59
-
60
- Data-attribute-driven visibility rules for multi-state tooltip labels.
61
- Uses adjacent sibling selectors to match button state → tooltip content.
62
- ========================================================================== */
63
-
64
- /* --- All multi-state labels hidden by default --- */
65
-
66
- .media-tooltip-label {
67
- display: none;
68
- }
69
-
70
- /* --- Active label per state --- */
71
-
72
- /* Play: ended → replay */
73
- .media-button--play[data-ended] + .media-tooltip .media-tooltip-label--replay,
74
- /* Play: paused (not ended) → play */
75
- .media-button--play:not([data-ended])[data-paused] + .media-tooltip
76
- .media-tooltip-label--play,
77
- /* Play: playing (not paused, not ended) → pause */
78
- .media-button--play:not([data-paused]):not([data-ended]) + .media-tooltip
79
- .media-tooltip-label--pause,
80
- /* Fullscreen: not fullscreen → enter */
81
- .media-button--fullscreen:not([data-fullscreen]) + .media-tooltip
82
- .media-tooltip-label--enter-fullscreen,
83
- /* Fullscreen: fullscreen → exit */
84
- .media-button--fullscreen[data-fullscreen] + .media-tooltip
85
- .media-tooltip-label--exit-fullscreen,
86
- /* Captions: not active → enable */
87
- .media-button--captions:not([data-active]) + .media-tooltip
88
- .media-tooltip-label--enable-captions,
89
- /* Captions: active → disable */
90
- .media-button--captions[data-active] + .media-tooltip
91
- .media-tooltip-label--disable-captions,
92
- /* PiP: not in pip → enter */
93
- .media-button--pip:not([data-pip]) + .media-tooltip
94
- .media-tooltip-label--enter-pip,
95
- /* PiP: in pip → exit */
96
- .media-button--pip[data-pip] + .media-tooltip
97
- .media-tooltip-label--exit-pip {
98
- display: block;
99
- }
100
-
101
1
  /* ==========================================================================
102
2
  Reset
103
3
  ========================================================================== */
@@ -145,6 +45,8 @@
145
45
  letter-spacing: normal;
146
46
  -webkit-font-smoothing: auto;
147
47
  -moz-osx-font-smoothing: auto;
48
+
49
+ --media-controls-radius: var(--media-border-radius, 1rem);
148
50
  }
149
51
 
150
52
  /* ==========================================================================
@@ -183,27 +85,20 @@
183
85
  backdrop-filter: blur(0) saturate(1.5);
184
86
  opacity: 0;
185
87
  pointer-events: none;
88
+ transition-property: opacity, backdrop-filter;
89
+ transition-duration: var(--media-controls-transition-duration);
90
+ transition-delay: var(--media-controls-transition-delay);
91
+ transition-timing-function: ease-out;
92
+ }
186
93
 
187
- @media (pointer: fine) {
188
- transition-property: opacity, backdrop-filter;
189
- transition-duration: 500ms;
190
- transition-delay: 500ms;
191
- transition-timing-function: ease-out;
192
-
193
- @media (prefers-reduced-motion: reduce) {
194
- transition-duration: 100ms;
195
- }
196
- }
94
+ .media-minimal-skin .media-error ~ .media-overlay {
95
+ transition-duration: var(--media-error-dialog-transition-duration);
96
+ transition-delay: var(--media-error-dialog-transition-delay);
197
97
  }
198
98
 
199
99
  .media-minimal-skin .media-controls[data-visible] ~ .media-overlay,
200
100
  .media-minimal-skin .media-error[data-open] ~ .media-overlay {
201
101
  opacity: 1;
202
-
203
- @media (pointer: fine) {
204
- transition-duration: 150ms;
205
- transition-delay: 0ms;
206
- }
207
102
  }
208
103
 
209
104
  .media-minimal-skin .media-error[data-open] ~ .media-overlay {
@@ -232,61 +127,6 @@
232
127
  Error Dialog
233
128
  ========================================================================== */
234
129
 
235
- .media-minimal-skin .media-error {
236
- position: absolute;
237
- inset: 0;
238
- z-index: 20;
239
- display: flex;
240
- align-items: center;
241
- justify-content: center;
242
- pointer-events: none;
243
- }
244
-
245
- .media-minimal-skin .media-error__dialog {
246
- display: flex;
247
- flex-direction: column;
248
- gap: 0.75rem;
249
- max-width: 16rem;
250
- padding: 1rem;
251
- color: oklch(1 0 0);
252
- font-size: 0.875rem;
253
- text-shadow: 0 1px 0 oklch(0 0 0 / 0.5);
254
- transition-property: opacity, scale;
255
- transition-duration: 500ms;
256
- transition-delay: 100ms;
257
- transition-timing-function: linear(
258
- 0,
259
- 0.034 1.5%,
260
- 0.763 9.7%,
261
- 1.066 13.9%,
262
- 1.198 19.9%,
263
- 1.184 21.8%,
264
- 0.963 37.5%,
265
- 0.997 50.9%,
266
- 1
267
- );
268
-
269
- /* Simple, fast transition for reduced motion users */
270
- @media (prefers-reduced-motion: reduce) {
271
- transition-duration: 100ms;
272
- transition-delay: 0ms;
273
- transition-timing-function: ease-out;
274
- }
275
- }
276
-
277
- .media-minimal-skin .media-error[data-starting-style] .media-error__dialog,
278
- .media-minimal-skin .media-error[data-ending-style] .media-error__dialog {
279
- opacity: 0;
280
- scale: 0.5;
281
- }
282
-
283
- .media-minimal-skin .media-error__content {
284
- display: flex;
285
- flex-direction: column;
286
- gap: 0.5rem;
287
- padding: 0.375rem 0;
288
- }
289
-
290
130
  .media-minimal-skin .media-error__title {
291
131
  font-weight: 600;
292
132
  line-height: 1.25;
@@ -306,6 +146,10 @@
306
146
  }
307
147
  }
308
148
 
149
+ .media-minimal-skin .media-error[data-open] ~ .media-controls * {
150
+ visibility: hidden;
151
+ }
152
+
309
153
  /* ==========================================================================
310
154
  Controls
311
155
  ========================================================================== */
@@ -384,16 +228,11 @@
384
228
  justify-content: center;
385
229
  flex-shrink: 0;
386
230
  padding: 0.5rem 1rem;
387
- background: oklch(1 0 0);
388
231
  border: none;
389
- border-radius: 0.5rem;
232
+ border-radius: calc(var(--media-controls-radius) - var(--media-controls-padding));
390
233
  outline: 2px solid transparent;
391
234
  outline-offset: -2px;
392
- color: oklch(0 0 0);
393
- font-weight: 500;
394
- text-align: center;
395
- text-shadow: inherit;
396
- transition-property: background-color, color, outline-offset, scale;
235
+ transition-property: background-color, outline-offset, scale;
397
236
  transition-duration: 150ms;
398
237
  transition-timing-function: ease-out;
399
238
  cursor: pointer;
@@ -405,6 +244,10 @@
405
244
  outline-offset: 2px;
406
245
  }
407
246
 
247
+ &:active {
248
+ scale: 0.98;
249
+ }
250
+
408
251
  &[disabled] {
409
252
  opacity: 0.5;
410
253
  filter: grayscale(1);
@@ -416,21 +259,42 @@
416
259
  }
417
260
  }
418
261
 
419
- /* Icon button variant */
420
- .media-minimal-skin .media-button--icon {
421
- display: grid;
422
- width: 2.375rem;
423
- padding: 0;
424
- aspect-ratio: 1;
262
+ /* biome-ignore lint/correctness/noUnknownProperty: corner-shape is an emerging CSS spec */
263
+ @supports (corner-shape: squircle) {
264
+ .media-minimal-skin .media-button {
265
+ border-radius: var(--media-controls-radius);
266
+ /* biome-ignore lint/correctness/noUnknownProperty: corner-shape is an emerging CSS spec */
267
+ corner-shape: squircle;
268
+ }
269
+ }
270
+
271
+ /* Primary button variant */
272
+ .media-minimal-skin .media-button--primary {
273
+ background: oklch(1 0 0);
274
+ color: oklch(0 0 0);
275
+ font-weight: 500;
276
+ text-align: center;
277
+ }
278
+
279
+ /* Subtle button variant */
280
+ .media-minimal-skin .media-button--subtle {
425
281
  background: transparent;
426
282
  color: inherit;
283
+ text-shadow: inherit;
427
284
 
428
285
  &:hover,
429
286
  &:focus-visible,
430
287
  &[aria-expanded="true"] {
431
- color: oklch(from currentColor l c h / 0.8);
432
- text-decoration: none;
288
+ background: oklch(from currentColor l c h / 0.1);
433
289
  }
290
+ }
291
+
292
+ /* Icon button variant */
293
+ .media-minimal-skin .media-button--icon {
294
+ display: grid;
295
+ width: 2.375rem;
296
+ padding: 0;
297
+ aspect-ratio: 1;
434
298
 
435
299
  &:active {
436
300
  scale: 0.9;
@@ -447,7 +311,7 @@
447
311
  position: absolute;
448
312
  right: -1px;
449
313
  bottom: -3px;
450
- font-size: 0.75em;
314
+ font-size: 10px;
451
315
  font-weight: 480;
452
316
  font-variant-numeric: tabular-nums;
453
317
  }
@@ -733,7 +597,8 @@
733
597
  color: inherit;
734
598
  overflow: visible;
735
599
  transition-property: scale, opacity, filter;
736
- transition-duration: 150ms;
600
+ transition-duration: var(--media-popup-transition-duration);
601
+ transition-timing-function: var(--media-popup-transition-timing-function);
737
602
 
738
603
  &[data-starting-style],
739
604
  &[data-ending-style] {
@@ -859,6 +724,106 @@
859
724
  font-family: inherit;
860
725
  }
861
726
 
727
+ /* ==========================================================================
728
+ Icon State Visibility for Video Skins
729
+
730
+ Data-attribute-driven visibility rules for multi-state icon buttons.
731
+ Uses :is() with both element selectors (for HTML custom element wrappers)
732
+ and class selectors (for React rendered SVG elements).
733
+ ========================================================================== */
734
+
735
+ /* --- All icons hidden by default --- */
736
+
737
+ .media-button--play .media-icon--restart,
738
+ .media-button--play .media-icon--play,
739
+ .media-button--play .media-icon--pause,
740
+ .media-button--mute .media-icon--volume-off,
741
+ .media-button--mute .media-icon--volume-low,
742
+ .media-button--mute .media-icon--volume-high,
743
+ .media-button--fullscreen .media-icon--fullscreen-enter,
744
+ .media-button--fullscreen .media-icon--fullscreen-exit,
745
+ .media-button--pip .media-icon--pip-enter,
746
+ .media-button--pip .media-icon--pip-exit,
747
+ .media-button--captions .media-icon--captions-off,
748
+ .media-button--captions .media-icon--captions-on {
749
+ display: none;
750
+ opacity: 0;
751
+ }
752
+
753
+ /* --- Active icon per state --- */
754
+
755
+ /* Play: ended → restart */
756
+ .media-button--play[data-ended] .media-icon--restart,
757
+ /* Play: paused (not ended) → play */
758
+ .media-button--play:not([data-ended])[data-paused] .media-icon--play,
759
+ /* Play: playing (not paused, not ended) → pause */
760
+ .media-button--play:not([data-paused]):not([data-ended]) .media-icon--pause,
761
+ /* Mute: muted → volume off */
762
+ .media-button--mute[data-muted] .media-icon--volume-off,
763
+ /* Mute: volume low (not muted) → volume low */
764
+ .media-button--mute:not([data-muted])[data-volume-level="low"] .media-icon--volume-low,
765
+ /* Mute: volume high (not muted, not low) → volume high */
766
+ .media-button--mute:not([data-muted]):not([data-volume-level="low"]) .media-icon--volume-high,
767
+ /* Fullscreen: not fullscreen → enter */
768
+ .media-button--fullscreen:not([data-fullscreen]) .media-icon--fullscreen-enter,
769
+ /* Fullscreen: fullscreen → exit */
770
+ .media-button--fullscreen[data-fullscreen] .media-icon--fullscreen-exit,
771
+ /* Picture-in-Picture: not active → enter */
772
+ .media-button--pip:not([data-pip]) .media-icon--pip-enter,
773
+ /* Picture-in-Picture: active → exit */
774
+ .media-button--pip[data-pip] .media-icon--pip-exit,
775
+ /* Captions: not active → captions off */
776
+ .media-button--captions:not([data-active]) .media-icon--captions-off,
777
+ /* Captions: active → captions on */
778
+ .media-button--captions[data-active] .media-icon--captions-on {
779
+ display: block;
780
+ opacity: 1;
781
+ }
782
+
783
+ /* ==========================================================================
784
+ Tooltip Label State Visibility for Video Skins
785
+
786
+ Data-attribute-driven visibility rules for multi-state tooltip labels.
787
+ Uses adjacent sibling selectors to match button state → tooltip content.
788
+ ========================================================================== */
789
+
790
+ /* --- All multi-state labels hidden by default --- */
791
+
792
+ .media-tooltip-label {
793
+ display: none;
794
+ }
795
+
796
+ /* --- Active label per state --- */
797
+
798
+ /* Play: ended → replay */
799
+ .media-button--play[data-ended] + .media-tooltip .media-tooltip-label--replay,
800
+ /* Play: paused (not ended) → play */
801
+ .media-button--play:not([data-ended])[data-paused] + .media-tooltip
802
+ .media-tooltip-label--play,
803
+ /* Play: playing (not paused, not ended) → pause */
804
+ .media-button--play:not([data-paused]):not([data-ended]) + .media-tooltip
805
+ .media-tooltip-label--pause,
806
+ /* Fullscreen: not fullscreen → enter */
807
+ .media-button--fullscreen:not([data-fullscreen]) + .media-tooltip
808
+ .media-tooltip-label--enter-fullscreen,
809
+ /* Fullscreen: fullscreen → exit */
810
+ .media-button--fullscreen[data-fullscreen] + .media-tooltip
811
+ .media-tooltip-label--exit-fullscreen,
812
+ /* Captions: not active → enable */
813
+ .media-button--captions:not([data-active]) + .media-tooltip
814
+ .media-tooltip-label--enable-captions,
815
+ /* Captions: active → disable */
816
+ .media-button--captions[data-active] + .media-tooltip
817
+ .media-tooltip-label--disable-captions,
818
+ /* PiP: not in pip → enter */
819
+ .media-button--pip:not([data-pip]) + .media-tooltip
820
+ .media-tooltip-label--enter-pip,
821
+ /* PiP: in pip → exit */
822
+ .media-button--pip[data-pip] + .media-tooltip
823
+ .media-tooltip-label--exit-pip {
824
+ display: block;
825
+ }
826
+
862
827
 
863
828
  /* ==========================================================================
864
829
  Root
@@ -869,8 +834,21 @@
869
834
  background: oklch(0 0 0);
870
835
  --media-border-color: oklch(0 0 0 / 0.15);
871
836
  --media-video-border-radius: var(--media-border-radius, 0.75rem);
837
+ --media-controls-padding: 0.375rem;
872
838
  --media-controls-transition-duration: 100ms;
873
839
  --media-controls-transition-delay: 0ms;
840
+ --media-controls-transition-timing-function: ease-out;
841
+ --media-error-dialog-transition-duration: 250ms;
842
+ --media-error-dialog-transition-delay: 100ms;
843
+ --media-error-dialog-transition-timing-function: ease-out;
844
+ --media-popup-transition-duration: 100ms;
845
+ --media-popup-transition-timing-function: ease-out;
846
+
847
+ @media (prefers-reduced-motion: reduce) {
848
+ --media-error-dialog-transition-duration: 50ms;
849
+ --media-error-dialog-transition-delay: 0ms;
850
+ --media-popup-transition-duration: 0ms;
851
+ }
874
852
 
875
853
  @media (prefers-color-scheme: dark) {
876
854
  --media-border-color: oklch(1 0 0 / 0.15);
@@ -886,7 +864,7 @@
886
864
  --media-controls-transition-duration: 150ms;
887
865
  }
888
866
  @media (prefers-reduced-motion: reduce) {
889
- --media-controls-transition-duration: 100ms;
867
+ --media-controls-transition-duration: 50ms;
890
868
  }
891
869
  }
892
870
 
@@ -907,6 +885,60 @@
907
885
  }
908
886
  }
909
887
 
888
+ /* ==========================================================================
889
+ Error Dialog
890
+ ========================================================================== */
891
+
892
+ .media-minimal-skin--video .media-error {
893
+ position: absolute;
894
+ inset: 0;
895
+ z-index: 20;
896
+ display: flex;
897
+ align-items: center;
898
+ justify-content: center;
899
+ pointer-events: none;
900
+ outline: none;
901
+ }
902
+
903
+ .media-minimal-skin--video .media-error__dialog {
904
+ display: flex;
905
+ flex-direction: column;
906
+ gap: 0.75rem;
907
+ max-width: 16rem;
908
+ padding: 1rem;
909
+ color: oklch(1 0 0);
910
+ text-shadow: 0 1px 0 oklch(0 0 0 / 0.5);
911
+ transition-property: opacity, scale;
912
+ transition-duration: var(--media-error-dialog-transition-duration);
913
+ transition-delay: var(--media-error-dialog-transition-delay);
914
+ transition-timing-function: var(--media-error-dialog-transition-timing-function);
915
+ pointer-events: auto;
916
+ }
917
+
918
+ .media-minimal-skin--video .media-error[data-starting-style] .media-error__dialog,
919
+ .media-minimal-skin--video .media-error[data-ending-style] .media-error__dialog {
920
+ opacity: 0;
921
+ scale: 0.5;
922
+ }
923
+ .media-minimal-skin--video .media-error[data-ending-style] .media-error__dialog {
924
+ transition-delay: 0ms;
925
+ }
926
+
927
+ .media-minimal-skin--video .media-error__content {
928
+ display: flex;
929
+ flex-direction: column;
930
+ gap: 0.5rem;
931
+ padding: 0.375rem 0;
932
+ }
933
+
934
+ .media-minimal-skin--video .media-error__title {
935
+ font-size: 1.125rem;
936
+ }
937
+
938
+ .media-minimal-skin--video .media-error[data-open] ~ .media-controls {
939
+ display: none;
940
+ }
941
+
910
942
  /* ==========================================================================
911
943
  Controls (hide/show behavior)
912
944
  ========================================================================== */
@@ -917,11 +949,11 @@
917
949
  inset-inline: 0;
918
950
  z-index: 10;
919
951
  gap: 0.5rem;
920
- padding: 2rem 0.375rem 0.375rem 0.375rem;
952
+ padding: 2rem var(--media-controls-padding) var(--media-controls-padding) var(--media-controls-padding);
921
953
  color: var(--media-color-primary, oklch(1 0 0));
922
954
  transition-duration: var(--media-controls-transition-duration);
923
955
  transition-delay: var(--media-controls-transition-delay);
924
- transition-timing-function: ease-out;
956
+ transition-timing-function: var(--media-controls-transition-timing-function);
925
957
 
926
958
  @media (pointer: fine) {
927
959
  will-change: translate, filter, opacity;
@@ -981,7 +1013,7 @@
981
1013
  Slider preview
982
1014
  ========================================================================== */
983
1015
 
984
- .media-minimal-skin .media-slider__preview {
1016
+ .media-minimal-skin--video .media-slider__preview {
985
1017
  position: absolute;
986
1018
  left: var(--media-slider-pointer);
987
1019
  bottom: calc(100% + 0.5rem);
@@ -1017,7 +1049,7 @@
1017
1049
  max-height: 6rem;
1018
1050
  }
1019
1051
  }
1020
- .media-minimal-skin .media-slider[data-pointing] .media-slider__preview:has([role="img"]:not([data-hidden])) {
1052
+ .media-minimal-skin--video .media-slider[data-pointing] .media-slider__preview:has([role="img"]:not([data-hidden])) {
1021
1053
  opacity: 1;
1022
1054
  scale: 1;
1023
1055
  filter: blur(0);