/* OxOnOS Design System v2 — tokens. Iris, 2026-10-04.
   Spec: pod/dev/specs/oxonos-gui-v2.md (UX-Contract-Hash in that file).
   Landed by Mason 2026-10-04 from the prototype tokens.css.

   Rules this file keeps from v1 (ui/css/tokens.css, 2026-09-01):
   - No remote font. The ONE face this file names first, Inter, is a file the
     box itself serves (ui/assets/fonts/InterVariable.woff2, OFL 1.1, licence
     beside it). Nothing is fetched from anyone else, ever.
   - Aluminium is a hairline colour, never text.
   - Status keeps semantic colour, and colour is never the only carrier: every
     dot ships beside its word (rule 4 — could-not-look is its own state).
   - Brand primitives are verbatim from brand-tokens.css and are not edited.

   Every text/ground pair below is measured (WCAG 2.1 relative luminance).
   Light worst-case ground = --surface-2; dark worst-case ground = --surface-2.

     LIGHT                       ratio     DARK                        ratio
     --text      #000000 / F4F1EA 18.6    --text      #F4F1EA / 252321 13.9
     --text-2    #5F5C55 / FBF9F4  6.3    --text-2    #BEB9AE / 252321  8.0
     --text-3    #6A665C / EFEBE3  4.8    --text-3    #A09B90 / 252321  5.7
     --ok        #1C6742 / F4F1EA  5.5    --ok        #7CC89D / 252321  7.9
     --warn      #7D550F / F0E7D2  5.4    --warn      #E2B866 / 252321  8.4
     --bad       #93342A / F0DDD8  5.8    --bad       #F2907F / 252321  6.8
     --info      #1E3A5F / F4F1EA 10.2    --info      #9DBCE3 / 252321  8.0
     on tints:   ok 5.6 · warn 5.4 · bad 5.8     ok 7.2 · warn 7.7 · bad 6.4 · info 7.6
     --control-border (1.4.11, 3:1)  light #8C887F / FBF9F4 3.4 · dark #7A756C / 1C1B19 3.8 (3.4 on 252321)
*/

:root {
  /* ── brand primitives (verbatim, do not edit) ─────────────────────────── */
  --oxon-black: #000000;
  --oxon-paper: #f4f1ea;
  --oxon-aluminium: #b8b8b4;
  --oxon-oxford-blue: #1e3a5f;

  /* ── type: ONE family, the device's own ───────────────────────────────── */
  /* ⛔ THE BUNDLED FACE COMES FIRST (glance-polish, 2026-10-04). This stack
     used to lead with "Helvetica Neue", which the Mac has and the box does
     not: on RH003 `fc-match "Helvetica Neue"` and `fc-match Inter` both
     answer DejaVu Sans, and DejaVu has Book and Bold only, so every 300/500
     weight drew as Book and every 600 as Bold. Every review shot was taken in
     a typeface the glass has never drawn. "OxOnOS Inter" is our own file
     (@font-face at the foot of this file), so the Mac, a phone and the glass
     now draw the same face; what follows is only the fallback. */
  --font: "OxOnOS Inter", "Helvetica Neue", Inter, "Inter Variable", -apple-system, BlinkMacSystemFont,
          "Segoe UI", "Liberation Sans", "DejaVu Sans", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;

  /* Scale: 12 · 13 · 15 · 17 · 20 · 24 · 32 · 44. Eight steps and no others. */
  --t-caption: 12px;   /* timestamps, footnotes. NEVER uppercase-tracked */
  --t-small:   13px;   /* secondary lines in rows */
  --t-body:    15px;   /* body, buttons, inputs */
  --t-lead:    17px;   /* row titles, page lede */
  --t-title-3: 20px;   /* card titles */
  --t-title-2: 24px;   /* section titles */
  --t-title-1: 32px;   /* page titles */
  --t-display: 44px;   /* Home greeting, big numerals only */
  --lh-tight: 1.15;
  --lh-snug:  1.3;
  --lh-body:  1.5;
  --w-regular: 400;
  --w-medium:  500;
  --w-bold:    600;
  --w-display: 300;    /* the brand's light numerals — display + stat only */
  --track-display: -0.02em;
  --track-title:   -0.01em;

  /* ── spacing: 4-point ─────────────────────────────────────────────────── */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px; --s-5: 20px;
  --s-6: 24px; --s-8: 32px; --s-10: 40px; --s-12: 48px; --s-16: 64px;
  --page-pad: var(--s-10);
  --page-max: 1120px;      /* one content width for every page */
  --read-max: 62ch;        /* prose never runs wider than this */

  /* ── radii ─────────────────────────────────────────────────────────────── */
  --r-sm: 8px;        /* inputs, small buttons */
  --r-md: 12px;       /* buttons, list groups */
  --r-lg: 16px;       /* cards */
  --r-xl: 24px;       /* hero card, sheets */
  --r-icon: 22.37%;   /* app-icon superellipse approximation (Juno family) */
  --r-pill: 999px;    /* chips only */

  /* ── touch ─────────────────────────────────────────────────────────────── */
  --hit: 44px;        /* minimum target, every control */
  --hit-lg: 52px;     /* primary actions; glass default */

  /* ── motion ────────────────────────────────────────────────────────────── */
  --dur-1: 120ms;     /* press, hover */
  --dur-2: 200ms;     /* toggles, chips */
  --dur-3: 320ms;     /* page and sheet */
  --ease: cubic-bezier(.2, .8, .2, 1);
  --ease-in-out: cubic-bezier(.4, 0, .2, 1);
  /* ⭐ FOUR NAMED TRANSITIONS (Atlas "what makes an OS" item 4; RULEBOOK R-O8).
     Nothing else animates except progress. Each is a duration + easing pair for
     the `animation`/`transition` shorthand; reduced motion zeroes the --dur-*
     they are built from, so all four stop together. */
  --motion-screen: var(--dur-2) var(--ease);        /* page change: cross-fade */
  --motion-sheet:  var(--dur-3) var(--ease);        /* sheets / popovers rise */
  --motion-app:    var(--dur-3) var(--ease);        /* app opens from its icon */
  --motion-banner: var(--dur-2) var(--ease);        /* banners + toasts in/out */
  --motion-exit:   var(--dur-2) var(--ease-in-out); /* anything leaving */

  /* ── layout ────────────────────────────────────────────────────────────── */
  --rail-w: 248px;
  --tabbar-h: 64px;

  /* ── colour: LIGHT (default) ──────────────────────────────────────────── */
  color-scheme: light;
  --bg:          #F4F1EA;   /* paper */
  --surface:     #FBF9F4;   /* cards */
  --surface-2:   #EFEBE3;   /* grouped rows, sunk wells */
  --surface-glass: rgba(251, 249, 244, .82);
  --text:        #000000;
  --text-2:      #5F5C55;
  --text-3:      #6A665C;
  --hairline:    #DDD9D0;   /* dividers inside cards */
  --border:      #D2CFC6;   /* card edge */
  --control-border: #8C887F;/* inputs, outline buttons (1.4.11) */
  --accent:      #000000;   /* primary button ground */
  --on-accent:   #F4F1EA;
  --ok:   #1C6742;  --ok-bg:   #E2EAE2;
  /* the persona's ONE colour (js/persona.js sets --persona-light/-dark from
     the palette in js/persona-art.js; every pair passes AA on its theme) */
  --persona: var(--persona-light, #1C6742);
  --warn: #7D550F;  --warn-bg: #F0E7D2;
  --bad:  #93342A;  --bad-bg:  #F0DDD8;
  --info: #1E3A5F;  --info-bg: #E1E6EE;
  --idle: #6A665C;  --idle-bg: #ECE8E0;   /* could-not-look / not checked */
  --focus: #1E3A5F;
  --shadow-1: 0 1px 2px rgba(30, 24, 10, .06);
  --shadow-2: 0 2px 6px rgba(30, 24, 10, .06), 0 8px 24px rgba(30, 24, 10, .06);
  --shadow-3: 0 12px 40px rgba(30, 24, 10, .14);
  --logo: url("/assets/brand/OxOnOS-primary-black-transparent.png");
}

/* ── colour: DARK — follows the device unless the owner chose ─────────── */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:          #141311;
    --surface:     #1C1B19;
    --surface-2:   #252321;
    --surface-glass: rgba(28, 27, 25, .82);
    --text:        #F4F1EA;
    --text-2:      #BEB9AE;
    --text-3:      #A09B90;
    --hairline:    #2E2C29;
    --border:      #34322E;
    --control-border: #7A756C;
    --accent:      #F4F1EA;
    --on-accent:   #141311;
    --ok:   #7CC89D;  --ok-bg:   #1E2E24;
    --persona: var(--persona-dark, #7CC89D);
    --warn: #E2B866;  --warn-bg: #33291A;
    --bad:  #F2907F;  --bad-bg:  #3A221E;
    --info: #9DBCE3;  --info-bg: #1E2836;
    --idle: #A09B90;  --idle-bg: #2A2826;
    --focus: #9DBCE3;
    --shadow-1: 0 0 0 1px rgba(255, 255, 255, .02);
    --shadow-2: 0 0 0 1px rgba(255, 255, 255, .03), 0 8px 24px rgba(0, 0, 0, .35);
    --shadow-3: 0 16px 48px rgba(0, 0, 0, .55);
    --logo: url("/assets/brand/OxOnOS-primary-white-transparent.png");
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #141311; --surface: #1C1B19; --surface-2: #252321;
  --surface-glass: rgba(28, 27, 25, .82);
  --text: #F4F1EA; --text-2: #BEB9AE; --text-3: #A09B90;
  --hairline: #2E2C29; --border: #34322E; --control-border: #7A756C;
  --accent: #F4F1EA; --on-accent: #141311;
  --ok: #7CC89D; --ok-bg: #1E2E24; --warn: #E2B866; --warn-bg: #33291A;
  --persona: var(--persona-dark, #7CC89D);
  --bad: #F2907F; --bad-bg: #3A221E; --info: #9DBCE3; --info-bg: #1E2836;
  --idle: #A09B90; --idle-bg: #2A2826; --focus: #9DBCE3;
  --shadow-1: 0 0 0 1px rgba(255, 255, 255, .02);
  --shadow-2: 0 0 0 1px rgba(255, 255, 255, .03), 0 8px 24px rgba(0, 0, 0, .35);
  --shadow-3: 0 16px 48px rgba(0, 0, 0, .55);
  --logo: url("/assets/brand/OxOnOS-primary-white-transparent.png");
}

/* ── the glass: 1920×1080 read across a desk ──────────────────────────── */
@media (min-width: 1700px) {
  :root {
    --t-caption: 13px; --t-small: 15px; --t-body: 17px; --t-lead: 19px;
    --t-title-3: 22px; --t-title-2: 28px; --t-title-1: 40px; --t-display: 56px;
    --page-max: 1360px; --page-pad: var(--s-12); --rail-w: 280px;
    --hit: 48px; --hit-lg: 56px;
  }
}
/* ── phones ────────────────────────────────────────────────────────────── */
@media (max-width: 760px) {
  :root { --page-pad: var(--s-5); --t-title-1: 28px; --t-display: 34px; }
}

/* ── reduced motion: everything still works, nothing moves ────────────── */
@media (prefers-reduced-motion: reduce) {
  :root { --dur-1: 0ms; --dur-2: 0ms; --dur-3: 0ms; }
}

/* ── brand mark: the APPROVED master for each ground, swapped, never recoloured.
   Two <img> elements carry .logo-on-light / .logo-on-dark; exactly one shows. */
:root { --logo-on-light: block; --logo-on-dark: none; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --logo-on-light: none; --logo-on-dark: block; } }
:root[data-theme="dark"] { --logo-on-light: none; --logo-on-dark: block; }
.logo-on-light { display: var(--logo-on-light) !important; }
.logo-on-dark  { display: var(--logo-on-dark) !important; }

/* ══════════════════════════════════════════════════════════════════════════
   v1 ALIASES — ONE RELEASE ONLY (spec §3: keep the v1 names mapped onto the
   semantic tokens for one release, then delete them).
   ⚠️ They are declared on :root as var() references, so they resolve on :root
   AFTER the theme block above has set the semantic value. That is what makes
   every v1 rule in app.css, join.css and welcome.html follow the dark theme
   without being rewritten. Lens owns the token-registry drift dispatch.
   The v1 contrast corrections of 2026-09-01 (--ink-40 #6A665C, --amber
   #7D550F, --local #1C6742, --red #93342A) are exactly the v2 light values,
   so no light text pair moved.
   ══════════════════════════════════════════════════════════════════════════ */
:root {
  --oxon-font-sans: var(--font);
  --oxon-letter-spacing-label: 0.02em;   /* the 0.22em tracked micro-label is retired */

  --paper:       var(--bg);
  --paper-deep:  var(--surface-2);
  --paper-raise: var(--surface);
  --ink:         var(--text);
  --ink-60:      var(--text-2);
  --ink-40:      var(--text-3);
  --alu:         var(--border);
  --alu-soft:    var(--hairline);
  --local:       var(--ok);
  --local-tint:  var(--ok-bg);
  --amber:       var(--warn);
  --amber-tint:  var(--warn-bg);
  --red:         var(--bad);
  --red-tint:    var(--bad-bg);
  --oxford:      var(--info);

  --radius:    var(--r-md);
  --radius-md: var(--r-md);
  --radius-lg: var(--r-lg);

  --fs-micro: var(--t-caption);  /* was 11px uppercase; now 12, sentence case */
  --fs-sm:    var(--t-small);
  --fs-small: var(--t-small);
  --fs-base:  var(--t-body);
  --fs-lg:    var(--t-lead);
  --fs-h2:    var(--t-title-3);
  --fs-h1:    var(--t-title-1);
  --fs-stat:  var(--t-title-1);
  --font-mono: var(--mono);
}

/* ── the bundled face (glance-polish, 2026-10-04) ─────────────────────────
   Inter 4.1 variable (rsms/inter release v4.1, web/InterVariable.woff2,
   SIL OFL 1.1 — ui/assets/fonts/OFL.txt). Served by the box from ui/, so it
   is local on the glass and LAN-local on every paired device. One file covers
   every weight 100–900, so 300/500/600 are real weights, not synthesised.
   The URL is RELATIVE to this file so a release-stamped /r/<GLASS_UI>/css/
   path resolves it inside the same immutable release.
   ⭐ TWO NAMES FOR ONE FILE, BECAUSE TWO SCREENS WANT DIFFERENT THINGS
   (2026-10-05, founder: "the home page takes a bit of time to load").
   · THE GLASS keeps font-display: block — it never draws a DejaVu frame that
     then jumps (a theme-flash-class finding); the file is on its own disk, so
     the block is a few ms. Selected by html[data-glass], which
     js/theme-boot.js sets before the stylesheets for a kiosk-injected page.
   · EVERY OTHER DEVICE gets swap. Over the LAN the 344 KB face can take a
     visible moment on a cold load, and block meant the page was laid out with
     NO text at all until it arrived. Swap draws the fallback and replaces it.
   Both rules name the same URL, so the browser fetches the file once; the
   shell preloads exactly that URL (core/api/ui_shell.py). */
@font-face {
  font-family: "OxOnOS Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../assets/fonts/InterVariable.woff2") format("woff2");
}
@font-face {
  font-family: "OxOnOS Inter Glass";
  font-style: normal;
  font-weight: 100 900;
  font-display: block;
  src: url("../assets/fonts/InterVariable.woff2") format("woff2");
}
html[data-glass] {
  --font: "OxOnOS Inter Glass", "Helvetica Neue", Inter, "Inter Variable", -apple-system, BlinkMacSystemFont,
          "Segoe UI", "Liberation Sans", "DejaVu Sans", Arial, sans-serif;
}
