.cc-media-dialog { color-scheme: dark; --media-bg: #0b0d12; --media-fg: #eceef3; --media-muted: #98a1b3; --media-border: #2b3242; --media-accent: #7c5cff; --media-bar: #0b0d12; --media-danger: #f25f72; background: var(--media-bg); color: var(--media-fg); border: 1px solid var(--media-border); border-radius: 12px; padding: 0; width: min(1000px, calc(100vw - 32px)); max-width: 100%; max-height: calc(100dvh - 32px); margin: auto; overflow: auto; font: 14px/1.5 Inter, -apple-system, "Segoe UI", sans-serif; box-shadow: 0 18px 64px #0008; }
.cc-media-dialog[data-theme=light] { color-scheme: light; --media-bg: #f6f7f9; --media-fg: #11131a; --media-muted: #5d6678; --media-border: #dadee5; --media-accent: #6a4cff; --media-bar: #e3e5ea; --media-danger: #d02844; }
.cc-media-dialog::backdrop { background: #000b; }
.cc-media-dialog [hidden] { display: none !important; }
.cc-media-header { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 18px; }
.cc-media-title { font-size: 15px; line-height: 1.4; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin: 0; }
.cc-media-button { appearance: auto; background: transparent; border: 1px solid var(--media-border); border-radius: 6px; padding: 7px 12px; color: inherit; cursor: pointer; text-decoration: none; font: inherit; white-space: nowrap; }
.cc-media-button:hover { background: var(--media-border); }
.cc-media-button:focus-visible { outline: 2px solid var(--media-accent); outline-offset: 3px; }
.cc-media-button:disabled { opacity: .5; cursor: wait; }
.cc-media-viewport { position: relative; box-sizing: border-box; width: 100%; background: #000; aspect-ratio: 16 / 9; min-height: 200px; max-height: 65dvh; display: flex; align-items: center; justify-content: center; }
.cc-media-viewport[data-provider=Twitch] { min-height: 356px; }
.cc-media-viewport[data-controls=shared]:is([data-provider=YouTube], [data-provider=Vimeo]) { min-height: 256px; }
.cc-media-video, .cc-media-frame { display: block; width: 100%; height: 100%; min-width: 0; min-height: 0; object-fit: contain; border: 0; }
.cc-media-video:is(audio) { display: none; }
.cc-media-dialog:not(.cc-media-inline) .cc-media-viewport[data-controls=shared]:not(:fullscreen) { width: min(100%, calc(65dvh * 16 / 9)); margin-inline: auto; }
/* Every file has one control set (Discord's): one row of Play/Pause, the time, a seek bar
   whose played part is the accent colour, Volume (a vertical slider above its button) and, for
   video, Fullscreen. Video lays it over the bottom of its picture on a soft gradient: it shows
   on hover, focus, touch and while paused, and steps aside while playback runs and the pointer
   rests. Audio's bar is its whole player. Nothing animates while idle: a fill is a CSS variable
   set from media events, and transitions run only on hover or a state change. */
.cc-media-controls { --cc-track: #ffffff40; position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; box-sizing: border-box; padding: 24px 8px 4px; color: #fff; color-scheme: dark; background: linear-gradient(to top, #000000b8, #00000066 55%, transparent); container-type: inline-size; transition: opacity .2s ease; }
.cc-media-controls[data-kind=audio] { --cc-track: color-mix(in srgb, currentColor 22%, transparent); position: static; height: 100%; width: 100%; display: flex; align-items: center; padding: 0 6px; color: var(--media-fg); color-scheme: inherit; background: var(--media-bar); border-radius: 8px; }
.cc-media-controls[data-kind=audio] .cc-media-control-row { flex: 1 1 auto; }
.cc-media-viewport[data-idle=true] > .cc-media-controls:not(:focus-visible):not(:has(:focus-visible)) { opacity: 0; pointer-events: none; }
.cc-media-viewport[data-idle=true]:not(:has(:focus-visible)) { cursor: none; }
.cc-media-control-row { display: flex; align-items: center; gap: 4px; min-width: 0; }
.cc-media-controls .cc-media-button { display: grid; place-items: center; box-sizing: border-box; flex: 0 0 32px; width: 32px; height: 32px; min-height: 32px; padding: 5px; border: 0; border-radius: 6px; background: transparent; color: inherit; opacity: .9; }
.cc-media-controls .cc-media-button:hover { opacity: 1; background: color-mix(in srgb, currentColor 14%, transparent); }
.cc-media-controls .cc-media-button svg { display: block; width: 22px; height: 22px; }
.cc-media-time { flex: 0 0 auto; min-width: 0; padding: 0 6px 0 2px; white-space: nowrap; font: 600 13px/1 ui-monospace, "Cascadia Mono", Consolas, Menlo, monospace; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.cc-media-track { flex: 1 1 auto; min-width: 24px; display: flex; align-items: center; }
/* Ranges draw their own track: the played part in the accent colour, the rest a filled track. */
.cc-media-seek, .cc-media-volume { --cc-fill: 0%; appearance: none; -webkit-appearance: none; display: block; height: 16px; margin: 0; padding: 0; background: transparent; cursor: pointer; touch-action: manipulation; }
.cc-media-seek { width: 100%; }
.cc-media-seek::-webkit-slider-runnable-track, .cc-media-volume::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: linear-gradient(to right, var(--media-accent) var(--cc-fill), var(--cc-track) var(--cc-fill)); }
.cc-media-seek::-moz-range-track, .cc-media-volume::-moz-range-track { height: 6px; border-radius: 3px; background: linear-gradient(to right, var(--media-accent) var(--cc-fill), var(--cc-track) var(--cc-fill)); }
.cc-media-seek::-webkit-slider-thumb, .cc-media-volume::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; margin-top: -3px; border: 0; border-radius: 50%; background: #fff; box-shadow: 0 0 2px #0008; opacity: 0; transition: opacity .12s; }
.cc-media-seek::-moz-range-thumb, .cc-media-volume::-moz-range-thumb { width: 12px; height: 12px; border: 0; border-radius: 50%; background: #fff; box-shadow: 0 0 2px #0008; opacity: 0; }
.cc-media-track:hover .cc-media-seek::-webkit-slider-thumb, .cc-media-seek:focus-visible::-webkit-slider-thumb, .cc-media-volume::-webkit-slider-thumb { opacity: 1; }
.cc-media-track:hover .cc-media-seek::-moz-range-thumb, .cc-media-seek:focus-visible::-moz-range-thumb, .cc-media-volume::-moz-range-thumb { opacity: 1; }
.cc-media-seek:disabled { cursor: default; }
/* Volume: the speaker button, its vertical slider in a popover above it (Discord's and YouTube's;
   the owner, 2026-10-18: "just make it vertical"). It opens on hover and keyboard focus, stays
   150 ms after the pointer leaves and through a drag, and never covers or narrows the seek bar.
   Its foot meets the button, so the pointer crosses onto it without leaving either. The slider is
   a range turned upright (its low end at the bottom); `--cc-volume-length` is its length, which
   the script shortens in a short player so the popover stays inside it. It stays focusable while
   closed (transparent, not hidden), so Tab reaches it from the button and opens it. */
.cc-media-sound { --cc-volume-length: 80px; position: relative; display: flex; align-items: center; flex: 0 0 auto; }
.cc-media-volume-pop { position: absolute; z-index: 3; left: 50%; bottom: 100%; box-sizing: border-box; width: 36px; height: calc(var(--cc-volume-length) + 30px); margin-left: -18px; padding-bottom: 6px; opacity: 0; pointer-events: none; transition: opacity .12s ease .15s; }
.cc-media-volume-pop::before { content: ''; position: absolute; inset: 0 0 6px; border-radius: 8px; background: #000000c8; box-shadow: 0 4px 16px #0006; }
.cc-media-controls[data-kind=audio] .cc-media-volume-pop::before { background: var(--media-bg); border: 1px solid var(--media-border); }
.cc-media-sound:hover > .cc-media-volume-pop, .cc-media-sound:has(:focus-visible) > .cc-media-volume-pop, .cc-media-sound[data-dragging=true] > .cc-media-volume-pop { opacity: 1; pointer-events: auto; transition-delay: 0s; }
.cc-media-volume-pop .cc-media-volume { position: absolute; left: 50%; top: calc(12px + var(--cc-volume-length) / 2); width: var(--cc-volume-length); margin: -8px 0 0 calc(var(--cc-volume-length) / -2); transform: rotate(-90deg); }
.cc-media-seek:focus-visible, .cc-media-volume:focus-visible { outline: 2px solid var(--media-accent); outline-offset: 2px; border-radius: 3px; }
.cc-media-video:focus-visible { outline: 2px solid #fff; outline-offset: -2px; }
.cc-media-controls:focus-visible { outline: 2px solid var(--media-accent); outline-offset: -2px; }
.cc-media-play-overlay { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
.cc-media-play-large { display: grid; place-items: center; box-sizing: border-box; width: 56px; height: 56px; padding: 16px; border: 0; border-radius: 50%; color: #fff; background: #000000a0; box-shadow: 0 2px 12px #0004; pointer-events: auto; }
.cc-media-play-large:hover { background: #000000c8; }
.cc-media-play-large svg { display: block; width: 24px; height: 24px; }
.cc-media-viewport:fullscreen { width: 100vw; height: 100dvh; max-height: none; aspect-ratio: auto; }
/* Narrow pictures (portrait clips, phone columns) keep the essentials. */
@container (max-width: 300px) { .cc-media-control-row { gap: 2px; } .cc-media-time { font-size: 11px; padding: 0 3px 0 0; } .cc-media-controls .cc-media-button { flex-basis: 28px; width: 28px; } }
@container (max-width: 210px) { .cc-media-controls .cc-media-time { display: none; } }
.cc-media-footer { display: flex; flex-direction: column; gap: 8px; padding: 14px 18px 18px; }
.cc-media-status { font-size: 13px; margin: 0; }
.cc-media-status[data-error] { color: var(--media-danger); }
.cc-media-notice { margin: 0; color: var(--media-muted); font-size: 12px; }
.cc-media-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 4px; }
.cc-media-dialog[data-native=true] { width: 100vw; max-height: 100dvh; border: 0; border-radius: 0; }
@media(max-width: 480px) { .cc-media-dialog { width: calc(100vw - 16px); max-height: calc(100dvh - 16px); border-radius: 8px; } .cc-media-header, .cc-media-footer { padding: 12px; } .cc-media-button { min-height: 40px; } .cc-media-viewport { min-height: 200px; } }
@media(prefers-reduced-motion: reduce) { .cc-media-dialog * { scroll-behavior: auto; } }

/* The active player replaces exactly the painted poster, without modal chrome. */
.cc-media-inline { position: fixed; z-index: 20; margin: 0; padding: 0; max-width: none; max-height: none; border: 0; overflow: hidden; border-radius: 8px; box-sizing: border-box; box-shadow: none; background: #000; }
.cc-media-inline[hidden] { display: none !important; }
/* Chromium can occlude the GPU canvas at vertically mirrored overlay bounds.
   Keep browser overlays fractionally translucent so surrounding canvas pixels
   remain composed. Native WebViews do not overlap an HTML canvas. */
.cc-media-inline[data-native=false] { opacity: .999; }
.cc-media-inline .cc-media-viewport { width: 100%; height: 100%; min-height: 0; max-height: none; aspect-ratio: auto; }
/* Inline players are only the picture; the app's caption row owns their actions. */
.cc-media-inline .cc-media-title, .cc-media-inline .cc-media-notice { display: none; }
/* Audio has no picture: the player is exactly the app's control bar, drawn the same. */
.cc-media-inline[data-kind=audio], .cc-media-inline[data-kind=audio] .cc-media-viewport { justify-content: stretch; align-items: stretch; background: var(--media-bar); }
.cc-media-dialog[data-kind=audio]:not(.cc-media-inline) .cc-media-viewport { aspect-ratio: auto; min-height: 0; height: 44px; margin: 18px; width: auto; background: transparent; }
.cc-media-inline[data-kind=audio] .cc-media-footer { inset: 0; }
.cc-media-inline[data-kind=audio] .cc-media-status[data-error], .cc-media-inline[data-kind=audio] .cc-media-status[data-busy] { height: 100%; box-sizing: border-box; padding: 0 10px; display: flex; align-items: center; border-radius: 8px; font-size: 12px; line-height: 1.3; overflow: hidden; }
.cc-media-inline .cc-media-footer { position: absolute; z-index: 2; top: 8px; left: 8px; right: 8px; padding: 0; gap: 4px; pointer-events: none; }
.cc-media-inline .cc-media-status:not([data-error]):not([data-busy]) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
.cc-media-inline .cc-media-status[data-busy] { display: flex; align-items: center; gap: 8px; color: #fff; background: #15171ded; padding: 6px 8px; border-radius: 4px; }
.cc-media-status[data-busy]::before { content: ''; display: inline-block; flex: 0 0 12px; width: 12px; height: 12px; box-sizing: border-box; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: cc-media-spin 1s linear infinite; }
@keyframes cc-media-spin { to { transform: rotate(360deg); } }
@media(prefers-reduced-motion: reduce) { .cc-media-status[data-busy]::before { animation: none; } }
.cc-media-inline .cc-media-status[data-error] { color: #fff; background: #15171ded; padding: 8px; border-radius: 4px; }
/* The provider's frame already explains this failure: keep ours for assistive tech only. */
.cc-media-inline .cc-media-status[data-error][data-quiet] { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip-path: inset(50%); }
/* Seamless start (the owner's report of 2026-10-11): until a video's first frame is on screen, or a
   provider's player is ready, the player is clear. The app's poster shows through, the pointer goes
   to the app, and nothing of the player shows but the video's own picture once it has one (a
   <video> without a frame paints nothing). The app draws a spinner over its poster should this
   take more than 300 ms; Windows keeps its player window clipped away meanwhile. */
.cc-media-inline:not([data-kind=audio])[data-state=loading] { background: transparent; pointer-events: none; }
.cc-media-inline:not([data-kind=audio])[data-state=loading] .cc-media-viewport { background: transparent; }
.cc-media-inline:not([data-kind=audio])[data-state=loading] .cc-media-viewport > :not(video):not(.cc-media-video-host),
.cc-media-inline:not([data-kind=audio])[data-state=loading] .cc-media-footer { visibility: hidden; }
/* Buffering shows only once it has lasted 300 ms (a stall, not a seek's blink): a video's as a
   round spinner over its middle, its words for assistive technology. */
.cc-media-inline:not([data-kind=audio]) .cc-media-status[data-busy] { animation: cc-media-after .3s step-end both; }
@keyframes cc-media-after { from { opacity: 0; } to { opacity: 1; } }
.cc-media-inline[data-kind=video] .cc-media-footer:has(> .cc-media-status[data-busy]) { inset: 0; align-items: center; justify-content: center; }
.cc-media-inline[data-kind=video] .cc-media-status[data-busy] { box-sizing: border-box; width: 48px; height: 48px; padding: 0; justify-content: center; gap: 0; border-radius: 50%; font-size: 0; background: #000000a0; }
.cc-media-inline[data-kind=video] .cc-media-status[data-busy]::before { flex-basis: 22px; width: 22px; height: 22px; border-width: 3px; }
/* Provider frames keep their own controls. The invisible scroller receives wheel
   input the browser chains out of the frame, which the player hands to the app. */
.cc-media-wheel { position: relative; width: 100%; height: 100%; overflow-x: hidden; overflow-y: scroll; scrollbar-width: none; overscroll-behavior: contain; }
.cc-media-wheel::-webkit-scrollbar { display: none; }
.cc-media-wheel > .cc-media-frame { position: sticky; top: 0; height: 100%; }
.cc-media-wheel-space { height: 8000px; }
/* Fullscreen direct video: the toolbar steps aside while the pointer rests. */
.cc-media-inline[data-native=true] { position: absolute; inset: 0; width: 100vw; height: 100dvh; }
.cc-media-inline:fullscreen { inset: 0 !important; width: 100vw !important; height: 100dvh !important; clip-path: none !important; border-radius: 0; }
