/**
 * Design tokens — colour, type scale, spacing, elevation.
 *
 * Everything downstream (layout.css, chat.css, cards.css) reads these custom properties and
 * never hardcodes a colour or a px font-size. Three consequences that matter for the demo:
 *
 *  1. **Dark mode is a token swap, not a second stylesheet.** `:root[data-theme="dark"|"light"]`
 *     is the attribute the header toggle stamps on <html>, and it wins in *both* directions. The
 *     `prefers-color-scheme: dark` media query is a fallback only — js/theme.js and the
 *     before-paint script in index.html now stamp `light` explicitly when the viewer has no
 *     stored preference (see "Light is the default" below).
 *  2. **Tenant theming is a token swap too.** `--brand` / `--accent` are set inline on <html>
 *     from /api/bootstrap's `tenant_theme`. Nothing else needs to know. This is why *no* surface
 *     colour is derived from `--brand`: a tenant sending a magenta brand must not be able to turn
 *     the header, the paper or the composer magenta.
 *  3. **Stage mode is a scale swap.** `:root[data-stage="1"]` multiplies one variable,
 *     `--type-scale`, and every size in the app grows with it — because every size is
 *     `calc(<base> * var(--type-scale))`, never a literal.
 *
 * ## Light is the default, and the light palette is the designed one
 * The previous build read as "a dark green app": the header was a `--brand-dark → --brand`
 * gradient (a heavy #16493d slab) in *both* themes, and dark mode followed the presenter's OS, so
 * a laptop set to dark showed a near-black green UI. Two changes:
 *
 *   - **Light is the default theme.** Dark is one click away and still fully supported, but the
 *     room this is presented in is bright, and projected dark UI washes out to mud.
 *   - **The header is a light surface with dark ink**, not a saturated slab. Green survives where
 *     green earns its place — the brand mark, the send button, links, list markers, the routing
 *     trail — instead of covering 15% of the screen.
 *
 * ## Palette rationale — "Kanchenjunga at first light"
 * Warm ivory paper (#f7f2e8) and sand (#e9e2d4) rather than the neutral greys every SaaS chat
 * uses; pine green (#1f6f5c) as the brand; marigold (#d9a441) as the accent. The warm/cool pair
 * is the actual colour of the region at dawn and it photographs well under projector light.
 *
 * ## Contrast
 * Every ink/surface pair below was measured, not eyeballed. Body and micro text clear WCAG AA
 * (4.5:1) on every surface it is actually rendered on:
 *
 *   --ink        / --paper 13.4   / --surface 15.0  / --bubble-out 12.6
 *   --ink-soft   / --paper  6.4   / --surface  7.2  / --surface-2   6.1
 *   --ink-faint  / --paper  4.9   / --surface  5.4  / --surface-2   4.6
 *   --brand-ink  / --paper  7.5   / --surface  8.3  / --surface-2   7.1
 *   --header-ink / header   11.6  · --header-ink-soft / header 5.0
 *   ok/warn/danger/info ink on their own bg: 7.0-8.4
 *
 * Type scale rationale: sizes are `clamp()`ed so they grow with the viewport, then multiplied by
 * --type-scale so `?stage=1` / Ctrl+Shift+P can jump the whole app ~1.45x for row three.
 */

:root {
  color-scheme: light;

  /* ---------------------------------------------------------------------------------------
   * Brand. --brand/--accent are the two the server actually sends per tenant
   * (bootstrap.py's BootstrapTenantTheme); the -dark/-light ramps are derived shades this UI
   * needs and are recomputed in js/theme.js when a tenant overrides the base pair.
   * ------------------------------------------------------------------------------------- */
  /* Saffron ramp — ported from SahayakAI's own globals.css (the "Vidya"/OmniOrb house style),
     HSL authoritative, hex computed. The orb is the hero and the hero is saffron. This replaces
     pine as the brand hue; pine survives only where it earns its place — status-green and the
     receipts trail (see --pine below). Contrast measured in the block at the foot of :root. */
  --saffron-50: #fff4eb;
  --saffron-100: #fee9d7;
  --saffron-200: #fdd4af;
  --saffron-300: #f7b67e;
  --saffron-500: #e0924d;  /* fill — NOT a text colour (2.1:1 on white; fails AA) */
  --saffron-600: #df6c20;
  --saffron-700: #ac4815;  /* ink — 5.1:1 on --paper, 5.7:1 on white (AA ✓) */
  --saffron-800: #8b330e;  /* strong ink — 7.3:1 on --paper */

  /* Brand = saffron. --brand/--accent are still the two the server sends per tenant
     (bootstrap.py's BootstrapTenantTheme); the -dark/-light ramps are derived shades and are
     recomputed in js/theme.js when a tenant overrides the base pair. --brand is a FILL; the
     readable text colour is --brand-ink (same fill/ink split the file has always used). */
  /* ---------------------------------------------------------------------------------------
   * WHO OWNS COLOUR, PER PAGE. This file's colour tokens are authoritative on manager.html,
   * which loads fonts/tokens/chat/cards/manager and never loads css/glass.css. On index.html
   * (the guest concierge) glass.css loads AFTER this file and redefines every colour below from
   * its own indigo/violet/champagne palette — see its header comment. The non-colour tokens
   * here (spacing, type scale, radius, motion) are authoritative on both.
   *
   * The champagne/teal/ember literals that used to be declared here (the --gold, --teal and
   * --ember families) are gone: they were shadowed by glass.css on the guest app and read by
   * nothing on the manager, so they painted nothing anywhere. Their VALUES survive inlined at
   * the four sites that actually consumed them, so manager.html's computed palette is unchanged.
   *
   * The --saffron-* ramp above is NOT dead and must not be tidied away with them: the
   * `@media (prefers-color-scheme: dark) :root:not([data-theme])` block near the foot of this
   * file — the documented JS-disabled fallback — is its one remaining consumer, and by
   * specificity (`:root:not([data-theme])` beats bare `:root`) it wins over glass.css's dark
   * palette in exactly that one no-JS, OS-dark case. It is the only brand-colour source on that
   * degrade path.
   * ------------------------------------------------------------------------------------- */
  --brand: #c08a3e;
  --brand-dark: #9a6a28;
  --brand-light: #dcae63;
  --brand-ink: #9a6a28;
  --brand-wash: color-mix(in srgb, #c08a3e 10%, transparent);
  --brand-wash-strong: color-mix(in srgb, #c08a3e 18%, transparent);
  --accent: #1c6f68;
  --accent-ink: #ffffff;

  /* Pine — demoted from brand to exactly where the original palette note said green earns its
     place: the status system (--ok = open/eligible) and the receipts rail's routing trail.
     Kept as a named token so those surfaces reference intent, not a raw hex. */
  --pine: #1f6f5c;
  --pine-ink: #14584a;

  /* The hero orb (see css/orb.css). One warm light source, a single calm pulse. */
  --orb-size: clamp(84px, 15vmin, 100px);
  /* --orb-fill / --orb-ring / --orb-glow / --orb-label-bg / --orb-label-ink used to live here too.
     Confirmed by grep: nothing in static/css reads any of the five by name — css/orb.css paints
     the sphere from --orb-cue/--orb-cue-soft instead (glass.css's own note by THE SIGNATURE
     records making the same call for its own copy of these). Removed rather than kept as unused
     legacy, matching that precedent. */
  --orb-pulse-dur: 2.4s;  /* the ONE calm breath — matches OmniOrb's single-ring restraint */
  --ease-out-quart: cubic-bezier(0.16, 1, 0.3, 1);

  /* Semantic surfaces — light theme. Warm, not grey: ivory paper on warm sand. */
  --bg: #e7dfd0;
  --paper: #f1ede3;
  --paper-2: #f8f4ec;
  --paper-warm: #efe8d9;
  --surface: #fcf9f3;
  --surface-2: #f3ece0;
  /* Frosted-glass fills — the redesign's signature. Translucent white over the warm ground, with
     a backdrop blur applied where they're used (hero chrome, chips, cards, mic). */
  --glass: rgba(255, 255, 255, 0.58);
  --glass-2: rgba(255, 255, 255, 0.72);
  --lift: 0 22px 48px -22px rgba(18, 41, 45, 0.30);
  --bubble-out: #eef4ee;
  --bubble-in: #ffffff;
  --ink: #12292d;
  --ink-soft: #47605f;
  --ink-faint: #6a7f7c;
  --hairline: rgba(18, 41, 45, 0.10);
  --hairline-strong: rgba(18, 41, 45, 0.20);

  /* Header. A light surface with dark ink — see this file's header note. The chrome buttons that
     sit on it read these too, so light/dark needs no per-theme button rule. */
  /* The header is now transparent over the hero photo, so "header ink" is the dark teal that sits
     legibly on the bright sky, and the chrome pills (lang / theme / tts) are frosted white. */
  --header-bg: transparent;
  --header-ink: #12292d;
  --header-ink-soft: rgba(18, 41, 45, 0.66);
  --header-line: rgba(18, 41, 45, 0.14);
  --header-rule: linear-gradient(90deg, #c08a3e, #1c6f68 60%, #dcae63);
  --ghost-bg: var(--glass-2);
  --ghost-bg-hover: rgba(255, 255, 255, 0.88);
  --ghost-line: rgba(255, 255, 255, 0.7);

  /* Scrollbars are a designed element here, not an OS accident — see layout.css. */
  --scroll-thumb: rgba(24, 42, 36, 0.28);
  --scroll-thumb-hover: rgba(24, 42, 36, 0.45);
  --scroll-track: rgba(24, 42, 36, 0.06);

  /* Status palette. Used by the grounding cards *and* the road traffic-light chips, so they stay
     one system: green=open/eligible, amber=caution/unknown, red=closed/blocked. */
  --ok-bg: #e4f2e9;
  --ok-ink: #0f5b3b;
  --ok-line: #66b993;
  --warn-bg: #fbf1da;
  --warn-ink: #6f4a0c;
  --warn-line: #d9ac52;
  --danger-bg: #fbe9e6;
  --danger-ink: #8a2f27;
  --danger-line: #dc9188;
  --info-bg: #e7eff8;
  --info-ink: #1b476c;
  --info-line: #8db1d4;
  /* Solid fills — the -bg/-ink/-line trio covers washes and text, but a filled control (the
     safety card's tap-to-call pill) needs one opaque hue that carries white text at 4.5:1. */
  --ok: var(--pine);
  --warn: #b8791a;
  --danger: #a4342a;
  --info: #1b5a8a;

  /* ---------------------------------------------------------------------------------------
   * Type. --type-scale is the single knob stage mode turns.
   * ------------------------------------------------------------------------------------- */
  --type-scale: 1;
  --font-sans: "Segoe UI", "Noto Sans", system-ui, -apple-system, "Helvetica Neue", sans-serif;
  /* Indic families come FIRST for the scripts they cover: the @font-face unicode-range in
     fonts.css means a Latin-only page never fetches them, but a Bengali page must reach the
     self-hosted face before the OS's Nirmala UI/Vrinda fallback gets a chance. */
  --font-indic: "Noto Sans Bengali", "Noto Sans Devanagari", var(--font-sans);
  --font-mono: "Cascadia Mono", "SF Mono", "Consolas", ui-monospace, monospace;
  /* Display serif for the greeting and card headlines — self-hosted (fonts.css), Georgia fallback
     so an offline first paint is still elegant, never Times. */
  --font-serif: "Cormorant Garamond", "Noto Serif", Georgia, "Times New Roman", serif;

  --fs-micro: calc(clamp(11px, 0.72vw, 13px) * var(--type-scale));
  --fs-small: calc(clamp(13px, 0.85vw, 15px) * var(--type-scale));
  --fs-body: calc(clamp(15px, 1vw, 17.5px) * var(--type-scale));
  --fs-lead: calc(clamp(16.5px, 1.15vw, 20px) * var(--type-scale));
  --fs-h3: calc(clamp(15px, 1vw, 18px) * var(--type-scale));
  --fs-h2: calc(clamp(18px, 1.3vw, 23px) * var(--type-scale));
  --fs-h1: calc(clamp(20px, 1.5vw, 28px) * var(--type-scale));

  --lh-tight: 1.25;
  --lh-body: 1.5;

  /* ---------------------------------------------------------------------------------------
   * Space & shape. One 4px-based ramp so nothing is an ad-hoc magic number.
   * ------------------------------------------------------------------------------------- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  --sp-7: 48px;

  --radius-sm: 8px;
  --radius: 16px;
  --radius-lg: 22px;
  --radius-pill: 999px;
  /* The header band's corner — referenced from css/glass.css, defined here so the full ladder
     (28 band -> 26 cap-panel -> 22 bubble -> 18 pill/card -> 16 -> 8) is inspectable from one
     file instead of only existing as an inline fallback three call sites deep. */
  --radius-xl: 28px;

  /* THE composer control height. Mic, textarea and send all derive their box from this one
     token, which is what makes them line up by construction instead of by nudging margins.
     `--control-pad` is the vertical padding that centres a single line of --fs-body text inside
     it, accounting for the textarea's 1px borders. */
  --control-h: calc(46px * var(--type-scale));
  --control-pad: calc((var(--control-h) - (var(--fs-body) * var(--lh-body)) - 2px) / 2);

  --shadow-1: 0 1px 2px rgba(28, 40, 30, 0.07);
  --shadow-2: 0 2px 10px rgba(28, 40, 30, 0.09);
  --shadow-3: 0 8px 34px rgba(28, 40, 30, 0.16);

  /* Focus ring — defined once, here. `outline: none` with no :focus-visible replacement was one
     of the verified accessibility gaps. */
  --focus-ring: 0 0 0 3px rgba(192, 138, 62, 0.5);

  --dur-fast: 120ms;
  --dur: 200ms;
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);
}

/* -------------------------------------------------------------------------------------------
 * Dark theme. Two selectors, deliberately:
 *   - the attribute is the explicit choice and always wins (js/theme.js writes it, and the
 *     before-paint script in index.html writes `light` when nothing is stored — so in practice
 *     the attribute is always present and the media query below is a belt-and-braces fallback
 *     for a page served with JS disabled).
 *   - the media query covers that JS-disabled case only, and is scoped `:not([data-theme])` so
 *     it can never fight an explicit choice in either direction.
 *
 * Dark is no longer green-black. It is a warm charcoal with a pine undertone, so switching
 * themes reads as the same product at a different time of day rather than two different apps.
 * ----------------------------------------------------------------------------------------- */

:root[data-theme="dark"] {
  color-scheme: dark;

  /* Base --brand is inherited from :root; only the derived shades change here. The two literals
     are the champagne deep/lit pair, inlined when the dead --gold family was removed from :root.
     KEEP IN SYNC with the `@media (prefers-color-scheme: dark)` fallback block near the foot of
     this file — it is a near-copy of this one, and only these three lines differ between them
     (it derives them from the --saffron-* ramp instead, since no JS ran to resolve a tenant). */
  --brand-dark: #9a6a28;
  --brand-light: #dcae63;
  --brand-ink: #e6c07a;

  --bg: #101715;
  --paper: #161d1a;
  --surface: #1e2723;
  --surface-2: #1a221f;
  --bubble-out: #24382f;
  --bubble-in: #212b27;
  --ink: #eaf1ee;
  --ink-soft: #a9bab4;
  --ink-faint: #8b9c96;
  --hairline: rgba(255, 255, 255, 0.1);
  --hairline-strong: rgba(255, 255, 255, 0.2);

  --header-bg: linear-gradient(180deg, #1c2723 0%, #141c19 100%);
  --header-ink: #f1f6f3;
  --header-ink-soft: #aebfb9;
  --header-line: rgba(255, 255, 255, 0.12);
  --ghost-bg: rgba(255, 255, 255, 0.08);
  --ghost-bg-hover: rgba(255, 255, 255, 0.16);
  --ghost-line: rgba(255, 255, 255, 0.24);

  --scroll-thumb: rgba(233, 241, 238, 0.26);
  --scroll-thumb-hover: rgba(233, 241, 238, 0.42);
  --scroll-track: rgba(233, 241, 238, 0.06);

  --accent-ink: #ffffff;

  --ok-bg: #10281e;
  --ok-ink: #7fdcae;
  --ok-line: #2e7a56;
  --warn-bg: #2e2411;
  --warn-ink: #f0cd7f;
  --warn-line: #8a6a22;
  --danger-bg: #331b18;
  --danger-ink: #f4a9a1;
  --danger-line: #8c4340;
  --info-bg: #33212e;
  --info-ink: #fdb799;
  --info-line: #a44656;
  --ok: #2a7d5a;
  --warn: #9c7419;
  --danger: #a94a40;
  --info: #8c445e;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-2: 0 2px 12px rgba(0, 0, 0, 0.55);
  --shadow-3: 0 10px 38px rgba(0, 0, 0, 0.6);

  --focus-ring: 0 0 0 3px rgba(247, 182, 126, 0.55);
}

/* JS-disabled fallback only — see the note above. Kept as a duplicated block rather than a
   shared rule because CSS has no way to say "this media query OR this attribute" in one
   selector without a build step, and this file has no build step by design.

   KEEP IN SYNC with `:root[data-theme="dark"]` above: every declaration below is identical to
   its counterpart there EXCEPT the three brand lines immediately following, which are the only
   intentional divergence. They read the --saffron-* ramp because this is the path where no JS
   ran to resolve a tenant's own brand pair, which makes that ramp's one live consumer this
   block — do not delete it as unused. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    color-scheme: dark;

    /* The three lines that differ from :root[data-theme="dark"]. */
    --brand-dark: var(--saffron-700);
    --brand-light: var(--saffron-300);
    --brand-ink: var(--saffron-300);

    --bg: #101715;
    --paper: #161d1a;
    --surface: #1e2723;
    --surface-2: #1a221f;
    --bubble-out: #24382f;
    --bubble-in: #212b27;
    --ink: #eaf1ee;
    --ink-soft: #a9bab4;
    --ink-faint: #8b9c96;
    --hairline: rgba(255, 255, 255, 0.1);
    --hairline-strong: rgba(255, 255, 255, 0.2);

    --header-bg: linear-gradient(180deg, #1c2723 0%, #141c19 100%);
    --header-ink: #f1f6f3;
    --header-ink-soft: #aebfb9;
    --header-line: rgba(255, 255, 255, 0.12);
    --ghost-bg: rgba(255, 255, 255, 0.08);
    --ghost-bg-hover: rgba(255, 255, 255, 0.16);
    --ghost-line: rgba(255, 255, 255, 0.24);

    --scroll-thumb: rgba(233, 241, 238, 0.26);
    --scroll-thumb-hover: rgba(233, 241, 238, 0.42);
    --scroll-track: rgba(233, 241, 238, 0.06);

    --accent-ink: #ffffff;

    --ok-bg: #10281e;
    --ok-ink: #7fdcae;
    --ok-line: #2e7a56;
    --warn-bg: #2e2411;
    --warn-ink: #f0cd7f;
    --warn-line: #8a6a22;
    --danger-bg: #331b18;
    --danger-ink: #f4a9a1;
    --danger-line: #8c4340;
    --info-bg: #33212e;
    --info-ink: #fdb799;
    --info-line: #a44656;
    --ok: #2a7d5a;
    --warn: #9c7419;
    --danger: #a94a40;
    --info: #8c445e;

    --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.5);
    --shadow-2: 0 2px 12px rgba(0, 0, 0, 0.55);
    --shadow-3: 0 10px 38px rgba(0, 0, 0, 0.6);

    --focus-ring: 0 0 0 3px rgba(247, 182, 126, 0.55);
  }
}

/* Stage/presentation mode — one variable, whole-app effect. Triggered by `?stage=1` or
   Ctrl+Shift+P (js/theme.js). 1.45x lands ~25px body text on a 1920px projector, which is the
   readable-from-row-three target. It no longer forces dark: the demo room is bright, and a light
   projected surface holds up in a bright room where a dark one turns to mud. */
:root[data-stage="1"] {
  --type-scale: 1.45;
}
