/* ==========================================================================
   Kapta Design System — tokens.css
   SINGLE SOURCE for the site's brand values. The kapta.fi theme imports this
   file; the /designsystem/ page renders from it. Change a token here and both
   the live site and this documentation move together — they cannot drift.

   Release: 2.6.5 "Estuary" (2026-08-28) — --shadow-edge settled at the
   threshold: 2.6.4's step down vanished entirely on dark grounds, so half
   a step back up (0 -3px 9px -3px; gray .10 light / black .38 dark).
   2.6.4 — quieter + the toggle/.theme-dark block — which had kept the
   louder pre-whisper value — brought into line: all three shadow-edge
   definitions now share one geometry.
   2.6.3 — adds .theme-dark, the inverted-
   surface scope: put the class on any element and the semantic tokens remap
   dark for that subtree while the page stays light (first use: the front-page
   card stack). Same remap as the page-level [data-theme="dark"] toggle.
   Also adds --shadow-edge (top-edge shadow for stacked surfaces; 2.6.3
   sets the RULE: Kapta shadows are whisper-quiet — almost unnoticeable,
   gray not black, sides compressed by negative spread, upward-only for
   edges. Sensed, never seen. Dark remap deepens alpha only.)
   DEFINED: colour palette (mono 6 + green 5 + orange 5 + carmine 5 levels),
            status colours, typography (Archivo; medium-tuned rem/pt scale),
            spacing, radii, containers, motion (durations/easing, from the
            nav rollout), interaction states (focus/pressed/disabled).

   Two layers:
     1. PRIMITIVES  — the raw palette (--mono-*, --green-*). Theme-independent.
     2. SEMANTIC    — role tokens (--color-*) mapped onto primitives. Re-mapped
                      per theme. Components reference these, never the primitives.
   ========================================================================== */

:root {
  /* ===== PRIMITIVES — palette (primary colours) ============================ */
  /* Neutral / mono — 6 levels, 1 = darkest … 6 = lightest */
  --mono-1: #050505;
  --mono-2: #3a3a3a;
  --mono-3: #8a8a8a;
  --mono-4: #d9d9d9;
  --mono-5: #f2f2f2;
  --mono-6: #fafafa;

  /* Green — 5 levels, 1 = darkest … 5 = lightest */
  --green-1: #112f0d;
  --green-2: #1a4b15;
  --green-3: #246b1d;
  --green-4: #4f9448;
  --green-5: #86b982;

  /* Orange — 5 levels, 1 = darkest … 5 = lightest */
  --orange-1: #743315;
  --orange-2: #da7025;
  --orange-3: #fbb841;
  --orange-4: #ffe76e;
  --orange-5: #fff5c3;

  /* Carmine — 5 levels, 1 = darkest … 5 = lightest */
  --carmine-1: #380017;
  --carmine-2: #570024;
  --carmine-3: #70002f;
  --carmine-4: #8f003c;
  --carmine-5: #a80046;

  /* ===== SEMANTIC — light theme (roles → palette) ========================= */
  --color-paper:          var(--mono-6);   /* page ground              */
  --color-surface:        var(--mono-6);   /* card ground (+ border/shadow) */
  --color-surface-2:      var(--mono-5);   /* sunken / subtle fill     */
  --color-border:         var(--mono-4);
  --color-border-strong:  var(--mono-3);
  --color-ink-3:          color-mix(in srgb, var(--mono-2) 55%, var(--mono-3)); /* muted text */
  --color-ink-2:          var(--mono-2);   /* secondary text           */
  --color-ink:            var(--mono-1);   /* primary text             */

  --color-accent:          var(--green-3); /* brand accent             */
  --color-accent-hover:    var(--green-2);
  --color-accent-active:   var(--green-1); /* pressed — one step beyond hover */
  --color-accent-contrast: var(--mono-6);

  /* Interaction states. Focus ring on :focus-visible only:
       outline: var(--focus-width) solid var(--color-focus);
       outline-offset: var(--focus-offset);
     (outline, not box-shadow — follows radius, respects forced-colors; the
     offset gap keeps it legible on accent fills). Disabled = whole-element
     opacity + suppressed interaction styles; never disable links.
     Visited links = deliberately identical to unvisited. */
  --color-focus:      var(--color-accent);  /* follows accent per theme */
  --focus-width:      2px;
  --focus-offset:     2px;
  --disabled-opacity: 0.5;
  --color-selection:  var(--green-5);  /* ::selection ground, mono-1 text; theme-independent */

  /* Status triad — positive=green, neutral=orange, negative=carmine */
  --color-success: var(--green-3);    /* positive / ascending  */
  --color-warning: var(--orange-2);   /* neutral  / stable     */
  --color-danger:  var(--carmine-5);  /* negative / descending */
  /* Intent aliases (same values, data-viz-friendly names) */
  --color-positive: var(--color-success);
  --color-neutral:  var(--color-warning);
  --color-negative: var(--color-danger);

  /* ===== Typography — Archivo (Google Fonts). Word/pt mapping in brand.md. == */
  --font-display: "Archivo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-body:    "Archivo", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono:    ui-monospace, "SFMono-Regular", "Cascadia Code", Consolas, monospace;

  /* Type roles. Online base = Archivo Regular; docs/Word base = Archivo Medium
     (Regular renders light on paper). Word: Title = "Archivo SemiExpanded" Bold,
     Subtitle = "Archivo" Bold. */
  --title-weight:    700;      /* Titles: Archivo SemiExpanded, Bold  */
  --title-stretch:   112.5%;   /* SemiExpanded width (wdth 112.5)     */
  --subtitle-weight: 600;      /* Subtitles: Archivo Medium, bolded (SemiBold) */
  --subtitle-stretch: 112.5%;  /* Subtitles: SemiExpanded, same width as titles */
  --body-weight:     400;      /* Online base: Archivo Regular. Docs base: Medium 500 (see brand.md). */
  --eyebrow-weight:  200;      /* Eyebrows/labels: Archivo ExtraLight (thin), uppercase + --tracking-label */
  --eyebrow-stretch: 112.5%;   /* Eyebrows: SemiExpanded, same width as titles */

  /* Type scale — MEDIUM-TUNED, not unit conversions: web = rem (screen reads
     larger); print/Word = pt (Word-native body ~11pt). See brand.md. */
  --text-xs:   0.75rem;   /* 12px · print  8pt */
  --text-sm:   0.875rem;  /* 14px · print  9pt */
  --text-base: 1.125rem;  /* 18px · print 11pt */
  --text-lg:   1.375rem;  /* 22px · print 14pt */
  --text-xl:   1.75rem;   /* 28px · print 18pt */
  --text-2xl:  2.25rem;   /* 36px · print 24pt */
  --text-3xl:  2.75rem;   /* 44px · print 30pt */
  --text-4xl:  3.5rem;    /* 56px · print 40pt */
  /* Display — viewport-scaled statement size, web only (no print mapping):
     sized so ~26 characters (≈ ⅓ of a long statement) span the standard
     content container per line. Subtitle voice (600 SemiExpanded). */
  --text-display: clamp(2.25rem, 6.6vw, 6.7rem);

  --weight-thin:     200;
  --weight-normal:   400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;

  --leading-tight:  1.15;
  --leading-snug:   1.35;
  --leading-normal: 1.6;

  --tracking-tight: -0.02em;   /* large display / titles */
  --tracking-label:  0.06em;   /* uppercase labels, eyebrows */

  /* ===== Spacing — web: 5-step scale (8px grid + 24px medium) + section ==== */
  /* Docs/Word: pt = px × 0.75 (8px = 6pt). Round off-scale needs to nearest step. */
  --space-1: 0.25rem;    /*   4px ·  3pt · tight internal (icon↔label, chips)   */
  --space-2: 0.5rem;     /*   8px ·  6pt · small padding / related gap          */
  --space-3: 1rem;       /*  16px · 12pt · standard component gap / card pad    */
  --space-4: 1.5rem;     /*  24px · 18pt · comfortable medium                   */
  --space-5: 2rem;       /*  32px · 24pt · group / block separation             */
  --space-section: 8rem; /* 128px · major page-section spacer (mobile floor 4rem) */

  /* ===== Radii — DEFINED ================================================== */
  --radius-sm:   4px;
  --radius-md:   8px;
  --radius-lg:   14px;
  --radius-full: 999px;

  /* ===== Containers — DEFINED ============================================= */
  --container:      72rem;
  --container-text: 38rem;   /* readable measure (~65–75 chars) */

  /* ===== Motion — learned from the nav rollout (2026-08) ================== */
  /* fast = micro color/opacity (hovers, crossfades); medium = surface fades
     (bar, scrim); slow = size/position morphs (panel height, slides, widening).
     Morphs use --ease-standard; color/opacity use plain `ease`.
     Always honor prefers-reduced-motion. */
  --motion-fast:   150ms;
  --motion-medium: 250ms;
  --motion-slow:   280ms;
  --ease-standard: cubic-bezier(.4, 0, .2, 1);
  --hover-grace:   130ms;   /* delay before a hover-opened surface closes */

  /* ===== Elevation ======================================================== */
  --shadow-sm: 0 1px 2px rgba(5, 5, 5, .06), 0 1px 3px rgba(5, 5, 5, .08);
  --shadow-md: 0 4px 12px rgba(5, 5, 5, .08), 0 2px 4px rgba(5, 5, 5, .06);
  --shadow-lg: 0 20px 30px -12px rgba(5, 5, 5, .20);   /* panels, modals */
  --shadow-edge: 0 -3px 9px -3px rgba(58, 58, 58, .10);  /* top-edge, whisper-quiet: gray (mono-2), sides compressed (−3px spread) — stacked / overlapping surfaces (card decks) */

  /* ===== Breakpoints (reference — CSS vars can't drive media queries) ===== */
  --bp-content: 992px;    /* content/mobile handoff */
  --bp-nav:     1400px;   /* nav items → hamburger */

  /* ===== Z-index scale ==================================================== */
  --z-scrim:   80;    /* nav glassmorphism scrim  */
  --z-nav:     90;    /* fixed bar + mega-panel   */
  --z-curtain: 100;   /* page-transition curtain  */
  --z-modal:   1000;  /* lightbox/modal           */
}

/* ===== SEMANTIC — dark theme remap (primitives are unchanged) ============= */
/* Applied when the OS prefers dark AND the user hasn't forced light. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --color-paper:          var(--mono-1);
    --color-surface:        color-mix(in srgb, var(--mono-1) 80%, var(--mono-2));
    --color-surface-2:      color-mix(in srgb, var(--mono-1) 62%, var(--mono-2));
    --color-border:         color-mix(in srgb, var(--mono-2) 75%, var(--mono-1));
    --color-border-strong:  var(--mono-2);
    --color-ink-3:          var(--mono-3);
    --color-ink-2:          var(--mono-4);
    --color-ink:            var(--mono-6);
    --color-accent:          var(--green-4);
    --color-accent-hover:    var(--green-5);
    --color-accent-active:   var(--green-3); /* pressed dims (no lighter step above green-5) */
    --color-accent-contrast: var(--mono-1);
    --color-success: var(--green-4);    /* positive / ascending  */
    --color-warning: var(--orange-3);   /* neutral  / stable     */
    --color-danger:  var(--carmine-5);  /* negative / descending */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .40);
    --shadow-md: 0 6px 18px rgba(0, 0, 0, .45);
    --shadow-edge: 0 -3px 9px -3px rgba(0, 0, 0, .38);
  }
}

/* Explicit user toggle — overrides the media query in both directions.
   .theme-dark is the same remap as an inverted-surface scope: put the class
   on any component and its subtree flips dark while the page stays light. */
:root[data-theme="dark"],
.theme-dark {
  color-scheme: dark;
  --color-paper:          var(--mono-1);
  --color-surface:        color-mix(in srgb, var(--mono-1) 80%, var(--mono-2));
  --color-surface-2:      color-mix(in srgb, var(--mono-1) 62%, var(--mono-2));
  --color-border:         color-mix(in srgb, var(--mono-2) 75%, var(--mono-1));
  --color-border-strong:  var(--mono-2);
  --color-ink-3:          var(--mono-3);
  --color-ink-2:          var(--mono-4);
  --color-ink:            var(--mono-6);
  --color-accent:          var(--green-4);
  --color-accent-hover:    var(--green-5);
  --color-accent-active:   var(--green-3); /* pressed dims (no lighter step above green-5) */
  --color-accent-contrast: var(--mono-1);
  --color-success: var(--green-4);
  --color-warning: #cc9a3a;
  --color-danger:  #e0736c;
  /* Aliases must be REDECLARED in this scope, not just their targets. A
     custom property's computed value has its var() already substituted, so
     `--color-focus: var(--color-accent)` on :root computes to the LIGHT
     accent and inherits that literal colour into here — remapping
     --color-accent below does not reach back into it. Missing these gave
     every focus ring inside a .theme-dark subtree (the footer card, the
     front-page card deck) green-3 #246b1d on ≈#101010 = 2.91:1, under the
     3:1 WCAG 1.4.11 minimum; green-4 gives 5.13:1.
     The page-level dark path (the prefers-color-scheme block above) is
     unaffected because it redeclares --color-accent on :root itself, which
     re-substitutes the aliases. Only a SUBTREE scope loses them. */
  --color-focus:    var(--color-accent);
  --color-positive: var(--color-success);
  --color-neutral:  var(--color-warning);
  --color-negative: var(--color-danger);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .40);
  --shadow-md: 0 6px 18px rgba(0, 0, 0, .45);
  --shadow-edge: 0 -3px 9px -3px rgba(0, 0, 0, .38);
}
