/* ==========================================================================
   tokens.css — the single source of visual truth
   Every colour, size, and space used anywhere in this site is declared here.
   Nothing outside this file may hard-code a hex value, a font size, or a
   spacing value. A rebrand is a change to this file alone.
   ========================================================================== */

/* --- Typefaces ---------------------------------------------------------- */
/* Self-hosted, latin subset only, so the site makes zero third-party
   requests. See assets/fonts/README.md for provenance and licensing. */

@font-face {
  font-family: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/instrument-serif-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/inter-latin-var.woff2') format('woff2-variations');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* --- Font stacks ------------------------------------------------------ */
  --font-display: 'Instrument Serif', 'Iowan Old Style', 'Palatino Linotype',
    Palatino, Georgia, 'Times New Roman', serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
    'Helvetica Neue', Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas,
    'Liberation Mono', monospace;

  /* --- Type scale -------------------------------------------------------
     Fluid between a 360px and a 1200px viewport. Body never drops below
     17px, and the display step is large enough to carry a hero on its own. */
  --step--1: clamp(0.875rem, 0.85rem + 0.12vw, 0.9375rem); /* 14 → 15 captions   */
  --step-0:  clamp(1.0625rem, 1.03rem + 0.18vw, 1.1875rem); /* 17 → 19 body       */
  --step-1:  clamp(1.25rem, 1.18rem + 0.35vw, 1.5rem);      /* 20 → 24 lead       */
  --step-2:  clamp(1.5rem, 1.36rem + 0.7vw, 2rem);          /* 24 → 32 h3         */
  --step-3:  clamp(1.875rem, 1.62rem + 1.25vw, 2.75rem);    /* 30 → 44 h2         */
  --step-4:  clamp(2.5rem, 1.9rem + 3vw, 4.5rem);           /* 40 → 72 display    */

  --leading-tight: 1.1;
  --leading-snug: 1.3;
  --leading-normal: 1.65;

  --tracking-tight: -0.02em;
  --tracking-normal: 0;
  --tracking-wide: 0.08em;

  --weight-normal: 400;
  --weight-medium: 500;
  --weight-semibold: 600;

  /* --- Spacing scale — 4px base ---------------------------------------- */
  --space-3xs: 0.25rem;  /*  4 */
  --space-2xs: 0.5rem;   /*  8 */
  --space-xs:  0.75rem;  /* 12 */
  --space-s:   1rem;     /* 16 */
  --space-m:   1.5rem;   /* 24 */
  --space-l:   2rem;     /* 32 */
  --space-xl:  3rem;     /* 48 */
  --space-2xl: 4rem;     /* 64 */
  --space-3xl: 6rem;     /* 96 */

  /* Vertical rhythm between major page sections, fluid. */
  --space-section: clamp(3.5rem, 2rem + 7vw, 7rem);

  /* --- Layout ----------------------------------------------------------- */
  --measure: 68ch;              /* comfortable reading width  */
  --width-content: 44rem;       /* prose column               */
  --width-wide: 68rem;          /* full section width         */
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --header-height: 4rem;

  /* --- Radius, border, elevation ---------------------------------------- */
  --radius-s: 0.25rem;
  --radius-m: 0.5rem;
  --radius-l: 0.875rem;
  --radius-pill: 999px;
  --border-width: 1px;

  /* --- Motion ------------------------------------------------------------
     Nothing here exceeds 250ms; base.css disables all of it under
     prefers-reduced-motion. */
  --duration-fast: 120ms;
  --duration-base: 200ms;
  --duration-slow: 250ms;
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);

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

  /* --- Light palette (default) ------------------------------------------
     Every text/background pair below is verified against WCAG 2.1 AA by
     scripts/check-contrast.py. Do not edit a value without re-running it. */
  color-scheme: light;

  --surface: #fbfaf8;           /* page background, warm off-white */
  --surface-raised: #ffffff;    /* cards                           */
  --surface-sunken: #f2efea;    /* chips, code, subtle fills       */
  --surface-inverse: #16181c;

  --text: #16181c;              /* 17.0:1 on --surface             */
  --text-muted: #565b63;        /*  6.6:1 on --surface             */
  --text-inverse: #fbfaf8;

  --border: #e2ded7;
  --border-strong: #8b857c;    /*  3.4:1 on --surface (WCAG 1.4.11) */

  --accent: #0b5e55;            /*  7.3:1 on --surface             */
  --accent-hover: #084841;
  --accent-contrast: #ffffff;   /*  7.7:1 on --accent              */
  --accent-soft: #e4f0ed;
  --accent-soft-text: #084841;  /*  8.9:1 on --accent-soft         */

  --shadow-s: 0 1px 2px rgb(22 24 28 / 6%), 0 1px 3px rgb(22 24 28 / 4%);
  --shadow-m: 0 2px 4px rgb(22 24 28 / 5%), 0 8px 24px rgb(22 24 28 / 7%);

  --selection-bg: #cfe6e1;
  --selection-text: #0b1f1c;
}

/* --- Dark palette --------------------------------------------------------
   Applied when the visitor's system prefers dark and they have not chosen
   light explicitly, or when they toggle dark. assets/js/theme.js sets
   data-theme on <html> before first paint, so there is no flash. */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    color-scheme: dark;

    --surface: #101214;
    --surface-raised: #171a1d;
    --surface-sunken: #0a0c0d;
    --surface-inverse: #ecebe7;

    --text: #ecebe7;            /* 15.7:1 on --surface */
    --text-muted: #a6acb4;      /*  8.2:1 on --surface */
    --text-inverse: #101214;

    --border: #272b2f;
    --border-strong: #6a7178;   /*  3.2:1 on --surface (WCAG 1.4.11) */

    --accent: #6fdcc9;          /* 11.4:1 on --surface */
    --accent-hover: #93e8d9;
    --accent-contrast: #06211d;
    --accent-soft: #14312c;
    --accent-soft-text: #8fe5d5;

    --shadow-s: 0 1px 2px rgb(0 0 0 / 40%), 0 1px 3px rgb(0 0 0 / 30%);
    --shadow-m: 0 2px 4px rgb(0 0 0 / 35%), 0 8px 24px rgb(0 0 0 / 45%);

    --selection-bg: #1d4a43;
    --selection-text: #eafaf6;
  }
}

:root[data-theme='dark'] {
  color-scheme: dark;

  --surface: #101214;
  --surface-raised: #171a1d;
  --surface-sunken: #0a0c0d;
  --surface-inverse: #ecebe7;

  --text: #ecebe7;
  --text-muted: #a6acb4;
  --text-inverse: #101214;

  --border: #272b2f;
  --border-strong: #6a7178;

  --accent: #6fdcc9;
  --accent-hover: #93e8d9;
  --accent-contrast: #06211d;
  --accent-soft: #14312c;
  --accent-soft-text: #8fe5d5;

  --shadow-s: 0 1px 2px rgb(0 0 0 / 40%), 0 1px 3px rgb(0 0 0 / 30%);
  --shadow-m: 0 2px 4px rgb(0 0 0 / 35%), 0 8px 24px rgb(0 0 0 / 45%);

  --selection-bg: #1d4a43;
  --selection-text: #eafaf6;
}
