/* --- 00-config.css --- */
/* =============================================================================
   00-CONFIG
   The only file you edit per project. Everything downstream derives from here.
   Layer order is declared once, here, and never changes.
   ========================================================================== */

@layer config, tokens, reset, base, layouts, components, utilities;

@layer config {
  :root {
    /* @private:start ------------------------------------------------------
       Brand hue + chroma. Lightness stops live in 01-tokens.css. These are
       inputs to the palette, never referenced by a component.
       -------------------------------------------------------------------- */
    --primary-h: 191.9;
    --primary-c: 0.094;

    --secondary-h: 30;
    --secondary-c: 0.040;

    --accent-h: 65;
    --accent-c: 0.140;

    /* Neutrals carry a trace of the primary hue so greys feel part of the
       palette rather than dropped in from a different system. */
    --neutral-h: 210;
    --neutral-c: 0.007;

    /* @private:end */

    /* --- Typefaces --------------------------------------------------------
       These are placeholder aliases. Replace both the names here and the
       @font-face blocks in 05-fonts.css with the project's actual typeface.
       rename.sh deliberately leaves them alone. */
    --font-display: "Blueprint Display", system-ui, sans-serif;
    --font-body: "Blueprint Body", system-ui, sans-serif;
    --font-mono: ui-monospace, "SFMono-Regular", monospace;

    /* --- Measure ---------------------------------------------------------- */
    --width-content: 85.375rem;  /* 1366px — the main rail                    */
    --width-narrow: 56.25rem;    /*  900px — prose and forms                  */
    --width-wide: 100rem;        /* 1600px — full-bleed media sections        */
    --measure: 68ch;             /* line length ceiling for body copy         */

    /* --- Chrome ----------------------------------------------------------- */
    --header-height: 4rem;
    --radius-s: 0.25rem;
    --radius-m: 0.5rem;
    --radius-l: 1rem;
    --radius-pill: 100vmax;
  }
}

/* --- 01-tokens.css --- */
/* =============================================================================
   01-TOKENS
   Derived from 00-config.css. Do not hand-edit values here — change the config.
   Fluid values interpolate across a 375px -> 1440px viewport.
   ========================================================================== */

@layer tokens {
  :root {
    /* @private:start ------------------------------------------------------
       PALETTE. Five lightness stops per brand colour. Hue and chroma come from
       config, so a rebrand is three numbers, not a find-and-replace.

       Nothing outside this file may reference a palette token. Components bind
       to the semantic tier below. tools/check-tokens.mjs enforces this.
       -------------------------------------------------------------------- */
    --primary-ultra-light: oklch(96% calc(var(--primary-c) * 0.25) var(--primary-h));
    --primary-light:       oklch(85% calc(var(--primary-c) * 0.6)  var(--primary-h));
    --primary:             oklch(54.8% var(--primary-c)            var(--primary-h));
    --primary-dark:        oklch(42% calc(var(--primary-c) * 0.95) var(--primary-h));
    --primary-ultra-dark:  oklch(26% calc(var(--primary-c) * 0.7)  var(--primary-h));

    --secondary-ultra-light: oklch(97% calc(var(--secondary-c) * 0.4) var(--secondary-h));
    --secondary-light:       oklch(92.5% var(--secondary-c)           var(--secondary-h));
    --secondary:             oklch(80% calc(var(--secondary-c) * 1.6) var(--secondary-h));
    --secondary-dark:        oklch(55% calc(var(--secondary-c) * 2.2) var(--secondary-h));
    --secondary-ultra-dark:  oklch(32% calc(var(--secondary-c) * 1.8) var(--secondary-h));

    --accent-light:      oklch(82% calc(var(--accent-c) * 0.55) var(--accent-h));
    --accent:            oklch(62% var(--accent-c)              var(--accent-h));
    --accent-dark:       oklch(46% calc(var(--accent-c) * 0.9)  var(--accent-h));

    --neutral-100: oklch(99%   calc(var(--neutral-c) * 0.3) var(--neutral-h));
    --neutral-200: oklch(96%   var(--neutral-c)             var(--neutral-h));
    --neutral-300: oklch(91%   var(--neutral-c)             var(--neutral-h));
    --neutral-400: oklch(78%   var(--neutral-c)             var(--neutral-h));
    --neutral-500: oklch(62%   var(--neutral-c)             var(--neutral-h));
    --neutral-600: oklch(48%   var(--neutral-c)             var(--neutral-h));
    --neutral-700: oklch(36%   var(--neutral-c)             var(--neutral-h));
    --neutral-800: oklch(24%   var(--neutral-c)             var(--neutral-h));
    --neutral-900: oklch(15%   var(--neutral-c)             var(--neutral-h));

    /* Status colours borrow the neutral hue's chroma discipline. */
    --success: oklch(58% 0.130 150);
    --warning: oklch(72% 0.150 75);
    --danger:  oklch(55% 0.180 27);

    /* @private:end */

    /* --- Semantic tokens -------------------------------------------------
       Components bind to these, never to the palette above. Re-point them
       under [data-theme] and every component follows without being touched.
       -------------------------------------------------------------------- */
    --text-main: var(--neutral-900);
    --text-body: var(--neutral-700);
    --text-muted: var(--neutral-500);
    --text-inverse: var(--neutral-100);
    --text-link: var(--primary-dark);
    --text-link-hover: var(--primary-ultra-dark);

    --surface: var(--neutral-100);
    --surface-raised: oklch(100% 0 0);
    --surface-sunken: var(--neutral-200);
    --surface-tinted: var(--primary-ultra-light);
    --surface-inverse: var(--neutral-900);

    --border-subtle: var(--neutral-300);
    --border-default: var(--neutral-400);
    --border-strong: var(--neutral-600);

    --text-accent: var(--primary);
    --text-disabled: var(--neutral-400);

    /* Interactive fills. Everything clickable that carries a background binds
       to these, so a change of button colour is one edit, not eleven. */
    --action-bg: var(--primary);
    --action-bg-hover: var(--primary-dark);
    --action-bg-active: var(--primary-ultra-dark);
    --action-fg: var(--text-inverse);
    --action-border: var(--primary);
    --action-border-hover: var(--primary-dark);

    /* Surface states, for anything that reacts without carrying a fill. */
    --surface-hover: var(--neutral-200);
    --surface-active: var(--neutral-300);
    --surface-selected: var(--primary);
    --surface-selected-fg: var(--text-inverse);
    --surface-disabled: var(--neutral-200);

    --border-accent: var(--primary);
    --border-hover: var(--border-strong);
    --border-focus: var(--primary);
    --border-disabled: var(--neutral-300);

    /* Status. Text, surface and border for each state, so a notice never has
       to derive its own background with color-mix() in a component file. */
    --text-success: oklch(38% 0.110 150);
    --text-warning: oklch(40% 0.110 75);
    --text-danger: oklch(40% 0.150 27);

    --surface-success: color-mix(in oklch, var(--success) 15%, var(--surface));
    --surface-warning: color-mix(in oklch, var(--warning) 18%, var(--surface));
    --surface-danger: color-mix(in oklch, var(--danger) 12%, var(--surface));

    --border-success: var(--success);
    --border-warning: var(--warning);
    --border-danger: var(--danger);

    --focus-ring: var(--accent);
    --focus-ring-width: 3px;
    --focus-ring-offset: 2px;

    --opacity-disabled: 0.5;

    /* Overlays are mixed, not stored as pre-baked alpha variants. */
    --overlay-subtle: color-mix(in oklch, var(--neutral-900) 8%, transparent);
    --overlay-medium: color-mix(in oklch, var(--neutral-900) 45%, transparent);
    --overlay-strong: color-mix(in oklch, var(--neutral-900) 75%, transparent);

    --shadow-s: 0 1px 2px var(--overlay-subtle);
    --shadow-m: 0 2px 4px var(--overlay-subtle), 0 8px 16px -8px var(--overlay-subtle);
    --shadow-l: 0 4px 8px var(--overlay-subtle), 0 24px 48px -16px var(--overlay-subtle);

    /* --- Type scale ------------------------------------------------------ */
    --text-2xs: clamp(0.6944rem, 0.6854rem + 0.0384vw, 0.72rem);
    --text-xs: clamp(0.8333rem, 0.8099rem + 0.1002vw, 0.9rem);
    --text-s: clamp(0.9129rem, 0.88rem + 0.1403vw, 1.0062rem);
    --text-m: clamp(1rem, 0.956rem + 0.1878vw, 1.125rem);
    --text-l: clamp(1.2rem, 1.1274rem + 0.3099vw, 1.4062rem);
    --text-xl: clamp(1.44rem, 1.3281rem + 0.4775vw, 1.7578rem);
    --text-2xl: clamp(1.728rem, 1.5628rem + 0.705vw, 2.1973rem);
    --text-3xl: clamp(2.0736rem, 1.8366rem + 1.0111vw, 2.7466rem);
    --text-4xl: clamp(2.4883rem, 2.1556rem + 1.4196vw, 3.4332rem);
    --text-5xl: clamp(2.986rem, 2.5263rem + 1.9614vw, 4.2915rem);

    --leading-tight: 1.1;
    --leading-snug: 1.25;
    --leading-normal: 1.55;
    --leading-loose: 1.75;

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

    --weight-light: 300;
    --weight-regular: 400;
    --weight-medium: 500;
    --weight-semibold: 600;
    --weight-bold: 700;

    /* --- Space scale ----------------------------------------------------- */
    --space-3xs: clamp(0.25rem, 0.228rem + 0.0939vw, 0.3125rem);
    --space-2xs: clamp(0.5rem, 0.456rem + 0.1878vw, 0.625rem);
    --space-xs: clamp(0.75rem, 0.662rem + 0.3756vw, 1rem);
    --space-s: clamp(1rem, 0.912rem + 0.3756vw, 1.25rem);
    --space-m: clamp(1.5rem, 1.3239rem + 0.7512vw, 2rem);
    --space-l: clamp(2rem, 1.6479rem + 1.5023vw, 3rem);
    --space-xl: clamp(3rem, 2.6479rem + 1.5023vw, 4rem);
    --space-2xl: clamp(4rem, 3.2958rem + 3.0047vw, 6rem);
    --space-3xl: clamp(6rem, 5.2958rem + 3.0047vw, 8rem);

    /* --- Section rhythm -------------------------------------------------- */
    --section-space-xs: clamp(2rem, 1.6479rem + 1.5023vw, 3rem);
    --section-space-s: clamp(3rem, 2.4718rem + 2.2535vw, 4.5rem);
    --section-space-m: clamp(4rem, 3.2958rem + 3.0047vw, 6rem);
    --section-space-l: clamp(5rem, 3.9437rem + 4.507vw, 8rem);
    --section-space-xl: clamp(6rem, 4.5915rem + 6.0094vw, 10rem);
    --section-space-2xl: clamp(8rem, 6.2394rem + 7.5117vw, 13rem);
    --gutter: clamp(1rem, 0.4718rem + 2.2535vw, 2.5rem);

    /* --- Motion ---------------------------------------------------------- */
    --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
    --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
    --duration-fast: 120ms;
    --duration-base: 220ms;
    --duration-slow: 400ms;

    --z-base: 1;
    --z-sticky: 100;
    --z-header: 200;
    --z-drawer: 300;
    --z-modal: 400;
  }

  /* --- Section themes ---------------------------------------------------
     Applied as [data-theme] on .section. Nothing else changes.
     -------------------------------------------------------------------- */
  [data-theme="light"] {
    --surface: var(--neutral-100);
    --surface-raised: oklch(100% 0 0);
  }

  [data-theme="sunken"] {
    --surface: var(--neutral-200);
    --surface-raised: var(--neutral-100);
    --surface-hover: var(--neutral-300);
    --surface-active: var(--neutral-400);
    --border-subtle: var(--neutral-400);
  }

  [data-theme="tinted"] {
    --surface: var(--primary-ultra-light);
    --surface-raised: oklch(100% 0 0);
    --surface-hover: color-mix(in oklch, var(--primary) 10%, var(--surface));
    --border-subtle: var(--primary-light);
  }

  [data-theme="brand"] {
    --surface: var(--primary);
    --surface-raised: var(--primary-dark);
    --text-main: var(--text-inverse);
    --text-body: color-mix(in oklch, var(--text-inverse) 88%, transparent);
    --text-muted: color-mix(in oklch, var(--text-inverse) 70%, transparent);
    --text-link: var(--text-inverse);
    --text-link-hover: var(--secondary-light);
    --text-accent: var(--secondary-light);
    --text-disabled: color-mix(in oklch, var(--text-inverse) 45%, transparent);
    --border-subtle: color-mix(in oklch, var(--text-inverse) 20%, transparent);
    --border-default: color-mix(in oklch, var(--text-inverse) 35%, transparent);
    --border-accent: var(--secondary-light);
    --border-hover: var(--text-inverse);
    --border-focus: var(--secondary-light);
    --border-disabled: color-mix(in oklch, var(--text-inverse) 20%, transparent);
    --focus-ring: var(--secondary-light);

    /* On a brand fill, the action reverses: light chip on dark ground. */
    --action-bg: var(--text-inverse);
    --action-bg-hover: var(--secondary-light);
    --action-bg-active: var(--secondary);
    --action-fg: var(--primary-ultra-dark);
    --action-border: var(--text-inverse);
    --action-border-hover: var(--secondary-light);

    --surface-hover: color-mix(in oklch, var(--text-inverse) 12%, transparent);
    --surface-active: color-mix(in oklch, var(--text-inverse) 20%, transparent);
    --surface-selected: var(--text-inverse);
    --surface-selected-fg: var(--primary-ultra-dark);
    --surface-disabled: color-mix(in oklch, var(--text-inverse) 10%, transparent);
  }

  [data-theme="dark"] {
    --surface: var(--neutral-900);
    --surface-raised: var(--neutral-800);
    --surface-sunken: oklch(10% var(--neutral-c) var(--neutral-h));
    --text-main: var(--neutral-100);
    --text-body: var(--neutral-300);
    --text-muted: var(--neutral-400);
    --text-link: var(--primary-light);
    --text-link-hover: var(--primary-ultra-light);
    --text-accent: var(--primary-light);
    --text-disabled: var(--neutral-600);
    --border-subtle: var(--neutral-800);
    --border-default: var(--neutral-700);
    --border-accent: var(--primary-light);
    --border-hover: var(--neutral-500);
    --border-focus: var(--primary-light);
    --border-disabled: var(--neutral-800);

    --action-bg: var(--primary-light);
    --action-bg-hover: var(--primary-ultra-light);
    --action-bg-active: oklch(100% 0 0);
    --action-fg: var(--neutral-900);
    --action-border: var(--primary-light);
    --action-border-hover: var(--primary-ultra-light);

    --surface-hover: var(--neutral-800);
    --surface-active: var(--neutral-700);
    --surface-selected: var(--primary-light);
    --surface-selected-fg: var(--neutral-900);
    --surface-disabled: var(--neutral-800);

    /* Status text must lighten on a dark ground or it fails contrast. */
    --text-success: oklch(78% 0.130 150);
    --text-warning: oklch(82% 0.130 75);
    --text-danger: oklch(72% 0.150 27);

    --surface-success: color-mix(in oklch, var(--success) 22%, var(--surface));
    --surface-warning: color-mix(in oklch, var(--warning) 22%, var(--surface));
    --surface-danger: color-mix(in oklch, var(--danger) 22%, var(--surface));

    color-scheme: dark;
  }
}

/* --- 02-reset.css --- */
/* =============================================================================
   02-RESET
   Wrapped in :where() so every rule sits at zero specificity. Any class you
   write beats it without !important and without escalation.
   ========================================================================== */

@layer reset {
  *, *::before, *::after { box-sizing: border-box; }

  :where(html) {
    -webkit-text-size-adjust: none;
    text-size-adjust: none;
  }

  :where(body, h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd) {
    margin: 0;
  }

  :where(ul[role="list"], ol[role="list"]) {
    list-style: none;
    padding: 0;
    margin: 0;
  }

  :where(img, picture, video, canvas, svg, iframe) {
    display: block;
    max-inline-size: 100%;
    block-size: auto;
  }

  :where(input, button, textarea, select) {
    font: inherit;
    color: inherit;
  }

  :where(button) { background: none; border: none; }

  :where(p, li, figcaption) { text-wrap: pretty; }
  :where(h1, h2, h3, h4) { text-wrap: balance; }

  :where(table) { border-collapse: collapse; inline-size: 100%; }

  :where(:target) { scroll-margin-block-start: calc(var(--header-height) + var(--space-m)); }

  :where(a):focus-visible,
  :where(button):focus-visible,
  :where(input, select, textarea):focus-visible,
  :where([tabindex]):focus-visible {
    outline: var(--focus-ring-width) solid var(--focus-ring);
    outline-offset: var(--focus-ring-offset);
  }

  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
      scroll-behavior: auto !important;
    }
  }
}

/* --- 03-base.css --- */
/* =============================================================================
   03-BASE
   Element defaults. Also :where()-wrapped — these are starting points, not
   opinions your components have to fight.
   ========================================================================== */

@layer base {
  :where(html) {
    scroll-behavior: smooth;
    color-scheme: light;
  }

  :where(body) {
    font-family: var(--font-body);
    font-size: var(--text-m);
    font-weight: var(--weight-regular);
    line-height: var(--leading-normal);
    color: var(--text-body);
    background-color: var(--surface);
    min-block-size: 100svh;
    -webkit-font-smoothing: antialiased;
  }

  :where(h1, h2, h3, h4, h5, h6) {
    font-family: var(--font-display);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-tight);
    color: var(--text-main);
  }

  :where(h1) { font-size: var(--text-4xl); }
  :where(h2) { font-size: var(--text-3xl); }
  :where(h3) { font-size: var(--text-2xl); }
  :where(h4) { font-size: var(--text-xl); }
  :where(h5) { font-size: var(--text-l); }
  :where(h6) { font-size: var(--text-m); font-weight: var(--weight-semibold); }

  :where(p, li) { max-inline-size: var(--measure); }

  :where(a) {
    color: var(--text-link);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.15em;
    transition: color var(--duration-fast) var(--ease-out);
  }
  :where(a:hover) { color: var(--text-link-hover); }

  :where(strong, b) { font-weight: var(--weight-semibold); color: var(--text-main); }
  :where(small) { font-size: var(--text-xs); }
  :where(code, kbd, samp, pre) { font-family: var(--font-mono); font-size: 0.9em; }

  :where(blockquote) {
    border-inline-start: 2px solid var(--border-accent);
    padding-inline-start: var(--space-s);
    font-size: var(--text-l);
  }

  :where(hr) {
    border: none;
    border-block-start: 1px solid var(--border-subtle);
  }

  :where(th) { text-align: start; font-weight: var(--weight-semibold); color: var(--text-main); }
  :where(th, td) {
    padding: var(--space-xs) var(--space-s);
    border-block-end: 1px solid var(--border-subtle);
  }

  :where(::selection) {
    background-color: var(--surface-selected);
    color: var(--surface-selected-fg);
  }

  /* Screen-reader-only text, revealed on focus for skip links. */
  .visually-hidden:not(:focus):not(:active) {
    clip-path: inset(50%);
    block-size: 1px;
    inline-size: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
  }
}

/* --- 04-layouts.css --- */
/* =============================================================================
   04-LAYOUTS
   Five primitives, each with exactly one job. The discipline is the point:
   if a primitive starts doing two things, the build stops being predictable.

     .section    spacing + background          (never flex, grid or gap)
     .container  width + centring              (never padding, flex or gap)
     .stack      vertical rhythm
     .grid       column layout
     .cluster    inline wrapping group

   Never put container-type on any of them. Give a named component wrapper a
   container-name instead.
   ========================================================================== */

@layer layouts {

  /* --- .section ---------------------------------------------------------
     Full viewport width. Owns the block rhythm and the surface colour.
     Override the rhythm with a modifier, never with a one-off padding.
     -------------------------------------------------------------------- */
  .section {
    --_space: var(--section-space-m);
    padding-block: var(--_space);
    padding-inline: var(--gutter);
    background-color: var(--surface);
    color: var(--text-body);
  }

  .section--xs { --_space: var(--section-space-xs); }
  .section--s  { --_space: var(--section-space-s); }
  .section--l  { --_space: var(--section-space-l); }
  .section--xl { --_space: var(--section-space-xl); }
  .section--2xl { --_space: var(--section-space-2xl); }

  /* Collapse the join where two sections share a surface. */
  .section--flush-top { padding-block-start: 0; }
  .section--flush-bottom { padding-block-end: 0; }

  /* --- .container -------------------------------------------------------
     Width and centring. Nothing else, ever.
     -------------------------------------------------------------------- */
  .container {
    --_width: var(--width-content);
    max-inline-size: var(--_width);
    margin-inline: auto;
  }

  .container--narrow { --_width: var(--width-narrow); }
  .container--wide   { --_width: var(--width-wide); }
  .container--full   { --_width: none; }

  /* --- .stack -----------------------------------------------------------
     Vertical rhythm. Gap only — never margin-top on children.
     -------------------------------------------------------------------- */
  .stack {
    --_gap: var(--space-m);
    display: flex;
    flex-direction: column;
    gap: var(--_gap);
  }

  .stack--3xs { --_gap: var(--space-3xs); }
  .stack--2xs { --_gap: var(--space-2xs); }
  .stack--xs  { --_gap: var(--space-xs); }
  .stack--s   { --_gap: var(--space-s); }
  .stack--l   { --_gap: var(--space-l); }
  .stack--xl  { --_gap: var(--space-xl); }
  .stack--2xl { --_gap: var(--space-2xl); }

  /* --- .grid ------------------------------------------------------------
     Columns and gap. Set the count with --grid-columns on the element or a
     modifier; it collapses on its own below the ideal column width.
     -------------------------------------------------------------------- */
  .grid {
    --_gap: var(--space-m);
    --_columns: 3;
    --_min: 18rem;
    display: grid;
    gap: var(--_gap);
    grid-template-columns: repeat(
      auto-fit,
      minmax(min(var(--_min), 100%), 1fr)
    );
  }

  /* Hard column counts when the design genuinely requires them. */
  .grid--2 { --_columns: 2; grid-template-columns: repeat(var(--_columns), 1fr); }
  .grid--3 { --_columns: 3; grid-template-columns: repeat(var(--_columns), 1fr); }
  .grid--4 { --_columns: 4; grid-template-columns: repeat(var(--_columns), 1fr); }

  @media (width < 60rem) {
    .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); }
  }
  @media (width < 40rem) {
    .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
  }

  .grid--xs  { --_gap: var(--space-xs); }
  .grid--s   { --_gap: var(--space-s); }
  .grid--l   { --_gap: var(--space-l); }
  .grid--xl  { --_gap: var(--space-xl); }

  /* --- .cluster ---------------------------------------------------------
     Things that sit in a row and wrap: tags, button pairs, meta lists.
     -------------------------------------------------------------------- */
  .cluster {
    --_gap: var(--space-xs);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--_gap);
  }

  .cluster--between { justify-content: space-between; }
  .cluster--center  { justify-content: center; }
  .cluster--end     { justify-content: flex-end; }
  .cluster--baseline { align-items: baseline; }
  .cluster--s  { --_gap: var(--space-s); }
  .cluster--m  { --_gap: var(--space-m); }
}

/* --- 05-fonts.css --- */
/* =============================================================================
   05-FONTS
   Self-hosted woff2 only. Deliberately outside @layer: @font-face is a
   registration, not a style, and layering it buys nothing.

   Drop the files into /assets/fonts and adjust the names. Load the weights the
   design actually uses — every extra face is a request and a render delay.
   ========================================================================== */

@font-face {
  font-family: "Blueprint Body";
  src: url("../assets/fonts/body-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Blueprint Body";
  src: url("../assets/fonts/body-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Blueprint Display";
  src: url("../assets/fonts/display-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

/* --- button.css --- */
@layer components {
  /* .btn — one block, three variants, two sizes.
     Binds to the action tier, so changing the button colour on a project is an
     edit in 01-tokens.css and nothing here. Never restyle a button by ID. */
  .btn {
    --_bg: var(--action-bg);
    --_fg: var(--action-fg);
    --_border: var(--action-border);
    --_padding-inline: var(--space-s);
    --_padding-block: var(--space-2xs);

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2xs);
    padding: var(--_padding-block) var(--_padding-inline);
    border: 1px solid var(--_border);
    border-radius: var(--radius-m);
    background-color: var(--_bg);
    color: var(--_fg);
    font-family: var(--font-body);
    font-size: var(--text-s);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-snug);
    text-decoration: none;
    cursor: pointer;
    transition: background-color var(--duration-fast) var(--ease-out),
                border-color var(--duration-fast) var(--ease-out),
                color var(--duration-fast) var(--ease-out);
  }

  .btn:hover {
    --_bg: var(--action-bg-hover);
    --_border: var(--action-border-hover);
  }

  .btn:active { --_bg: var(--action-bg-active); }

  .btn--secondary {
    --_bg: transparent;
    --_fg: var(--text-main);
    --_border: var(--border-default);
  }
  .btn--secondary:hover {
    --_bg: var(--surface-hover);
    --_fg: var(--text-main);
    --_border: var(--border-hover);
  }
  .btn--secondary:active { --_bg: var(--surface-active); }

  .btn--ghost {
    --_bg: transparent;
    --_fg: var(--text-link);
    --_border: transparent;
  }
  .btn--ghost:hover {
    --_bg: var(--surface-hover);
    --_fg: var(--text-link-hover);
    --_border: transparent;
  }

  .btn--s { --_padding-inline: var(--space-xs); font-size: var(--text-xs); }
  .btn--l { --_padding-inline: var(--space-m); --_padding-block: var(--space-xs); font-size: var(--text-m); }

  /* Disabled is a colour state, not an opacity trick: opacity would fade the
     focus ring too, and half-opacity text fails contrast at small sizes. */
  .btn[aria-disabled="true"],
  .btn:disabled {
    --_bg: var(--surface-disabled);
    --_fg: var(--text-disabled);
    --_border: var(--border-disabled);
    pointer-events: none;
  }
}

/* --- card.css --- */
@layer components {
  /* .card — the container-query reference for card-internal layout. This is a
     named component wrapper, which is the only place container-type belongs. */
  .card {
    container-type: inline-size;
    container-name: card;

    display: flex;
    flex-direction: column;
    gap: var(--space-xs);
    padding: var(--space-s);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-m);
    background-color: var(--surface-raised);
    block-size: 100%;
  }

  .card__media {
    margin: calc(var(--space-s) * -1) calc(var(--space-s) * -1) 0;
    border-start-start-radius: var(--radius-m);
    border-start-end-radius: var(--radius-m);
    overflow: hidden;
  }

  .card__image {
    inline-size: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
  }

  .card__eyebrow {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wide);
    color: var(--text-accent);
  }

  .card__title {
    font-size: var(--text-l);
    font-weight: var(--weight-semibold);
    line-height: var(--leading-snug);
    color: var(--text-main);
  }

  .card__title a {
    color: inherit;
    text-decoration: none;
  }

  /* Whole card clickable, title still the accessible name. */
  .card__title a::after {
    content: "";
    position: absolute;
    inset: 0;
  }

  .card__summary {
    font-size: var(--text-s);
    color: var(--text-body);
    max-inline-size: none;
  }

  .card__meta {
    margin-block-start: auto;
    font-size: var(--text-xs);
    color: var(--text-muted);
  }

  .card--linked { position: relative; }
  .card--linked:hover { border-color: var(--border-default); }

  @container card (width > 30rem) {
    .card__title { font-size: var(--text-xl); }
  }
}

/* --- form.css --- */
@layer components {
  .field {
    display: flex;
    flex-direction: column;
    gap: var(--space-3xs);
  }

  .field__label {
    font-size: var(--text-s);
    font-weight: var(--weight-medium);
    color: var(--text-main);
  }

  .field__control {
    padding: var(--space-2xs) var(--space-xs);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-s);
    background-color: var(--surface-raised);
    color: var(--text-main);
    inline-size: 100%;
  }

  .field__control:hover { border-color: var(--border-hover); }
  .field__control:focus { border-color: var(--border-focus); }

  .field__control:disabled {
    background-color: var(--surface-disabled);
    border-color: var(--border-disabled);
    color: var(--text-disabled);
  }

  .field__hint { font-size: var(--text-xs); color: var(--text-muted); }
  .field__error { font-size: var(--text-xs); color: var(--text-danger); }
  .field[data-invalid="true"] .field__control { border-color: var(--border-danger); }

  /* Honeypot. Off-screen rather than display:none so bots still fill it. */
  .field--trap {
    position: absolute;
    inset-inline-start: -9999px;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
  }

  .form__notice {
    padding: var(--space-xs) var(--space-s);
    border-inline-start: 3px solid currentcolor;
    border-radius: var(--radius-s);
    font-size: var(--text-s);
  }

  .form__notice--success {
    background-color: var(--surface-success);
    border-color: var(--border-success);
    color: var(--text-success);
  }

  .form__notice--error {
    background-color: var(--surface-danger);
    border-color: var(--border-danger);
    color: var(--text-danger);
  }

  .form__notice--warning {
    background-color: var(--surface-warning);
    border-color: var(--border-warning);
    color: var(--text-warning);
  }
}

/* --- page-banner.css --- */
@layer components {
  .page-banner {
    position: relative;
    isolation: isolate;
  }

  /* Only paints when --_banner-image is set on the element. */
  .page-banner[style*="--_banner-image"]::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-image: var(--_banner-image);
    background-size: cover;
    background-position: center;
  }

  .page-banner[style*="--_banner-image"]::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-color: var(--overlay-strong);
  }

  .page-banner__text {
    font-size: var(--text-l);
    color: var(--text-body);
  }

  .breadcrumbs {
    font-size: var(--text-xs);
    color: var(--text-muted);
  }

  .breadcrumbs ol { margin: 0; padding: 0; list-style: none; }
  .breadcrumbs a { color: inherit; text-decoration: none; }
  .breadcrumbs a:hover { text-decoration: underline; }

  .breadcrumbs li + li::before {
    content: "/";
    margin-inline-end: var(--space-xs);
    color: var(--text-muted);
  }
}

/* --- pagination.css --- */
@layer components {
  .pagination {
    margin-block-start: var(--space-l);
  }

  .pagination .nav-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2xs);
  }

  .pagination .page-numbers {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-inline-size: 2.5rem;
    padding: var(--space-3xs) var(--space-2xs);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-s);
    font-size: var(--text-s);
    color: var(--text-body);
    text-decoration: none;
  }

  .pagination .page-numbers:hover {
    background-color: var(--surface-hover);
    border-color: var(--border-hover);
    color: var(--text-main);
  }

  .pagination .page-numbers.current {
    background-color: var(--surface-selected);
    border-color: var(--surface-selected);
    color: var(--surface-selected-fg);
  }

  .pagination .page-numbers.dots { border-color: transparent; }
}

/* --- prose.css --- */
@layer components {
  /* .prose — the only place where editor-authored HTML is styled. Everything
     else in the theme is a component with its own class. */
  .prose > * + * { margin-block-start: 0; }

  .prose h2 { font-size: var(--text-2xl); margin-block-start: var(--space-m); }
  .prose h3 { font-size: var(--text-xl); margin-block-start: var(--space-s); }
  .prose h4 { font-size: var(--text-l); }

  .prose ul,
  .prose ol {
    display: flex;
    flex-direction: column;
    gap: var(--space-3xs);
    padding-inline-start: var(--space-m);
  }

  .prose img { border-radius: var(--radius-m); }

  .prose figure { display: flex; flex-direction: column; gap: var(--space-2xs); }
  .prose figcaption { font-size: var(--text-xs); color: var(--text-muted); }

  .prose table { font-size: var(--text-s); }
  .prose :where(a) { text-decoration: underline; }
}

/* --- site-footer.css --- */
@layer components {
  .site-footer {
    padding-block: var(--section-space-s) var(--section-space-xs);
    padding-inline: var(--gutter);
    background-color: var(--surface);
    color: var(--text-body);
  }

  .site-footer__inner {
    display: grid;
    gap: var(--space-l);
    max-inline-size: var(--width-content);
    margin-inline: auto;
    grid-template-columns: minmax(0, 1.5fr) repeat(auto-fit, minmax(12rem, 1fr));
  }

  @media (width < 48rem) {
    .site-footer__inner { grid-template-columns: 1fr; }
  }

  .site-footer__heading {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wide);
    color: var(--text-muted);
  }

  .site-footer__list {
    display: flex;
    flex-direction: column;
    gap: var(--space-2xs);
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: var(--text-s);
  }

  .site-footer__link { color: var(--text-body); text-decoration: none; }
  .site-footer__link:hover { color: var(--text-link); text-decoration: underline; }

  .site-footer__legal {
    max-inline-size: var(--width-content);
    margin-inline: auto;
    margin-block-start: var(--space-l);
    padding-block-start: var(--space-s);
    border-block-start: 1px solid var(--border-subtle);
    font-size: var(--text-xs);
    color: var(--text-muted);
  }
}

/* --- site-header.css --- */
@layer components {
  .site-header {
    position: sticky;
    inset-block-start: 0;
    z-index: var(--z-header);
    block-size: var(--header-height);
    padding-inline: var(--gutter);
    background-color: var(--surface-raised);
    border-block-end: 1px solid var(--border-subtle);
    transition: transform var(--duration-base) var(--ease-out);
  }

  /* Toggled by js/modules/site-nav.js on scroll direction. */
  .site-header[data-hidden="true"] { transform: translateY(-100%); }

  .site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-m);
    block-size: 100%;
    max-inline-size: var(--width-content);
    margin-inline: auto;
  }

  .site-header__logo img { block-size: calc(var(--header-height) * 0.5); inline-size: auto; }

  .site-nav__list {
    display: flex;
    align-items: center;
    gap: var(--space-m);
    list-style: none;
    margin: 0;
    padding: 0;
  }

  .site-nav__link {
    font-size: var(--text-s);
    font-weight: var(--weight-medium);
    color: var(--text-main);
    text-decoration: none;
  }
  .site-nav__link:hover,
  .site-nav__item.current-menu-item > .site-nav__link { color: var(--text-link); }

  .site-nav__toggle {
    display: none;
    padding: var(--space-2xs);
    cursor: pointer;
  }

  @media (width < 60rem) {
    .site-nav__toggle { display: inline-flex; }

    .site-nav__list {
      position: fixed;
      inset: var(--header-height) 0 0 auto;
      z-index: var(--z-drawer);
      flex-direction: column;
      align-items: flex-start;
      inline-size: min(22rem, 85vw);
      padding: var(--space-m) var(--gutter);
      background-color: var(--surface-raised);
      border-inline-start: 1px solid var(--border-subtle);
      transform: translateX(100%);
      visibility: hidden;
      transition: transform var(--duration-base) var(--ease-out),
                  visibility var(--duration-base);
    }

    .site-nav[data-open="true"] .site-nav__list {
      transform: translateX(0);
      visibility: visible;
    }
  }
}

/* --- 90-utilities.css --- */
/* =============================================================================
   90-UTILITIES
   Last layer, so these always win without !important. Deliberately small — if
   you find yourself adding a fifth utility for the same idea, it wants to be a
   component instead.
   ========================================================================== */

@layer utilities {
  .text-center { text-align: center; }
  .text-start  { text-align: start; }
  .text-balance { text-wrap: balance; }
  .measure-none { max-inline-size: none; }

  .text-muted { color: var(--text-muted); }
  .text-main  { color: var(--text-main); }

  .eyebrow {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wide);
    color: var(--text-accent);
  }

  .hide { display: none; }
  @media (width < 48rem) { .hide-mobile { display: none; } }
  @media (width >= 48rem) { .hide-desktop { display: none; } }

  .no-scroll { overflow: hidden; }
}

