/* ===========================================================================
   Elasticity — design tokens (2026-09-24 rebrand).

   Single source of truth for every colour, typeface and spacing value used
   across the Flask consoles (customer_portal.py, console.py, public_demo.py,
   test_ui.py). Load this before fonts.css, base.css and components.css.

   Two themes, one system. Every page supports both:
     · follows the visitor's OS setting (prefers-color-scheme), and
     · honours an explicit override, <html data-theme="light|dark">, set by
       the toggle in components (see theme.js) and remembered per browser.

   Accent, one per theme, spent on interaction only (active nav, primary
   button, focus, links, the "best value" highlight) — never decoration:
     dark  → Electric Mint  #2BFF9C  (14.5:1 on --bg; carries dark text 14.3:1)
     light → Ocean Blue     #0B5E8E  (2026-10-16, replaces Violet #7624F4;
             sampled from the sea in the landing day-scene art).
             7.0:1 on white, so the one hex serves as fill, text, link,
             focus ring and chart mark. Text ON an ocean fill is white
             (7.0:1).
   Consume the role tokens (--accent-text, --focus, --link, --accent-ink),
   never the raw hexes, anywhere the theme could change.

   Neutrals are cool, near-neutral greys — the electric accent reads
   cleanest against them (the old warm/cream surfaces muddied it).

   RULES (enforced by review, see webui/README.md):
     · no colour literal outside this file — add a token here first, with
       a reason, then use it
     · no Tailwind default palette hexes (#2563eb #dcfce7 #fee2e2 #f1f5f9 …)
     · hairlines come from --line; tables get row hairlines, never cell borders
     · no bare `system-ui` as a whole font stack
     · spacing stays on the 4px scale (--s1…--s7)
   =========================================================================== */

/* ---- light theme (default when the OS gives no preference) --------------- */
:root,
:root[data-theme="light"] {
  color-scheme: light;

  --bg:          #FAFBFC;
  --surface:     #FFFFFF;
  --surface-2:   #F1F3F6;   /* wells, inputs, hovered rows */
  --line:        #E3E6EA;
  --line-strong: #CDD2D9;

  --fg:          #14171C;   /* 17.3:1 on --bg */
  --fg-muted:    #4A5260;   /*  7.6:1 */
  --fg-faint:    #666E7B;   /* ≥4.5:1 on --bg and --surface; labels, hints */

  --accent:      #0B5E8E;   /* Ocean Blue — fill AND text */
  --accent-ink:  #FFFFFF;   /* text on an --accent fill: 7.0:1 */
  --accent-text: #0B5E8E;   /* text/links/focus: 7.0:1 on white, 6.3:1 on --surface-2 */
  --accent-hover:#084C73;   /* 9.2:1 on white */
  --accent-wash: rgba(11, 94, 142, .12);

  /* primary button: the same ocean fill with white text (7.0:1 / 9.2:1 hover). */
  --action:       #0B5E8E;
  --action-hover: #084C73;
  --action-ink:   #FFFFFF;

  /* status — each ≥4.7:1 as text on --surface-2 */
  --pass: #2F7A4F;  --pass-wash: rgba(47, 122, 79, .12);
  --flag: #B8471F;  --flag-wash: rgba(184, 71, 31, .12);
  --hold: #8A6400;  --hold-wash: rgba(138, 100, 0, .12);

  /* the redaction bar itself: a solid block that reads as "struck out"
     against the page — dark on light, light-grey on dark. */
  --redact:      #14171C;
  --redact-text: #FAFBFC;

  /* chart marks. Two only: --chart-mark carries "Elasticity subsidizes
     this", --chart-ref is the deliberate de-emphasis grey for a reference
     point. Not --accent/--fg-faint: those two fail the pair checks against
     each other. This pair is validated (2026-10-16, CIEDE2000 under Machado CVD simulation) for separation
     (ΔE 22.2 normal, 19.6 protan, 22.9 deutan, 20.4 tritan) AND 3:1 on its
     own surface. The ocean blue is deep enough that the brand hex itself
     carries the mark — no darker chart variant. */
  --chart-mark:  #0B5E8E;
  --chart-ref:   #7E8693;

  --shadow-pop: 0 8px 24px rgba(20, 23, 28, .10), 0 1px 2px rgba(20, 23, 28, .06);
  /* the one raised hero surface per page (landing trace card) — nothing else */
  --shadow-hero: 0 24px 60px rgba(20, 23, 28, .10), 0 1px 2px rgba(20, 23, 28, .06);
}

/* ---- dark theme ----------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --bg:          #0D0F12;
    --surface:     #14171B;
    --surface-2:   #1B1F24;
    --line:        #262A31;
    --line-strong: #353A42;

    --fg:          #EDEFF2;   /* 16.7:1 on --bg */
    --fg-muted:    #A3AAB5;   /*  8.2:1 */
    --fg-faint:    #858C99;   /* ≥4.5:1 on --bg and --surface */

    --accent:      #2BFF9C;   /* Electric Mint */
    --accent-ink:  #06140D;   /* 14.3:1 on mint */
    --accent-text: #2BFF9C;
    --accent-hover:#5CFFB4;
    --accent-wash: rgba(43, 255, 156, .12);
    --action:       #2BFF9C;
    --action-hover: #5CFFB4;
    --action-ink:   #06140D;

    --pass: #6BCB8B;  --pass-wash: rgba(107, 203, 139, .14);
    --flag: #FF7A5C;  --flag-wash: rgba(255, 122, 92, .14);
    --hold: #F2C14E;  --hold-wash: rgba(242, 193, 78, .14);

    --redact:      #C9CED6;
    --redact-text: #0D0F12;

    --chart-mark:  #2BFF9C;
    --chart-ref:   #7C8390;

    --shadow-pop: 0 8px 24px rgba(0, 0, 0, .45), 0 1px 2px rgba(0, 0, 0, .3);
    --shadow-hero: 0 24px 60px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .04);
  }
}
/* Same block again for the explicit override — a media query can't be
   combined with an attribute selector into one rule. Keep the two in sync. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --bg:          #0D0F12;
  --surface:     #14171B;
  --surface-2:   #1B1F24;
  --line:        #262A31;
  --line-strong: #353A42;

  --fg:          #EDEFF2;
  --fg-muted:    #A3AAB5;
  --fg-faint:    #858C99;

  --accent:      #2BFF9C;
  --accent-ink:  #06140D;
  --accent-text: #2BFF9C;
  --accent-hover:#5CFFB4;
  --accent-wash: rgba(43, 255, 156, .12);
  --action:       #2BFF9C;
  --action-hover: #5CFFB4;
  --action-ink:   #06140D;

  --pass: #6BCB8B;  --pass-wash: rgba(107, 203, 139, .14);
  --flag: #FF7A5C;  --flag-wash: rgba(255, 122, 92, .14);
  --hold: #F2C14E;  --hold-wash: rgba(242, 193, 78, .14);

  --redact:      #C9CED6;
  --redact-text: #0D0F12;

  --chart-mark:  #2BFF9C;
  --chart-ref:   #7C8390;

  --shadow-pop: 0 8px 24px rgba(0, 0, 0, .45), 0 1px 2px rgba(0, 0, 0, .3);
  --shadow-hero: 0 24px 60px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .04);
}

/* ---- theme-independent ---------------------------------------------------- */
:root {
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;
  /* headings: Geist 600/700, tight tracking. Body/UI stays Inter. */
  --display: "Geist", var(--sans);
  --mono-l: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;

  /* 4px scale. Every margin, padding and gap is one of these or a sum. */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px; --s7: 48px;

  /* radius ladder: chip/table 6 · input/button 10 · card 16 · feature panel 24 */
  --r: 6px;
  --r-lg: 10px;
  --r-xl: 16px;
  --r-2xl: 24px;
  --r-pill: 999px;

  /* motion. Animate transform and opacity only; base.css zeroes all of it
     under prefers-reduced-motion. --dur-1 hover/press, --dur-2 state change,
     --dur-3 entrance (reveal on scroll, hero swap). */
  --ease-out: cubic-bezier(.2, .8, .2, 1);
  --dur-1: 150ms;
  --dur-2: 300ms;
  --dur-3: 700ms;

  /* icons: Lucide sprite at static/img/icons.svg, 24px grid, 2px stroke */
  --icon: 20px;
  --icon-tile: 44px;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .12);

  /* ---- landing stage (2026-10-12 landing redesign) ----------------------
     The approved landing look is a true-black stage, not the #0D0F12 app
     dark theme. landing.css retargets the role tokens to these on the
     landing page only, in dark mode (light mode uses the day-scene art on
     the normal light tokens). --ls-* are never read by the portal/console. */
  --ls-bg:          #000;
  --ls-card:        #07090A;
  --ls-wash:        rgba(255, 255, 255, .04);
  --ls-line:        rgba(255, 255, 255, .12);
  --ls-line-row:    rgba(255, 255, 255, .08);
  --ls-line-strong: rgba(255, 255, 255, .28);
  --ls-fg:          #EDF3EF;
  --ls-body:        #C9D3CD;
  --ls-muted:       #9AA7A0;
  --ls-faint:       #7C8882;
  --ls-white:       #FFFFFF;
  --ls-accent:      #2BFF9C;
  --ls-accent-ink:  #000;

  /* ---- landing day stage (light theme, 2026-10-16) ----------------------
     The sun is the light-theme hero CTA, drawn over the day-scene art
     (sun baked out). Its fill only ever carries --sun-ink text (10.6:1);
     never use --sun as text — it's 1.7:1 on white. */
  --sun:            #FDBC01;
  --sun-ink:        #14171C;
  --sun-glow:       rgba(253, 188, 1, .45);
  --sun-glow-far:   rgba(253, 160, 1, .18);

  --focus: var(--accent-text);
  --link:  var(--accent-text);

  /* ---- legacy aliases ------------------------------------------------------
     The pre-rebrand system had two fixed surfaces: "ink" (--stock, --ink-0…)
     for the portal/console and "paper" (--p-stock, --p-ink-0…) for the
     public demo, switched by body.paper-surface. Both families now point at
     the SAME theme-aware roles, so every existing rule (and every page-local
     alias block in the templates and scrub_view_assets.py) follows the
     active theme with no per-surface override. New code should use the
     role names above; these exist so the migration isn't one giant diff. */
  --stock: var(--bg);        --p-stock: var(--bg);
  --raised: var(--surface);  --p-raised: var(--surface);
  --well: var(--surface-2);  --p-well: var(--surface-2);
  --rule: var(--line);       --p-rule: var(--line);
  --rule-lit: var(--line-strong); --p-rule-lit: var(--line-strong);
  --ink-0: var(--fg);        --p-ink-0: var(--fg);
  --ink-1: var(--fg-muted);  --p-ink-1: var(--fg-muted);
  --ink-2: var(--fg-faint);  --p-ink-2: var(--fg-faint);
  --sky: var(--accent);
  --sky-deep: var(--accent-text);
  --sky-wash: var(--accent-wash);
}
