/* ============================================================================
   ITOKAZE DS.
   tokens.css · the single source of truth for colour, type, space and motion
   ----------------------------------------------------------------------------
   THE TWO-STATE SIGNAL LAW
   The house has exactly two signal hues and neither one changes between themes:
       emerald  136.7°
       magenta  333.1°
   What changes is luminance, and it changes because the PHYSICS changes.
     · On obsidian the signal is EMISSION — light in air. It blooms.
     · On optic white the signal is INK — pigment on a lit surface. It never blooms.
   Bloom on white is the single tell that a dark-first brand was lazily inverted.
   That is why --sig-glow resolves to `none` in the light theme rather than to
   a softer shadow.

   Every ratio in the comments below is measured, not asserted.
   Run `node tools/verify-contrast.mjs` — it fails the build on regression, and
   it checks the OS-default blocks as well as the explicit-toggle blocks.
   ========================================================================== */

:root {
  color-scheme: light dark;

  /* ---- geometry: theme-invariant, because it is not colour ---------------- */
  --fault: 22.5deg;        /* half of true 45° bias — where woven cloth gives */
  --fault-axis: 112.5deg;  /* gradient axis that draws a stripe at --fault    */
  --pitch: 13px;           /* weave pitch; the half-pitch shear is 6.5px      */
  --shear: 6.5px;

  /* ---- type — Saira + Martian Mono, SIL OFL 1.1, self-hosted: fonts.css.
     Two further comparison faces live in assets/fonts for type-specimen.html. */
  --font-display: "Saira", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-body:    "Saira", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono:    "Martian Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* THE WIDTH LADDER — display hierarchy is built on this axis first.
     ONE superfamily at several widths: display and text are the same typeface
     separated by width alone. That is the Söhne Breit / Söhne relationship the
     direction originally called for, now in an OFL family.

     Saira spans wdth 50–125, and the expanded end alone is NOT enough —
     measured at 40px, "ITOKAZE" sets 166px at wdth 100 and only 194px at
     wdth 125, a 17% gain. So this ladder is deliberately asymmetric and leans
     on the CONDENSED end to open the span: 62 → 125 is 99px → 194px, a 1.95×
     range, which is wide enough for the hierarchy to hold.

     THE RULE THAT FOLLOWS: dense data must actually be set at --wdth-data or
     narrower. If everything sits between 100 and 125 the ladder collapses,
     and the first thing anyone reaches for is arbitrary tracking. The system
     reserves tracking for wordmarks, short labels and mono truth. */
  --wdth-hero:   125;   /* hero display only, weight 400–500                 */
  --wdth-wide:   112;   /* section heads, collection titles                  */
  --wdth-normal: 100;   /* body, UI, anything below ~24px                    */
  --wdth-data:    75;   /* spec tables, size ladders, dense numeric columns  */
  --wdth-tight:   62;   /* the narrow extreme — long tables, vertical rails  */

  /* display ramp — 1.333 perfect fourth. Hierarchy is built on the WIDTH axis
     first and the size axis second: 28px Breit outranks 38px Regular. */
  --t-90: 90px; --t-67: 67px; --t-50: 50px; --t-38: 38px;
  --t-28: 28px; --t-21: 21px; --t-16: 16px;
  /* ui ramp — 1.2 from 13. mono is fixed at 11/13 and never scales. */
  --t-23: 23px; --t-19: 19px; --t-13: 13px; --t-11: 11px;

  --track-display: -0.015em;
  --track-display-lg: -0.03em;
  --track-wordmark: 0.18em;    /* identity lockups and campaign signatures    */
  --track-label: 0.10em;       /* short uppercase navigation and controls     */
  --track-mono: 0.08em;        /* machine-truth and indexed section labels    */

  /* ---- space: 8px base, 4px subgrid reserved for mono data rows ---------- */
  --s-1: 8px; --s-2: 16px; --s-3: 24px; --s-4: 40px; --s-5: 64px; --s-6: 104px;
  --gutter: 24px;
  --radius: 2px;            /* precision radius: nearly square, never soft   */
  --radius-panel: 10px;     /* digital glass only; not used in print         */
  --radius-state: 999px;    /* ...except state chips. If it is round, it is
                               a live fact: LIVE / 4 LEFT / SOLD OUT.        */

  /* ---- motion ----------------------------------------------------------- */
  --ease-enter: cubic-bezier(0.16, 1, 0.3, 1);   /* fast launch, long settle */
  --ease-micro: cubic-bezier(0.4, 0, 0.2, 1);
  --dur-enter: 420ms;
  --dur-micro: 160ms;
  --dur-shear: 260ms;

  /* ---- HORIZON CHROME — deliberately theme-invariant --------------------- */
  /* Chrome here is not a shine effect, it is a reflection of ONE FIXED ROOM.
     The room does not repaint when the page turns white. This gradient is
     byte-identical in both themes, and it is the element that proves the two
     themes are the same house. Specular break locked at 52% of object height. */
  --chrome: linear-gradient(to bottom,
      #0A0C0E 0%, #647076 18%, #F8FBFC 34%, #818B90 46%,
      #111416 51.6%, #FFFFFF 52%, #AEB8BD 61%, #30453B 78%, #431128 100%);
  --chrome-break: 52%;
  --chrome-specular: #FFFFFF;
  --holographic: linear-gradient(112deg,
      #E8FBFF 0%, #F7F7FF 15%, #B6FFE0 31%, #FFFFFF 45%,
      #FFD5EA 61%, #C9E4FF 78%, #F4F5F6 100%);
  --signal-spectrum: linear-gradient(105deg,
      #05C33A 0%, #0A3D1C 33%, #080A0C 49%, #4A0B26 67%, #E60067 100%);
}

/* ============================================================================
   PALETTES
   ----------------------------------------------------------------------------
   Each palette is declared ONCE, in a @-less selector list that covers every
   way it can be requested:
     · the bare :root default          (dark — first paint, JS disabled)
     · the explicit attribute toggle   ([data-theme=…])
     · the class hook                  (.theme-…)
     · the OS preference               (@media, guarded against both hooks)
   The guard `:not([data-theme]):not(.theme-dark):not(.theme-light)` is load
   bearing: without it the media block (0,2,0) outranks `.theme-dark` (0,1,0)
   and a consumer using the class hook ships a light-locked site to every
   light-preference visitor.
   ========================================================================== */

/* ---- DARK — Obsidian. The signal is emission. --------------------------- */
:root,
:root[data-theme="dark"],
.theme-dark {
  --bg:         #080A0C;   /* Obsidian                                       */
  --surface:    #14181C;   /* Carbon Weave                                   */
  --surface-2:  #1B2126;   /* popovers, menus                                */
  --line:       #262C31;   /* 1.40:1 — STRUCTURE ONLY. Never an interactive
                              boundary; see --line-control.                  */
  --line-control: #5C666B; /* 3.37:1 ✓ 1.4.11 — every interactive edge       */
  --line-soft:  #1A1F23;

  --text:       #F4F7F5;   /* optic white on obsidian                        */
  --text-2:     #A2ACA8;   /* titanium                                       */
  --text-3:     #68736E;   /* large/decorative only                          */

  --sig:        #05C33A;   /*  8.38:1 ✓ AA — lit emerald, ≤4% of viewport    */
  --sig-quiet:  #0A3D1C;   /* unlit emerald — REQUIRED above 4% of viewport  */
  --sig-on:     #080A0C;   /* text on a lit-emerald fill                     */

  --state:      #E60067;   /*  4.31:1 — UI ONLY: edges, fills, 1–2px. NOT text */
  --state-text: #FA0070;   /*  5.00:1 ✓ AA — the text/label variant, same hue */
  --state-quiet:#4A0B26;

  --glass: rgba(20,24,28,.72);
  --glass-strong: rgba(8,10,12,.90);
  --glass-line: rgba(244,247,245,.22);
  --grid-line: rgba(244,247,245,.055);
  --panel-shadow: 0 22px 70px rgba(0,0,0,.42);
  --ambient: radial-gradient(circle at 72% 18%, rgba(230,0,103,.13), transparent 34%),
             radial-gradient(circle at 22% 76%, rgba(5,195,58,.11), transparent 32%);

  /* Emission. Delivered as a FILTER, never as box-shadow: box-shadow is the
     property components use for their 1px rings, and a focus rule that sets
     it would erase them. Two rings maximum. Never applied to text. */
  --sig-glow:   drop-shadow(0 0 3px rgba(5,195,58,.42)) drop-shadow(0 0 9px rgba(5,195,58,.16));
  --state-glow: drop-shadow(0 0 3px rgba(230,0,103,.38)) drop-shadow(0 0 8px rgba(230,0,103,.12));

  /* Dry Obsidian — 3% dithered grain. Functional: it kills the 8-bit banding
     that ruins every near-black gradient. */
  --grain-opacity: .30;
  --grain-blend: normal;
}

/* ---- LIGHT — Optic White. The signal is ink. ---------------------------- */
/* Not an inversion: a cool, luminous surface carrying the same two hues.    */
:root[data-theme="light"],
.theme-light {
  --bg:         #F6F8F7;   /* Optic White — cool, clean, luminous            */
  --surface:    #FFFFFF;   /* Pure Light                                     */
  --surface-2:  #E9EEEB;   /* Soft Titanium                                  */
  --line:       #D7DDDA;   /* STRUCTURE ONLY                                 */
  --line-control: #737C78; /* every interactive edge                         */
  --line-soft:  #E7ECE9;

  --text:       #0A0C0D;   /* Obsidian ink                                   */
  --text-2:     #505956;   /* Graphite                                       */
  --text-3:     #737C78;   /* large/decorative only                          */

  --sig:        #036B20;   /*  6.29:1 ✓ AA — emerald INK, hue 136.7° held    */
  --sig-quiet:  #CDE4D3;   /* emerald TINT — required above 4% of viewport   */
  --sig-on:     #F6F8F7;

  --state:      #C4005A;   /*  5.63:1 ✓ AA — magenta ink, 0.7° drift        */
  --state-text: #C4005A;   /* on paper the ink IS the text colour            */
  --state-quiet:#F8DCE8;

  --glass: rgba(255,255,255,.76);
  --glass-strong: rgba(255,255,255,.92);
  --glass-line: rgba(10,12,13,.16);
  --grid-line: rgba(10,12,13,.055);
  --panel-shadow: 0 22px 70px rgba(18,25,22,.10);
  --ambient: radial-gradient(circle at 72% 18%, rgba(230,0,103,.08), transparent 34%),
             radial-gradient(circle at 22% 76%, rgba(5,195,58,.07), transparent 32%);

  /* Ink does not bloom. This is the law, not an oversight. */
  --sig-glow:   none;
  --state-glow: none;

  --grain-opacity: .10;    /* paper tooth, not dither */
  --grain-blend: multiply;
}

/* The OS preference drives the default, but only when neither explicit hook
   is present — see the guard note above. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme]):not(.theme-dark):not(.theme-light) {
    --bg:         #F6F8F7;
    --surface:    #FFFFFF;
    --surface-2:  #E9EEEB;
    --line:       #D7DDDA;
    --line-control: #737C78;
    --line-soft:  #E7ECE9;
    --text:       #0A0C0D;
    --text-2:     #505956;
    --text-3:     #737C78;
    --sig:        #036B20;
    --sig-quiet:  #CDE4D3;
    --sig-on:     #F6F8F7;
    --state:      #C4005A;
    --state-text: #C4005A;
    --state-quiet:#F8DCE8;
    --glass: rgba(255,255,255,.76);
    --glass-strong: rgba(255,255,255,.92);
    --glass-line: rgba(10,12,13,.16);
    --grid-line: rgba(10,12,13,.055);
    --panel-shadow: 0 22px 70px rgba(18,25,22,.10);
    --ambient: radial-gradient(circle at 72% 18%, rgba(230,0,103,.08), transparent 34%),
             radial-gradient(circle at 22% 76%, rgba(5,195,58,.07), transparent 32%);
    --sig-glow:   none;
    --state-glow: none;
    --grain-opacity: .10;
    --grain-blend: multiply;
  }
}
