/* =====================================================================================================
   v18 design tokens: the single source of truth for type, spacing and layout (2026-10-10).
   Every size on the page reads one of these names. Change a value here and every use changes.

   FLUID RULE: a fluid token has a phone size (at 320px wide) and a desktop size (at 1710px wide) and
   grows in a straight line between them. Below 320 it stays at the phone size; above 1710 it STOPS
   growing (Van, 2026-10-10: wider screens get wider margins, not bigger text).
     --fluid(min, max) = clamp(min, min + (max - min) * (100vw - 320px) / 1390, max)
   CSS has no functions, so each token writes that formula out. To change a token, change only its two
   numbers (the phone px and the desktop px); the "(max - min)" number must equal desktop minus phone.

   Starting values come from the v17 audit (docs/v18/audit-summary.md, v17 baseline sizes per width) and
   Van's notes (hero too big at 320). Van approves them on the specimen page before any section moves.
   ===================================================================================================== */

@font-face {
  font-family: "Inter";
  src: url("assets/fonts/inter-normal.woff2") format("woff2");
  font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("assets/fonts/inter-italic.woff2") format("woff2");
  font-weight: 100 900; font-style: italic; font-display: swap;
}

:root {
  /* ---------- Font: one family on every device ---------- */
  --font: "Inter", system-ui, sans-serif;

  /* ---------- Type roles: size (phone 320 -> desktop 1710), line height, weight, tracking ----------
     v17 source in brackets. */
  /* Display: hero headline [--fs-hero-title 60; 49 at 320 felt too big] */
  --type-display-size: clamp(40px, calc(40px + 20 * (100vw - 320px) / 1390), 60px);
  --type-display-lh: 1.02;  --type-display-weight: 300;  --type-display-track: -0.025em;
  /* H1: section and About titles [--fs-section-title 56, clamp(56px, 8vw, ...)] */
  --type-h1-size: clamp(34px, calc(34px + 22 * (100vw - 320px) / 1390), 56px);
  --type-h1-lh: 1.0;  --type-h1-weight: 700;  --type-h1-track: -0.02em;
  /* H2: case-study headlines [clamp(30px, 4vw, 46px)] */
  --type-h2-size: clamp(26px, calc(26px + 24 * (100vw - 320px) / 1390), 50px);
  --type-h2-lh: 1.08;  --type-h2-weight: 700;  --type-h2-track: -0.015em;
  /* H3: beat headings, card titles [--fs-head-lg 28, --fs-head-md 26, merged] */
  --type-h3-size: clamp(20px, calc(20px + 8 * (100vw - 320px) / 1390), 28px);
  --type-h3-lh: 1.15;  --type-h3-weight: 500;  --type-h3-track: -0.01em;
  /* Tagline: the four scroll-revealed beat taglines [v17 32 phone / 40 tablet / 56 desktop in a marker
     font; Inter runs wider, so a little smaller]. Its own role so it doesn't read as a heading. */
  --type-tagline-size: clamp(26px, calc(26px + 26 * (100vw - 320px) / 1390), 52px);
  --type-tagline-lh: 1.3;  --type-tagline-weight: 300;  --type-tagline-track: -0.01em;  --type-tagline-style: italic;
  /* Body L: hero subline, lead paragraphs [--fs-body-lg 20, --fs-sub-lg 20, --fs-sub-md 18] */
  --type-body-l-size: clamp(17px, calc(17px + 3 * (100vw - 320px) / 1390), 20px);
  --type-body-l-lh: 1.55;  --type-body-l-weight: 300;  --type-body-l-track: 0;
  /* Body: running text [--fs-body-sm 16, --fs-body-md 14] */
  --type-body-size: clamp(15px, calc(15px + 1 * (100vw - 320px) / 1390), 16px);
  --type-body-lh: 1.6;  --type-body-weight: 400;  --type-body-track: 0;
  /* Small: captions, meta, legal [12 to 14px literals] */
  --type-small-size: 13px;
  --type-small-lh: 1.5;  --type-small-weight: 400;  --type-small-track: 0;
  /* Label: eyebrows, buttons, nav, rail; always uppercase [--fs-eyebrow-xs/sm/md 10/11/12, merged] */
  --type-label-size: clamp(11px, calc(11px + 1 * (100vw - 320px) / 1390), 12px);
  --type-label-lh: 1.2;  --type-label-weight: 500;  --type-label-track: 0.16em;

  /* ---------- Spacing steps: every padding, margin and gap uses one of these ---------- */
  --space-1: 4px;   --space-2: 8px;   --space-3: 12px;  --space-4: 16px;  --space-5: 24px;
  --space-6: 32px;  --space-7: 48px;  --space-8: 64px;  --space-9: 96px;  --space-10: 128px;

  /* ---------- Gap steps: the fixed menu every gap on the page is picked from (named by their desktop pixel size) ----------
     Steps are fixed on purpose: a "64" is always 64 on desktop. 8 to 48 are the same at every screen width. 64 and up shrink on
     phones, growing in a straight line from the phone size at 320px wide to the full size at 1710px (fluid rule above). */
  --step-8: 8px;   --step-16: 16px;  --step-24: 24px;  --step-36: 36px;  --step-48: 48px;
  --step-64: clamp(40px, calc(40px + 24 * (100vw - 320px) / 1390), 64px);      /* phone 40 */
  --step-96: clamp(56px, calc(56px + 40 * (100vw - 320px) / 1390), 96px);      /* phone 56 */
  --step-128: clamp(72px, calc(72px + 56 * (100vw - 320px) / 1390), 128px);    /* phone 72 */
  --step-200: clamp(96px, calc(96px + 104 * (100vw - 320px) / 1390), 200px);   /* phone 96 */
  --step-240: clamp(112px, calc(112px + 128 * (100vw - 320px) / 1390), 240px); /* phone 112 (added 2026-10-10) */
  --step-320: clamp(144px, calc(144px + 176 * (100vw - 320px) / 1390), 320px); /* phone 144 */
  --step-400: clamp(176px, calc(176px + 224 * (100vw - 320px) / 1390), 400px); /* phone 176 */

  /* ---------- Gap slots: one named setting per real gap on the page, each picks ONE step above ----------
     Write each slot as exactly  --gap-<name>: var(--step-<N>);  on its own line (tools/bake_v18.py rewrites these lines, and the
     panel's Spacing group has one row per slot). A slot applies at every screen width; the step itself handles phones. */
  --gap-nav-top: var(--step-16);                   /* page top to the floating nav (shows once you scroll) */
  --gap-hero-nav-to-copy: var(--step-128);          /* hero: nav to the headline block (moves the block down) */
  --gap-hero-copy-to-logos: var(--step-200);       /* hero: headline block to the client logo strip (moves the strip down) */
  --gap-logo-to-logo: var(--step-96);              /* hero: space between two client logos */
  --gap-project-heading: var(--step-16);           /* each project: between the name, the headline and the subline */
  --gap-project-copy-to-shot: var(--step-36);      /* each project: text block to the screenshot */
  --gap-project-shot-to-button: var(--step-36);    /* each project: screenshot to the "See how" button */
  --gap-project-below: var(--step-200);            /* each project: below the button to the end of its section (all 4 projects share it) */
  --gap-tagline-above: var(--step-240);            /* each project: visible space below the black notch to the tagline text (notch allowance added automatically; each project adds its own "extra gap", 0 by default) */
  --gap-about-above: var(--step-320);              /* About: visible space below the black notch to the About content (the notch allowance is added automatically) */
  --gap-about-text-to-portrait: var(--step-16);    /* About, tablet and phone only: buttons to the portrait (desktop lays the portrait beside the text) */
  --gap-footer-top: var(--step-8);                /* About footer island: top edge to its first line */
  --gap-footer-bottom: var(--step-24);             /* About footer island: last line to the bottom of the page */

  /* ---------- Text over animation: how far each project's text rises over the bottom of its animation ----------
     A fraction of the screen height (50vh = half a screen), so it looks the same on a phone and a laptop. Each project adds its
     own "extra overlap" on top (art setting, 0 by default). The panel offers 0, 1/8 ... 1 screen; write it as  NNvh. */
  --overlap-text: 62.5vh;

  /* ---------- Layout ---------- */
  --gutter: clamp(12px, calc(12px + 44 * (100vw - 320px) / 1390), 56px);   /* side margin [clamp(20px, 6vw, 56px)] */
  --measure: 630px;            /* longest comfortable text line [v17-about-text-w 630] */
  --container: 1250px;         /* widest content block [case tagline min(1250px, 90vw)] */
  --columns: 12;               /* grid columns: 4 phone, 8 tablet, 12 desktop (set below) */

  /* ---------- Components ---------- */
  --btn-h: 44px;               /* every button and icon button, also the phone tap-target minimum */
  --radius-btn: 999px;
  --radius-card: 16px;
  --radius-nav: 8px;           /* [v17-nav-radius 8] */
  --logo-h: clamp(21px, calc(21px + 8 * (100vw - 320px) / 1390), 29px);     /* client logo strip [21 / 23 / 29] */

  /* ---------- Milestone B: layout and component tokens (2026-10-10) ---------- */
  /* Page column caps. --container (1250) is the widest block (tagline watermark); v17's text columns were capped at 1080,
     and the case-study headline group at 960, so those keep their own names rather than widening to 1250 at 1710. */
  --content-w: 1080px;         /* every .slide child, the floating nav, the footer island [v17 literal 1080] */
  --content-w-narrow: 960px;   /* case-study headline group [v17 literal 960] */

  /* Hero: art-coupled, deliberately NOT on the spacing scale (changing them moves the hero art against the text). */
  --slide-pad-y: 80px;         /* hero extends 100vh + this; also the default .slide padding [v17 --slide-pad-y 80] */
  --hero-pad-top: 120px;       /* hero text top, multiplied by the desktop-fit --dk in the page [v17 literal 120] */
  /* Hero stack spacing and the nav gap are gap slots now (--gap-hero-nav-to-copy, --gap-hero-copy-to-logos, --gap-logo-to-logo, --gap-nav-top above). */

  /* Case cover image scale: 96% phone, 80% tablet and desktop (v17-cover-scale baked; media queries at the bottom). */
  --cover-scale: 80%;

  /* About layout (v17-about-* keys). Desktop values here, tablet and phone in the media queries at the bottom.
     v17's About top padding was 328 on desktop (400 on phone) and the text was then lifted up 155 (--about-text-y). The top gap is now
     --gap-about-above plus --notch-clear: the black seam notch painted over the top of About is 116px tall (161px on phones, art, not changed),
     so the text needs that much clear space as well as the gap. 200 + 128 = 328, the same as v17 at 1710. The pick (--gap-about-above) is the visible space below the notch; the notch allowance is built in. */
  --notch-clear: var(--space-10);      /* room for the notch: 128 vs the 116px notch (168 on phones, see below) */
  /* The lift on desktop is -160 (= -(96 + 64), two scale steps) for -155 in v17, the closest grid value, so text, portrait and footer keep
     their 1710 composition. Tablet and phone stack the layout and need no lift (0); the portrait gap absorbs it (see below). */
  --about-text-y: calc(-1 * (var(--space-9) + var(--space-8)));
  --about-portrait-w: 640px;         /* [v17-about-portrait-w, desktop 640] */
  --about-portrait-x: 120px;         /* sideways nudge, scaled by the desktop-fit width in the page [desktop 120] */
  --about-portrait-overlap: 70px;    /* how far the portrait's fade reaches under the text column [v17 literal 70] */
  --about-body-min-h: 620px;         /* desktop height of the text + portrait row [v17 literal 620] */

  /* ---------- Colour: not tokenised yet. v18 still uses v17's own colour names (note v17's --ink is
     #f5f5f5, a light colour, despite the name); colours get their own pass later. ---------- */
}

/* Screen groups: phone up to 600px, tablet 601 to 900px, desktop above. Only layout changes by group;
   type and spacing are already fluid. */
@media (max-width: 900px) {
  :root {
    --columns: 8;
    /* About, tablet: v17 baked w 430, x -10 (-> -8), gap -152 (+155 lift removed -> 3 -> 0; the portrait gap is now the --gap-about-text-to-portrait slot) */
    --about-text-y: 0px;  --about-portrait-w: 430px;  --about-portrait-x: -8px;
  }
}
@media (max-width: 600px) {
  :root {
    --columns: 4;
    --cover-scale: 96%;
    --notch-clear: 168px;   /* the notch is 161px tall on phones */
    /* About, phone: v17 baked w 280, x -15 (-> -16), gap -138 (+155 lift removed -> 17 -> 16) */
    --about-portrait-w: 280px;  --about-portrait-x: -16px;
  }
}

/* Role classes: components apply a role with one class (or @extend-style by copying the four lines). */
.t-display, .t-h1, .t-h2, .t-h3, .t-tagline, .t-body-l, .t-body, .t-small, .t-label { font-family: var(--font); }
.t-display { font-size: var(--type-display-size); line-height: var(--type-display-lh); font-weight: var(--type-display-weight); letter-spacing: var(--type-display-track); }
.t-h1      { font-size: var(--type-h1-size);      line-height: var(--type-h1-lh);      font-weight: var(--type-h1-weight);      letter-spacing: var(--type-h1-track); }
.t-h2      { font-size: var(--type-h2-size);      line-height: var(--type-h2-lh);      font-weight: var(--type-h2-weight);      letter-spacing: var(--type-h2-track); }
.t-h3      { font-size: var(--type-h3-size);      line-height: var(--type-h3-lh);      font-weight: var(--type-h3-weight);      letter-spacing: var(--type-h3-track); }
.t-tagline { font-size: var(--type-tagline-size); line-height: var(--type-tagline-lh); font-weight: var(--type-tagline-weight); letter-spacing: var(--type-tagline-track); font-style: var(--type-tagline-style); }
.t-body-l  { font-size: var(--type-body-l-size);  line-height: var(--type-body-l-lh);  font-weight: var(--type-body-l-weight);  letter-spacing: var(--type-body-l-track); }
.t-body    { font-size: var(--type-body-size);    line-height: var(--type-body-lh);    font-weight: var(--type-body-weight);    letter-spacing: var(--type-body-track); }
.t-small   { font-size: var(--type-small-size);   line-height: var(--type-small-lh);   font-weight: var(--type-small-weight);   letter-spacing: var(--type-small-track); }
.t-label   { font-size: var(--type-label-size);   line-height: var(--type-label-lh);   font-weight: var(--type-label-weight);   letter-spacing: var(--type-label-track); text-transform: uppercase; }
