/* =============================================================================
   tokens.v1.css — the shared token layer for derek-portfolio and /learn.

   Specification: docs/design-system.md (every value here is documented and,
   for colour, contrast-checked there). Change a value there first.

   Rules
   - Tokens only: custom properties and nothing that styles an element.
   - Works with no JavaScript. The theme follows prefers-color-scheme; an
     explicit [data-theme="light"|"dark"] on <html> overrides it (set early by
     /assets/js/theme.v1.js from the visitor's saved choice).
   - /assets/ is served `immutable` for a year (vercel.json), so a change to
     any value ships as a NEW FILE (tokens.v2.css), never an edit to this one
     once it is live.
   - `--reserved-*` hues carry meaning (confidence class, record kind, status
     flag). They are never used for decoration, and they are never the only
     signal: every use pairs them with a word and a shape.
   - Token names reuse the portfolio's existing custom properties (ADR 0001).
   ========================================================================== */

/* ------------------------------------------------ theme-independent tokens */
:root {
  /* Brand constants. Decorative use only (fills, gradients, glows); never
     text on a light surface. Text-safe variants are per theme, below. */
  --accent: #7c5cff;          /* violet  */
  --accent-2: #4f8cff;        /* blue    */
  --accent-solid: #6a48f5;    /* violet surface under white text (5.44:1) */
  --grad: linear-gradient(115deg, #7c5cff 0%, #4f8cff 48%, #3ddad7 100%);
  --grad-soft: linear-gradient(115deg, rgba(124, 92, 255, .16), rgba(61, 218, 215, .12));

  /* Families. "… Fallback" names are metric-adjusted local faces that
     fonts.v1.css will declare (added with the /learn page template; see
     docs/design-system.md, "Fonts"). Until then they simply do not match
     and the next family in the stack is used. */
  --font-sans: "Inter", "Inter Fallback", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-display: "Space Grotesk", "Space Grotesk Fallback", "Inter", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Type scale: 17px reading body, ratio ~1.2 below the h3, fluid above it. */
  --step--2: .75rem;                                         /* 12  mono labels, badges, units   */
  --step--1: .875rem;                                        /* 14  meta, captions, evidence     */
  --step-0: 1.0625rem;                                       /* 17  body copy                     */
  --step-1: 1.25rem;                                         /* 20  h4, lead paragraph            */
  --step-2: 1.5rem;                                          /* 24  h3                            */
  --step-3: clamp(1.75rem, 1.45rem + 1.1vw, 2.125rem);       /* 28-34  h2                         */
  --step-4: clamp(2.125rem, 1.6rem + 2.1vw, 3rem);           /* 34-48  h1 (section title)         */
  --step-5: clamp(2.75rem, 1.9rem + 3.5vw, 4.25rem);         /* 44-68  display (hub page only)    */

  --lh-display: 1.02;
  --lh-heading: 1.15;
  --lh-dense: 1.45;           /* tables, badges, evidence metadata */
  --lh-body: 1.65;

  --tracking-display: -.035em;
  --tracking-heading: -.02em;
  --tracking-label: .08em;    /* uppercase mono labels */

  --measure: 68ch;            /* prose column                        */
  --measure-narrow: 52ch;     /* captions, margin notes, callouts    */
  --measure-wide: 88ch;       /* tables and figures may run to this  */

  /* Spacing: 4px base. */
  --space-1: .25rem;   /*   4 */
  --space-2: .5rem;    /*   8 */
  --space-3: .75rem;   /*  12 */
  --space-4: 1rem;     /*  16 */
  --space-5: 1.5rem;   /*  24 */
  --space-6: 2rem;     /*  32 */
  --space-7: 3rem;     /*  48 */
  --space-8: 4rem;     /*  64 */
  --space-9: 6rem;     /*  96 */
  --space-10: 8rem;    /* 128 */

  /* Radii. /learn uses the two tight radii; the four large ones are the
     portfolio's and stay there. */
  --radius-2xs: 2px;   /* badges, flags, table cells  */
  --radius-xs: 4px;    /* inputs, panels, evidence    */
  --radius-sm: 10px;
  --radius: 16px;
  --radius-lg: 24px;
  --radius-xl: 32px;

  /* Layout */
  --shell: 1180px;
  --gutter: clamp(16px, 5vw, 48px);
  --rail-w: 15rem;     /* /learn section rail (>= 64rem viewport)   */
  --margin-w: 17rem;   /* /learn margin notes (>= 80rem viewport)   */

  /* Motion. /learn uses --dur-1..3 with --ease-out only; --ease-spring
     and --dur are the portfolio's. */
  --ease: cubic-bezier(.22, .61, .36, 1);
  --ease-out: cubic-bezier(.2, .7, .2, 1);
  --ease-spring: cubic-bezier(.34, 1.42, .64, 1);
  --dur: .5s;
  --dur-1: 120ms;      /* state feedback: hover, press, check  */
  --dur-2: 200ms;      /* disclosure: evidence panel, filter   */
  --dur-3: 320ms;      /* explanatory transition (step to step) */

  --focus-width: 2px;
  --focus-offset: 2px;

  --z-sticky: 20;
  --z-overlay: 100;
  --z-skip: 200;
}

/* -------------------------------------------- dark theme (the default) */
:root,
:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #08090f;              /* page                          */
  --bg-2: #0b0d16;            /* raised plate: cards, panels   */
  --bg-3: #101324;            /* inset: evidence, code, tables */
  --surface: rgba(255, 255, 255, .045);
  --surface-2: rgba(255, 255, 255, .075);
  --border: rgba(255, 255, 255, .09);        /* decorative rule (no contrast duty) */
  --border-strong: rgba(255, 255, 255, .18);
  --border-control: #6b7390;                 /* input, checkbox outlines: >= 3:1   */

  --text: #eef0f7;
  --text-dim: #b9c0d4;
  --muted: #8e97af;

  --accent-3: #3ddad7;        /* teal, text-safe in this theme */
  --link: #a594ff;
  --focus-ring: #3ddad7;
  --grad-text: var(--grad);

  --shadow: 0 24px 60px -20px rgba(0, 0, 0, .8);
  --shadow-glow: 0 0 0 1px rgba(124, 92, 255, .22), 0 18px 50px -18px rgba(124, 92, 255, .55);
  --elev-1: inset 0 0 0 1px var(--border);
  --elev-2: 0 1px 0 var(--border), 0 12px 28px -16px rgba(0, 0, 0, .9);
  --elev-3: var(--shadow);

  /* Reserved hues. ink = text; fill = icon, border, bar (>= 3:1 on every
     page background); wash = badge background. */
  --reserved-verified-ink: #94d187;      --reserved-verified-fill: #4ba435;      --reserved-verified-wash: #122015;
  --reserved-inferred-ink: #dbb96f;      --reserved-inferred-fill: #af8500;      --reserved-inferred-wash: #211c0d;
  --reserved-assumed-ink: #fda674;       --reserved-assumed-fill: #da6601;       --reserved-assumed-wash: #28170d;
  --reserved-gap-ink: #f59ecf;           --reserved-gap-fill: #d15aa3;           --reserved-gap-wash: #261525;
  --reserved-contradiction-ink: #ffa09c; --reserved-contradiction-fill: #ed4952; --reserved-contradiction-wash: #2a1319;
  --reserved-cell-ink: #b4c697;          --reserved-cell-fill: #7f9654;          --reserved-cell-wash: #1a1e19;
  --reserved-design-ink: #d2ade9;        --reserved-design-fill: #a673c5;        --reserved-design-wash: #20192a;
  --reserved-recommend-ink: #d6b7a2;     --reserved-recommend-fill: #ac8266;     --reserved-recommend-wash: #211b1c;
}

/* ------------------------------------------------------------ light theme
   Declared twice with identical bodies: once for "system prefers light and
   no override", once for the explicit override. The contrast script in
   docs/design-system.md (Appendix A) fails if the two copies differ. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    color-scheme: light;

    --bg: #f6f7fc;
    --bg-2: #ffffff;
    --bg-3: #eef0f9;
    --surface: rgba(255, 255, 255, .72);
    --surface-2: rgba(255, 255, 255, .92);
    --border: rgba(12, 16, 40, .1);
    --border-strong: rgba(12, 16, 40, .2);
    --border-control: #7a819c;

    --text: #0d1024;
    --text-dim: #3b4360;
    --muted: #626b8a;

    --accent-3: #0a6f6d;
    --link: #5a3de6;
    --focus-ring: #0a6f6d;
    --grad-text: linear-gradient(115deg, #6a48f5 0%, #2c66d8 48%, #0a6f6d 100%);

    --shadow: 0 24px 60px -26px rgba(16, 22, 60, .3);
    --shadow-glow: 0 0 0 1px rgba(124, 92, 255, .18), 0 18px 44px -20px rgba(124, 92, 255, .45);
    --elev-1: inset 0 0 0 1px var(--border);
    --elev-2: 0 1px 0 var(--border), 0 12px 28px -18px rgba(16, 22, 60, .35);
    --elev-3: var(--shadow);

    --reserved-verified-ink: #227603;      --reserved-verified-fill: #3c9625;      --reserved-verified-wash: #eaf3e7;
    --reserved-inferred-ink: #806104;      --reserved-inferred-fill: #a47d08;      --reserved-inferred-wash: #f5f1e4;
    --reserved-assumed-ink: #a54c01;       --reserved-assumed-fill: #d36301;       --reserved-assumed-wash: #faeee3;
    --reserved-gap-ink: #ad3983;           --reserved-gap-fill: #cd57a0;           --reserved-gap-wash: #faedf5;
    --reserved-contradiction-ink: #c51b32; --reserved-contradiction-fill: #eb4750; --reserved-contradiction-wash: #fdebec;
    --reserved-cell-ink: #586e2c;          --reserved-cell-fill: #738a48;          --reserved-cell-wash: #f0f2eb;
    --reserved-design-ink: #8351a0;        --reserved-design-fill: #a26fc0;        --reserved-design-wash: #f5eff8;
    --reserved-recommend-ink: #855d43;     --reserved-recommend-fill: #a47b5f;     --reserved-recommend-wash: #f5f0ed;
  }
}

:root[data-theme="light"] {
  color-scheme: light;

  --bg: #f6f7fc;
  --bg-2: #ffffff;
  --bg-3: #eef0f9;
  --surface: rgba(255, 255, 255, .72);
  --surface-2: rgba(255, 255, 255, .92);
  --border: rgba(12, 16, 40, .1);
  --border-strong: rgba(12, 16, 40, .2);
  --border-control: #7a819c;

  --text: #0d1024;
  --text-dim: #3b4360;
  --muted: #626b8a;

  --accent-3: #0a6f6d;
  --link: #5a3de6;
  --focus-ring: #0a6f6d;
  --grad-text: linear-gradient(115deg, #6a48f5 0%, #2c66d8 48%, #0a6f6d 100%);

  --shadow: 0 24px 60px -26px rgba(16, 22, 60, .3);
  --shadow-glow: 0 0 0 1px rgba(124, 92, 255, .18), 0 18px 44px -20px rgba(124, 92, 255, .45);
  --elev-1: inset 0 0 0 1px var(--border);
  --elev-2: 0 1px 0 var(--border), 0 12px 28px -18px rgba(16, 22, 60, .35);
  --elev-3: var(--shadow);

  --reserved-verified-ink: #227603;      --reserved-verified-fill: #3c9625;      --reserved-verified-wash: #eaf3e7;
  --reserved-inferred-ink: #806104;      --reserved-inferred-fill: #a47d08;      --reserved-inferred-wash: #f5f1e4;
  --reserved-assumed-ink: #a54c01;       --reserved-assumed-fill: #d36301;       --reserved-assumed-wash: #faeee3;
  --reserved-gap-ink: #ad3983;           --reserved-gap-fill: #cd57a0;           --reserved-gap-wash: #faedf5;
  --reserved-contradiction-ink: #c51b32; --reserved-contradiction-fill: #eb4750; --reserved-contradiction-wash: #fdebec;
  --reserved-cell-ink: #586e2c;          --reserved-cell-fill: #738a48;          --reserved-cell-wash: #f0f2eb;
  --reserved-design-ink: #8351a0;        --reserved-design-fill: #a26fc0;        --reserved-design-wash: #f5eff8;
  --reserved-recommend-ink: #855d43;     --reserved-recommend-fill: #a47b5f;     --reserved-recommend-wash: #f5f0ed;
}

/* -------------------------------------------------------- reduced motion
   A media query, so it applies live when the OS setting changes. Durations
   collapse to near zero (not 0, so transitionend still fires for code that
   waits on it). Explanatory animation that carries meaning must also offer
   a stepped, static equivalent (docs/design-system.md, "Motion"). */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur: .01ms;
    --dur-1: .01ms;
    --dur-2: .01ms;
    --dur-3: .01ms;
  }
}

/* ------------------------------------------------ forced colours (WHCM)
   System colours replace every hue; words and shapes still carry meaning. */
@media (forced-colors: active) {
  :root {
    --focus-ring: Highlight;
    --border-control: CanvasText;
  }
}
