The Open Source Player
for the Web
For over 15 years, Video.js has been the world's web video player. Now rebuilt in v10 for modern development and performance.
Assemble your player
Feel at home with your framework, skin, and media source
import { VideoPlayer, VideoSkin, Video } from '@videojs/react/video';
import '@videojs/react/video/skin.css';
export function App() {
return (
<VideoPlayer poster="https://image.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/thumbnail.webp">
<VideoSkin>
<Video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" playsInline />
</VideoSkin>
</VideoPlayer>
);
}<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/html@10.0.0-beta.32/cdn/video.js"></script>
<video-player>
<video-skin>
<video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" playsinline></video>
</video-skin>
</video-player><script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/html@10.0.0-beta.32/cdn/video-minimal.js"></script>
<video-player>
<video-minimal-skin>
<video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" playsinline></video>
</video-minimal-skin>
</video-player>import { VideoPlayer, MinimalVideoSkin, Video } from '@videojs/react/video';
import '@videojs/react/video/minimal-skin.css';
export function App() {
return (
<VideoPlayer poster="https://image.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/thumbnail.webp">
<MinimalVideoSkin>
<Video src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" playsInline />
</MinimalVideoSkin>
</VideoPlayer>
);
}Take full control
Make your player truly your own with fully-editable components
'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;
<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);
}
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/html@10.0.0-beta.32/cdn/video-minimal.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--minimal 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" family="minimal" 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-controls">
<media-tooltip-group>
<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" family="minimal" class="media-icon media-icon--restart"></media-icon>
<media-icon name="play" family="minimal" class="media-icon media-icon--play"></media-icon>
<media-icon name="pause" family="minimal" class="media-icon media-icon--pause"></media-icon>
</media-play-button>
<media-tooltip id="play-tooltip" side="top" class="media-tooltip">
<media-tooltip-label></media-tooltip-label>
<media-tooltip-shortcut class="media-tooltip__kbd"></media-tooltip-shortcut>
</media-tooltip>
<media-mute-button id="video-mute-trigger" commandfor="video-volume-popover" class="media-button media-button--subtle media-button--icon media-button--mute">
<media-icon name="volume-off" family="minimal" class="media-icon media-icon--volume-off"></media-icon>
<media-icon name="volume-low" family="minimal" class="media-icon media-icon--volume-low"></media-icon>
<media-icon name="volume-high" family="minimal" class="media-icon media-icon--volume-high"></media-icon>
</media-mute-button>
<media-tooltip trigger="video-mute-trigger" delay="0" sticky side="top" class="media-tooltip">
<media-tooltip-label></media-tooltip-label>
<media-tooltip-shortcut class="media-tooltip__kbd"></media-tooltip-shortcut>
</media-tooltip>
<media-popover id="video-volume-popover" open-on-hover delay="200" close-delay="100" side="right" class="media-popover media-popover--volume">
<media-volume-slider class="media-slider" orientation="horizontal" 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-group class="media-time-group">
<media-time toggle type="current" class="media-time media-time--current"></media-time>
<media-time-separator class="media-time-separator"></media-time-separator>
<media-time type="duration" class="media-time media-time--duration"></media-time>
</media-time-group>
<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 class="media-slider__preview">
<div class="media-thumbnail media-slider__thumbnail">
<media-slider-thumbnail class="media-thumbnail__image"></media-slider-thumbnail>
<media-icon name="spinner" family="minimal" 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>
</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" family="minimal" class="media-icon media-icon--captions-off"></media-icon>
<media-icon name="captions-on" family="minimal" class="media-icon media-icon--captions-on"></media-icon>
</media-captions-button>
<media-tooltip id="captions-tooltip" side="top" class="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" family="minimal" 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-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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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" family="minimal" 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-tooltip">
<media-text token="menu.settings">Settings</media-text>
</media-tooltip>
<media-cast-button commandfor="cast-tooltip" class="media-button media-button--subtle media-button--icon media-button--cast">
<media-icon name="cast-enter" family="minimal" class="media-icon media-icon--cast-enter"></media-icon>
<media-icon name="cast-exit" family="minimal" class="media-icon media-icon--cast-exit"></media-icon>
</media-cast-button>
<media-tooltip id="cast-tooltip" side="top" class="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" family="minimal" class="media-icon media-icon--airplay-enter"></media-icon>
<media-icon name="airplay-exit" family="minimal" class="media-icon media-icon--airplay-exit"></media-icon>
</media-airplay-button>
<media-tooltip id="airplay-tooltip" side="top" class="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" family="minimal" class="media-icon media-icon--pip-enter"></media-icon>
<media-icon name="pip-exit" family="minimal" class="media-icon media-icon--pip-exit"></media-icon>
</media-pip-button>
<media-tooltip id="pip-tooltip" side="top" class="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" family="minimal" class="media-icon media-icon--fullscreen-enter"></media-icon>
<media-icon name="fullscreen-exit" family="minimal" class="media-icon media-icon--fullscreen-exit"></media-icon>
</media-fullscreen-button>
<media-tooltip id="fullscreen-tooltip" side="top" class="media-tooltip">
<media-tooltip-label></media-tooltip-label>
<media-tooltip-shortcut class="media-tooltip__kbd"></media-tooltip-shortcut>
</media-tooltip>
</div>
</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-volume-indicator">
<media-volume-indicator-fill class="media-volume-indicator__content">
<media-icon name="volume-high" family="minimal" class="media-icon media-icon--volume-high"></media-icon>
<media-icon name="volume-low" family="minimal" class="media-icon media-icon--volume-low"></media-icon>
<media-icon name="volume-off" family="minimal" class="media-icon media-icon--volume-off"></media-icon>
<div class="media-volume-indicator__progress" aria-hidden="true"></div>
<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-status-indicator media-status-indicator--state">
<div class="media-status-indicator__content">
<media-icon name="captions-on" family="minimal" class="media-icon media-icon--captions-on"></media-icon>
<media-icon name="captions-off" family="minimal" class="media-icon media-icon--captions-off"></media-icon>
<media-icon name="fullscreen-enter" family="minimal" class="media-icon media-icon--fullscreen-enter"></media-icon>
<media-icon name="fullscreen-exit" family="minimal" class="media-icon media-icon--fullscreen-exit"></media-icon>
<media-icon name="pip-enter" family="minimal" class="media-icon media-icon--pip-enter"></media-icon>
<media-icon name="pip-exit" family="minimal" 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" family="minimal" 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" family="minimal" class="media-icon media-icon--play"></media-icon>
<media-icon name="pause" family="minimal" 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--minimal {
/* 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) * 3));
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);
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--minimal ::slotted(video),
.media-skin--minimal video {
display: block;
width: 100%;
height: 100%;
object-fit: var(--media-object-fit, contain);
object-position: var(--media-object-position, center);
}
.media-skin--minimal ::slotted(video) {
border-radius: var(--media-container-border-radius);
}
.media-skin--minimal video {
border-radius: inherit;
}
.media-skin--minimal:fullscreen ::slotted(video),
.media-skin--minimal:fullscreen video {
object-fit: contain;
}
.media-skin--minimal .media-controls__backdrop {
position: absolute;
inset: 0;
z-index: 10;
pointer-events: none;
background-image: linear-gradient(
to top,
oklch(0 0 0 / 0.7),
oklch(0 0 0 / 0.5) calc(var(--media-spacing) * 30),
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--minimal .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--minimal {
.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.2);
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--minimal .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, 0) + 1));
--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);
background-color: var(--media-controls-background-color);
backdrop-filter: var(--media-controls-backdrop-filter);
&:dir(rtl) {
flex-direction: row-reverse;
}
}
.media-skin--minimal .media-time-controls {
display: flex;
flex: 1;
flex-direction: row-reverse;
gap: calc(var(--media-spacing) * 3);
align-items: center;
container: media-time-controls / inline-size;
&:dir(rtl) {
flex-direction: row;
}
}
.media-skin--minimal .media-time-group {
display: flex;
gap: calc(var(--media-spacing) * 1);
align-items: center;
&:dir(rtl) {
flex-direction: row-reverse;
}
}
.media-skin--minimal .media-time {
font-variant-numeric: tabular-nums;
}
.media-skin--minimal .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;
@supports (corner-shape: squircle) {
border-radius: calc(var(--media-spacing) * 4);
corner-shape: squircle;
}
&:focus-visible {
outline-color: var(--media-focus-ring-color);
outline-offset: 2px;
}
}
.media-skin--minimal .media-time--current,
.media-skin--minimal .media-time-separator {
display: none;
}
@container media-root (width > 672px) {
.media-skin--minimal .media-time-controls {
flex-direction: row;
&:dir(rtl) {
flex-direction: row-reverse;
}
}
.media-skin--minimal .media-time--duration,
.media-skin--minimal .media-time-separator {
color: oklch(from currentColor l c h / 0.6);
}
.media-skin--minimal .media-time--current,
.media-skin--minimal .media-time-separator {
display: inline;
}
}
/* Base button */
.media-skin--minimal .media-button {
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
height: calc(var(--media-spacing) * 9.5);
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(var(--media-spacing) * 2);
transition-timing-function: ease-out;
transition-duration: 150ms;
transition-property: background-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;
}
}
@supports (corner-shape: squircle) {
.media-skin--minimal .media-button {
border-radius: calc(var(--media-spacing) * 4);
corner-shape: squircle;
}
}
/* Primary button variant */
.media-skin--minimal .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--minimal .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--minimal .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--minimal .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--minimal .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--minimal .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--minimal .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--minimal .media-button {
scale: 1;
transition-property: background-color;
will-change: auto;
}
}
.media-skin--minimal .media-button-group {
display: flex;
gap: 1px;
align-items: center;
&:dir(rtl) {
flex-direction: row-reverse;
}
}
.media-skin--minimal .media-badge {
padding: calc(var(--media-spacing) * 1) 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(var(--media-spacing) * 1);
}
.media-skin--minimal .media-icon__container {
position: relative;
}
.media-skin--minimal .media-icon {
flex-shrink: 0;
width: var(--media-icon-size);
height: var(--media-icon-size);
}
.media-skin--minimal .media-icon--flipped,
.media-skin--minimal:dir(rtl) .media-menu__chevron {
scale: -1 1;
}
.media-skin--minimal:dir(rtl) .media-menu__chevron.media-icon--flipped {
scale: 1 1;
}
.media-skin--minimal media-poster,
.media-skin--minimal > img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
transition: opacity 0.25s;
}
.media-skin--minimal media-poster:not([data-visible]),
.media-skin--minimal > img:not([data-visible]) {
opacity: 0;
}
.media-skin--minimal media-poster > slot > img:not([src]):not([srcset]),
.media-skin--minimal media-poster ::slotted(img:not([src]):not([srcset])),
.media-skin--minimal > img:not([src]):not([srcset]) {
visibility: hidden;
}
.media-skin--minimal media-poster ::slotted(img),
.media-skin--minimal 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--minimal > img {
object-fit: var(--media-object-fit, contain);
object-position: var(--media-object-position, center);
border-radius: inherit;
}
.media-skin--minimal:fullscreen media-poster ::slotted(img),
.media-skin--minimal:fullscreen media-poster img,
.media-skin--minimal:fullscreen > img {
object-fit: contain;
}
.media-skin--minimal .media-thumbnail {
position: relative;
pointer-events: none;
background-color: oklch(0 0 0 / 0.9);
border-radius: calc(var(--media-spacing) * 2);
&::after {
position: absolute;
inset: 0;
content: "";
border-radius: inherit;
box-shadow:
0 0 0 1px oklch(0 0 0 / 0.05),
0 1px 3px 0 oklch(0 0 0 / 0.2),
0 1px 2px -1px oklch(0 0 0 / 0.2);
}
.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;
}
.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--minimal .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;
border-radius: var(--media-track-border-radius);
&[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: inherit;
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;
&:first-child {
--media-internal-chapter-inset-start: 0px;
}
&:last-child {
--media-internal-chapter-inset-end: 0px;
}
.media-slider__chapter-track {
border-radius: var(--media-track-border-radius);
@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: 2px solid transparent;
outline-offset: -2px;
background-color: currentColor;
border-radius: calc(Infinity * 1px);
box-shadow:
0 0 0 1px var(--media-shadow-current-color, oklch(0 0 0 / 0.15)),
0 1px 3px 0 oklch(0 0 0 / 0.15),
0 1px 2px -1px oklch(0 0 0 / 0.15);
opacity: 0;
transform-origin: center;
scale: 0.7;
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: var(--media-focus-ring-color);
outline-offset: 2px;
}
&:focus-visible,
&.media-slider__thumb--persistent {
opacity: 1;
scale: 1;
}
@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;
}
}
@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: 28;
--media-max-size: min(calc(var(--media-spacing) * var(--media-max-size-factor)), 100cqi);
min-width: 100%;
height: calc(var(--media-spacing) * 1);
@container media-root (width > 512px) {
--media-max-size-factor: 36;
}
@container media-root (width > 672px) {
--media-max-size-factor: 48;
}
.media-slider__thumbnail,
.media-slider__value {
position: absolute;
left: var(--media-preview-left, var(--media-slider-pointer));
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;
transition-property: filter, opacity, scale;
}
.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) * 14));
}
.media-slider__value {
bottom: calc(100% + (var(--media-spacing) * 7));
display: flex;
flex-direction: row-reverse;
gap: calc(var(--media-spacing) * 2);
justify-content: center;
}
.media-slider__chapter-title {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&:empty {
display: none;
}
}
&::before {
position: absolute;
z-index: 1;
pointer-events: none;
content: "";
background-color: oklch(from currentColor l c h / 0.35);
opacity: 0;
scale: 0.5;
translate: -50% -50%;
transition-timing-function: ease-out;
transition-duration: 200ms;
transition-property: opacity, scale;
}
&[data-orientation="horizontal"]::before {
top: 50%;
left: var(--media-slider-pointer);
width: 1px;
height: calc(var(--media-spacing) * 5);
}
&[data-orientation="vertical"]::before {
top: calc(100% - var(--media-slider-pointer));
left: 50%;
width: calc(var(--media-spacing) * 5);
height: 1px;
}
&[data-pointing]:not([data-dragging])::before {
opacity: 1;
scale: 1;
}
}
&:is([data-pointing], :has(:focus-visible))
.media-slider__preview
:is(.media-slider__value, .media-slider__thumbnail) {
opacity: 1;
filter: blur(0);
scale: 1;
}
}
.media-skin--minimal {
--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--minimal .media-popover,
.media-skin--minimal .media-tooltip {
--media-popup-translate-distance: calc(var(--media-spacing) * 2);
margin: 0;
overflow: visible;
color: inherit;
border: 0;
transition: var(--media-popup-transition);
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
/* 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] {
filter: blur(4px);
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--minimal .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--minimal .media-tooltip {
padding: calc(var(--media-spacing) * 1) calc(var(--media-spacing) * 2);
font-size: var(--media-font-size-base);
color: var(--media-tooltip-text-color);
white-space: nowrap;
background-color: var(--media-tooltip-background-color);
border-radius: calc(var(--media-spacing) * 2);
box-shadow:
0 0 0 1px var(--media-tooltip-border-color),
0 4px 6px -1px oklch(0 0 0 / 0.2),
0 2px 4px -2px oklch(0 0 0 / 0.2);
backdrop-filter: var(--media-tooltip-backdrop-filter);
/* `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;
margin-right: calc(var(--media-spacing) * -1);
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.15);
border-radius: calc(var(--media-spacing) * 1);
}
}
.media-skin--minimal .media-popover--volume:has(media-volume-slider[data-hidden]) {
display: none;
}
.media-skin--minimal .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) * 2.5);
--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;
background-color: var(--media-popover-background-color);
border-radius: var(--media-menu-border-radius);
box-shadow:
0 0 0 1px var(--media-popover-border-color),
0 4px 6px -1px oklch(0 0 0 / 0.1),
0 2px 4px -2px oklch(0 0 0 / 0.1);
backdrop-filter: var(--media-popover-backdrop-filter);
@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: calc(var(--media-spacing) * 1) 0;
border-bottom: 1px solid oklch(1 0 0 / 0.1);
}
.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.5);
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-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--minimal {
--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) * -18);
}
@container media-root (width > 672px) {
&:has(.media-controls[data-visible]) > * {
--media-caption-track-y: calc(var(--media-spacing) * -12);
}
}
}
.media-skin--minimal 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--minimal .media-input-indicator {
position: absolute;
inset: 0;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
align-items: center;
justify-items: center;
overflow: hidden;
color: oklch(1 0 0);
pointer-events: none;
border-radius: inherit;
}
.media-skin--minimal {
.media-volume-indicator,
.media-status-indicator--state {
position: absolute;
inset-inline: 0;
top: 0;
display: flex;
justify-content: center;
padding-top: calc(var(--media-spacing) * 3);
padding-bottom: calc(var(--media-spacing) * 32);
color: inherit;
text-shadow: 0 1px 0 var(--media-shadow-current-color);
pointer-events: none;
background-image: linear-gradient(
to bottom,
oklch(0 0 0 / 0.35),
oklch(0 0 0 / 0.2) calc(var(--media-spacing) * 12),
oklch(0 0 0 / 0)
);
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;
padding: calc(var(--media-spacing) * 1) calc(var(--media-spacing) * 2.5);
}
.media-icon {
display: none;
flex-shrink: 0;
filter: drop-shadow(0 1px 0 var(--media-shadow-current-color));
}
.media-volume-indicator__value,
.media-status-indicator__value {
margin-left: auto;
}
@media (pointer: fine) {
transition-property: translate, filter, opacity;
will-change: translate, filter, opacity;
}
@media (pointer: coarse) {
transition-property: translate, opacity;
will-change: translate, opacity;
}
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
transition-property: translate, filter, opacity;
}
@media (prefers-reduced-transparency: reduce) or (prefers-contrast: more) {
.media-volume-indicator__content,
.media-status-indicator__content {
background: var(--media-controls-background-color);
border-radius: calc(var(--media-spacing) * 2);
}
}
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
transition-timing-function: ease-in;
transition-duration: 400ms;
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
filter: blur(8px);
}
}
&[data-ending-style] {
@media (prefers-reduced-motion: no-preference) {
translate: 0 -100%;
}
}
}
.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--minimal .media-volume-indicator {
.media-volume-indicator__content {
width: min(80%, calc(var(--media-spacing) * 56));
transform: translateX(0);
}
.media-volume-indicator__progress {
position: relative;
width: 100%;
height: calc(var(--media-spacing) * 0.75);
background: oklch(from currentColor l c h / 0.2);
border-radius: calc(Infinity * 1px);
box-shadow: 0 1px 0 var(--media-shadow-subtle-current-color);
&::before {
position: absolute;
inset-block: 0;
left: 0;
width: var(--media-volume-fill, 0%);
content: "";
background: var(--media-internal-accent-color);
border-radius: inherit;
transition: width 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]) .media-volume-indicator__content,
&[data-max]:not([data-starting-style], [data-ending-style]) .media-volume-indicator__content {
transform: translateX(0.25px);
transition: transform 300ms linear(0, -24 20%, 16 40%, -8 60%, 4 80%, 1);
}
}
}
.media-skin--minimal .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--minimal .media-status-indicator--playback {
transition-timing-function: ease-out;
transition-duration: 200ms;
transition-property: opacity, scale;
.media-icon {
grid-area: 1 / 1;
width: calc(var(--media-icon-size) * 2);
height: calc(var(--media-icon-size) * 2);
opacity: 0;
scale: 0;
transition-timing-function: ease-out;
transition-duration: 150ms;
transition-property: opacity, scale;
}
&[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--minimal .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;
}
}
/* Container */
/* :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--minimal:where(.media-skin--video) {
--media-default-accent-color: oklch(1 0 0);
--media-border-color: light-dark(oklch(0 0 0 / 0.15), 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-controls-background-color: transparent;
--media-controls-transition-duration: 100ms;
--media-controls-transition-timing-function: ease-out;
--media-dialog-transition-duration: 150ms;
--media-dialog-transition-delay: 100ms;
--media-dialog-transition-timing-function: ease-out;
--media-popup-transition-duration: 100ms;
--media-popup-transition-timing-function: ease-out;
--media-popover-backdrop-filter: blur(16px) saturate(1.5);
--media-popover-background-color: oklch(0 0 0 / 0.5);
--media-popover-border-color: oklch(1 0 0 / 0.1);
--media-tooltip-backdrop-filter: var(--media-popover-backdrop-filter);
--media-tooltip-background-color: var(--media-popover-background-color);
--media-tooltip-border-color: var(--media-popover-border-color);
--media-tooltip-text-color: currentColor;
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-controls-background-color: oklch(0 0 0);
--media-tooltip-background-color: oklch(0 0 0);
}
&:has(.media-controls: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--minimal: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) * 64);
max-height: calc(100% - var(--media-spacing) * 2);
padding: calc(var(--media-spacing) * 4);
color: oklch(1 0 0);
text-shadow: 0 1px 0 oklch(0 0 0 / 0.5);
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;
&[data-starting-style],
&[data-ending-style] {
opacity: 0;
scale: 0.95;
}
&[data-ending-style] {
transition-duration: max(calc(var(--media-dialog-transition-duration) - 100ms), 50ms);
transition-delay: 0ms;
}
}
.media-skin--minimal: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) * 1.5) 0;
overflow-y: auto;
}
.media-skin--minimal:where(.media-skin--video) .media-dialog__title {
font-size: var(--media-font-size-medium);
}
/* Controls (hide/show behavior) */
.media-skin--minimal:where(.media-skin--video) .media-controls {
--media-base-side-offset: 5;
--media-base-boundary-offset: 1;
--media-inset-factor: 1;
--media-inset: calc(var(--media-spacing) * var(--media-inset-factor));
--media-volume-mask: linear-gradient(to right, transparent 10%, #000 25%, #000 100%);
position: absolute;
inset-inline: var(--media-inset);
bottom: var(--media-inset);
z-index: 10;
flex-wrap: wrap;
column-gap: calc(var(--media-spacing) * 2);
color: oklch(1 0 0);
border-radius: calc(var(--media-spacing) * 3);
transition-timing-function: var(--media-controls-transition-timing-function);
/* Speed up the entry transition */
transition-duration: calc(var(--media-controls-transition-duration) / 2);
@media (pointer: fine) {
transition-property: translate, filter, opacity;
}
@media (pointer: coarse) {
transition-property: translate, opacity;
}
&:not([data-visible]) {
pointer-events: none;
opacity: 0;
transition-duration: var(--media-controls-transition-duration);
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
filter: blur(8px);
}
@media (prefers-reduced-motion: no-preference) {
translate: 0 100%;
}
}
.media-time-controls {
--media-slider-height: calc(var(--media-spacing) * 5);
flex: 0 0 100%;
order: -1;
padding-inline: calc(var(--media-spacing) * 1.5);
}
.media-button-group:first-child {
flex: 1;
text-align: left;
}
.media-button-group:last-child {
flex: 1;
justify-content: end;
}
:is(.media-time-controls, .media-button-group:last-child) {
mask-image: var(--media-volume-mask-image, none);
mask-repeat: no-repeat;
mask-position: var(--media-volume-mask-position, 100% 0);
mask-size: var(--media-volume-mask-size, 200% 100%);
transition: mask-position 50ms ease-out;
}
&:has(.media-button--mute[aria-expanded="true"]) {
@container media-root (width <= 672px) {
.media-button-group:last-child {
--media-volume-mask-image: var(--media-volume-mask);
--media-volume-mask-position: 0 0;
--media-volume-mask-size: 400% 100%;
}
}
@container media-root (width > 672px) {
.media-time-controls {
--media-volume-mask-image: var(--media-volume-mask);
--media-volume-mask-position: 0 0;
}
}
}
@container media-root (width > 672px) {
--media-inset-factor: 2;
--media-base-side-offset: 2;
flex-wrap: nowrap;
.media-time-controls {
--media-slider-height: calc(var(--media-spacing) * 8);
flex: 1;
order: unset;
}
.media-button-group:first-child,
.media-button-group:last-child {
flex: 0 0 auto;
}
}
}
/* Hide cursor when controls are hidden */
.media-skin--minimal:where(.media-skin--video):has(.media-controls:not([data-visible])) {
cursor: none;
}
/* Popups & Animations */
.media-skin--minimal:where(.media-skin--video) .media-popover--volume {
--media-popover-side-offset: 0rem;
padding: 0 calc(var(--media-spacing) * 3);
background: transparent;
}
/* Slider preview */
.media-skin--minimal:where(.media-skin--video) .media-slider__value {
padding-inline: calc(var(--media-spacing) * 3);
text-shadow: 0 1px 0 var(--media-shadow-current-color);
}
.media-skin--minimal:where(.media-skin--video) .media-slider .media-slider__preview {
--media-preview-end-inset: calc(100cqi - 100%);
--media-preview-left: clamp(
calc(var(--media-max-size) / 2),
var(--media-slider-pointer),
calc(100% - var(--media-max-size) / 2 + var(--media-preview-end-inset))
);
@container media-root (width > 672px) {
--media-preview-left: var(--media-slider-pointer);
}
}
'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 MinimalVideoSkinProps 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 MinimalVideoControls() {
return (
<Controls.Root>
<Controls.Backdrop className={'media-controls__backdrop'} />
<Controls.Content className={'media-controls media-controls'}>
<Tooltip.Provider>
<Controls.Group className={'media-controls-start'}>
<PlayButton />
<VolumePopover showTooltip side="right" orientation="horizontal" />
</Controls.Group>
<Controls.Group className={'media-time-slider-group'}>
<Time.Group className={'media-time-group'}>
<Time.Value className={'media-time-current-value'} type="current" toggle />
<Time.Separator className={'media-time-separator'} />
<Time.Value className={'media-time-duration-value'} type="duration" />
</Time.Group>
<TimeSlider previewOverflow="clamp" />
</Controls.Group>
<Controls.Group className={'media-controls-end'}>
<CaptionsButton />
<VideoSettingsMenu />
<Controls.Group className={'media-controls-trailing'}>
<CastButton />
<AirPlayButton />
<PiPButton />
<FullscreenButton />
</Controls.Group>
</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 MinimalVideoSkin({ children, className, poster, ...props }: MinimalVideoSkinProps = {}) {
const isPosterString = typeof poster === 'string';
return (
<Container className={`media-skin media-skin--minimal media-skin--video ${className ?? ''}`} {...props}>
{children}
<Poster src={isPosterString ? poster : undefined}>{isPosterString ? undefined : poster}</Poster>
<BufferingIndicator />
<ErrorDialog />
<MinimalVideoControls />
<VideoHotkeys />
<VideoGestures />
<VideoStatusIndicators />
</Container>
);
}
const Skin = MinimalVideoSkin;
// ================================================================
// Player
// ================================================================
export interface VideoPlayerProps {
children?: ReactNode;
style?: CSSProperties;
className?: string;
renderPoster?: Poster.Props['render'];
}
export function MinimalVideoSkin({ renderPoster, ...props }: MinimalVideoSkinProps) {
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--minimal.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-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--minimal.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--minimal.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-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-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--minimal.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--minimal.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--minimal.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--minimal.media-skin--video) {
@media (prefers-reduced-motion: reduce) {
}
.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--minimal.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--minimal.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--minimal.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-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--minimal.media-skin--video) {
.media-controls {
inset-inline: calc(var(--media-spacing) * 1);
bottom: calc(var(--media-spacing) * 1);
z-index: 20;
align-items: center;
column-gap: calc(var(--media-spacing) * 2);
padding: calc(var(--media-spacing) * 1);
color: #fff;
transition-property: filter, opacity, translate;
transition-duration: calc(var(--media-controls-transition-duration) / 2);
--media-popover-boundary-offset: calc(var(--media-spacing) * 2);
--media-popover-side-offset: calc(var(--media-spacing) * 5);
--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);
background-color: #0000;
border-radius: .75rem;
flex-wrap: wrap;
transition-timing-function: cubic-bezier(0, 0, .2, 1);
display: flex;
position: absolute;
}
.media-controls:not([data-visible]) {
pointer-events: none;
opacity: 0;
transition-duration: var(--media-controls-transition-duration);
}
@media (prefers-reduced-motion: no-preference) {
.media-controls:not([data-visible]) {
translate: 0 100%;
}
}
@media (prefers-contrast: more) {
.media-controls {
background-color: #000;
}
}
@container media-root (width >= 42rem) {
.media-controls {
inset-inline: calc(var(--media-spacing) * 2);
bottom: calc(var(--media-spacing) * 2);
--media-popover-side-offset: calc(var(--media-spacing) * 3);
flex-wrap: nowrap;
}
}
@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: #000;
}
}
.media-controls__backdrop {
pointer-events: none;
inset: calc(var(--media-spacing) * 0);
z-index: 10;
border-radius: inherit;
background-image: linear-gradient(to top, oklab(0% none none / .7) 0.0%, oklab(0% none none / .5) calc(var(--media-spacing) * 30), transparent 100.0%);
transition-property: opacity;
transition-duration: var(--media-controls-transition-duration);
transition-timing-function: cubic-bezier(0, 0, .2, 1);
position: absolute;
}
.media-controls__backdrop:not([data-visible]) {
opacity: 0;
}
.media-controls-end {
flex: 1;
justify-content: flex-end;
align-items: center;
gap: 1px;
display: flex;
}
@container media-root (width < 42rem) {
.media-controls-end {
transition: mask-position 50ms ease-out;
mask-position: 100% 0;
mask-size: 400% 100%;
mask-repeat: no-repeat;
}
@scope (.media-controls) {
&:has([data-volume-level][aria-expanded="true"]) .media-controls-end {
mask-image: linear-gradient(to right, #0000 10%, #000 25% 100%);
mask-position: 0 0;
}
}
}
@container media-root (width >= 42rem) {
.media-controls-end {
flex: none;
}
}
.media-controls-start {
flex: 1;
align-items: center;
gap: 1px;
display: flex;
}
@container media-root (width >= 42rem) {
.media-controls-start {
flex: none;
}
}
.media-controls-trailing {
align-items: center;
gap: 1px;
display: flex;
}
.media-time-current-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);
display: none;
}
.media-time-current-value:focus-visible {
outline-offset: 2px;
outline-color: #fff;
}
@supports (corner-shape: squircle) {
.media-time-current-value {
corner-shape: squircle;
border-radius: 1rem;
}
}
@container media-root (width >= 42rem) {
.media-time-current-value {
display: inline;
}
}
.media-time-duration-value {
font-variant-numeric: tabular-nums;
}
@container media-root (width >= 42rem) {
.media-time-duration-value {
color: currentColor;
}
@supports (color: color-mix(in lab, red, red)) {
.media-time-duration-value {
color: color-mix(in oklab, currentcolor 60%, transparent);
}
}
}
.media-time-group {
align-items: center;
gap: calc(var(--media-spacing) * 1);
display: flex;
}
.media-time-separator {
display: none;
}
@container media-root (width >= 42rem) {
.media-time-separator {
color: currentColor;
display: inline;
}
@supports (color: color-mix(in lab, red, red)) {
.media-time-separator {
color: color-mix(in oklab, currentcolor 60%, transparent);
}
}
}
.media-time-slider-group {
align-items: center;
gap: calc(var(--media-spacing) * 3);
padding-inline: calc(var(--media-spacing) * 1.5);
--media-slider-height: calc(var(--media-spacing) * 5);
flex-direction: row-reverse;
flex: 0 0 100%;
order: -1;
display: flex;
container: media-time-controls / inline-size;
}
@container media-root (width >= 42rem) {
.media-time-slider-group {
min-width: calc(var(--media-spacing) * 0);
--media-slider-height: calc(var(--media-spacing) * 8);
flex-direction: row;
flex: 1;
order: 0;
transition: mask-position 50ms ease-out;
mask-position: 100% 0;
mask-size: 200% 100%;
mask-repeat: no-repeat;
}
@scope (.media-controls) {
&:has([data-volume-level][aria-expanded="true"]) .media-time-slider-group {
mask-image: linear-gradient(to right, #0000 10%, #000 25% 100%);
mask-position: 0 0;
}
}
}
}
@scope (.media-skin--minimal.media-skin--video) {
@media (hover: hover) {
}
@supports (top: anchor(top)) {
@media (hover: hover) {
}
}
@media (prefers-reduced-motion: reduce) {
}
.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;
}
@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-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 (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--minimal.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;
}
}
@scope (.media-skin--minimal.media-skin--video) {
.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--minimal.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--minimal.media-skin--video) {
@media (prefers-reduced-motion: reduce) {
}
}
@scope (.media-skin--minimal.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--minimal.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--minimal.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--minimal.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--minimal.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--minimal.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--minimal.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--minimal.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--minimal.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--minimal.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--minimal.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--minimal.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--minimal.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;
}
}
}
@layer utilities;
v10 is built different
Video.js 10 is complete ground-up rewrite of the player for the modern web. The UI is separated from the underlying media renderer. Every component is independent and works together through open API contracts. We've structured the project for modern JavaScript bundlers to support tree-shaking and intelligent code splitting.
Start with a small player and only add what you need.
Download speeds
(based on slow 4G connection)VJS 8
VJS 8
3.96s/200kB
VJS 10
VJS 10
0.75s/38kB
Roadmap
Oct 2025
Tech Preview
Kick the tires, and light the fires
Mar 2026
Beta
Close to stable. Experimental adoption in real projects
Mid 2026
GA
Stable APIs. Feature parity w/ Media Chrome, Vidstack, Plyr.
End of 2026
Core Feature Parity
Video.js core/contrib plugins migrated
Sponsors
Corporate Shepherd
The role of Corporate Shepherd is held by the company that has been elected by the Video.js Technical Steering Committee (TSC) to be a steward of the project and make significant investment into the development of Video.js. The role is currently held by Mux, taking over for Brightcove in 2025. Mux is a leader in streaming video technology and was founded by Steve Heffernan, the creator of Video.js.