/* ==========================================================================
   MEDIA MAKER — design system
   One file. Dark cinematic ground, warm bias, single amber accent.
   Display: Fraunces · Body: Inter · Urdu: Noto Nastaliq Urdu ·
   Arabic: Noto Naskh Arabic

   LAYOUT OF THIS FILE
     1. Tokens          — :root, plus the light-theme override
     2. Reset & ground
     3. Primitives      — type, buttons, chips, forms
     4. Chrome          — header, nav, flashes/toasts, footer
     5. Page systems    — landing, catalogues, dashboard, studio, admin
     6. Components (v2) — the documented, reusable layer at the bottom of
                          this file. New pages should build from there.

   RULES OF THE ROAD
     · Nothing outside the token block hard-codes a colour. If you need a
       new one, add a token and define it for BOTH themes.
     · Every class already in use keeps working — the 2026 pass is
       additive. Where a rule was wrong (contrast, unscoped Nastaliq,
       inputs with no type) it was corrected in place, not forked.
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   The dark theme is the default and lives on bare :root. A page can opt
   into the light theme with <html data-theme="light">; only the values
   that must change are redefined there, so any rule written against the
   tokens works in both. There is no toggle in the UI yet — the layer is
   here so one can land without another CSS pass.
   ========================================================================== */

:root {
  color-scheme: dark;

  /* -- ground ----------------------------------------------------------- */
  --ink-0: #0b0906;            /* page ground — near-black, warm */
  --ink-1: #120e09;            /* raised ground */
  --ink-2: #1a150e;            /* highest ground (cards on cards) */
  --glass: rgba(255, 244, 224, 0.035);
  --glass-strong: rgba(255, 244, 224, 0.06);
  --line: rgba(255, 236, 205, 0.10);
  --line-strong: rgba(255, 236, 205, 0.18);
  --scrim: rgba(7, 5, 3, 0.88);           /* over imagery */
  --field-bg: rgba(0, 0, 0, 0.32);

  /* -- text -------------------------------------------------------------
     --text-low was #837a68: 4.43:1 on a card and 4.21:1 on --glass-strong,
     i.e. below AA for the 12–13 px sizes it is used at (U-u15). Lifted to
     #9a9080 — 5.6:1 on the page ground, 5.3:1 on a card. */
  --text-hi: #f4eee2;
  --text-mid: #c2b6a0;
  --text-low: #9a9080;

  /* -- the one accent — film-light amber -------------------------------- */
  --amber: #f2b544;
  --amber-hot: #ffcd6b;
  --amber-deep: #b9821f;
  --amber-ink: #1c1204;        /* text on amber */
  /* Ink for a fill that is pale in BOTH themes (the six speaker pastels).
     It is deliberately NOT redefined for the light theme: the fill does
     not change, so neither may the ink. */
  --on-pastel: #1c1204;
  --amber-glow: rgba(242, 181, 68, 0.16);
  /* --accent was used nine times and never defined, so the calendar day
     badge, the selected day and the studio "will regenerate" marker had
     no colour at all (U-u1). Same for --good in studio.html. They are
     aliases, not new hues: the palette still has one accent. */
  --accent: var(--amber);
  --accent-hot: var(--amber-hot);
  --accent-ink: var(--amber-ink);
  --accent-glow: var(--amber-glow);

  /* -- status hues (muted, chip-only) ----------------------------------- */
  --ok: #7fc98a;
  --ok-bg: rgba(127, 201, 138, 0.12);
  --good: var(--ok);
  --good-bg: var(--ok-bg);
  --warn: #e6b45a;
  --warn-bg: rgba(230, 180, 90, 0.12);
  --info: #8db4d8;
  --info-bg: rgba(141, 180, 216, 0.12);
  --bad: #e07a6b;
  --bad-bg: rgba(224, 122, 107, 0.13);
  --neutral: #a49a86;
  --neutral-bg: rgba(164, 154, 134, 0.12);

  /* -- faces ------------------------------------------------------------
     Arabic used to fall through to Noto Nastaliq Urdu, which typesets it
     in a Persian hanging style no Arabic reader expects (U-u3). */
  --font-display: "Fraunces", "Georgia", serif;
  --font-body: "Inter", "Segoe UI", system-ui, sans-serif;
  --font-urdu: "Noto Nastaliq Urdu", "Fraunces", serif;
  --font-arabic: "Noto Naskh Arabic", "Segoe UI", "Times New Roman", serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;

  /* -- type scale -------------------------------------------------------
     Fluid where it carries the page, fixed where it labels the UI. */
  --fs-xs:   0.72rem;          /* eyebrows, kbd, counts */
  --fs-sm:   0.82rem;          /* meta, hints */
  --fs-base: 0.94rem;          /* body in app chrome */
  --fs-md:   1.05rem;          /* lede, section intros */
  --fs-lg:   clamp(1.15rem, 1.6vw, 1.35rem);
  --fs-xl:   clamp(1.35rem, 2.2vw, 1.75rem);
  --fs-2xl:  clamp(1.85rem, 3.6vw, 2.75rem);
  --fs-3xl:  clamp(2.4rem, 5.4vw, 3.6rem);
  --fs-4xl:  clamp(2.7rem, 6.2vw, 4.4rem);
  --lh-tight: 1.12;
  --lh-body: 1.65;
  --tracking-caps: 0.16em;

  /* -- spacing scale ----------------------------------------------------
     A 4 px base. Use these instead of ad-hoc rem values. */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.25rem;
  --sp-6: 1.5rem;
  --sp-8: 2rem;
  --sp-10: 2.5rem;
  --sp-12: 3rem;
  --sp-16: 4rem;

  /* -- radii ------------------------------------------------------------ */
  --radius-xs: 5px;
  --radius-s: 8px;
  --radius-m: 14px;
  --radius-l: 22px;
  --radius-xl: 30px;
  --radius-pill: 999px;

  /* -- layout ----------------------------------------------------------- */
  --container: 1160px;
  --container-wide: 1360px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
  --section-gap: clamp(4.5rem, 10vw, 8.5rem);
  --header-h: 76px;

  /* -- motion ----------------------------------------------------------- */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --speed-fast: 120ms;
  --speed: 240ms;
  --speed-slow: 460ms;

  /* -- elevation --------------------------------------------------------
     One ramp. --shadow-card/--shadow-pop are the old names, kept so every
     existing rule still resolves. */
  --shadow-1: 0 1px 0 rgba(255, 236, 205, 0.05) inset,
              0 20px 50px -30px rgba(0, 0, 0, 0.9);
  --shadow-2: 0 30px 70px -30px rgba(0, 0, 0, 0.95), 0 0 0 1px var(--line);
  --shadow-3: 0 40px 90px -24px rgba(0, 0, 0, 0.96), 0 0 0 1px var(--line-strong);
  --shadow-card: var(--shadow-1);
  --shadow-pop: var(--shadow-2);
  --focus-ring: 0 0 0 3px var(--amber-glow);

  /* -- z-index ----------------------------------------------------------
     Six stops, nothing between them. Anything that needs to sit above
     another layer belongs in this list, not on a made-up number. */
  --z-base: 1;
  --z-sticky: 50;     /* filter bars under the header */
  --z-header: 100;
  --z-overlay: 200;   /* skip link, backdrops */
  --z-modal: 300;
  --z-toast: 400;
}

/* Light theme. Same structure, same token names — only the values move.
   Kept deliberately warm so the brand does not turn into a generic white
   SaaS page: paper, not screen. */
:root[data-theme="light"] {
  color-scheme: light;

  --ink-0: #faf6ef;
  --ink-1: #ffffff;
  --ink-2: #f3ece0;
  --glass: rgba(28, 18, 4, 0.028);
  --glass-strong: rgba(28, 18, 4, 0.055);
  --line: rgba(28, 18, 4, 0.12);
  --line-strong: rgba(28, 18, 4, 0.22);
  --scrim: rgba(255, 250, 242, 0.9);
  --field-bg: #ffffff;

  --text-hi: #1c1509;
  --text-mid: #574d3c;          /* 7.4:1 on --ink-0 */
  --text-low: #6b6152;          /* 5.5:1 on --ink-0 */

  /* #9a6a06 was documented as "AA against paper" and is not: measured in
     the browser on the light theme it is 4.39:1 on --ink-0, 4.09:1 under
     a .schip and 3.85:1 on a callout — below AA at every size the accent
     is actually used at (11.5 px eyebrows, 13.4 px chips, body links).
     #8a5e05 measures 5.29 / 4.86 / 4.64 on those same three grounds.
     The dark theme's --amber is untouched: it is 8.9:1 there. */
  --amber: #8a5e05;
  --amber-hot: #7d5504;
  --amber-deep: #f2b544;
  --amber-ink: #fffaf0;
  --amber-glow: rgba(154, 106, 6, 0.14);

  --ok: #2f7a45;
  --ok-bg: rgba(47, 122, 69, 0.12);
  --warn: #8a5c05;
  --warn-bg: rgba(138, 92, 5, 0.12);
  --info: #245f8c;
  --info-bg: rgba(36, 95, 140, 0.12);
  --bad: #a53324;
  --bad-bg: rgba(165, 51, 36, 0.12);
  --neutral: #5d5445;
  --neutral-bg: rgba(93, 84, 69, 0.12);

  --shadow-1: 0 1px 2px rgba(28, 18, 4, 0.06), 0 12px 30px -22px rgba(28, 18, 4, 0.5);
  --shadow-2: 0 18px 44px -22px rgba(28, 18, 4, 0.4), 0 0 0 1px var(--line);
  --shadow-3: 0 28px 60px -20px rgba(28, 18, 4, 0.45), 0 0 0 1px var(--line-strong);
}

/* --------------------------------------------------------------------------
   Reset & ground
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background:
    radial-gradient(1200px 600px at 70% -10%, var(--amber-glow), transparent 60%),
    radial-gradient(900px 500px at 0% 110%, var(--amber-glow), transparent 55%),
    var(--ink-0);
  color: var(--text-hi);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.65;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
}

main { flex: 1 0 auto; }

img, svg, video { max-width: 100%; display: block; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 560;
  line-height: 1.12;
  letter-spacing: -0.015em;
  margin: 0 0 0.6em;
  text-wrap: balance;
}

h1 { font-size: clamp(2.5rem, 6.2vw, 4.4rem); }
h2 { font-size: clamp(1.85rem, 3.6vw, 2.75rem); }
h3 { font-size: clamp(1.2rem, 2vw, 1.5rem); }
h4 { font-size: 1.05rem; }

p { margin: 0 0 1em; }

a {
  color: var(--amber);
  text-decoration: none;
  transition: color var(--speed) var(--ease-out);
}
a:hover { color: var(--amber-hot); }

::selection { background: var(--amber); color: var(--amber-ink); }

:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 3px;
  border-radius: 4px;
}

.container {
  width: min(var(--container), 100% - 2 * var(--gutter));
  margin-inline: auto;
}

.skip-link {
  position: absolute;
  top: -60px;
  left: 1rem;
  z-index: 200;
  background: var(--amber);
  color: var(--amber-ink);
  padding: 0.6rem 1rem;
  border-radius: var(--radius-s);
  font-weight: 600;
  transition: top var(--speed) var(--ease-out);
}
.skip-link:focus { top: 1rem; color: var(--amber-ink); }

/* --------------------------------------------------------------------------
   Script-aware typography

   The old rule was `[lang="ur"], .urdu, [dir="rtl"] textarea` — every
   right-to-left field, in any language, was set in Noto Nastaliq Urdu,
   and Arabic (which is never Nastaliq) came out in a Persian hanging
   style (U-u3). Direction is now the element's own business (dir="auto"
   on anything user-supplied, U-u2); the FACE follows the language, and
   only the language.
   -------------------------------------------------------------------------- */

[lang|="ur"], .urdu, .lang-urdu {
  font-family: var(--font-urdu);
  line-height: 2.1;
}
[lang|="ar"], .lang-arabic {
  font-family: var(--font-arabic);
  line-height: 1.9;
}
[lang|="fa"], [lang|="ps"] {         /* Persian/Pashto read Nastaliq too */
  font-family: var(--font-urdu);
  line-height: 2.1;
}
/* Hindi and English carry no override at all: Inter and the system
   Devanagari fallback are correct, and forcing a face here is what
   scrambled 'SIP या FD: 10 साल बाद कौन जीता?'. */

/* --------------------------------------------------------------------------
   Micro-labels, eyebrows, section headers
   -------------------------------------------------------------------------- */

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--amber);
  margin-bottom: 1.1rem;
}
.eyebrow::before {
  content: "";
  width: 26px;
  height: 1px;
  background: linear-gradient(90deg, var(--amber), transparent);
}

.section {
  padding-block: calc(var(--section-gap) / 2);
}

.section-head {
  max-width: 640px;
  margin-bottom: clamp(2.25rem, 5vw, 3.75rem);
}
.section-head p {
  color: var(--text-mid);
  font-size: 1.05rem;
}
.section-head.is-centered {
  margin-inline: auto;
  text-align: center;
}
.section-head.is-centered .eyebrow::before { display: none; }

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 0.78rem 1.5rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font: 600 0.95rem/1 var(--font-body);
  letter-spacing: 0.01em;
  cursor: pointer;
  white-space: nowrap;
  transition: transform var(--speed) var(--ease-out),
              box-shadow var(--speed) var(--ease-out),
              background var(--speed) var(--ease-out),
              border-color var(--speed) var(--ease-out),
              color var(--speed) var(--ease-out);
}
.btn svg { width: 17px; height: 17px; }

.btn-primary {
  background: linear-gradient(180deg, var(--amber-hot), var(--amber));
  color: var(--amber-ink);
  box-shadow: 0 8px 30px -10px var(--amber-glow), 0 1px 0 rgba(255,255,255,0.25) inset;
}
.btn-primary:hover {
  transform: translateY(-2px);
  color: var(--amber-ink);
  box-shadow: 0 14px 38px -10px rgba(242, 181, 68, 0.45), 0 1px 0 rgba(255,255,255,0.3) inset;
}
.btn-primary:active { transform: translateY(0); }

.btn-ghost {
  background: transparent;
  border-color: var(--line-strong);
  color: var(--text-hi);
}
.btn-ghost:hover {
  border-color: var(--amber);
  color: var(--amber-hot);
  transform: translateY(-2px);
}

.btn-quiet {
  background: var(--glass);
  border-color: var(--line);
  color: var(--text-mid);
  padding: 0.5rem 1rem;
  font-size: 0.85rem;
}
.btn-quiet:hover { color: var(--text-hi); border-color: var(--line-strong); }

.btn-danger {
  background: transparent;
  border-color: rgba(224, 122, 107, 0.4);
  color: var(--bad);
  padding: 0.5rem 1rem;
  font-size: 0.85rem;
}
.btn-danger:hover { background: var(--bad-bg); border-color: var(--bad); }

.btn-approve {
  background: var(--ok-bg);
  border-color: rgba(127, 201, 138, 0.4);
  color: var(--ok);
  padding: 0.5rem 1.1rem;
  font-size: 0.85rem;
}
.btn-approve:hover { border-color: var(--ok); transform: translateY(-1px); }

.btn-block { width: 100%; }
.btn-lg { padding: 0.95rem 2rem; font-size: 1.02rem; }

/* --------------------------------------------------------------------------
   Header / nav
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  background: color-mix(in srgb, var(--ink-0) 72%, transparent);
  border-bottom: 1px solid transparent;
  transition: border-color var(--speed) var(--ease-out), background var(--speed) var(--ease-out);
}
.site-header.is-scrolled {
  border-bottom-color: var(--line);
  background: color-mix(in srgb, var(--ink-0) 88%, transparent);
}

.nav {
  display: flex;
  align-items: center;
  gap: 2rem;
  min-height: 76px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  color: var(--text-hi);
  font-family: var(--font-display);
  font-size: 1.28rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.brand:hover { color: var(--text-hi); }
.brand-mark {
  width: 34px;
  height: 34px;
  color: var(--amber);
  filter: drop-shadow(0 0 12px var(--amber-glow));
}
.brand em {
  font-style: normal;
  color: var(--amber);
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 1.9rem;
  margin-inline-start: auto;
  list-style: none;
  padding: 0;
  margin-block: 0;
}
.nav-links a:not(.btn) {
  color: var(--text-mid);
  font-size: 0.93rem;
  font-weight: 500;
  position: relative;
}
.nav-links a:not(.btn):hover,
.nav-links a:not(.btn)[aria-current="page"] { color: var(--text-hi); }
.nav-links a:not(.btn)::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -6px;
  width: 100%;
  height: 1px;
  background: var(--amber);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--speed) var(--ease-out);
}
.nav-links a:not(.btn):hover::after,
.nav-links a:not(.btn)[aria-current="page"]::after { transform: scaleX(1); }

.nav-user {
  color: var(--text-low);
  font-size: 0.85rem;
  border-inline-start: 1px solid var(--line);
  padding-inline-start: 1.4rem;
}

.nav-toggle {
  display: none;
  margin-inline-start: auto;
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  color: var(--text-hi);
  padding: 0.5rem 0.6rem;
  cursor: pointer;
}
.nav-toggle svg { width: 20px; height: 20px; display: block; }

@media (max-width: 860px) {
  .nav { flex-wrap: wrap; row-gap: 0; }
  .nav-toggle { display: inline-flex; }
  .nav-links {
    display: none;
    flex-direction: column;
    align-items: flex-start;
    width: 100%;
    gap: 1.1rem;
    margin: 0;
    padding: 1.1rem 0 1.5rem;
    border-top: 1px solid var(--line);
  }
  .nav-links.is-open { display: flex; }
  .nav-user { border: 0; padding: 0; }
}

/* --------------------------------------------------------------------------
   Flash messages
   -------------------------------------------------------------------------- */

/* The stack used to sit in flow between the header and <main>, so every
   message pushed the whole page down and none of them ever went away
   (U-u28). It is now a fixed toast stack in the corner: it never
   reflows the page, and site.js auto-dismisses anything that is not an
   error after 6 s. */
.flash-stack {
  position: fixed;
  z-index: var(--z-toast);
  top: calc(var(--header-h) + var(--sp-3));
  inset-inline-end: var(--gutter);
  width: min(24rem, calc(100vw - 2 * var(--gutter)));
  display: grid;
  gap: var(--sp-2);
  pointer-events: none;
}
.flash {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  padding: 0.85rem 1.1rem;
  border-radius: var(--radius-m);
  background: color-mix(in srgb, var(--ink-1) 92%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-2);
  font-size: 0.93rem;
  color: var(--text-hi);
  pointer-events: auto;
  animation: toast-in 320ms var(--ease-out) both;
}
.flash.is-leaving {
  animation: toast-out 220ms var(--ease-out) forwards;
}
.flash.is-error { border-color: color-mix(in srgb, var(--bad) 55%, transparent); }
.flash.is-error svg { color: var(--bad); }
.flash svg { width: 18px; height: 18px; color: var(--amber); flex: none; margin-top: 0.15rem; }
.flash span { flex: 1; }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(-8px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}
@keyframes toast-out {
  to { opacity: 0; transform: translateY(-6px) scale(0.98); }
}
@media (max-width: 620px) {
  .flash-stack {
    inset-inline: var(--gutter);
    width: auto;
  }
}
.flash-close {
  margin-inline-start: auto;
  background: none;
  border: 0;
  color: var(--text-low);
  cursor: pointer;
  font-size: 1.1rem;
  line-height: 1;
  padding: 0.2rem;
}
.flash-close:hover { color: var(--text-hi); }

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  padding-block: clamp(4.5rem, 11vw, 8.5rem) clamp(3.5rem, 8vw, 6rem);
  overflow: hidden;
}
.hero::before {
  /* film-light beam */
  content: "";
  position: absolute;
  inset: -20% -10% auto;
  height: 120%;
  background:
    conic-gradient(from 190deg at 78% 8%, transparent 0deg, rgba(242,181,68,0.10) 18deg, transparent 42deg);
  pointer-events: none;
}
.hero-grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(2.5rem, 6vw, 5rem);
  align-items: center;
}
.hero h1 em {
  font-style: italic;
  color: var(--amber);
}
.hero-lede {
  color: var(--text-mid);
  font-size: clamp(1.05rem, 1.6vw, 1.2rem);
  max-width: 34rem;
  margin-bottom: 2rem;
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  align-items: center;
}
.hero-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 1.6rem;
  margin-top: 2.6rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--line);
}
.hero-meta div strong {
  display: block;
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--text-hi);
}
.hero-meta div span {
  font-size: 0.8rem;
  color: var(--text-low);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.hero-urdu {
  display: block;
  margin-top: 0.9rem;
  font-family: var(--font-urdu);
  font-size: 1.15rem;
  color: var(--text-mid);
  direction: rtl;
}

@media (max-width: 960px) {
  .hero-grid { grid-template-columns: 1fr; }
}

/* --------------------------------------------------------------------------
   Cinematic frame (video/poster placeholder)
   -------------------------------------------------------------------------- */

.cinema-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-l);
  overflow: hidden;
  background:
    radial-gradient(120% 140% at 30% 20%, #241a0d 0%, #120d07 55%, #0a0805 100%);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-pop), 0 0 80px -20px var(--amber-glow);
}
.cinema-frame::before,
.cinema-frame::after {
  /* letterbox bars */
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 7%;
  background: rgba(0, 0, 0, 0.55);
  z-index: 2;
}
.cinema-frame::before { top: 0; }
.cinema-frame::after { bottom: 0; }

.cinema-frame .frame-grain {
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    0deg, rgba(255,255,255,0.015) 0 1px, transparent 1px 3px);
  mix-blend-mode: overlay;
}
.cinema-frame .frame-play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  z-index: 3;
}
.cinema-frame .frame-play span {
  width: 74px;
  height: 74px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(11, 9, 6, 0.55);
  border: 1px solid var(--line-strong);
  backdrop-filter: blur(6px);
  color: var(--amber);
  transition: transform var(--speed) var(--ease-out), box-shadow var(--speed) var(--ease-out);
}
.cinema-frame:hover .frame-play span {
  transform: scale(1.08);
  box-shadow: 0 0 40px -6px var(--amber-glow);
}
.cinema-frame .frame-play svg { width: 26px; height: 26px; margin-inline-start: 4px; }
.cinema-frame .frame-caption {
  position: absolute;
  bottom: 10%;
  left: 5%;
  right: 5%;
  z-index: 3;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-mid);
}
.cinema-frame .frame-caption .rec {
  color: var(--amber);
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}
.cinema-frame .frame-caption .rec::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--amber);
  box-shadow: 0 0 10px var(--amber);
}
.cinema-frame.is-vertical { aspect-ratio: 9 / 16; max-height: 480px; margin-inline: auto; }

/* --------------------------------------------------------------------------
   Cards & feature grid
   -------------------------------------------------------------------------- */

.card {
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  box-shadow: var(--shadow-card);
  backdrop-filter: blur(8px);
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.1rem;
}
@media (max-width: 960px) { .feature-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .feature-grid { grid-template-columns: 1fr; } }

.feature {
  padding: 1.7rem 1.6rem 1.5rem;
  transition: transform var(--speed) var(--ease-out),
              border-color var(--speed) var(--ease-out),
              background var(--speed) var(--ease-out);
}
.feature:hover {
  transform: translateY(-4px);
  border-color: var(--line-strong);
  background: var(--glass-strong);
}
.feature-icon {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: var(--amber-glow);
  border: 1px solid rgba(242, 181, 68, 0.25);
  color: var(--amber);
  margin-bottom: 1.1rem;
}
.feature-icon svg { width: 22px; height: 22px; }
.feature h3 { font-size: 1.12rem; margin-bottom: 0.45rem; }
.feature p { color: var(--text-mid); font-size: 0.92rem; margin: 0; }

/* --------------------------------------------------------------------------
   How it works — steps
   -------------------------------------------------------------------------- */

.steps {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.1rem;
  counter-reset: step;
}
@media (max-width: 820px) { .steps { grid-template-columns: 1fr; } }

.step {
  position: relative;
  padding: 2rem 1.7rem 1.7rem;
  counter-increment: step;
  overflow: hidden;
}
.step::before {
  content: "0" counter(step);
  position: absolute;
  top: 0.6rem;
  right: 1.1rem;
  font-family: var(--font-display);
  font-size: 4.4rem;
  font-weight: 500;
  color: rgba(242, 181, 68, 0.09);
  line-height: 1;
  pointer-events: none;
}
.step-kicker {
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--amber);
  margin-bottom: 0.6rem;
  display: block;
}
.step h3 { margin-bottom: 0.5rem; }
.step p { color: var(--text-mid); font-size: 0.93rem; margin: 0; }

/* --------------------------------------------------------------------------
   Packages
   -------------------------------------------------------------------------- */

.package-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: 1.2rem;
  align-items: stretch;
}

.package-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 2rem 1.8rem 1.8rem;
  transition: transform var(--speed) var(--ease-out), border-color var(--speed) var(--ease-out);
}
.package-card:hover { transform: translateY(-5px); border-color: var(--line-strong); }
.package-card.is-featured {
  border-color: rgba(242, 181, 68, 0.45);
  background: linear-gradient(180deg, rgba(242, 181, 68, 0.07), var(--glass) 45%);
  box-shadow: var(--shadow-card), 0 0 60px -20px var(--amber-glow);
}
.package-flag {
  position: absolute;
  top: -0.75rem;
  inset-inline-start: 1.6rem;
  background: linear-gradient(180deg, var(--amber-hot), var(--amber));
  color: var(--amber-ink);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.32rem 0.8rem;
  border-radius: 999px;
}
.package-card h3 { margin-bottom: 0.2rem; }
.package-tagline { color: var(--text-mid); font-size: 0.9rem; min-height: 2.6em; }
.package-price {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  margin: 0.6rem 0 1.3rem;
  padding-bottom: 1.3rem;
  border-bottom: 1px solid var(--line);
}
.package-price .price-pkr {
  font-family: var(--font-display);
  font-size: 2rem;
  color: var(--text-hi);
}
.package-price .price-usd {
  color: var(--text-low);
  font-size: 0.87rem;
}
.package-features {
  list-style: none;
  padding: 0;
  margin: 0 0 1.8rem;
  display: grid;
  gap: 0.65rem;
  flex: 1;
}
.package-features li {
  display: flex;
  gap: 0.65rem;
  align-items: flex-start;
  color: var(--text-mid);
  font-size: 0.92rem;
}
.package-features svg {
  width: 16px;
  height: 16px;
  color: var(--amber);
  flex: none;
  margin-top: 0.25rem;
}

/* --------------------------------------------------------------------------
   CTA band
   -------------------------------------------------------------------------- */

.cta-band {
  position: relative;
  border-radius: var(--radius-l);
  border: 1px solid rgba(242, 181, 68, 0.28);
  background:
    radial-gradient(600px 300px at 85% 0%, rgba(242, 181, 68, 0.14), transparent 60%),
    var(--ink-1);
  padding: clamp(2.5rem, 6vw, 4.5rem);
  text-align: center;
  overflow: hidden;
}
.cta-band h2 { margin-bottom: 0.5rem; }
.cta-band p { color: var(--text-mid); max-width: 34rem; margin-inline: auto; }
.cta-band .hero-actions { justify-content: center; margin-top: 1.8rem; }

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

.site-footer {
  margin-top: var(--section-gap);
  border-top: 1px solid var(--line);
  background: color-mix(in srgb, var(--ink-1) 60%, transparent);
  padding: 3rem 0 2rem;
}
.footer-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 2rem;
  justify-content: space-between;
  align-items: flex-start;
}
.footer-brand p {
  color: var(--text-low);
  font-size: 0.88rem;
  max-width: 22rem;
  margin-top: 0.8rem;
}
.footer-nav {
  display: flex;
  gap: 3rem;
  flex-wrap: wrap;
}
.footer-nav h4 {
  font-family: var(--font-body);
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-low);
  margin-bottom: 0.9rem;
}
.footer-nav ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.55rem; }
.footer-nav a { color: var(--text-mid); font-size: 0.9rem; }
.footer-nav a:hover { color: var(--amber-hot); }
.footer-base {
  margin-top: 2.5rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: space-between;
  color: var(--text-low);
  font-size: 0.82rem;
}

/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */

.field { display: grid; gap: 0.45rem; margin-bottom: 1.15rem; }
.field label {
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--text-mid);
}
/* .hint was --text-low at 12.5 px — under AA on a card ground. Hints are
   read, not decorative, so they take --text-mid (U-u15). */
.field .hint { font-size: var(--fs-sm); color: var(--text-mid); margin: 0; }
.field .hint-quiet { font-size: var(--fs-sm); color: var(--text-low); margin: 0; }

/* Every <input> written without a type attribute fell through to the UA
   stylesheet: white box, black Arial, on a dark cinematic page — six of
   them on the Studio and one on /my-voices (U-2). The selector list is
   ADDITIVE. It is deliberately not the inverted
   `input:not([type=checkbox])…` form, which would also catch
   input[type=hidden] (every CSRF field) and datetime-local, whose own
   rule further down this file it would then fight on specificity. */
input:not([type]),
input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="search"],
input[type="url"],
input[type="tel"],
select,
textarea {
  width: 100%;
  background: var(--field-bg);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-s);
  color: var(--text-hi);
  font: 400 0.95rem/1.5 var(--font-body);
  padding: 0.72rem 0.9rem;
  transition: border-color var(--speed) var(--ease-out),
              box-shadow var(--speed) var(--ease-out),
              background var(--speed) var(--ease-out);
}
textarea { resize: vertical; min-height: 8.5rem; }

/* RTL script fields. .is-rtl only turns the direction round; the FACE
   comes from the language class site.js sets alongside it, so an Arabic
   script field is Naskh and an Urdu one Nastaliq (U-u3). Inputs get the
   same treatment as textareas — the Studio's native-title input is an
   <input>, and it used to render Urdu in Arial (U-2). */
textarea.is-rtl, input.is-rtl { direction: rtl; }
textarea.lang-urdu, input.lang-urdu {
  font-family: var(--font-urdu); line-height: 2.2; font-size: 1.05rem;
}
textarea.lang-arabic, input.lang-arabic {
  font-family: var(--font-arabic); line-height: 1.95; font-size: 1.02rem;
}
/* Back-compat: boards that only carry .is-rtl (no language class) keep
   the old Nastaliq look rather than losing their face entirely. */
textarea.is-rtl:not(.lang-arabic):not(.lang-urdu),
input.is-rtl:not(.lang-arabic):not(.lang-urdu) {
  font-family: var(--font-urdu); line-height: 2.2; font-size: 1.05rem;
}

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--amber);
  box-shadow: var(--focus-ring);
}
input::placeholder, textarea::placeholder { color: var(--text-low); }
input:disabled, select:disabled, textarea:disabled {
  opacity: 0.55; cursor: not-allowed;
}
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-color: var(--bad);
}

/* File input: the native control is a grey Windows button in a dark UI.
   ::file-selector-button turns it into our quiet button. */
input[type="file"] {
  width: 100%;
  background: var(--field-bg);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-s);
  color: var(--text-mid);
  font: 400 0.9rem/1.5 var(--font-body);
  padding: 0.6rem 0.7rem;
  cursor: pointer;
}
input[type="file"]::file-selector-button {
  margin-inline-end: 0.8rem;
  padding: 0.42rem 0.95rem;
  border-radius: var(--radius-pill);
  border: 1px solid var(--line-strong);
  background: var(--glass-strong);
  color: var(--text-hi);
  font: 600 0.85rem var(--font-body);
  cursor: pointer;
  transition: border-color var(--speed) var(--ease-out), color var(--speed) var(--ease-out);
}
input[type="file"]::file-selector-button:hover {
  border-color: var(--amber); color: var(--amber-hot);
}
input[type="file"]:focus-visible { border-color: var(--amber); box-shadow: var(--focus-ring); }

select {
  appearance: none;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--text-mid) 50%),
    linear-gradient(135deg, var(--text-mid) 50%, transparent 50%);
  background-position: calc(100% - 18px) 55%, calc(100% - 13px) 55%;
  background-size: 5px 5px;
  background-repeat: no-repeat;
  padding-inline-end: 2.4rem;
}
select optgroup, select option { background: var(--ink-2); color: var(--text-hi); }

.check {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.9rem;
  color: var(--text-mid);
  cursor: pointer;
}
.check input { accent-color: var(--amber); width: 16px; height: 16px; }

.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0 1rem;
}

/* auth */
.auth-wrap {
  min-height: calc(100vh - 76px);
  display: grid;
  place-items: center;
  padding: clamp(2rem, 6vw, 4rem) var(--gutter);
}
.auth-card {
  width: min(420px, 100%);
  padding: 2.4rem 2.2rem 2.2rem;
  border-radius: var(--radius-l);
}
.auth-card h1 {
  font-size: 1.9rem;
  margin-bottom: 0.3rem;
}
.auth-card > p { color: var(--text-mid); font-size: 0.92rem; margin-bottom: 1.8rem; }
.auth-alt {
  margin: 1.4rem 0 0;
  text-align: center;
  font-size: 0.88rem;
  color: var(--text-low);
}
.auth-note {
  margin-top: 1.3rem;
  padding: 0.8rem 1rem;
  border-radius: var(--radius-s);
  background: var(--amber-glow);
  border: 1px solid rgba(242, 181, 68, 0.25);
  color: var(--text-mid);
  font-size: 0.83rem;
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
}
.auth-note svg { width: 16px; height: 16px; color: var(--amber); flex: none; margin-top: 0.15rem; }

/* --------------------------------------------------------------------------
   App chrome: page headers, stats, tables, chips
   -------------------------------------------------------------------------- */

.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.2rem;
  padding: clamp(2.2rem, 5vw, 3.5rem) 0 1.8rem;
}
.page-head h1 { font-size: clamp(1.9rem, 4vw, 2.6rem); margin: 0; }
.page-head .sub { color: var(--text-mid); font-size: 0.95rem; margin: 0.4rem 0 0; }

.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1rem;
  margin-bottom: 2rem;
}
.stat {
  padding: 1.3rem 1.4rem 1.15rem;
}
.stat .stat-label {
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-low);
}
.stat .stat-value {
  font-family: var(--font-display);
  font-size: 2.3rem;
  line-height: 1.1;
  color: var(--text-hi);
}
.stat.is-accent .stat-value { color: var(--amber); }

.table-wrap {
  overflow-x: auto;
  border-radius: var(--radius-m);
  border: 1px solid var(--line);
  background: var(--glass);
  box-shadow: var(--shadow-card);
}
table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
  min-width: 640px;
}
table.data th {
  text-align: start;
  font-size: 0.7rem;
  font-weight: 650;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-low);
  padding: 0.9rem 1.1rem;
  border-bottom: 1px solid var(--line-strong);
  white-space: nowrap;
}
table.data td {
  padding: 0.85rem 1.1rem;
  border-bottom: 1px solid var(--line);
  color: var(--text-mid);
  vertical-align: middle;
}
table.data tbody tr { transition: background var(--speed) var(--ease-out); }
table.data tbody tr:hover { background: var(--glass-strong); }
table.data tbody tr:last-child td { border-bottom: 0; }
table.data td.cell-strong { color: var(--text-hi); font-weight: 550; }
table.data td.cell-num { font-variant-numeric: tabular-nums; }
table.data .row-link { font-weight: 600; font-size: 0.86rem; }

.empty-state {
  padding: 3.5rem 2rem;
  text-align: center;
  color: var(--text-mid);
}
.empty-state svg { width: 40px; height: 40px; color: var(--text-low); margin: 0 auto 1rem; }
.empty-state h3 { font-size: 1.2rem; }
.empty-state p { font-size: 0.92rem; color: var(--text-low); max-width: 26rem; margin-inline: auto; }

/* status chips */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.26rem 0.7rem;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 650;
  letter-spacing: 0.05em;
  text-transform: capitalize;
  border: 1px solid transparent;
  white-space: nowrap;
}
.chip::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}
.status-draft      { color: var(--neutral); background: var(--neutral-bg); border-color: rgba(164,154,134,0.25); }
.status-queued     { color: var(--info);    background: var(--info-bg);    border-color: rgba(141,180,216,0.25); }
.status-rendering  { color: var(--warn);    background: var(--warn-bg);    border-color: rgba(230,180,90,0.3); }
.status-assembling { color: var(--warn);    background: var(--warn-bg);    border-color: rgba(230,180,90,0.3); }
.status-uploaded   { color: var(--info);    background: var(--info-bg);    border-color: rgba(141,180,216,0.25); }
.status-completed  { color: var(--ok);      background: var(--ok-bg);      border-color: rgba(127,201,138,0.3); }
.status-failed     { color: var(--bad);     background: var(--bad-bg);     border-color: rgba(224,122,107,0.3); }
.status-rendering::before,
.status-assembling::before,
.status-queued::before { animation: pulse 1.6s ease-in-out infinite; }

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}

/* role / package chips */
.chip-plain {
  color: var(--text-mid);
  background: var(--glass-strong);
  border-color: var(--line);
}
.chip-plain::before { display: none; }
.chip-amber {
  color: var(--amber);
  background: var(--amber-glow);
  border-color: rgba(242, 181, 68, 0.3);
}
.chip-amber::before { display: none; }

/* --------------------------------------------------------------------------
   Storyboard detail: meta, timeline, scenes, player
   -------------------------------------------------------------------------- */

.meta-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1rem;
  padding: 1.4rem 1.5rem;
  margin-bottom: 1.6rem;
}
.meta-grid dt {
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-low);
  margin-bottom: 0.25rem;
}
.meta-grid dd {
  margin: 0;
  color: var(--text-hi);
  font-size: 0.95rem;
  font-weight: 500;
}

.timeline {
  display: flex;
  align-items: flex-start;
  gap: 0;
  list-style: none;
  padding: 1.6rem 1.5rem 1.2rem;
  margin: 0 0 1.6rem;
  overflow-x: auto;
}
.timeline li {
  position: relative;
  flex: 1;
  min-width: 96px;
  text-align: center;
  font-size: 0.76rem;
  color: var(--text-low);
  letter-spacing: 0.04em;
  text-transform: capitalize;
  padding-top: 1.6rem;
}
.timeline li::before {
  /* node */
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--ink-2);
  border: 2px solid var(--line-strong);
  z-index: 1;
}
.timeline li::after {
  /* connector */
  content: "";
  position: absolute;
  top: 6px;
  left: calc(-50% + 8px);
  width: calc(100% - 16px);
  height: 1px;
  background: var(--line-strong);
}
.timeline li:first-child::after { display: none; }
.timeline li.is-done { color: var(--text-mid); }
.timeline li.is-done::before { background: var(--amber-deep); border-color: var(--amber-deep); }
.timeline li.is-done::after { background: var(--amber-deep); }
.timeline li.is-current { color: var(--amber); font-weight: 650; }
.timeline li.is-current::before {
  background: var(--amber);
  border-color: var(--amber);
  box-shadow: 0 0 14px var(--amber-glow), 0 0 0 4px rgba(242, 181, 68, 0.15);
}
.timeline li.is-current::after { background: var(--amber-deep); }
/* The schedule page: a month of hand-overs beside what is in them. */
.sched-top {
  display: grid; gap: 1.2rem; align-items: start;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
}
@media (max-width: 820px) { .sched-top { grid-template-columns: 1fr; } }
.sched-cal { padding: 1rem 1.1rem; }
.sched-cal .cal-grid { max-width: none; }
.sched-day {
  font-size: .92rem; margin: 1.4rem 0 .4rem; padding-bottom: .3rem;
  border-bottom: 1px solid var(--line);
}
.sched-table { width: 100%; border-collapse: collapse; }
.sched-table td, .sched-table th { padding: .4rem .5rem; }
.cal-day.is-empty { opacity: .35; cursor: default; }
.cal-day:disabled:hover { border-color: var(--line); }

/* Assignment calendar: each day carries how many videos that account is
   already due to receive, so an admin can see a pile-up before making
   it worse. */
.cal { flex-basis: 100%; margin-top: .8rem; }
.cal-head {
  display: flex; align-items: center; gap: .5rem; margin-bottom: .5rem;
}
.cal-head .grow { flex: 1; }
.cal-grid {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px;
  max-width: 30rem;
}
.cal-dow {
  text-align: center; font-size: .7rem; color: var(--dim);
  padding: .2rem 0;
}
.cal-day {
  position: relative; aspect-ratio: 1 / 1; min-height: 2.1rem;
  border: 1px solid var(--line); border-radius: 6px;
  background: transparent; color: inherit; cursor: pointer;
  font: inherit; font-size: .82rem; padding: 0;
}
.cal-day:hover { border-color: var(--accent); }
.cal-day.is-today { border-color: var(--accent); font-weight: 700; }
/* White on amber is 1.8:1 — measured on the day badge at 9.9 px, which
   is the worst possible place for it. Text on an amber fill is
   --amber-ink (11:1), the same pair every .btn-primary already uses. */
.cal-day.is-on { background: var(--accent); color: var(--amber-ink); }
.cal-day.is-past { opacity: .4; }
.cal-day b {
  position: absolute; right: 2px; bottom: 1px;
  font-size: .62rem; line-height: 1; font-weight: 700;
  background: var(--accent); color: var(--amber-ink);
  border-radius: 999px; padding: .1rem .28rem;
}
.cal-day.is-on b { background: var(--amber-ink); color: var(--amber); }
.cal-legend { font-size: .78rem; margin-top: .5rem; max-width: 30rem; }

/* A booked hand-over, and the control that books one. */
.scheduled-note {
  border-color: var(--accent);
  padding: .8rem 1rem;
  margin-bottom: .8rem;
  display: flex;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
}
.alloc-box input[type="datetime-local"] {
  padding: .35rem .5rem;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: transparent;
  color: inherit;
}
.alloc-box input[type="datetime-local"]:disabled { opacity: .45; }

/* Allocate / reallocate, on the storyboard's own page. */
.alloc-box {
  display: flex;
  align-items: center;
  gap: .7rem;
  flex-wrap: wrap;
  padding: .8rem 1rem;
  margin-bottom: 1.2rem;
}
.alloc-box label { font-weight: 600; font-size: .9rem; }
.alloc-box select { min-width: 16rem; }

/* Failure panel — a failed job used to render as a red chip and nothing
   else, so the reason the pipeline wrote was never shown to anyone. */
.failure-panel {
  border-color: rgba(224, 122, 107, 0.42);
  background: var(--bad-bg);
  padding: 1rem 1.15rem;
  margin-bottom: 1.2rem;
  display: flex;
  gap: 1.2rem;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
}
.failure-panel h2 { font-size: 1.1rem; margin: 0 0 .35rem; color: var(--bad); }
.failure-panel p { margin: 0; max-width: 60ch; }
.failure-body { flex: 1 1 24rem; }
.failure-detail { margin-top: .7rem; }
.failure-detail summary { cursor: pointer; font-size: .84rem; opacity: .78; }
.failure-detail pre {
  margin: .5rem 0 0;
  padding: .6rem .7rem;
  max-height: 15rem;
  overflow: auto;
  font-size: .76rem;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.22);
}
.requeue-note {
  border-color: var(--accent);
  padding: .8rem 1rem;
  margin-bottom: 1rem;
}
.sb-fail { margin: .35rem 0 0; font-size: .82rem; color: var(--bad); }

.timeline li.is-failed { color: var(--bad); font-weight: 650; }
.timeline li.is-failed::before { background: var(--bad); border-color: var(--bad); }

.player-shell {
  border-radius: var(--radius-l);
  overflow: hidden;
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-pop);
  margin-bottom: 1.6rem;
  background: #000;
}
/* The player must never outgrow the viewport: a 9:16 master at 100%
   width would render ~1.7x the screen height. Cap by height and let
   width follow the aspect; the shell centers the narrower result. */
.player-shell { display: flex; justify-content: center; }
.player-shell video {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: 78vh;
}

.scene-narration {
  max-width: 34rem;
  white-space: pre-line;
}
/* Scene narration. The face follows the LANGUAGE, not the direction: the
   old rule keyed on [dir="rtl"] and so set Arabic scenes in Nastaliq
   too (U-u3). storyboard_detail.html belongs to another package; when it
   starts emitting lang= on the narration these two rules take over, and
   the third keeps today's markup looking right until it does. */
.scene-narration[lang|="ur"] { font-family: var(--font-urdu); line-height: 2.1; font-size: 1rem; }
.scene-narration[lang|="ar"] { font-family: var(--font-arabic); line-height: 1.9; font-size: 1rem; }
.scene-narration[dir="rtl"]:not([lang]) { font-family: var(--font-urdu); line-height: 2.1; font-size: 1rem; }

/* --------------------------------------------------------------------------
   Admin tabs
   -------------------------------------------------------------------------- */

.tabs {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--line);
  margin-bottom: 1.8rem;
}
.tab-btn {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--text-mid);
  font: 600 0.9rem/1 var(--font-body);
  padding: 0.8rem 1rem;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  transition: color var(--speed) var(--ease-out), border-color var(--speed) var(--ease-out);
  margin-bottom: -1px;
}
.tab-btn:hover { color: var(--text-hi); }
.tab-btn.is-active { color: var(--amber); border-bottom-color: var(--amber); }
.tab-btn .count {
  background: var(--glass-strong);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.7rem;
  padding: 0.1rem 0.5rem;
  color: var(--text-low);
}
.tab-btn.is-active .count { color: var(--amber); border-color: rgba(242,181,68,0.3); }

.tab-panel { display: none; }
.tab-panel.is-active { display: block; animation: panel-in 260ms var(--ease-out); }

@keyframes panel-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

.panel-split {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(280px, 1fr);
  gap: 1.4rem;
  align-items: start;
}
@media (max-width: 900px) { .panel-split { grid-template-columns: 1fr; } }

.panel-form {
  padding: 1.6rem 1.5rem;
  position: sticky;
  top: 96px;
}
.panel-form h3 { font-size: 1.1rem; margin-bottom: 1.2rem; }

.inline-actions { display: flex; gap: 0.5rem; align-items: center; }
.inline-actions form { margin: 0; }

/* --------------------------------------------------------------------------
   Pending page
   -------------------------------------------------------------------------- */

.pending-wrap {
  min-height: calc(100vh - 76px);
  display: grid;
  place-items: center;
  padding: clamp(2rem, 6vw, 4rem) var(--gutter);
  text-align: center;
}
.pending-card {
  width: min(560px, 100%);
  padding: 3rem 2.5rem;
  border-radius: var(--radius-l);
}
.pending-icon {
  width: 68px;
  height: 68px;
  margin: 0 auto 1.5rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--amber-glow);
  border: 1px solid rgba(242, 181, 68, 0.3);
  color: var(--amber);
}
.pending-icon svg { width: 30px; height: 30px; }
.pending-card p { color: var(--text-mid); }
.pending-steps {
  text-align: start;
  margin: 1.8rem 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0.9rem;
}
.pending-steps li {
  display: flex;
  gap: 0.8rem;
  align-items: flex-start;
  font-size: 0.92rem;
  color: var(--text-mid);
}
.pending-steps svg { width: 18px; height: 18px; color: var(--amber); flex: none; margin-top: 0.2rem; }

/* --------------------------------------------------------------------------
   Reveal on scroll
   -------------------------------------------------------------------------- */

.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 600ms var(--ease-out), transform 600ms var(--ease-out);
}
.reveal.is-visible { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   Utilities
   -------------------------------------------------------------------------- */

.muted { color: var(--text-mid); }
.dim { color: var(--text-low); }
.mono { font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }
.mt-0 { margin-top: 0; }
.mb-2 { margin-bottom: 2rem; }
.text-center { text-align: center; }

/* --------------------------------------------------------------------------
   Reduced motion
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   Voice library
   -------------------------------------------------------------------------- */

/* The bar is two pieces: a sticky search/language row and a collapsible
   panel for everything else. The wrapper is display:contents so the
   sticky row's containing block is the page container (a sticky child
   is otherwise bounded by its parent's short box and never sticks). */
.voice-filterbar { display: contents; }

.vf-sticky {
  position: sticky;
  top: 76px;                 /* sits under the sticky site header */
  z-index: 50;
  margin: 0 0 1rem;
  padding: 0.8rem 1.1rem;
  background: color-mix(in srgb, var(--ink-1) 88%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  box-shadow: var(--shadow-card);
}

.vf-panel {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  margin: -0.3rem 0 1.4rem;
  padding: 0.95rem 1.1rem;
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
}

.vf-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.42rem 0.9rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-mid);
  font: inherit;
  font-size: 0.84rem;
  cursor: pointer;
  transition: color var(--speed) var(--ease-out),
              border-color var(--speed) var(--ease-out);
}

.vf-toggle:hover { color: var(--text-hi); border-color: var(--line-strong); }
.vf-toggle.is-open { color: var(--text-hi); border-color: var(--line-strong); }
.vf-toggle .vf-chev { transition: transform var(--speed) var(--ease-out); }
.vf-toggle.is-open .vf-chev { transform: rotate(180deg); }

.vf-toggle-n {
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--amber);
  color: var(--amber-ink);
  font-size: 0.7rem;
  font-weight: 700;
  display: inline-grid;
  place-items: center;
}

.vf-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem;
}

.vf-top { justify-content: space-between; }

.vf-search {
  position: relative;
  flex: 1 1 230px;
  min-width: 190px;
  max-width: 340px;
}

.vf-search-icon {
  position: absolute;
  left: 0.7rem;
  top: 50%;
  transform: translateY(-50%);
  width: 15px;
  height: 15px;
  color: var(--text-low);
  pointer-events: none;
}

.vf-search input {
  width: 100%;
  background: var(--field-bg);
  color: var(--text-hi);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.5rem 0.9rem 0.5rem 2.1rem;
  font: inherit;
  font-size: 0.88rem;
}

.vf-search input:focus-visible {
  outline: none;
  border-color: var(--amber);
  box-shadow: 0 0 0 3px var(--amber-glow);
}

.vf-count {
  color: var(--text-mid);
  font-size: 0.82rem;
  white-space: nowrap;
}

.vf-label {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-low);
  margin-right: 0.15rem;
  white-space: nowrap;
}

.vf-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.fpill {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.32rem 0.75rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-mid);
  font: inherit;
  font-size: 0.8rem;
  cursor: pointer;
  transition: color var(--speed) var(--ease-out),
              border-color var(--speed) var(--ease-out),
              background var(--speed) var(--ease-out);
}

.fpill:hover { color: var(--text-hi); border-color: var(--line-strong); }

.fpill.is-on {
  background: var(--amber);
  border-color: var(--amber);
  color: var(--amber-ink);
  font-weight: 600;
}

.fpill:disabled {
  opacity: 0.32;
  cursor: default;
  pointer-events: none;
}

.fpill-n {
  font-size: 0.68rem;
  opacity: 0.75;
  font-variant-numeric: tabular-nums;
}

.fpill-n:empty { display: none; }

.vf-traits { gap: 0.9rem 1.4rem; }

.vf-group {
  display: flex;
  align-items: center;
  gap: 0.45rem;
}

.vf-active {
  border-top: 1px solid var(--line);
  padding-top: 0.65rem;
}

.vf-active-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }

.vf-active-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.28rem 0.7rem;
  border-radius: 999px;
  border: 1px solid rgba(242, 181, 68, 0.45);
  background: var(--amber-glow);
  color: var(--amber-hot);
  font: inherit;
  font-size: 0.78rem;
  cursor: pointer;
  text-transform: capitalize;
}

.vf-active-chip span { font-size: 0.95rem; line-height: 1; }
.vf-active-chip:hover { border-color: var(--amber); }

.vf-clear {
  margin-left: auto;
  background: none;
  border: none;
  color: var(--text-mid);
  font: inherit;
  font-size: 0.8rem;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.vf-clear:hover { color: var(--text-hi); }

@media (max-width: 720px) {
  .vf-sticky { position: static; }   /* a sticky bar would eat the
                                        small screen */
  .vf-search { max-width: none; }
}

.voice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 1.4rem;
}

.voice-card {
  padding: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: transform var(--speed) var(--ease-out),
              box-shadow var(--speed) var(--ease-out),
              border-color var(--speed) var(--ease-out);
}

.voice-card:hover {
  transform: translateY(-3px);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-pop);
}

.voice-portrait {
  position: relative;
  aspect-ratio: 1;
  background: var(--ink-2);
}

.voice-portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: saturate(0.92);
}

.voice-lang {
  position: absolute;
  top: 0.7rem;
  left: 0.7rem;
  backdrop-filter: blur(6px);
  background: rgba(11, 9, 6, 0.55);
}

.voice-play {
  position: absolute;
  right: 0.8rem;
  bottom: 0.8rem;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: none;
  background: var(--amber);
  color: var(--amber-ink);
  display: grid;
  place-items: center;
  cursor: pointer;
  box-shadow: 0 6px 18px -6px rgba(0, 0, 0, 0.8);
  transition: transform var(--speed) var(--ease-out),
              background var(--speed) var(--ease-out);
}

.voice-play:hover { background: var(--amber-hot); transform: scale(1.07); }
.voice-play svg { width: 20px; height: 20px; }
.voice-play .vp-bars { display: none; gap: 3px; align-items: flex-end; height: 18px; }
.voice-play .vp-bars i {
  width: 3px;
  background: var(--amber-ink);
  border-radius: 2px;
  animation: vp-eq 0.9s ease-in-out infinite;
}
.voice-play .vp-bars i:nth-child(1) { height: 60%; animation-delay: 0s; }
.voice-play .vp-bars i:nth-child(2) { height: 100%; animation-delay: 0.15s; }
.voice-play .vp-bars i:nth-child(3) { height: 45%; animation-delay: 0.3s; }
.voice-play .vp-bars i:nth-child(4) { height: 80%; animation-delay: 0.45s; }

@keyframes vp-eq {
  0%, 100% { transform: scaleY(0.5); }
  50% { transform: scaleY(1); }
}

.voice-card.is-playing .vp-play { display: none; }
.voice-card.is-playing .vp-bars { display: flex; }
.voice-card.is-playing .voice-portrait img { filter: saturate(1.05); }

.voice-body {
  padding: 1.1rem 1.2rem 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  flex: 1;
}

.voice-name {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.25rem;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
}

/* Native-script name. NO font-family and NO direction here: the element
   carries lang= from the record and dir="auto", so the rules above pick
   Nastaliq for Urdu, Naskh for Arabic and leave Devanagari and Latin
   alone (U-u2). Hardcoding Nastaliq here is what painted the Hindi
   question mark in the middle of 'SIP या FD'. */
.voice-native {
  font-size: 0.95rem;
  color: var(--text-mid);
  font-weight: 400;
  line-height: 1.9;
}

.voice-desc {
  margin: 0;
  color: var(--text-mid);
  font-size: 0.88rem;
  line-height: 1.55;
  flex: 1;
}

.voice-meta { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.voice-meta .chip { font-size: 0.7rem; }

.voice-tags { display: flex; flex-wrap: wrap; gap: 0.35rem; }

.voice-tag {
  font-size: 0.74rem;
  color: var(--amber);
  text-decoration: none;
  padding: 0.18rem 0.55rem;
  border: 1px solid rgba(242, 181, 68, 0.35);
  border-radius: 999px;
  transition: background var(--speed) var(--ease-out);
}

.voice-tag:hover { background: var(--amber-glow); }

.voice-actions { margin-top: 0.2rem; }
.voice-actions .btn { width: 100%; justify-content: center; }

.voice-footnote {
  margin: 3rem auto 0;
  max-width: 640px;
  text-align: center;
  font-size: 0.82rem;
}

.btn-sm { padding: 0.35rem 0.8rem; font-size: 0.8rem; }

/* voice picker on the storyboard form */
.voice-pick-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0.8rem;
}

/* --------------------------------------------------------------------------
   Template gallery
   -------------------------------------------------------------------------- */

.tpl-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 1.4rem;
  margin-top: 1.4rem;
}

.tpl-card { padding: 0; overflow: hidden; display: flex; flex-direction: column; }

.tpl-cover { position: relative; aspect-ratio: 16/9; background: var(--ink-2); }
.tpl-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tpl-lang { position: absolute; top: 0.7rem; left: 0.7rem; background: rgba(11,9,6,0.55); backdrop-filter: blur(6px); }
.tpl-cat  { position: absolute; top: 0.7rem; right: 0.7rem; }

.tpl-body { padding: 1.1rem 1.2rem 1.25rem; display: flex; flex-direction: column; gap: 0.6rem; flex: 1; }
.tpl-title { margin: 0; font-family: var(--font-display); font-size: 1.2rem; display: flex; justify-content: space-between; gap: 0.6rem; align-items: baseline; }
.tpl-meta { display: flex; gap: 0.45rem; font-size: 0.8rem; }
.tpl-body .voice-actions { margin-top: auto; }

/* --------------------------------------------------------------------------
   Studio editor
   -------------------------------------------------------------------------- */

.studio-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 360px;
  gap: 1.6rem;
  align-items: start;
}

@media (max-width: 960px) {
  .studio-grid { grid-template-columns: 1fr; }
  .st-side { order: -1; }
}

.st-scenes-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 0.8rem; }
.st-scenes-head h2 { margin: 0; font-size: 1.15rem; }

.st-scene { padding: 0.85rem 1rem 1rem; margin-bottom: 0.8rem; }
.st-scene.is-dragging { opacity: 0.45; }

.st-scene-head { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.55rem; }
.st-scene-drag { cursor: grab; color: var(--text-low); user-select: none; }
.st-scene-num { font-size: 0.78rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-low); }
.st-scene-secs { font-size: 0.75rem; margin-left: auto; font-variant-numeric: tabular-nums; }

.st-scene-speaker {
  background: var(--ink-1); color: var(--text-hi);
  border: 1px solid var(--line); border-radius: 999px;
  padding: 0.22rem 0.6rem; font: inherit; font-size: 0.78rem;
}

.st-scene-tools { display: flex; gap: 0.25rem; }
.st-tool {
  width: 26px; height: 26px; border-radius: 7px;
  border: 1px solid transparent; background: transparent;
  color: var(--text-low); font-size: 0.95rem; cursor: pointer;
  display: grid; place-items: center;
}
.st-tool:hover { color: var(--text-hi); border-color: var(--line); background: var(--glass); }
.st-tool-del:hover { color: var(--bad); }

.st-scene-text {
  width: 100%; resize: none; overflow: hidden;
  background: var(--ink-0); color: var(--text-hi);
  border: 1px solid var(--line); border-radius: var(--radius-s);
  padding: 0.65rem 0.8rem; font: inherit; font-size: 0.95rem; line-height: 1.7;
}
.st-scene-text.lang-urdu { font-family: var(--font-urdu); font-size: 1.05rem; line-height: 2.1; }
.st-scene-text:focus-visible, .st-scene-visual:focus-visible {
  outline: none; border-color: var(--amber); box-shadow: 0 0 0 3px var(--amber-glow);
}

.st-scene-visual {
  width: 100%; margin-top: 0.5rem;
  background: transparent; color: var(--text-mid);
  border: 1px dashed var(--line); border-radius: var(--radius-s);
  padding: 0.45rem 0.8rem; font: inherit; font-size: 0.82rem;
}

.st-add { width: 100%; justify-content: center; border-style: dashed; }

.st-side { display: flex; flex-direction: column; gap: 1.1rem; position: sticky; top: 92px; }
@media (max-width: 960px) { .st-side { position: static; } }

.st-panel { padding: 1.2rem 1.25rem; }
.st-panel h3 { margin: 0 0 0.9rem; font-size: 1rem; }
.st-panel .field { margin-bottom: 0.8rem; }

.st-cast-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.4rem; }
.st-cast-head h3 { margin: 0; }

.st-cast-row { display: flex; gap: 0.7rem; align-items: flex-start; padding: 0.6rem 0; border-top: 1px solid var(--line); }
.st-cast-row:first-of-type { border-top: none; }

.st-cast-avatar {
  width: 52px; height: 52px; border-radius: 50%; overflow: hidden;
  border: 2px solid var(--line-strong); background: var(--ink-2);
  cursor: pointer; flex-shrink: 0; display: grid; place-items: center;
  color: var(--text-low); padding: 0;
  transition: border-color var(--speed) var(--ease-out);
}
.st-cast-avatar:hover { border-color: var(--amber); }
.st-cast-avatar img { width: 100%; height: 100%; object-fit: cover; }
.st-cast-avatar svg { width: 20px; height: 20px; }

.st-cast-main { flex: 1; min-width: 0; }
.st-cast-top { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 0.4rem; }
.st-cast-letter {
  width: 22px; height: 22px; border-radius: 6px; flex-shrink: 0;
  /* The six --spk-* fills are pastels in BOTH themes, so the ink on them
     must not flip with the theme. --amber-ink does flip (it is near-white
     on the light theme, because there it sits on a dark amber), and that
     put white on a pastel: 1.76:1, measured on /studio in light mode.
     --on-pastel is fixed for exactly this reason. */
  background: var(--amber); color: var(--on-pastel);
  font-size: 0.75rem; font-weight: 700; display: grid; place-items: center;
}
.st-cast-name {
  flex: 1; min-width: 0; background: transparent; color: var(--text-hi);
  border: none; border-bottom: 1px dashed var(--line);
  padding: 0.15rem 0.1rem; font: inherit; font-size: 0.92rem;
}
.st-cast-name:focus-visible { outline: none; border-bottom-color: var(--amber); }

.st-cast-voicebar { display: flex; gap: 0.4rem; }
.st-cast-voice {
  flex: 1; min-width: 0; background: var(--ink-1); color: var(--text-mid);
  border: 1px solid var(--line); border-radius: var(--radius-s);
  padding: 0.35rem 0.5rem; font: inherit; font-size: 0.8rem;
}
.st-cast-play {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  border: 1px solid var(--line); background: transparent; color: var(--amber);
  cursor: pointer; display: grid; place-items: center;
}
.st-cast-play svg { width: 13px; height: 13px; }
.st-cast-play:hover { border-color: var(--amber); background: var(--amber-glow); }

.st-cast-del {
  border: none; background: none; color: var(--text-low);
  font-size: 1.1rem; cursor: pointer; padding: 0.2rem;
}
.st-cast-del:hover { color: var(--bad); }

.st-submit-panel { text-align: center; }
.st-estimate { margin-bottom: 0.9rem; }
.st-est-num {
  display: block; font-family: var(--font-display);
  font-size: 2rem; color: var(--amber); font-variant-numeric: tabular-nums;
}

/* character modal */
.st-modal {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(6, 5, 3, 0.75); backdrop-filter: blur(6px);
  display: grid; place-items: center; padding: 1.5rem;
}
.st-modal-card {
  width: min(860px, 100%); max-height: 82vh; overflow: auto;
  padding: 1.3rem 1.4rem;
}
.st-modal-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; }
.st-modal-head h3 { margin: 0; }

.st-char-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 0.9rem;
}
.st-char-pick {
  display: flex; flex-direction: column; gap: 0.3rem; text-align: left;
  background: var(--glass); border: 1px solid var(--line);
  border-radius: var(--radius-m); padding: 0; overflow: hidden;
  cursor: pointer; font: inherit; color: var(--text-mid);
  transition: border-color var(--speed) var(--ease-out),
              transform var(--speed) var(--ease-out);
}
.st-char-pick:hover { border-color: var(--amber); transform: translateY(-2px); }
.st-char-pick img { width: 100%; aspect-ratio: 1; object-fit: cover; }
.st-char-name { color: var(--text-hi); font-weight: 600; font-size: 0.9rem; padding: 0.1rem 0.7rem 0; }
.st-char-role { font-size: 0.72rem; text-transform: capitalize; padding: 0 0.7rem; color: var(--amber); }
.st-char-persona { font-size: 0.75rem; line-height: 1.45; padding: 0 0.7rem; }
.st-char-voice { font-size: 0.72rem; padding: 0.15rem 0.7rem 0.7rem; }

/* featured voices band on the landing page */
.feat-voices {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 1rem;
}
.feat-voice {
  text-align: center; text-decoration: none; color: var(--text-mid);
  transition: transform var(--speed) var(--ease-out);
}
.feat-voice:hover { transform: translateY(-3px); }
.feat-voice-avatar {
  /* display:block was implicit before only because the <img> inside had
     no intrinsic size to fall back on. Now that the portrait declares
     width/height (U-u12), an inline span would let the image render at
     its attribute size and blow the band apart. */
  display: block;
  position: relative; width: 92px; height: 92px; margin: 0 auto 0.55rem;
  border-radius: 50%; overflow: hidden;
  border: 2px solid var(--line-strong);
  background: var(--ink-2);
}
.feat-voice:hover .feat-voice-avatar { border-color: var(--amber); }
.feat-voice-avatar img { width: 100%; height: 100%; object-fit: cover; }
.feat-voice-play {
  position: absolute; right: 2px; bottom: 2px;
  width: 26px; height: 26px; border-radius: 50%; border: none;
  background: var(--amber); color: var(--amber-ink);
  display: grid; place-items: center; cursor: pointer;
}
.feat-voice-play svg { width: 11px; height: 11px; }
.feat-voice-play:hover { background: var(--amber-hot); }
.feat-voice-name {
  display: block; color: var(--text-hi); font-weight: 600; font-size: 0.92rem;
}
.feat-voice-name:hover { color: var(--amber-hot); }
.feat-voice-line { display: block; font-size: 0.75rem; }
/* The card is a <div> now, not an <a> wrapped round a <button> (U-u29):
   the name carries the stretched link, the play button sits above it. */
.feat-voice:focus-within .feat-voice-avatar { border-color: var(--amber); }
.feat-voice .stretch-link:focus-visible { outline: none; }
.feat-voice:has(.stretch-link:focus-visible) .feat-voice-avatar {
  outline: 2px solid var(--amber); outline-offset: 3px;
}

/* per-speaker color coding: the scene card carries its speaker hue */
:root {
  --spk-a: #f2b544; --spk-b: #7fb8c9; --spk-c: #e08bb0;
  --spk-d: #a68be0; --spk-e: #8bc98f; --spk-f: #e0a06b;
}
.st-spk-A { border-left: 3px solid var(--spk-a); }
.st-spk-B { border-left: 3px solid var(--spk-b); }
.st-spk-C { border-left: 3px solid var(--spk-c); }
.st-spk-D { border-left: 3px solid var(--spk-d); }
.st-spk-E { border-left: 3px solid var(--spk-e); }
.st-spk-F { border-left: 3px solid var(--spk-f); }
.st-cast-row:nth-of-type(1) .st-cast-letter { background: var(--spk-a); }
.st-cast-row:nth-of-type(2) .st-cast-letter { background: var(--spk-b); }
.st-cast-row:nth-of-type(3) .st-cast-letter { background: var(--spk-c); }
.st-cast-row:nth-of-type(4) .st-cast-letter { background: var(--spk-d); }
.st-cast-row:nth-of-type(5) .st-cast-letter { background: var(--spk-e); }
.st-cast-row:nth-of-type(6) .st-cast-letter { background: var(--spk-f); }

/* visual style picker (studio) + style chips */
.st-styles { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.st-style {
  padding: 0.35rem 0.8rem; border-radius: 999px;
  border: 1px solid var(--line); background: transparent;
  color: var(--text-mid); font: inherit; font-size: 0.8rem;
  cursor: pointer;
  transition: color var(--speed) var(--ease-out),
              border-color var(--speed) var(--ease-out),
              background var(--speed) var(--ease-out);
}
.st-style:hover { color: var(--text-hi); border-color: var(--line-strong); }
.st-style.is-on {
  background: var(--amber); border-color: var(--amber);
  color: var(--amber-ink); font-weight: 600;
}
.tpl-style {
  position: absolute; bottom: 0.7rem; left: 0.7rem;
  background: rgba(11,9,6,0.55); backdrop-filter: blur(6px);
}

/* The hidden attribute must always win: several cards/panels set their
   own display (flex/grid), which silently defeats the UA's [hidden]
   rule — the /characters and /voices filters were toggling `hidden`
   with no visible effect (2026-08-29). */
[hidden] { display: none !important; }

/* ==========================================================================
   Storyboard gallery (dashboard) — thumbnail cards, filters, pagination
   ========================================================================== */
.filter-bar {
  display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center;
  margin: 1.6rem 0 0.4rem;
}
.filter-bar select, .filter-bar .filter-search {
  background: var(--ink-1); color: var(--text-hi);
  border: 1px solid var(--line); border-radius: var(--radius-s);
  padding: 0.55rem 0.8rem; font: 0.88rem var(--font-body);
}
.filter-bar .filter-search { flex: 1 1 200px; min-width: 160px; }
.filter-bar select:focus, .filter-bar .filter-search:focus {
  border-color: var(--amber); outline: none;
  box-shadow: 0 0 0 3px var(--amber-glow);
}
.filter-clear {
  color: var(--text-low); font-size: 0.85rem; text-decoration: none;
  border-bottom: 1px dotted var(--line-strong);
}
.filter-clear:hover { color: var(--amber); }
.filter-count { margin: 0.5rem 0 1.1rem; font-size: 0.85rem; }

.sb-grid {
  display: grid; gap: 1.1rem;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}
.sb-card {
  display: flex; flex-direction: column; padding: 0; overflow: hidden;
  text-decoration: none; color: inherit;
  transition: transform var(--speed) var(--ease-out),
              box-shadow var(--speed) var(--ease-out),
              border-color var(--speed) var(--ease-out);
}
.sb-card:hover {
  transform: translateY(-3px); box-shadow: var(--shadow-pop);
  border-color: var(--line-strong);
}
.sb-thumb {
  position: relative; aspect-ratio: 16 / 10; background: var(--ink-1);
  overflow: hidden;
}
.sb-thumb img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 480ms var(--ease-out);
}
.sb-card:hover .sb-thumb img { transform: scale(1.045); }
.sb-thumb-empty {
  height: 100%; display: grid; place-items: center;
  background:
    radial-gradient(120% 90% at 30% 20%, var(--amber-glow), transparent 60%),
    var(--ink-1);
}
.sb-thumb-empty svg { width: 34px; height: 34px; color: var(--text-low); }
.sb-status {
  position: absolute; top: 0.6rem; left: 0.6rem;
  backdrop-filter: blur(4px);
}
.sb-play {
  position: absolute; right: 0.6rem; bottom: 0.6rem;
  width: 2rem; height: 2rem; display: grid; place-items: center;
  border-radius: 50%; background: rgba(11, 9, 6, 0.65);
  color: var(--amber-hot); font-size: 0.7rem; padding-left: 2px;
  border: 1px solid var(--line-strong); backdrop-filter: blur(4px);
}
.sb-body { padding: 0.85rem 1rem 1rem; display: flex; flex-direction: column; gap: 0.2rem; }
.sb-title {
  font: 600 0.98rem/1.35 var(--font-body); color: var(--text-hi);
  margin: 0; display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden;
}
/* Dashboard card native title. Same reasoning as .voice-native: the
   element supplies lang and dir="auto"; `direction: rtl; text-align:
   right` here forced Hindi and English titles to render right-to-left
   (U-u2). text-align:start follows whatever dir="auto" resolved to. */
.sb-native {
  font-size: 0.9rem; color: var(--text-mid);
  margin: 0; text-align: start;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sb-meta { font-size: 0.78rem; margin: 0.25rem 0 0; text-transform: capitalize; }

.pagination {
  display: flex; flex-wrap: wrap; gap: 0.4rem; justify-content: center;
  margin: 2rem 0 1rem;
}
.page-btn {
  min-width: 2.2rem; padding: 0.45rem 0.7rem; text-align: center;
  border: 1px solid var(--line); border-radius: var(--radius-s);
  color: var(--text-mid); text-decoration: none; font-size: 0.88rem;
  transition: border-color var(--speed), color var(--speed);
}
.page-btn:hover { border-color: var(--amber); color: var(--amber-hot); }
.page-btn.is-current {
  background: var(--amber); color: var(--amber-ink);
  border-color: var(--amber); font-weight: 600;
}
.page-gap { color: var(--text-low); padding: 0.45rem 0.2rem; }

/* Small thumbnails inside the admin storyboards table */
.row-thumb {
  width: 72px; height: 44px; object-fit: cover; border-radius: 6px;
  border: 1px solid var(--line); display: block; background: var(--ink-1);
}

/* ---- orientation-aware gallery (v2) ------------------------------------ */
/* Status chips with live counts — one click, no dropdown digging. */
.status-chips {
  display: flex; flex-wrap: wrap; gap: 0.45rem; margin: 1.6rem 0 0.2rem;
}
.schip {
  display: inline-flex; gap: 0.4rem; align-items: baseline;
  padding: 0.4rem 0.75rem; border: 1px solid var(--line);
  border-radius: 999px; font-size: 0.84rem; color: var(--text-mid);
  text-decoration: none; transition: border-color var(--speed), color var(--speed);
}
.schip b { font-weight: 600; color: var(--text-low); }
.schip:hover { border-color: var(--amber); color: var(--amber-hot); }
.schip.is-on {
  background: var(--amber); border-color: var(--amber);
  color: var(--amber-ink);
}
.schip.is-on b { color: var(--amber-ink); }

/* Orientation toggle */
.shape-toggle {
  display: inline-flex; border: 1px solid var(--line);
  border-radius: var(--radius-s); overflow: hidden;
}
.shape-toggle a {
  padding: 0.55rem 0.85rem; font-size: 0.85rem; color: var(--text-mid);
  text-decoration: none; border-right: 1px solid var(--line);
}
.shape-toggle a:last-child { border-right: 0; }
.shape-toggle a:hover { color: var(--amber-hot); }
.shape-toggle a.is-on { background: var(--glass-strong); color: var(--text-hi); }

.shelf-head {
  font: 600 1.02rem var(--font-body); color: var(--text-hi);
  margin: 1.8rem 0 0.8rem; display: flex; gap: 0.6rem; align-items: baseline;
}
.shelf-head .dim { font-size: 0.8rem; font-weight: 400; }

/* Long-form: true 16:9 so the full thumbnail shows (YouTube grid). */
.sb-thumb.is-wide { aspect-ratio: 16 / 9; }
.sb-grid.is-wide { grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); }

/* Shorts: true 9:16 columns with the title on a bottom scrim
   (TikTok / YouTube-Shorts shelf), so the full portrait card shows. */
.sbp-grid {
  display: grid; gap: 0.9rem;
  grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
}
.sbp-card { display: block; text-decoration: none; color: inherit; }
.sbp-media {
  position: relative; aspect-ratio: 9 / 16; overflow: hidden;
  border-radius: var(--radius-m); border: 1px solid var(--line);
  background: var(--ink-1); box-shadow: var(--shadow-card);
  transition: transform var(--speed) var(--ease-out),
              box-shadow var(--speed) var(--ease-out),
              border-color var(--speed) var(--ease-out);
}
.sbp-card:hover .sbp-media {
  transform: translateY(-3px); box-shadow: var(--shadow-pop);
  border-color: var(--line-strong);
}
.sbp-media img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 480ms var(--ease-out);
}
.sbp-card:hover .sbp-media img { transform: scale(1.045); }
.sbp-media .sb-thumb-empty { height: 100%; }
.sbp-scrim {
  position: absolute; inset: auto 0 0 0; padding: 2.2rem 0.7rem 0.65rem;
  background: linear-gradient(180deg, transparent, rgba(7, 5, 3, 0.88) 72%);
}
.sbp-title {
  font: 600 0.85rem/1.3 var(--font-body); color: var(--text-hi);
  margin: 0; display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden;
}
.sbp-meta {
  font-size: 0.7rem; color: var(--text-mid); margin: 0.25rem 0 0;
  text-transform: capitalize; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis;
}

/* Filter-bar controls must not inherit the global full-width form
   styling — they sit inline in one wrapping row. */
.filter-bar select { width: auto; flex: 0 1 auto; }
.filter-bar .filter-search { width: auto; }

/* Delivery section — publish-ready assets and listing copy */
.delivery-grid {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  margin-bottom: 1rem;
}
.delivery-card { padding: 1.1rem 1.2rem; }
.delivery-card h3 {
  font: 600 0.95rem var(--font-body); color: var(--text-hi);
  margin: 0 0 0.7rem;
}
.delivery-thumb {
  display: block; max-width: 160px; max-height: 200px; width: auto;
  border-radius: var(--radius-s); border: 1px solid var(--line);
  margin-bottom: 0.7rem;
}
.tag-cloud { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.8rem; }
.tag-cloud .schip { cursor: default; }
.delivery-desc {
  width: 100%; background: var(--ink-1); color: var(--text-mid);
  border: 1px solid var(--line); border-radius: var(--radius-s);
  padding: 0.7rem 0.8rem; font: 0.88rem/1.5 var(--font-body);
  resize: vertical; margin-bottom: 0.6rem; white-space: pre-wrap;
}
.tag-chips { margin-top: 0.5rem; }

/* ---------------------------------------------------------- brief wizard
   One question per screen, built from the site's own tokens so the
   wizard reads as part of the studio rather than a bolted-on form. */
.brief { max-width: 60rem; }

.bw-steps {
  display: flex; flex-wrap: wrap; gap: .4rem 1.1rem;
  list-style: none; margin: 0 0 1.4rem; padding: 0;
  font-size: .78rem; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-low);
}
.bw-steps li { position: relative; padding-left: 1.1rem; }
.bw-steps li::before {
  content: ""; position: absolute; left: 0; top: .42em;
  width: .5rem; height: .5rem; border-radius: 50%;
  background: var(--line-strong);
}
.bw-steps li.is-done { color: var(--text-mid); }
.bw-steps li.is-done::before { background: var(--amber-deep); }
.bw-steps li.is-on { color: var(--amber); }
.bw-steps li.is-on::before { background: var(--amber); }

.bw-step { padding: 1.6rem 1.6rem 1.8rem; }
.bw-step h2 { margin: 0 0 .35rem; font-size: 1.5rem; }
.bw-step h3 {
  margin: 1.6rem 0 .5rem; font-size: .82rem; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text-low);
}
.bw-step textarea, .bw-step input[type="text"], .bw-step input:not([type]) {
  width: 100%; margin-top: .7rem; padding: .8rem .9rem;
  background: var(--ink-0); color: var(--text-hi);
  border: 1px solid var(--line-strong); border-radius: 8px;
  font: inherit; resize: vertical;
}
.bw-step textarea:focus, .bw-step input:focus {
  outline: 2px solid var(--amber); outline-offset: 1px;
}

.bw-tiles {
  display: grid; gap: .6rem; margin-top: .8rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
}
.bw-tiles-sm { grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr)); }
.bw-tile {
  display: flex; flex-direction: column; gap: .25rem; text-align: left;
  padding: .8rem .9rem; cursor: pointer;
  background: var(--glass); color: var(--text-hi);
  border: 1px solid var(--line); border-radius: 10px;
  font: inherit; transition: border-color .12s, background .12s;
}
.bw-tile:hover { border-color: var(--line-strong); background: var(--glass-strong); }
.bw-tile.is-on { border-color: var(--amber); background: rgba(242,181,68,.10); }
.bw-tile:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.bw-tile-name { font-weight: 600; }
.bw-tile-hint { font-size: .8rem; color: var(--text-low); line-height: 1.4; }

.bw-count { display: flex; align-items: center; gap: .9rem; margin-top: .8rem; }
.bw-count output {
  min-width: 2.5rem; text-align: center; font-size: 1.6rem; font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.bw-similar {
  margin-top: 1rem; padding: .9rem 1rem;
  border: 1px solid var(--amber-deep); border-radius: 8px;
  background: rgba(242,181,68,.06);
}
.bw-similar-head { margin: 0 0 .5rem; font-size: .9rem; color: var(--amber-hot); }
.bw-similar ul { margin: 0; padding-left: 1.1rem; font-size: .9rem; }
.bw-similar li { margin: .2rem 0; }

.bw-review { display: grid; grid-template-columns: 11rem 1fr; gap: .5rem 1rem; margin: 1rem 0 1.2rem; }
.bw-review dt { color: var(--text-low); font-size: .85rem; }
.bw-review dd { margin: 0; color: var(--text-hi); }

.bw-nav { display: flex; align-items: center; gap: .7rem; margin-top: 1.2rem; }
.bw-err { margin: 0 0 0 .4rem; color: #ff9d9d; font-size: .9rem; }
.bw-done { padding: 2rem 1.6rem; }

@media (max-width: 640px) {
  .bw-review { grid-template-columns: 1fr; gap: .1rem .5rem; }
  .bw-review dd { margin-bottom: .6rem; }
}


/* ==========================================================================
   6. COMPONENTS (2026 pass)

   Everything below is new and reusable. Nothing above was renamed — this
   layer is what new markup should be built from, and what the pages that
   belong to other work packages (dashboard, studio, admin, brief,
   storyboard detail, signup, error) can adopt in pass 2 without touching
   a single token.

   Each block below states: what it is, the markup it expects, and the
   modifiers it answers to. Read the comment before using the class.
   ========================================================================== */


/* --------------------------------------------------------------------------
   6.1 PAGE HEADER — .pg
   The band at the top of an app page: eyebrow, title, one line of
   explanation, and actions pinned to the end.

     <header class="pg">
       <div class="pg-text">
         <span class="eyebrow">Voice library</span>
         <h1 class="pg-title">Find the voice…</h1>
         <p class="pg-sub">One sentence.</p>
       </div>
       <div class="pg-actions"> …buttons… </div>
     </header>

   .page-head (the older class) still works and is styled as before; .pg
   is the version with a real type scale and a stable action rail.
   -------------------------------------------------------------------------- */

.pg {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-5);
  padding: clamp(2rem, 4.5vw, 3.25rem) 0 var(--sp-6);
}
.pg-text { max-width: 46rem; }
.pg-title { font-size: var(--fs-2xl); margin: 0; }
.pg-sub {
  color: var(--text-mid);
  font-size: var(--fs-base);
  margin: var(--sp-3) 0 0;
  max-width: 42rem;
}
.pg-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }


/* --------------------------------------------------------------------------
   6.2 TOOLBAR — .toolbar
   A horizontal control rail: search, chips, counts, view switches. Use
   .toolbar-sticky to park it under the site header while a long list
   scrolls. .toolbar-spacer pushes what follows it to the end.

     <div class="toolbar toolbar-sticky">
       <div class="searchbox">…</div>
       <div class="chipbar">…</div>
       <span class="toolbar-spacer"></span>
       <span class="count">264 voices</span>
     </div>
   -------------------------------------------------------------------------- */

.toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  background: color-mix(in srgb, var(--ink-1) 88%, transparent);
  box-shadow: var(--shadow-1);
}
.toolbar-sticky {
  position: sticky;
  top: var(--header-h);
  z-index: var(--z-sticky);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.toolbar-spacer { flex: 1 1 auto; }
.count { color: var(--text-mid); font-size: var(--fs-sm); white-space: nowrap;
         font-variant-numeric: tabular-nums; }

/* A sticky bar eats a phone screen. Below 720 px it rides with the page. */
@media (max-width: 720px) {
  .toolbar-sticky { position: static; }
}

/* Search field with a leading glyph. The <svg> must come first. */
.searchbox { position: relative; flex: 1 1 220px; min-width: 180px; max-width: 340px; }
.searchbox svg {
  position: absolute; inset-inline-start: 0.7rem; top: 50%;
  transform: translateY(-50%); width: 15px; height: 15px;
  color: var(--text-low); pointer-events: none;
}
.searchbox input {
  width: 100%;
  background: var(--field-bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  padding: 0.5rem 0.9rem 0.5rem 2.1rem;
  font: inherit; font-size: var(--fs-sm);
}


/* --------------------------------------------------------------------------
   6.3 FILTER CHIPS — .chipbar / .fpill
   .fpill is the canonical filter chip (already used by /voices,
   /characters, /templates). .chipbar is its wrapper; .chipbar-scroll
   makes the row scroll sideways on a phone instead of wrapping into four
   lines. States: .is-on (selected), [disabled] (no results behind it).
   A trailing <span class="fpill-n"> shows the faceted count and hides
   itself when empty.
   -------------------------------------------------------------------------- */

.chipbar { display: flex; flex-wrap: wrap; gap: var(--sp-1); align-items: center; }
.chipbar-scroll {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-bottom: 2px;
  scroll-snap-type: x proximity;
}
.chipbar-scroll::-webkit-scrollbar { display: none; }
.chipbar-scroll > * { flex: none; scroll-snap-align: start; }
.fpill:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }


/* --------------------------------------------------------------------------
   6.4 CARDS — .c-card and its three shapes
   One surface, three aspect behaviours:
     .c-card--portrait   9:16 media (Shorts, voice portraits)
     .c-card--landscape  16:9 media (long-form, template covers)
     .c-card--media      1:1 media  (people, characters)
   Structure is always the same:

     <article class="c-card c-card--landscape">
       <div class="c-card-media"><img …></div>
       <div class="c-card-body">
         <h3 class="c-card-title">…</h3>
         <p class="c-card-desc">…</p>
         <div class="c-card-foot">…</div>
       </div>
     </article>

   Use .c-grid (auto-fill) as the container; --c-min sets the column
   floor, so one grid serves phones and 1280 without a media query.
   -------------------------------------------------------------------------- */

.c-grid {
  --c-min: 250px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--c-min), 1fr));
  gap: var(--sp-5);
}
.c-grid--tight { --c-min: 168px; gap: var(--sp-3); }
.c-grid--wide  { --c-min: 300px; }

.c-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--glass);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  box-shadow: var(--shadow-1);
  transition: transform var(--speed) var(--ease-out),
              border-color var(--speed) var(--ease-out),
              box-shadow var(--speed) var(--ease-out);
}
.c-card:hover,
.c-card:focus-within {
  transform: translateY(-3px);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-2);
}
.c-card-media {
  position: relative;
  background: var(--ink-2);
  aspect-ratio: 16 / 9;
  overflow: hidden;
}
.c-card--portrait  .c-card-media { aspect-ratio: 9 / 16; }
.c-card--landscape .c-card-media { aspect-ratio: 16 / 9; }
.c-card--media     .c-card-media { aspect-ratio: 1; }
.c-card-media img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform var(--speed-slow) var(--ease-out);
}
.c-card:hover .c-card-media img { transform: scale(1.04); }
.c-card-body {
  display: flex; flex-direction: column; gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-4) var(--sp-5);
  flex: 1;
}
.c-card-title {
  margin: 0; font-family: var(--font-display); font-size: var(--fs-lg);
  line-height: 1.25;
}
.c-card-desc { margin: 0; color: var(--text-mid); font-size: var(--fs-sm); flex: 1; }
.c-card-foot { margin-top: auto; display: flex; gap: var(--sp-2); flex-wrap: wrap; }

/* Stretched link: the whole card is clickable, but the DOM keeps ONE
   anchor and any real buttons stay clickable as siblings. This is the
   fix for the featured-voice cards, which nested a <button> inside an
   <a> and needed preventDefault/stopPropagation to work at all (U-u29). */
.stretch-link::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
}
.has-stretch-link { position: relative; }
.has-stretch-link .above-link { position: relative; z-index: 2; }


/* --------------------------------------------------------------------------
   6.5 STATUS BADGES — .badge
   ONE vocabulary for pipeline state, everywhere in the product. The
   database statuses map onto it like this:

     draft       → Written    (script exists, nothing queued)
     queued      → Written    (waiting for a worker)
     rendering   → Voiced     (narration + frames in progress)
     uploaded    → Framed     (assets on the server, not yet cut)
     assembling  → Assembled  (being cut together)
     completed   → Delivered  (downloadable)
     failed      → Failed
     (admin hold)→ Held

   Markup: <span class="badge badge-delivered">Delivered</span>
   The live states (Written/Voiced/Framed/Assembled) pulse their dot so a
   running job is distinguishable from a parked one at a glance.
   -------------------------------------------------------------------------- */

.badge {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.26rem 0.7rem;
  border-radius: var(--radius-pill);
  font-size: var(--fs-xs); font-weight: 650; letter-spacing: 0.05em;
  border: 1px solid transparent; white-space: nowrap;
}
.badge::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; flex: none;
}
.badge-written   { color: var(--neutral); background: var(--neutral-bg); border-color: color-mix(in srgb, var(--neutral) 30%, transparent); }
.badge-voiced    { color: var(--warn);    background: var(--warn-bg);    border-color: color-mix(in srgb, var(--warn) 32%, transparent); }
.badge-framed    { color: var(--info);    background: var(--info-bg);    border-color: color-mix(in srgb, var(--info) 30%, transparent); }
.badge-assembled { color: var(--info);    background: var(--info-bg);    border-color: color-mix(in srgb, var(--info) 30%, transparent); }
.badge-delivered { color: var(--ok);      background: var(--ok-bg);      border-color: color-mix(in srgb, var(--ok) 32%, transparent); }
.badge-failed    { color: var(--bad);     background: var(--bad-bg);     border-color: color-mix(in srgb, var(--bad) 32%, transparent); }
.badge-held      { color: var(--text-mid); background: var(--glass-strong); border-color: var(--line-strong); }
.badge-voiced::before,
.badge-framed::before,
.badge-assembled::before { animation: pulse 1.6s ease-in-out infinite; }


/* --------------------------------------------------------------------------
   6.6 STAGE TRACKER — .tracker
   The five-stop journey of a board, in order. One <li> per stage:
   .is-done (behind us), .is-now (current), neither (ahead).

     <ol class="tracker">
       <li class="is-done"><span class="tracker-dot"></span>Written</li>
       <li class="is-now"> <span class="tracker-dot"></span>Voiced</li>
       …
     </ol>

   Horizontal from 620 px up, vertical below it — a five-stop rail does
   not fit a 375 px screen without either truncating or lying.
   -------------------------------------------------------------------------- */

.tracker {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--sp-3);
}
.tracker li {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-sm); color: var(--text-low);
  position: relative;
}
.tracker-dot {
  width: 11px; height: 11px; border-radius: 50%; flex: none;
  border: 2px solid currentColor; background: transparent;
}
.tracker li.is-done { color: var(--text-mid); }
.tracker li.is-done .tracker-dot { background: currentColor; }
.tracker li.is-now { color: var(--amber); font-weight: 650; }
.tracker li.is-now .tracker-dot {
  background: currentColor;
  box-shadow: 0 0 0 4px var(--amber-glow);
  animation: pulse 1.8s ease-in-out infinite;
}
@media (min-width: 620px) {
  .tracker { grid-auto-flow: column; grid-auto-columns: 1fr; gap: 0; }
  .tracker li { flex-direction: column; text-align: center; gap: var(--sp-2); }
  .tracker li::before {
    content: ""; position: absolute; top: 5px; inset-inline-start: -50%;
    width: 100%; height: 2px; background: var(--line);
  }
  .tracker li:first-child::before { display: none; }
  .tracker li.is-done::before,
  .tracker li.is-now::before { background: color-mix(in srgb, var(--amber) 55%, transparent); }
}


/* --------------------------------------------------------------------------
   6.7 EMPTY STATES — .empty
   Never a bare "nothing here". An empty state names what is missing, why,
   and the one action that fixes it.

     <div class="empty">
       <svg class="empty-icon">…</svg>
       <h3>No voices match those filters</h3>
       <p>…</p>
       <button class="btn btn-quiet">Clear filters</button>
     </div>

   .empty--inline is the smaller version for a panel inside a page.
   (.empty-state, the older class, is untouched and still used.)
   -------------------------------------------------------------------------- */

.empty {
  display: grid; justify-items: center; text-align: center;
  gap: var(--sp-3);
  padding: clamp(2.5rem, 6vw, 4rem) var(--sp-6);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-m);
  background: var(--glass);
  color: var(--text-mid);
}
.empty--inline { padding: var(--sp-6) var(--sp-4); }
.empty-icon { width: 38px; height: 38px; color: var(--text-low); }
.empty h3 { margin: 0; font-size: var(--fs-lg); }
.empty p { margin: 0; font-size: var(--fs-sm); color: var(--text-mid); max-width: 30rem; }
/* .empty-state p was --text-low: raised to --text-mid for AA (U-u15). */
.empty-state p { color: var(--text-mid); }


/* --------------------------------------------------------------------------
   6.8 SKELETONS — .skel
   Placeholder blocks while something loads. Give the element its real
   size so nothing jumps when the content lands.

     <div class="skel skel-media"></div>
     <div class="skel skel-line" style="width:70%"></div>

   The shimmer is disabled under prefers-reduced-motion (the global rule
   at the top of the file kills the animation; the flat tint remains).
   -------------------------------------------------------------------------- */

.skel {
  position: relative; overflow: hidden;
  background: var(--glass-strong);
  border-radius: var(--radius-s);
}
.skel::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent,
              rgba(255, 244, 224, 0.06), transparent);
  transform: translateX(-100%);
  animation: skel-sweep 1.4s var(--ease-in-out) infinite;
}
.skel-line { height: 0.85rem; margin-bottom: var(--sp-2); }
.skel-title { height: 1.35rem; width: 60%; margin-bottom: var(--sp-3); }
.skel-media { aspect-ratio: 16 / 9; border-radius: var(--radius-m); }
.skel-media--portrait { aspect-ratio: 9 / 16; }
.skel-media--square { aspect-ratio: 1; }
@keyframes skel-sweep { to { transform: translateX(100%); } }


/* --------------------------------------------------------------------------
   6.9 MODAL / DIALOG — .dlg
   Built on the native <dialog> element so Escape, focus trapping and the
   top layer come from the browser rather than from us.

     <dialog class="dlg" id="pick">
       <form method="dialog" class="dlg-panel">
         <header class="dlg-head">
           <h2 class="dlg-title">Pick a character</h2>
           <button class="btn-icon" value="cancel" aria-label="Close">×</button>
         </header>
         <div class="dlg-body">…</div>
         <footer class="dlg-foot">…</footer>
       </form>
     </dialog>

   Open with el.showModal(). For the older hand-rolled overlays (studio),
   .dlg-panel/.dlg-head/.dlg-body can be used on plain divs too.
   -------------------------------------------------------------------------- */

.dlg {
  border: 0; padding: 0; background: transparent;
  max-width: min(46rem, calc(100vw - 2 * var(--gutter)));
  max-height: calc(100dvh - 2 * var(--sp-8));
  color: var(--text-hi);
}
.dlg::backdrop { background: rgba(4, 3, 2, 0.72); backdrop-filter: blur(3px); }
.dlg[open] { animation: dlg-in 200ms var(--ease-out); }
@keyframes dlg-in { from { opacity: 0; transform: translateY(8px) scale(0.985); } }
.dlg-panel {
  display: flex; flex-direction: column;
  max-height: inherit;
  background: var(--ink-1);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-3);
  overflow: hidden;
}
.dlg-head {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--line);
}
.dlg-title { margin: 0; font-size: var(--fs-lg); flex: 1; }
.dlg-body { padding: var(--sp-5); overflow: auto; }
.dlg-foot {
  display: flex; gap: var(--sp-2); justify-content: flex-end;
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--line);
}


/* --------------------------------------------------------------------------
   6.10 TABS — .tabs
   Works with the existing [data-tab]/[data-tab-panel] handler in site.js
   (admin already uses it). Add role="tablist"/role="tab" in the markup;
   the CSS only draws it.
   -------------------------------------------------------------------------- */

.tabs {
  display: flex; gap: var(--sp-1); flex-wrap: wrap;
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--sp-6);
}
.tabs button {
  appearance: none; background: none; border: 0;
  border-bottom: 2px solid transparent;
  padding: var(--sp-3) var(--sp-4);
  color: var(--text-mid); font: 600 var(--fs-base) var(--font-body);
  cursor: pointer;
  transition: color var(--speed) var(--ease-out),
              border-color var(--speed) var(--ease-out);
}
.tabs button:hover { color: var(--text-hi); }
.tabs button.is-active { color: var(--amber); border-bottom-color: var(--amber); }


/* --------------------------------------------------------------------------
   6.11 BUTTONS — additions
   The .btn family above is unchanged. What is new:
     .btn-icon    square, glyph only — ALWAYS needs aria-label
     .btn-xs      dense rows and card feet
     .btn-group   segmented control (view switches)
     .btn.is-busy spinner + pointer-events off while a request runs
   -------------------------------------------------------------------------- */

.btn-icon {
  display: inline-grid; place-items: center;
  width: 2.25rem; height: 2.25rem; padding: 0;
  border-radius: var(--radius-s);
  border: 1px solid var(--line);
  background: transparent;
  color: var(--text-mid);
  cursor: pointer;
  transition: color var(--speed) var(--ease-out),
              border-color var(--speed) var(--ease-out),
              background var(--speed) var(--ease-out);
}
.btn-icon:hover { color: var(--text-hi); border-color: var(--line-strong); background: var(--glass-strong); }
.btn-icon svg { width: 17px; height: 17px; }
.btn-icon.is-round { border-radius: 50%; }

.btn-xs { padding: 0.28rem 0.65rem; font-size: var(--fs-xs); }

.btn-group {
  display: inline-flex; border: 1px solid var(--line);
  border-radius: var(--radius-s); overflow: hidden;
}
.btn-group > * {
  border: 0; border-inline-end: 1px solid var(--line); border-radius: 0;
  padding: 0.5rem 0.85rem; font-size: var(--fs-sm);
  background: transparent; color: var(--text-mid); cursor: pointer;
}
.btn-group > *:last-child { border-inline-end: 0; }
.btn-group > *.is-on { background: var(--glass-strong); color: var(--text-hi); }

.btn.is-busy { pointer-events: none; opacity: 0.7; }
.btn.is-busy::before {
  content: ""; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }


/* --------------------------------------------------------------------------
   6.12 PROGRESS — .prog
   A determinate bar. Set the width of .prog-fill from JS; it is used by
   the voice-clone upload, which previously gave no feedback at all on a
   25 MB file (U-u16).
   -------------------------------------------------------------------------- */

.prog {
  height: 6px; border-radius: var(--radius-pill);
  background: var(--glass-strong); overflow: hidden;
}
.prog-fill {
  height: 100%; width: 0;
  background: linear-gradient(90deg, var(--amber-deep), var(--amber));
  transition: width 160ms linear;
}
.prog-label { font-size: var(--fs-sm); color: var(--text-mid); margin-top: var(--sp-2); }


/* --------------------------------------------------------------------------
   6.13 KEYBOARD HINTS — .kbd
     Press <kbd class="kbd">/</kbd> to search
   -------------------------------------------------------------------------- */

.kbd-hint { font-size: var(--fs-sm); }

.kbd {
  display: inline-block; min-width: 1.5em; text-align: center;
  padding: 0.1em 0.4em;
  font: 600 var(--fs-xs) var(--font-mono);
  color: var(--text-mid);
  background: var(--glass-strong);
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: var(--radius-xs);
}


/* --------------------------------------------------------------------------
   6.14 SECTION SCAFFOLD — .band, .band-head
   A landing/marketing section with a headline block. .band-head--wide
   drops the 640 px reading measure when the head introduces a grid.
   -------------------------------------------------------------------------- */

.band { padding-block: clamp(3.5rem, 8vw, 6rem); }
.band--tight { padding-block: clamp(2.5rem, 5vw, 4rem); }
.band-head { max-width: 40rem; margin-bottom: clamp(2rem, 4vw, 3rem); }
.band-head--wide { max-width: none; }
.band-head--center { margin-inline: auto; text-align: center; }
.band-head--center .eyebrow::before { display: none; }
.band-head h2 { margin-bottom: var(--sp-3); }
.band-head p { color: var(--text-mid); font-size: var(--fs-md); margin: 0; }
.band-head--split {
  max-width: none; display: flex; flex-wrap: wrap;
  align-items: flex-end; justify-content: space-between; gap: var(--sp-5);
}
.band-head--split > div { max-width: 40rem; }


/* --------------------------------------------------------------------------
   6.15 LANDING — hero storyboard visual
   A real product picture, drawn in CSS: three storyboard frames on the
   left feeding one assembled cut on the right, with the stage tracker
   under it. No invented durations, no fake captions — it shows the
   MECHANISM, which is the honest thing to show when there is no
   showcase reel to play (U-u22).
   -------------------------------------------------------------------------- */

.hero-vis {
  position: relative;
  display: grid;
  gap: var(--sp-4);
  padding: var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-l);
  background:
    radial-gradient(120% 140% at 30% 0%, color-mix(in srgb, var(--ink-2) 90%, transparent), var(--ink-1) 70%);
  box-shadow: var(--shadow-2);
}
.hero-vis-row {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) auto minmax(0, 1.35fr);
  align-items: center;
  gap: var(--sp-4);
}
.hv-boards { display: grid; gap: var(--sp-2); }
.hv-board {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  background: var(--glass);
  font-size: var(--fs-xs);
  color: var(--text-mid);
}
.hv-board i {
  width: 26px; height: 18px; flex: none; border-radius: 3px;
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--amber) 40%, var(--ink-2)), var(--ink-2));
}
.hv-board:nth-child(2) i { background: linear-gradient(135deg, #3d4d5c, var(--ink-2)); }
.hv-board:nth-child(3) i { background: linear-gradient(135deg, #5c3d3d, var(--ink-2)); }
.hv-arrow { color: var(--amber); display: grid; place-items: center; }
.hv-arrow svg { width: 22px; height: 22px; }
.hv-cut {
  position: relative; aspect-ratio: 16 / 9; border-radius: var(--radius-m);
  border: 1px solid var(--line-strong);
  background:
    linear-gradient(180deg, rgba(0,0,0,0.4), transparent 30%, rgba(0,0,0,0.55)),
    radial-gradient(120% 130% at 65% 25%,
      color-mix(in srgb, var(--amber) 26%, #241a0d), #0d0a06 70%);
  overflow: hidden;
}
.hv-cut::before,
.hv-cut::after {
  content: ""; position: absolute; inset-inline: 0; height: 8%;
  background: rgba(0, 0, 0, 0.6);
}
.hv-cut::before { top: 0; } .hv-cut::after { bottom: 0; }
.hv-cut-play {
  position: absolute; inset: 0; display: grid; place-items: center;
  color: var(--amber);
}
.hv-cut-play span {
  width: 54px; height: 54px; border-radius: 50%; display: grid;
  place-items: center;
  background: rgba(11, 9, 6, 0.55);
  border: 1px solid var(--line-strong);
  backdrop-filter: blur(6px);
}
.hv-cut-play svg { width: 20px; height: 20px; margin-inline-start: 3px; }
.hv-wave {
  display: flex; align-items: flex-end; gap: 3px; height: 26px;
  padding-inline: var(--sp-1);
}
.hv-wave i {
  flex: 1; background: color-mix(in srgb, var(--amber) 55%, transparent);
  border-radius: 2px; min-height: 3px;
  animation: hv-eq 1.6s var(--ease-in-out) infinite;
}
@keyframes hv-eq { 0%, 100% { transform: scaleY(0.45); } 50% { transform: scaleY(1); } }
.hv-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); flex-wrap: wrap;
  padding-top: var(--sp-3); border-top: 1px solid var(--line);
  font-size: var(--fs-xs); color: var(--text-low);
  letter-spacing: 0.1em; text-transform: uppercase;
}
@media (max-width: 520px) {
  .hero-vis-row { grid-template-columns: 1fr; }
  .hv-arrow { transform: rotate(90deg); }
}


/* --------------------------------------------------------------------------
   6.16 LANDING — stage strip (how it works, four stages)
   -------------------------------------------------------------------------- */

.stage-strip {
  display: grid; gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  counter-reset: stage;
}
.stage {
  position: relative; counter-increment: stage;
  padding: var(--sp-6) var(--sp-5) var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  background: var(--glass);
  overflow: hidden;
}
.stage::before {
  content: "0" counter(stage);
  position: absolute; top: var(--sp-2); inset-inline-end: var(--sp-4);
  font: 500 3.4rem/1 var(--font-display);
  color: color-mix(in srgb, var(--amber) 12%, transparent);
  pointer-events: none;
}
.stage-icon {
  width: 38px; height: 38px; display: grid; place-items: center;
  border-radius: 11px; margin-bottom: var(--sp-3);
  background: var(--amber-glow);
  border: 1px solid color-mix(in srgb, var(--amber) 26%, transparent);
  color: var(--amber);
}
.stage-icon svg { width: 19px; height: 19px; }
.stage h3 { font-size: var(--fs-md); margin-bottom: var(--sp-2); }
.stage p { color: var(--text-mid); font-size: var(--fs-sm); margin: 0; }
.stage-out {
  margin-top: var(--sp-3); padding-top: var(--sp-3);
  border-top: 1px solid var(--line);
  font-size: var(--fs-xs); color: var(--text-low);
  letter-spacing: 0.08em; text-transform: uppercase;
}


/* --------------------------------------------------------------------------
   6.17 LANDING — format browser
   A dense, scannable grid of what the pipeline can actually render.
   Filter chips above it; each tile names the format and its shape.
   -------------------------------------------------------------------------- */

.fmt-grid {
  display: grid; gap: var(--sp-2);
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
}
.fmt {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-s);
  background: var(--glass);
  transition: border-color var(--speed) var(--ease-out),
              background var(--speed) var(--ease-out);
}
.fmt:hover { border-color: var(--line-strong); background: var(--glass-strong); }
.fmt-shape {
  flex: none; width: 20px; height: 26px; border-radius: 3px;
  border: 1px solid color-mix(in srgb, var(--amber) 45%, transparent);
  background: var(--amber-glow);
}
.fmt-shape.is-wide { width: 30px; height: 18px; }
.fmt-shape.is-audio { border-radius: 50%; width: 22px; height: 22px; }
.fmt-name { font-size: var(--fs-sm); color: var(--text-hi); line-height: 1.3; }
.fmt-kind { display: block; font-size: var(--fs-xs); color: var(--text-low); }


/* --------------------------------------------------------------------------
   6.18 LANDING — languages proof + showcase
   .showcase renders ONLY when the server supplies a `showcase` list of
   real delivered films. There is no placeholder variant on purpose: the
   old render wall shipped three empty gradients with invented durations
   and cast sizes (U-u22).
   -------------------------------------------------------------------------- */

.lang-proof {
  display: grid; gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.lang-card {
  padding: var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  background: var(--glass);
}
.lang-card .lang-sample {
  font-size: 1.5rem; line-height: 1.9; color: var(--text-hi);
  margin: 0 0 var(--sp-3); display: block;
}
.lang-card h3 { font-size: var(--fs-md); margin: 0 0 var(--sp-1); }
.lang-card p { margin: 0; font-size: var(--fs-sm); color: var(--text-mid); }

.showcase-grid {
  display: grid; gap: var(--sp-4);
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.showcase-item { display: flex; flex-direction: column; gap: var(--sp-3); }
.showcase-item video,
.showcase-item .showcase-poster {
  width: 100%; border-radius: var(--radius-m);
  border: 1px solid var(--line-strong);
  background: var(--ink-2);
  aspect-ratio: 16 / 9; object-fit: cover;
}
.showcase-meta {
  display: flex; gap: var(--sp-2); flex-wrap: wrap;
  font-size: var(--fs-xs); color: var(--text-low);
  letter-spacing: 0.08em; text-transform: uppercase;
}
.showcase-title { margin: 0; font-size: var(--fs-base); color: var(--text-hi); font-weight: 600; }


/* --------------------------------------------------------------------------
   6.19 FAQ — <details> based, no JS
   -------------------------------------------------------------------------- */

.faq { display: grid; gap: var(--sp-2); max-width: 46rem; }
.faq details {
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  background: var(--glass);
  padding: 0 var(--sp-5);
}
.faq summary {
  cursor: pointer; list-style: none;
  padding: var(--sp-4) 0;
  font: 600 var(--fs-base) var(--font-body);
  color: var(--text-hi);
  display: flex; align-items: center; gap: var(--sp-3);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; margin-inline-start: auto;
  color: var(--amber); font-size: 1.2rem; line-height: 1;
  transition: transform var(--speed) var(--ease-out);
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq summary:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.faq details > p {
  margin: 0 0 var(--sp-4); color: var(--text-mid); font-size: var(--fs-base);
  max-width: 42rem;
}


/* --------------------------------------------------------------------------
   6.20 "SHOW MORE" WINDOWING — .more-bar
   /voices renders 264 cards server-side (530 KB of HTML, 8,000 DOM
   nodes, 264 <img>). site.js now hides everything past the first window
   so the initial DOM is ~60 cards; this is the control that grows it
   (U-u12, client half). Filtering still runs across the FULL set — the
   window is a paint budget, not a filter.
   -------------------------------------------------------------------------- */

.more-bar {
  display: grid; justify-items: center; gap: var(--sp-2);
  margin: var(--sp-8) 0 var(--sp-4);
}
.more-bar p { margin: 0; font-size: var(--fs-sm); color: var(--text-mid); }


/* --------------------------------------------------------------------------
   6.21 CONTACT LINE — .contact-line
   Used on /pending and in the footer. The product had no way to reach
   anyone from any page (U-5, U-7).
   -------------------------------------------------------------------------- */

.contact-line {
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4);
  align-items: center; justify-content: center;
  padding: var(--sp-4);
  margin-top: var(--sp-6);
  border-top: 1px solid var(--line);
  font-size: var(--fs-sm); color: var(--text-mid);
}
.contact-line a { font-weight: 600; }


/* --------------------------------------------------------------------------
   6.22 ACCESSIBILITY UTILITIES
   -------------------------------------------------------------------------- */

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
  border: 0;
}
/* Anything that scrolls sideways must say so and must not take the page
   with it. Wrap wide tables, code and diagrams in this. */
.scroll-x { overflow-x: auto; max-width: 100%; }

/* .dim/.hint are read as content on cards, so they take --text-mid;
   --text-low is reserved for genuinely decorative type (U-u15). */
.dim { color: var(--text-mid); }
.dim-quiet { color: var(--text-low); }


/* --------------------------------------------------------------------------
   6.23 LATE ADDITIONS — the glue the new markup needs
   -------------------------------------------------------------------------- */

/* Upload status line: neutral by default, red once the client-side size
   check has rejected the file (U-u16). */
[data-upload-status].is-bad { color: var(--bad); }
[data-upload-progress] { margin-top: var(--sp-2); }

/* The filter bars park under the site header; both used a hardcoded 76px.
   --header-h is the single source now, so one change moves both. */
.vf-sticky { top: var(--header-h); }

/* A .pg header's actions must never push the page sideways. */
.pg-actions .btn { flex: 0 0 auto; }

.fmt[hidden] { display: none !important; }

/* Focus rings must not be clipped by an overflow:hidden card. */
.voice-card:focus-within,
.tpl-card:focus-within,
.c-card:focus-within { overflow: visible; }
.voice-card:focus-within .voice-portrait,
.tpl-card:focus-within .tpl-cover { overflow: hidden; }

/* Reduced motion: the equaliser, the toast slide and the skeleton sweep
   are decoration. The global rule at the top of the file clamps every
   animation to 0.01ms; these are the ones that would otherwise be left
   mid-transform when it does. */
@media (prefers-reduced-motion: reduce) {
  .hv-wave i { transform: none; }
  .skel::after { display: none; }
  .flash { animation: none; }
}


/* --------------------------------------------------------------------------
   6.24 CATALOGUE ON A PHONE
   At 375 px the 250 px column floor gave ONE card per row: a 264-voice
   library became a 264-screen scroll. Two up is the readable minimum for
   a browsing grid on a phone; the portrait stays square either way.
   -------------------------------------------------------------------------- */

@media (max-width: 560px) {
  .voice-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3); }
  .voice-body { padding: var(--sp-3); gap: var(--sp-2); }
  .voice-name { font-size: 1rem; flex-direction: column; align-items: flex-start; gap: 0.1rem; }
  .voice-desc { font-size: 0.78rem; }
  .voice-meta .chip, .voice-tag { font-size: 0.64rem; padding-inline: 0.45rem; }
  .voice-play { width: 36px; height: 36px; right: 0.5rem; bottom: 0.5rem; }
  .voice-play svg { width: 15px; height: 15px; }
  .tpl-grid { grid-template-columns: 1fr; }
  /* The "/" hint is meaningless without a keyboard. */
  .kbd-hint { display: none; }
}

/* 768 px: two columns of formats and a comfortable three of voices. */
@media (min-width: 561px) and (max-width: 900px) {
  .voice-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
}

/* The storyboard detail action row: it must wrap on a phone rather
   than push the page wider than the viewport (U-u14). */
.detail-actions {
  display: flex;
  gap: .6rem;
  align-items: center;
  flex-wrap: wrap;
}


/* ==========================================================================
   7. THE AUTHENTICATED APP (2026 pass 2)

   Pass 1 built the token layer and the component layer (section 6) and
   dressed the public pages. Everything below is what the SIGNED-IN pages
   needed on top of it: the project page, the studio workspace, the admin
   control room and the account chrome in the header.

   Same rules as section 6. Nothing here hard-codes a colour, every block
   says what it is and what markup it expects, and nothing above was
   renamed — the old class names all still resolve.
   ========================================================================== */


/* --------------------------------------------------------------------------
   7.1 CALLOUT — .callout
   A one-paragraph notice inside a page: a draft waiting to be rendered,
   a board that was restarted, edits that have not been rendered yet. It
   is NOT an empty state (.empty) and not a toast (.flash): those are
   "nothing here" and "something just happened". A callout is a standing
   fact about the thing you are looking at.

     <div class="callout callout--warn">
       <svg class="callout-icon" aria-hidden="true"><use href="#i-info"/></svg>
       <div class="callout-body"><b>Restarted.</b> …</div>
       <div class="callout-act"><button class="btn">…</button></div>
     </div>

   Modifiers: --warn (amber), --bad (a failure), --ok. Bare is neutral.
   The action rail wraps under the text below 620 px; the whole thing is
   a grid, not a flex row with a hard-coded gap, because that is what put
   the old inline `display:flex` rows off the side of a phone.
   -------------------------------------------------------------------------- */

.callout {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--sp-2) var(--sp-3);
  align-items: start;
  padding: var(--sp-4) var(--sp-5);
  margin-bottom: var(--sp-5);
  border: 1px solid var(--line);
  border-inline-start: 3px solid var(--line-strong);
  border-radius: var(--radius-m);
  background: var(--glass);
  font-size: var(--fs-base);
}
.callout-icon { width: 18px; height: 18px; color: var(--text-mid); margin-top: 2px; flex: none; }
.callout-body { margin: 0; color: var(--text-mid); }
.callout-body > :first-child { margin-top: 0; }
.callout-body > :last-child { margin-bottom: 0; }
.callout-body b, .callout-body strong { color: var(--text-hi); }
.callout-act {
  grid-column: 2;
  display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center;
}
.callout--warn { border-inline-start-color: var(--warn); background: var(--warn-bg); }
.callout--warn .callout-icon { color: var(--warn); }
.callout--bad  { border-inline-start-color: var(--bad);  background: var(--bad-bg); }
.callout--bad  .callout-icon { color: var(--bad); }
.callout--ok   { border-inline-start-color: var(--ok);   background: var(--ok-bg); }
.callout--ok   .callout-icon { color: var(--ok); }
@media (min-width: 700px) {
  .callout { grid-template-columns: auto 1fr auto; align-items: center; }
  .callout-act { grid-column: auto; }
}


/* --------------------------------------------------------------------------
   7.2 PROJECT PAGE — .prj
   The storyboard detail page. A signed-in customer opens it to answer
   one of three questions, in this order: is it done, can I have the
   files, and what is in it. The layout follows that order.

   .prj-split is the player + production rail; below 980 px the rail
   drops under the player rather than squeezing a 16:9 video into a
   column that cannot hold it.
   -------------------------------------------------------------------------- */

.prj-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-5);
  align-items: start;
  margin-bottom: var(--sp-8);
}
@media (min-width: 980px) {
  .prj-split { grid-template-columns: minmax(0, 1.9fr) minmax(280px, 1fr); }
}

/* The player. A card, not a bare <video>: the poster, the runtime and
   the download live together so the finished film reads as a deliverable
   rather than as an embedded file. */
.prj-player {
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  background: var(--ink-1);
  box-shadow: var(--shadow-1);
  overflow: hidden;
}
.prj-player video,
.prj-player .prj-poster {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  object-fit: contain;
}
.prj-player-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--line);
  font-size: var(--fs-sm); color: var(--text-mid);
}
.prj-player-foot .toolbar-spacer { flex: 1 1 auto; }

/* Progress sits full width above the film: it is the first question the
   page answers, and six horizontal stops do not fit a sidebar column at
   any viewport width — the labels overlapped each other. */
.prj-progress { margin-bottom: var(--sp-5); }

/* The rail: metadata beside the film. */
.prj-rail { display: grid; gap: var(--sp-4); }
.prj-panel {
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  background: var(--glass);
  padding: var(--sp-4) var(--sp-5);
}
.prj-panel > h2 {
  margin: 0 0 var(--sp-4);
  font: 600 var(--fs-xs)/1 var(--font-body);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-low);
}
/* The live line under the tracker: "4 of 6 scenes · last signal 31s ago".
   Empty until the poll answers, so it must not reserve a visible box. */
.prj-live { font-size: var(--fs-sm); color: var(--text-mid); margin: var(--sp-3) 0 0; }
.prj-live:empty { display: none; }
.prj-live.is-stale { color: var(--warn); }

/* Metadata as a definition list that never becomes a two-column squeeze
   on a phone. */
.prj-meta { display: grid; gap: var(--sp-3); margin: 0; }
.prj-meta > div { display: grid; gap: 2px; }
.prj-meta dt {
  font: 600 var(--fs-xs)/1 var(--font-body);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-low);
}
.prj-meta dd { margin: 0; font-size: var(--fs-sm); color: var(--text-hi); }
.prj-meta dd .dim { font-size: var(--fs-xs); }


/* --------------------------------------------------------------------------
   7.3 DELIVERY GRID — .deliv
   Everything the customer takes away. Each card is one artefact with one
   primary action; a card that has nothing to give says so rather than
   disappearing, because a missing card reads as a missing feature.
   -------------------------------------------------------------------------- */

.deliv {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: var(--sp-4);
}
.deliv-card {
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5) var(--sp-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  background: var(--glass);
}
.deliv-card h3 {
  margin: 0;
  font: 600 var(--fs-xs)/1 var(--font-body);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-low);
}
.deliv-card p { margin: 0; font-size: var(--fs-sm); color: var(--text-mid); }
.deliv-card .btn { align-self: flex-start; }
.deliv-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: auto; }
.deliv-card--wide { grid-column: 1 / -1; }
.deliv-thumb {
  display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--radius-s); border: 1px solid var(--line);
  background: var(--ink-2);
}
.deliv-desc {
  width: 100%; resize: vertical; min-height: 6rem;
  background: var(--field-bg); color: var(--text-hi);
  border: 1px solid var(--line); border-radius: var(--radius-s);
  padding: var(--sp-3); font: inherit; font-size: var(--fs-sm);
}
.deliv-credit {
  margin: 0; font-size: var(--fs-sm); color: var(--text-hi);
  background: var(--glass-strong); border-radius: var(--radius-s);
  padding: var(--sp-3); word-break: break-word;
}


/* --------------------------------------------------------------------------
   7.4 MEDIA TABLE — .mt
   A table whose first column is a picture: the scene list, and anything
   else that is "a row with a frame". Below 720 px it stops being a table
   and becomes a stack of rows, because a four-column table on a 375 px
   phone either truncates or scrolls the page sideways.

     <div class="scroll-x">
       <table class="data mt"> … <td class="mt-cell"><img class="mt-thumb"> …
   -------------------------------------------------------------------------- */

.mt-thumb {
  display: block; width: 132px; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--radius-s); border: 1px solid var(--line);
  background: var(--ink-2);
}
.mt-thumb--empty { display: grid; place-items: center; color: var(--text-low); }
.mt td { vertical-align: top; }
.mt .mt-media { width: 148px; }
/* The row-number column is addressed by position, not by a class: a
   test in the shared suite pins the exact `class="cell-num dim"` string
   on that cell, and a layout concern is not worth breaking it over. */
.mt .mt-num, .mt td:first-child { width: 3.5rem; }
.mt .mt-dur { width: 6rem; text-align: end; font-variant-numeric: tabular-nums; }
.mt .mt-shot { color: var(--text-mid); font-size: var(--fs-sm); max-width: 14rem; }

@media (max-width: 720px) {
  /* table.data carries min-width:640px so a real table scrolls rather
     than crushing its columns. A stacked one is not a table any more and
     the floor keeps it 640 px wide inside a 375 px screen — measured:
     the scene list still scrolled in its box at 375 until this line.
     It has to out-specify `table.data`, which a bare `.mt` does not —
     a media query changes nothing about specificity. */
  table.data.mt { min-width: 0; }
  .mt, .mt tbody, .mt td { display: block; width: auto; }
  .mt thead { display: none; }
  /* The frame goes in its own column on the left and the three text
     cells stack beside it. Both have to be placed EXPLICITLY: the
     picture is the second cell in source order (the row number comes
     first, which is right for a real table) and auto-placement put the
     narration in the 104 px column. */
  .mt tr {
    display: grid;
    grid-template-columns: 104px minmax(0, 1fr);
    gap: var(--sp-1) var(--sp-3);
    padding: var(--sp-4) 0;
    border-bottom: 1px solid var(--line);
    align-items: start;
  }
  /* `table.data td` is (0,1,2) and carries the row rule; a bare `.mt td`
     is (0,1,1) and loses to it, which left a stray underline beside
     every stacked cell. */
  table.data.mt td { border: 0; padding: 0; grid-column: 2; }
  table.data.mt td.mt-media { grid-column: 1; grid-row: 1 / span 4; width: auto; }
  .mt .mt-thumb { width: 100%; }
  .mt .mt-num { font-size: var(--fs-xs); }
  .mt .mt-shot, .mt .mt-dur { font-size: var(--fs-xs); color: var(--text-mid); }
  .mt .mt-dur { text-align: start; }
}


/* --------------------------------------------------------------------------
   7.5 ACCOUNT MENU — .usermenu
   The header used to spend two whole slots on the signed-in identity: a
   plain <li> with the address in it and a Sign out button beside it, on
   a nav that already carried seven links and wrapped onto two rows at
   1280. Both now live behind one control.

   Built on <details>/<summary> so it opens with no JavaScript at all;
   site.js only adds click-outside and Escape.

     <li class="usermenu-wrap">
       <details class="usermenu">
         <summary class="usermenu-btn">…</summary>
         <div class="usermenu-panel"> … </div>
       </details>
     </li>
   -------------------------------------------------------------------------- */

.usermenu { position: relative; }
.usermenu > summary { list-style: none; cursor: pointer; }
.usermenu > summary::-webkit-details-marker { display: none; }
.usermenu-btn {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: 0.35rem 0.6rem 0.35rem 0.35rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  color: var(--text-mid); font-size: var(--fs-sm); font-weight: 600;
  transition: border-color var(--speed) var(--ease-out), color var(--speed) var(--ease-out);
}
.usermenu-btn:hover, .usermenu[open] > .usermenu-btn {
  color: var(--text-hi); border-color: var(--line-strong);
}
.usermenu-avatar {
  display: grid; place-items: center; flex: none;
  width: 1.7rem; height: 1.7rem; border-radius: 50%;
  background: var(--amber); color: var(--amber-ink);
  font-size: var(--fs-xs); font-weight: 700; text-transform: uppercase;
}
.usermenu-caret { width: 12px; height: 12px; flex: none; }
.usermenu[open] .usermenu-caret { transform: rotate(180deg); }

.usermenu-panel {
  position: absolute; inset-inline-end: 0; top: calc(100% + 0.5rem);
  z-index: var(--z-header);
  min-width: 15rem;
  padding: var(--sp-3);
  background: var(--ink-1);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-m);
  box-shadow: var(--shadow-3);
  display: grid; gap: 2px;
}
.usermenu-id {
  padding: var(--sp-2) var(--sp-3) var(--sp-3);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--sp-2);
}
.usermenu-id b { display: block; color: var(--text-hi); font-size: var(--fs-base); }
.usermenu-id span { display: block; color: var(--text-low); font-size: var(--fs-xs); word-break: break-all; }
.usermenu-panel a,
.usermenu-panel button {
  display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; text-align: start;
  padding: var(--sp-2) var(--sp-3);
  border: 0; background: none; border-radius: var(--radius-s);
  color: var(--text-mid); font: inherit; font-size: var(--fs-sm);
  cursor: pointer;
}
/* An <svg><use> with no width fills its container. The sprite symbols
   have a viewBox and nothing else, so the sign-out glyph rendered at
   150 px inside the menu until this rule. */
.usermenu-panel svg { width: 15px; height: 15px; flex: none; }
.usermenu-panel a:hover,
.usermenu-panel button:hover { background: var(--glass-strong); color: var(--text-hi); }
.usermenu-panel form { margin: 0; }
.usermenu-sep { height: 1px; background: var(--line); margin: var(--sp-2) 0; }

/* Sign out in the footer's Account column: a form, so it can POST, but
   it has to read as the link it sits beside (HANDOFF-B2 §2). */
.nav-logout { display: inline; margin: 0; }
.nav-logout button {
  background: none; border: 0; padding: 0; font: inherit;
  color: inherit; cursor: pointer; text-align: start;
}
.nav-logout button:hover { color: var(--amber); }

/* On a phone the nav is a stacked drawer; a floating panel inside it
   would hang off the screen. It becomes an inline block instead. */
@media (max-width: 900px) {
  .usermenu-panel {
    position: static; box-shadow: none; min-width: 0;
    background: var(--glass); border-color: var(--line);
    margin-top: var(--sp-2);
  }
}

/* The theme control. Three states in one button: it shows what pressing
   it will DO, and its aria-label says the same thing. */
.theme-toggle .theme-on-dark { display: inline; }
.theme-toggle .theme-on-light { display: none; }
:root[data-theme="light"] .theme-toggle .theme-on-dark { display: none; }
:root[data-theme="light"] .theme-toggle .theme-on-light { display: inline; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme]) .theme-toggle .theme-on-dark { display: inline; }
}
.theme-toggle svg { width: 15px; height: 15px; flex: none; }


/* --------------------------------------------------------------------------
   7.6 STUDIO WORKSPACE — .stx
   The editor is not a page with a form on it; it is a workspace with one
   thing you are writing and one panel of decisions about it. The old
   layout put both in a two-column grid and let the sidebar scroll away,
   so on a 30-scene board the Send button — and the runtime estimate that
   tells you whether the board is the right LENGTH — were a full screen
   of scrolling away from the scene you were editing.

   .stx-side is sticky from 1000 px up and its own scroll container, so a
   long production panel never pushes the submit block off the bottom.
   -------------------------------------------------------------------------- */

.stx {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-6);
  align-items: start;
}
@media (min-width: 1000px) {
  .stx { grid-template-columns: minmax(0, 1fr) minmax(320px, 380px); }
  .stx-side {
    position: sticky;
    top: calc(var(--header-h) + var(--sp-4));
    max-height: calc(100dvh - var(--header-h) - var(--sp-8));
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    padding-inline-end: 2px;   /* room for the scrollbar, not the content */
  }
}
.stx-side { display: grid; gap: var(--sp-4); align-content: start; }
/* The old rule hoisted the sidebar above the scenes below 960 px
   (`.st-side { order: -1 }`), which was defensible when the panel was
   only settings. It is not now that the panel leads with Save: a phone
   opened the editor on a Save button and the runtime of a board the
   reader could not yet see. Scenes first; the submit block is the first
   thing under them, and the settings follow it. */
@media (max-width: 960px) { .stx-side { order: 0; } }

/* The scene column head: count, search, import, keyboard hints. */
.stx-head {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--sp-2) var(--sp-3);
  margin-bottom: var(--sp-4);
}
.stx-head h2 { margin: 0; font-size: var(--fs-lg); }
.stx-head .searchbox { flex: 1 1 160px; max-width: 260px; }

/* A scene card. It is the .card surface plus a head rail that survives a
   375 px screen: the tools wrap under the title instead of pushing it. */
.stx-scene { padding: var(--sp-4); margin-bottom: var(--sp-3); scroll-margin-top: calc(var(--header-h) + var(--sp-4)); }
.stx-scene.is-dragging { opacity: 0.45; }
.stx-scene.is-hit { border-color: var(--amber); box-shadow: var(--focus-ring); }
.stx-scene[hidden] { display: none !important; }
.stx-scene-head {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--sp-2); margin-bottom: var(--sp-3);
}
.stx-scene-num {
  font: 600 var(--fs-xs)/1 var(--font-body);
  letter-spacing: var(--tracking-caps); text-transform: uppercase;
  color: var(--text-low);
}
.stx-scene-secs { font-size: var(--fs-xs); color: var(--text-low); font-variant-numeric: tabular-nums; }
.stx-scene-tools { display: flex; gap: 2px; margin-inline-start: auto; }

/* The per-scene speaker pill: who says this line, as a control that
   looks like the cast entry it points at rather than a bare <select>. */
.spk {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: var(--glass-strong);
  padding-inline-start: 0.5rem;
}
.spk-letter {
  display: grid; place-items: center;
  width: 1.15rem; height: 1.15rem; border-radius: 50%;
  background: var(--neutral); color: var(--ink-0);
  font: 700 0.62rem/1 var(--font-body);
}
.spk select {
  appearance: none; background: none; border: 0; padding: 0.25rem 0.5rem 0.25rem 0.25rem;
  color: var(--text-mid); font: inherit; font-size: var(--fs-xs); cursor: pointer;
  max-width: 11rem;
}
.spk select:focus-visible { outline: 2px solid var(--amber); outline-offset: 1px; border-radius: var(--radius-pill); }
.spk-A .spk-letter { background: var(--amber); color: var(--amber-ink); }
.spk-B .spk-letter { background: var(--info); color: var(--ink-0); }
.spk-C .spk-letter { background: var(--ok); color: var(--ink-0); }
.spk-D .spk-letter { background: var(--warn); color: var(--ink-0); }
.spk-E .spk-letter { background: var(--bad); color: var(--ink-0); }
.spk-F .spk-letter { background: var(--text-mid); color: var(--ink-0); }

/* The rendered frame on a scene card, in edit mode. Clicking it marks
   the scene for regeneration — the marked state has to be visible
   without colour alone, so it also carries a label. */
.stx-frame {
  position: relative; display: block; width: 100%;
  margin: 0 0 var(--sp-3);
  border: 0; padding: 0; background: none; cursor: pointer;
  border-radius: var(--radius-s); overflow: hidden;
}
.stx-frame img {
  display: block; width: 100%; max-height: 170px; object-fit: cover;
  border-radius: var(--radius-s); border: 1px solid var(--line);
  transition: opacity var(--speed) var(--ease-out);
}
.stx-frame-mark {
  position: absolute; inset: 0;
  display: none; align-items: center; justify-content: center;
  gap: var(--sp-2);
  background: var(--scrim); color: var(--amber);
  font-size: var(--fs-sm); font-weight: 650;
  border-radius: var(--radius-s);
}
.stx-frame.is-regen img { opacity: 0.35; }
.stx-frame.is-regen .stx-frame-mark { display: flex; }
.stx-frame:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.stx-frame-meta {
  display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4);
  align-items: baseline; font-size: var(--fs-xs); color: var(--text-low);
  margin-bottom: var(--sp-3);
}
.stx-frame-meta details { min-width: 0; }
.stx-frame-meta summary { cursor: pointer; }
.stx-frame-meta span[dir] { user-select: all; }

/* The submit block: the runtime estimate as a bar against the format's
   own length band, so "0:42" means something without knowing that a
   Short caps at 180 s. --pct is written by studio.js. */
.stx-runtime { display: grid; gap: var(--sp-2); }
.stx-runtime-top {
  display: flex; align-items: baseline; gap: var(--sp-2);
}
.stx-runtime-num {
  font: 600 var(--fs-xl)/1 var(--font-display);
  color: var(--text-hi); font-variant-numeric: tabular-nums;
}
.stx-runtime-band {
  --pct: 0%;
  position: relative; height: 6px; border-radius: var(--radius-pill);
  background: var(--glass-strong); overflow: hidden;
}
.stx-runtime-band::after {
  content: ""; position: absolute; inset-block: 0; inset-inline-start: 0;
  width: var(--pct);
  background: linear-gradient(90deg, var(--amber-deep), var(--amber));
  transition: width 200ms var(--ease-out);
}
.stx-runtime-band.is-over::after { background: var(--bad); }
.stx-runtime-note { font-size: var(--fs-xs); color: var(--text-mid); margin: 0; }
.stx-runtime-note.is-over { color: var(--warn); }

/* The autosave stamp. It reports a fact ("saved locally 12:04") and is
   empty until there is one — never a permanent "Saving…" that lies. */
.stx-stamp { font-size: var(--fs-xs); color: var(--text-low); margin: 0; min-height: 1.1em; }
.stx-stamp.is-dirty { color: var(--warn); }

/* Keyboard hints sit under the controls they describe and disappear on
   a touch screen, where they are noise. */
.stx-keys {
  display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4);
  font-size: var(--fs-xs); color: var(--text-low);
  margin: var(--sp-3) 0 0;
}
@media (max-width: 720px) { .stx-keys { display: none; } }

/* The regenerate tool, when it is armed. Colour alone would not say it,
   so the button also carries aria-pressed. */
.st-tool.is-on { color: var(--amber); }

/* The save/error line under the submit button. It used to carry
   style="color:var(--bad)" and then be repainted to green from JS with a
   hard-coded hex; both meanings are tokens now. */
.st-error { color: var(--bad); min-height: 1.1em; }
.st-error.is-ok { color: var(--ok); }

/* The import textarea: eight inline style declarations, none of which
   were about this textarea in particular. */
.st-import-text {
  width: 100%;
  background: var(--field-bg); color: var(--text-hi);
  border: 1px solid var(--line); border-radius: var(--radius-s);
  padding: var(--sp-3); font: inherit;
}
.st-import-text.lang-urdu { font-family: var(--font-urdu); line-height: 2.1; }

/* The rendered cover, in the edit-mode banner. */
.stx-cover {
  width: 128px; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--radius-s); border: 1px solid var(--line);
}

/* The character picker holds a grid, so it gets the wide dialog. */
.dlg-wide { max-width: min(64rem, calc(100vw - 2 * var(--gutter))); }

/* A .field-inline that is switched off must actually disappear: the
   caption options are hidden with the `hidden` attribute and a bare
   display:flex outranks the UA's [hidden] rule. */
.field-inline[hidden] { display: none; }

/* The character picker grid inside the native dialog. */
.stx-picks {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--sp-3);
}
.stx-pick {
  display: grid; gap: 2px; text-align: start;
  padding: var(--sp-3); cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius-m);
  background: var(--glass); color: var(--text-mid); font: inherit;
}
.stx-pick:hover { border-color: var(--line-strong); background: var(--glass-strong); }
.stx-pick:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.stx-pick img {
  width: 100%; aspect-ratio: 1; object-fit: cover;
  border-radius: var(--radius-s); margin-bottom: var(--sp-2);
  background: var(--ink-2);
}
.stx-pick b { color: var(--text-hi); font-size: var(--fs-sm); }
.stx-pick small { font-size: var(--fs-xs); color: var(--text-low); }


/* --------------------------------------------------------------------------
   7.7 ADMIN — leftovers the control room needed
   Two things: a <select> inside a table cell had no width floor and
   collapsed to the arrow alone on the approvals row, and the inline
   forms in a cell were hand-rolled flex with no wrap.
   -------------------------------------------------------------------------- */

.cellform {
  display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center;
  margin: 0;
}
.cellform select, .cellform input { min-width: 9rem; }
.inline-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }
.adm-form-grid {
  display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: end;
}
.adm-form-grid .field { margin: 0; min-width: 11rem; flex: 1 1 11rem; }
.adm-form-grid button { flex: 0 0 auto; }
.adm-assign { max-width: 11rem; }
.adm-adduser { margin-top: var(--sp-4); max-width: 44rem; }
.adm-adduser h3 { margin-top: 0; }
.adm-tagline { font-size: var(--fs-sm); font-weight: 400; }
.adm-last-check { margin-bottom: var(--sp-6); }
.adm-reset { margin-top: var(--sp-2); }


/* --------------------------------------------------------------------------
   7.8 FORM PAGES — the shared shell
   /storyboards/new, /signup and the clone-upload form all had their own
   inline padding and their own idea of how wide a form should be.
   -------------------------------------------------------------------------- */

.formcard { padding: clamp(1.4rem, 4vw, 2rem) clamp(1.2rem, 3.5vw, 1.9rem); }
.form-actions {
  display: flex; flex-wrap: wrap; gap: var(--sp-3);
  align-items: center; margin-top: var(--sp-6);
}
.field-check {
  display: flex; gap: var(--sp-3); align-items: flex-start; cursor: pointer;
  font-weight: 400;
}
.field-check input { width: auto; flex: none; margin-top: 0.28rem; accent-color: var(--amber); }
.field-inline { display: flex; flex-wrap: wrap; gap: var(--sp-4); }
.field-inline > label { display: grid; gap: var(--sp-1); font-size: var(--fs-sm); color: var(--text-mid); }
.field-flush { margin: 0; }
.label-sm { font-size: var(--fs-xs) !important; }
/* A <fieldset> carries a UA border and padding that fight every card it
   sits in; the group semantics are what it is here for. */
.fieldset-bare { border: 0; padding: 0; margin: 0; min-width: 0; }
.fieldset-bare > legend {
  padding: 0;
  font: 600 var(--fs-sm)/1.3 var(--font-body);
  color: var(--text-hi);
  margin-bottom: var(--sp-2);
}
/* A single-column form does not want the 1160 px measure. */
.container-narrow { max-width: 780px; }

/* An icon sitting inside a line of button text. */
.icon-inline { width: 13px; height: 13px; vertical-align: -2px; }

/* /my-voices and /schedule: the last of the inline style attributes. */
.mv-upload { margin-top: var(--sp-10); }
.sched-h2 {
  margin: 0 0 var(--sp-3);
  font: 600 var(--fs-xs)/1 var(--font-body);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-low);
}
.sched-due { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.sched-due td { padding: var(--sp-2) 0; border-bottom: 1px solid var(--line); }
.sched-due tr:last-child td { border-bottom: 0; }
.sched-listhead { margin: var(--sp-8) 0 var(--sp-4); }


/* --------------------------------------------------------------------------
   7.12 DASHBOARD AND BRIEF — the classes lane B's pass 2 markup expects
   Verbatim from HANDOFF-B2.md §1. dashboard.html and brief.html are lane
   B's files; these five rules are the half that lives here. Every one of
   them degrades to readable block flow when missing, which is why the
   pages already work — but none of them is laid out.
   -------------------------------------------------------------------------- */

/* The failure headline on a portrait (Shorts) card. It used to live only
   in a title= tooltip, which a phone and a screen reader never show, so
   12/12 failed Shorts rendered with no visible reason (U-u17). It sits
   in the scrim above the meta line and must clamp: an ffmpeg headline is
   longer than a 158 px card. */
.sbp-fail {
  margin: 0.25rem 0 0;
  font-size: 0.72rem;
  line-height: 1.3;
  color: var(--bad);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* "Your briefs" on the dashboard (A-1): one row per wizard brief the
   signed-in user has sent, with its state. Rows, not cards in a grid — a
   brief is a line item, and there are rarely more than three. */
.brief-list { display: grid; gap: var(--sp-2); margin-bottom: var(--sp-5); }
.brief-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-3) var(--sp-4);
}
.brief-row-main { flex: 1 1 20rem; min-width: 0; }
.brief-row-state { display: flex; align-items: center; gap: var(--sp-2);
                   flex-wrap: wrap; }
.brief-topic {
  margin: 0; color: var(--text-hi); font-size: var(--fs-sm);
  display: -webkit-box; -webkit-line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden;
}
.brief-meta { margin: 0.2rem 0 0; font-size: var(--fs-xs); }

/* The remaining-characters hint under the wizard's subject box. It is
   hidden until the last 300 characters, so it is quiet until it matters
   (A-1: the live brief arrived cut mid-word at exactly 600). */
.bw-count-hint { margin: 0.35rem 0 0; font-size: var(--fs-xs); }
.bw-count-hint.is-full { color: var(--warn); }


/* --------------------------------------------------------------------------
   7.13 API TOKENS — the one-shot plaintext
   A minted token is shown once and never again. It has to be selectable
   as one unit and it must not wrap into something a reader can mis-copy.
   -------------------------------------------------------------------------- */

.token-plain {
  display: inline-block;
  font: 600 var(--fs-sm) var(--font-mono);
  color: var(--text-hi);
  background: var(--field-bg);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-s);
  padding: var(--sp-2) var(--sp-3);
  user-select: all;
  word-break: break-all;
}
/* A grid item's automatic minimum size is min-content, not zero, so the
   wrapper around an eight-column table refused to shrink and took the
   page sideways at 375 (measured: clientWidth 375, scrollWidth 901) even
   though the .scroll-x box inside it was ready to scroll. */
.tok-wrap { display: grid; gap: var(--sp-6); }
.tok-wrap > *, .stx > *, .prj-split > * { min-width: 0; }
.tok-mint { padding: var(--sp-6); max-width: 34rem; }
.tok-mint h3 { margin: 0 0 var(--sp-5); font-size: var(--fs-lg); }


/* --------------------------------------------------------------------------
   7.9 ERROR PAGE — .errpage
   A 404 is a page, not a stack trace. It gets the same header, the same
   footer and one way out.
   -------------------------------------------------------------------------- */

.errpage { max-width: 44rem; margin-inline: auto; padding-block: clamp(3rem, 9vw, 6rem); }
.errpage .empty { background: var(--glass); }
.errpage-actions { display: flex; flex-wrap: wrap; gap: var(--sp-2); justify-content: center; }
.errpage .contact-line { margin-top: var(--sp-4); }


/* --------------------------------------------------------------------------
   7.10 NO PAGE MAY SCROLL SIDEWAYS
   Measured at 375, 768 and 1280 on every page in this package. The two
   things that broke it were a long unbroken token (an Urdu title, a
   format id, a raw error) and a flex row with no wrap. The first is what
   this rule is for; the second is fixed at each site.
   -------------------------------------------------------------------------- */

/* `break-word`, NOT `anywhere`: `anywhere` also shrinks the element's
   min-content width, which let the packages table collapse its Name
   column to one character per line inside .panel-split. `break-word`
   breaks a token that genuinely does not fit and changes nothing else. */
.pg-title, .c-card-title, .prj-meta dd, .deliv-card p { overflow-wrap: break-word; }
table.data td, table.data th { overflow-wrap: break-word; }

/* The package editor sits beside its table. Below 1100 px the table was
   a 640 px min-width squeezed into a 460 px column: a horizontal
   scrollbar on a panel that had a whole empty page beside it. */
@media (max-width: 1100px) { .panel-split { grid-template-columns: minmax(0, 1fr); } }


/* --------------------------------------------------------------------------
   7.11 ALLOCATION ROW — the last inline styles on the project page
   Three labels and a note carried style="" attributes; the note in
   particular needed flex-basis:100% to sit on its own line, and that is
   a layout decision, not a one-off.
   -------------------------------------------------------------------------- */

.alloc-when { font-weight: 500; display: inline-flex; align-items: center; gap: var(--sp-2); }
.alloc-box label.alloc-when { font-weight: 500; }
.alloc-when input { width: auto; accent-color: var(--amber); }
.alloc-note { font-size: var(--fs-sm); flex-basis: 100%; }


/* ==========================================================================
   8. MOTION (2026-09-03 — the LTX pass)
   The facelift's design system had no vocabulary for video: every visual
   component assumed a still or a table. These five do the work of the
   whole motion front end — a video card, a featured strip, a category
   rail, a per-shot filmstrip and a cost meter — and every one of them is
   built so the page does not move when a clip finishes loading.
   ========================================================================== */

/* --------------------------------------------------------------------------
   8.1 VIDEO CARD — .sc-card / .sc-frame
   The frame is an aspect-ratio box, ALWAYS. A <video> with no intrinsic
   size is 300x150 until its metadata arrives, and with preload="none"
   that is never — so a grid of lazy players would reflow the moment the
   first one attached. aspect-ratio reserves the space up front and the
   poster paints into it.
   -------------------------------------------------------------------------- */

.sc-frame {
  position: relative;
  aspect-ratio: 9 / 16;
  border-radius: var(--radius-m);
  overflow: hidden;
  background: var(--glass-strong);
  border: 1px solid var(--line);
}
.sc-frame video,
.sc-frame img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
/* A slot with nothing in it. Deliberately not a gradient that could be
   mistaken for a frame of film: a dashed box with the words in it. */
.sc-frame--empty {
  display: grid; place-items: center;
  border-style: dashed;
  background: transparent;
}
.sc-slot-mark {
  font-size: var(--fs-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-low);
}
.sc-card { display: flex; flex-direction: column; gap: var(--sp-3); margin: 0; min-width: 0; }
.sc-card.is-slot .sc-cap { opacity: .78; }
.sc-cap { display: flex; flex-direction: column; gap: var(--sp-2); }
.sc-title { margin: 0; font-weight: 600; color: var(--text-hi); font-size: var(--fs-base); }
.sc-blurb { margin: 0; color: var(--text-mid); font-size: var(--fs-sm); line-height: 1.5; }
.sc-note { margin: 0; color: var(--text-low); font-size: var(--fs-xs); font-style: italic; }
.sc-meta { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.chip-quiet { background: transparent; border: 1px solid var(--line); color: var(--text-low); }

/* The sound toggle sits on the clip. It says the state in words — an
   unlabelled speaker glyph is the one control people press twice. */
.sc-sound {
  position: absolute; inset-block-end: var(--sp-3); inset-inline-end: var(--sp-3);
  font: inherit; font-size: var(--fs-xs);
  padding: var(--sp-2) var(--sp-3);
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: rgb(0 0 0 / .62);
  color: #fff;
  cursor: pointer;
}
.sc-sound:hover { background: rgb(0 0 0 / .8); }
.sc-sound:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   8.2 FEATURED STRIP — .sc-strip
   Hero clips are 1088x1920. Three across on a desktop is 3264 px of
   source in a 1200 px container, which is fine for a video element and
   catastrophic if the cards are allowed to grow: the strip caps each
   card so the browser is never asked to scale a hero clip up.
   -------------------------------------------------------------------------- */

.sc-strip {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
}
.sc-card--hero .sc-frame { border-color: var(--line-strong); }
.sc-grid {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr));
}
.sc-group { margin-block: clamp(2.5rem, 6vw, 4rem); }
.sc-facts { padding: var(--sp-6); }
.sc-facts h2 { margin: 0 0 var(--sp-4); font-size: var(--fs-lg); }
.sc-factlist { margin: 0; padding-inline-start: 1.1rem; display: grid; gap: var(--sp-3); }
.sc-factlist li { color: var(--text-mid); font-size: var(--fs-sm); line-height: 1.55; }
.sc-factlist b { color: var(--text-hi); font-weight: 600; }
.sc-licence { margin: var(--sp-5) 0 0; font-size: var(--fs-xs); }

/* --------------------------------------------------------------------------
   8.3 CATEGORY RAIL — .rail
   A row of tiles per category on the home page. Below 720 px it becomes
   a horizontal scroller rather than wrapping: six categories x four
   wrapped tiles is a home page nobody reaches the bottom of on a phone.
   -------------------------------------------------------------------------- */

.rail { margin-block: clamp(2rem, 5vw, 3.2rem); }
.rail-head { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: baseline; justify-content: space-between; margin-bottom: var(--sp-4); }
.rail-head h3 { margin: 0; font-size: var(--fs-lg); }
.rail-head p { margin: 0; color: var(--text-mid); font-size: var(--fs-sm); flex-basis: 100%; }
.rail-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(13rem, 1fr);
  gap: var(--sp-4);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-bottom: var(--sp-3);
  scrollbar-width: thin;
}
.rail-track > * { scroll-snap-align: start; min-width: 0; }
@media (min-width: 900px) {
  .rail-track {
    grid-auto-flow: row;
    grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
    overflow-x: visible;
  }
}
.rail-tile {
  display: flex; flex-direction: column; gap: var(--sp-2);
  padding: var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-m);
  background: var(--glass);
  color: inherit; text-decoration: none;
}
.rail-tile:hover { border-color: var(--line-strong); background: var(--glass-strong); }
.rail-tile b { color: var(--text-hi); font-size: var(--fs-sm); }
.rail-tile span { color: var(--text-low); font-size: var(--fs-xs); line-height: 1.45; }

/* --------------------------------------------------------------------------
   8.4 SHOT FILMSTRIP — .shotstrip / .shot
   The delivery page's per-shot row. A shot is not a scene: it has a
   duration, possibly a camera move and possibly a voice in it, and those
   three facts are what a customer checks before they publish.
   -------------------------------------------------------------------------- */

.shotstrip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(9.5rem, 1fr);
  gap: var(--sp-4);
  overflow-x: auto;
  padding-bottom: var(--sp-3);
}
@media (min-width: 900px) {
  .shotstrip {
    grid-auto-flow: row;
    grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr));
    overflow-x: visible;
  }
}
.shot { display: flex; flex-direction: column; gap: var(--sp-2); min-width: 0; }
.shot .sc-frame { aspect-ratio: 9 / 16; }
.shot-n { font-size: var(--fs-xs); color: var(--text-low); letter-spacing: .06em; text-transform: uppercase; }
.shot-chips { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.shot-chips .chip { font-size: var(--fs-xs); }

/* --------------------------------------------------------------------------
   8.5 COST METER — .meter
   A number with nothing to compare it against is not information. The
   meter draws the ask against the format's own GPU budget, so "232
   seconds" means something without knowing what the budget is.
   -------------------------------------------------------------------------- */

.meter { display: grid; gap: var(--sp-2); }
.meter-bar {
  position: relative;
  height: .5rem;
  border-radius: 999px;
  background: var(--glass-strong);
  border: 1px solid var(--line);
  overflow: hidden;
}
.meter-fill { position: absolute; inset-block: 0; inset-inline-start: 0; background: var(--amber); }
.meter-fill.is-over { background: var(--bad); }
.meter-line { display: flex; flex-wrap: wrap; gap: var(--sp-3); justify-content: space-between; font-size: var(--fs-xs); color: var(--text-mid); }
.meter-line b { color: var(--text-hi); }

/* --------------------------------------------------------------------------
   8.6 REDUCED MOTION
   The autoplay in the featured strip is decoration. Someone who has told
   their operating system that movement makes them ill has told us too,
   and showcase.js reads the same query before it calls play().
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .sc-frame video { animation: none !important; }
}


/* --------------------------------------------------------------------------
   8.7 THE STAGE STRIP AS AN ORDERED LIST
   /how-it-works numbers its four stages, so the strip is an <ol> there
   rather than a div of <article>s: the order is the content, and a
   screen reader should be told there are four of them and which one it
   is on. The visual treatment is unchanged.
   -------------------------------------------------------------------------- */

.stage-strip--numbered { list-style: none; margin: 0; padding: 0; }
.stage-strip--numbered > .stage { margin: 0; }
