@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
  --font-scale: 1.06;

  /* Vertical space the floating top header needs to clear (top offset 12px + pill height 44px +
     bottom breathing room ~12px). Module content pads its top by this so nothing hides under the
     header; kept in one place since App and Playlists both reference it. */
  --hdr-h: 68px;

  /* ===== Glass tunables — every value that materially drives the look lives here so it can be
     tuned in ONE place. ===== */
  /* GLOBAL baseline = "Adaptive": solid-enough dark glass that reads well on content-less chrome
     (nav/header/dialogs/filters/settings — where there's nothing behind the glass to refract).
     Rich-backdrop surfaces override these via `.glass-media` below. */
  --glass-blur: 20px; /* backdrop blur radius */
  --glass-saturate: 1.8; /* backdrop saturation */
  --glass-dark-bright: 1.25; /* extra brightness lift applied to .glass/.glass-menu in dark mode only */
  --glass-surface-alpha: 94%; /* .glass panel translucency (higher = more solid = "adaptive") */
  --glass-card-alpha: 94%; /* .glass-card translucency */
  --glass-menu-alpha: 98%; /* .glass-menu translucency */
  --glass-border-alpha: 78%; /* .glass border opacity */
  --glass-inset: 16%; /* top specular highlight strength (#fff N%) */
  --glass-edge: 10%; /* extra edge-light mixed into the TOP border (#fff N%) — 0 = off */
  --glass-scrim: 14%; /* under-content scrim: darkens surfaces toward --bg for text contrast — 0 = off */
  --ambient: 1.1; /* multiplier on the ambient accent backdrop pools */

  /* Per-scheme background image dim (see frontend/public/backdrops/): how strongly the faded --bg
     overlay hides the image — higher = fainter. Only in effect while data-backdrop="on". */
  --bg-fade: 60%;
}

/* ===== "Glass over image" — the translucent tier. Applies whenever a
   real image sits behind the surfaces: app-wide when the per-scheme background image is on
   (`html[data-backdrop="on"]`), and on the Plex art-backed detail views (`.glass-media`, which
   have their own art backdrop even when the global image is off). When there's nothing behind the
   glass (image off / perf), the :root defaults keep it solid & readable. ===== */
html[data-backdrop="on"],
.glass-media {
  --glass-blur: 10px;
  --glass-saturate: 1.6;
  --glass-dark-bright: 1.2;
  --glass-surface-alpha: 50%;
  --glass-card-alpha: 60%;
  --glass-menu-alpha: 66%;
  --glass-border-alpha: 80%;
  --glass-edge: 25%;
  --glass-inset: 15%;
  --glass-scrim: 30%;
}

/* Light theme carries no per-scheme background image, so the near-opaque :root (adaptive) glass
   reads as flat white and every panel becomes an opaque island. Give light its OWN translucent tier
   — one central override, every .glass* surface — so the ambient tint (and content) shows through
   and glass stays glassy in light too. (Perf mode below still forces solid + no blur.) */
html[data-theme="light"] {
  --glass-surface-alpha: 62%;
  --glass-card-alpha: 74%;
  --glass-menu-alpha: 86%;
}

/* Per-scheme background image, painted on <body> (the app root is transparent so it shows through
   the whole app and the glass refracts it). A faded --bg overlay keeps it subtle; `fixed` so it
   doesn't scroll. Dark theme uses the dark backdrops, light theme the lighter set in /light/. Only
   when the backdrop is on (the "Background image" setting; off in perf). The [data-theme] qualifier
   also out-specifies the ambient `background` shorthand (which would else reset background-size). */
html[data-backdrop="on"][data-theme="dark"][data-scheme="midnight"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/midnight.svg");
}
html[data-backdrop="on"][data-theme="dark"][data-scheme="forest"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/forest.svg");
}
html[data-backdrop="on"][data-theme="dark"][data-scheme="slate"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/slate.svg");
}
html[data-backdrop="on"][data-theme="dark"][data-scheme="youtube"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/youtube.svg");
}
html[data-backdrop="on"][data-theme="dark"][data-scheme="starship"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/starship.svg");
}
html[data-backdrop="on"][data-theme="dark"][data-scheme="matrix"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/matrix.svg");
}
html[data-backdrop="on"][data-theme="light"][data-scheme="midnight"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/light/midnight.svg");
}
html[data-backdrop="on"][data-theme="light"][data-scheme="forest"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/light/forest.svg");
}
html[data-backdrop="on"][data-theme="light"][data-scheme="slate"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/light/slate.svg");
}
html[data-backdrop="on"][data-theme="light"][data-scheme="youtube"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/light/youtube.svg");
}
html[data-backdrop="on"][data-theme="light"][data-scheme="starship"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/light/starship.svg");
}
html[data-backdrop="on"][data-theme="light"][data-scheme="matrix"] body {
  background-image:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent),
      color-mix(in srgb, var(--bg) var(--bg-fade), transparent)
    ),
    url("/backdrops/light/matrix.svg");
}
html[data-backdrop="on"][data-theme="dark"] body,
html[data-backdrop="on"][data-theme="light"] body {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
}

/* Make native controls (date picker, scrollbars) follow the theme. */
html[data-theme="dark"] {
  color-scheme: dark;
}
html[data-theme="light"] {
  color-scheme: light;
}

html {
  font-size: calc(16px * var(--font-scale));
  background: var(--bg);
}

body {
  margin: 0;
  color: var(--fg);
  /* Ambient backdrop so translucent "glass" surfaces have soft color to refract. Kept
     subtle but a touch richer (three soft pools, incl. a bottom glow) now that the nav,
     header and dialogs are all frosted glass and refract it. */
  background:
    radial-gradient(
      1100px 620px at 10% -10%,
      color-mix(in srgb, var(--accent) calc(20% * var(--ambient)), transparent),
      transparent 60%
    ),
    radial-gradient(
      1000px 720px at 115% 10%,
      color-mix(in srgb, var(--accent) calc(14% * var(--ambient)), transparent),
      transparent 55%
    ),
    radial-gradient(
      900px 640px at 50% 118%,
      color-mix(in srgb, var(--accent) calc(11% * var(--ambient)), transparent),
      transparent 60%
    ),
    var(--bg);
  background-attachment: fixed;
}

/* Hide the native scrollbar while keeping the element scrollable (wheel/trackpad/keyboard).
   Used on the nav rail so a high browser-zoom overflow scrolls without showing a scrollbar. */
.no-scrollbar {
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* legacy Edge/IE */
}
.no-scrollbar::-webkit-scrollbar {
  display: none; /* Chromium/WebKit */
}

/* ===== Liquid-glass surface system (theme-aware, GPU-light) ===== */
.glass {
  /* Frosted overlay surface: translucent enough that the blurred backdrop shows
     through (the glassy look), opaque enough that the background isn't distracting.
     The strong blur turns whatever is behind into soft colour, not a sharp image.
     Layer 1 (top) = the optional scrim; layer 2 = the translucent surface tint. */
  background:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--glass-scrim), transparent),
      color-mix(in srgb, var(--bg) var(--glass-scrim), transparent)
    ),
    color-mix(in srgb, var(--surface) var(--glass-surface-alpha), transparent);
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border: 1px solid color-mix(in srgb, var(--border) var(--glass-border-alpha), transparent);
  border-top-color: color-mix(
    in srgb,
    #fff var(--glass-edge),
    color-mix(in srgb, var(--border) var(--glass-border-alpha), transparent)
  );
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff var(--glass-inset), transparent),
    0 18px 44px -16px rgba(0, 0, 0, 0.6);
}
.glass-card {
  /* No backdrop-filter here: cards render in bulk (feed grid) over a solid background
     where blur adds almost nothing visually but is GPU-expensive and triggers reflow.
     Translucency + border + depth keep the look; blur is reserved for .glass overlays. */
  background:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--glass-scrim), transparent),
      color-mix(in srgb, var(--bg) var(--glass-scrim), transparent)
    ),
    color-mix(in srgb, var(--card) var(--glass-card-alpha), transparent);
  border: 1px solid color-mix(in srgb, var(--border) 65%, transparent);
  border-top-color: color-mix(
    in srgb,
    #fff var(--glass-edge),
    color-mix(in srgb, var(--border) 65%, transparent)
  );
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff calc(var(--glass-inset) / 2), transparent),
    0 8px 22px -14px rgba(0, 0, 0, 0.45);
}
.glass-menu {
  /* Floating menus/popovers hover over undimmed content (no backdrop scrim like dialogs),
     so they must be near-opaque to stay readable — only a hint of translucency + the blur. */
  background:
    linear-gradient(
      color-mix(in srgb, var(--bg) var(--glass-scrim), transparent),
      color-mix(in srgb, var(--bg) var(--glass-scrim), transparent)
    ),
    color-mix(in srgb, var(--surface) var(--glass-menu-alpha), transparent);
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
  border: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
  border-top-color: color-mix(
    in srgb,
    #fff var(--glass-edge),
    color-mix(in srgb, var(--border) 80%, transparent)
  );
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff calc(var(--glass-inset) - 2%), transparent),
    0 18px 44px -16px rgba(0, 0, 0, 0.6);
}
.glass-hover:hover {
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #fff 12%, transparent),
    0 14px 30px -14px rgba(0, 0, 0, 0.5);
}

/* Dark mode: the ambient accent pools are faint over a near-black bg, so the docked frosted
   chrome (nav/header) barely reads — there's no content behind it to refract, unlike dialogs
   which sit over the feed. Strengthen the pools and let a touch more bleed through the glass.
   (The full "videos behind glass everywhere" effect is Phase 2 / end-of-project polish.) */
html[data-theme="dark"] body {
  background:
    radial-gradient(
      1100px 620px at 10% -10%,
      color-mix(in srgb, var(--accent) calc(34% * var(--ambient)), transparent),
      transparent 60%
    ),
    radial-gradient(
      1000px 720px at 115% 10%,
      color-mix(in srgb, var(--accent) calc(24% * var(--ambient)), transparent),
      transparent 55%
    ),
    radial-gradient(
      900px 640px at 50% 118%,
      color-mix(in srgb, var(--accent) calc(18% * var(--ambient)), transparent),
      transparent 60%
    ),
    var(--bg);
  background-attachment: fixed;
}
/* Dark glass reads faint because the blurred backdrop is itself dark; lift its brightness so
   the frosted sheen shows even over dark UI (over colourful content it just looks richer). */
html[data-theme="dark"] .glass,
html[data-theme="dark"] .glass-menu {
  backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate))
    brightness(var(--glass-dark-bright));
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate))
    brightness(var(--glass-dark-bright));
}
/* Toasts surface bottom-left (by the nav's notification bell), off the conventional
   top-right; a brighter rim draws the eye there. Most needed in dark mode, where the
   default glass border (dark navy) all but vanishes against the backdrop. */
html[data-theme="dark"] .toast-card {
  border-color: color-mix(in srgb, #fff 50%, transparent);
}

/* Performance mode (Settings → Appearance) drops the expensive blur + soft shadows. */
html[data-perf="1"] .glass,
html[data-perf="1"] .glass-menu,
html[data-perf="1"] .glass-card {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  background: var(--surface);
  box-shadow: 0 2px 8px -4px rgba(0, 0, 0, 0.4);
}
html[data-perf="1"] body {
  background: var(--bg);
}

/* Skip layout/paint for off-screen feed cards so long lists stay smooth while
   scrolling. contain-intrinsic-size reserves an approximate box so the scrollbar
   stays stable; `auto` lets the browser remember each card's real size after it
   has rendered once. */
.cv-card {
  content-visibility: auto;
  contain-intrinsic-size: auto 320px;
}
.cv-row {
  content-visibility: auto;
  contain-intrinsic-size: auto 96px;
}

/* ===== Motion ===== */
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes overlayIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes overlayOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
@keyframes panelIn {
  from {
    transform: translateX(100%);
  }
  to {
    transform: translateX(0);
  }
}
@keyframes panelOut {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(100%);
  }
}
@keyframes popIn {
  from {
    opacity: 0;
    transform: translateY(-6px) scale(0.97);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
/* One-shot attention flash for a chat dock window on a new message. Inset glow so the
   window's own overflow-hidden doesn't clip it; pulses twice then fades. */
@keyframes chatFlash {
  0% {
    box-shadow: inset 0 0 0 0 transparent;
  }
  18% {
    box-shadow:
      inset 0 0 0 3px var(--accent),
      inset 0 0 22px 0 color-mix(in srgb, var(--accent) 55%, transparent);
  }
  40% {
    box-shadow: inset 0 0 0 1px transparent;
  }
  62% {
    box-shadow:
      inset 0 0 0 3px var(--accent),
      inset 0 0 22px 0 color-mix(in srgb, var(--accent) 55%, transparent);
  }
  100% {
    box-shadow: inset 0 0 0 0 transparent;
  }
}
.chat-flash {
  animation: chatFlash 1.1s ease-out;
}

/* ===== Color schemes (accent + neutrals), each with dark + light ===== */

/* Midnight — deep navy/slate with blue accent (default) */
html[data-scheme="midnight"][data-theme="dark"] {
  --bg: #0b1020;
  --surface: #121a2e;
  --card: #161f38;
  --border: #243049;
  --fg: #e6e9f0;
  --muted: #97a3c0;
  --accent: #6d8cff;
  --accent-fg: #0b1020;
}
html[data-scheme="midnight"][data-theme="light"] {
  --bg: #f4f6fc;
  --surface: #ffffff;
  --card: #ffffff;
  --border: #dde3f0;
  --fg: #1a2238;
  --muted: #5b6685;
  --accent: #3b5bdb;
  --accent-fg: #ffffff;
}

/* Forest — dark slate with teal/green accent */
html[data-scheme="forest"][data-theme="dark"] {
  --bg: #0a1512;
  --surface: #0f1f1a;
  --card: #12241e;
  --border: #1f3a30;
  --fg: #e6f0ec;
  --muted: #90b1a4;
  --accent: #2dd4bf;
  --accent-fg: #04110d;
}
html[data-scheme="forest"][data-theme="light"] {
  --bg: #f1f7f4;
  --surface: #ffffff;
  --card: #ffffff;
  --border: #d6e7e0;
  --fg: #102a22;
  --muted: #4d6b60;
  --accent: #0d9488;
  --accent-fg: #ffffff;
}

/* Slate — neutral grey with warm orange accent (muted in dark) */
html[data-scheme="slate"][data-theme="dark"] {
  --bg: #15171c;
  --surface: #1b1e25;
  --card: #1f232b;
  --border: #2c313b;
  --fg: #e7e9ee;
  --muted: #9aa1ad;
  --accent: #e8913c;
  --accent-fg: #1a1206;
}
html[data-scheme="slate"][data-theme="light"] {
  --bg: #f6f7f9;
  --surface: #ffffff;
  --card: #ffffff;
  --border: #e3e6eb;
  --fg: #1c1f26;
  --muted: #5d636e;
  --accent: #d97706;
  --accent-fg: #ffffff;
}

/* YouTube — near-black with red accent */
html[data-scheme="youtube"][data-theme="dark"] {
  --bg: #0f0f0f;
  --surface: #181818;
  --card: #1f1f1f;
  --border: #303030;
  --fg: #f1f1f1;
  --muted: #aaaaaa;
  --accent: #ff3b46;
  --accent-fg: #ffffff;
}
html[data-scheme="youtube"][data-theme="light"] {
  --bg: #ffffff;
  --surface: #f9f9f9;
  --card: #ffffff;
  --border: #e5e5e5;
  --fg: #0f0f0f;
  --muted: #606060;
  --accent: #ff0033;
  --accent-fg: #ffffff;
}

/* Starship — deep space blue-black with a bright azure "LCARS/computer" accent */
html[data-scheme="starship"][data-theme="dark"] {
  --bg: #050b16;
  --surface: #0b1728;
  --card: #101f36;
  --border: #1f3557;
  --fg: #dfeaff;
  --muted: #8aa6cc;
  --accent: #38b6ff;
  --accent-fg: #04101f;
}
html[data-scheme="starship"][data-theme="light"] {
  --bg: #eef4fb;
  --surface: #ffffff;
  --card: #ffffff;
  --border: #d3e0f0;
  --fg: #0b1b30;
  --muted: #4a5f7d;
  --accent: #0b6bd6;
  --accent-fg: #ffffff;
}

/* Matrix — near-black with a muted terminal-green accent (softened from neon phosphor) */
html[data-scheme="matrix"][data-theme="dark"] {
  --bg: #030a06;
  --surface: #08130d;
  --card: #0b1c12;
  --border: #163d27;
  --fg: #cfe8d6;
  --muted: #6fae86;
  --accent: #46b87c;
  --accent-fg: #04170c;
}
html[data-scheme="matrix"][data-theme="light"] {
  --bg: #f0f7f1;
  --surface: #ffffff;
  --card: #ffffff;
  --border: #cfe6d6;
  --fg: #08130b;
  --muted: #4c6b56;
  --accent: #12a150;
  --accent-fg: #ffffff;
}

/* Toast auto-dismiss countdown bar (shrinks left-to-right to zero) */
@keyframes toastbar {
  from {
    transform: scaleX(1);
  }
  to {
    transform: scaleX(0);
  }
}

/* The in-app player stage filling the screen: either because something fullscreened it (YouTube's
   own button hands the lock to the iframe, not to us — but keep this for any browser that does),
   or via our own F-key maximise. `--max` deliberately does NOT use the Fullscreen API: while we
   hold the browser's lock, the cross-origin YouTube embed never learns it is fullscreen and its own
   fullscreen button stops working (see PlayerModal.toggleFullscreen). */
.player-stage:fullscreen,
.player-stage--max {
  aspect-ratio: auto;
  border-radius: 0;
}

/* A fullscreened element is already sized by the browser; the viewport units are only for the
   `:fullscreen` path, where the stage is not positioned. */
.player-stage:fullscreen {
  width: 100vw;
  height: 100vh;
}

/* Sizing, precisely: the element keeps Tailwind's `w-full` from its base className, so the WIDTH is
   `100%` of the containing block — which, for a fixed element, is the viewport minus any classic
   scrollbar. The HEIGHT comes from `inset: 0` (top+bottom, once `aspect-ratio` is released above).
   `right: 0` is therefore ignored (over-constrained: left + width win) — harmless, but don't read
   this rule as inset-sized. What had to go are the viewport units it used to inherit: `100vw`
   INCLUDES the scrollbar (horizontal overflow) and `100vh` includes a mobile browser's retracting
   chrome, which pushes the bottom edge — YouTube's own control bar — off screen. */
.player-stage--max {
  position: fixed;
  inset: 0;
  /* rail-level (40): this stage only has to beat the modal chrome it is nested inside (whose own
     children top out at z-menu/20). The modal root is a z-overlay stacking context, so nothing
     here escapes it — 9999 is the glass tuner's reserved level and claimed an authority this
     layer neither has nor needs. */
  z-index: 40;
}

/* Thin, theme-aware scrollbars */
* {
  scrollbar-color: var(--border) transparent;
}
*::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
*::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 8px;
}
