/* ============================================================================
   Design tokens — the LIGHT theme.

   Same token names, same scales, different values. This file is a sibling of
   theme_purple.css, not an override of it: exactly one of the two is loaded
   (see the <link id="theme"> in index.html), so each has to be complete.

   The palette, the three faces and the label treatment come from the Sallyport
   website. The spacing scale, the type sizes and the layout constants do NOT —
   the site is a marketing page with 110px section padding and a 116px hero, and
   importing that would make an application unusable. So a theme here changes
   what a token is worth, never the scale it sits on.

   Two consequences worth knowing:

   - Hanken Grotesk is a static family (400/500/600/700). The purple theme runs
     on a variable system stack and asks for 560/620/660, which would snap
     unpredictably here, so --fw-* are redefined to weights this family has.
     That is the whole reason weights are tokens.
   - The site sets every eyebrow, table header and badge in mono, uppercase and
     widely tracked. The app already routes those through --font-mono, so
     --ls-label and --ls-caps opening up is most of what carries the look across.

   Requires the Google Fonts link in index.html. With it absent the stacks fall
   back to the system faces and everything still works, just without the voice.
   ========================================================================= */

:root {
  color-scheme: light dark;

  --bg: #FAFAF8;
  --surface: #FFFFFF;
  --surface-2: #FAFAF8;
  --surface-3: #F4F3EF;

  --ink: #18181B;
  --ink-soft: #3A3936;
  --muted: #6B6A66;
  --faint: #9C9A94;

  --line: #ECEBE7;
  --line-strong: #E2E0DA;

  /* The chrome (sidebar, topbar) and the quiet rows inside cards. */
  --chrome: #F4F3EF;
  --chrome-line: #E8E6E1;
  --chrome-hover: #ECEAE5;
  --nav-ink: #55544F;
  --topbar-bg: rgba(250, 250, 248, .85);
  --faintest: #C9C7C1;
  --row-line: #F2F1ED;
  --row-hover: #FBFBF9;
  --badge-bg: #FDE8D7;
  --badge-ink: #A4501B;
  --alert: #E5484D;
  /* Hue tiles: oklch(tint-l tint-c H) behind oklch(ink-l ink-c H). Views set only
     the hue (--h), so one rule serves every colour in both themes. */
  --tile-tint-l: .96; --tile-tint-c: .035; --tile-ink-l: .5; --tile-ink-c: .14;

  --accent: #5C4B33;
  --accent-solid: #1E2126;   /* primary buttons are the site's ink, not the accent */
  --accent-bright: #8A7355;
  --on-accent: #FFFFFF;

  --purple: #8E4EC6;
  --purple-solid: #8E4EC6;
  --purple-bright: #A167D2;

  --pop: #F5871F;
  --pop-bright: #F79A42;
  --on-pop: #241400;

  /* Ink that sits on ANY saturated fill — buttons, avatars, logo tiles,
     segmented pills. Constant across themes because the fills stay saturated;
     --on-accent stays separate so a theme can re-pair the accent alone. */
  --on-solid: #FFFFFF;
  /* Hover states mix a fill toward this. A theme that lightens on hover
     instead of darkening re-points it. */
  --shade: #000000;

  /* Tile ground for the workspace-logo squares (.wslogo) and the tour step
     numbers (.tour-num), which put --on-solid (white, constant) on top. Flat
     near-black rather than a gradient, and it stays dark in dark mode so the
     white initials read on either ground. NOT the brand mark — that is the real
     logo now, inlined by core/brand.js, and it carries its own colours. */
  --grad-brand: #111214;

  --flow: #635238;
  --allow: #30A46C;
  --warn: #DFA400;
  --block: #D64545;

  --shadow-sm: 0 1px 2px rgba(30, 33, 38, .05);
  --shadow: 0 1px 0 rgba(30, 33, 38, .03), 0 16px 40px -26px rgba(30, 33, 38, .32);
  --shadow-lg: 0 2px 4px rgba(30, 33, 38, .04), 0 30px 70px -34px rgba(30, 33, 38, .34);
  --shadow-pop: 0 30px 60px -24px rgba(30, 33, 38, .34);
  --shadow-btn: 0 8px 24px -10px rgba(30, 33, 38, .5);     /* filled buttons */
  --shadow-seg: 0 1px 3px rgba(30, 33, 38, .14);      /* segmented-control pill */
  --shadow-knob: 0 1px 3px rgba(0, 0, 0, .22);       /* switch knob */

  /* Full-screen dims: dialog backdrop, and the heavier tour overlay. */
  --scrim: color-mix(in srgb, #1E2126 46%, transparent);
  --scrim-heavy: color-mix(in srgb, #1E2126 50%, transparent);

  --knob: #FFFFFF;                                   /* switch knob face */

  --font-sans: "Hanken Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI",
               system-ui, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "Spline Sans Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* The heading face. Purple uses the same system stack as body copy — this app
     has never had a display face — but headings read it through their own token
     so a theme can give them one without touching a single view rule. */
  --font-display: "Bricolage Grotesque", "Hanken Grotesk", "Helvetica Neue",
                  Arial, sans-serif;

  /* Type scale. The views reached for 42 distinct sizes before this existed,
     but most were several spellings of one step: 10.4–10.8 (24 uses),
     11.0–11.8 (89), 12.0–12.8 (83). The round values 12 and 14 keep their own
     steps — 14 is the body size, and rounding it away is not a tidy-up. */
  --fs-1:  9.6px; --fs-2: 10.5px; --fs-3: 11.5px; --fs-4: 12px;   --fs-5: 12.5px;
  --fs-6: 13px;   --fs-7: 14px;   --fs-8: 15px;   --fs-9: 18px;   --fs-10: 22px;

  /* Weights. The system stack is variable, so the views used seventeen of them;
     550–580 were one weight written four ways, as were 620–660. A theme on a
     static family (400/500/600/700) redefines these and the app follows. */
  --fw-body: 400; --fw-med: 500; --fw-semi: 600; --fw-bold: 700;

  --lh-tight: 1.25; --lh-snug: 1.35; --lh-body: 1.5; --lh-loose: 1.6;

  /* Two families of tracking: negative tightens headings, positive opens the
     uppercase mono labels. */
  --ls-tight: -.02em; --ls-h: -.01em; --ls-label: .14em; --ls-caps: .18em;

  /* Headings. h4 had no styles at all before this — `.section-h` was doing that
     job by hand — so it gets a step here and base.css picks it up. */
  --fs-h1: 22px; --fs-h2: 18px; --fs-h3: 15px; --fs-h4: 13px;
  --fw-h1: 700;  --fw-h2: 700;  --fw-h3: 600;  --fw-h4: 600;
  --lh-h1: 1.25; --lh-h2: 1.3;  --lh-h3: 1.35; --lh-h4: 1.4;
  --ls-h1: -.02em; --ls-h2: -.015em; --ls-h3: -.01em; --ls-h4: -.01em;

  /* Spacing scale. A 2px grid at the small end because that is what the app
     actually uses — before this, every integer from 1 to 16 appeared in the
     views, 14/10/9/15/7/11 among the most common. A 4px scale could not absorb
     those without moving everything, so the steps the UI was already reaching
     for are named here. Above 16 it opens out. */
  --s0:  2px; --s1:  4px; --s2:  6px; --s3:  8px;
  --s4: 10px; --s5: 12px; --s6: 14px; --s7: 16px;
  --s8: 20px; --s9: 24px; --s10: 32px; --s11: 44px; --s12: 64px;

  --r1: 6px; --r2: 9px; --r3: 12px; --r4: 14px; --r5: 22px; --rf: 999px;

  /* The focus ring. It was written five times at 15%, 16% and 18% — drift, not
     intent. One value, one place. */
  --ring-w: 3px;
  --ring: 0 0 0 var(--ring-w) color-mix(in srgb, var(--accent-bright) 16%, transparent);

  /* Stacking order. Thirteen z-indexes were spread across three files, with the
     tooltip/popover relationship documented only in a prose comment. */
  --z-below: -1;        /* decorative fill behind its own box */
  --z-sticky-col: 1;    /* a frozen first column, UNDER the frozen header */
  --z-sticky: 2;        /* a frozen table header */
  --z-raised: 5;
  --z-topbar: 20;  --z-scrim: 25;   --z-nav: 30;
  --z-tooltip: 60;                  /* tooltip UNDER popover, deliberately */
  --z-popover: 70;
  --z-tour-scrim: 150; --z-tour-spot: 151; --z-tour-card: 152;
  --z-dialog: 200;

  /* Micro radii for the small chrome, named by what wears them. Together with
     the scale above, every literal corner in the views comes from here
     (circles stay `50%` — that's shape, not theme). */
  --r-swatch: 3px;    /* colour swatches, the nav rail marker */
  --r-keycap: 4px;    /* kbd chips, large swatches, chart-bar tops */
  --r-chip: 5px;      /* mini pill badges, xs logo tiles */
  --r-tile-sm: 7px;   /* 22–24px icon tiles, checkboxes, the brand mark */
  --r-tile: 8px;      /* 26–32px icon tiles */
  --r-tile-lg: 11px;  /* the 40px workspace logo */

  /* Motion. Every duration collapses to 0 under prefers-reduced-motion,
     which is why views read them from here rather than hardcoding. */
  --dur-xfast: 90ms;
  --dur-fast: 140ms;
  --dur: 230ms;
  --dur-slow: 420ms;
  --dur-xslow: 680ms;

  --ease: cubic-bezier(.4, 0, .2, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);          /* out-expo, the workhorse */
  --ease-in: cubic-bezier(.7, 0, .84, 0);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);   /* overshoots — use sparingly */

  --nav-w: 232px;
  --nav-w-collapsed: 66px;
  --topbar-h: 56px;
  --maxw: 1240px;

  /* Icon tiles: solid fills behind a white icon, derived from the logo (icon-colour
     handoff, 2026-10-30). Rainbow order, greys last; ui.js iconTones() assigns them.
     The same in both themes: the fills stay saturated and the icon stays white. */
  --icon-red: #E0484D; --icon-coral: #E35E3A; --icon-orange: #E8742A; --icon-amber: #E0A200;
  --icon-lime: #7FB236; --icon-green: #32A46C; --icon-teal: #13A595; --icon-cyan: #119FB8;
  --icon-sky: #1E96D6; --icon-blue: #4166DD; --icon-indigo: #5B4FD6; --icon-violet: #8E4EC6;
  --icon-plum: #B045B5; --icon-pink: #D6409F; --icon-rose: #E0457B;
  --icon-stone: #8A857C; --icon-slate: #5C6670; --icon-graphite: #1F2226;
  /* coral, cyan and plum are not in the handoff: in-betweens at the same brightness, so a
     page with more tiles than the handoff's 15 still runs red to black without repeats. */

  /* Field classification hues. These are semantic, not brand. */
  --cls-special: #E5484D;
  --cls-personal: #8E4EC6;
  --cls-financial: #F5871F;
  --cls-public: #6F737B;

  /* Decorative hues for static UI tiles — settings tiles, workflow step
     types. JS feeds these into inline `--tc:` props as var() references
     (views/settings.js, mock/steps.js). Colours stored ON records (roles,
     connectors, workflows) are content, not theme, and stay in the mock db. */
  --hue-sky: #3E63DD;
  --hue-teal: #12A594;
  --hue-green: #30A46C;
  --hue-rose: #D6409F;
  --hue-amber: #DFA400;
  --hue-slate: #6F737B;
}

:root[data-theme="light"] {
  /* Native controls (scrollbars, pickers, autofill) follow the theme, not the OS. */
  color-scheme: light;
  --bg: #FAFAF8;
  --surface: #FFFFFF;
  --surface-2: #FAFAF8;
  --surface-3: #F4F3EF;
  --ink: #18181B;
  --ink-soft: #3A3936;
  --muted: #6B6A66;
  --faint: #9C9A94;
  --line: #ECEBE7;
  --line-strong: #E2E0DA;
  --chrome: #F4F3EF;
  --chrome-line: #E8E6E1;
  --chrome-hover: #ECEAE5;
  --nav-ink: #55544F;
  --topbar-bg: rgba(250, 250, 248, .85);
  --faintest: #C9C7C1;
  --row-line: #F2F1ED;
  --row-hover: #FBFBF9;
  --badge-bg: #FDE8D7;
  --badge-ink: #A4501B;
  --alert: #E5484D;
  --tile-tint-l: .96; --tile-tint-c: .035; --tile-ink-l: .5; --tile-ink-c: .14;
  --accent: #5C4B33;
  --accent-solid: #1E2126;   /* primary buttons are the site's ink, not the accent */
  --accent-bright: #8A7355;
  --purple: #8E4EC6;
  --purple-solid: #8E4EC6;
  --purple-bright: #A167D2;
  --pop: #F5871F;
  --flow: #635238;
  --allow: #30A46C;
  --warn: #DFA400;
  --block: #D64545;
  --shadow-sm: 0 1px 2px rgba(30, 33, 38, .05);
  --shadow: 0 1px 0 rgba(30, 33, 38, .03), 0 16px 40px -26px rgba(30, 33, 38, .32);
  --shadow-lg: 0 2px 4px rgba(30, 33, 38, .04), 0 30px 70px -34px rgba(30, 33, 38, .34);
  --shadow-pop: 0 30px 60px -24px rgba(30, 33, 38, .34);
  --cls-special: #E5484D;
  --cls-personal: #8E4EC6;
  --cls-financial: #F5871F;
  --cls-public: #6F737B;
}

/* Dark is defined once and referenced by both the explicit toggle and the OS
   preference, so the two can never drift. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0F1013;
  --surface: #16171B;
  --surface-2: #1C1D22;
  --surface-3: #24252B;

  --ink: #ECECE8;
  --ink-soft: #C4C4BF;
  --muted: #8E9095;
  --faint: #67696F;

  --line: #26272C;
  --line-strong: #3A3C42;
  --chrome: #131417;
  --chrome-line: #26272C;
  --chrome-hover: #1F2025;
  --nav-ink: #B4B4AF;
  --topbar-bg: rgba(15, 16, 19, .82);
  --faintest: #4A4C52;
  --row-line: #222328;
  --row-hover: #1B1C21;
  --badge-bg: #3A2618;
  --badge-ink: #F0A56E;
  --alert: #F06A6E;
  --tile-tint-l: .3; --tile-tint-c: .05; --tile-ink-l: .82; --tile-ink-c: .11;

  /* The accent inverts in dark — a light beige rather than a dark one — so the
     ink that sits on it has to invert too. --on-accent is a separate token for
     exactly this; white on a light beige is around 1.6:1 and unreadable. */
  --accent: #CDBC9C;
  --accent-solid: #ECECE8;   /* ink inverts in dark, and so does the button */
  --accent-bright: #D8C9AE;
  --on-accent: #26211A;

  --purple: #BB93E0;
  --purple-solid: #8E4EC6;
  --purple-bright: #CBA9E8;

  --pop: #FF9F52;
  --pop-bright: #FFB273;

  --flow: #CDBC9C;
  --allow: #4CBF8C;
  --warn: #E0B45C;
  --block: #E56E5E;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
  --shadow: 0 1px 0 rgba(0, 0, 0, .2), 0 24px 54px -28px rgba(0, 0, 0, .62);
  --shadow-lg: 0 2px 6px rgba(0, 0, 0, .3), 0 38px 72px -30px rgba(0, 0, 0, .72);
  --shadow-pop: 0 28px 70px -22px rgba(0, 0, 0, .7);

  --cls-special: #F08A80;
  --cls-personal: #CBA9E8;
  --cls-financial: #EFB65C;
  --cls-public: #8E9095;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #0F1013;
    --surface: #16171B;
    --surface-2: #1C1D22;
    --surface-3: #24252B;
    --ink: #ECECE8;
    --ink-soft: #C4C4BF;
    --muted: #8E9095;
    --faint: #67696F;
    --line: #26272C;
    --line-strong: #3A3C42;
    --chrome: #131417;
    --chrome-line: #26272C;
    --chrome-hover: #1F2025;
    --nav-ink: #B4B4AF;
    --topbar-bg: rgba(15, 16, 19, .82);
    --faintest: #4A4C52;
    --row-line: #222328;
    --row-hover: #1B1C21;
    --badge-bg: #3A2618;
    --badge-ink: #F0A56E;
    --alert: #F06A6E;
    --tile-tint-l: .3; --tile-tint-c: .05; --tile-ink-l: .82; --tile-ink-c: .11;
    --accent: #CDBC9C;
    --accent-solid: #ECECE8;   /* ink inverts in dark, and so does the button */
    --accent-bright: #D8C9AE;
    /* Must be here as well as in [data-theme="dark"]: these two blocks are
       separate copies, and this is the token that actually differs between the
       themes. Missing it left anyone on OS-dark with white on light beige. */
    --on-accent: #26211A;
    --purple: #BB93E0;
    --purple-solid: #8E4EC6;
    --purple-bright: #CBA9E8;
    --pop: #FF9F52;
    --pop-bright: #FFB273;
    --flow: #CDBC9C;
    --allow: #4CBF8C;
    --warn: #E0B45C;
    --block: #E56E5E;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
    --shadow: 0 1px 0 rgba(0, 0, 0, .2), 0 24px 54px -28px rgba(0, 0, 0, .62);
    --shadow-lg: 0 2px 6px rgba(0, 0, 0, .3), 0 38px 72px -30px rgba(0, 0, 0, .72);
    --shadow-pop: 0 28px 70px -22px rgba(0, 0, 0, .7);
    --cls-special: #F08A80;
    --cls-personal: #CBA9E8;
    --cls-financial: #EFB65C;
    --cls-public: #8E9095;
  }
}

/* Touch wants less motion than a mouse does. A pointer moves to a target and
   an animation explains the change it caused; a finger is already ON the
   target, so the same animation is just time between the tap and the answer.
   ~60% of the desktop values — enough to still read as motion, short enough to
   stay out of the way. Everything downstream follows, because views read these
   rather than hardcoding: the 68 transitions, the mobile drawer's translate
   (shell.css), the dialog pop-in and the view-transition groups (motion.css). */
@media (pointer: coarse) {
  :root {
    --dur-xfast: 60ms;
    --dur-fast: 90ms;
    --dur: 140ms;
    --dur-slow: 250ms;
    --dur-xslow: 400ms;
  }
}

/* Last, so it wins over the touch block above — a stated accessibility
   preference outranks a device guess. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-xfast: 0ms;
    --dur-fast: 0ms;
    --dur: 0ms;
    --dur-slow: 0ms;
    --dur-xslow: 0ms;
  }
}