/* =============================================================================
   tokens.css — design tokens
   -----------------------------------------------------------------------------
   Source of truth for the portfolio design system.

   Provenance:
     · Structure, cascade architecture, motion scale, state ramp
         → the pi.dev visual language (studied from its shipped stylesheet)
     · Palette, type pairing, display treatment, card/section grammar
         → example.html, the reference page for this project

   Design decisions baked in here:
     · LIGHT IS THE DEFAULT THEME. example.html is a light editorial page; the
       dark theme is the alternate, not the baseline.
     · Every one of the 67 ad-hoc hex values in example.html has been folded
       into a named ramp. That file is the reference for the LOOK, not the
       reference for the VALUES — see DESIGN.md §12 for the census.
     · Chrome is monospace. Story is serif, italic, regular weight.
     · Radius defaults to 4px (example.html), not pi.dev's 0. One token flips it.

   This file contains exactly ONE cascade layer: `tokens`. Reset, base element
   styles and the layer-order declaration live in base.css, which must be
   linked AFTER this file.

   Nothing here paints anything. Every rule in this file declares a custom
   property on `html`.

   Rule: no raw color, size, duration, or spacing literal may appear anywhere
   else in the codebase. If a value is needed and not found here, add a token —
   do not inline the value.
   ============================================================================= */

/* Declared here because this file is loaded first. base.css repeats the
   identical statement; re-declaring an already-registered layer name is a
   no-op and layers keep their first-registered position, so this order is
   authoritative regardless of link order. */
@layer reset, tokens, base, layout, components, pages, utilities, overrides;

@layer tokens {
  :root {
    color-scheme: light;

    /* ---------------------------------------------------------------------
       1. PRIMITIVES
       Raw materials. These are the only literal colors in the system.

       Naming is by material, not by usage: paper is warm off-white stock,
       greige is the hairline family that draws on it, ink is what is printed,
       slate is the one cool accent in a warm page.
       ------------------------------------------------------------------ */

    /* PAPER — the warm neutral ramp. `paper-1` is the page itself. */
    --paper-0: #fbf9f5; /* one step above the page: inset terminal canvas */
    --paper-1: #f6f3ee; /* THE PAGE */
    --paper-2: #f1ede3; /* card / panel */
    --paper-3: #ebe5db; /* inline code, chips, tab strip */
    --paper-4: #e4ded2; /* footer, wells, structural chrome */
    --paper-5: #d8d1c1; /* deepest recess, disabled fills */

    /* GREIGE — hairlines. Eleven values collapsed to four. */
    --greige-1: #e8e2d8; /* faintest: internal dividers */
    --greige-2: #ded8ca; /* DEFAULT rule */
    --greige-3: #cdc6b5; /* emphasised rule, card hover */
    --greige-4: #c5bfae; /* control borders, chip outlines */

    /* INK — printed text. Twenty-three values collapsed to six. */
    --ink-0: #1a1917; /* display headings */
    --ink-1: #292724; /* strong: terminal text, <strong>, card titles */
    --ink-2: #423f3a; /* body copy */
    --ink-3: #55514a; /* secondary body */
    --ink-4: #686560; /* muted: labels, captions, annex copy */
    --ink-5: #7d7870; /* faint: metadata, terminal caption row */

    /* SLATE — the accent. One hue, four usable steps. */
    --slate-0: #44607a; /* emphasis / hover text */
    --slate-1: #55728a; /* THE ACCENT */
    --slate-2: #6d8598; /* mid */
    --slate-3: #8ba4b9; /* decorative: link underlines, rules */
    --slate-4: #b9c9d6; /* lightest: chart fills, hints */

    /* WARM SECONDARY — optional. Charts, status, one-off moments only.
       Never used for chrome, never for links. */
    --rust: #844f3b;
    --amber: #e1b06e;
    --sage: #a3a473;

    /* NIGHT — the dark theme's paper ramp. Cool-warm black, not neutral gray. */
    --night-0: #0a0d12;
    --night-1: #0d1116;
    --night-2: #121821;
    --night-3: #161d27;
    --night-4: #1c2431;
    --night-5: #212730;
    --night-6: #2a3442;

    /* NIGHT HAIRLINES */
    --night-line-1: #2f3844;
    --night-line-2: #3d4653;
    --night-line-3: #495059;
    --night-line-4: #757d89;

    --pure-white: #ffffff;
    --pure-black: #000000;

    /* ---------------------------------------------------------------------
       2. SURFACES
       Named by ROLE, not by direction. This matters: in the light theme a
       card is DARKER than the page (sunken + framed); in the dark theme a
       card is LIGHTER than the page (raised). Naming by direction would force
       one theme to invert its own semantics. Naming by role lets each theme
       pick the correct move.
       ------------------------------------------------------------------ */
    --surface-page: var(--paper-1); /* the page plane */
    --surface-card: var(--paper-2); /* framed content blocks */
    --surface-fill: var(--paper-3); /* inline code, chips, kbd */
    --surface-chrome: var(--paper-4); /* tab strips, footers, table heads */
    --surface-well: var(--paper-5); /* deepest recess: input wells */
    --surface-inset: var(--paper-0); /* the terminal canvas */

    /* Neutral alpha tints. Used for inert fills that carry no accent meaning. */
    --tint-faint: rgb(26 25 23 / 0.02);
    --tint-soft: rgb(26 25 23 / 0.04);
    --tint: rgb(26 25 23 / 0.06);
    --tint-strong: rgb(26 25 23 / 0.09);

    /* ---------------------------------------------------------------------
       3. RULES
       ------------------------------------------------------------------ */
    --rule-faint: var(--greige-1);
    --rule: var(--greige-2);
    --rule-strong: var(--greige-3);
    --rule-control: var(--greige-4);

    /* ---------------------------------------------------------------------
       4. INK
       Semantic names map to usage, so a component asks for the meaning.
       ------------------------------------------------------------------ */
    --ink-display: var(--ink-0);
    --ink-strong: var(--ink-1);
    --ink-body: var(--ink-2);
    --ink-secondary: var(--ink-3);
    --ink-muted: var(--ink-4);
    --ink-faint: var(--ink-5);

    /* Back-compat aliases so component code reads naturally in both roles. */
    --text: var(--ink-strong);
    --copy: var(--ink-body);
    --muted: var(--ink-muted);
    --muted-strong: var(--ink-secondary);
    --line: var(--rule);
    --line-strong: var(--rule-strong);

    /* ---------------------------------------------------------------------
       5. ACCENT
       The accent is used SPARINGLY in this style: links, the one highlighted
       word in a headline, the active-tab indicator, focus rings, selection.
       Tinted surfaces are the exception, not the norm — example.html uses
       neutral paper fills almost everywhere.
       ------------------------------------------------------------------ */
    --accent: var(--slate-1);
    --accent-strong: var(--slate-0);
    --accent-soft: var(--slate-3);
    --accent-light: var(--slate-4);

    /* Tinted surfaces. Deliberately restrained: max 14% of the hue. */
    --accent-surface-faint: color-mix(in srgb, var(--accent) 3%, transparent);
    --accent-surface-subtle: color-mix(in srgb, var(--accent) 7%, transparent);
    --accent-surface-soft: color-mix(in srgb, var(--accent) 11%, transparent);
    --accent-border-muted: color-mix(in srgb, var(--accent) 18%, transparent);
    --accent-border-hover: color-mix(in srgb, var(--accent) 42%, transparent);
    --accent-border-active: color-mix(in srgb, var(--accent) 62%, transparent);
    --accent-fill-soft: color-mix(in srgb, var(--accent) 22%, transparent);

    /* Link underlines. The 1px rule is the VISUAL SIGNIFIER of a link, so it
       is held to the 3:1 non-text contrast threshold (WCAG 1.4.11).

       --slate-2 measures 3.48:1 on the page and 3.29:1 on a card. --slate-3
       (the value the reference page uses, #849caf) measures 2.34:1 and fails.
       Reverting is one token if you prefer the lighter rule. */
    --accent-underline: var(--slate-2);
    --accent-underline-hover: var(--accent);

    --focus-ring: color-mix(in srgb, var(--accent) 72%, transparent);

    /* Selection is SOLID accent, not a tint. Measured: a 24% tint over the
       page yields #cfd4d6, where white text scores 1.50:1 — unreadable. Solid
       accent gives white 5.05:1 and matches the reference page exactly. */
    --selection-background: var(--accent);
    --selection-ink: var(--pure-white);

    /* The active-page indicator. A two-stop gradient in dark (where it reads),
       collapsed to one stop in light (where the second stop is invisible and
       only adds noise). */
    --active-stripe: linear-gradient(90deg, var(--accent) 0 62%, var(--slate-2) 62% 100%);

    /* ---------------------------------------------------------------------
       6. CHROME
       ------------------------------------------------------------------ */
    --chrome-surface: color-mix(in srgb, var(--surface-page) 92%, transparent);
    --chrome-border: var(--rule);
    --chrome-highlight: color-mix(in srgb, var(--surface-page) 70%, white);
    --chrome-backdrop: color-mix(in srgb, var(--surface-page) 72%, transparent);
    --chrome-link: var(--ink-muted);
    --chrome-link-hover: var(--ink-strong);
    --chrome-link-active: var(--ink-0);

    /* Scrollbar — thin, square, low-contrast. */
    --scrollbar-thumb: color-mix(in srgb, var(--accent) 28%, transparent);
    --scrollbar-thumb-hover: color-mix(in srgb, var(--accent) 44%, transparent);

    /* ---------------------------------------------------------------------
       7. TEXTURE
       The paper grid. DORMANT BY DEFAULT — example.html defines a dot grid but
       never applies it; pi.dev uses a line grid on every screen. Flip
       --texture on a container to enable, and choose the pattern with
       --texture-pattern.

       Both patterns sit at near-invisible alpha. If a reader notices the
       texture before the content, it is too strong.
       ------------------------------------------------------------------ */
    --grid-gap: 4px; /* line grid: minor cell */
    --grid-major: 20px; /* line grid: major cell AND dot grid pitch */
    --grid-minor-color: rgb(26 25 23 / 0.022);
    --grid-major-color: rgb(26 25 23 / 0.055);
    --grid-dot-color: rgb(26 25 23 / 0.08);

    /* ---------------------------------------------------------------------
       8. TYPOGRAPHY
       Two families, three registers:
         serif        storytelling. Italic for display, regular weight.
         mono         ALL machine text, ALL chrome.
         accent-mono  optional third register for chrome, if you want the
                      interface to have more character than JetBrains Mono
                      alone provides. Falls back cleanly — see DESIGN.md §5.
       ------------------------------------------------------------------ */
    --serif: "Newsreader", "Source Serif 4", "Iowan Old Style", Georgia, "Times New Roman", serif;
    --mono:
      "JetBrains Mono", ui-monospace, "SFMono-Regular", "Menlo", "Consolas", monospace;
    --accent-mono: "Departure Mono", var(--mono);

    /* Display treatment. THE defining stylistic choice of this system:
       large, italic, regular weight, tightly tracked. Not bold. */
    --display-style: italic;
    --display-weight: 400;
    --display-tracking: -0.015em;

    /* Root is 18px, not 16px. The whole scale is authored against that unit. */

    --fs-display: clamp(1.9rem, 5.5vw, 3rem);
    /* 1.1 is a floor, not a preference: below it, italic descenders collide
       with the following line. */
    --lh-display: 1.1;
    --ls-display: -0.02em;

    --fs-h1: clamp(1.75rem, 4.2vw, 2.6rem);
    --lh-h1: 1.1;
    --ls-h1: -0.015em;

    --fs-h2: clamp(1.5rem, 3vw, 1.9rem);
    --lh-h2: 1.15;
    --ls-h2: -0.015em;

    --fs-h3: 1.125rem;
    --lh-h3: 1.3;
    --ls-h3: -0.01em;

    /* Prose. Generous: this is a reading surface. */
    --fs-copy: 0.9375rem; /* 15px @ 16 root ≈ 16.9px @ 18 root */
    --lh-copy: 1.65;
    --fw-copy: 400;

    --fs-body: 1rem;
    --lh-body: 1.6;

    --fs-mono: 0.75rem;
    --lh-mono: 1.55;

    /* Chrome. Always uppercase, always tracked. */
    --fs-label: 0.611rem; /* 11px */
    --lh-label: 1;
    --ls-label: 0.08em;

    --fs-nav: 0.611rem;
    --ls-nav: 0.08em;

    --fs-button: 0.611rem;
    --ls-button: 0.08em;

    --fs-caption: 0.611rem;
    --ls-caption: 0.08em;

    --fs-code: 0.75rem; /* inline code inside prose */

    /* ---------------------------------------------------------------------
       9. SPACE
       ------------------------------------------------------------------ */
    --space-3xs: 0.125rem;
    --space-2xs: 0.25rem;
    --space-xs: 0.5rem;
    --space-sm: 0.75rem;
    --space-md: 1rem;
    --space-lg: 1.5rem;
    --space-xl: 2rem;
    --space-2xl: 3rem;
    --space-3xl: 4rem;
    --space-4xl: 7rem; /* section rhythm */

    /* ---------------------------------------------------------------------
       10. LAYOUT
       ------------------------------------------------------------------ */
    --page-max: 64rem; /* max-w-5xl: the reading measure */
    --page-max-wide: 72rem; /* max-w-6xl: the header bar */
    --page-pad-inline: 1.5rem;
    --page-pad-block-start: 4rem;
    --page-pad-block-end: 6rem;

    --prose-max: 42rem; /* max-w-2xl */
    --prose-narrow: 28rem; /* max-w-md: hero subtitle */
    --widget-max: 36rem; /* max-w-xl: install box */

    --grid-columns: 12;
    --col-gap: 3rem;

    --chrome-height: 3.5rem;
    --chrome-sticky-offset: 5rem; /* the sticky stage's top offset */

    --hit-min: 44px;

    /* ---------------------------------------------------------------------
       11. RADIUS
       4px (Tailwind `rounded`) is what example.html ships. pi.dev uses 0.
       Both are defensible; this is a one-token decision. See DESIGN.md §11.
       ------------------------------------------------------------------ */
    --radius-sharp: 0;
    --radius: 0.25rem;
    --radius-pill: 999px;

    /* ---------------------------------------------------------------------
       12. ELEVATION
       Shadows are rare and warm-tinted, never neutral black. In this style
       depth is carried by hairlines and paper fills; the shadow exists only to
       lift the terminal window and floating overlays off the page.
       ------------------------------------------------------------------ */
    --shadow-none: none;
    --shadow-window: 0 10px 30px -15px rgb(0 0 0 / 0.07);
    --shadow-chip: 0 1px 2px rgb(0 0 0 / 0.05);
    --shadow-panel: 0 4px 16px -8px rgb(0 0 0 / 0.1);

    /* ---------------------------------------------------------------------
       13. MOTION
       Slow, single-directional, heavily decelerated. No bounce, no spring.
       Three curves only; they are not interchangeable.
       ------------------------------------------------------------------ */
    --ease-reveal: cubic-bezier(0.22, 1, 0.36, 1); /* settles: panels, sections */
    --ease-hero: cubic-bezier(0.645, 0.045, 0.355, 1); /* the only curve allowed to accelerate */
    --ease-focus: cubic-bezier(0.215, 0.61, 0.355, 1); /* micro-interactions under 300ms */

    --dur-micro: 140ms; /* link rule, colour shift */
    --dur-ui: 260ms; /* chrome show/hide, chip state */
    --dur-theme: 400ms; /* theme crossfade */
    --dur-transition: 440ms; /* layout transform */
    --dur-hero: 770ms; /* hero entrance */
    --dur-heading: 1330ms; /* headline line reveal */
    --dur-reveal: 1540ms; /* section reveal */

    --motion-stagger: 105ms; /* per-line headline delay */

    /* ---------------------------------------------------------------------
       14. FORM CONTROLS
       ------------------------------------------------------------------ */
    --form-label-font-family: var(--accent-mono);
    --form-label-font-size: var(--fs-label);
    --form-label-letter-spacing: var(--ls-label);
    --form-label-color: var(--ink-muted);

    --form-control-block: var(--hit-min);
    --form-control-pad-block: 0.5rem;
    --form-control-pad-inline: 0.75rem;
    --form-control-border: var(--rule-control);
    --form-control-background: var(--surface-inset);
    --form-control-color: var(--ink-strong);
    --form-control-placeholder: var(--ink-faint);
    --form-control-font-family: var(--mono);
    --form-control-font-size: var(--fs-mono);
    --form-control-focus-border: var(--accent-border-active);
    --form-control-focus-ring: var(--focus-ring);
    --form-control-ring-width: 2px;
    --form-control-ring-offset: -1px;

    --form-invalid-accent: var(--rust);
    --form-invalid-border: var(--form-invalid-accent);
    --form-invalid-text: var(--form-invalid-accent);

    /* ---------------------------------------------------------------------
       15. STATUS
       Callouts only. Never decorative.
       ------------------------------------------------------------------ */
    --status-success: #4a7d5c;
    --status-warning: #9a6a1f;
    --status-error: #9c3f28;
    --status-info: var(--accent-strong);

    /* ---------------------------------------------------------------------
       16. RICH TEXT
       ------------------------------------------------------------------ */
    --rich-text-code-border: var(--rule);
    --rich-text-code-background: var(--surface-fill);
    --rich-text-code-color: var(--ink-strong);
    --rich-text-pre-border: var(--rule);
    --rich-text-pre-background: var(--surface-card);
    --rich-text-pre-color: var(--ink-strong);

    /* ---------------------------------------------------------------------
       17. TERMINAL
       The sticky stage. Its own surface family so a terminal reads as a
       terminal in both themes without borrowing card tokens.
       ------------------------------------------------------------------ */
    --terminal-background: var(--surface-inset);
    --terminal-chrome: var(--surface-card);
    --terminal-border: var(--rule);
    --terminal-ink: var(--ink-strong);
    --terminal-ink-faint: var(--ink-faint);
    --terminal-prompt: var(--accent-strong);
    --terminal-accent: var(--slate-2);
    --terminal-shadow: var(--shadow-window);
  }

  /* ==========================================================================
     DARK THEME
     Not an inversion. The paper ramp maps onto the night ramp, ink maps onto
     light values, and the accent lightens because #55728a fails contrast on
     a dark page.

     The card/surface move is the important one: in light, a card is DARKER
     than the page; in dark, it is LIGHTER. That is why surfaces are named by
     role and not by direction.
     ========================================================================== */
  :root[data-theme="dark"] {
    color-scheme: dark;

    /* Surfaces.
       A clean six-step elevation ladder. Each step must be distinguishable
       from its neighbour at a glance — if two steps are within ~6% lightness
       they read as one muddy surface, which is the failure mode of most dark
       themes. Light uses paper-0…paper-5; dark uses night-0…night-6. */
    --surface-well: var(--night-0); /* deepest recess */
    --surface-inset: var(--night-1); /* terminal canvas */
    --surface-chrome: var(--night-2); /* bars, footers */
    --surface-page: var(--night-3); /* the plane */
    --surface-card: var(--night-5); /* cards, panels — RAISED */
    --surface-fill: var(--night-6); /* chips, kbd, hover fill */

    --tint-faint: rgb(255 255 255 / 0.02);
    --tint-soft: rgb(255 255 255 / 0.04);
    --tint: rgb(255 255 255 / 0.06);
    --tint-strong: rgb(255 255 255 / 0.09);

    /* Rules */
    --rule-faint: var(--night-line-1);
    --rule: var(--night-line-3);
    --rule-strong: var(--night-line-4);
    --rule-control: var(--night-line-2);

    /* Ink */
    --ink-display: #f3f2f0;
    --ink-strong: #e6e8ea;
    --ink-body: #d5d8db;
    --ink-secondary: #b4b9c0;
    --ink-muted: #9fa4ab;
    --ink-faint: #7b838d;

    /* Accent — lightened so it holds contrast on a dark page. */
    --accent: var(--slate-3);
    --accent-strong: #a9c0cf;
    --accent-soft: #6d8598;
    --accent-light: var(--slate-4);

    /* Measured 6.54:1 for the accent on the dark page; the underline itself
       is held at full accent rather than a tint, for the same 1.4.11 reason as
       the light theme. */
    --accent-underline: var(--accent-soft);
    --accent-underline-hover: var(--accent);

    /* Solid accent. A 32% tint yields #3b4856, where --night-0 scores 2.08:1.
       Solid #8ba4b9 gives --night-0 7.51:1. */
    --selection-background: var(--accent);
    --selection-ink: var(--night-0);

    /* The two-stop stripe is visible at dark contrast; keep it. */
    --active-stripe: linear-gradient(90deg, var(--accent) 0 62%, var(--slate-1) 62% 100%);

    /* Chrome */
    --chrome-surface: color-mix(in srgb, var(--surface-page) 90%, transparent);
    --chrome-border: var(--rule);
    --chrome-highlight: var(--night-line-2);
    --chrome-backdrop: color-mix(in srgb, var(--night-0) 66%, transparent);
    --chrome-link: var(--ink-muted);
    --chrome-link-hover: var(--ink-strong);
    --chrome-link-active: var(--ink-display);

    --scrollbar-thumb: color-mix(in srgb, var(--accent) 28%, transparent);
    --scrollbar-thumb-hover: color-mix(in srgb, var(--accent) 44%, transparent);

    /* Texture must be built from light, not ink, on a dark page. */
    --grid-minor-color: rgb(255 255 255 / 0.014);
    --grid-major-color: rgb(255 255 255 / 0.032);
    --grid-dot-color: rgb(255 255 255 / 0.075);

    /* Elevation. Dark surfaces get separation from rules, not shadow, so the
       window shadow is reduced rather than reused at full strength. */
    --shadow-window: 0 14px 34px -18px rgb(0 0 0 / 0.65);
    --shadow-chip: 0 1px 2px rgb(0 0 0 / 0.4);
    --shadow-panel: 0 8px 24px -12px rgb(0 0 0 / 0.55);

    --form-control-background: var(--night-1);
    --form-control-color: var(--ink-strong);
    --form-control-placeholder: var(--ink-faint);

    --status-success: #5db87a;
    --status-warning: #e8993a;
    --status-error: #e8704f;

    --rich-text-pre-background: var(--surface-card);
    --rich-text-pre-color: var(--ink-body);
  }

  /* ==========================================================================
     MODERN COLOR DERIVATION

     The `color-mix()` ramp in scope 5 is a fallback-friendly approximation.
     Where relative color syntax is available we derive the ramp directly from
     the live accent value, so the palette cannot drift when the accent moves
     between themes.

     This block must come after both theme blocks so it wins on capability.
     ========================================================================== */
  @supports (color: rgb(from white r g b)) {
    :root {
      --accent-surface-faint: rgb(from var(--accent) r g b / 0.03);
      --accent-surface-subtle: rgb(from var(--accent) r g b / 0.07);
      --accent-surface-soft: rgb(from var(--accent) r g b / 0.11);
      --accent-border-muted: rgb(from var(--accent) r g b / 0.18);
      --accent-border-hover: rgb(from var(--accent) r g b / 0.42);
      --accent-border-active: rgb(from var(--accent) r g b / 0.62);
      --accent-fill-soft: rgb(from var(--accent) r g b / 0.22);
      --focus-ring: rgb(from var(--accent) r g b / 0.72);
      --scrollbar-thumb: rgb(from var(--accent) r g b / 0.28);
      --scrollbar-thumb-hover: rgb(from var(--accent) r g b / 0.44);
    }

    :root[data-theme="dark"] {
      --focus-ring: rgb(from var(--accent) r g b / 0.72);
    }
  }
}
