/* Folio v2 · design system for spencercav.com/p · source ~/projects/design-system (edit src/, run build.py) (tokens and fonts only) */
/* ==========================================================================
   Folio, design system v2 for Spencer's private pages.
   Tokens: the single place to change type, colour, spacing and shape.
   Light only (Spencer, Sep 29 2026: never dark mode). Every page that links
   /p/_kit/ds/ds.css picks up a change here after `python3 build.py`.
   ========================================================================== */

:root {
  color-scheme: light;

  /* ---- Type families (self-hosted, OFL) ---------------------------------- */
  --font-serif: "Newsreader", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --font-sans: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* ---- Type scale: a 1.2 minor-third on phone, stretching on desktop ------ */
  --text-2xs: 0.6875rem;                              /* 11px  mono labels   */
  --text-xs: 0.78125rem;                              /* 12.5  captions      */
  --text-sm: 0.875rem;                                /* 14    UI secondary  */
  --text-base: 1rem;                                  /* 16    UI body       */
  --text-read: clamp(1.0625rem, 0.98rem + 0.35vw, 1.1875rem); /* 17-19 prose */
  --text-lg: 1.25rem;                                 /* 20    lede, h3      */
  --text-xl: clamp(1.375rem, 1.2rem + 0.7vw, 1.75rem);   /* 22-28 h2        */
  --text-2xl: clamp(1.75rem, 1.4rem + 1.6vw, 2.625rem);  /* 28-42 page title */
  --text-3xl: clamp(2.25rem, 1.6rem + 3vw, 4rem);        /* 36-64 display    */
  --text-hero: clamp(2.75rem, 2rem + 3vw, 4.5rem);       /* hero figure      */

  --leading-tight: 1.08;
  --leading-snug: 1.3;
  --leading-ui: 1.5;
  --leading-read: 1.62;
  --tracking-display: -0.022em;
  --tracking-label: 0.09em;

  /* ---- Colour: paper, ink, one accent, one signal ------------------------ */
  --paper: #fbfaf7;          /* page plane                                   */
  --paper-sunk: #f3f1eb;     /* wells, table heads, code                     */
  --surface: #ffffff;        /* raised panels (decisions, inputs)            */
  --ink: #1b1a17;            /* primary text                                 */
  --ink-2: #45433e;          /* secondary text                               */
  --muted: #6d6a63;          /* meta, captions (4.9:1 on paper)              */
  --faint: #9a968d;          /* disabled, placeholder                        */
  --rule: #e4e0d6;           /* hairlines                                    */
  --rule-strong: #c9c3b6;    /* baselines, input borders                     */

  --accent: #1f5a48;         /* deep ink green: links, primary action        */
  --accent-ink: #174536;     /* pressed/hover                                */
  --accent-wash: #e8f0ec;    /* selected backgrounds                         */
  --signal: #b83f27;         /* vermilion: needs you, overdue, now-marker    */
  --signal-wash: #fbece7;

  /* State (decisions, status). Always paired with a word or glyph. */
  --ok: #2c6e47;     --ok-wash: #e6f1ea;
  --hold: #9a5d0c;   --hold-wash: #f8eedb;
  --no: #a8352a;     --no-wash: #f8e5e1;
  --info: var(--accent); --info-wash: var(--accent-wash);

  /* ---- Data colour (dataviz method; validated on #fbfaf7, Sep 30) --------
     Drawn from the system: green, blue, vermilion, ochre first. Order is
     fixed, never cycled. Adjacent pairs pass CVD >= 10 and normal >= 16;
     the first three also pass all-pairs (scatter, small multiples: cap at
     three). Slot 4 (ochre) is under 3:1, so charts carry direct labels or a
     table view. Re-run the dataviz validator after any change here.     */
  --series-1: #1a8a66; --series-2: #3d6fc4; --series-3: #d4582e; --series-4: #cf9c1c;
  --series-5: #a4579b; --series-6: #5f8f22; --series-7: #6450b8; --series-8: #c7434b;
  --seq-100: #cde2fb; --seq-200: #9ec5f4; --seq-300: #6da7ec; --seq-400: #3987e5;
  --seq-500: #256abf; --seq-600: #184f95; --seq-700: #0d366b;
  --div-neg: #e34948; --div-mid: #f0efec; --div-pos: #2a78d6;
  --status-good: #0ca30c; --status-warning: #fab219; --status-serious: #ec835a; --status-critical: #d03b3b;
  --grid: #e7e4dc; --axis: #c3c2b7; --chart-surface: var(--paper);

  /* ---- Space: 4px base --------------------------------------------------- */
  --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px; --s-5: 24px;
  --s-6: 32px; --s-7: 48px; --s-8: 64px; --s-9: 96px;
  --gutter: clamp(18px, 4vw, 40px);

  /* ---- Measure and page widths ------------------------------------------- */
  --w-text: 42rem;           /* ~68ch reading column                          */
  --w-wide: 66rem;           /* tables, dashboards, charts                    */
  --w-full: 78rem;           /* hub, trackers                                 */

  /* ---- Shape and depth: hairlines over shadows --------------------------- */
  --radius-sm: 4px; --radius: 8px; --radius-lg: 12px; --radius-pill: 999px;
  --shadow-1: 0 1px 0 rgba(27, 26, 23, 0.04);
  --shadow-2: 0 1px 2px rgba(27, 26, 23, 0.05), 0 8px 24px -12px rgba(27, 26, 23, 0.14);
  --focus: 0 0 0 3px rgba(31, 90, 72, 0.28);

  /* ---- Motion: only for state change -------------------------------------- */
  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --dur: 160ms;

  --tap: 44px;               /* minimum touch target                          */
}

/* v1 kit names, so page-level styles written against the old kit adopt v2 values.
   New work uses the names above. */
:root {
  --bg: var(--paper); --card: var(--surface); --line: var(--rule);
  --accent-soft: var(--accent-wash); --ok-soft: var(--ok-wash); --hold-soft: var(--hold-wash); --no-soft: var(--no-wash);
  --shadow: var(--shadow-1); --serif: var(--font-serif); --sans: var(--font-sans);
}

/* Self-hosted faces. URLs are relative to dist/ds.css, so the fonts travel with it. */
@font-face { font-family: "Newsreader"; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url(fonts/newsreader-latin-opsz-normal.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: "Newsreader"; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url(fonts/newsreader-latin-ext-opsz-normal.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Newsreader"; font-style: italic; font-weight: 200 800; font-display: swap;
  src: url(fonts/newsreader-latin-opsz-italic.woff2) format("woff2"); }

@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-400-normal.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: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-ext-400-normal.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1E9F, U+1EF2-1EFF, U+20A0-20AB, U+20AD-20C0, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "IBM Plex Sans"; font-style: italic; font-weight: 400; font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-400-italic.woff2) format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500; font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-500-normal.woff2) format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600 700; font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-600-normal.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: "IBM Plex Sans"; font-style: normal; font-weight: 600 700; font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-ext-600-normal.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1E00-1E9F, U+1EF2-1EFF, U+20A0-20AB, U+20AD-20C0, U+2C60-2C7F, U+A720-A7FF; }

@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-400-normal.woff2) format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500 700; font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-500-normal.woff2) format("woff2"); }
