/* ============================================================
   TOKENS: three layers: primitives -> semantic -> component
   Components read ONLY from the semantic and component layers.
   No raw hex and no raw px belong in any other stylesheet
   (the single exception is the 1px hairline).
   ============================================================ */

/* ── LAYER 1 · PRIMITIVES ─────────────────────────────────────
   Never change between themes. Never referenced by components. */
:root {
  /* Neutrals (warm, deliberately not blue-black) */
  --p-ink-900: #0E0E10;
  --p-ink-800: #161619;
  /* Kept without a use: it is the documented stronger step for
     --nav-bg-raised if the band ever reads too quietly (§40.2). */
  --p-ink-700: #1E1E22;
  --p-ink-600: #26262B;
  --p-ink-400: #5C5C63;
  --p-ink-300: #8F8F98;

  --p-linen-100: #F5F3EE;
  --p-linen-200: #EDEAE3;
  --p-linen-300: #DCD7CD;
  --p-linen-050: #EDE7DC;

  /* Accent: madder, the single thread */
  --p-madder-700: #A83A26;
  --p-madder-500: #C4452F;
  --p-madder-300: #E4614A;

  /* The module everything derives from */
  --p-stitch-unit: 8px;

  /* Spacing: base 8 with a 4 half-step */
  --p-space-1: 4px;
  --p-space-2: 8px;
  --p-space-3: 12px;
  --p-space-4: 16px;
  --p-space-5: 24px;
  --p-space-6: 32px;
  --p-space-7: 48px;
  --p-space-8: 64px;
  --p-space-9: 96px;

  /* Radius. Near-square for everything the page rules and divides; the
     soft values belong to objects that sit ON the page rather than
     being part of it. The full shape roster is in LAYER 3 below. */
  --p-radius-1: 2px;
  --p-radius-2: 4px;
  --p-radius-3: 8px;
  --p-radius-canvas: 28px;
  --p-radius-pill: 999px;

  /* Border */
  --p-border-hair: 1px;
  --p-border-med: 2px;

  /* Motion */
  --p-dur-1: 120ms;
  --p-dur-2: 220ms;
  --p-dur-3: 420ms;
  /* One step above the scale, for the single memorable moment on the
     page: the theme wipe. It was written by hand in theme.js before
     it had a name here. Nothing else is allowed to reach for it. */
  --p-dur-4: 620ms;
  --p-ease-out: cubic-bezier(0.20, 0.80, 0.20, 1.00);
  /* The exact mirror of the curve above, (1-x2, 1-y2, 1-x1, 1-y1).
     Exits use it so the interface answers faster than it is asked. */
  --p-ease-in: cubic-bezier(0.80, 0.00, 0.80, 0.20);

  /* Z-index */
  --p-z-sticky: 100;
  --p-z-nav: 200;
  --p-z-toast: 500;
}

/* ── LAYER 2 · SEMANTIC ───────────────────────────────────────
   The only layer a theme switch touches. */

/* DARK (default) */
:root,
[data-theme="dark"] {
  --color-bg: var(--p-ink-900);
  --color-bg-surface: var(--p-ink-800);
  --color-bg-inverse: var(--p-linen-200);

  --color-text: var(--p-linen-050);        /* 15.3:1 AAA */
  --color-text-mute: var(--p-ink-300);     /*  6.1:1 AA  */
  --color-text-accent: var(--p-madder-300);/*  5.5:1 AA  */

  --color-line: var(--p-ink-600);
  --color-line-strong: var(--p-ink-400);

  --color-accent: var(--p-madder-500);
  --color-accent-on: #FFFFFF;              /*  4.97:1 AA */

  /* Seams are the page's main divider, a step stronger than a hairline
     so the dashed run still reads on a large dark screen. */
  --color-stitch: var(--p-ink-400);
  --color-stitch-active: var(--p-madder-500);

  --color-focus: var(--p-madder-300);
  --color-focus-halo: var(--p-ink-900);

  /* Text colours for use *inside* the inverted Contact section,
     where the surface is light while the page theme is dark. */
  --color-on-inverse: var(--p-ink-900);
  --color-on-inverse-mute: var(--p-ink-400);
  --color-on-inverse-accent: var(--p-madder-700);

  --shadow-modal: 0 24px 64px rgb(0 0 0 / 0.55);
  /* Under the header band. On a near black page a shadow has almost
     nowhere to land, so there it is the tone step of --nav-bg-raised
     that carries the boundary and this only softens the edge. */
  --shadow-nav: 0 10px 24px -12px rgb(0 0 0 / 0.5);

  color-scheme: dark;
}

/* LIGHT */
[data-theme="light"] {
  --color-bg: var(--p-linen-200);
  --color-bg-surface: var(--p-linen-100);
  --color-bg-inverse: var(--p-ink-900);

  --color-text: #141416;                   /* 15.4:1 AAA */
  --color-text-mute: var(--p-ink-400);     /*  5.4:1 AA  */
  --color-text-accent: var(--p-madder-700);/*  5.3:1 AA  */

  --color-line: var(--p-linen-300);
  --color-line-strong: #B9B2A5;

  --color-accent: var(--p-madder-500);
  --color-accent-on: #FFFFFF;

  --color-stitch: #B9B2A5;
  --color-stitch-active: var(--p-madder-500);

  --color-focus: var(--p-madder-700);
  --color-focus-halo: var(--p-linen-200);

  /* Inverted Contact is dark while the page is light. */
  --color-on-inverse: var(--p-linen-050);
  --color-on-inverse-mute: var(--p-ink-300);
  --color-on-inverse-accent: var(--p-madder-300);

  --shadow-modal: 0 24px 64px rgb(20 20 22 / 0.16);
  /* The theme where a shadow can actually do work, so it does. */
  --shadow-nav: 0 8px 20px -10px rgb(20 20 22 / 0.16);

  color-scheme: light;
}

/* ── LAYER 3 · COMPONENT ──────────────────────────────────────
   Named for the thing they style, resolved from semantics. */
:root {
  /* Type families */
  --font-display: "Bricolage Grotesque", "Arial Narrow", system-ui, sans-serif;
  --font-body: "Switzer", -apple-system, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", monospace;

  /* Type scale. The hero headline is the one place the display face
     runs at poster size, and it sets its own clamp on the canvas;
     everything below it is deliberately quiet so the contrast does the
     work instead of six competing sizes. */
  --t-d2: clamp(2rem, 4.2vw, 3.25rem);
  --t-d3: clamp(1.75rem, 3vw, 2.5rem);
  --t-quote: clamp(1.375rem, 2vw, 1.625rem);
  --t-h4: clamp(1.25rem, 1.6vw, 1.5rem);
  --t-h5: 1.0625rem;
  --t-lead: clamp(1.0625rem, 1.4vw, 1.25rem);
  --t-body: 1.0625rem;
  --t-body-sm: 0.9375rem;
  --t-meta: 0.8125rem;
  --t-label: 0.75rem;

  --lh-d2: 1.02;
  --lh-d3: 1.08;
  --lh-quote: 1.34;
  --lh-h4: 1.25;
  --lh-lead: 1.55;
  --lh-body: 1.62;

  --ls-d2: -0.025em;
  --ls-d3: -0.02em;
  --ls-h4: -0.01em;
  --ls-meta: 0.02em;
  --ls-label: 0.10em;

  /* Grid and measure */
  --grid-max: 1240px;
  --grid-pad: clamp(20px, 5vw, 64px);
  --measure: 34em;
  --measure-quote: 38em;

  /* The vertical rhythm was measured against the viewport HEIGHT alone,
     and a phone is about as tall as a laptop. So a phone was getting the
     laptop's spacing, 89px above and below every section, 178px between
     two of them, in a column only 375px wide: half a screen of nothing.

     Width is now the second bound. It only ever wins on a narrow
     viewport, so every desktop size resolves to exactly the number it
     resolved to before, and only phones and tablets come down.

       375 x 812   89 -> 56     (the floor)
       768 x 1024  113 -> 92
       1440 x 900   99 -> 99    (unchanged) */
  --space-section-y: clamp(56px, min(11vh, 12vw), 152px);
  --space-block-y: clamp(32px, min(6vh, 7vw), 72px);

  /* The inset the hero canvas is held in, and the width the header is
     measured against, so the wordmark starts where the canvas starts and
     the CTA ends where it ends.

     One and a half times its first value. The canvas corner is 28px, so
     an inset a little larger than that reads as breathing room; at twice
     the old value the dark canvas starts reading as a card in a frame
     rather than as the first screen of the page. */
  --canvas-inset: clamp(18px, 2.4vw, 34px);

  /* Nav. The band tightens to the compact height over the first 160px
     of scroll; see the scroll-driven animation in layout.css. */
  --nav-h: 76px;
  --nav-h-compact: 60px;
  --nav-h-mobile: 60px;
  /* A hairline still, but readable at the top of a wide display. */
  --progress-h: 3px;

  /* The address now sits in half the container, so it is sized against
     that half rather than the full width: 36px keeps it on one line at
     the widest and unbroken at the narrowest. */
  --contact-mail-size: clamp(1.375rem, 2.6vw, 2.25rem);

  /* Two states, because the band has two jobs.

     At rest it is the page: the same value as what it sits on, so on
     the first screen there is nothing to see between the band and the
     background, and the top edge of the hero canvas is the only
     boundary drawn. That is the whole idea of the cinematic opening.

     Raised is what it becomes once the page moves under it, when there
     is no canvas edge left to borrow and it has to carry its own
     boundary. --color-bg-surface is lighter than --color-bg in BOTH
     themes, so one declaration gives the step in both: #161619 over
     #0E0E10, and #F5F3EE over #EDEAE3. Tone, not a rule, which is why
     no line was added (see LINES, §34).

     The crossfade between the two is on the scroll timeline in
     layout.css, the same one that tightens the band. */
  --nav-bg: color-mix(in srgb, var(--color-bg) 86%, transparent);
  /* Nearly opaque, and deliberately so. It sits ON the resting layer,
     which is page coloured, so anything more translucent dilutes the
     very tone step it exists to make. Being opaque when raised also
     ends the ghosting that started all this: below the fold there is
     no longer 14% of the text underneath showing through. */
  --nav-bg-raised: color-mix(in srgb, var(--color-bg-surface) 96%, transparent);

  /* Shape roles. Four radii on the page, and every one of them is
     listed here so the system stays countable. The comment used to
     claim two, which was the count of the tokens rather than the count
     of the shapes, and an audit reads the page not the token file:
       canvas 28px ... the cinematic hero, the one object on the page
       pill 999px .... controls that are reached for (buttons, the nav
                       links, the icon buttons, the availability chip)
       image 8px ..... project imagery, --p-radius-3, set on the media
                       box in components.css
       avatar 50% .... the recommendation portraits only, a client
                       decision (§20). Nothing else on the page is a
                       circle except the availability dot. */
  --radius-canvas: var(--p-radius-canvas);
  --radius-pill: var(--p-radius-pill);

  /* Button */
  --btn-h: 48px;
  --btn-h-sm: 40px;
  --btn-pad-x: var(--p-space-6);
  --btn-radius: var(--radius-pill);
  --btn-bg-primary: var(--color-accent);
  --btn-fg-primary: var(--color-accent-on);
  --btn-bg-ghost: transparent;
  --btn-fg-ghost: var(--color-text);
  --btn-border-ghost: var(--p-border-hair) solid var(--color-line-strong);

  /* Rows, portrait, avatars */
  --row-pad-y: var(--p-space-6);
  --avatar-size: 64px;
  --avatar-size-sm: 56px;

  /* Stitch: the module, and the counted marker built from it */
  --stitch-unit: var(--p-stitch-unit);
  --stitch-gap: 2px;
  /* Seams are drawn as a repeating gradient, so the run length is the
     token the stylesheets actually consume. */
  --seam-run: 6px;
  --mark-unit: var(--p-stitch-unit);
  --mark-gap: 3px;
  /* Half scale, for the counted mark inside the mobile menu, where it
     sits beside 20px text instead of out in the gutter. */
  --menu-mark-unit: calc(var(--p-stitch-unit) / 2 + 1px);
  --menu-mark-gap: 2px;

  /* The mobile contact bar is a 48px button between two 8px paddings
     over a hairline. Named because the footer has to clear it: the bar
     is fixed, so it paints over whatever the last line of the page is. */
  --sticky-cta-h: calc(48px + var(--p-space-2) * 2 + var(--p-border-hair));
  /* Two columns of stitches plus the gap between them and the text. */
  --mark-inset: 34px;

  /* Focus */
  --focus-ring: var(--p-border-med) solid var(--color-focus);
  --focus-offset: 3px;

  /* Minimum tap target, everywhere */
  --tap-min: 44px;
}
