Skins
Packaged player designs that include both UI components and their styles.
A skin wraps the media component and provides the player’s complete interface. It combines a specific set of UI components with the styles that arrange and present them.
Packaged and ejected skins
When you choose a skin you have two options for how you use it: packaged or ejected. It’s usually easiest to start with a packaged skin and later eject its internal components into your project when you need more customization.
Packaged skins cover common visual changes through documented CSS custom properties. Packaged video skins also let you replace the poster. When you need more than that, eject and change the components and styles directly.
| Packaged | Ejected |
|---|---|
| Single component | Many UI components |
| Documented CSS custom properties | Components and styles you own |
| Future design updates auto-applied by bumping the version | Future design updates manually applied, or intentionally ignored |
Packaged skin
<script type="module">
import '@videojs/html/video/player';
import '@videojs/html/video/skin';
</script>
<video-player>
<video-skin>
<video src="video.mp4"></video>
</video-skin>
</video-player>import { Video, VideoPlayer, VideoSkin } from '@videojs/react/video';
import '@videojs/react/video/skin.css';
export function Player() {
return (
<VideoPlayer>
<VideoSkin>
<Video src="video.mp4" />
</VideoSkin>
</VideoPlayer>
);
}Don’t depend on elements, class names, or undocumented custom properties inside a packaged skin. They may change between releases.
Ejected skin
An ejected skin exposes its UI components and styles as app code that you own. You can add, remove, rearrange, or restyle any part of it.
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/html@10.0.0-beta.32/cdn/video.js"></script>
<link rel="stylesheet" href="./player.css">
<video-player poster="https://image.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/thumbnail.webp">
<media-container class="media-skin media-skin--default media-skin--video">
<video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" playsinline></video>
<media-poster>
<img alt="" decoding="async" />
</media-poster>
<media-buffering-indicator class="media-buffering-indicator">
<media-icon name="spinner" class="media-icon"></media-icon>
</media-buffering-indicator>
<media-error-dialog>
<media-dialog-backdrop class="media-dialog__backdrop"></media-dialog-backdrop>
<media-dialog-popup class="media-dialog__popup media-surface">
<div class="media-dialog__content">
<media-dialog-title class="media-dialog__title"></media-dialog-title>
<media-dialog-description class="media-dialog__description"></media-dialog-description>
</div>
<div class="media-dialog__actions">
<media-dialog-close class="media-button media-button--primary"></media-dialog-close>
</div>
</media-dialog-popup>
</media-error-dialog>
<media-controls>
<media-controls-backdrop class="media-controls__backdrop"></media-controls-backdrop>
<media-controls-content class="media-surface media-controls media-controls--root">
<media-tooltip-group>
<media-controls-group class="media-surface media-controls media-controls--primary">
<div class="media-button-group">
<media-play-button commandfor="play-tooltip" class="media-button media-button--subtle media-button--icon media-button--play">
<media-icon name="restart" class="media-icon media-icon--restart"></media-icon>
<media-icon name="play" class="media-icon media-icon--play"></media-icon>
<media-icon name="pause" class="media-icon media-icon--pause"></media-icon>
</media-play-button>
<media-tooltip id="play-tooltip" side="top" class="media-surface media-tooltip">
<media-tooltip-label></media-tooltip-label>
<media-tooltip-shortcut class="media-tooltip__kbd"></media-tooltip-shortcut>
</media-tooltip>
<media-mute-button commandfor="video-volume-popover" class="media-button media-button--subtle media-button--icon media-button--mute">
<media-icon name="volume-off" class="media-icon media-icon--volume-off"></media-icon>
<media-icon name="volume-low" class="media-icon media-icon--volume-low"></media-icon>
<media-icon name="volume-high" class="media-icon media-icon--volume-high"></media-icon>
</media-mute-button>
<media-popover id="video-volume-popover" open-on-hover delay="200" close-delay="100" side="top" class="media-surface media-popover media-popover--volume">
<media-volume-slider class="media-slider" orientation="vertical" thumb-alignment="edge">
<media-slider-track class="media-slider__track">
<media-slider-fill class="media-slider__fill"></media-slider-fill>
</media-slider-track>
<media-slider-thumb class="media-slider__thumb media-slider__thumb--persistent"></media-slider-thumb>
</media-volume-slider>
</media-popover>
</div>
<div class="media-time-controls">
<media-time type="current" class="media-time"></media-time>
<media-time-slider class="media-slider">
<media-time-slider-chapters class="media-slider__chapters">
<template>
<div class="media-slider__chapter">
<media-slider-track class="media-slider__track media-slider__chapter-track">
<media-slider-buffer class="media-slider__buffer"></media-slider-buffer>
<media-slider-fill class="media-slider__fill"></media-slider-fill>
</media-slider-track>
</div>
</template>
</media-time-slider-chapters>
<media-slider-thumb class="media-slider__thumb"></media-slider-thumb>
<media-slider-preview overflow="visible" class="media-slider__preview">
<div class="media-surface media-thumbnail media-slider__thumbnail">
<media-slider-thumbnail class="media-thumbnail__image"></media-slider-thumbnail>
<media-icon name="spinner" class="media-thumbnail__spinner media-icon"></media-icon>
</div>
<div class="media-slider__value">
<media-time-slider-chapter-title class="media-slider__chapter-title"></media-time-slider-chapter-title>
<media-slider-value type="pointer" class="media-time"></media-slider-value>
</div>
</media-slider-preview>
</media-time-slider>
<media-time toggle type="remaining" class="media-time"></media-time>
</div>
<div class="media-button-group">
<media-captions-button commandfor="captions-tooltip" class="media-button media-button--subtle media-button--icon media-button--captions">
<media-icon name="captions-off" class="media-icon media-icon--captions-off"></media-icon>
<media-icon name="captions-on" class="media-icon media-icon--captions-on"></media-icon>
</media-captions-button>
<media-tooltip id="captions-tooltip" side="top" class="media-surface media-tooltip">
<media-tooltip-label></media-tooltip-label>
<media-tooltip-shortcut class="media-tooltip__kbd"></media-tooltip-shortcut>
</media-tooltip>
<button id="settings-trigger" commandfor="settings-menu" aria-labelledby="settings-label" class="media-button media-button--subtle media-button--icon media-button--settings">
<media-icon name="gear" class="media-icon media-icon--settings"></media-icon>
<media-text token="menu.settings" id="settings-label" class="media-sr-only">Settings</media-text>
</button>
<media-menu id="settings-menu" side="top" align="center" class="media-surface media-popover media-menu media-menu--settings">
<media-menu-content class="media-menu__content">
<media-menu-item commandfor="settings-quality-menu" class="media-menu__item media-menu__item--submenu">
<media-icon name="switches" class="media-icon"></media-icon>
<media-text token="menu.quality">Quality</media-text>
<span class="media-menu__hint">
<bdi data-part="hint" dir="auto" class="media-menu__hint-label"></bdi>
<media-icon name="chevron" class="media-icon media-menu__chevron"></media-icon>
</span>
</media-menu-item>
<media-menu-item commandfor="settings-audio-menu" class="media-menu__item media-menu__item--submenu">
<media-icon name="speech" class="media-icon"></media-icon>
<media-text token="menu.audio">Audio</media-text>
<span class="media-menu__hint">
<bdi data-part="hint" dir="auto" class="media-menu__hint-label"></bdi>
<media-icon name="chevron" class="media-icon media-menu__chevron"></media-icon>
</span>
</media-menu-item>
<media-menu-item commandfor="settings-speed-menu" class="media-menu__item media-menu__item--submenu">
<media-icon name="speed" class="media-icon"></media-icon>
<media-text token="menu.speed">Speed</media-text>
<span class="media-menu__hint">
<bdi data-part="hint" dir="auto" class="media-menu__hint-label"></bdi>
<media-icon name="chevron" class="media-icon media-menu__chevron"></media-icon>
</span>
</media-menu-item>
<media-menu-item commandfor="settings-captions-menu" class="media-menu__item media-menu__item--submenu">
<media-icon name="captions-off" class="media-icon"></media-icon>
<media-text token="menu.captions">Captions</media-text>
<span class="media-menu__hint">
<bdi data-part="hint" dir="auto" class="media-menu__hint-label"></bdi>
<media-icon name="chevron" class="media-icon media-menu__chevron"></media-icon>
</span>
</media-menu-item>
</media-menu-content>
<media-menu-content id="settings-quality-menu" class="media-menu__panel">
<media-menu-item class="media-menu__back">
<media-icon name="chevron" class="media-icon media-menu__chevron media-icon--flipped"></media-icon>
<media-text token="menu.quality">Quality</media-text>
</media-menu-item>
<div class="media-menu__separator"></div>
<media-quality-radio-group class="media-menu__group">
<template>
<media-menu-radio-item class="media-menu__item">
<span>
<bdi data-part="label" dir="auto"></bdi>
<sup data-part="tier" class="media-menu__tier"></sup>
</span>
<span data-part="badge" class="media-badge"></span>
<media-menu-item-indicator force-mount class="media-menu__indicator">
<media-icon name="check" class="media-icon"></media-icon>
</media-menu-item-indicator>
</media-menu-radio-item>
</template>
</media-quality-radio-group>
</media-menu-content>
<media-menu-content id="settings-audio-menu" class="media-menu__panel">
<media-menu-item class="media-menu__back">
<media-icon name="chevron" class="media-icon media-menu__chevron media-icon--flipped"></media-icon>
<media-text token="menu.audio">Audio</media-text>
</media-menu-item>
<div class="media-menu__separator"></div>
<media-audio-track-radio-group class="media-menu__group">
<template>
<media-menu-radio-item class="media-menu__item">
<bdi data-part="label" dir="auto"></bdi>
<media-menu-item-indicator force-mount class="media-menu__indicator">
<media-icon name="check" class="media-icon"></media-icon>
</media-menu-item-indicator>
</media-menu-radio-item>
</template>
</media-audio-track-radio-group>
</media-menu-content>
<media-menu-content id="settings-speed-menu" class="media-menu__panel">
<media-menu-item class="media-menu__back">
<media-icon name="chevron" class="media-icon media-menu__chevron media-icon--flipped"></media-icon>
<media-text token="menu.speed">Speed</media-text>
</media-menu-item>
<div class="media-menu__separator"></div>
<media-playback-rate-radio-group class="media-menu__group">
<template>
<media-menu-radio-item class="media-menu__item">
<bdi data-part="label" dir="auto"></bdi>
<media-menu-item-indicator force-mount class="media-menu__indicator">
<media-icon name="check" class="media-icon"></media-icon>
</media-menu-item-indicator>
</media-menu-radio-item>
</template>
</media-playback-rate-radio-group>
</media-menu-content>
<media-menu-content id="settings-captions-menu" class="media-menu__panel">
<media-menu-item class="media-menu__back">
<media-icon name="chevron" class="media-icon media-menu__chevron media-icon--flipped"></media-icon>
<media-text token="menu.captions">Captions</media-text>
</media-menu-item>
<div class="media-menu__separator"></div>
<media-captions-radio-group class="media-menu__group">
<template>
<media-menu-radio-item class="media-menu__item">
<bdi data-part="label" dir="auto"></bdi>
<media-menu-item-indicator force-mount class="media-menu__indicator">
<media-icon name="check" class="media-icon"></media-icon>
</media-menu-item-indicator>
</media-menu-radio-item>
</template>
</media-captions-radio-group>
</media-menu-content>
</media-menu>
<media-tooltip id="settings-tooltip" trigger="settings-trigger" side="top" class="media-surface media-tooltip">
<media-text token="menu.settings">Settings</media-text>
</media-tooltip>
</div>
</media-controls-group>
<media-controls-group class="media-surface media-controls media-controls--secondary">
<div class="media-button-group">
<media-cast-button commandfor="cast-tooltip" class="media-button media-button--subtle media-button--icon media-button--cast">
<media-icon name="cast-enter" class="media-icon media-icon--cast-enter"></media-icon>
<media-icon name="cast-exit" class="media-icon media-icon--cast-exit"></media-icon>
</media-cast-button>
<media-tooltip id="cast-tooltip" side="top" class="media-surface media-tooltip">
<media-tooltip-label></media-tooltip-label>
<media-tooltip-shortcut class="media-tooltip__kbd"></media-tooltip-shortcut>
</media-tooltip>
<media-airplay-button commandfor="airplay-tooltip" class="media-button media-button--subtle media-button--icon media-button--airplay">
<media-icon name="airplay-enter" class="media-icon media-icon--airplay-enter"></media-icon>
<media-icon name="airplay-exit" class="media-icon media-icon--airplay-exit"></media-icon>
</media-airplay-button>
<media-tooltip id="airplay-tooltip" side="top" class="media-surface media-tooltip">
<media-tooltip-label></media-tooltip-label>
<media-tooltip-shortcut class="media-tooltip__kbd"></media-tooltip-shortcut>
</media-tooltip>
<media-pip-button commandfor="pip-tooltip" class="media-button media-button--subtle media-button--icon media-button--pip">
<media-icon name="pip-enter" class="media-icon media-icon--pip-enter"></media-icon>
<media-icon name="pip-exit" class="media-icon media-icon--pip-exit"></media-icon>
</media-pip-button>
<media-tooltip id="pip-tooltip" side="top" class="media-surface media-tooltip">
<media-tooltip-label></media-tooltip-label>
<media-tooltip-shortcut class="media-tooltip__kbd"></media-tooltip-shortcut>
</media-tooltip>
<media-fullscreen-button commandfor="fullscreen-tooltip" class="media-button media-button--subtle media-button--icon media-button--fullscreen">
<media-icon name="fullscreen-enter" class="media-icon media-icon--fullscreen-enter"></media-icon>
<media-icon name="fullscreen-exit" class="media-icon media-icon--fullscreen-exit"></media-icon>
</media-fullscreen-button>
<media-tooltip id="fullscreen-tooltip" side="top" class="media-surface media-tooltip">
<media-tooltip-label></media-tooltip-label>
<media-tooltip-shortcut class="media-tooltip__kbd"></media-tooltip-shortcut>
</media-tooltip>
</div>
</media-controls-group>
</media-tooltip-group>
</media-controls-content>
</media-controls>
<!-- Hotkeys -->
<media-hotkey keys="Space" action="togglePaused"></media-hotkey>
<media-hotkey keys="k" action="togglePaused"></media-hotkey>
<media-hotkey keys="m" action="toggleMuted"></media-hotkey>
<media-hotkey keys="f" action="toggleFullscreen"></media-hotkey>
<media-hotkey keys="c" action="toggleSubtitles"></media-hotkey>
<media-hotkey keys="i" action="togglePictureInPicture"></media-hotkey>
<media-hotkey keys="ArrowRight" action="seekStep"></media-hotkey>
<media-hotkey keys="ArrowLeft" action="seekStep"></media-hotkey>
<media-hotkey keys="l" action="seekStep"></media-hotkey>
<media-hotkey keys="j" action="seekStep"></media-hotkey>
<media-hotkey keys="ArrowUp" action="volumeStep"></media-hotkey>
<media-hotkey keys="ArrowDown" action="volumeStep"></media-hotkey>
<media-hotkey keys="0-9" action="seekToPercent"></media-hotkey>
<media-hotkey keys="Home" action="seekToPercent" value="0"></media-hotkey>
<media-hotkey keys="End" action="seekToPercent" value="100"></media-hotkey>
<media-hotkey keys=">" action="speedUp"></media-hotkey>
<media-hotkey keys="<" action="speedDown"></media-hotkey>
<!-- Gestures -->
<media-gesture type="tap" action="togglePaused" pointer="mouse" region="center"></media-gesture>
<media-gesture type="tap" action="toggleControls" pointer="touch"></media-gesture>
<media-gesture type="doubletap" action="seekStep" region="left"></media-gesture>
<media-gesture type="doubletap" action="toggleFullscreen" region="center"></media-gesture>
<media-gesture type="doubletap" action="seekStep" region="right"></media-gesture>
<!-- Input Indicators -->
<media-status-announcer class="media-sr-only"></media-status-announcer>
<div class="media-input-indicator">
<media-volume-indicator hidden class="media-surface media-volume-indicator">
<media-volume-indicator-fill class="media-volume-indicator__content">
<media-icon name="volume-high" class="media-icon media-icon--volume-high"></media-icon>
<media-icon name="volume-low" class="media-icon media-icon--volume-low"></media-icon>
<media-icon name="volume-off" class="media-icon media-icon--volume-off"></media-icon>
<media-volume-indicator-value class="media-volume-indicator__value"></media-volume-indicator-value>
</media-volume-indicator-fill>
</media-volume-indicator>
<media-status-indicator
hidden
actions="toggleSubtitles toggleFullscreen togglePictureInPicture"
class="media-surface media-status-indicator media-status-indicator--state"
>
<div class="media-status-indicator__content">
<media-icon name="captions-on" class="media-icon media-icon--captions-on"></media-icon>
<media-icon name="captions-off" class="media-icon media-icon--captions-off"></media-icon>
<media-icon name="fullscreen-enter" class="media-icon media-icon--fullscreen-enter"></media-icon>
<media-icon name="fullscreen-exit" class="media-icon media-icon--fullscreen-exit"></media-icon>
<media-icon name="pip-enter" class="media-icon media-icon--pip-enter"></media-icon>
<media-icon name="pip-exit" class="media-icon media-icon--pip-exit"></media-icon>
<media-status-indicator-value class="media-status-indicator__value"></media-status-indicator-value>
</div>
</media-status-indicator>
<media-seek-indicator hidden class="media-seek-indicator">
<media-icon name="chevron" class="media-icon media-icon--seek"></media-icon>
<media-seek-indicator-value class="media-seek-indicator__value"></media-seek-indicator-value>
</media-seek-indicator>
<media-status-indicator hidden actions="togglePaused" class="media-status-indicator media-status-indicator--playback">
<media-icon name="play" class="media-icon media-icon--play"></media-icon>
<media-icon name="pause" class="media-icon media-icon--pause"></media-icon>
</media-status-indicator>
</div>
</media-container>
</video-player>/* -------------------------------------------------------------------------- */
/* Global styles for the host document, outside of the Shadow DOM */
/* -------------------------------------------------------------------------- */
video-player,
live-video-player,
media-i18n,
media-dialog,
media-alert-dialog,
media-error-dialog,
media-controls {
display: contents;
}
/*
Required to override any default video and image styles (such as
Tailwind's CSS reset) and ensure they fill the container as expected.
*/
media-container video,
media-container [slot="poster"] {
display: block;
width: 100%;
height: 100%;
}
media-container video::-webkit-media-text-track-container {
z-index: 1;
font-family: inherit;
scale: 0.98;
translate: 0 var(--media-caption-track-y, 0);
transition: translate var(--media-caption-track-duration, 0) ease-out;
transition-delay: var(--media-caption-track-delay, 0);
}
/* -------------------------------------------------------------------------- */
/* Shared styles for all HTML skins */
/* -------------------------------------------------------------------------- */
media-tooltip-group,
media-dialog,
media-alert-dialog,
media-error-dialog,
media-controls {
display: contents;
}
:host {
/* `display:grid` fixes a weird issue with Safari when setting aspect-ratio */
display: grid;
width: 100%;
}
media-container {
min-width: 0;
min-height: 0;
}
/* Hide the volume popover when its slider is unavailable. */
.media-popover--volume:has(media-volume-slider[data-hidden]) {
display: none;
}
.media-sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
white-space: nowrap;
border: 0;
clip: rect(0, 0, 0, 0);
}
.media-skin *,
.media-skin *::before,
.media-skin *::after {
box-sizing: border-box;
}
.media-skin img,
.media-skin video,
.media-skin svg {
display: block;
max-width: 100%;
margin: 0;
}
.media-skin button {
margin: 0;
font: inherit;
text-transform: none;
letter-spacing: inherit;
}
/* Icons author fill and stroke as presentational attributes, which lose to any host-page `svg` rule. */
.media-skin svg[fill="currentColor"] {
fill: currentColor;
}
.media-skin svg[fill="none"] {
fill: none;
}
.media-skin svg[stroke="currentColor"] {
stroke: currentColor;
}
.media-skin [hidden][hidden] {
/* Keep authored templates hidden even when component classes set display. */
display: none;
}
@media (prefers-reduced-motion: no-preference) {
.media-skin {
interpolate-size: allow-keywords;
}
}
.media-skin--default {
/* Colors */
--media-internal-accent-color: var(--media-accent-color, var(--media-default-accent-color));
--media-accent-contrast-color: contrast-color(var(--media-internal-accent-color));
--media-accent-background-color: var(
--media-accent-color,
oklch(from var(--media-default-accent-color) l c h / calc(alpha * 0.1))
);
/* The surface behind hovered subtle controls; audio skins override it for their light-dark surface. */
--media-internal-accent-text-base: oklch(0 0 0);
--media-internal-accent-text-color: var(
--media-accent-text-color,
contrast-color(var(--media-accent-color, var(--media-internal-accent-text-base)))
);
--media-shadow-current-color: oklch(from currentColor 0 0 0 / clamp(0, calc((l - 0.5) * 0.5), 0.15));
--media-shadow-subtle-current-color: oklch(from var(--media-shadow-current-color) l c h / calc(alpha * 0.4));
--media-scrollbar-thumb-color: oklch(from currentColor l c h / 0.3);
/* Scaling - used in video fullscreen to scale the UI. */
--media-scale: 1;
/* Fixed scaling unit to avoid inheriting the document's root font size. This must be a CSS <length>. */
--media-internal-scale-unit: var(--media-scale-unit, 16px);
--media-size: calc(var(--media-internal-scale-unit) * var(--media-scale));
/* Create a Tailwind-like spacing unit where 1 equals 4px with default scaling. */
--media-spacing: calc(var(--media-size) / 4);
/* Font sizes */
--media-font-size-medium: calc(0.9375 * var(--media-size)); /* 15px */
--media-font-size-base: calc(0.8125 * var(--media-size)); /* 13px */
--media-font-size-small: calc(0.6875 * var(--media-size)); /* 11px */
--media-font-size-tiny: calc(0.5625 * var(--media-size)); /* 9px */
--media-icon-size: calc(1.125 * var(--media-size)); /* 18px */
/* Radii */
--media-container-border-radius: var(--media-border-radius, calc(var(--media-spacing) * 7));
position: relative;
display: block;
width: 100%;
height: 100%;
container: media-root / inline-size;
font-family:
Inter Variable,
Inter,
ui-sans-serif,
system-ui,
sans-serif;
font-size: var(--media-font-size-base);
-webkit-font-smoothing: auto;
-moz-osx-font-smoothing: auto;
line-height: 1.5;
letter-spacing: normal;
outline: 2px solid transparent;
outline-offset: -4px;
scrollbar-color: var(--media-scrollbar-thumb-color) transparent;
scrollbar-width: thin;
border-radius: var(--media-container-border-radius, calc(var(--media-spacing) * 7));
isolation: isolate;
transition-timing-function: ease-out;
transition-duration: 100ms;
transition-property: outline-offset, outline-color;
&:focus-visible {
outline-color: var(--media-focus-ring-color);
outline-offset: 2px;
}
&::-webkit-scrollbar-thumb {
background: var(--media-scrollbar-thumb-color);
border-radius: 9999px;
}
@media (prefers-reduced-transparency: reduce) or (prefers-contrast: more) {
--media-scrollbar-thumb-color: oklch(from currentColor l c h / 0.8);
scrollbar-width: auto;
}
}
.media-skin--default .media-surface {
background-color: var(--media-surface-background-color);
box-shadow:
0 0 0 1px var(--media-surface-outer-border-color),
0 1px 3px 0 var(--media-surface-shadow-color),
0 1px 2px -1px var(--media-surface-shadow-color);
backdrop-filter: var(--media-surface-backdrop-filter);
/* Inner border ring */
&::after {
position: absolute;
inset: 0;
z-index: 10;
pointer-events: none;
content: "";
border-radius: inherit;
box-shadow:
inset 0 1px 0 0 var(--media-surface-inner-border-color),
inset 0 0 0 1px oklch(from var(--media-surface-inner-border-color) l c h / calc(alpha * 0.5));
}
}
.media-skin--default ::slotted(video),
.media-skin--default video {
display: block;
width: 100%;
height: 100%;
object-fit: var(--media-object-fit, contain);
object-position: var(--media-object-position, center);
}
.media-skin--default ::slotted(video) {
border-radius: var(--media-container-border-radius);
}
.media-skin--default video {
border-radius: inherit;
}
.media-skin--default:fullscreen ::slotted(video),
.media-skin--default:fullscreen video {
object-fit: contain;
}
.media-skin--default .media-controls__backdrop {
position: absolute;
inset: 0;
z-index: 10;
pointer-events: none;
background-image: linear-gradient(to top, oklch(0 0 0 / 0.5), oklch(0 0 0 / 0.3) 25%, oklch(0 0 0 / 0));
border-radius: inherit;
opacity: 0;
transition-timing-function: ease-out;
transition-duration: var(--media-controls-transition-duration);
transition-property: opacity;
&[data-visible] {
opacity: 1;
}
}
.media-skin--default .media-buffering-indicator {
position: absolute;
inset: 0;
z-index: 10;
display: none;
place-content: center;
color: oklch(1 0 0);
pointer-events: none;
&::before {
position: absolute;
inset: 0;
content: "";
background: oklch(0 0 0 / 0.35);
backdrop-filter: blur(8px);
}
> * {
position: relative;
z-index: 20;
}
&:not([data-visible]) {
--media-spinner-animation: none;
}
&[data-visible] {
display: grid;
}
@media (prefers-reduced-motion: reduce) {
--media-spinner-animation: none;
}
}
.media-skin--default {
.media-dialog__backdrop {
position: absolute;
inset: 0;
z-index: 20;
pointer-events: none;
background: oklch(0 0 0 / 0.2);
backdrop-filter: blur(16px) saturate(1.5);
opacity: 1;
transition-timing-function: var(--media-dialog-transition-timing-function);
transition-duration: var(--media-dialog-transition-duration);
transition-property: opacity;
transition-delay: var(--media-dialog-transition-delay);
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
}
&[data-ending-style] {
transition-delay: 0ms;
}
&:not([data-open]) {
display: none;
}
}
.media-dialog__popup {
outline: none;
&:not([data-open]) {
display: none;
}
}
.media-dialog__title {
margin: 0;
font-weight: 600;
line-height: 1.25;
}
.media-dialog__description {
margin: 0;
overflow-wrap: anywhere;
opacity: 0.7;
}
.media-dialog__actions {
display: flex;
flex-shrink: 0;
gap: calc(var(--media-spacing) * 2);
> * {
flex: 1;
}
}
}
.media-skin--default .media-controls {
--media-popover-side-offset: calc(var(--media-spacing) * (var(--media-base-side-offset, 2) + 1));
--media-tooltip-side-offset: var(--media-popover-side-offset);
--media-popover-boundary-offset: calc(var(--media-spacing) * var(--media-base-boundary-offset, 2));
--media-tooltip-boundary-offset: var(--media-popover-boundary-offset);
display: flex;
align-items: center;
padding: calc(var(--media-spacing) * 1);
container: media-controls / inline-size;
text-shadow: 0 1px 0 var(--media-shadow-current-color);
border-radius: calc(Infinity * 1px);
&:dir(rtl) {
flex-direction: row-reverse;
}
}
.media-skin--default .media-time-controls {
display: flex;
flex: 1;
gap: calc(var(--media-spacing) * 2.5);
align-items: center;
container: media-time-controls / inline-size;
&:dir(rtl) {
flex-direction: row-reverse;
}
> .media-time:last-child {
@container media-time-controls (width < 256px) {
display: none;
}
}
}
.media-skin--default .media-time {
font-variant-numeric: tabular-nums;
}
.media-skin--default .media-time[role="button"] {
cursor: pointer;
outline: 2px solid transparent;
outline-offset: -2px;
border-radius: calc(var(--media-spacing) * 1);
transition-timing-function: ease-out;
transition-duration: 100ms;
transition-property: outline-color, outline-offset;
&:focus-visible {
outline-color: var(--media-focus-ring-color);
outline-offset: 2px;
}
}
/* Base button */
.media-skin--default .media-button {
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
height: calc(var(--media-spacing) * 9);
min-height: 0;
padding: calc(var(--media-spacing) * 2) calc(var(--media-spacing) * 4);
text-align: center;
touch-action: manipulation;
cursor: pointer;
user-select: none;
appearance: none;
color: inherit;
outline: 2px solid transparent;
outline-offset: -2px;
background: none;
border: none;
border-radius: calc(Infinity * 1px);
transition-timing-function: ease-out;
transition-duration: 150ms;
transition-property: background-color, color, outline-offset, scale;
/* Fix weird jumping when clicking on the buttons in Safari. */
will-change: scale;
&:focus-visible {
outline-color: var(--media-focus-ring-color);
outline-offset: 2px;
}
&:active:not([aria-disabled="true"]) {
scale: 0.97;
}
&[aria-disabled="true"] {
cursor: not-allowed;
opacity: 0.5;
}
}
/* Primary button variant */
.media-skin--default .media-button--primary {
font-weight: 500;
color: var(--media-accent-contrast-color);
text-shadow: none;
background: var(--media-internal-accent-color);
}
/* Subtle button variant */
.media-skin--default .media-button--subtle {
color: inherit;
text-shadow: inherit;
background: transparent;
&:not([aria-disabled="true"]) {
&:hover,
&:focus-visible,
&[aria-expanded="true"] {
color: var(--media-internal-accent-text-color);
text-decoration: none;
background-color: var(--media-accent-background-color);
}
}
}
/* Icon button variant */
.media-skin--default .media-button--icon {
display: grid;
aspect-ratio: 1;
padding: 0;
&:active:not([aria-disabled="true"]) {
scale: 0.97;
}
.media-icon__container {
display: grid;
}
.media-icon {
grid-area: 1 / 1;
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
transition-timing-function: ease-out;
transition-duration: 150ms;
transition-property: opacity, scale;
}
}
/* Seek button */
.media-skin--default .media-button--seek {
.media-icon__label {
position: absolute;
right: -1px;
bottom: -3px;
font-size: 0.715em; /* 10px */
font-weight: 500;
font-variant-numeric: tabular-nums;
letter-spacing: -0.05em;
}
&:has(.media-icon--flipped) .media-icon__label {
right: unset;
left: -1px;
}
}
/* Playback rate button */
.media-skin--default .media-button--playback-rate {
padding: 0;
font-variant-numeric: tabular-nums;
&::after {
width: 4ch;
content: attr(data-rate) "\00D7";
}
&[data-inline-rate-label]::after {
content: none;
}
}
/* Settings button */
.media-skin--default .media-button--settings {
.media-icon--settings {
transition: transform 150ms ease-in-out;
@media (prefers-reduced-motion: reduce) {
transition-duration: 0ms;
}
}
&[aria-expanded="true"] .media-icon--settings {
transform: rotate(90deg);
}
}
/* Live button — wide pill button with a status dot (gray → red at the live
edge) rendered via ::before, and "LIVE" text rendered as the button's own
text content. */
.media-skin--default .media-button--live {
display: inline-flex;
gap: calc(var(--media-spacing) * 1.5);
align-items: center;
width: auto;
aspect-ratio: auto;
padding: calc(var(--media-spacing) * 2) calc(var(--media-spacing) * 3);
font-size: var(--media-font-size-small);
font-weight: 600;
line-height: 1;
text-transform: uppercase;
letter-spacing: 0.05em;
&::before {
display: inline-block;
flex-shrink: 0;
width: calc(var(--media-spacing) * 2);
height: calc(var(--media-spacing) * 2);
content: "";
background-color: oklch(from currentColor l c h / 0.4);
border-radius: 50%;
transition: background-color 150ms ease-out;
}
&[data-live-edge]::before {
background-color: oklch(0.65 0.22 27);
}
}
@media (prefers-reduced-motion: reduce) {
.media-skin--default .media-button {
scale: 1;
transition-property: background-color, color;
will-change: auto;
}
}
.media-skin--default .media-button-group {
display: flex;
gap: 1px;
align-items: center;
&:dir(rtl) {
flex-direction: row-reverse;
}
}
.media-skin--default .media-badge {
padding: calc(var(--media-spacing) * 0.5) calc(var(--media-spacing) * 1.5);
font-size: var(--media-font-size-small);
font-weight: 500;
line-height: 1;
color: oklch(from currentColor l c h / 0.85);
white-space: nowrap;
background-color: oklch(from currentColor l c h / 0.1);
border-radius: calc(Infinity * 1px);
}
.media-skin--default .media-icon__container {
position: relative;
}
.media-skin--default .media-icon {
flex-shrink: 0;
width: var(--media-icon-size);
height: var(--media-icon-size);
}
.media-skin--default .media-icon--flipped,
.media-skin--default:dir(rtl) .media-menu__chevron {
scale: -1 1;
}
.media-skin--default:dir(rtl) .media-menu__chevron.media-icon--flipped {
scale: 1 1;
}
.media-skin--default media-poster,
.media-skin--default > img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
transition: opacity 0.25s;
}
.media-skin--default media-poster:not([data-visible]),
.media-skin--default > img:not([data-visible]) {
opacity: 0;
}
.media-skin--default media-poster > slot > img:not([src]):not([srcset]),
.media-skin--default media-poster ::slotted(img:not([src]):not([srcset])),
.media-skin--default > img:not([src]):not([srcset]) {
visibility: hidden;
}
.media-skin--default media-poster ::slotted(img),
.media-skin--default media-poster img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: var(--media-object-fit, contain);
object-position: var(--media-object-position, center);
border-radius: var(--media-container-border-radius);
}
.media-skin--default > img {
object-fit: var(--media-object-fit, contain);
object-position: var(--media-object-position, center);
border-radius: inherit;
}
.media-skin--default:fullscreen media-poster ::slotted(img),
.media-skin--default:fullscreen media-poster img,
.media-skin--default:fullscreen > img {
object-fit: contain;
}
.media-skin--default .media-thumbnail {
position: relative;
pointer-events: none;
background-color: oklch(0 0 0 / 0.9);
border-radius: calc(var(--media-spacing) * 3);
.media-thumbnail__image {
position: relative;
display: block;
max-width: var(--media-thumbnail-max-width);
max-height: var(--media-thumbnail-max-height);
overflow: clip;
border-radius: inherit;
&::after {
position: absolute;
inset: 0;
content: "";
background-image: linear-gradient(to top, oklch(0 0 0 / 0.5), oklch(0 0 0 / 0.1), oklch(0 0 0 / 0));
border-radius: inherit;
}
}
.media-thumbnail__spinner {
position: absolute;
top: 50%;
left: 50%;
opacity: 0;
translate: -50% -50%;
}
.media-thumbnail__image,
.media-thumbnail__spinner {
transition: opacity 150ms ease-out;
}
&:not(:has(.media-thumbnail__image[data-loading])) {
.media-thumbnail__spinner {
--media-spinner-animation: none;
}
}
@media (prefers-reduced-motion: reduce) {
--media-spinner-animation: none;
}
&:has(.media-thumbnail__image[data-loading]) {
width: var(--media-thumbnail-max-width);
max-width: 100%;
aspect-ratio: 16 / 9;
overflow: hidden;
.media-thumbnail__image {
opacity: 0;
}
.media-thumbnail__spinner {
opacity: 1;
}
}
}
.media-skin--default .media-slider {
--media-track-size: calc(var(--media-spacing) * 1);
--media-track-highlighted-size: calc(var(--media-spacing) * 1.75);
--media-track-border-radius: 99px;
--media-track-transition-duration: 100ms;
--media-thumb-size: calc(var(--media-spacing) * 3);
--media-chapter-gap: calc(var(--media-spacing) * 1);
--media-internal-chapter-inset-start: calc(var(--media-chapter-gap) / 2);
--media-internal-chapter-inset-end: calc(var(--media-chapter-gap) / 2);
position: relative;
display: flex;
flex: 1;
align-items: center;
justify-content: center;
cursor: pointer;
outline: none;
&[data-orientation="horizontal"] {
width: var(--media-slider-width, 100%);
min-width: calc(var(--media-spacing) * 20);
height: var(--media-slider-height, calc(var(--media-spacing) * 8));
}
&[data-orientation="vertical"] {
width: var(--media-slider-width, calc(var(--media-spacing) * 8));
height: var(--media-slider-height, calc(var(--media-spacing) * 20));
}
/* Track */
.media-slider__track {
position: relative;
overflow: hidden;
user-select: none;
background-color: oklch(from currentColor l c h / 0.2);
border-radius: var(--media-track-border-radius);
isolation: isolate;
&[data-orientation="horizontal"] {
width: 100%;
height: var(--media-track-size);
}
&[data-orientation="vertical"] {
width: var(--media-track-size);
height: 100%;
}
}
/* Shared track fills */
.media-slider__buffer,
.media-slider__fill {
position: absolute;
pointer-events: none;
border-radius: inherit;
&[data-orientation="horizontal"] {
inset-block: 0;
left: 0;
width: 100%;
}
&[data-orientation="vertical"] {
inset-inline: 0;
bottom: 0;
height: 100%;
}
@media (prefers-reduced-motion: no-preference) {
transition: clip-path var(--media-track-transition-duration) ease-out;
}
}
&[data-dragging] {
.media-slider__fill,
.media-slider__buffer {
transition-duration: 0ms;
}
}
/* Buffer */
.media-slider__buffer {
background-color: oklch(from currentColor l c h / 0.2);
&[data-orientation="horizontal"] {
clip-path: inset(0 calc(100% - var(--media-slider-buffer)) 0 0 round var(--media-track-border-radius));
}
&[data-orientation="vertical"] {
clip-path: inset(calc(100% - var(--media-slider-buffer)) 0 0 0 round var(--media-track-border-radius));
}
}
/* Fill */
.media-slider__fill {
background-color: var(--media-internal-accent-color);
&[data-orientation="horizontal"] {
clip-path: inset(0 calc(100% - var(--media-slider-fill)) 0 0 round var(--media-track-border-radius));
}
&[data-orientation="vertical"] {
clip-path: inset(calc(100% - var(--media-slider-fill)) 0 0 0 round var(--media-track-border-radius));
}
}
&[data-dragging] {
.media-slider__fill[data-orientation="horizontal"] {
clip-path: inset(0 calc(100% - var(--media-slider-pointer)) 0 0 round var(--media-track-border-radius));
}
.media-slider__fill[data-orientation="vertical"] {
clip-path: inset(calc(100% - var(--media-slider-pointer)) 0 0 0 round var(--media-track-border-radius));
}
}
/* Chapters */
.media-slider__chapters {
position: relative;
display: flex;
flex: 1;
align-items: center;
min-width: 0;
min-height: 0;
border-radius: inherit;
&[data-orientation="horizontal"] {
width: 100%;
height: 100%;
}
&[data-orientation="vertical"] {
flex-direction: column-reverse;
width: 100%;
height: 100%;
}
}
.media-slider__chapter {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
min-width: 0;
min-height: 0;
border-radius: inherit;
&:first-child {
--media-internal-chapter-inset-start: 0px;
}
&:last-child {
--media-internal-chapter-inset-end: 0px;
}
.media-slider__chapter-track {
border-radius: inherit;
@media (prefers-reduced-motion: no-preference) {
transition: 200ms ease-out;
transition-property: height, width;
}
}
&[data-orientation="horizontal"] {
clip-path: inset(0 calc(100% - var(--media-slider-chapter-end)) 0 var(--media-slider-chapter-start));
.media-slider__chapter-track {
height: var(--media-track-size);
clip-path: inset(
0 calc(100% - var(--media-slider-chapter-end) + var(--media-internal-chapter-inset-end)) 0
calc(var(--media-slider-chapter-start) + var(--media-internal-chapter-inset-start)) round
var(--media-track-border-radius)
);
}
&[data-highlighted] .media-slider__chapter-track {
height: var(--media-track-highlighted-size);
}
}
&[data-orientation="vertical"] {
clip-path: inset(calc(100% - var(--media-slider-chapter-end)) 0 var(--media-slider-chapter-start) 0);
.media-slider__chapter-track {
width: var(--media-track-size);
clip-path: inset(
calc(100% - var(--media-slider-chapter-end) + var(--media-internal-chapter-inset-end)) 0
calc(var(--media-slider-chapter-start) + var(--media-internal-chapter-inset-start)) 0 round
var(--media-track-border-radius)
);
}
&[data-highlighted] .media-slider__chapter-track {
width: var(--media-track-highlighted-size);
}
}
}
/* Thumb */
.media-slider__thumb {
position: absolute;
z-index: 10;
width: var(--media-thumb-size);
height: var(--media-thumb-size);
user-select: none;
outline: 4px solid transparent;
outline-offset: -4px;
background-color: currentColor;
border-radius: calc(Infinity * 1px);
box-shadow:
0 0 0 1px var(--media-shadow-current-color, oklch(0 0 0 / 0.1)),
0 1px 3px 0 oklch(0 0 0 / 0.35),
0 1px 2px -1px oklch(0 0 0 / 0.35);
opacity: 0;
scale: 0.8;
translate: -50% -50%;
&[data-orientation="horizontal"] {
top: 50%;
left: var(--media-slider-fill);
}
&[data-orientation="vertical"] {
top: calc(100% - var(--media-slider-fill));
left: 50%;
}
&:focus-visible {
outline-color: oklch(from currentColor l c h / 0.15);
outline-offset: 0;
opacity: 1;
}
&::after {
position: absolute;
inset: -4px;
content: "";
border-radius: inherit;
box-shadow: 0 0 0 2px currentColor;
}
&:not(:focus-visible)::after {
opacity: 0;
scale: 0.5;
}
&.media-slider__thumb--persistent {
opacity: 1;
scale: 1;
}
@media (hover: hover) and (pointer: fine) {
&:hover {
outline-color: oklch(from currentColor l c h / 0.15);
outline-offset: 0;
}
}
@media (prefers-reduced-motion: no-preference) {
transition-timing-function: ease-out;
transition-duration: var(--media-track-transition-duration);
transition-property: opacity, outline-offset, left, top, scale;
&::after {
transition-timing-function: ease-out;
transition-duration: 150ms;
transition-property: opacity, scale;
}
}
}
@media (hover: hover) and (pointer: fine) {
&:hover .media-slider__thumb {
opacity: 1;
scale: 1;
}
}
&[data-dragging] .media-slider__thumb {
opacity: 1;
scale: 0.9;
@media (prefers-reduced-motion: no-preference) {
transition-property: opacity, outline-offset, scale;
}
&[data-orientation="horizontal"] {
left: var(--media-slider-pointer);
}
&[data-orientation="vertical"] {
top: calc(100% - var(--media-slider-pointer));
}
}
/* Preview */
.media-slider__preview {
--media-max-size-factor: 36;
--media-max-size: min(calc(var(--media-spacing) * var(--media-max-size-factor)), 100cqi);
min-width: var(--media-max-size);
height: calc(var(--media-spacing) * 1);
@container media-root (width > 672px) {
--media-max-size-factor: 48;
}
.media-slider__thumbnail,
.media-slider__value {
position: absolute;
left: 50%;
max-width: var(--media-max-size);
opacity: 0;
filter: blur(8px);
transform-origin: bottom;
scale: 0.8;
translate: -50% calc(var(--media-spacing) * 2);
transition-timing-function: ease-out;
transition-duration: 150ms;
}
.media-slider__thumbnail {
--media-thumbnail-max-width: var(--media-max-size);
--media-thumbnail-max-height: var(--media-max-size);
bottom: calc(100% + (var(--media-spacing) * 9));
}
.media-slider__value {
bottom: calc(100% + (var(--media-spacing) * 12.5));
display: flex;
flex-direction: column;
align-items: center;
}
.media-slider__chapter-title {
min-width: 0;
max-width: var(--media-max-size);
padding-inline: calc(var(--media-spacing) * 6);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&:empty {
display: none;
}
}
&::before {
position: absolute;
top: 50%;
left: 50%;
z-index: 1;
width: calc(var(--media-spacing) * 1);
height: calc(var(--media-spacing) * 1);
pointer-events: none;
content: "";
background-color: currentColor;
border-radius: 100%;
box-shadow:
0 0 0 1px var(--media-shadow-current-color, oklch(0 0 0 / 0.15)),
0 1px 2px 0 oklch(0 0 0 / 0.35);
opacity: 0;
scale: 0.5;
translate: -50% -50%;
transition-timing-function: ease-out;
transition-duration: 200ms;
transition-property: opacity, scale;
}
}
&:is([data-pointing], :has(:focus-visible))
.media-slider__preview
:is(.media-slider__value, .media-slider__thumbnail),
.media-slider__preview[data-pointing]:not([data-dragging])::before {
opacity: 1;
filter: blur(0);
scale: 1;
}
}
.media-skin--default {
--media-popup-transition:
opacity var(--media-popup-transition-timing-function) var(--media-popup-transition-duration),
filter var(--media-popup-transition-timing-function) var(--media-popup-transition-duration),
transform var(--media-popup-transition-timing-function) var(--media-popup-transition-duration),
scale var(--media-popup-transition-timing-function) var(--media-popup-transition-duration);
}
.media-skin--default .media-popover,
.media-skin--default .media-tooltip {
--media-popup-translate-distance: calc(0.5 * var(--media-internal-scale-unit));
margin: 0;
overflow: visible;
color: inherit;
border: 0;
transition: var(--media-popup-transition);
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
filter: blur(4px);
/* We have to use transform here for translate as the translate property is used for positioning by core. */
transform: translate(var(--media-popup-translate-x-distance, 0), var(--media-popup-translate-y-distance, 0));
scale: 0.95;
}
&[data-ending-style] {
transform: none;
/* Speed up the exit transition. */
transition-duration: max(0ms, calc(var(--media-popup-transition-duration) - 50ms));
}
&[data-side="top"] {
--media-popup-translate-y-distance: var(--media-popup-translate-distance);
transform-origin: bottom;
}
&[data-side="bottom"] {
--media-popup-translate-y-distance: calc(var(--media-popup-translate-distance) * -1);
transform-origin: top;
}
&[data-side="left"] {
--media-popup-translate-x-distance: var(--media-popup-translate-distance);
transform-origin: right;
}
&[data-side="right"] {
--media-popup-translate-x-distance: calc(var(--media-popup-translate-distance) * -1);
transform-origin: left;
}
/* Safe area between trigger and popup */
&::before {
position: absolute;
pointer-events: inherit;
content: "";
}
&[data-side="top"]::before,
&[data-side="bottom"]::before {
inset-inline: 0;
width: 100%;
}
&[data-side="top"]::before {
top: 100%;
}
&[data-side="bottom"]::before {
bottom: 100%;
}
&[data-side="left"]::before,
&[data-side="right"]::before {
inset-block: 0;
height: 100%;
}
&[data-side="left"]::before {
left: 100%;
}
&[data-side="right"]::before {
right: 100%;
}
}
.media-skin--default .media-popover {
&[data-side="top"]::before,
&[data-side="bottom"]::before {
height: var(--media-popover-side-offset);
}
&[data-side="left"]::before,
&[data-side="right"]::before {
width: var(--media-popover-side-offset);
}
}
.media-skin--default .media-popover--volume {
padding: calc(var(--media-spacing) * 3) 0;
border-radius: calc(Infinity * 1px);
&:has(media-volume-slider[data-hidden]) {
display: none;
}
}
.media-skin--default .media-tooltip {
padding: calc(var(--media-spacing) * 1) calc(var(--media-spacing) * 2.5);
font-size: var(--media-font-size-base);
white-space: nowrap;
border-radius: calc(Infinity * 1px);
/* `display: flex` must not apply while closed — it overrides UA `[popover]` hiding. */
&[data-open] {
display: flex;
column-gap: calc(var(--media-spacing) * 1);
align-items: center;
}
&[data-side="top"]::before,
&[data-side="bottom"]::before {
height: var(--media-tooltip-side-offset);
}
&[data-side="left"]::before,
&[data-side="right"]::before {
width: var(--media-tooltip-side-offset);
}
.media-tooltip__kbd {
min-width: 1.5em;
padding: 0.1em;
font-family: inherit;
font-size: var(--media-font-size-small);
font-weight: 600;
line-height: 1.25;
text-align: center;
background-color: oklch(from currentColor l c h / 0.3);
border-radius: calc(var(--media-spacing) * 1);
}
}
.media-skin--default .media-menu {
--media-menu-transition-duration: 250ms;
--media-menu-max-height: calc(var(--media-spacing) * 56);
--media-menu-padding: calc(var(--media-spacing) * 1);
--media-menu-border-radius: calc(var(--media-spacing) * 3);
--media-menu-item-border-radius: calc(var(--media-menu-border-radius) - var(--media-menu-padding));
box-sizing: border-box;
min-width: max-content;
max-width: var(--media-menu-available-width, none);
max-height: min(var(--media-menu-available-height, var(--media-menu-max-height)), var(--media-menu-max-height));
padding: var(--media-menu-padding);
overflow: auto;
overscroll-behavior: none;
border-radius: var(--media-menu-border-radius);
@media (prefers-reduced-motion: reduce) {
--media-menu-transition-duration: 0ms;
}
& > .media-menu__panel {
--media-menu-content-enter-translate: 100%;
position: absolute;
inset-inline: 0;
top: 0;
z-index: 10;
max-height: inherit;
padding: var(--media-menu-padding);
overflow: auto;
overscroll-behavior: none;
outline: none;
translate: 0 0;
transition-timing-function: ease-out;
transition-duration: var(--media-menu-transition-duration);
transition-property: translate, filter;
&:where([data-starting-style], [data-ending-style]) {
overflow: hidden;
pointer-events: none;
filter: blur(8px);
translate: var(--media-menu-content-enter-translate) 0;
}
&:dir(rtl):where([data-starting-style], [data-ending-style]) {
--media-menu-content-enter-translate: -100%;
}
}
.media-menu__separator {
margin-block: calc(var(--media-spacing) * 1);
border-bottom: 1px solid oklch(0 0 0 / 0.1);
box-shadow: 0 1px 0 0 oklch(1 0 0 / 0.075);
}
.media-menu__content,
.media-menu__group {
anchor-scope: --menu-item-highlight-anchor;
display: flex;
flex-direction: column;
gap: calc(var(--media-spacing) * 0.5);
@supports (top: anchor(top)) {
&::before {
position: absolute;
position-anchor: --menu-item-highlight-anchor;
inset: anchor(inside);
/* Firefox treats the moving highlight as a content shift and re-scrolls
the menu while hovering. Exclude it from scroll anchoring. */
overflow-anchor: none;
pointer-events: none;
content: "";
background-color: var(--media-accent-background-color);
border-radius: var(--media-menu-item-border-radius);
transition: inset 100ms ease-in-out;
}
&:has([data-highlighted=""])::before {
transition-duration: 0ms;
}
}
}
.media-menu__item,
.media-menu__back {
position: relative;
display: flex;
gap: calc(var(--media-spacing) * 1.5);
align-items: center;
padding: calc(var(--media-spacing) * 1.5) calc(var(--media-spacing) * 2);
text-align: start;
white-space: nowrap;
text-shadow: 0 1px 0 var(--media-shadow-current-color);
cursor: pointer;
user-select: none;
outline: 2px solid transparent;
outline-offset: -2px;
border-radius: var(--media-menu-item-border-radius);
transition: background-color, color;
transition-timing-function: ease-in-out;
transition-duration: 100ms;
.media-icon {
flex-shrink: 0;
color: oklch(from currentColor l c h / 0.65);
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
}
&:focus-visible {
outline-color: var(--media-focus-ring-color);
outline-offset: 2px;
}
&:hover,
&[data-highlighted] {
color: var(--media-internal-accent-text-color);
background-color: var(--media-accent-background-color);
.media-icon {
color: inherit;
}
}
@supports (top: anchor(top)) {
transition-duration: 50ms;
&:hover,
&[data-highlighted] {
transition-duration: 200ms;
}
}
}
.media-menu__indicator {
flex-shrink: 0;
margin-inline: auto calc(var(--media-spacing) * -1);
opacity: 0;
.media-icon {
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
}
}
.media-menu__item {
justify-content: space-between;
font-variant-numeric: tabular-nums;
color: inherit;
&[aria-disabled="true"] {
pointer-events: none;
cursor: not-allowed;
opacity: 0.5;
}
&[aria-checked="true"] .media-menu__indicator {
opacity: 1;
}
&[data-availability="unavailable"],
&[data-availability="unsupported"] {
display: none;
}
&[data-highlighted] {
@supports (top: anchor(top)) {
anchor-name: --menu-item-highlight-anchor;
background-color: transparent;
}
}
}
.media-menu__tier {
padding-inline-start: calc(var(--media-spacing) * 0.5);
padding-top: 1px;
font-size: var(--media-font-size-tiny);
font-weight: 600;
line-height: 1;
color: oklch(from currentColor l c h / 0.7);
}
.media-menu__back {
width: 100%;
margin-bottom: calc(var(--media-spacing) * 0.5);
}
.media-menu__hint {
display: inline-flex;
gap: calc(var(--media-spacing) * 1);
align-items: center;
min-width: 0;
padding-inline-start: calc(var(--media-spacing) * 2);
margin-inline-start: auto;
color: oklch(from currentColor l c h / 0.65);
}
.media-menu__hint-label {
max-width: calc(var(--media-spacing) * 24);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.media-menu__chevron {
width: calc(var(--media-spacing) * 3.5);
height: calc(var(--media-spacing) * 3.5);
}
/* Settings menu */
&.media-menu--settings {
width: var(--media-menu-width);
min-width: calc(var(--media-spacing) * 44);
height: var(--media-menu-height);
overflow: hidden;
/* Only the menu size changes between panels. */
transition:
var(--media-popup-transition),
width var(--media-popup-transition-timing-function) var(--media-menu-transition-duration),
height var(--media-popup-transition-timing-function) var(--media-menu-transition-duration);
& > .media-menu__content {
--media-menu-content-exit-translate: -100%;
translate: 0 0;
transition:
translate var(--media-menu-transition-duration) ease-out,
filter var(--media-menu-transition-duration) ease-out;
&:dir(rtl) {
--media-menu-content-exit-translate: 100%;
}
}
& > .media-menu__content[data-child-open] {
filter: blur(8px);
translate: var(--media-menu-content-exit-translate) 0;
}
/* WebKit can restart the parent Content transition while the
anchor-positioned highlight remains active. */
& > .media-menu__content[data-child-open]::before,
&:has(> .media-menu__panel[data-ending-style]) > .media-menu__content::before {
display: none;
}
/* Don't transition size on open/close. */
&[data-starting-style],
&[data-ending-style] {
transition: var(--media-popup-transition);
}
}
}
.media-skin--default {
--media-caption-track-duration: var(--media-controls-transition-duration);
--media-caption-track-delay: 25ms;
--media-caption-track-y: calc(var(--media-spacing) * -2);
&:has(.media-controls[data-visible]) {
--media-caption-track-y: calc(var(--media-spacing) * -14);
}
}
.media-skin--default video::-webkit-media-text-track-container {
z-index: 1;
font-family: inherit;
scale: 0.98;
translate: 0 var(--media-caption-track-y);
transition: translate var(--media-caption-track-duration) ease-out;
transition-delay: var(--media-caption-track-delay);
}
.media-skin--default .media-input-indicator {
position: absolute;
inset: 0;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
align-items: center;
justify-items: center;
color: oklch(1 0 0);
pointer-events: none;
}
.media-skin--default {
.media-volume-indicator,
.media-status-indicator--state {
--media-surface-background-color: oklch(0 0 0 / 0.25);
position: absolute;
top: calc(var(--media-spacing) * 3);
font-weight: 500;
color: inherit;
pointer-events: none;
border-radius: calc(Infinity * 1px);
transform-origin: top center;
transition-timing-function: ease-out;
transition-duration: 100ms;
.media-volume-indicator__content,
.media-status-indicator__content {
display: flex;
gap: calc(var(--media-spacing) * 2);
align-items: center;
justify-content: space-between;
width: 100%;
padding: calc(var(--media-spacing) * 1) calc(var(--media-spacing) * 2.5);
* {
mix-blend-mode: difference;
}
}
.media-icon {
display: none;
flex-shrink: 0;
}
.media-volume-indicator__value,
.media-status-indicator__value {
margin-left: auto;
}
@media (pointer: coarse) {
transition-property: scale, translate, opacity;
will-change: scale, translate, opacity;
}
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
transition-property: scale, translate, filter, opacity;
will-change: scale, translate, filter, opacity;
}
@media (prefers-reduced-transparency: reduce) or (prefers-contrast: more) {
--media-surface-background-color: oklch(0 0 0);
}
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
transition-timing-function: ease-in;
transition-duration: 250ms;
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
filter: blur(8px);
scale: 0.9;
}
}
&[data-ending-style] {
@media (prefers-reduced-motion: no-preference) {
translate: 0 -25%;
}
}
}
.media-seek-indicator,
.media-status-indicator--playback {
display: grid;
grid-row: 1;
grid-column: 2;
place-content: center;
padding: calc(var(--media-spacing) * 4);
text-align: center;
}
}
.media-skin--default .media-volume-indicator {
width: min(80%, calc(var(--media-spacing) * 48));
transform: translateX(0);
.media-volume-indicator__content {
background-image: linear-gradient(currentColor, currentColor);
background-repeat: no-repeat;
background-position: left;
background-size: var(--media-volume-fill, 0%) 100%;
border-radius: inherit;
transition: background-size 200ms linear;
}
&[data-level="high"] .media-icon--volume-high,
&[data-level="low"] .media-icon--volume-low,
&[data-level="off"] .media-icon--volume-off {
display: block;
}
@media (prefers-reduced-motion: no-preference) {
&[data-min]:not([data-starting-style], [data-ending-style]),
&[data-max]:not([data-starting-style], [data-ending-style]) {
transform: translateX(0.25px);
transition: transform 300ms linear(0, -24 20%, 16 40%, -8 60%, 4 80%, 1);
}
}
}
.media-skin--default .media-status-indicator--state {
&[data-status="captions-on"] .media-icon--captions-on,
&[data-status="captions-off"] .media-icon--captions-off,
&[data-status="fullscreen"] .media-icon--fullscreen-enter,
&[data-status="exit-fullscreen"] .media-icon--fullscreen-exit,
&[data-status="pip"] .media-icon--pip-enter,
&[data-status="exit-pip"] .media-icon--pip-exit {
display: block;
}
}
.media-skin--default .media-status-indicator--playback {
background: oklch(0 0 0 / 0.35);
border-radius: 100%;
backdrop-filter: blur(8px);
transition-timing-function: ease-out;
transition-duration: 200ms;
transition-property: opacity, scale;
.media-icon {
grid-area: 1 / 1;
width: calc(var(--media-icon-size) * 1.5);
height: calc(var(--media-icon-size) * 1.5);
opacity: 0;
scale: 0;
transition-timing-function: ease-out;
transition-duration: 150ms;
transition-property: opacity, scale;
&.media-icon--play {
translate: 1px 0;
}
}
&[data-status="pause"] .media-icon--pause,
&[data-status="play"] .media-icon--play {
opacity: 1;
scale: 1;
}
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
scale: 0.85;
}
&[data-ending-style] {
transition-timing-function: ease-in;
transition-duration: 100ms;
}
@media (prefers-reduced-motion: reduce) {
transition-duration: 50ms;
transition-property: opacity;
&[data-starting-style],
&[data-ending-style],
.media-icon {
scale: 1;
}
.media-icon {
transition-duration: 50ms;
transition-property: opacity;
}
}
}
.media-skin--default .media-seek-indicator {
gap: calc(var(--media-spacing) * 1);
.media-seek-indicator__value {
font-variant-numeric: tabular-nums;
}
@container media-root (width > 384px) {
padding: calc(var(--media-spacing) * 6);
}
&[data-direction="backward"] {
grid-column: 1;
justify-self: left;
}
&[data-direction="forward"] {
grid-column: 3;
justify-self: right;
}
.media-icon--seek {
display: block;
width: calc(var(--media-icon-size) * 1.5);
height: calc(var(--media-icon-size) * 1.5);
}
&[data-direction="backward"] .media-icon--seek {
scale: -1 1;
}
@media (prefers-reduced-motion: no-preference) {
.media-icon--seek {
transition-timing-function: ease-in-out;
transition-duration: 200ms;
transition-property: translate, opacity;
}
&[data-starting-style] .media-icon--seek,
&[data-ending-style] .media-icon--seek {
opacity: 0;
}
&[data-direction="forward"][data-starting-style] .media-icon--seek {
translate: -60% 0;
}
&[data-direction="backward"][data-starting-style] .media-icon--seek {
translate: 60% 0;
}
}
}
/* ==========================================================================
Icon State Visibility for Video Skins
Data-attribute-driven visibility rules for multi-state icon buttons shared
by the HTML and React skins.
========================================================================== */
/* --- All icons hidden by default --- */
.media-button--play .media-icon,
.media-button--mute .media-icon,
.media-button--fullscreen .media-icon,
.media-button--pip .media-icon,
.media-button--cast .media-icon,
.media-button--airplay .media-icon,
.media-button--captions .media-icon {
opacity: 0;
}
.media-button--play .media-icon {
scale: 0;
}
/* --- Active icon per state --- */
/* Play: ended → restart */
.media-button--play[data-ended] .media-icon--restart,
/* Play: paused or not yet started (not ended) → play */
.media-button--play:not([data-ended])[data-paused] .media-icon--play,
.media-button--play:not([data-ended]):not([data-started]) .media-icon--play,
/* Play: started and not paused/ended → pause */
.media-button--play[data-started]:not([data-paused]):not([data-ended]) .media-icon--pause,
/* Mute: muted → volume off */
.media-button--mute[data-muted] .media-icon--volume-off,
/* Mute: volume low (not muted) → volume low */
.media-button--mute:not([data-muted])[data-volume-level="low"] .media-icon--volume-low,
/* Mute: volume high (not muted, not low) → volume high */
.media-button--mute:not([data-muted]):not([data-volume-level="low"]) .media-icon--volume-high,
/* Fullscreen: not fullscreen → enter */
.media-button--fullscreen:not([data-fullscreen]) .media-icon--fullscreen-enter,
/* Fullscreen: fullscreen → exit */
.media-button--fullscreen[data-fullscreen] .media-icon--fullscreen-exit,
/* Picture-in-Picture: not active → enter */
.media-button--pip:not([data-pip]) .media-icon--pip-enter,
/* Picture-in-Picture: active → exit */
.media-button--pip[data-pip] .media-icon--pip-exit,
/* Cast: not connected → enter */
.media-button--cast:not([data-cast-state="connected"]) .media-icon--cast-enter,
/* Cast: connected → exit */
.media-button--cast[data-cast-state="connected"] .media-icon--cast-exit,
/* AirPlay: not connected → enter */
.media-button--airplay:not([data-airplay-state="connected"]) .media-icon--airplay-enter,
/* AirPlay: connected → exit */
.media-button--airplay[data-airplay-state="connected"] .media-icon--airplay-exit,
/* Captions: not active → captions off */
.media-button--captions:not([data-active]) .media-icon--captions-off,
/* Captions: active → captions on */
.media-button--captions[data-active] .media-icon--captions-on {
opacity: 1;
scale: 1;
}
/* --- Pause keyframe animations on inactive icons --- */
/* The airplay-exit SVG defines its keyframes against CSS variables (mirroring
the spinner pattern). When the AirPlay session isn't active the SVG is
still in the DOM — just `display: none` — so its animations would keep
running. Set the variables to `none` to short-circuit the keyframes. */
.media-button--airplay:not([data-airplay-state="connected"]) {
--media-icon-airplay-fill-animation: none;
--media-icon-airplay-triangle-animation: none;
}
@media (prefers-reduced-motion: reduce) {
.media-button--airplay {
--media-icon--airplay__fill-animation: none;
--media-icon--airplay__triangle-animation: none;
}
}
/* Video-specific container styles */
/* :where() keeps the media-type class at zero specificity so component state rules (for example dialog
`:not([data-open])`) still outrank these entry rules as they did before the shared-class rename. */
.media-skin--default:where(.media-skin--video) {
--media-default-accent-color: oklch(1 0 0);
--media-border-color: light-dark(oklch(0 0 0 / 0.1), oklch(1 0 0 / 0.15));
--media-focus-ring-color: light-dark(oklch(0 0 0), oklch(1 0 0));
--media-video-border-radius: var(--media-container-border-radius);
--media-surface-background-color: oklch(1 0 0 / 0.1);
--media-surface-inner-border-color: oklch(1 0 0 / 0.1);
--media-surface-outer-border-color: oklch(0 0 0 / 0.1);
--media-surface-shadow-color: oklch(0 0 0 / 0.15);
--media-surface-backdrop-filter: blur(16px) saturate(1.5);
--media-controls-transition-duration: 100ms;
--media-controls-transition-timing-function: ease-out;
--media-dialog-transition-duration: 350ms;
--media-dialog-transition-delay: 100ms;
--media-dialog-transition-timing-function: ease-out;
--media-popup-transition-duration: 100ms;
--media-popup-transition-timing-function: ease-out;
overflow: clip;
background: oklch(0 0 0);
@media (prefers-reduced-motion: reduce) {
--media-dialog-transition-duration: 50ms;
--media-dialog-transition-delay: 0ms;
--media-popup-transition-duration: 0ms;
.media-dialog__popup {
scale: 1;
transition-property: opacity;
}
}
@media (prefers-reduced-transparency: reduce) or (prefers-contrast: more) {
--media-surface-background-color: oklch(0 0 0);
--media-surface-inner-border-color: oklch(1 0 0 / 0.25);
--media-surface-outer-border-color: transparent;
}
&:has(.media-controls--root:not([data-visible])) {
/* Slight delay to hide controls on non-touch devices after interaction */
@media (pointer: fine) {
--media-controls-transition-duration: 300ms;
}
@media (pointer: coarse) {
--media-controls-transition-duration: 150ms;
}
@media (prefers-reduced-motion: reduce) {
--media-controls-transition-duration: 50ms;
}
}
/* Inner border ring */
&::after {
position: absolute;
inset: 0;
z-index: 10;
pointer-events: none;
content: "";
border-radius: inherit;
box-shadow: inset 0 0 0 1px var(--media-border-color);
}
&:fullscreen {
--media-container-border-radius: 0;
&::after {
display: none;
}
@media (width >= 1280px) {
--media-scale: 1.25;
}
@media (width >= 1536px) {
--media-scale: 1.5;
}
@media (width >= 1920px) {
--media-scale: 1.75;
}
}
* {
--media-focus-ring-color: oklch(1 0 0);
}
}
/* Dialog */
.media-skin--default:where(.media-skin--video) .media-dialog__popup {
position: absolute;
top: 50%;
left: 50%;
z-index: 20;
display: flex;
flex-direction: column;
gap: calc(var(--media-spacing) * 3);
width: 100%;
max-width: calc(var(--media-spacing) * 72);
max-height: calc(100% - var(--media-spacing) * 2);
padding: calc(var(--media-spacing) * 3);
color: oklch(1 0 0);
text-shadow: 0 1px 0 oklch(0 0 0 / 0.25);
border-radius: calc(var(--media-spacing) * 7);
translate: -50% -50%;
transition-delay: var(--media-dialog-transition-delay);
transition-timing-function: var(--media-dialog-transition-timing-function);
transition-duration: var(--media-dialog-transition-duration);
transition-property: opacity, scale;
}
.media-skin--default:where(.media-skin--video) .media-dialog__popup[data-starting-style],
.media-skin--default:where(.media-skin--video) .media-dialog__popup[data-ending-style] {
opacity: 0;
scale: 0.95;
}
.media-skin--default:where(.media-skin--video) .media-dialog__popup[data-ending-style] {
transition-duration: max(calc(var(--media-dialog-transition-duration) - 100ms), 50ms);
transition-delay: 0ms;
}
.media-skin--default:where(.media-skin--video) .media-dialog__content {
display: flex;
flex-direction: column;
min-height: 0;
gap: calc(var(--media-spacing) * 2);
padding: calc(var(--media-spacing) * 2) calc(var(--media-spacing) * 2) calc(var(--media-spacing) * 1.5);
overflow-y: auto;
text-shadow: inherit;
}
.media-skin--default:where(.media-skin--video) .media-dialog__title {
font-size: var(--media-font-size-medium);
}
.media-skin--default:where(.media-skin--video):has([role="alertdialog"][data-open]) .media-controls {
display: none;
}
.media-skin--default:where(.media-skin--video) .media-slider__value {
text-shadow: 0 1px 0 var(--media-shadow-current-color);
}
/* Controls (hide/show behavior) */
.media-skin--default:where(.media-skin--video) .media-controls--root {
--media-inset-factor: 2;
--media-inset: calc(var(--media-spacing) * var(--media-inset-factor));
--media-base-boundary-offset: var(--media-inset-factor);
z-index: 10;
display: contents;
color: oklch(1 0 0);
transition-timing-function: var(--media-controls-transition-timing-function);
/* Speed up the entry transition */
transition-duration: calc(var(--media-controls-transition-duration) / 2);
.media-controls--primary,
.media-controls--secondary {
position: absolute;
}
/* Primary must be higher for the preview/thumbnail */
.media-controls--primary {
z-index: 20;
}
.media-controls--secondary {
z-index: 10;
}
.media-controls--primary {
inset-inline: var(--media-inset);
bottom: var(--media-inset);
transform-origin: bottom;
}
.media-controls--secondary {
top: var(--media-inset);
right: var(--media-inset);
container-type: normal;
transform-origin: top;
}
.media-time-controls {
flex: 1;
padding-inline: calc(var(--media-spacing) * 2);
}
@container media-root (width < 512px) {
.media-controls--primary,
.media-controls--secondary {
transition-timing-function: inherit;
transition-duration: inherit;
@media (pointer: fine) {
transition-property: filter, opacity, scale, translate;
}
@media (pointer: coarse) {
transition-property: opacity, scale, translate;
}
}
&:after {
display: none;
}
&:not([data-visible]) {
.media-controls--primary,
.media-controls--secondary {
pointer-events: none;
opacity: 0;
scale: 0.95;
transition-duration: var(--media-controls-transition-duration);
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
filter: blur(8px);
}
@media (prefers-reduced-motion: reduce) {
scale: 1;
}
}
.media-controls--primary {
@media (prefers-reduced-motion: no-preference) {
translate: 0 4px;
}
}
.media-controls--secondary {
@media (prefers-reduced-motion: no-preference) {
translate: 0 -4px;
}
}
}
.media-button--captions {
display: none;
}
}
@container media-root (width >= 512px) {
position: absolute;
inset-inline: var(--media-inset);
bottom: var(--media-inset);
display: flex;
transform-origin: bottom;
.media-controls--primary,
.media-controls--secondary {
display: contents;
&::after {
display: none;
}
}
&:not([data-visible]) {
pointer-events: none;
opacity: 0;
scale: 0.95;
transition-duration: var(--media-controls-transition-duration);
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
filter: blur(8px);
}
@media (prefers-reduced-motion: reduce) {
scale: 1;
}
@media (prefers-reduced-motion: no-preference) {
translate: 0 4px;
}
}
.media-time-controls {
padding-inline: calc(var(--media-spacing) * 3);
}
}
@media (pointer: fine) {
transition-property: filter, opacity, scale, translate;
}
@media (pointer: coarse) {
transition-property: opacity, scale, translate;
}
@container media-root (width > 672px) {
--media-inset-factor: 3;
}
}
/* Hide cursor when controls are hidden */
.media-skin--default:where(.media-skin--video):has(.media-controls--root:not([data-visible])) {
cursor: none;
}
/* Sliders */
.media-skin--default:where(.media-skin--video) .media-slider__track {
background-color: oklch(1 0 0 / 0.2);
}
'use client';
import { type SVGProps, type ComponentProps, type ReactElement, type ReactNode, type CSSProperties } from 'react';
import { SpinnerIcon as SpinnerIconPrimitive, ChevronIcon as ChevronIconPrimitive, CaptionsOnIcon as CaptionsOnIconPrimitive, CaptionsOffIcon as CaptionsOffIconPrimitive, FullscreenEnterIcon as FullscreenEnterIconPrimitive, FullscreenExitIcon as FullscreenExitIconPrimitive, PipEnterIcon as PipEnterIconPrimitive, PipExitIcon as PipExitIconPrimitive, PlayIcon as PlayIconPrimitive, PauseIcon as PauseIconPrimitive, VolumeHighIcon as VolumeHighIconPrimitive, VolumeLowIcon as VolumeLowIconPrimitive, VolumeOffIcon as VolumeOffIconPrimitive, AirPlayEnterIcon as AirPlayEnterIconPrimitive, AirPlayExitIcon as AirPlayExitIconPrimitive, CastEnterIcon as CastEnterIconPrimitive, CastExitIcon as CastExitIconPrimitive, RestartIcon as RestartIconPrimitive, CheckIcon as CheckIconPrimitive, GearIcon as GearIconPrimitive } from '@videojs/react/icons';
import { SpinnerIcon as SpinnerIconPrimitive2, ChevronIcon as ChevronIconPrimitive2, CaptionsOnIcon as CaptionsOnIconPrimitive2, CaptionsOffIcon as CaptionsOffIconPrimitive2, FullscreenEnterIcon as FullscreenEnterIconPrimitive2, FullscreenExitIcon as FullscreenExitIconPrimitive2, PipEnterIcon as PipEnterIconPrimitive2, PipExitIcon as PipExitIconPrimitive2, PlayIcon as PlayIconPrimitive2, PauseIcon as PauseIconPrimitive2, VolumeHighIcon as VolumeHighIconPrimitive2, VolumeLowIcon as VolumeLowIconPrimitive2, VolumeOffIcon as VolumeOffIconPrimitive2, AirPlayEnterIcon as AirPlayEnterIconPrimitive2, AirPlayExitIcon as AirPlayExitIconPrimitive2, CastEnterIcon as CastEnterIconPrimitive2, CastExitIcon as CastExitIconPrimitive2, RestartIcon as RestartIconPrimitive2, CheckIcon as CheckIconPrimitive2, GearIcon as GearIconPrimitive2 } from '@videojs/react/icons/minimal';
import { BufferingIndicator as BufferingIndicatorPrimitive, ErrorDialog as ErrorDialogPrimitive, Container as ContainerPrimitive, Poster as PosterPrimitive, Gesture, Hotkey, SeekIndicator as SeekIndicatorPrimitive, StatusAnnouncer as StatusAnnouncerPrimitive, StatusIndicator as StatusIndicatorPrimitive, VolumeIndicator as VolumeIndicatorPrimitive, Tooltip, AirPlayButton as AirPlayButtonPrimitive, CaptionsButton as CaptionsButtonPrimitive, CastButton as CastButtonPrimitive, FullscreenButton as FullscreenButtonPrimitive, PiPButton as PiPButtonPrimitive, PlayButton as PlayButtonPrimitive, MuteButton as MuteButtonPrimitive, VolumeSlider as VolumeSliderPrimitive, VolumePopover as VolumePopoverPrimitive, TimeSlider as TimeSliderPrimitive, Slider, Menu, Text as TextPrimitive, Controls, Time } from '@videojs/react';
import { Video } from '@videojs/react/video';
import './player.css';
import { Player } from './player';
import { type VolumeSliderProps as CoreVolumeSliderProps, type SliderPreviewOverflow } from '@videojs/core';
import { audioText, captionsText, speedText, qualityText, settingsText } from '@videojs/core/i18n/text/menu';
import { type Poster } from '@videojs/react';
type ContainerProps = ContainerPrimitive.Props;
function Container({ children, className, ...props }: ContainerProps) {
return (
<ContainerPrimitive className={`media-container ${className ?? ''}`} {...props}>
{children}
</ContainerPrimitive>
);
}
interface PosterProps extends Omit<PosterPrimitive.Props, 'children' | 'render'> {
children?: PosterPrimitive.Props['render'];
}
function Poster({ children, className, src, ...props }: PosterProps = {}) {
return (
<PosterPrimitive
render={children}
className={(state) => `media-poster ${resolveClassName(className, state)}`}
src={src}
{...props}
/>
);
}
interface DefaultVideoSkinProps extends Omit<NonNullable<ComponentProps<typeof Container>>, 'children'> {
src: string;
poster?: string | undefined;
poster?: string | NonNullable<ComponentProps<typeof Poster>>['children'];
}
type BufferingIndicatorProps = Omit<BufferingIndicatorPrimitive.Props, 'children'>;
function BufferingIndicator({ className, ...props }: BufferingIndicatorProps = {}) {
return (
<BufferingIndicatorPrimitive
className={(state) => `media-buffering-indicator ${resolveClassName(className, state)}`}
{...props}
>
<>
<span className="contents theme-minimal:hidden">
<SpinnerIconPrimitive className={'media-buffering-indicator-spinner-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<SpinnerIconPrimitive2 className={'media-buffering-indicator-spinner-icon'} />
</span>
</>
</BufferingIndicatorPrimitive>
);
}
type ErrorDialogProps = Omit<ErrorDialogPrimitive.PopupProps, 'children'>;
type ButtonProps = ComponentProps<'button'>;
type PlayButtonProps = Omit<PlayButtonPrimitive.Props, 'children'>;
interface ButtonTooltipProps extends Tooltip.RootProps {
children: ReactElement;
label?: ReactNode;
}
function ButtonTooltip({ children, label, ...props }: ButtonTooltipProps) {
return (
<Tooltip.Root {...props}>
<Tooltip.Trigger render={children} />
<Tooltip.Popup className={'media-tooltip'}>
{label ?? <Tooltip.Label />}
{!label && <Tooltip.Shortcut className={'media-tooltip-shortcut'} />}
</Tooltip.Popup>
</Tooltip.Root>
);
}
function PlayButton({ className, ...props }: PlayButtonProps = {}) {
return (
<ButtonTooltip side="top">
<PlayButtonPrimitive
render={<Button />}
className={(state) => `media-play-button ${resolveClassName(className, state)}`}
{...props}
>
<>
<span className="contents theme-minimal:hidden">
<RestartIconPrimitive className={'media-button-icon media-play-button-restart-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<RestartIconPrimitive2 className={'media-button-icon media-play-button-restart-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<PlayIconPrimitive className={'media-button-icon media-play-button-play-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<PlayIconPrimitive2 className={'media-button-icon media-play-button-play-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<PauseIconPrimitive className={'media-button-icon media-play-button-pause-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<PauseIconPrimitive2 className={'media-button-icon media-play-button-pause-icon'} />
</span>
</>
</PlayButtonPrimitive>
</ButtonTooltip>
);
}
interface VolumePopoverProps extends Omit<VolumePopoverPrimitive.RootProps, 'children'> {
className?: string | undefined;
orientation?: CoreVolumeSliderProps['orientation'];
showTooltip?: boolean;
popupClassName?: ClassValue;
}
type MuteButtonProps = Omit<MuteButtonPrimitive.Props, 'children'>;
function MuteButton({ className, ...props }: MuteButtonProps = {}) {
return (
<MuteButtonPrimitive
render={<Button />}
className={(state) => `media-mute-button ${resolveClassName(className, state)}`}
{...props}
>
<>
<span className="contents theme-minimal:hidden">
<VolumeOffIconPrimitive className={'media-button-icon media-mute-button-off-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<VolumeOffIconPrimitive2 className={'media-button-icon media-mute-button-off-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<VolumeLowIconPrimitive className={'media-button-icon media-mute-button-low-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<VolumeLowIconPrimitive2 className={'media-button-icon media-mute-button-low-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<VolumeHighIconPrimitive className={'media-button-icon media-mute-button-high-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<VolumeHighIconPrimitive2 className={'media-button-icon media-mute-button-high-icon'} />
</span>
</>
</MuteButtonPrimitive>
);
}
type VolumeSliderProps = Omit<VolumeSliderPrimitive.RootProps, 'children'>;
function VolumeSlider({ className, ...props }: VolumeSliderProps = {}) {
return (
<VolumeSliderPrimitive.Root
className={(state) => `media-slider media-volume-slider ${resolveClassName(className, state)}`}
thumbAlignment="edge"
{...props}
>
<VolumeSliderPrimitive.Track render={<SliderTrack />}>
<VolumeSliderPrimitive.Fill render={<SliderFill />} />
</VolumeSliderPrimitive.Track>
<VolumeSliderPrimitive.Thumb render={<SliderThumb />} className={'media-volume-slider-thumb'} />
</VolumeSliderPrimitive.Root>
);
}
interface TimeSliderProps extends Omit<TimeSliderPrimitive.RootProps, 'children'> {
previewOverflow?: SliderPreviewOverflow | undefined;
}
function TimeSlider({ className, previewOverflow = 'visible', ...props }: TimeSliderProps = {}) {
return (
<TimeSliderPrimitive.Root
className={(state) => `media-slider media-time-slider ${resolveClassName(className, state)}`}
{...props}
>
<TimeSliderPrimitive.Chapters
className={'media-time-slider-chapters'}
renderChapter={(props) => (
<div className={'media-time-slider-chapter'} {...props}>
<TimeSliderPrimitive.Track render={<SliderTrack />} className={'media-time-slider-chapter-track'}>
<TimeSliderPrimitive.Buffer render={<SliderBuffer />} />
<TimeSliderPrimitive.Fill render={<SliderFill />} />
</TimeSliderPrimitive.Track>
</div>
)}
></TimeSliderPrimitive.Chapters>
<TimeSliderPrimitive.Thumb render={<SliderThumb />} className={'media-time-slider-thumb'} />
<TimeSliderPrimitive.Preview className={'media-slider-preview'} overflow={previewOverflow}>
<div className={'media-slider-thumbnail'}>
<Slider.Thumbnail className={'media-slider-thumbnail-image'} />
<>
<span className="contents theme-minimal:hidden">
<SpinnerIconPrimitive className={'media-slider-thumbnail-spinner-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<SpinnerIconPrimitive2 className={'media-slider-thumbnail-spinner-icon'} />
</span>
</>
</div>
<div className={'media-time-slider-preview-content'}>
<TimeSliderPrimitive.ChapterTitle className={'media-time-slider-chapter-title'} />
<TimeSliderPrimitive.Value className={'media-time-slider-value'} type="pointer" />
</div>
</TimeSliderPrimitive.Preview>
</TimeSliderPrimitive.Root>
);
}
type CaptionsButtonProps = Omit<CaptionsButtonPrimitive.Props, 'children'>;
function CaptionsButton({ className, ...props }: CaptionsButtonProps = {}) {
return (
<ButtonTooltip side="top">
<CaptionsButtonPrimitive
render={<Button />}
className={(state) => `media-captions-button ${resolveClassName(className, state)}`}
{...props}
>
<>
<span className="contents theme-minimal:hidden">
<CaptionsOffIconPrimitive className={'media-button-icon media-captions-button-off-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<CaptionsOffIconPrimitive2 className={'media-button-icon media-captions-button-off-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<CaptionsOnIconPrimitive className={'media-button-icon media-captions-button-on-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<CaptionsOnIconPrimitive2 className={'media-button-icon media-captions-button-on-icon'} />
</span>
</>
</CaptionsButtonPrimitive>
</ButtonTooltip>
);
}
interface SettingsMenuProps extends Menu.RootProps {
className?: string | undefined;
}
function SettingsMenu({ children, className, ...props }: SettingsMenuProps) {
return (
<Menu.Root side="top" align="center" {...props}>
<ButtonTooltip label={<TextPrimitive token={settingsText.key}>{settingsText.text}</TextPrimitive>} side="top">
<Menu.Trigger render={<Button />} className={'media-settings-menu-trigger'}>
<>
<span className="contents theme-minimal:hidden">
<GearIconPrimitive className={'media-button-icon media-settings-menu-trigger-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<GearIconPrimitive2 className={'media-button-icon media-settings-menu-trigger-icon'} />
</span>
</>
<TextPrimitive className={'media-settings-menu-trigger-label'} token={settingsText.key}>
{settingsText.text}
</TextPrimitive>
</Menu.Trigger>
</ButtonTooltip>
<Menu.Popup keepMounted className={(state) => `media-menu-popup ${resolveClassName(className, state)}`}>
<Menu.Content className={'media-menu-content'}>{children}</Menu.Content>
</Menu.Popup>
</Menu.Root>
);
}
type VideoSettingsMenuProps = Omit<NonNullable<ComponentProps<typeof SettingsMenu>>, 'children'>;
interface QualityMenuProps extends MenuProps {
className?: ClassValue;
}
interface MenuChevronProps {
back?: boolean;
className?: ClassValue;
}
function MenuChevron({ back = false, className }: MenuChevronProps = {}) {
return (
<>
<span className="contents theme-minimal:hidden">
<ChevronIconPrimitive
className={`${back ? 'media-menu-back-chevron' : 'media-menu-forward-chevron'} ${className ?? ''}`}
/>
</span>
<span className="hidden theme-minimal:contents">
<ChevronIconPrimitive2
className={`${back ? 'media-menu-back-chevron' : 'media-menu-forward-chevron'} ${className ?? ''}`}
/>
</span>
</>
);
}
type RadioItemProps = Menu.RadioItemProps;
function RadioItem({ children, className, ...props }: RadioItemProps) {
return (
<Menu.RadioItem className={(state) => `media-menu-radio-item ${resolveClassName(className, state)}`} {...props}>
{children}
<Menu.ItemIndicator forceMount className={'media-menu-item-indicator'}>
<>
<span className="contents theme-minimal:hidden">
<CheckIconPrimitive className={'media-menu-radio-item-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<CheckIconPrimitive2 className={'media-menu-radio-item-icon'} />
</span>
</>
</Menu.ItemIndicator>
</Menu.RadioItem>
);
}
function QualityMenu({ className, ...props }: QualityMenuProps = {}) {
return (
<Menu.Root {...props}>
<QualityRadioGroup.Root>
<Menu.Trigger className={'media-menu-trigger-item'}>
<>
<span className="contents theme-minimal:hidden">
<SwitchesIconPrimitive className={'media-menu-trigger-item-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<SwitchesIconPrimitive2 className={'media-menu-trigger-item-icon'} />
</span>
</>
<TextPrimitive token={qualityText.key}>{qualityText.text}</TextPrimitive>
<span className={'media-menu-hint'}>
<QualityRadioGroup.Value className={'media-menu-hint-label'} />
<MenuChevron />
</span>
</Menu.Trigger>
<Menu.Content className={(state) => `media-menu-content ${resolveClassName(className, state)}`}>
<Menu.Item className={'media-menu-back-item'}>
<MenuChevron back />
<TextPrimitive token={qualityText.key}>{qualityText.text}</TextPrimitive>
</Menu.Item>
<Menu.Separator className={'media-menu-separator'} />
<QualityRadioGroup.Options
className={'media-menu-radio-group'}
renderItem={(props, item) => (
<RadioItem {...props}>
<span>
<span>{item.label}</span>
{item.tier ? <sup className={'media-menu-tier'}>{item.tier}</sup> : null}
</span>
{item.badge ? <span className={'media-menu-badge'}>{item.badge}</span> : null}
</RadioItem>
)}
></QualityRadioGroup.Options>
</Menu.Content>
</QualityRadioGroup.Root>
</Menu.Root>
);
}
interface AudioTrackMenuProps extends MenuProps {
className?: ClassValue;
}
function AudioTrackMenu({ className, ...props }: AudioTrackMenuProps = {}) {
return (
<Menu.Root {...props}>
<AudioTrackRadioGroup.Root>
<Menu.Trigger className={'media-menu-trigger-item'}>
<>
<span className="contents theme-minimal:hidden">
<SpeechIconPrimitive className={'media-menu-trigger-item-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<SpeechIconPrimitive2 className={'media-menu-trigger-item-icon'} />
</span>
</>
<TextPrimitive token={audioText.key}>{audioText.text}</TextPrimitive>
<span className={'media-menu-hint'}>
<AudioTrackRadioGroup.Value className={'media-menu-hint-label'} />
<MenuChevron />
</span>
</Menu.Trigger>
<Menu.Content className={(state) => `media-menu-content ${resolveClassName(className, state)}`}>
<Menu.Item className={'media-menu-back-item'}>
<MenuChevron back />
<TextPrimitive token={audioText.key}>{audioText.text}</TextPrimitive>
</Menu.Item>
<Menu.Separator className={'media-menu-separator'} />
<AudioTrackRadioGroup.Options
className={'media-menu-radio-group'}
renderItem={(props, item) => (
<RadioItem {...props}>
<span>{item.label}</span>
</RadioItem>
)}
></AudioTrackRadioGroup.Options>
</Menu.Content>
</AudioTrackRadioGroup.Root>
</Menu.Root>
);
}
interface PlaybackRateSubmenuProps extends MenuProps {
className?: ClassValue;
}
function PlaybackRateSubmenu({ className, ...props }: PlaybackRateSubmenuProps = {}) {
return (
<Menu.Root {...props}>
<PlaybackRateRadioGroup.Root>
<Menu.Trigger className={'media-menu-trigger-item'}>
<>
<span className="contents theme-minimal:hidden">
<SpeedIconPrimitive className={'media-menu-trigger-item-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<SpeedIconPrimitive2 className={'media-menu-trigger-item-icon'} />
</span>
</>
<TextPrimitive token={speedText.key}>{speedText.text}</TextPrimitive>
<span className={'media-menu-hint'}>
<PlaybackRateRadioGroup.Value className={'media-menu-hint-label'} />
<MenuChevron />
</span>
</Menu.Trigger>
<Menu.Content className={(state) => `media-menu-content ${resolveClassName(className, state)}`}>
<Menu.Item className={'media-menu-back-item'}>
<MenuChevron back />
<TextPrimitive token={speedText.key}>{speedText.text}</TextPrimitive>
</Menu.Item>
<Menu.Separator className={'media-menu-separator'} />
<PlaybackRateRadioGroup.Options
className={'media-menu-radio-group'}
renderItem={(props, item) => (
<RadioItem {...props}>
<span>{item.label}</span>
</RadioItem>
)}
></PlaybackRateRadioGroup.Options>
</Menu.Content>
</PlaybackRateRadioGroup.Root>
</Menu.Root>
);
}
interface CaptionsSubmenuProps extends MenuProps {
className?: ClassValue;
}
function CaptionsSubmenu({ className, ...props }: CaptionsSubmenuProps = {}) {
return (
<Menu.Root {...props}>
<CaptionsRadioGroup.Root>
<Menu.Trigger className={'media-menu-trigger-item'}>
<>
<span className="contents theme-minimal:hidden">
<CaptionsOffIconPrimitive className={'media-menu-trigger-item-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<CaptionsOffIconPrimitive2 className={'media-menu-trigger-item-icon'} />
</span>
</>
<TextPrimitive token={captionsText.key}>{captionsText.text}</TextPrimitive>
<span className={'media-menu-hint'}>
<CaptionsRadioGroup.Value className={'media-menu-hint-label'} />
<MenuChevron />
</span>
</Menu.Trigger>
<Menu.Content className={(state) => `media-menu-content ${resolveClassName(className, state)}`}>
<Menu.Item className={'media-menu-back-item'}>
<MenuChevron back />
<TextPrimitive token={captionsText.key}>{captionsText.text}</TextPrimitive>
</Menu.Item>
<Menu.Separator className={'media-menu-separator'} />
<CaptionsRadioGroup.Options
className={'media-menu-radio-group'}
renderItem={(props, item) => (
<RadioItem {...props}>
<span>{item.label}</span>
</RadioItem>
)}
></CaptionsRadioGroup.Options>
</Menu.Content>
</CaptionsRadioGroup.Root>
</Menu.Root>
);
}
function VideoSettingsMenu(props: VideoSettingsMenuProps = {}) {
return (
<SettingsMenu {...props}>
<QualityMenu />
<AudioTrackMenu />
<PlaybackRateSubmenu />
<CaptionsSubmenu />
</SettingsMenu>
);
}
type CastButtonProps = Omit<CastButtonPrimitive.Props, 'children'>;
function CastButton({ className, ...props }: CastButtonProps = {}) {
return (
<ButtonTooltip side="top">
<CastButtonPrimitive
render={<Button />}
className={(state) => `media-cast-button ${resolveClassName(className, state)}`}
{...props}
>
<>
<span className="contents theme-minimal:hidden">
<CastEnterIconPrimitive className={'media-button-icon media-cast-button-enter-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<CastEnterIconPrimitive2 className={'media-button-icon media-cast-button-enter-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<CastExitIconPrimitive className={'media-button-icon media-cast-button-exit-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<CastExitIconPrimitive2 className={'media-button-icon media-cast-button-exit-icon'} />
</span>
</>
</CastButtonPrimitive>
</ButtonTooltip>
);
}
type AirPlayButtonProps = Omit<AirPlayButtonPrimitive.Props, 'children'>;
function AirPlayButton({ className, ...props }: AirPlayButtonProps = {}) {
return (
<ButtonTooltip side="top">
<AirPlayButtonPrimitive
render={<Button />}
className={(state) => `media-airplay-button ${resolveClassName(className, state)}`}
{...props}
>
<>
<span className="contents theme-minimal:hidden">
<AirPlayEnterIconPrimitive className={'media-button-icon media-airplay-button-enter-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<AirPlayEnterIconPrimitive2 className={'media-button-icon media-airplay-button-enter-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<AirPlayExitIconPrimitive className={'media-button-icon media-airplay-button-exit-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<AirPlayExitIconPrimitive2 className={'media-button-icon media-airplay-button-exit-icon'} />
</span>
</>
</AirPlayButtonPrimitive>
</ButtonTooltip>
);
}
type PiPButtonProps = Omit<PiPButtonPrimitive.Props, 'children'>;
function PiPButton({ className, ...props }: PiPButtonProps = {}) {
return (
<ButtonTooltip side="top">
<PiPButtonPrimitive
render={<Button />}
className={(state) => `media-pip-button ${resolveClassName(className, state)}`}
{...props}
>
<>
<span className="contents theme-minimal:hidden">
<PipEnterIconPrimitive className={'media-button-icon media-pip-button-enter-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<PipEnterIconPrimitive2 className={'media-button-icon media-pip-button-enter-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<PipExitIconPrimitive className={'media-button-icon media-pip-button-exit-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<PipExitIconPrimitive2 className={'media-button-icon media-pip-button-exit-icon'} />
</span>
</>
</PiPButtonPrimitive>
</ButtonTooltip>
);
}
type FullscreenButtonProps = Omit<FullscreenButtonPrimitive.Props, 'children'>;
function FullscreenButton({ className, ...props }: FullscreenButtonProps = {}) {
return (
<ButtonTooltip side="top">
<FullscreenButtonPrimitive
render={<Button />}
className={(state) => `media-fullscreen-button ${resolveClassName(className, state)}`}
{...props}
>
<>
<span className="contents theme-minimal:hidden">
<FullscreenEnterIconPrimitive className={'media-button-icon media-fullscreen-button-enter-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<FullscreenEnterIconPrimitive2 className={'media-button-icon media-fullscreen-button-enter-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<FullscreenExitIconPrimitive className={'media-button-icon media-fullscreen-button-exit-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<FullscreenExitIconPrimitive2 className={'media-button-icon media-fullscreen-button-exit-icon'} />
</span>
</>
</FullscreenButtonPrimitive>
</ButtonTooltip>
);
}
function DefaultVideoControls() {
return (
<Controls.Root>
<Controls.Backdrop className={'media-controls__backdrop'} />
<Controls.Content className={'media-controls media-controls'}>
<Tooltip.Provider>
<Controls.Group className={'media-controls-primary'}>
<PlayButton />
<VolumePopover className={'media-controls-volume-button'} />
<Controls.Group className={'media-time-slider-group'}>
<Time.Value className={'media-time-current-value'} type="current" />
<TimeSlider />
<Time.Value className={'media-time-remaining-value'} type="remaining" toggle />
</Controls.Group>
<CaptionsButton className={'media-controls-captions-button'} />
<VideoSettingsMenu className={'media-controls-settings-button'} />
</Controls.Group>
<Controls.Group className={'media-controls-secondary'}>
<CastButton />
<AirPlayButton />
<PiPButton />
<FullscreenButton />
</Controls.Group>
</Tooltip.Provider>
</Controls.Content>
</Controls.Root>
);
}
interface VideoHotkeysProps {
disabled?: boolean | undefined;
}
interface PlaybackHotkeysProps {
disabled?: boolean | undefined;
}
function PlaybackHotkeys({ disabled = false }: PlaybackHotkeysProps = {}) {
return (
<>
<Hotkey disabled={disabled} keys="Space" action="togglePaused" />
<Hotkey disabled={disabled} keys="k" action="togglePaused" />
<Hotkey disabled={disabled} keys="m" action="toggleMuted" />
<Hotkey disabled={disabled} keys="ArrowRight" action="seekStep" value={5} />
<Hotkey disabled={disabled} keys="ArrowLeft" action="seekStep" value={-5} />
<Hotkey disabled={disabled} keys="l" action="seekStep" value={10} />
<Hotkey disabled={disabled} keys="j" action="seekStep" value={-10} />
<Hotkey disabled={disabled} keys="ArrowUp" action="volumeStep" value={0.05} />
<Hotkey disabled={disabled} keys="ArrowDown" action="volumeStep" value={-0.05} />
<Hotkey disabled={disabled} keys="0-9" action="seekToPercent" />
<Hotkey disabled={disabled} keys="Home" action="seekToPercent" value={0} />
<Hotkey disabled={disabled} keys="End" action="seekToPercent" value={100} />
<Hotkey disabled={disabled} keys=">" action="speedUp" />
<Hotkey disabled={disabled} keys="<" action="speedDown" />
</>
);
}
function VideoHotkeys({ disabled = false }: VideoHotkeysProps = {}) {
return (
<>
<PlaybackHotkeys disabled={disabled} />
<Hotkey disabled={disabled} keys="f" action="toggleFullscreen" />
<Hotkey disabled={disabled} keys="c" action="toggleSubtitles" />
<Hotkey disabled={disabled} keys="i" action="togglePictureInPicture" />
</>
);
}
interface VideoGesturesProps {
disabled?: boolean | undefined;
}
function VideoGestures({ disabled = false }: VideoGesturesProps = {}) {
return (
<>
<Gesture disabled={disabled} type="tap" action="togglePaused" pointer="mouse" region="center" />
<Gesture disabled={disabled} type="tap" action="toggleControls" pointer="touch" />
<Gesture disabled={disabled} type="doubletap" action="seekStep" value={-10} region="left" />
<Gesture disabled={disabled} type="doubletap" action="toggleFullscreen" region="center" />
<Gesture disabled={disabled} type="doubletap" action="seekStep" value={10} region="right" />
</>
);
}
type VideoStatusIndicatorsProps = Omit<ComponentProps<'div'>, 'children'>;
type StatusAnnouncerProps = Omit<StatusAnnouncerPrimitive.Props, 'children'>;
function StatusAnnouncer({ className, ...props }: StatusAnnouncerProps = {}) {
return (
<StatusAnnouncerPrimitive
className={(state) => `media-status-announcer ${resolveClassName(className, state)}`}
{...props}
/>
);
}
type VolumeIndicatorProps = Omit<VolumeIndicatorPrimitive.RootProps, 'children'>;
function VolumeIndicator({ className, ...props }: VolumeIndicatorProps = {}) {
return (
<VolumeIndicatorPrimitive.Root
className={(state) => `media-volume-indicator ${resolveClassName(className, state)}`}
{...props}
>
<VolumeIndicatorPrimitive.Fill className={'media-volume-indicator-fill'}>
<>
<span className="contents theme-minimal:hidden">
<VolumeHighIconPrimitive className={'media-volume-indicator-high-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<VolumeHighIconPrimitive2 className={'media-volume-indicator-high-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<VolumeLowIconPrimitive className={'media-volume-indicator-low-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<VolumeLowIconPrimitive2 className={'media-volume-indicator-low-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<VolumeOffIconPrimitive className={'media-volume-indicator-off-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<VolumeOffIconPrimitive2 className={'media-volume-indicator-off-icon'} />
</span>
</>
<VolumeIndicatorPrimitive.Value className={'media-volume-indicator-value'} />
</VolumeIndicatorPrimitive.Fill>
</VolumeIndicatorPrimitive.Root>
);
}
type StatusIndicatorProps = Omit<StatusIndicatorPrimitive.RootProps, 'children'>;
const TOP_STATUS_ACTIONS = ['toggleSubtitles', 'toggleFullscreen', 'togglePictureInPicture'] as const;
function StatusIndicator({ className, ...props }: StatusIndicatorProps = {}) {
return (
<StatusIndicatorPrimitive.Root
actions={TOP_STATUS_ACTIONS}
className={(state) => `media-status-indicator ${resolveClassName(className, state)}`}
{...props}
>
<div className={'media-status-indicator-content'}>
<>
<span className="contents theme-minimal:hidden">
<CaptionsOnIconPrimitive className={'media-status-indicator-captions-on-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<CaptionsOnIconPrimitive2 className={'media-status-indicator-captions-on-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<CaptionsOffIconPrimitive className={'media-status-indicator-captions-off-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<CaptionsOffIconPrimitive2 className={'media-status-indicator-captions-off-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<FullscreenEnterIconPrimitive className={'media-status-indicator-fullscreen-enter-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<FullscreenEnterIconPrimitive2 className={'media-status-indicator-fullscreen-enter-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<FullscreenExitIconPrimitive className={'media-status-indicator-fullscreen-exit-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<FullscreenExitIconPrimitive2 className={'media-status-indicator-fullscreen-exit-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<PipEnterIconPrimitive className={'media-status-indicator-pip-enter-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<PipEnterIconPrimitive2 className={'media-status-indicator-pip-enter-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<PipExitIconPrimitive className={'media-status-indicator-pip-exit-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<PipExitIconPrimitive2 className={'media-status-indicator-pip-exit-icon'} />
</span>
</>
<StatusIndicatorPrimitive.Value className={'media-status-indicator-value'} />
</div>
</StatusIndicatorPrimitive.Root>
);
}
type SeekIndicatorProps = Omit<SeekIndicatorPrimitive.RootProps, 'children'>;
function SeekIndicator({ className, ...props }: SeekIndicatorProps = {}) {
return (
<SeekIndicatorPrimitive.Root
className={(state) => `media-seek-indicator ${resolveClassName(className, state)}`}
{...props}
>
<>
<span className="contents theme-minimal:hidden">
<ChevronIconPrimitive className={'media-seek-indicator-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<ChevronIconPrimitive2 className={'media-seek-indicator-icon'} />
</span>
</>
<SeekIndicatorPrimitive.Value className={'media-seek-indicator-value'} />
</SeekIndicatorPrimitive.Root>
);
}
type PlaybackStatusIndicatorProps = Omit<StatusIndicatorPrimitive.RootProps, 'children'>;
const PLAYBACK_STATUS_ACTIONS = ['togglePaused'] as const;
function PlaybackStatusIndicator({ className, ...props }: PlaybackStatusIndicatorProps = {}) {
return (
<StatusIndicatorPrimitive.Root
actions={PLAYBACK_STATUS_ACTIONS}
className={(state) => `media-playback-status-indicator ${resolveClassName(className, state)}`}
{...props}
>
<>
<span className="contents theme-minimal:hidden">
<PlayIconPrimitive className={'media-playback-status-indicator-play-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<PlayIconPrimitive2 className={'media-playback-status-indicator-play-icon'} />
</span>
</>
<>
<span className="contents theme-minimal:hidden">
<PauseIconPrimitive className={'media-playback-status-indicator-pause-icon'} />
</span>
<span className="hidden theme-minimal:contents">
<PauseIconPrimitive2 className={'media-playback-status-indicator-pause-icon'} />
</span>
</>
</StatusIndicatorPrimitive.Root>
);
}
function VideoStatusIndicators({ className, ...props }: VideoStatusIndicatorsProps = {}) {
return (
<>
<StatusAnnouncer />
<div className={`media-video-status-indicators ${className ?? ''}`} {...props}>
<VolumeIndicator />
<StatusIndicator />
<SeekIndicator />
<PlaybackStatusIndicator />
</div>
</>
);
}
function DefaultVideoSkin({ children, className, poster, ...props }: DefaultVideoSkinProps = {}) {
const isPosterString = typeof poster === 'string';
return (
<Container className={`media-skin media-skin--video ${className ?? ''}`} {...props}>
{children}
<Poster src={isPosterString ? poster : undefined}>{isPosterString ? undefined : poster}</Poster>
<BufferingIndicator />
<ErrorDialog />
<DefaultVideoControls />
<VideoHotkeys />
<VideoGestures />
<VideoStatusIndicators />
</Container>
);
}
const Skin = DefaultVideoSkin;
// ================================================================
// Player
// ================================================================
export interface VideoPlayerProps {
children?: ReactNode;
style?: CSSProperties;
className?: string;
renderPoster?: Poster.Props['render'];
}
export function VideoSkin({ renderPoster, ...props }: VideoSkinProps) {
return <Skin poster={renderPoster} {...props} />;
}
// ================================================================
// Components
// ================================================================
function Button({ className, ...props }: ButtonProps) {
return <button className={`media-button ${className ?? ''}`} {...props} />;
}
type SliderTrackProps = ComponentProps<'div'>;
function SliderTrack({ className, ...props }: SliderTrackProps) {
return <div className={`media-slider-track ${className ?? ''}`} {...props} />;
}
type SliderFillProps = ComponentProps<'div'>;
function SliderFill({ className, ...props }: SliderFillProps) {
return <div className={`media-slider-fill ${className ?? ''}`} {...props} />;
}
type SliderThumbProps = ComponentProps<'div'>;
function SliderThumb({ className, ...props }: SliderThumbProps) {
return <div className={`media-slider-thumb ${className ?? ''}`} {...props} />;
}
function VolumePopover({
className,
popupClassName,
showTooltip = false,
side = 'top',
orientation = 'vertical',
...props
}: VolumePopoverProps = {}) {
return (
<VolumePopoverPrimitive.Root openOnHover delay={200} closeDelay={100} side={side} {...props}>
<ButtonTooltip delay={0} disabled={!showTooltip} sticky side="top">
<VolumePopoverPrimitive.Trigger render={<MuteButton className={className} />} />
</ButtonTooltip>
<VolumePopoverPrimitive.Popup className={`media-volume-popover ${popupClassName}`}>
<VolumeSlider orientation={orientation} />
</VolumePopoverPrimitive.Popup>
</VolumePopoverPrimitive.Root>
);
}
type SliderBufferProps = ComponentProps<'div'>;
function SliderBuffer({ className, ...props }: SliderBufferProps) {
return <div className={`media-slider-buffer ${className ?? ''}`} {...props} />;
}
// ================================================================
// Error Dialog
// ================================================================
function ErrorDialog({ className, ...props }: ErrorDialogProps = {}) {
return (
<ErrorDialogPrimitive.Root>
<ErrorDialogPrimitive.Backdrop className={'media-dialog-backdrop'} />
<ErrorDialogPrimitive.Popup
className={(state) => `media-dialog-popup ${resolveClassName(className, state)}`}
{...props}
>
<div className={'media-dialog-content'}>
<ErrorDialogPrimitive.Title className={'media-dialog-title'} />
<ErrorDialogPrimitive.Description className={'media-dialog-description'} />
</div>
<div className={'media-dialog-actions'}>
<ErrorDialogPrimitive.Close render={<Button />} className={'media-dialog-close'} />
</div>
</ErrorDialogPrimitive.Popup>
</ErrorDialogPrimitive.Root>
);
}
import { createPlayer } from '@videojs/react';
import { videoFeatures } from '@videojs/react/video';
export const { Player } = createPlayer({ features: videoFeatures });
@layer base {
.media-skin {
--media-background: oklch(0% 0 0);
--media-foreground: oklch(100% 0 0);
--media-controls: oklch(0% 0 0 / .35);
--media-controls-foreground: var(--media-foreground);
--media-popover: oklch(100% 0 0 / .1);
--media-popover-foreground: var(--media-foreground);
--media-primary: var(--media-accent-color, var(--media-default-accent-color));
--media-primary-foreground: var(--media-accent-text-color, contrast-color(var(--media-accent-color, var(--media-default-accent-color))));
--media-accent: var(--media-accent-color, color-mix(in oklab, var(--media-default-accent-color) 10%, transparent));
--media-accent-foreground: var(--media-accent-text-color, contrast-color(var(--media-accent-color, var(--media-internal-accent-text-base, oklch(0% 0 0)))));
--media-muted: oklch(100% 0 0 / .15);
--media-muted-foreground: oklch(100% 0 0 / .65);
--media-border: oklch(0% 0 0 / .1);
--media-ring: var(--media-focus-ring-color, oklch(100% 0 0));
--media-shadow-sm: 0 1px 2px oklch(0% 0 0 / .15);
--media-caption-controls-y: calc(var(--media-spacing) * -14);
--media-control-corner-shape: round;
--media-control-radius: calc(infinity * 1px);
--media-control-size: calc(var(--media-spacing) * 9);
--media-controls-transition-duration: .1s;
--media-default-accent-color: oklch(100% 0 0);
--media-focus-ring-color: oklch(100% 0 0);
--media-menu-item-border-radius: calc(var(--media-spacing) * 2);
--media-menu-transition-duration: .25s;
--media-popup-translate-distance: calc(var(--media-scale-unit, 16px) * .5);
--media-video-border-radius: var(--media-border-radius, 28px);
--media-scale: 1;
--media-scrollbar-thumb-color: oklch(from currentColor l c h / .3);
--media-spacing: calc(var(--media-scale-unit, 16px) * var(--media-scale) / 4);
scrollbar-color: var(--media-scrollbar-thumb-color) transparent;
scrollbar-width: thin;
}
.media-skin::-webkit-scrollbar-thumb {
background: var(--media-scrollbar-thumb-color);
border-radius: 9999px;
}
.media-skin--minimal {
--media-caption-controls-y: calc(var(--media-spacing) * -18);
--media-control-corner-shape: squircle;
--media-control-radius: calc(var(--media-spacing) * 2);
--media-control-size: calc(var(--media-spacing) * 9.5);
--media-popover: oklch(0% 0 0 / .5);
--media-border: oklch(100% 0 0 / .1);
--media-shadow-sm: 0 1px 2px oklch(0% 0 0 / .2);
--media-menu-item-border-radius: calc(var(--media-spacing) * 1.5);
--media-popup-translate-distance: calc(var(--media-spacing) * 2);
--media-video-border-radius: var(--media-border-radius, 12px);
}
:is(.media-skin--audio, .media-skin--live-audio) {
--media-background: light-dark(oklch(100% 0 0), oklch(0% 0 0));
--media-foreground: light-dark(oklch(0% 0 0), oklch(100% 0 0));
--media-controls: light-dark(oklch(100% 0 0 / .5), oklch(0% 0 0 / .4));
--media-controls-foreground: var(--media-foreground);
--media-popover: var(--media-controls);
--media-popover-foreground: var(--media-foreground);
--media-primary: var(--media-accent-color, var(--media-foreground));
--media-primary-foreground: var(--media-accent-text-color, contrast-color(var(--media-primary)));
--media-border: light-dark(oklch(0% 0 0 / .1), oklch(100% 0 0 / .1));
--media-ring: var(--media-foreground);
--media-default-accent-color: light-dark(oklch(0% 0 0), oklch(100% 0 0));
--media-internal-accent-text-base: light-dark(oklch(100% 0 0), oklch(0% 0 0));
--media-focus-ring-color: light-dark(oklch(0% 0 0), oklch(100% 0 0));
}
:is(.media-skin--audio, .media-skin--live-audio).media-skin--minimal {
--media-controls: var(--media-background);
--media-popover: var(--media-background);
}
@media (pointer: fine) {
.media-skin:not([data-controls-visible]) {
--media-controls-transition-duration: .3s;
}
}
@media (pointer: coarse) {
.media-skin:not([data-controls-visible]) {
--media-controls-transition-duration: .15s;
}
}
@media (prefers-reduced-motion: reduce) {
.media-skin {
--media-controls-transition-duration: 50ms;
}
}
@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
.media-skin {
--media-scrollbar-thumb-color: oklch(from currentColor l c h / .8);
scrollbar-width: auto;
}
}
@scope (.media-skin) {
:scope, *, :before, :after {
box-sizing: border-box;
}
button {
font: inherit;
color: inherit;
text-transform: none;
letter-spacing: inherit;
appearance: none;
background: none;
margin: 0;
}
img, svg, media-icon {
max-width: 100%;
margin: 0;
display: block;
}
svg[fill="currentColor"] {
fill: currentColor;
}
svg[fill="none"] {
fill: none;
}
svg[stroke="currentColor"] {
stroke: currentColor;
}
video {
border-radius: inherit;
object-fit: var(--media-object-fit, contain);
object-position: var(--media-object-position, center);
width: 100%;
max-width: 100%;
height: 100%;
display: block;
}
media-icon > svg {
width: 100%;
height: 100%;
}
media-tooltip-group, media-dialog, media-alert-dialog, media-error-dialog, media-controls {
display: contents;
}
[hidden][hidden] {
display: none !important;
}
}
@media (prefers-reduced-motion: no-preference) {
.media-skin {
interpolate-size: allow-keywords;
}
}
}
@layer components {
@scope (.media-skin) {
:scope {
--media-caption-track-duration: var(--media-controls-transition-duration);
--media-caption-track-delay: 25ms;
--media-caption-track-y: calc(var(--media-spacing) * -2);
}
video::-webkit-media-text-track-container {
z-index: 1;
scale: .98;
translate: 0 var(--media-caption-track-y);
transition: translate var(--media-caption-track-duration) ease-out;
transition-delay: var(--media-caption-track-delay);
font-family: inherit;
}
:scope[data-controls-visible] {
--media-caption-track-y: var(--media-caption-controls-y);
}
@container media-root (width > 672px) {
:scope.media-skin--minimal[data-controls-visible] {
--media-caption-track-y: calc(var(--media-spacing) * -12);
}
}
}
@scope (.media-skin--video) {
.media-button {
width: var(--media-control-size);
height: var(--media-control-size);
min-height: calc(var(--media-spacing) * 0);
cursor: pointer;
touch-action: manipulation;
border-radius: var(--media-control-radius);
padding: calc(var(--media-spacing) * 0);
text-align: center;
color: inherit;
outline-offset: -2px;
will-change: scale;
-webkit-user-select: none;
user-select: none;
corner-shape: var(--media-control-corner-shape);
text-shadow: inherit;
background-color: #0000;
border-style: solid;
border-width: 0;
outline: 2px solid #0000;
flex-shrink: 0;
place-items: center;
transition-property: background-color, color, outline-offset, scale;
transition-duration: .15s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
display: grid;
}
@media (hover: hover) {
.media-button:not([aria-disabled="true"]):hover {
background-color: var(--media-accent);
color: var(--media-accent-foreground);
}
}
.media-button:focus-visible {
outline-offset: 2px;
outline-color: var(--media-focus-ring-color, white);
}
.media-button:not([aria-disabled="true"]):focus-visible {
background-color: var(--media-accent);
color: var(--media-accent-foreground);
}
.media-button:not([aria-disabled="true"]):active {
scale: .97;
}
.media-button[aria-disabled="true"] {
cursor: not-allowed;
opacity: .5;
}
.media-button:not([aria-disabled="true"])[aria-expanded="true"] {
background-color: var(--media-accent);
color: var(--media-accent-foreground);
}
@media (prefers-reduced-motion: reduce) {
.media-button {
will-change: auto;
transition-property: background-color, color;
scale: 1;
}
}
}
@scope (.media-skin--video) {
.media-menu-back-item {
margin-bottom: calc(var(--media-spacing) * .5);
cursor: pointer;
align-items: center;
gap: calc(var(--media-spacing) * 1.5);
border-radius: var(--media-menu-item-border-radius);
width: 100%;
padding-inline: calc(var(--media-spacing) * 2);
padding-block: calc(var(--media-spacing) * 1.5);
text-align: start;
white-space: nowrap;
outline-offset: -2px;
-webkit-user-select: none;
user-select: none;
text-shadow: 0 1px 0 var(--media-shadow-current-color);
outline: 2px solid #0000;
transition-property: background-color, color;
transition-duration: .1s;
transition-timing-function: ease-in-out;
display: flex;
position: relative;
}
@media (hover: hover) {
.media-menu-back-item:hover {
background-color: var(--media-accent);
color: var(--media-accent-foreground);
}
}
.media-menu-back-item:focus-visible {
outline-offset: 2px;
outline-color: #fff;
}
.media-menu-back-item[data-highlighted] {
background-color: var(--media-accent);
color: var(--media-accent-foreground);
}
@supports (top: anchor(top)) {
.media-menu-back-item {
transition-duration: 50ms;
}
@media (hover: hover) {
.media-menu-back-item:hover {
transition-duration: .2s;
}
}
.media-menu-back-item[data-highlighted] {
transition-duration: .2s;
}
}
@media (prefers-reduced-motion: reduce) {
.media-menu-back-item {
transition-duration: 50ms;
}
}
.media-menu-badge {
border-radius: var(--media-control-radius);
background-color: var(--media-accent);
padding-inline: calc(var(--media-spacing) * 1.5);
font-size: .7em;
font-weight: 600;
}
.media-menu-content {
max-height: inherit;
overscroll-behavior: none;
transition-property: translate, filter;
transition-duration: var(--media-menu-transition-duration);
anchor-scope: --media-menu-item-highlight-anchor;
outline-style: none;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
position: absolute;
overflow: auto;
}
.media-menu-content:not([data-submenu]) {
inset-inline: calc(var(--media-spacing) * 1);
top: calc(var(--media-spacing) * 1);
gap: calc(var(--media-spacing) * .5);
flex-direction: column;
display: flex;
}
.media-menu-content[data-submenu] {
inset-inline: calc(var(--media-spacing) * 0);
top: calc(var(--media-spacing) * 0);
z-index: 10;
max-height: inherit;
padding: calc(var(--media-spacing) * 1);
}
.media-menu-content[data-submenu][data-ending-style], .media-menu-content[data-submenu][data-starting-style] {
pointer-events: none;
filter: blur(8px);
overflow: hidden;
translate: 100%;
}
.media-menu-content:not([data-submenu])[data-child-open] {
filter: blur(8px);
translate: -100%;
}
.media-menu-content:not([data-submenu])[data-child-open]:before {
content: "";
display: none;
}
@supports (top: anchor(top)) {
.media-menu-content:before {
pointer-events: none;
inset: anchor(inside);
border-radius: var(--media-menu-item-border-radius);
background-color: var(--media-accent);
overflow-anchor: none;
content: "";
position-anchor: --media-menu-item-highlight-anchor;
transition-property: inset;
transition-duration: .1s;
transition-timing-function: ease-in-out;
position: absolute;
}
.media-menu-content:has([data-highlighted=""]):before {
content: "";
transition-duration: 0s;
}
}
.media-menu-content[data-submenu][data-ending-style]:dir(rtl), .media-menu-content[data-submenu][data-starting-style]:dir(rtl) {
translate: -100%;
}
.media-menu-content:not([data-submenu])[data-child-open]:dir(rtl) {
translate: 100%;
}
.media-menu-hint {
min-width: calc(var(--media-spacing) * 0);
align-items: center;
gap: calc(var(--media-spacing) * 1);
color: currentColor;
margin-inline-start: auto;
padding-inline-start: calc(var(--media-spacing) * 2);
display: inline-flex;
}
@supports (color: color-mix(in lab, red, red)) {
.media-menu-hint {
color: color-mix(in oklab, currentcolor 65.0%, transparent);
}
}
.media-menu-hint-label {
max-width: calc(var(--media-spacing) * 24);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.media-menu-radio-group {
max-height: inherit;
gap: calc(var(--media-spacing) * .5);
anchor-scope: --media-menu-item-highlight-anchor;
flex-direction: column;
display: flex;
}
@supports (top: anchor(top)) {
.media-menu-radio-group:before {
pointer-events: none;
inset: anchor(inside);
border-radius: var(--media-menu-item-border-radius);
background-color: var(--media-accent);
overflow-anchor: none;
content: "";
position-anchor: --media-menu-item-highlight-anchor;
transition-property: inset;
transition-duration: .1s;
transition-timing-function: ease-in-out;
position: absolute;
}
.media-menu-radio-group:has([data-highlighted=""]):before {
content: "";
transition-duration: 0s;
}
}
.media-menu-separator {
margin-block: calc(var(--media-spacing) * 1);
border-bottom-style: solid;
border-bottom-width: 1px;
border-color: var(--media-border);
display: block;
}
@media (prefers-contrast: more) {
.media-menu-separator {
border-color: oklab(100% 0 5.96046e-8 / .25);
}
}
@media (forced-colors: active) {
.media-menu-separator {
border-color: canvastext;
}
}
@media (prefers-reduced-transparency: reduce) {
.media-menu-separator {
border-color: oklab(100% 0 5.96046e-8 / .25);
}
}
.media-menu-tier {
color: currentColor;
padding-inline-start: calc(var(--media-spacing) * .5);
padding-top: 1px;
font-size: .7em;
font-weight: 600;
line-height: 1;
}
@supports (color: color-mix(in lab, red, red)) {
.media-menu-tier {
color: color-mix(in oklab, currentcolor 70.0%, transparent);
}
}
.media-menu-trigger-item {
cursor: pointer;
justify-content: space-between;
align-items: center;
gap: calc(var(--media-spacing) * 1.5);
border-radius: var(--media-menu-item-border-radius);
padding-inline: calc(var(--media-spacing) * 2);
padding-block: calc(var(--media-spacing) * 1.5);
text-align: start;
white-space: nowrap;
color: inherit;
font-variant-numeric: tabular-nums;
outline-offset: -2px;
-webkit-user-select: none;
user-select: none;
text-shadow: 0 1px 0 var(--media-shadow-current-color);
outline: 2px solid #0000;
transition-property: background-color, color;
transition-duration: .1s;
transition-timing-function: ease-in-out;
display: flex;
position: relative;
}
@media (hover: hover) {
.media-menu-trigger-item:hover {
background-color: var(--media-accent);
color: var(--media-accent-foreground);
}
}
.media-menu-trigger-item:focus-visible {
outline-offset: 2px;
outline-color: #fff;
}
.media-menu-trigger-item[aria-disabled="true"] {
pointer-events: none;
cursor: not-allowed;
opacity: .5;
}
.media-menu-trigger-item[data-highlighted] {
background-color: var(--media-accent);
color: var(--media-accent-foreground);
}
.media-menu-trigger-item[data-availability="unavailable"], .media-menu-trigger-item[data-availability="unsupported"] {
display: none;
}
@supports (top: anchor(top)) {
.media-menu-trigger-item {
transition-duration: 50ms;
}
@media (hover: hover) {
.media-menu-trigger-item:hover {
transition-duration: .2s;
}
}
.media-menu-trigger-item[data-highlighted] {
anchor-name: --media-menu-item-highlight-anchor;
background-color: #0000;
transition-duration: .2s;
}
}
@media (prefers-reduced-motion: reduce) {
.media-menu-trigger-item {
transition-duration: 50ms;
}
}
.media-menu-trigger-item-icon {
width: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
height: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
color: var(--media-muted-foreground);
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
flex-shrink: 0;
}
@media (hover: hover) {
@scope (.media-menu-trigger-item) {
&:hover .media-menu-trigger-item-icon {
color: inherit;
}
}
}
@scope (.media-menu-trigger-item) {
&[data-highlighted] .media-menu-trigger-item-icon {
color: inherit;
}
}
}
@scope (.media-skin--video) {
.media-tooltip {
margin: calc(var(--media-spacing) * 0);
background-color: var(--media-popover);
font-size: calc(var(--media-spacing) * 3.25);
white-space: nowrap;
color: var(--media-popover-foreground);
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 calc(1px + 0px) var(--media-border), 0 0 #0000;
box-shadow: var(--media-shadow-sm);
backdrop-filter: blur(16px) saturate(150%);
border-style: solid;
border-width: 0;
transition-property: opacity, filter, transform, scale;
transition-duration: .1s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
overflow: visible;
}
.media-tooltip:before {
pointer-events: auto;
content: "";
position: absolute;
}
.media-tooltip:after {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
content: "";
position: absolute;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff1a, inset 0 0 0 1px #ffffff0d;
}
.media-tooltip[data-ending-style] {
opacity: 0;
filter: blur(4px);
transition-duration: 50ms;
transform: none;
}
.media-tooltip[data-open] {
align-items: center;
gap: calc(var(--media-spacing) * 1);
display: flex;
}
.media-tooltip[data-starting-style] {
transform: translate(var(--media-popup-translate-x-distance, 0),var(--media-popup-translate-y-distance, 0));
opacity: 0;
filter: blur(4px);
}
.media-tooltip[data-side="bottom"] {
transform-origin: top;
--media-popup-translate-y-distance: calc(var(--media-popup-translate-distance) * -1);
}
.media-tooltip[data-side="bottom"]:before {
inset-inline: calc(var(--media-spacing) * 0);
content: "";
height: var(--media-tooltip-side-offset);
bottom: 100%;
}
.media-tooltip[data-side="left"] {
transform-origin: 100%;
--media-popup-translate-x-distance: var(--media-popup-translate-distance);
}
.media-tooltip[data-side="left"]:before {
inset-block: calc(var(--media-spacing) * 0);
content: "";
width: var(--media-tooltip-side-offset);
left: 100%;
}
.media-tooltip[data-side="right"] {
transform-origin: 0;
--media-popup-translate-x-distance: calc(var(--media-popup-translate-distance) * -1);
}
.media-tooltip[data-side="right"]:before {
inset-block: calc(var(--media-spacing) * 0);
content: "";
width: var(--media-tooltip-side-offset);
right: 100%;
}
.media-tooltip[data-side="top"] {
transform-origin: bottom;
--media-popup-translate-y-distance: var(--media-popup-translate-distance);
}
.media-tooltip[data-side="top"]:before {
inset-inline: calc(var(--media-spacing) * 0);
content: "";
height: var(--media-tooltip-side-offset);
top: 100%;
}
@media (prefers-reduced-motion: reduce) {
.media-tooltip {
transition-duration: 0s !important;
}
.media-tooltip[data-ending-style] {
filter: none !important;
transition-duration: 0s !important;
transform: none !important;
}
.media-tooltip[data-starting-style] {
filter: none !important;
transform: none !important;
}
}
@media (prefers-contrast: more) {
.media-tooltip {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-tooltip:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
@media (forced-colors: active) {
.media-tooltip {
color: canvastext;
background-color: canvas;
}
.media-tooltip:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px canvastext, inset 0 0 0 1px canvastext;
}
}
.media-tooltip:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
padding-inline: calc(var(--media-spacing) * 2.5);
padding-block: calc(var(--media-spacing) * 1);
border-radius: 9999px;
}
.media-tooltip:where(.media-skin--minimal, .media-skin--minimal *) {
border-radius: calc(var(--media-spacing) * 2);
padding-inline: calc(var(--media-spacing) * 2);
padding-block: calc(var(--media-spacing) * 1);
}
.media-tooltip:where(.media-skin--minimal, .media-skin--minimal *):after {
content: "";
display: none;
}
.media-tooltip:where(.media-skin--minimal, .media-skin--minimal *)[data-starting-style] {
filter: none;
}
.media-tooltip:is([data-starting-style], [data-ending-style]) {
scale: .95;
}
@media (prefers-reduced-motion: reduce) {
.media-tooltip:is([data-starting-style], [data-ending-style]) {
scale: 1 !important;
}
}
@media (prefers-reduced-transparency: reduce) {
.media-tooltip {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-tooltip:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
.media-tooltip-shortcut {
border-radius: calc(var(--media-spacing) * 1);
background-color: var(--media-muted);
text-align: center;
min-width: 1.5em;
font-family: inherit;
font-size: calc(var(--media-spacing) * 2.75);
padding: .1em;
font-weight: 600;
line-height: 1.25;
}
.media-tooltip-shortcut:where(.media-skin--minimal, .media-skin--minimal *) {
margin-inline-end: calc(var(--media-spacing) * -1);
}
}
@scope (.media-skin--video) {
.media-buffering-indicator {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
color: #fff;
place-content: center;
display: none;
position: absolute;
}
.media-buffering-indicator:not([data-visible]) {
--media-spinner-animation: none;
}
.media-buffering-indicator:before {
inset: calc(var(--media-spacing) * 0);
content: "";
backdrop-filter: blur(8px);
background-color: oklab(0% none none / .35);
position: absolute;
}
.media-buffering-indicator[data-visible] {
display: grid;
}
@media (prefers-reduced-motion: reduce) {
.media-buffering-indicator {
--media-spinner-animation: none;
}
}
.media-buffering-indicator-spinner-icon {
z-index: 30;
width: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
height: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
position: relative;
}
}
@scope (.media-skin--video) {
.media-volume-popover {
margin: calc(var(--media-spacing) * 0);
border-radius: var(--media-control-radius);
background-color: var(--media-popover);
padding-inline: calc(var(--media-spacing) * 0);
padding-block: calc(var(--media-spacing) * 3);
color: var(--media-popover-foreground);
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 calc(1px + 0px) var(--media-border), 0 0 #0000;
box-shadow: var(--media-shadow-sm);
backdrop-filter: blur(16px) saturate(150%);
border-style: solid;
border-width: 0;
transition-property: opacity, filter, transform, scale;
transition-duration: .1s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
overflow: visible;
}
.media-volume-popover:before {
pointer-events: auto;
content: "";
position: absolute;
}
.media-volume-popover:after {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
content: "";
position: absolute;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff1a, inset 0 0 0 1px #ffffff0d;
}
.media-volume-popover[data-ending-style] {
opacity: 0;
filter: blur(4px);
transition-duration: 50ms;
transform: none;
}
.media-volume-popover[data-starting-style] {
transform: translate(var(--media-popup-translate-x-distance, 0),var(--media-popup-translate-y-distance, 0));
opacity: 0;
filter: blur(4px);
}
.media-volume-popover[data-side="bottom"] {
transform-origin: top;
--media-popup-translate-y-distance: calc(var(--media-popup-translate-distance) * -1);
}
.media-volume-popover[data-side="bottom"]:before {
inset-inline: calc(var(--media-spacing) * 0);
content: "";
height: var(--media-popover-side-offset);
bottom: 100%;
}
.media-volume-popover[data-side="left"] {
transform-origin: 100%;
--media-popup-translate-x-distance: var(--media-popup-translate-distance);
}
.media-volume-popover[data-side="left"]:before {
inset-block: calc(var(--media-spacing) * 0);
content: "";
width: var(--media-popover-side-offset);
left: 100%;
}
.media-volume-popover[data-side="right"] {
transform-origin: 0;
padding: calc(var(--media-spacing) * 0);
padding-inline: calc(var(--media-spacing) * 3);
backdrop-filter: none;
--media-popover-side-offset: 0rem;
--media-popup-translate-x-distance: calc(var(--media-popup-translate-distance) * -1);
background-color: #0000;
border-radius: 0;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0, 0 0 #0000 !important;
}
.media-volume-popover[data-side="right"]:before {
inset-block: calc(var(--media-spacing) * 0);
content: "";
width: var(--media-popover-side-offset);
right: 100%;
}
.media-volume-popover[data-side="right"]:after {
content: "";
display: none;
}
.media-volume-popover[data-side="top"] {
transform-origin: bottom;
--media-popup-translate-y-distance: var(--media-popup-translate-distance);
}
.media-volume-popover[data-side="top"]:before {
inset-inline: calc(var(--media-spacing) * 0);
content: "";
height: var(--media-popover-side-offset);
top: 100%;
}
@media (prefers-reduced-motion: reduce) {
.media-volume-popover {
transition-duration: 0s !important;
}
.media-volume-popover[data-ending-style] {
filter: none !important;
transition-duration: 0s !important;
transform: none !important;
}
.media-volume-popover[data-starting-style] {
filter: none !important;
transform: none !important;
}
}
@media (prefers-contrast: more) {
.media-volume-popover {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-volume-popover:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
@media (forced-colors: active) {
.media-volume-popover {
color: canvastext;
background-color: canvas;
}
.media-volume-popover:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px canvastext, inset 0 0 0 1px canvastext;
}
}
.media-volume-popover:where(.media-skin--minimal, .media-skin--minimal *):after {
content: "";
display: none;
}
.media-volume-popover:where(.media-skin--minimal, .media-skin--minimal *)[data-starting-style] {
filter: none;
}
.media-volume-popover:is([data-starting-style], [data-ending-style]) {
scale: .95;
}
@media (prefers-reduced-motion: reduce) {
.media-volume-popover:is([data-starting-style], [data-ending-style]) {
scale: 1 !important;
}
}
@media (prefers-reduced-transparency: reduce) {
.media-volume-popover {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-volume-popover:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
}
@scope (.media-skin--video) {
.media-volume-indicator {
pointer-events: none;
transform-origin: top;
color: inherit;
position: absolute;
}
.media-volume-indicator[data-ending-style], .media-volume-indicator[data-starting-style] {
opacity: 0;
}
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
top: calc(var(--media-spacing) * 3);
background-color: oklab(0% none none / .25);
background-color: var(--media-popover);
width: min(80%, 12rem);
color: var(--media-popover-foreground);
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 calc(1px + 0px) var(--media-border), 0 0 #0000;
box-shadow: var(--media-shadow-sm);
backdrop-filter: blur(16px) saturate(150%);
border-radius: 9999px;
font-weight: 500;
transition-duration: .1s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
transform: translateX(0);
}
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
content: "";
position: absolute;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff1a, inset 0 0 0 1px #ffffff0d;
}
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-ending-style], .media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-starting-style] {
transition-duration: .25s;
transition-timing-function: cubic-bezier(.4, 0, 1, 1);
}
@media (prefers-reduced-motion: no-preference) {
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-ending-style] {
translate: 0 -25%;
}
}
@media (prefers-contrast: more) {
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
@media (forced-colors: active) {
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
color: canvastext;
background-color: canvas;
}
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px canvastext, inset 0 0 0 1px canvastext;
}
}
@media (pointer: coarse) {
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
will-change: scale,translate,opacity;
transition-property: scale, translate, opacity;
}
}
@media (pointer: fine) {
@media (prefers-reduced-motion: no-preference) {
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
will-change: scale,translate,filter,opacity;
transition-property: scale, translate, filter, opacity;
}
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-ending-style], .media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-starting-style] {
filter: blur(8px);
scale: .9;
}
}
}
.media-volume-indicator:where(.media-skin--minimal, .media-skin--minimal *) {
inset-inline: calc(var(--media-spacing) * 0);
top: calc(var(--media-spacing) * 0);
background-image: linear-gradient(to bottom,oklch(0% 0 0 / .35),oklch(0% 0 0 / .2) calc(var(--media-spacing) * 12),transparent);
padding-top: calc(var(--media-spacing) * 3);
padding-bottom: calc(var(--media-spacing) * 32);
text-shadow: 0 1px 0 var(--media-shadow-current-color);
justify-content: center;
transition-duration: .1s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
display: flex;
}
.media-volume-indicator:where(.media-skin--minimal, .media-skin--minimal *)[data-ending-style], .media-volume-indicator:where(.media-skin--minimal, .media-skin--minimal *)[data-starting-style] {
transition-duration: .4s;
transition-timing-function: cubic-bezier(.4, 0, 1, 1);
}
@media (prefers-reduced-motion: no-preference) {
.media-volume-indicator:where(.media-skin--minimal, .media-skin--minimal *)[data-ending-style] {
translate: 0 -100%;
}
}
@media (pointer: coarse) {
.media-volume-indicator:where(.media-skin--minimal, .media-skin--minimal *) {
will-change: translate,opacity;
transition-property: translate, opacity;
}
}
@media (pointer: fine) {
.media-volume-indicator:where(.media-skin--minimal, .media-skin--minimal *) {
will-change: translate,filter,opacity;
transition-property: translate, filter, opacity;
}
@media (prefers-reduced-motion: no-preference) {
.media-volume-indicator:where(.media-skin--minimal, .media-skin--minimal *)[data-ending-style], .media-volume-indicator:where(.media-skin--minimal, .media-skin--minimal *)[data-starting-style] {
filter: blur(8px);
}
}
}
@media (prefers-reduced-motion: no-preference) {
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):is([data-min], [data-max]):not([data-starting-style], [data-ending-style]) {
transition: transform .3s linear(0,-24 20.0%,16 40.0%,-8 60%,4 80.0%,1);
transform: translateX(.25px);
}
}
@media (prefers-reduced-transparency: reduce) {
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-volume-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
.media-volume-indicator-fill {
justify-content: space-between;
align-items: center;
gap: calc(var(--media-spacing) * 2);
border-radius: inherit;
padding-inline: calc(var(--media-spacing) * 2.5);
padding-block: calc(var(--media-spacing) * 1);
}
.media-volume-indicator-fill:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
background-image: linear-gradient(currentColor, currentColor);
background-size: var(--media-volume-fill, 0.0%) 100.0%;
background-position: 0;
background-repeat: no-repeat;
width: 100%;
transition-property: background-size;
transition-duration: .2s;
transition-timing-function: linear;
display: flex;
}
.media-volume-indicator-fill:where(.media-skin--minimal, .media-skin--minimal *) {
grid-template-columns: auto minmax(0, 1fr) auto;
width: min(80%, 14rem);
display: grid;
transform: translateX(0);
}
.media-volume-indicator-fill:where(.media-skin--minimal, .media-skin--minimal *):before {
height: calc(var(--media-spacing) * .75);
content: "";
width: 100%;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 1px 0 var(--media-shadow-subtle-current-color);
background-color: currentColor;
border-radius: 9999px;
grid-row-start: 1;
grid-column-start: 2;
}
@supports (color: color-mix(in lab, red, red)) {
.media-volume-indicator-fill:where(.media-skin--minimal, .media-skin--minimal *):before {
background-color: color-mix(in oklab, currentcolor 20.0%, transparent);
}
}
.media-volume-indicator-fill:where(.media-skin--minimal, .media-skin--minimal *):after {
height: calc(var(--media-spacing) * .75);
width: var(--media-volume-fill, 0.0%);
background-color: var(--media-primary);
content: "";
border-radius: 9999px;
grid-row-start: 1;
grid-column-start: 2;
justify-self: flex-start;
transition-property: width;
transition-duration: .2s;
transition-timing-function: linear;
}
@media (prefers-reduced-motion: no-preference) {
@scope (.media-volume-indicator) {
&:is([data-min], [data-max]):not([data-starting-style], [data-ending-style]) .media-volume-indicator-fill:where(.media-skin--minimal, .media-skin--minimal *) {
transition: transform .3s linear(0,-24 20.0%,16 40.0%,-8 60%,4 80.0%,1);
transform: translateX(.25px);
}
}
}
@media (prefers-contrast: more) {
.media-volume-indicator-fill:where(.media-skin--minimal, .media-skin--minimal *) {
border-radius: calc(var(--media-spacing) * 2);
background-color: #000;
}
}
@media (prefers-reduced-transparency: reduce) {
.media-volume-indicator-fill:where(.media-skin--minimal, .media-skin--minimal *) {
border-radius: calc(var(--media-spacing) * 2);
background-color: #000;
}
}
.media-volume-indicator-high-icon {
flex-shrink: 0;
display: none;
}
@scope (.media-volume-indicator) {
&[data-level="high"] .media-volume-indicator-high-icon {
display: block;
}
}
.media-volume-indicator-high-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
mix-blend-mode: difference;
}
.media-volume-indicator-high-icon:where(.media-skin--minimal, .media-skin--minimal *) {
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
grid-row-start: 1;
grid-column-start: 1;
}
.media-volume-indicator-low-icon {
flex-shrink: 0;
display: none;
}
@scope (.media-volume-indicator) {
&[data-level="low"] .media-volume-indicator-low-icon {
display: block;
}
}
.media-volume-indicator-low-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
mix-blend-mode: difference;
}
.media-volume-indicator-low-icon:where(.media-skin--minimal, .media-skin--minimal *) {
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
grid-row-start: 1;
grid-column-start: 1;
}
.media-volume-indicator-off-icon {
flex-shrink: 0;
display: none;
}
@scope (.media-volume-indicator) {
&[data-level="off"] .media-volume-indicator-off-icon {
display: block;
}
}
.media-volume-indicator-off-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
mix-blend-mode: difference;
}
.media-volume-indicator-off-icon:where(.media-skin--minimal, .media-skin--minimal *) {
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
grid-row-start: 1;
grid-column-start: 1;
}
.media-volume-indicator-value:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
mix-blend-mode: difference;
margin-left: auto;
}
.media-volume-indicator-value:where(.media-skin--minimal, .media-skin--minimal *) {
grid-row-start: 1;
grid-column-start: 3;
}
}
@scope (.media-skin--video) {
.media-slider {
cursor: pointer;
border-radius: 99px;
outline-style: none;
flex: 1;
justify-content: center;
align-items: center;
display: flex;
position: relative;
}
.media-slider[data-orientation="horizontal"] {
height: var(--media-slider-height, calc(var(--media-spacing) * 8));
min-width: calc(var(--media-spacing) * 20);
}
.media-slider[data-orientation="vertical"] {
height: calc(var(--media-spacing) * 20);
width: calc(var(--media-spacing) * 8);
min-width: calc(var(--media-spacing) * 0);
}
.media-volume-slider-thumb {
width: calc(var(--media-spacing) * 3);
height: calc(var(--media-spacing) * 3);
opacity: 1;
scale: 1;
}
.media-volume-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
outline-offset: -4px;
outline: 4px solid #0000;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 1px #0000001a, 0 1px 3px #00000059, 0 1px 2px -1px #00000059;
}
.media-volume-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
pointer-events: none;
inset: calc(var(--media-spacing) * -1);
border-radius: inherit;
opacity: 0;
content: "";
position: absolute;
scale: .5;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 2px;
}
@media (hover: hover) {
.media-volume-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):hover {
outline-offset: 0px;
outline-color: currentColor;
}
@supports (color: color-mix(in lab, red, red)) {
.media-volume-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):hover {
outline-color: color-mix(in oklab, currentcolor 15%, transparent);
}
}
}
.media-volume-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):focus-visible {
outline-offset: 0px;
outline-color: currentColor;
}
@supports (color: color-mix(in lab, red, red)) {
.media-volume-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):focus-visible {
outline-color: color-mix(in oklab, currentcolor 15%, transparent);
}
}
.media-volume-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):focus-visible:after {
content: "";
opacity: 1;
scale: 1;
}
@media (prefers-reduced-motion: no-preference) {
.media-volume-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
content: "";
transition-property: opacity, scale;
transition-duration: .15s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
}
.media-volume-slider-thumb:where(.media-skin--minimal, .media-skin--minimal *) {
outline-offset: -2px;
outline: 2px solid #0000;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 1px #00000026, 0 1px 3px #00000026, 0 1px 2px -1px #00000026;
}
.media-volume-slider-thumb:where(.media-skin--minimal, .media-skin--minimal *):focus-visible {
outline-offset: 2px;
outline-color: #fff;
}
}
@scope (.media-skin--video) {
.media-controls {
padding: calc(var(--media-spacing) * 1);
color: #fff;
transition-property: filter, opacity, scale, translate;
transition-duration: calc(var(--media-controls-transition-duration) / 2);
--media-popover-boundary-offset: .75rem;
--media-popover-side-offset: calc(var(--media-spacing) * 3);
--media-tooltip-boundary-offset: var(--media-popover-boundary-offset);
--media-tooltip-side-offset: var(--media-popover-side-offset);
text-shadow: 0 1px 0 var(--media-shadow-current-color);
transition-timing-function: cubic-bezier(0, 0, .2, 1);
display: contents;
}
@container media-root (width >= 32rem) {
.media-controls {
inset-inline: calc(var(--media-spacing) * 2);
bottom: calc(var(--media-spacing) * 2);
z-index: 10;
border-radius: var(--media-control-radius);
background-color: var(--media-popover);
color: var(--media-popover-foreground);
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 calc(1px + 0px) var(--media-border), 0 0 #0000;
box-shadow: var(--media-shadow-sm);
backdrop-filter: blur(16px) saturate(150%);
align-items: center;
display: flex;
position: absolute;
}
.media-controls:not([data-visible]) {
pointer-events: none;
opacity: 0;
transition-duration: var(--media-controls-transition-duration);
}
.media-controls:after {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
content: "";
position: absolute;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff1a, inset 0 0 0 1px #ffffff0d;
}
@media (prefers-reduced-motion: no-preference) {
.media-controls:not([data-visible]) {
translate: 0 calc(var(--media-spacing) * 1);
scale: .95;
}
}
@media (prefers-contrast: more) {
.media-controls {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-controls:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
}
@container media-root (width >= 42rem) {
.media-controls {
inset-inline: calc(var(--media-spacing) * 3);
bottom: calc(var(--media-spacing) * 3);
}
}
@container media-root (width >= 32rem) {
@media (forced-colors: active) {
.media-controls {
color: canvastext;
background-color: canvas;
}
.media-controls:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px canvastext, inset 0 0 0 1px canvastext;
}
}
@media (pointer: fine) {
@media (prefers-reduced-motion: no-preference) {
.media-controls:not([data-visible]) {
filter: blur(8px);
}
}
}
@media (prefers-reduced-transparency: reduce) {
.media-controls {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-controls:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
}
.media-controls__backdrop {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
transition-property: opacity;
transition-duration: var(--media-controls-transition-duration);
background-image: linear-gradient(to top, oklab(0% none none / .5) 0%, oklab(0% none none / .3) 25%, #0000 100%);
transition-timing-function: cubic-bezier(0, 0, .2, 1);
position: absolute;
}
.media-controls__backdrop:not([data-visible]) {
opacity: 0;
}
@container media-root (width < 32rem) {
.media-controls-captions-button {
display: none;
}
}
.media-controls-primary {
inset-inline: calc(var(--media-spacing) * 2);
bottom: calc(var(--media-spacing) * 2);
z-index: 10;
transform-origin: bottom;
border-radius: var(--media-control-radius);
background-color: var(--media-popover);
padding: calc(var(--media-spacing) * 1);
color: var(--media-popover-foreground);
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 calc(1px + 0px) var(--media-border), 0 0 #0000;
box-shadow: var(--media-shadow-sm);
backdrop-filter: blur(16px) saturate(150%);
transition-property: filter, opacity, scale, translate;
transition-duration: calc(var(--media-controls-transition-duration) / 2);
align-items: center;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
display: flex;
position: absolute;
}
.media-controls-primary:after {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
content: "";
position: absolute;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff1a, inset 0 0 0 1px #ffffff0d;
}
@media (prefers-contrast: more) {
.media-controls-primary {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-controls-primary:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
@container media-root (width < 32rem) {
@scope (.media-controls) {
&:not([data-visible]) .media-controls-primary {
pointer-events: none;
opacity: 0;
transition-duration: var(--media-controls-transition-duration);
}
}
@media (prefers-reduced-motion: no-preference) {
@scope (.media-controls) {
&:not([data-visible]) .media-controls-primary {
translate: 0 calc(var(--media-spacing) * 1);
scale: .95;
}
}
}
}
@container media-root (width >= 32rem) {
.media-controls-primary {
backdrop-filter: none;
background-color: #0000;
border-radius: 0;
display: contents;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0, 0 0 #0000;
}
.media-controls-primary:after {
content: "";
display: none;
}
}
@media (forced-colors: active) {
.media-controls-primary {
color: canvastext;
background-color: canvas;
}
.media-controls-primary:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px canvastext, inset 0 0 0 1px canvastext;
}
}
@container media-root (width < 32rem) {
@media (pointer: fine) {
@media (prefers-reduced-motion: no-preference) {
@scope (.media-controls) {
&:not([data-visible]) .media-controls-primary {
filter: blur(8px);
}
}
}
}
}
@media (prefers-reduced-transparency: reduce) {
.media-controls-primary {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-controls-primary:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
.media-controls-secondary {
top: calc(var(--media-spacing) * 2);
right: calc(var(--media-spacing) * 2);
z-index: 10;
transform-origin: top;
border-radius: var(--media-control-radius);
background-color: var(--media-popover);
padding: calc(var(--media-spacing) * 1);
color: var(--media-popover-foreground);
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 calc(1px + 0px) var(--media-border), 0 0 #0000;
box-shadow: var(--media-shadow-sm);
backdrop-filter: blur(16px) saturate(150%);
transition-property: filter, opacity, scale, translate;
transition-duration: calc(var(--media-controls-transition-duration) / 2);
align-items: center;
gap: 1px;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
display: flex;
position: absolute;
}
.media-controls-secondary:after {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
content: "";
position: absolute;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff1a, inset 0 0 0 1px #ffffff0d;
}
@media (prefers-contrast: more) {
.media-controls-secondary {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-controls-secondary:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
@container media-root (width < 32rem) {
@scope (.media-controls) {
&:not([data-visible]) .media-controls-secondary {
pointer-events: none;
opacity: 0;
transition-duration: var(--media-controls-transition-duration);
}
}
@media (prefers-reduced-motion: no-preference) {
@scope (.media-controls) {
&:not([data-visible]) .media-controls-secondary {
translate: 0 calc(var(--media-spacing) * -1);
scale: .95;
}
}
}
}
@container media-root (width >= 32rem) {
.media-controls-secondary {
padding: calc(var(--media-spacing) * 0);
backdrop-filter: none;
background-color: #0000;
border-radius: 0;
display: flex;
position: static;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0, 0 0 #0000;
}
.media-controls-secondary:after {
content: "";
display: none;
}
}
@media (forced-colors: active) {
.media-controls-secondary {
color: canvastext;
background-color: canvas;
}
.media-controls-secondary:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px canvastext, inset 0 0 0 1px canvastext;
}
}
@container media-root (width < 32rem) {
@media (pointer: fine) {
@media (prefers-reduced-motion: no-preference) {
@scope (.media-controls) {
&:not([data-visible]) .media-controls-secondary {
filter: blur(8px);
}
}
}
}
}
@media (prefers-reduced-transparency: reduce) {
.media-controls-secondary {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-controls-secondary:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
@container media-root (width >= 32rem) {
.media-controls-settings-button {
margin-inline-start: 1px;
}
}
.media-controls-volume-button {
margin-inline-start: 1px;
}
.media-time-current-value {
font-variant-numeric: tabular-nums;
}
.media-time-remaining-value {
cursor: pointer;
font-variant-numeric: tabular-nums;
outline-offset: -2px;
border-radius: .25rem;
outline: 2px solid #0000;
transition-property: outline-color, outline-offset;
transition-duration: .1s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
.media-time-remaining-value:focus-visible {
outline-offset: 2px;
outline-color: #fff;
}
@container media-time (width < 16rem) {
.media-time-remaining-value {
display: none;
}
}
.media-time-slider-group {
align-items: center;
gap: calc(var(--media-spacing) * 2.5);
padding-inline: calc(var(--media-spacing) * 2);
flex: 1;
display: flex;
container: media-time / inline-size;
}
@container media-root (width >= 32rem) {
.media-time-slider-group {
padding-inline: calc(var(--media-spacing) * 3);
}
}
}
@scope (.media-skin--video) {
.media-button-icon {
width: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
height: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
grid-row-start: 1;
grid-column-start: 1;
transition-property: opacity, scale;
transition-duration: .15s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
@media (prefers-reduced-motion: reduce) {
.media-button-icon {
transition-property: opacity;
transition-duration: 50ms;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
}
}
.media-cast-button-enter-icon {
opacity: 0;
}
@scope (.media-cast-button) {
&:not([data-cast-state="connected"]) .media-cast-button-enter-icon {
opacity: 1;
scale: 1;
}
}
.media-cast-button-exit-icon {
opacity: 0;
}
@scope (.media-cast-button) {
&[data-cast-state="connected"] .media-cast-button-exit-icon {
opacity: 1;
scale: 1;
}
}
}
@scope (.media-skin--video) {
.media-slider-preview {
height: calc(var(--media-spacing) * 1);
--media-slider-preview-max-height: var(--media-slider-preview-max-width);
position: relative;
}
.media-slider-preview:before {
pointer-events: none;
z-index: 1;
content: "";
opacity: 0;
position: absolute;
translate: -50% -50%;
scale: .5;
}
.media-slider-preview[data-pointing]:not([data-dragging]):before {
content: "";
opacity: 1;
scale: 1;
}
@media (prefers-reduced-motion: no-preference) {
.media-slider-preview:before {
content: "";
transition-property: opacity, scale;
transition-duration: .2s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
}
.media-slider-preview:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
min-width: var(--media-slider-preview-max-width);
--media-slider-preview-max-width: min(calc(var(--media-spacing) * 36), 100cqi);
}
.media-slider-preview:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):before {
width: calc(var(--media-spacing) * 1);
height: calc(var(--media-spacing) * 1);
border-radius: var(--media-control-radius);
content: "";
background-color: currentColor;
top: 50%;
left: 50%;
}
@container media-root (width >= 42rem) {
.media-slider-preview:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
--media-slider-preview-max-width: min(calc(var(--media-spacing) * 48), 100cqi);
}
}
.media-slider-preview:where(.media-skin--minimal, .media-skin--minimal *) {
--media-preview-end-inset: calc(100cqi - 100.0%);
--media-preview-left: clamp(calc(var(--media-slider-preview-max-width) / 2), var(--media-slider-pointer), calc(100.0% - var(--media-slider-preview-max-width) / 2 + var(--media-preview-end-inset)));
--media-slider-preview-max-width: min(calc(var(--media-spacing) * 28), 100cqi);
min-width: 100%;
}
.media-slider-preview:where(.media-skin--minimal, .media-skin--minimal *):before {
content: "";
background-color: currentColor;
}
@supports (color: color-mix(in lab, red, red)) {
.media-slider-preview:where(.media-skin--minimal, .media-skin--minimal *):before {
background-color: color-mix(in oklab, currentcolor 35.0%, transparent);
}
}
.media-slider-preview:where(.media-skin--minimal, .media-skin--minimal *)[data-orientation="horizontal"]:before {
top: 50%;
left: var(--media-slider-pointer);
height: calc(var(--media-spacing) * 5);
content: "";
width: 1px;
}
.media-slider-preview:where(.media-skin--minimal, .media-skin--minimal *)[data-orientation="vertical"]:before {
top: calc(100.0% - var(--media-slider-pointer));
content: "";
height: 1px;
width: calc(var(--media-spacing) * 5);
left: 50%;
}
@container media-root (width >= 32rem) {
.media-slider-preview:where(.media-skin--minimal, .media-skin--minimal *) {
--media-slider-preview-max-width: min(calc(var(--media-spacing) * 36), 100cqi);
}
}
@container media-root (width >= 42rem) {
.media-slider-preview:where(.media-skin--minimal, .media-skin--minimal *) {
--media-preview-left: var(--media-slider-pointer);
--media-slider-preview-max-width: min(calc(var(--media-spacing) * 48), 100cqi);
}
}
.media-slider-thumbnail {
pointer-events: none;
max-width: var(--media-slider-preview-max-width);
transform-origin: bottom;
translate: -50.0% calc(var(--media-spacing) * 2);
background-color: var(--media-popover);
color: var(--media-popover-foreground);
opacity: 0;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 calc(1px + 0px) var(--media-border), 0 0 #0000;
box-shadow: var(--media-shadow-sm);
filter: blur(8px);
backdrop-filter: blur(16px) saturate(150%);
position: absolute;
overflow: hidden;
scale: .8;
}
:where(.media-slider):has(:focus-visible) .media-slider-thumbnail, :where(.media-slider-preview)[data-pointing] .media-slider-thumbnail {
opacity: 1;
filter: none;
scale: 1;
}
.media-slider-thumbnail:after {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
content: "";
position: absolute;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff1a, inset 0 0 0 1px #ffffff0d;
}
.media-slider-thumbnail:has([data-loading]) {
aspect-ratio: 16 / 9;
width: var(--media-slider-preview-max-width);
}
@media (prefers-reduced-motion: no-preference) {
.media-slider-thumbnail {
transition-property: filter, opacity, scale;
transition-duration: .15s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
}
@media (prefers-contrast: more) {
.media-slider-thumbnail {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-slider-thumbnail:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
@media (forced-colors: active) {
.media-slider-thumbnail {
color: canvastext;
background-color: canvas;
}
.media-slider-thumbnail:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px canvastext, inset 0 0 0 1px canvastext;
}
}
.media-slider-thumbnail:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
bottom: calc(100.0% + calc(var(--media-spacing) * 9));
background-color: oklab(0% none none / .9);
border-radius: .75rem;
left: 50%;
}
.media-slider-thumbnail:where(.media-skin--minimal, .media-skin--minimal *) {
bottom: calc(100.0% + calc(var(--media-spacing) * 14));
left: var(--media-preview-left, var(--media-slider-pointer));
background-color: oklab(0% none none / .9);
border-radius: .5rem;
}
.media-slider-thumbnail:where(.media-skin--minimal, .media-skin--minimal *):after {
content: "";
display: none;
}
@media (prefers-reduced-transparency: reduce) {
.media-slider-thumbnail {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-slider-thumbnail:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
.media-slider-thumbnail-image {
max-height: var(--media-slider-preview-max-height);
max-width: var(--media-slider-preview-max-width);
border-radius: inherit;
transition-property: opacity;
transition-duration: .15s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
display: block;
position: relative;
overflow: clip;
}
.media-slider-thumbnail-image[data-loading] {
opacity: 0;
}
@media (prefers-reduced-motion: reduce) {
.media-slider-thumbnail-image {
transition-duration: 50ms;
}
}
.media-slider-thumbnail-spinner-icon {
width: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
height: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
opacity: 0;
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
transition-property: opacity;
transition-duration: .15s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
}
@scope (.media-slider-thumbnail) {
&:not(:has([role="img"][data-loading])) .media-slider-thumbnail-spinner-icon {
--media-spinner-animation: none;
}
}
@scope (.media-slider-thumbnail) {
&:has([role="img"][data-loading]) .media-slider-thumbnail-spinner-icon {
opacity: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.media-slider-thumbnail-spinner-icon {
--media-spinner-animation: none;
}
}
.media-time-slider-chapter {
inset: calc(var(--media-spacing) * 0);
min-height: calc(var(--media-spacing) * 0);
min-width: calc(var(--media-spacing) * 0);
--media-chapter-inset-end: .5;
--media-chapter-inset-start: .5;
justify-content: center;
align-items: center;
display: flex;
position: absolute;
}
.media-time-slider-chapter:first-child {
--media-chapter-inset-start: 0;
}
.media-time-slider-chapter:last-child {
--media-chapter-inset-end: 0;
}
.media-time-slider-chapter[data-orientation="horizontal"] {
clip-path: inset(0 calc(100.0% - var(--media-slider-chapter-end)) 0 var(--media-slider-chapter-start));
}
.media-time-slider-chapter[data-orientation="vertical"] {
clip-path: inset(calc(100.0% - var(--media-slider-chapter-end)) 0 var(--media-slider-chapter-start) 0);
}
.media-time-slider-chapter-title {
max-width: var(--media-slider-preview-max-width);
min-width: calc(var(--media-spacing) * 0);
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.media-time-slider-chapter-title:empty {
display: none;
}
.media-time-slider-chapter-title:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
padding-inline: calc(var(--media-spacing) * 6);
}
.media-time-slider-chapter-track[data-orientation="horizontal"] {
clip-path: inset(0 calc(100.0% - var(--media-slider-chapter-end) + var(--media-spacing) * var(--media-chapter-inset-end)) 0 calc(var(--media-slider-chapter-start) + var(--media-spacing) * var(--media-chapter-inset-start)) round var(--media-control-radius));
}
@scope (.media-time-slider-chapter) {
&[data-highlighted] .media-time-slider-chapter-track[data-orientation="horizontal"] {
height: calc(var(--media-spacing) * 1.75);
}
}
.media-time-slider-chapter-track[data-orientation="vertical"] {
clip-path: inset(calc(100.0% - var(--media-slider-chapter-end) + var(--media-spacing) * var(--media-chapter-inset-end)) 0 calc(var(--media-slider-chapter-start) + var(--media-spacing) * var(--media-chapter-inset-start)) 0 round var(--media-control-radius));
}
@scope (.media-time-slider-chapter) {
&[data-highlighted] .media-time-slider-chapter-track[data-orientation="vertical"] {
width: calc(var(--media-spacing) * 1.75);
}
}
@media (prefers-reduced-motion: no-preference) {
.media-time-slider-chapter-track {
transition-property: height, width;
transition-duration: .2s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
}
.media-time-slider-chapters {
width: 100%;
height: 100%;
min-height: calc(var(--media-spacing) * 0);
min-width: calc(var(--media-spacing) * 0);
border-radius: inherit;
flex: 1;
align-items: center;
display: flex;
position: relative;
}
.media-time-slider-preview-content {
max-width: var(--media-slider-preview-max-width);
transform-origin: bottom;
translate: -50.0% calc(var(--media-spacing) * 2);
font-variant-numeric: tabular-nums;
opacity: 0;
filter: blur(8px);
display: flex;
position: absolute;
scale: .8;
}
:where(.media-slider):has(:focus-visible) .media-time-slider-preview-content, :where(.media-slider-preview)[data-pointing] .media-time-slider-preview-content {
opacity: 1;
filter: none;
scale: 1;
}
@media (prefers-reduced-motion: no-preference) {
.media-time-slider-preview-content {
transition-property: filter, opacity, scale;
transition-duration: .15s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
}
.media-time-slider-preview-content:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
bottom: calc(100.0% + calc(var(--media-spacing) * 12.5));
flex-direction: column;
align-items: center;
left: 50%;
}
.media-time-slider-preview-content:where(.media-skin--minimal, .media-skin--minimal *) {
bottom: calc(100.0% + calc(var(--media-spacing) * 7));
left: var(--media-preview-left, var(--media-slider-pointer));
justify-content: center;
gap: calc(var(--media-spacing) * 2);
padding-inline: calc(var(--media-spacing) * 3);
flex-direction: row-reverse;
}
.media-time-slider-thumb {
width: calc(var(--media-spacing) * 3);
height: calc(var(--media-spacing) * 3);
opacity: 0;
}
.media-time-slider-thumb:focus-visible, .media-time-slider-thumb[data-interactive] {
opacity: 1;
}
@media (pointer: fine) {
@media (hover: hover) {
@scope (.media-slider) {
&:hover .media-time-slider-thumb {
opacity: 1;
scale: 1;
}
}
}
}
.media-time-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
outline-offset: -4px;
outline: 4px solid #0000;
scale: .8;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 1px #0000001a, 0 1px 3px #00000059, 0 1px 2px -1px #00000059;
}
.media-time-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
pointer-events: none;
inset: calc(var(--media-spacing) * -1);
border-radius: inherit;
opacity: 0;
content: "";
position: absolute;
scale: .5;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 2px;
}
@media (hover: hover) {
.media-time-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):hover {
outline-offset: 0px;
outline-color: currentColor;
}
@supports (color: color-mix(in lab, red, red)) {
.media-time-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):hover {
outline-color: color-mix(in oklab, currentcolor 15%, transparent);
}
}
}
.media-time-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):focus-visible {
outline-offset: 0px;
outline-color: currentColor;
}
@supports (color: color-mix(in lab, red, red)) {
.media-time-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):focus-visible {
outline-color: color-mix(in oklab, currentcolor 15%, transparent);
}
}
.media-time-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):focus-visible:after {
content: "";
opacity: 1;
scale: 1;
}
@media (prefers-reduced-motion: no-preference) {
.media-time-slider-thumb:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
content: "";
transition-property: opacity, scale;
transition-duration: .15s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
}
.media-time-slider-thumb:where(.media-skin--minimal, .media-skin--minimal *) {
outline-offset: -2px;
outline: 2px solid #0000;
scale: .7;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 1px #00000026, 0 1px 3px #00000026, 0 1px 2px -1px #00000026;
}
.media-time-slider-thumb:where(.media-skin--minimal, .media-skin--minimal *):focus-visible {
outline-offset: 2px;
outline-color: #fff;
}
.media-time-slider-thumb:where(.media-skin--minimal, .media-skin--minimal *)[data-interactive] {
scale: 1;
}
.media-time-slider-value {
font-variant-numeric: tabular-nums;
}
}
@scope (.media-skin--video) {
.media-container, :scope.media-container {
isolation: isolate;
border-radius: var(--media-video-border-radius);
background-color: var(--media-background);
width: 100%;
height: 100%;
font-family: Inter Variable, Inter, ui-sans-serif, system-ui, sans-serif;
font-size: calc(var(--media-spacing) * 3.25);
-webkit-font-smoothing: auto;
-moz-osx-font-smoothing: auto;
outline-offset: -4px;
--media-shadow-current-color: oklch(from currentColor 0 0 0/clamp(0, calc((l - .5) * .5), .15));
--media-shadow-subtle-current-color: oklch(from var(--media-shadow-current-color) l c h/calc(alpha * .4));
--spacing: var(--media-spacing);
outline: 2px solid #0000;
line-height: 1.5;
transition-property: outline-offset, outline-color;
transition-duration: .1s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
display: block;
position: relative;
overflow: clip;
container: media-root / size;
}
.media-container:after, :scope.media-container:after {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 0 0 1px var(--media-border);
position: absolute;
}
.media-container:focus-visible, :scope.media-container:focus-visible {
outline-offset: 2px;
outline-color: var(--media-focus-ring-color, light-dark(#000, #fff));
}
@media (prefers-reduced-motion: reduce) {
.media-container, :scope.media-container {
transition-duration: 50ms;
}
}
@media (forced-colors: active) {
.media-container:after, :scope.media-container:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 0 0 1px canvastext;
}
.media-container:focus-visible, :scope.media-container:focus-visible {
outline-color: canvastext;
}
}
@media (pointer: fine) {
.media-container:not([data-controls-visible]), :scope.media-container:not([data-controls-visible]) {
cursor: none;
}
}
.media-container:fullscreen, :scope.media-container:fullscreen {
--media-object-fit: contain;
--media-video-border-radius: 0;
}
.media-container:fullscreen:after, :scope.media-container:fullscreen:after {
content: "";
display: none;
}
@media (width >= 1280px) {
.media-container:fullscreen, :scope.media-container:fullscreen {
--media-scale: 1.25;
}
}
@media (width >= 1536px) {
.media-container:fullscreen, :scope.media-container:fullscreen {
--media-scale: 1.5;
}
}
@media (width >= 1920px) {
.media-container:fullscreen, :scope.media-container:fullscreen {
--media-scale: 1.75;
}
}
}
@scope (.media-skin--video) {
.media-dialog-actions {
gap: calc(var(--media-spacing) * 2);
flex-shrink: 0;
display: flex;
}
.media-dialog-backdrop {
inset: calc(var(--media-spacing) * 0);
z-index: 40;
opacity: 1;
backdrop-filter: blur(16px) saturate(150%);
background-color: oklab(0% none none / .2);
transition: opacity .15s cubic-bezier(0, 0, .2, 1) .1s;
position: absolute;
}
.media-dialog-backdrop:not([data-open]) {
display: none;
}
.media-dialog-backdrop[data-ending-style] {
opacity: 0;
transition-delay: 0s;
}
.media-dialog-backdrop[data-starting-style] {
opacity: 0;
}
@media (prefers-reduced-motion: reduce) {
.media-dialog-backdrop {
transition-duration: 50ms;
transition-delay: 0s;
}
}
.media-dialog-backdrop:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
transition-duration: .35s;
}
.media-dialog-backdrop:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-ending-style] {
transition-duration: .25s;
}
@media (prefers-reduced-motion: reduce) {
.media-dialog-backdrop:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-ending-style] {
transition-duration: 50ms;
}
}
.media-dialog-backdrop:where(.media-skin--minimal, .media-skin--minimal *) {
backdrop-filter: saturate(120%);
transition-duration: .15s;
}
.media-dialog-backdrop:where(.media-skin--minimal, .media-skin--minimal *)[data-ending-style] {
transition-duration: 50ms;
}
@media (prefers-reduced-motion: reduce) {
.media-dialog-backdrop:where(.media-skin--minimal, .media-skin--minimal *)[data-ending-style] {
transition-duration: 50ms;
}
}
.media-dialog-close {
height: var(--media-control-size);
width: 100%;
padding-inline: calc(var(--media-spacing) * 4);
padding-block: calc(var(--media-spacing) * 2);
flex: 1;
font-weight: 500;
background-color: var(--media-primary) !important;
color: var(--media-accent-foreground) !important;
}
.media-dialog-content {
min-height: calc(var(--media-spacing) * 0);
gap: calc(var(--media-spacing) * 2);
flex-direction: column;
display: flex;
overflow-y: auto;
}
.media-dialog-content:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
padding-inline: calc(var(--media-spacing) * 2);
padding-top: calc(var(--media-spacing) * 2);
padding-bottom: calc(var(--media-spacing) * 1.5);
}
.media-dialog-content:where(.media-skin--minimal, .media-skin--minimal *) {
padding-block: calc(var(--media-spacing) * 1.5);
}
.media-dialog-description {
margin: calc(var(--media-spacing) * 0);
overflow-wrap: anywhere;
opacity: .7;
}
.media-dialog-popup {
z-index: 50;
gap: calc(var(--media-spacing) * 3);
outline-style: none;
flex-direction: column;
max-height: calc(100% - .5rem);
transition: opacity .15s cubic-bezier(0, 0, .2, 1) .1s, scale .15s cubic-bezier(0, 0, .2, 1) .1s;
display: flex;
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
}
.media-dialog-popup:not([data-open]) {
display: none;
}
.media-dialog-popup[data-ending-style] {
opacity: 0;
transition-delay: 0s;
scale: .95;
}
.media-dialog-popup[data-starting-style] {
opacity: 0;
scale: .95;
}
@media (prefers-reduced-motion: reduce) {
.media-dialog-popup {
transition-duration: 50ms;
transition-delay: 0s;
}
}
.media-dialog-popup:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
width: calc(100% - 1.5rem);
max-width: calc(var(--media-spacing) * 72);
background-color: var(--media-popover);
padding: calc(var(--media-spacing) * 3);
color: #fff;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 calc(1px + 0px) var(--media-border), 0 0 #0000;
box-shadow: var(--media-shadow-sm);
backdrop-filter: blur(16px) saturate(150%);
text-shadow: 0 1px #00000040;
border-radius: 1.75rem;
transition-duration: .35s;
}
.media-dialog-popup:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
content: "";
position: absolute;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff1a, inset 0 0 0 1px #ffffff0d;
}
.media-dialog-popup:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-ending-style] {
transition-duration: .25s;
}
@media (prefers-reduced-motion: reduce) {
.media-dialog-popup:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-ending-style] {
transition-duration: 50ms;
}
}
@media (prefers-contrast: more) {
.media-dialog-popup:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-dialog-popup:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
@media (forced-colors: active) {
.media-dialog-popup:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
color: canvastext;
background-color: canvas;
}
.media-dialog-popup:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px canvastext, inset 0 0 0 1px canvastext;
}
}
.media-dialog-popup:where(.media-skin--minimal, .media-skin--minimal *) {
width: 100%;
max-width: calc(var(--media-spacing) * 64);
padding: calc(var(--media-spacing) * 4);
color: #fff;
text-shadow: 0 1px #00000080;
transition-duration: .15s;
}
.media-dialog-popup:where(.media-skin--minimal, .media-skin--minimal *)[data-ending-style] {
transition-duration: 50ms;
}
@media (prefers-reduced-motion: reduce) {
.media-dialog-popup:where(.media-skin--minimal, .media-skin--minimal *)[data-ending-style] {
transition-duration: 50ms;
}
}
@media (prefers-reduced-transparency: reduce) {
.media-dialog-popup:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-dialog-popup:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
.media-dialog-title {
margin: calc(var(--media-spacing) * 0);
font-size: calc(var(--media-spacing) * 3.75);
font-weight: 600;
line-height: 1.25;
}
}
@scope (.media-skin--video) {
.media-airplay-button:not([data-airplay-state="connected"]) {
--media-icon-airplay-fill-animation: none;
--media-icon-airplay-triangle-animation: none;
}
@media (prefers-reduced-motion: reduce) {
.media-airplay-button {
--media-icon-airplay-fill-animation: none;
--media-icon-airplay-triangle-animation: none;
}
}
.media-airplay-button-enter-icon {
opacity: 0;
}
@scope (.media-airplay-button) {
&:not([data-airplay-state="connected"]) .media-airplay-button-enter-icon {
opacity: 1;
scale: 1;
}
}
.media-airplay-button-exit-icon {
opacity: 0;
}
@scope (.media-airplay-button) {
&[data-airplay-state="connected"] .media-airplay-button-exit-icon {
opacity: 1;
scale: 1;
}
}
@media (prefers-reduced-motion: reduce) {
}
}
@scope (.media-skin--video) {
@media (prefers-reduced-motion: reduce) {
}
.media-play-button-pause-icon {
opacity: 0;
scale: 0;
}
@scope (.media-play-button) {
&[data-started]:not([data-paused]):not([data-ended]) .media-play-button-pause-icon {
opacity: 1;
scale: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.media-play-button-pause-icon {
scale: 1;
}
}
.media-play-button-play-icon {
opacity: 0;
scale: 0;
}
@scope (.media-play-button) {
&:not([data-ended]):not([data-started]) .media-play-button-play-icon, &:not([data-ended])[data-paused] .media-play-button-play-icon {
opacity: 1;
scale: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.media-play-button-play-icon {
scale: 1;
}
}
.media-play-button-restart-icon {
opacity: 0;
scale: 0;
}
@scope (.media-play-button) {
&[data-ended] .media-play-button-restart-icon {
opacity: 1;
scale: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.media-play-button-restart-icon {
scale: 1;
}
}
}
@scope (.media-skin--video) {
.media-seek-indicator {
place-content: center;
gap: calc(var(--media-spacing) * 1);
padding: calc(var(--media-spacing) * 4);
text-align: center;
grid-row-start: 1;
grid-column-start: 2;
display: grid;
}
.media-seek-indicator[data-direction="backward"] {
grid-column-start: 1;
justify-self: flex-start;
}
.media-seek-indicator[data-direction="forward"] {
grid-column-start: 3;
justify-self: flex-end;
}
@container media-root (width >= 42rem) {
.media-seek-indicator {
padding: calc(var(--media-spacing) * 6);
}
}
.media-seek-indicator-icon {
width: calc(var(--media-icon-size, calc(var(--media-spacing) * 4.5)) * 1.5);
height: calc(var(--media-icon-size, calc(var(--media-spacing) * 4.5)) * 1.5);
display: none;
}
@scope (.media-seek-indicator) {
&[data-direction] .media-seek-indicator-icon {
display: block;
}
}
@scope (.media-seek-indicator) {
&[data-direction="backward"] .media-seek-indicator-icon {
scale: -1 1;
}
}
@media (prefers-reduced-motion: no-preference) {
.media-seek-indicator-icon {
transition-property: translate, opacity;
transition-duration: .2s;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
}
@scope (.media-seek-indicator) {
&[data-ending-style] .media-seek-indicator-icon, &[data-starting-style] .media-seek-indicator-icon {
opacity: 0;
}
}
@scope (.media-seek-indicator) {
&[data-direction="backward"][data-starting-style] .media-seek-indicator-icon {
translate: 60%;
}
}
@scope (.media-seek-indicator) {
&[data-direction="forward"][data-starting-style] .media-seek-indicator-icon {
translate: -60%;
}
}
}
.media-seek-indicator-value {
font-variant-numeric: tabular-nums;
}
}
@scope (.media-skin--video) {
.media-playback-status-indicator {
padding: calc(var(--media-spacing) * 4);
text-align: center;
grid-row-start: 1;
grid-column-start: 2;
place-content: center;
transition-property: opacity, scale;
transition-duration: .2s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
display: grid;
}
.media-playback-status-indicator[data-ending-style] {
opacity: 0;
transition-duration: .1s;
transition-timing-function: cubic-bezier(.4, 0, 1, 1);
scale: .85;
}
.media-playback-status-indicator[data-starting-style] {
opacity: 0;
scale: .85;
}
@media (prefers-reduced-motion: reduce) {
.media-playback-status-indicator {
transition-property: opacity;
transition-duration: 50ms;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
}
.media-playback-status-indicator[data-ending-style], .media-playback-status-indicator[data-starting-style] {
scale: 1;
}
}
.media-playback-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
backdrop-filter: blur(8px);
background-color: oklab(0% none none / .35);
border-radius: 9999px;
}
.media-playback-status-indicator-pause-icon {
opacity: 0;
grid-row-start: 1;
grid-column-start: 1;
transition-property: opacity, scale;
transition-duration: .15s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
scale: 0;
}
@scope (.media-playback-status-indicator) {
&[data-status="pause"] .media-playback-status-indicator-pause-icon {
opacity: 1;
scale: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.media-playback-status-indicator-pause-icon {
transition-property: opacity;
transition-duration: 50ms;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
scale: 1;
}
}
.media-playback-status-indicator-pause-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
width: calc(var(--media-icon-size, calc(var(--media-spacing) * 4.5)) * 1.5);
height: calc(var(--media-icon-size, calc(var(--media-spacing) * 4.5)) * 1.5);
}
.media-playback-status-indicator-pause-icon:where(.media-skin--minimal, .media-skin--minimal *) {
width: calc(var(--media-icon-size, calc(var(--media-spacing) * 4.5)) * 2);
height: calc(var(--media-icon-size, calc(var(--media-spacing) * 4.5)) * 2);
}
.media-playback-status-indicator-play-icon {
opacity: 0;
grid-row-start: 1;
grid-column-start: 1;
transition-property: opacity, scale;
transition-duration: .15s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
scale: 0;
}
@scope (.media-playback-status-indicator) {
&[data-status="play"] .media-playback-status-indicator-play-icon {
opacity: 1;
scale: 1;
}
}
@media (prefers-reduced-motion: reduce) {
.media-playback-status-indicator-play-icon {
transition-property: opacity;
transition-duration: 50ms;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
scale: 1;
}
}
.media-playback-status-indicator-play-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
width: calc(var(--media-icon-size, calc(var(--media-spacing) * 4.5)) * 1.5);
height: calc(var(--media-icon-size, calc(var(--media-spacing) * 4.5)) * 1.5);
}
@scope (.media-playback-status-indicator) {
&[data-status="play"] .media-playback-status-indicator-play-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
translate: 1px;
}
}
.media-playback-status-indicator-play-icon:where(.media-skin--minimal, .media-skin--minimal *) {
width: calc(var(--media-icon-size, calc(var(--media-spacing) * 4.5)) * 2);
height: calc(var(--media-icon-size, calc(var(--media-spacing) * 4.5)) * 2);
}
.media-status-indicator {
pointer-events: none;
transform-origin: top;
color: inherit;
position: absolute;
}
.media-status-indicator[data-ending-style], .media-status-indicator[data-starting-style] {
opacity: 0;
}
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
top: calc(var(--media-spacing) * 3);
background-color: oklab(0% none none / .25);
background-color: var(--media-popover);
color: var(--media-popover-foreground);
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 calc(1px + 0px) var(--media-border), 0 0 #0000;
box-shadow: var(--media-shadow-sm);
backdrop-filter: blur(16px) saturate(150%);
border-radius: 9999px;
font-weight: 500;
transition-duration: .1s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
content: "";
position: absolute;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff1a, inset 0 0 0 1px #ffffff0d;
}
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-ending-style], .media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-starting-style] {
transition-duration: .25s;
transition-timing-function: cubic-bezier(.4, 0, 1, 1);
}
@media (prefers-reduced-motion: no-preference) {
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-ending-style] {
translate: 0 -25%;
}
}
@media (prefers-contrast: more) {
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
@media (forced-colors: active) {
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
color: canvastext;
background-color: canvas;
}
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px canvastext, inset 0 0 0 1px canvastext;
}
}
@media (pointer: coarse) {
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
will-change: scale,translate,opacity;
transition-property: scale, translate, opacity;
}
}
@media (pointer: fine) {
@media (prefers-reduced-motion: no-preference) {
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
will-change: scale,translate,filter,opacity;
transition-property: scale, translate, filter, opacity;
}
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-ending-style], .media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *)[data-starting-style] {
filter: blur(8px);
scale: .9;
}
}
}
.media-status-indicator:where(.media-skin--minimal, .media-skin--minimal *) {
inset-inline: calc(var(--media-spacing) * 0);
top: calc(var(--media-spacing) * 0);
background-image: linear-gradient(to bottom,oklch(0% 0 0 / .35),oklch(0% 0 0 / .2) calc(var(--media-spacing) * 12),transparent);
padding-top: calc(var(--media-spacing) * 3);
padding-bottom: calc(var(--media-spacing) * 32);
text-shadow: 0 1px 0 var(--media-shadow-current-color);
justify-content: center;
transition-duration: .1s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
display: flex;
}
.media-status-indicator:where(.media-skin--minimal, .media-skin--minimal *)[data-ending-style], .media-status-indicator:where(.media-skin--minimal, .media-skin--minimal *)[data-starting-style] {
transition-duration: .4s;
transition-timing-function: cubic-bezier(.4, 0, 1, 1);
}
@media (prefers-reduced-motion: no-preference) {
.media-status-indicator:where(.media-skin--minimal, .media-skin--minimal *)[data-ending-style] {
translate: 0 -100%;
}
}
@media (pointer: coarse) {
.media-status-indicator:where(.media-skin--minimal, .media-skin--minimal *) {
will-change: translate,opacity;
transition-property: translate, opacity;
}
}
@media (pointer: fine) {
.media-status-indicator:where(.media-skin--minimal, .media-skin--minimal *) {
will-change: translate,filter,opacity;
transition-property: translate, filter, opacity;
}
@media (prefers-reduced-motion: no-preference) {
.media-status-indicator:where(.media-skin--minimal, .media-skin--minimal *)[data-ending-style], .media-status-indicator:where(.media-skin--minimal, .media-skin--minimal *)[data-starting-style] {
filter: blur(8px);
}
}
}
@media (prefers-reduced-transparency: reduce) {
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-status-indicator:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *):after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
.media-status-indicator-captions-off-icon {
flex-shrink: 0;
display: none;
}
@scope (.media-status-indicator) {
&[data-status="captions-off"] .media-status-indicator-captions-off-icon {
display: block;
}
}
.media-status-indicator-captions-off-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
mix-blend-mode: difference;
}
.media-status-indicator-captions-off-icon:where(.media-skin--minimal, .media-skin--minimal *) {
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
}
.media-status-indicator-captions-on-icon {
flex-shrink: 0;
display: none;
}
@scope (.media-status-indicator) {
&[data-status="captions-on"] .media-status-indicator-captions-on-icon {
display: block;
}
}
.media-status-indicator-captions-on-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
mix-blend-mode: difference;
}
.media-status-indicator-captions-on-icon:where(.media-skin--minimal, .media-skin--minimal *) {
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
}
.media-status-indicator-content {
justify-content: space-between;
align-items: center;
gap: calc(var(--media-spacing) * 2);
padding-inline: calc(var(--media-spacing) * 2.5);
padding-block: calc(var(--media-spacing) * 1);
display: flex;
}
.media-status-indicator-content:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
width: 100%;
}
@media (prefers-contrast: more) {
.media-status-indicator-content:where(.media-skin--minimal, .media-skin--minimal *) {
border-radius: calc(var(--media-spacing) * 2);
background-color: #000;
}
}
@media (prefers-reduced-transparency: reduce) {
.media-status-indicator-content:where(.media-skin--minimal, .media-skin--minimal *) {
border-radius: calc(var(--media-spacing) * 2);
background-color: #000;
}
}
.media-status-indicator-fullscreen-enter-icon {
flex-shrink: 0;
display: none;
}
@scope (.media-status-indicator) {
&[data-status="fullscreen"] .media-status-indicator-fullscreen-enter-icon {
display: block;
}
}
.media-status-indicator-fullscreen-enter-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
mix-blend-mode: difference;
}
.media-status-indicator-fullscreen-enter-icon:where(.media-skin--minimal, .media-skin--minimal *) {
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
}
.media-status-indicator-fullscreen-exit-icon {
flex-shrink: 0;
display: none;
}
@scope (.media-status-indicator) {
&[data-status="exit-fullscreen"] .media-status-indicator-fullscreen-exit-icon {
display: block;
}
}
.media-status-indicator-fullscreen-exit-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
mix-blend-mode: difference;
}
.media-status-indicator-fullscreen-exit-icon:where(.media-skin--minimal, .media-skin--minimal *) {
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
}
.media-status-indicator-pip-enter-icon {
flex-shrink: 0;
display: none;
}
@scope (.media-status-indicator) {
&[data-status="pip"] .media-status-indicator-pip-enter-icon {
display: block;
}
}
.media-status-indicator-pip-enter-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
mix-blend-mode: difference;
}
.media-status-indicator-pip-enter-icon:where(.media-skin--minimal, .media-skin--minimal *) {
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
}
.media-status-indicator-pip-exit-icon {
flex-shrink: 0;
display: none;
}
@scope (.media-status-indicator) {
&[data-status="exit-pip"] .media-status-indicator-pip-exit-icon {
display: block;
}
}
.media-status-indicator-pip-exit-icon:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
mix-blend-mode: difference;
}
.media-status-indicator-pip-exit-icon:where(.media-skin--minimal, .media-skin--minimal *) {
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
}
.media-status-indicator-value {
margin-left: auto;
}
.media-status-indicator-value:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
mix-blend-mode: difference;
}
}
@scope (.media-skin--video) {
.media-status-announcer {
clip-path: inset(50%);
white-space: nowrap;
border-width: 0;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
position: absolute;
overflow: hidden;
}
}
@scope (.media-skin--video) {
@media (prefers-reduced-motion: reduce) {
}
.media-captions-button-off-icon {
opacity: 0;
}
@scope (.media-captions-button) {
&:not([data-active]) .media-captions-button-off-icon {
opacity: 1;
scale: 1;
}
}
.media-captions-button-on-icon {
opacity: 0;
}
@scope (.media-captions-button) {
&[data-active] .media-captions-button-on-icon {
opacity: 1;
scale: 1;
}
}
}
@scope (.media-skin--video) {
@media (prefers-reduced-motion: reduce) {
}
.media-mute-button-high-icon {
opacity: 0;
}
@scope (.media-mute-button) {
&:not([data-muted]):not([data-volume-level="low"]) .media-mute-button-high-icon {
opacity: 1;
scale: 1;
}
}
.media-mute-button-low-icon {
opacity: 0;
}
@scope (.media-mute-button) {
&:not([data-muted])[data-volume-level="low"] .media-mute-button-low-icon {
opacity: 1;
scale: 1;
}
}
.media-mute-button-off-icon {
opacity: 0;
}
@scope (.media-mute-button) {
&[data-muted] .media-mute-button-off-icon {
opacity: 1;
scale: 1;
}
}
}
@scope (.media-skin--video) {
@media (prefers-reduced-motion: reduce) {
}
.media-fullscreen-button-enter-icon {
opacity: 0;
}
@scope (.media-fullscreen-button) {
&:not([data-fullscreen]) .media-fullscreen-button-enter-icon {
opacity: 1;
scale: 1;
}
}
.media-fullscreen-button-exit-icon {
opacity: 0;
}
@scope (.media-fullscreen-button) {
&[data-fullscreen] .media-fullscreen-button-exit-icon {
opacity: 1;
scale: 1;
}
}
}
@scope (.media-skin--video) {
.media-slider-buffer {
pointer-events: none;
border-radius: inherit;
background-color: currentColor;
position: absolute;
}
@supports (color: color-mix(in lab, red, red)) {
.media-slider-buffer {
background-color: color-mix(in oklab, currentcolor 20.0%, transparent);
}
}
@scope (.media-slider) {
&[data-dragging] .media-slider-buffer, &[data-seeking] .media-slider-buffer {
transition-duration: 0s;
}
}
.media-slider-buffer[data-orientation="horizontal"] {
inset-block: calc(var(--media-spacing) * 0);
left: calc(var(--media-spacing) * 0);
width: 100%;
clip-path: inset(0 calc(100.0% - var(--media-slider-buffer)) 0 0 round 99px);
}
.media-slider-buffer[data-orientation="vertical"] {
inset-inline: calc(var(--media-spacing) * 0);
bottom: calc(var(--media-spacing) * 0);
height: 100%;
clip-path: inset(calc(100.0% - var(--media-slider-buffer)) 0 0 0 round 99px);
}
@media (prefers-reduced-motion: no-preference) {
.media-slider-buffer {
transition-property: clip-path;
transition-duration: .1s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
}
.media-slider-fill {
pointer-events: none;
border-radius: inherit;
background-color: var(--media-primary);
position: absolute;
}
@scope (.media-slider) {
&[data-dragging] .media-slider-fill, &[data-seeking] .media-slider-fill {
transition-duration: 0s;
}
}
.media-slider-fill[data-orientation="horizontal"] {
inset-block: calc(var(--media-spacing) * 0);
left: calc(var(--media-spacing) * 0);
width: 100%;
clip-path: inset(0 calc(100.0% - var(--media-slider-fill)) 0 0 round 99px);
}
@scope (.media-slider) {
&[data-dragging] .media-slider-fill[data-orientation="horizontal"] {
clip-path: inset(0 calc(100.0% - var(--media-slider-pointer)) 0 0 round 99px);
}
}
.media-slider-fill[data-orientation="vertical"] {
inset-inline: calc(var(--media-spacing) * 0);
bottom: calc(var(--media-spacing) * 0);
height: 100%;
clip-path: inset(calc(100.0% - var(--media-slider-fill)) 0 0 0 round 99px);
}
@scope (.media-slider) {
&[data-dragging] .media-slider-fill[data-orientation="vertical"] {
clip-path: inset(calc(100.0% - var(--media-slider-pointer)) 0 0 0 round 99px);
}
}
@media (prefers-reduced-motion: no-preference) {
.media-slider-fill {
transition-property: clip-path;
transition-duration: .1s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
}
.media-slider-thumb {
top: 50%;
left: var(--media-slider-fill);
z-index: 10;
border-radius: var(--media-control-radius);
-webkit-user-select: none;
user-select: none;
background-color: currentColor;
transition-property: none;
position: absolute;
translate: -50% -50%;
}
@scope (.media-slider) {
&[data-dragging] .media-slider-thumb {
scale: .9;
}
}
@scope (.media-slider) {
&[data-dragging] .media-slider-thumb[data-orientation="horizontal"] {
left: var(--media-slider-pointer);
}
}
.media-slider-thumb[data-orientation="vertical"] {
top: calc(100.0% - var(--media-slider-fill));
left: 50%;
}
@scope (.media-slider) {
&[data-dragging] .media-slider-thumb[data-orientation="vertical"] {
top: calc(100.0% - var(--media-slider-pointer));
}
}
@media (prefers-reduced-motion: no-preference) {
.media-slider-thumb {
transition-property: opacity, height, width, outline-offset, left, top, scale;
transition-duration: .1s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
}
@scope (.media-slider) {
&[data-dragging] .media-slider-thumb {
transition-property: opacity, height, width, outline-offset, scale;
transition-duration: .15s;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
}
}
}
.media-slider-track {
isolation: isolate;
-webkit-user-select: none;
user-select: none;
background-color: currentColor;
border-radius: 99px;
width: 100%;
position: relative;
overflow: hidden;
}
@supports (color: color-mix(in lab, red, red)) {
.media-slider-track {
background-color: color-mix(in oklab, currentcolor 20.0%, transparent);
}
}
.media-slider-track[data-orientation="horizontal"] {
height: calc(var(--media-spacing) * 1);
}
.media-slider-track[data-orientation="vertical"] {
height: 100%;
width: calc(var(--media-spacing) * 1);
}
}
@scope (.media-skin--video) {
@media (prefers-reduced-motion: reduce) {
}
.media-pip-button-enter-icon {
opacity: 0;
}
@scope (.media-pip-button) {
&:not([data-pip]) .media-pip-button-enter-icon {
opacity: 1;
scale: 1;
}
}
.media-pip-button-exit-icon {
opacity: 0;
}
@scope (.media-pip-button) {
&[data-pip] .media-pip-button-exit-icon {
opacity: 1;
scale: 1;
}
}
}
@scope (.media-skin--video) {
.media-menu-item-indicator {
opacity: 0;
flex-shrink: 0;
margin-inline-start: auto;
margin-inline-end: calc(var(--media-spacing) * -1);
}
@scope (.media-menu-radio-item) {
&[aria-checked="true"] .media-menu-item-indicator {
opacity: 1;
}
}
.media-menu-radio-item {
cursor: pointer;
justify-content: space-between;
align-items: center;
gap: calc(var(--media-spacing) * 1.5);
border-radius: var(--media-menu-item-border-radius);
padding-inline: calc(var(--media-spacing) * 2);
padding-block: calc(var(--media-spacing) * 1.5);
text-align: start;
white-space: nowrap;
color: inherit;
font-variant-numeric: tabular-nums;
outline-offset: -2px;
-webkit-user-select: none;
user-select: none;
text-shadow: 0 1px 0 var(--media-shadow-current-color);
outline: 2px solid #0000;
transition-property: background-color, color;
transition-duration: .1s;
transition-timing-function: ease-in-out;
display: flex;
position: relative;
}
@media (hover: hover) {
.media-menu-radio-item:hover {
background-color: var(--media-accent);
color: var(--media-accent-foreground);
}
}
.media-menu-radio-item:focus-visible {
outline-offset: 2px;
outline-color: #fff;
}
.media-menu-radio-item[aria-disabled="true"] {
pointer-events: none;
cursor: not-allowed;
opacity: .5;
}
.media-menu-radio-item[data-highlighted] {
background-color: var(--media-accent);
color: var(--media-accent-foreground);
}
.media-menu-radio-item[data-availability="unavailable"], .media-menu-radio-item[data-availability="unsupported"] {
display: none;
}
@supports (top: anchor(top)) {
.media-menu-radio-item {
transition-duration: 50ms;
}
@media (hover: hover) {
.media-menu-radio-item:hover {
transition-duration: .2s;
}
}
.media-menu-radio-item[data-highlighted] {
anchor-name: --media-menu-item-highlight-anchor;
background-color: #0000;
transition-duration: .2s;
}
}
@media (prefers-reduced-motion: reduce) {
.media-menu-radio-item {
transition-duration: 50ms;
}
}
.media-menu-radio-item-icon {
width: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
height: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
color: var(--media-muted-foreground);
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
flex-shrink: 0;
}
@media (hover: hover) {
@scope (.media-menu-radio-item) {
&:hover .media-menu-radio-item-icon {
color: inherit;
}
}
}
@scope (.media-menu-radio-item) {
&[data-highlighted] .media-menu-radio-item-icon {
color: inherit;
}
}
}
@scope (.media-skin--video) {
.media-poster {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
border-radius: inherit;
object-fit: var(--media-object-fit, contain);
object-position: var(--media-object-position, center);
width: 100%;
height: 100%;
transition-property: opacity;
transition-duration: .25s;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
position: absolute;
}
.media-poster:not([data-visible]) {
opacity: 0;
}
.media-poster img {
inset: calc(var(--media-spacing) * 0);
border-radius: inherit;
object-fit: var(--media-object-fit, contain);
object-position: var(--media-object-position, center);
width: 100%;
height: 100%;
position: absolute;
}
.media-poster:is(img):not([src]):not([srcset]) {
visibility: hidden;
}
}
@scope (.media-skin--video) {
.media-menu-back-chevron {
width: calc(var(--media-spacing) * 3.5);
height: calc(var(--media-spacing) * 3.5);
width: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
height: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
color: var(--media-muted-foreground);
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
flex-shrink: 0;
rotate: 180deg;
}
@media (hover: hover) {
@scope (.media-menu-back-item) {
&:hover .media-menu-back-chevron {
color: inherit;
}
}
}
@scope (.media-menu-back-item) {
&[data-highlighted] .media-menu-back-chevron {
color: inherit;
}
}
.media-menu-back-chevron:dir(rtl) {
rotate: 0deg;
scale: 1;
}
.media-menu-forward-chevron {
width: calc(var(--media-spacing) * 3.5);
height: calc(var(--media-spacing) * 3.5);
width: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
height: var(--media-icon-size, calc(var(--media-spacing) * 4.5));
color: var(--media-muted-foreground);
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
flex-shrink: 0;
}
@media (hover: hover) {
@scope (.media-menu-trigger-item) {
&:hover .media-menu-forward-chevron {
color: inherit;
}
}
}
@scope (.media-menu-trigger-item) {
&[data-highlighted] .media-menu-forward-chevron {
color: inherit;
}
}
.media-menu-forward-chevron:dir(rtl) {
scale: -1 1;
}
}
@scope (.media-skin--video) {
@media (prefers-reduced-motion: reduce) {
}
}
@scope (.media-skin--video) {
.media-video-status-indicators {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
color: #fff;
grid-template-columns: repeat(3, minmax(0, 1fr));
place-items: center;
display: grid;
position: absolute;
}
}
@scope (.media-skin--video) {
@media (hover: hover) {
}
@supports (top: anchor(top)) {
@media (hover: hover) {
}
}
@media (prefers-reduced-motion: reduce) {
}
@supports (top: anchor(top)) {
}
@supports (color: color-mix(in lab, red, red)) {
}
@supports (top: anchor(top)) {
}
@media (prefers-contrast: more) {
}
@media (forced-colors: active) {
}
@media (prefers-reduced-transparency: reduce) {
}
@media (hover: hover) {
}
@supports (top: anchor(top)) {
@media (hover: hover) {
}
}
@media (prefers-reduced-motion: reduce) {
}
@media (hover: hover) {
@scope (.media-menu-trigger-item) {
}
}
@scope (.media-menu-trigger-item) {
}
}
@scope (.media-skin--video) {
@supports (top: anchor(top)) {
}
.media-menu-popup {
margin: calc(var(--media-spacing) * 0);
height: var(--media-menu-height);
max-height: min(var(--media-menu-available-height, calc(var(--media-spacing) * 56)), calc(var(--media-spacing) * 56));
width: var(--media-menu-width);
max-width: var(--media-menu-available-width);
min-width: calc(var(--media-spacing) * 44);
overscroll-behavior: none;
background-color: var(--media-popover);
padding: calc(var(--media-spacing) * 1);
color: var(--media-popover-foreground);
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 0 calc(1px + 0px) var(--media-border), 0 0 #0000;
box-shadow: var(--media-shadow-sm);
backdrop-filter: blur(16px) saturate(150%);
border-style: solid;
border-width: 0;
transition-property: opacity, filter, transform, scale, width, height;
transition-duration: .1s, .1s, .1s, .1s, .25s, .25s;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
overflow: visible;
overflow: hidden !important;
}
.media-menu-popup:before {
pointer-events: auto;
content: "";
position: absolute;
}
.media-menu-popup:after {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
content: "";
position: absolute;
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff1a, inset 0 0 0 1px #ffffff0d;
}
.media-menu-popup[data-ending-style] {
opacity: 0;
filter: blur(4px);
transition-property: opacity, filter, transform, scale;
transition-duration: .1s;
transform: none;
}
.media-menu-popup[data-starting-style] {
transform: translate(var(--media-popup-translate-x-distance, 0),var(--media-popup-translate-y-distance, 0));
opacity: 0;
filter: blur(4px);
transition-property: opacity, filter, transform, scale;
transition-duration: .1s;
}
.media-menu-popup[data-side="bottom"] {
transform-origin: top;
--media-popup-translate-y-distance: calc(var(--media-popup-translate-distance) * -1);
}
.media-menu-popup[data-side="bottom"]:before {
inset-inline: calc(var(--media-spacing) * 0);
content: "";
height: var(--media-popover-side-offset);
bottom: 100%;
}
.media-menu-popup[data-side="left"] {
transform-origin: 100%;
--media-popup-translate-x-distance: var(--media-popup-translate-distance);
}
.media-menu-popup[data-side="left"]:before {
inset-block: calc(var(--media-spacing) * 0);
content: "";
width: var(--media-popover-side-offset);
left: 100%;
}
.media-menu-popup[data-side="right"] {
transform-origin: 0;
--media-popup-translate-x-distance: calc(var(--media-popup-translate-distance) * -1);
}
.media-menu-popup[data-side="right"]:before {
inset-block: calc(var(--media-spacing) * 0);
content: "";
width: var(--media-popover-side-offset);
right: 100%;
}
.media-menu-popup[data-side="top"] {
transform-origin: bottom;
--media-popup-translate-y-distance: var(--media-popup-translate-distance);
}
.media-menu-popup[data-side="top"]:before {
inset-inline: calc(var(--media-spacing) * 0);
content: "";
height: var(--media-popover-side-offset);
top: 100%;
}
@media (prefers-reduced-motion: reduce) {
.media-menu-popup {
--media-menu-transition-duration: 0s;
transition-duration: 0s !important;
}
.media-menu-popup[data-ending-style], .media-menu-popup[data-starting-style] {
filter: none !important;
transform: none !important;
}
}
@media (prefers-contrast: more) {
.media-menu-popup {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-menu-popup:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
@media (forced-colors: active) {
.media-menu-popup {
color: canvastext;
background-color: canvas;
}
.media-menu-popup:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px canvastext, inset 0 0 0 1px canvastext;
}
}
.media-menu-popup:where(.media-skin:not(.media-skin--minimal), .media-skin:not(.media-skin--minimal) *) {
border-radius: calc(var(--media-spacing) * 3);
}
.media-menu-popup:where(.media-skin--minimal, .media-skin--minimal *) {
border-radius: calc(var(--media-spacing) * 2.5);
}
.media-menu-popup:where(.media-skin--minimal, .media-skin--minimal *):after {
content: "";
display: none;
}
.media-menu-popup:where(.media-skin--minimal, .media-skin--minimal *)[data-starting-style] {
filter: none;
}
.media-menu-popup:is([data-starting-style], [data-ending-style]) {
scale: .95;
}
@media (prefers-reduced-motion: reduce) {
.media-menu-popup:is([data-starting-style], [data-ending-style]) {
scale: 1 !important;
}
}
@media (prefers-reduced-transparency: reduce) {
.media-menu-popup {
background-color: var(--media-background);
backdrop-filter: none;
}
.media-menu-popup:after {
content: "";
box-shadow: 0 0 #0000, 0 0 #0000, 0 0 #0000, 0 0 #0000, inset 0 1px #ffffff40, inset 0 0 0 1px #ffffff20;
}
}
.media-settings-menu-trigger-icon {
transition-property: transform, translate, scale, rotate;
transition-duration: .15s;
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
}
@scope (.media-settings-menu-trigger) {
&[aria-expanded="true"] .media-settings-menu-trigger-icon {
rotate: 90deg;
}
}
@media (prefers-reduced-motion: reduce) {
.media-settings-menu-trigger-icon {
transition-property: none !important;
transition-duration: 0s !important;
}
}
.media-settings-menu-trigger-label {
clip-path: inset(50%);
white-space: nowrap;
border-width: 0;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
position: absolute;
overflow: hidden;
}
}
}
@layer utilities;
Skins, features, and presets
Each skin is built with specific features in mind. For example, a video skin renders fullscreen and picture-in-picture controls. An audio skin doesn’t.
You’ll find a preconfigured player, its typed hook, a skin, and the matching feature bundle exported from the same path. We call these paths presets.
| Import | Description | Details |
|---|---|---|
@videojs/html/video | General-purpose video player preset with full playback controls. | |
| ||
@videojs/html/audio | Audio-only player preset with playback and volume controls. | |
@videojs/html/background | Ambient background video preset with no user controls. | |
| ||
@videojs/html/live-audio | Live audio player preset — audio minus playback rate, plus the live feature, with a skin that swaps the time slider
and time displays for a Live button. | |
| ||
@videojs/html/live-video | Live video player preset — video minus playback rate, quality selection, and audio-track selection, plus the live
feature, with a skin that swaps the time slider and time displays for a Live button. | |
| ||
Styling
Packaged skins use vanilla CSS. Their documented CSS custom properties cover common visual changes.
Import the stylesheet listed for each skin in the preset table.
The skin registration entry point imports its styles automatically.
Either way the styles travel inside the skin’s JavaScript and apply when the element upgrades, so there is no stylesheet to add. The CDN publishes them as files as well, which matters when you want the player’s box styled before that upgrade — see Self-host the player.
To use Tailwind or change the underlying CSS, eject the skin and edit its styles in your app.
Shared limitations
- Skin spacing and icons use a fixed
16pxbase by default. Vanilla CSS font sizes use the same base, while Tailwind font sizes use rem units and assume a 16px root font size. - The default font stack includes
Inter, but we do not load the webfont for you. If Inter is unavailable, the skin uses system fonts.
Ejected vanilla CSS
- We use a BEM classname structure and every component classname is scoped with a
media-prefix.
Ejected Tailwind
- Ejected skins establish their own spacing scale but otherwise assume the default configuration. A future CLI eject command will support custom class prefixes. For now, edit the ejected skin to use your prefix.
- Ejected skins currently support Tailwind 4.3.x.