/* ============================================================
   TTS Studio — Design Tokens
   Direction: "Warm Room" v1
   ------------------------------------------------------------
   Rules for anyone (human or AI) writing UI in this codebase:
   1. Never hardcode a hex value in a component. Use a token.
   2. --signal (amber) is only for things that carry or produce
      sound. One --signal action per screen, maximum.
   3. --seal (teal) means sealed / verified / safe. Nothing else.
   4. Fully round corners (--radius-ribbon) belong to the take
      ribbon and its playhead only.
   5. No gradients, no glass, no glow, no blur. Matte only.
   6. If a token you need does not exist, add it here first.
   7. Borders come in three strengths and they are not
      interchangeable. --line and --line-strong are decorative:
      they separate things, and they sit well under 3:1 on purpose
      so the room stays quiet. --line-control is the only border
      allowed to be the thing that identifies an interactive
      control (input, ghost button, checkbox). WCAG 1.4.11 needs
      3:1 there, and the surface fills in this palette are too
      close to the canvas to carry that job on their own.
   ============================================================ */

:root {
  /* ---- Typography ---------------------------------------- */
  --font-display: "Bricolage Grotesque", system-ui, sans-serif;
  --font-body: "Public Sans", "Noto Sans Thai Looped", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", monospace;

  --text-2xs: 0.6875rem;  /* 11px — mono labels, eyebrows */
  --text-xs:  0.75rem;    /* 12px — captions, meta */
  --text-sm:  0.8125rem;  /* 13px — dense UI, table cells */
  --text-base:0.875rem;   /* 14px — default UI text */
  --text-md:  1rem;       /* 16px — body prose, inputs */
  --text-lg:  1.25rem;    /* 20px */
  --text-xl:  1.5rem;     /* 24px — h2 */
  --text-2xl: 2rem;       /* 32px — h1 in app */
  --text-3xl: 3rem;       /* 48px — h1 on marketing */
  --text-4xl: 4rem;       /* 64px — hero only */

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-display: 600;  /* display face only — never on body */

  --leading-tight: 1.05;  /* display */
  --leading-snug: 1.4;    /* headings, labels */
  --leading-body: 1.6;    /* UI text */
  --leading-prose: 1.75;  /* long paragraphs */
  --leading-thai: 1.85;   /* Thai needs room for vowel marks */

  --tracking-display: -0.025em;
  --tracking-normal: 0;
  --tracking-label: 0.14em; /* mono eyebrows / uppercase labels */

  /* ---- Spacing (4px base) -------------------------------- */
  --space-1: 0.25rem; --space-2: 0.5rem;  --space-3: 0.75rem;
  --space-4: 1rem;    --space-5: 1.25rem; --space-6: 1.5rem;
  --space-8: 2rem;    --space-10: 2.5rem; --space-12: 3rem;
  --space-16: 4rem;   --space-20: 5rem;

  /* ---- Shape --------------------------------------------- */
  --radius-tag: 2px;
  --radius-input: 6px;
  --radius-button: 10px;
  --radius-card: 14px;
  --radius-panel: 20px;
  --radius-ribbon: 999px;   /* ribbon + playhead ONLY */

  --border-width: 1px;

  /* ---- Motion -------------------------------------------- */
  --dur-instant: 90ms;
  --dur-fast: 160ms;    /* default for all hover/press */
  --dur-slow: 320ms;    /* panel open, tier switch */
  --dur-ribbon: 1400ms; /* the one orchestrated moment */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-inout: cubic-bezier(0.4, 0, 0.2, 1);

  /* ---- Elevation (matte, warm-tinted, never glossy) ------ */
  --shadow-card: 0 1px 2px rgba(36, 29, 22, 0.04);
  --shadow-raised: 0 8px 24px rgba(36, 29, 22, 0.08), 0 2px 6px rgba(36, 29, 22, 0.04);
  --shadow-panel: 0 24px 48px rgba(36, 29, 22, 0.12);

  /* ---- Focus (never remove, never rely on colour alone) -- */
  --focus-width: 2px;
  --focus-offset: 2px;
}

/* ============================================================
   LIGHT MODE — "room at noon"
   Default. Warm chalk, not editorial cream.
   ============================================================ */
:root,
[data-theme="light"] {
  --canvas:        #FBF8F3;
  --surface:       #FFFFFF;
  --surface-sunken:#F4EFE7;  /* inputs, code blocks, track */
  --surface-raised:#FFFFFF;  /* menus, popovers */

  --line:          #E5DDD1;  /* 1.3:1 — decorative dividers only */
  --line-strong:   #D3C7B6;  /* 1.6:1 — emphasis dividers, still decorative */
  --line-control:  #8F877C;  /* 3.4:1 — see note above */

  --tx:            #241D16;  /* 15.7:1 on canvas */
  --tx-muted:      #6B5F51;  /* 5.9:1 */
  --tx-faint:      #9A8E7E;  /* 3.0:1 — decorative + large only */
  --tx-inverse:    #FBF8F3;

  --signal:        #B87517;  /* 3.5:1 — UI + large text only, never small text */
  --signal-text:   #8F5A0F;  /* 5.5:1 — small text on canvas */
  --signal-bg:     #FBF0DC;
  --signal-line:   #EBD6AE;
  --signal-solid:  #E8A33D;  /* filled button bg */
  /* Hover fill for the filled button. It cannot be --signal: that is a
     text/UI colour, and --signal-on sits only 3.9:1 on it, under AA. This
     darkens the resting fill instead and keeps the label at 5.3:1. */
  --signal-solid-hover: #D18E2E;
  --signal-on:     #3D2404;  /* text on --signal-solid, 6.7:1 */

  --seal:          #2F6E5F;  /* 5.6:1 */
  --seal-bg:       #E4F0EC;
  --seal-line:     #BEDCD3;

  /* Modal backdrop. Warm near-black at 50%: the dimmed page drops 3.2:1
     below the canvas and a white panel sits 3.4:1 above the scrim, so the
     modal edge is a real boundary without needing a border. Never #000. */
  --scrim:         rgba(36, 29, 22, 0.50);

  --danger:        #B23A2A;
  --danger-bg:     #FBEAE7;
  --danger-line:   #EFCBC3;

  --warn:          #8A5A08;
  --warn-bg:       #FAF0DA;

  --focus-ring:    #B87517;

  --shadow-card:   0 1px 2px rgba(36, 29, 22, 0.05);
  --shadow-raised: 0 8px 24px rgba(36, 29, 22, 0.09), 0 2px 6px rgba(36, 29, 22, 0.05);
}

/* ============================================================
   DARK MODE — "room at dusk"
   Equal citizen, not an afterthought.
   Warm graphite with brown undertone. Never #000.
   ============================================================ */
[data-theme="dark"] {
  --canvas:        #17130F;
  --surface:       #201A15;
  --surface-sunken:#131009;
  --surface-raised:#2A231C;

  --line:          #392F26;  /* 1.4:1 — decorative dividers only */
  --line-strong:   #4E4134;  /* 1.9:1 — emphasis dividers, still decorative */
  --line-control:  #786F65;  /* 3.8:1 — see note at the top of this file */

  --tx:            #F5EDE3;  /* 15.9:1 on canvas */
  --tx-muted:      #B5A695;  /* 7.8:1 */
  --tx-faint:      #7E7364;  /* 4.0:1 — decorative + large only */
  --tx-inverse:    #17130F;

  --signal:        #E8A33D;  /* 8.6:1 */
  --signal-text:   #E8A33D;
  --signal-bg:     #2B2013;
  --signal-line:   #4A3418;
  --signal-solid:  #E8A33D;
  /* Dark mode goes lighter on hover, not darker: --signal and --signal-solid
     are the same value here, so reusing --signal would give the filled button
     no hover feedback at all. Label stays at 7.8:1. */
  --signal-solid-hover: #F0B45C;
  --signal-on:     #3D2404;

  --seal:          #5FA898;  /* 6.6:1 */
  --seal-bg:       #16261F;
  --seal-line:     #26443A;

  /* Dark canvas is already near the luminance floor, so a scrim cannot dim
     it much (1.1:1). The modal reads as separate because it is *lighter*
     (--surface-raised) and carries a --line-control edge, not because the
     backdrop went darker. 66% is enough to kill the page underneath. */
  --scrim:         rgba(9, 7, 5, 0.66);

  --danger:        #E8806C;
  --danger-bg:     #2B1611;
  --danger-line:   #4A2419;

  --warn:          #DDA94E;
  --warn-bg:       #2A1F0F;

  --focus-ring:    #E8A33D;

  --shadow-card:   0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-raised: 0 8px 24px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.25);
  --shadow-panel:  0 24px 48px rgba(0, 0, 0, 0.5);
}

/* Follow the OS when the user has not chosen explicitly */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --canvas: #17130F; --surface: #201A15; --surface-sunken: #131009;
    --surface-raised: #2A231C; --line: #392F26; --line-strong: #4E4134;
    --line-control: #786F65; --scrim: rgba(9, 7, 5, 0.66);
    --tx: #F5EDE3; --tx-muted: #B5A695; --tx-faint: #7E7364; --tx-inverse: #17130F;
    --signal: #E8A33D; --signal-text: #E8A33D; --signal-bg: #2B2013;
    --signal-line: #4A3418; --signal-solid: #E8A33D; --signal-on: #3D2404;
    --signal-solid-hover: #F0B45C;
    --seal: #5FA898; --seal-bg: #16261F; --seal-line: #26443A;
    --danger: #E8806C; --danger-bg: #2B1611; --danger-line: #4A2419;
    --warn: #DDA94E; --warn-bg: #2A1F0F; --focus-ring: #E8A33D;
    --shadow-card: 0 1px 2px rgba(0,0,0,0.3);
    --shadow-raised: 0 8px 24px rgba(0,0,0,0.4), 0 2px 6px rgba(0,0,0,0.25);
    --shadow-panel: 0 24px 48px rgba(0,0,0,0.5);
  }
}

/* ============================================================
   BASE + REQUIRED BEHAVIOURS
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

html { color-scheme: light dark; }

body {
  margin: 0;
  background: var(--canvas);
  color: var(--tx);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, .display {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  margin: 0;
}
h1 { font-size: var(--text-2xl); }
h2 { font-size: var(--text-xl); }
h3 { font-size: var(--text-md); font-weight: var(--weight-medium); margin: 0; }

/* Every number that must align vertically */
.num, time, .credits, .timecode, .charcount {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: -0.01em;
}

/* Uppercase mono label — the only place uppercase is allowed */
.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--tx-muted);
}

/* Thai text: taller leading, and never break mid-syllable */
:lang(th), .th {
  line-height: var(--leading-thai);
  word-break: normal;
  overflow-wrap: normal;
  line-break: normal;
  hyphens: none;
}
/* Thai has no inter-word spaces — justify creates rivers. Never justify. */
:lang(th) p, .th p { text-align: start; }

/* Focus is always visible and never colour-only */
:focus-visible {
  outline: var(--focus-width) solid var(--focus-ring);
  outline-offset: var(--focus-offset);
  border-radius: var(--radius-input);
}
:focus:not(:focus-visible) { outline: none; }

/* Respect reduced motion — the ribbon draw must be skippable */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Colour-blind safe mode: amber vs teal is a blue–yellow pair, which
   survives protan/deutan. This mode covers tritanopia and anyone who
   needs shape, not hue. It adds a secondary cue to every state. */
[data-cb="on"] .state-sealed::before   { content: "✓ "; }
[data-cb="on"] .state-pending::before  { content: "· "; }
[data-cb="on"] .state-failed::before   { content: "× "; }
[data-cb="on"] .tier.is-selected { outline: var(--border-width) dashed var(--signal); }
[data-cb="on"] .ribbon-seam { border-left: 1px dashed var(--seal); }

/* Screen-reader-only utility — required on every icon-only control */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Minimum touch target on every interactive element */
button, a[role="button"], .control {
  min-height: 44px;
  min-width: 44px;
}
@media (pointer: fine) {
  button, a[role="button"], .control { min-height: 36px; min-width: 36px; }
}
