/* ============================================================
   main.css
   Order: fonts → tokens → reset → base → layout → components
   ============================================================ */

/* ── Fonts ───────────────────────────────────────────────── */
/* Inter is the only typeface on the site. Self-hosted as the variable
   cut, so one file covers every weight the design uses (400 for body
   and UI, 600 for the lede). Two subsets: latin, and latin-ext for the
   curly quotes, dashes, currency marks and Turkish characters the copy
   uses. SIL Open Font License. */
@font-face {
  font-family: "Inter";
  src: url("../assets/fonts/Inter-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  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";
  src: url("../assets/fonts/Inter-latin-ext.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ── Design tokens ───────────────────────────────────────── */
:root {
  /* Four colours — the whole structural palette, sampled off the
     exports. Everything else in them (#3567F6, #FEC62E, #3BFFB5,
     #006831 …) lives inside the product mockups, not the site. */
  --bg:      #ffffff;
  --ink:     #1e1e24;
  --muted:   #686878;       /* second text colour, not a fade         */
  --surface: #f4f4f6;       /* work card backing, figure panels       */
  --rule:    #d2d2db;       /* case study hairlines                   */

  --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Type. Every size below was solved by matching rendered ink widths
     against the export's own paths, not guessed: ten strings land
     within ~1px at 14/400, and the lede's ascent matches to 0.0px at
     64/600/-2%. */
  --size-body: 14px;        /* name, rail, captions, footer, dates    */
  --size-copy: 14px;        /* running copy — 16px until 2026-10-23   */
  --size-intro: 16px;       /* the paragraph under the lede           */
  --size-subhead: 16px;     /* case study sub-headings                */
  --size-heading: 32px;     /* case study section headings            */
  --size-title: 48px;       /* case study title                       */
  --size-cursor: 10px;      /* the label inside the cursor pill       */
  --weight-head: 600;       /* titles, headings and sub-headings      */
  /* Inter wants tighter tracking as it gets bigger, and the design
     follows that curve: solved per string against the exports, four
     of five headings land on -0.0075em and the 48px title on -1.5%,
     with the 64px Work lede tighter still at -2%. */
  --track-title: -0.0156em;
  --track-head:  -0.0075em;
  --size-lede: 64px;
  --weight-lede: 600;
  --track-lede: -0.02em;    /* Inter wants negative tracking this big */

  --leading-body:  17px;    /* 14px text set as a block               */
  --leading-copy:  21px;    /* 1.5 × 14                               */
  --leading-line:  18px;    /* a lone 14px line — see the note below  */
  --leading-nav:   29px;    /* the rail                               */
  --leading-intro: 24px;    /* 1.5 × 16                               */
  --leading-lede:  96px;    /* 1.5 × 64                               */
  --leading-subhead: 24px;  /* 1.5 × 16                               */
  --leading-heading: 48px;  /* 1.5 × 32                               */
  --leading-title:   72px;  /* 1.5 × 48                               */

  /* --leading-line and --leading-body are both for 14px text but mean
     different things: 18px is what lands a single line's baseline
     where Figma puts it, 17px is the rhythm running copy sits on. */

  --margin: 24px;           /* page edge to content, all four sides   */
  --gutter: 24px;           /* between the six columns                */

  /* Vertical rhythm. Each value is whatever puts the next baseline
     where the export has it, measured in the browser with a zero-size
     inline-block probe. */
  --lede-top:  198.7px;     /* content row → the 64px lede            */
  --lede-intro: 23.2px;     /* lede → intro                           */
  --intro-work: 48.1px;     /* intro → the card grid                  */
  --caption-gap:17.7px;     /* a card's bottom edge → its caption     */
  --work-row-gap:25.3px;     /* a caption → the next row of cards      */
  --nav-top:  194.1px;      /* content row → the rail's first line.
                               The rail is fixed, so it has one position
                               for the whole site. About and all three
                               case study frames agree on it; the Work
                               frame alone puts it 24px lower and was
                               outvoted.                              */
  --copy-top: 198.5px;      /* content row → a page that opens in copy */
  --block-gap:   48px;      /* between blocks inside a page           */
  --exp-indent: 134px;      /* date column → role column (x = 394)    */
  --exp-gap:     24px;      /* between entries beside the label       */

  /* Case study rhythm — tuned against the exports the same way as the
     rest: each value is whatever puts the next baseline where the
     export has it. */
  --cs-measure:      684px;
  --cs-top: calc(-1 * (var(--margin) + var(--leading-line)));  /* pulls the hero up to the page top edge */
  --cs-hero-title:  46.9px;  /* hero → title                          */
  --cs-title-meta:  27.1px;  /* title → meta label                    */
  --cs-meta-gap:     5.5px;  /* meta label → its value                */
  --cs-meta-rule:   47.3px;  /* meta value → the first rule           */
  --cs-rule-label:  49.8px;  /* rule → section label                  */
  --cs-label-head:   5.5px;  /* section label → heading               */
  --cs-head-body:   24.2px;  /* heading → whatever follows it         */
  --cs-block:       23.7px;  /* between blocks inside a section       */
  --cs-subhead-body: 4.6px;  /* sub-heading → its copy or list        */
  --cs-list-gap:      21px;  /* between list items                    */
  --cs-sec-bottom:  47.5px;  /* section end → the next rule           */
  --cs-aside-inset: 22.2px;  /* the divide → the text beside a figure */
  --cs-split-gap:   25.5px;  /* between split rows                    */
  --cs-step-gap:      16px;  /* between numbered annotations          */

  /* The owner's standing rule: every page ends with the same 240px of
     space that it opens with. So the run from the last piece of content
     to the bottom of the page is always 240 — the footer sits inside
     that space, and the page height follows from the content rather
     than from whatever height the Figma frame happens to be. This
     overrides the exports, so page heights deliberately differ from the
     frames. 240 = the gap, minus the footer's own line box and the
     bottom margin. */
  --page-gap: 199px;

  --radius: 0px;            /* the new cards are square-cornered      */

  --dot:       14px;        /* the circle that follows the cursor     */
  --dot-hover: 24px;        /* …grown over anything clickable         */
  --bullet:     4px;        /* marks the current page in the rail     */
  --step:      20px;        /* numbered disc beside a case figure     */

  --hover-fade: 0.2s;       /* a link coming up to full ink           */

  /* Small screens only (ADR-0004). Breakpoints can't be custom
     properties, so they live here as a list and are repeated exactly in
     the Responsive section: 1024px, 768px, 480px. */
  --bar: 56px;              /* the header bar below 1024px            */
  --tap: 44px;              /* smallest tap target below 1024px       */
}

/* ── Reset ───────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; }

html { -webkit-text-size-adjust: 100%; }

img { display: block; max-width: 100%; height: auto; }

ul { padding: 0; list-style: none; }

h1, h2 { font-size: inherit; font-weight: 400; }

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

/* ── Base ────────────────────────────────────────────────── */
/* The section menu glides to its section instead of jumping there. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--size-body);
  font-weight: 400;
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
}

/* Read by screen readers, never seen: the About page's <h1>, and the
   status main.js announces after copying the email address. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The first Tab stop on every page. Fixed, so it takes no grid cell,
   and parked above the viewport until it has focus. */
.skip-link {
  position: fixed;
  top: var(--margin);
  left: var(--margin);
  z-index: 20;
  padding: 0 calc(var(--gutter) / 2);
  line-height: var(--leading-nav);
  background: var(--ink);
  color: var(--bg);
  transform: translateY(-200%);
}

.skip-link:focus { transform: none; }

/* <main> takes focus only as the skip link's target. It is not a
   control, so a ring around the whole page would be noise. */
main:focus { outline: none; }

/* ── Layout ──────────────────────────────────────────────── */
/* Six columns, 24px margin and gutter: at the 1440px design frame the
   columns are 212px wide, starting at x = 24 / 260 / 496 / 732 / 968 /
   1204. The name and the rail sit in column 1, everything else starts
   at column 2. Three rows: header, content, footer — the middle one
   takes the slack, so the footer rests on the bottom margin until the
   content pushes it past. */
body {
  min-height: 100vh;
  padding: var(--margin);
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-template-rows: var(--leading-line) 1fr auto;   /* row 1 keeps its
                               height even though the header is fixed */
  column-gap: var(--gutter);
  row-gap: 0;
}

/* The name. Identical on every page —
   copy it verbatim when adding one. Fixed, with no background, so
   content scrolls visibly behind it. The grid still reserves row 1, so
   nothing below shifts. */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 5;
  padding: var(--margin) var(--margin) 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  line-height: var(--leading-line);   /* name baseline on 38 */
}

/* The fade sits on the link, not the <p>, so hover can reach full. */
.site-name a {
  color: var(--muted);
  transition: color var(--hover-fade);
}

.site-name a:hover,
.site-name a:focus-visible { color: var(--ink); }

/* The rail: Work and About in column 1, 29px apart, and fixed
   exactly where the design puts it — the same sum the grid would have
   produced. Column 1 is empty of content on every page, so nothing
   scrolls underneath it. */
.site-nav {
  position: fixed;
  top: calc(var(--margin) + var(--leading-line) + var(--nav-top));
  left: var(--margin);
  z-index: 5;
  line-height: var(--leading-nav);
}

.nav-link {
  display: block;
  width: fit-content;       /* the word is the target — a full-width
                               block would make the whole 212px column
                               hover, far from the text */
  position: relative;
  color: var(--muted);
  transition: color var(--hover-fade);
}

a.nav-link:hover,
a.nav-link:focus-visible { color: var(--ink); }

/* The current page: full ink, and a 4px dot out in the left margin,
   centred on the line. */
.nav-link[aria-current] { color: var(--ink); }

.nav-link[aria-current]::before {
  content: "";
  position: absolute;
  left: calc(var(--margin) / -2);        /* centre at x = 14 */
  top: 50%;
  width: var(--bullet);
  height: var(--bullet);
  margin-top: calc(var(--bullet) / -2);
  border-radius: 50%;
  background: var(--ink);
}

/* main.js adds this to case studies; it only shows below 1024px. */
.nav-toggle {
  display: none;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--muted);
  cursor: pointer;
  transition: color var(--hover-fade);
}

/* Like the Back link, and it stays dark while the list is open. */
.nav-toggle:hover,
.nav-toggle:focus-visible,
.nav-toggle[aria-expanded="true"] { color: var(--ink); }

/* Content: columns 2–6, repeating five equal columns of its own, which
   line up with the page grid without needing subgrid. Children each
   start at its first column and take as many as the design gives
   them — the lede 4 (920px), body copy 2 (448px), the work grid 4. */
.page {
  grid-column: 2 / -1;
  grid-row: 2;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  column-gap: var(--gutter);
  align-content: start;
}

.page > * { grid-column: 1 / span 3; }    /* body copy: 684px, own row */
.page > .copy { grid-column: 1 / span 2; } /* About copy: 448px */

/* ── Footer ──────────────────────────────────────────────── */
.site-footer {
  grid-column: 1 / -1;
  grid-row: 3;
  margin-top: var(--page-gap);
  display: flex;
  gap: var(--gutter);
}

.site-footer a {
  color: var(--muted);
  transition: color var(--hover-fade);
}

.site-footer a:hover,
.site-footer a:focus-visible { color: var(--ink); }

/* ── Lede (Work) ─────────────────────────────────────────── */
/* 920px — columns 2–5. The break after "designer" is a <br> in the
   markup, not a wrap: the measure is wide enough to fit more. */
.lede {
  grid-column: 1 / span 4;
  margin-top: var(--lede-top);
  font-size: var(--size-lede);
  font-weight: var(--weight-lede);
  line-height: var(--leading-lede);
  letter-spacing: var(--track-lede);
}

/* ── Body copy ───────────────────────────────────────────── */
.copy {
  color: var(--muted);
  font-size: var(--size-copy);
  line-height: var(--leading-copy);
}

/* first-of-type, not first-child: About opens with a hidden <h1>. */
.page > .copy:first-of-type { margin-top: var(--copy-top); }

/* Paragraphs are one blank line apart. */
.copy p + p { margin-top: var(--leading-copy); }

/* The paragraph under the lede. It sits on a 684px measure — three
   columns, not the lede's four — which is what puts its break after
   "end-to-end". */
.intro {
  grid-column: 1 / span 3;
  margin-top: var(--lede-intro);
  color: var(--muted);
  font-size: var(--size-intro);
  line-height: var(--leading-intro);
}

/* ── Work ────────────────────────────────────────────────── */
/* Cards across columns 2–5, each 448×265 at the design frame. Three of
   them: two on the first row, one alone on the second. */
.work {
  grid-column: 1 / span 4;
  margin-top: var(--intro-work);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: var(--gutter);
  row-gap: var(--work-row-gap);
}

/* A block, so keyboard focus draws one ring around the whole card
   rather than one around the image and another around the caption. */
.card a { display: block; }

/* Each card is one flat image, cut from the export at 2×, so whatever
   the design does inside it arrives already composited. */
.card-frame {
  position: relative;
  aspect-ratio: 448 / 265;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
}

.card-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card-caption {
  margin-top: var(--caption-gap);
  line-height: var(--leading-line);
  color: var(--muted);
}

/* ── About ───────────────────────────────────────────────── */
/* One label in column 2 and the entries it covers 134px further in
   (x = 394). The label is --ink, what it points at is --muted, and
   both are 14px on the copy rhythm. The two columns are top-aligned,
   which is what the export does. */
.exp {
  margin-top: var(--block-gap);
  color: var(--muted);
  font-size: var(--size-copy);
  line-height: var(--leading-copy);
}

.exp-entry {
  display: grid;
  grid-template-columns: var(--exp-indent) 1fr;
  align-items: start;
}

.exp-date { color: var(--ink); }

/* Entries stack beside the one label, a blank line apart. */
.exp-roles p + p { margin-top: var(--exp-gap); }

/* ── Case study ──────────────────────────────────────────── */
/* Two measures on these pages: the hero keeps to the grid (columns
   2–5, 920px) while the text sits in a 684px column centred on the
   page — 378 → 1062 — which is three columns wide but centred rather
   than grid-aligned, so it lines up with nothing. That is what the
   exports do; don't "correct" it onto the grid. */
.case-page {
  grid-column: 1 / -1;
  grid-row: 2;
  margin-top: var(--cs-top);
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  column-gap: var(--gutter);
  align-content: start;
}

.case-hero {
  grid-column: 2 / 6;
  aspect-ratio: 920 / 546;
  background: var(--surface);
  overflow: hidden;
}

.case-hero img { width: 100%; height: 100%; object-fit: cover; }

.case-body {
  grid-column: 1 / -1;
  width: 100%;
  max-width: var(--cs-measure);
  margin-inline: auto;
  margin-top: var(--cs-hero-title);
}

/* The back link replaces the name. The arrow sits out in the margin,
   like the rail's bullet. */
.back {
  position: relative;
  color: var(--muted);
  transition: color var(--hover-fade);
}

.back:hover,
.back:focus-visible { color: var(--ink); }

.back-arrow {
  position: absolute;
  left: -12px;
  top: 50%;
  margin-top: -3px;
}

/* ── Case study: title and meta ──────────────────────────── */
/* The design system export sets its title → meta → rule run 24px
   wider than the other two case studies do. Its own frame, its own
   value. */
.case-ds {
  --cs-title-meta: 51.1px;
}

.case-title {
  font-size: var(--size-title);
  font-weight: var(--weight-head);
  line-height: var(--leading-title);
  letter-spacing: var(--track-title);
}

.case-meta {
  margin-top: var(--cs-title-meta);
  margin-bottom: var(--cs-meta-rule);
  display: flex;
  justify-content: space-between;
}

.case-meta dt {
  color: var(--muted);
  line-height: var(--leading-line);
}

.case-meta dd {
  margin-top: var(--cs-meta-gap);
  font-size: var(--size-copy);
  line-height: var(--leading-copy);
}

/* ── Case study: sections ────────────────────────────────── */
/* Every section opens with a hairline the full width of the measure.
   It is drawn with a ::before, not a border: a border adds its height
   to every section and walks the whole page down. */
.case-section {
  position: relative;
  padding-top: var(--cs-rule-label);
  padding-bottom: var(--cs-sec-bottom);
}

.case-section::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--rule);
}

.case-section:last-child { padding-bottom: 0; }

.case-label {
  color: var(--muted);
  line-height: var(--leading-line);
}

.case-section h2 {
  margin-top: var(--cs-label-head);
  font-size: var(--size-heading);
  font-weight: var(--weight-head);
  line-height: var(--leading-heading);
  letter-spacing: var(--track-head);
}

/* Anything following the heading, a figure, or anything else. */
.case-section > * + * { margin-top: var(--cs-block); }
.case-section > h2 + * { margin-top: var(--cs-head-body); }

.case-figure { width: 100%; }

/* Over a list or a paragraph. */
.case-subhead {
  font-size: var(--size-subhead);
  font-weight: var(--weight-head);
  line-height: var(--leading-subhead);
  letter-spacing: var(--track-head);
}

.case-section > .case-subhead + * { margin-top: var(--cs-subhead-body); }

/* ── Case study: lists ───────────────────────────────────── */
.case-list {
  color: var(--muted);
  font-size: var(--size-copy);
  line-height: var(--leading-copy);
}

.case-list li {
  position: relative;
  padding-left: 24.4px;
}

.case-list li + li { margin-top: var(--cs-list-gap); }

.case-list li::before {
  content: "•";
  position: absolute;
  left: 9.5px;
  color: var(--ink);
}

/* Lead-in phrases are --ink at the same weight as the copy. */
.case-list b,
.case-body b {
  color: var(--ink);
  font-weight: 400;
}

/* ── Case study: split rows ──────────────────────────────── */
/* The TUI case study alternates a half-measure figure against a
   half-measure of text. The halves meet in the middle with no gutter
   and the text is inset from the divide; the text block is centred on
   the figure. `-flip` puts the figure on the right. */
.case-split {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  align-items: center;
}

.case-split > .case-aside { padding-left: var(--cs-aside-inset); }

.case-split-flip > .case-figure { order: 2; }
.case-split-flip > .case-aside { padding-left: 0; padding-right: var(--cs-aside-inset); }

/* Rows run on the figure rhythm, not the copy rhythm. */
.case-section > .case-split + .case-split { margin-top: var(--cs-split-gap); }

.case-aside .case-subhead + * { margin-top: var(--cs-subhead-body); }

/* ── Case study: numbered annotations ────────────────────── */
/* The list that labels callouts drawn on the figure beside it: an
   --ink disc with the number knocked out of it, then the label. */
.case-steps {
  counter-reset: step;
  color: var(--muted);
  font-size: var(--size-copy);
  line-height: var(--leading-copy);
}

.case-steps li {
  position: relative;
  min-height: var(--step);
  padding-left: calc(var(--step) + 8px);
  display: flex;
  align-items: center;
}

.case-steps li + li { margin-top: var(--cs-step-gap); }

.case-steps li::before {
  counter-increment: step;
  content: counter(step);
  position: absolute;
  left: 0;
  top: 50%;
  margin-top: calc(var(--step) / -2);
  width: var(--step);
  height: var(--step);
  border-radius: 50%;
  background: var(--ink);
  color: var(--bg);
  display: grid;
  place-items: center;
  font-size: 12px;
  line-height: 1;
}

/* A list with no bold lead-ins — the whole item is muted. */
.case-list-plain b { color: inherit; }

/* A caption the design sets in --ink, above the figure it describes,
   smaller than body copy. The export measures these at 13.25px, which
   is a scaled text layer rather than a step on the scale; 14px is the
   nearest real size and keeps them on the one line the design has —
   at 16px they wrap and push the whole page down. */
.case-caption {
  color: var(--ink);
  font-size: var(--size-body);
  line-height: var(--leading-copy);
}

/* ── Cursor dot ──────────────────────────────────────────── */
/* Positioned by main.js; the system cursor stays. Three states: a bare
   dot, grown over anything clickable, or stretched into a labelled
   pill over an element carrying data-cursor. The radius is a flat
   999px rather than 50% so the circle and the pill are the same shape
   rule and morph between each other. */
.cursor-dot {
  position: fixed;
  top: 0;
  left: 0;
  width: var(--dot);
  height: var(--dot);
  margin: calc(var(--dot) / -2);   /* transform origin at the centre */
  border-radius: 999px;
  background: var(--ink);
  color: var(--bg);                /* the label is knocked out of it */
  pointer-events: none;
  z-index: 10;
  will-change: transform;
  display: grid;
  place-items: center;
  overflow: hidden;                /* the label is revealed as it widens */
  white-space: nowrap;
  transition: width 0.25s ease-out, height 0.25s ease-out,
              margin 0.25s ease-out;
}
.cursor-dot[hidden] { display: none; }

.cursor-dot.is-hovering {
  width: var(--dot-hover);
  height: var(--dot-hover);
  margin: calc(var(--dot-hover) / -2);
}

/* Labelled: main.js sets the width from the text, so only the height
   and its half-offset belong here. */
.cursor-dot.is-labelled {
  height: var(--dot-hover);
  margin-top: calc(var(--dot-hover) / -2);
}

/* main.js measures its ruler with this class too, so the pill fits. */
.cursor-label {
  font-size: var(--size-cursor);
  opacity: 0;
  transition: opacity var(--hover-fade);
}

.cursor-dot.is-labelled .cursor-label { opacity: 1; }

/* ── Reduced motion ──────────────────────────────────────── */
/* The dot stops easing and stops resizing; main.js also drops its lerp
   and follows the pointer directly. */
@media (prefers-reduced-motion: reduce) {
  .cursor-dot { transition: none; }
}

/* ── Responsive (ADR-0004) ───────────────────────────────── */
/* Everything above is the desktop layout, tuned to the 1440px frame.
   These overrides take over at 1024px and below, each block narrowing
   the one before it; above 1024px none of them applies, so desktop is
   unchanged. Tokens are redefined where they can be, so components
   keep reading the same names. */

/* ── Responsive: tablet landscape and below ──────────────── */
/* The fixed name and rail become one header bar with a background,
   content takes the full width, headings scale, and every link and
   button is at least 44px square. */
@media (max-width: 1024px) {
  :root {
    --lede-top:  48px;
    --copy-top:  48px;
    --page-gap:  96px;
    --cs-top:     0px;      /* the hero sits right under the bar      */

    --size-lede:  clamp(40px, 5vw + 20px, 64px);
    --size-title: clamp(32px, 3vw + 20px, 48px);
    --size-heading: clamp(24px, 1.5vw + 18px, 32px);
    --leading-lede:    1.5em;   /* the desktop ratio, at any size     */
    --leading-title:   1.5em;
    --leading-heading: 1.5em;
  }

  body {
    padding-top: 0;
    grid-template-rows: var(--bar) 1fr auto;   /* row 1 holds the bar */
  }

  .site-header {
    height: var(--bar);
    padding: 0 var(--margin);
    background: var(--bg);
  }

  /* The margin is too narrow for the arrow to hang in, so it joins the
     line. */
  .back { column-gap: 0.4em; }

  .back-arrow {
    position: static;
    margin-top: 0;
  }

  .skip-link,
  .site-name a,
  .back,
  .nav-link,
  .nav-toggle,
  .site-footer a {
    display: inline-flex;
    align-items: center;
    min-width: var(--tap);
    min-height: var(--tap);
  }

  /* Work and About: inline at the right end of the bar. */
  .site-nav {
    top: 0;
    left: auto;
    right: var(--margin);
    height: var(--bar);
    display: flex;
    align-items: center;
    column-gap: var(--gutter);
  }

  /* Case studies: the section links fold under the bar behind the
     Sections button. Without JS there is no button, and they stay
     folded away. */
  .nav-link[href^="#"] { display: none; }

  .site-nav.is-foldable {
    top: var(--bar);
    left: 0;
    right: 0;
    height: auto;
    max-height: calc(100vh - var(--bar));
    overflow-y: auto;
    display: block;
    padding: 0 var(--margin);
    background: var(--bg);
  }

  .site-nav.is-foldable:has([aria-expanded="true"]) {
    padding-bottom: var(--gutter);
    border-bottom: 1px solid var(--rule);
  }

  /* Fixed to the viewport, not the folded list, so it stays in the bar. */
  .nav-toggle {
    position: fixed;
    top: 0;
    right: var(--margin);
    height: var(--bar);
  }

  .nav-toggle[aria-expanded="true"] ~ .nav-link { display: flex; }

  /* A jump to a section lands below the bar, not under it. */
  .case-section { scroll-margin-top: var(--bar); }

  .page {
    grid-column: 1 / -1;
    grid-template-columns: minmax(0, 1fr);
  }

  .page > *,
  .page > .copy { grid-column: 1 / -1; }

  .intro,
  .page > .copy,
  .exp { max-width: var(--cs-measure); }

  .case-hero { grid-column: 1 / -1; }
}

/* ── Responsive: tablet portrait and below ───────────────── */
/* One card per row. The forced line breaks in case study copy were set
   for the 684px measure; narrower, they break mid-line. */
@media (max-width: 768px) {
  .work { grid-template-columns: minmax(0, 1fr); }

  .copy br { display: none; }
}

/* ── Responsive: phones ──────────────────────────────────── */
/* Tighter margins, and everything that sits side by side stacks: the
   case study meta goes two by two, TUI's figure-and-steps rows and the
   Experience list go one above the other. */
@media (max-width: 480px) {
  :root {
    --margin: 16px;
    --gutter: 16px;
  }

  .case-meta {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--gutter);
  }

  .case-split {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--cs-block);
  }

  .case-split > .case-aside,
  .case-split-flip > .case-aside { padding: 0; }

  .case-split-flip > .case-figure { order: 0; }

  .exp-entry {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--cs-subhead-body);
  }
}
