/* -------------------------------------------------------------
   site.css — the shared design system
   -------------------------------------------------------------
   Every page links this file. It holds the tokens, the type scale,
   the resets, the nav and footer, and every component that is not
   unique to one page.

   Authored out of pm.html, which was the most complete page, so the
   values here are the scale-based ones rather than the ad-hoc sizes
   the earlier home page used.

   A page's own <style> block should only hold what genuinely belongs
   to that page and nothing else. If a second page needs a rule, it
   moves here.
------------------------------------------------------------- */

:root {
  --bg: #0F0D0B;
  --bg-deep: #090807;   /* the footer band, a shade under the page */
  --surface: #1A1815;
  --surface-hi: #232019;
  --text: #F0EBE0;
  --muted: #6B655C;
  --dim: #3A3630;
  --red: #E2513A;
  --red-deep: #B33420;
  --yellow: #E8B84A;
  --green: #3F6B47;
  --green-text: #5C9367;  /* --green is 3.1:1 on --bg, under AA; this is for text */
  --teal: #2BB8A6;
  --teal-line: rgba(43, 184, 166, 0.38); /* the teal as a hairline, not a stripe */
  /* the same teal as a wave, tiled: the closing marks are the one place
     on the site that is not ruled straight */
  --teal-wave: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='6' viewBox='0 0 24 6'%3E%3Cpath d='M0 3 Q3 0.6 6 3 T12 3 T18 3 T24 3' fill='none' stroke='%232BB8A6' stroke-opacity='.55' stroke-width='1'/%3E%3C/svg%3E");
  --teal-soft: #5EBAAE;                  /* desaturated for large type, which vibrates at full chroma */
  --muted-hi: #9A9389; /* legible muted: 6.4:1 on --bg */

  --font-display: 'Bricolage Grotesque', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

  /* ---------------------------------------------------------
     TYPE SCALE — three text steps, four display steps.
     Nothing on this page uses a size outside this list.
     Hierarchy below body size is carried by color, not scale.
  --------------------------------------------------------- */
  --fs-micro: 12px;   /* editions, chips, plate notes, pager label */
  --fs-small: 14px;   /* nav, buttons, labels, captions, footer */
  --fs-body: 17px;    /* every piece of reading copy */

  --fs-d4: 1.15rem;                        /* sub-heads */
  --fs-d3: clamp(1.5rem, 3vw, 2.25rem);    /* card titles, pull quote */
  --fs-d2: clamp(2rem, 4.5vw, 3.25rem);    /* case titles, big numbers */
  --fs-d1: clamp(2.75rem, 8vw, 6rem);      /* page headline */

  /* optical size is bound to each display step so they never drift apart */
  --vs-d4: "opsz" 24;
  --vs-d3: "opsz" 48;
  --vs-d2: "opsz" 72;
  --vs-d1: "opsz" 96;

  /* just off a hard corner; the print language wants edges, not pills */
  --radius: 4px;

  --gutter: clamp(1.5rem, 6vw, 5rem);

  /* measured by JS on load and resize; these are sane fallbacks */
  --nav-h: 57px;
  --subnav-h: 45px;
}

*, *::before, *::after { box-sizing: border-box; }
/* the <symbol> sprite is markup, not layout: an <svg> with no width or
   height defaults to 300x150 and would push the page down */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
/* the deep colour, not the page colour: with no background here the canvas
   takes body's --bg, so overscrolling past the footer showed a lighter
   strip under the darker footer band. Now the rubber-band area continues
   the footer instead of interrupting it. */
html {
  scroll-behavior: smooth;
  background: var(--bg-deep);
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  /* clip, not hidden: hidden makes body a scroll container and breaks position:sticky */
  overflow-x: clip;
}
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
}
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
::selection { background: var(--red); color: var(--text); }

/* -------------------------------------------------------------
   NAV
------------------------------------------------------------- */
.nav {
  position: sticky; top: 0;
  background: rgba(15, 13, 11, 0.85);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  z-index: 50;
  border-bottom: 1px solid var(--dim);
}
.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  padding: 0.9rem var(--gutter);
  max-width: 1600px;
  margin: 0 auto;
}
.nav__brand {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--fs-d4);
  letter-spacing: -0.01em;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
}
/* The squid-nib mark. Inlined rather than masked or linked so it inherits
   currentColor and renders over file:// as well as http. */
.nav__brand-mark {
  width: 34px;
  height: auto;
  flex: none;
  color: var(--teal);
  transition: color 200ms ease;
}
.nav__brand:hover .nav__brand-mark { color: var(--text); }
.nav__links {
  display: flex;
  gap: 2.25rem;
  list-style: none;
  padding: 0; margin: 0;
  align-items: center;
}
.nav__link {
  font-size: var(--fs-small);
  color: var(--muted);
  padding: 0.5rem 0;
  position: relative;
  transition: color 180ms ease;
}
.nav__link:hover { color: var(--text); }
.nav__link[aria-current="page"] { color: var(--text); }
.nav__link[aria-current="page"]::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  bottom: -1px;
  height: 3px;
  background: var(--red);
  /* deliberate rough edge, like a linocut mark */
  clip-path: polygon(0 0, 8% 100%, 22% 30%, 40% 100%, 55% 20%, 70% 100%, 85% 40%, 100% 100%, 100% 0);
}
@media (max-width: 780px) {
  .nav__links { gap: 1.25rem; }
  .nav__link { font-size: var(--fs-micro); }
}
@media (max-width: 560px) {
  .nav__inner { padding: 1rem 1.25rem; gap: 1rem; }
  /* Five links plus the wordmark overflow a 390px viewport, which pushes
     the document wider than the screen. Zeroing the brand's font-size drops
     the wordmark and keeps the mark, which is sized in px. Done in CSS
     because partials/nav.html is shared with every other page. */
  .nav__brand { font-size: 0; gap: 0; }
  .nav__links { gap: 1.1rem; }
}

/* -------------------------------------------------------------
   PRIMITIVES
------------------------------------------------------------- */
.container {
  max-width: 1600px;
  margin: 0 auto;
  padding: 0 var(--gutter);
}
/* block padding only. The shorthand would also set padding-inline: 0, and
   because .section is declared after .container at the same specificity it
   would win on <section class="container section"> and run every page flush
   to the viewport edge. */
.section { padding-block: clamp(4rem, 8vw, 7rem); }

.edition {
  font-family: var(--font-body);
  font-size: var(--fs-micro);
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0.02em;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}
.edition::before {
  content: '';
  width: 24px; height: 1px;
  background: var(--red);
}
.edition--right::before { content: none; }
.edition--right::after {
  content: '';
  width: 24px; height: 1px;
  background: var(--red);
  margin-left: 0.5rem;
}

.highlight {
  background: var(--red);
  color: var(--text);
  padding: 0 0.2em 0.05em;
  display: inline-block;
  line-height: 1;
}

.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--text);
  padding: 0.75rem 1.25rem;
  background: transparent;
  border: 1px solid var(--dim);
  border-radius: var(--radius);
  transition: background 200ms ease, border-color 200ms ease;
}
.btn:hover {
  background: var(--teal);
  border-color: var(--teal);
  /* bone-on-teal was too close in lightness to read cleanly; the icon
     inherits this via currentColor too */
  color: var(--bg);
}
.btn svg { transition: transform 200ms ease; }
.btn:hover svg { transform: translateX(3px); }

/* -------------------------------------------------------------
   PAGE HEAD
------------------------------------------------------------- */
/* block padding only, for the same reason .section uses it: the shorthand
   would reset .container's gutter on <header class="container pagehead"> */
.pagehead {
  /* 1.25rem top to match .hero on the index, so the gap between the nav
     and the Ed. mark is the same on every page */
  padding-block: 1.25rem clamp(3rem, 6vw, 4.5rem);
  position: relative;
}
.pagehead__masthead {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 2rem;
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
  flex-wrap: wrap;
}
.pagehead__frame {
  display: grid;
  grid-template-columns: 1fr;
  gap: 3rem;
  position: relative;
  z-index: 2;
}
@media (min-width: 900px) {
  .pagehead__frame {
    grid-template-columns: minmax(0, 5fr) minmax(0, 3fr);
    gap: 4rem;
    align-items: start;
  }
  /* the headline's cap-height starts below its own line box, so a column
     aligned to the grid reads as sitting high next to it */
  .pagehead__meta { padding-top: 10px; }
}
.pagehead__headline {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d1);
  font-size: var(--fs-d1);
  line-height: 0.95;
  letter-spacing: -0.03em;
  margin: 0;
}
.pagehead__headline .stack { display: block; }
.pagehead__quote { margin-top: clamp(2rem, 4vw, 3rem); }
.pagehead__meta {
  font-size: var(--fs-body);
  color: var(--muted-hi);
  line-height: 1.55;
  max-width: 54ch;
}
/* The case pages' hero note is alone in the right column against a
   headline stack two or three tiers tall. At body size it read as a
   caption floating at the top of an empty column, so it takes the display
   face, a step up in size, and a short measure that stacks it into more
   lines. Scoped to the aside: About's note is a div carrying
   pagehead__quote, and its second paragraph is long enough that this
   measure would run it to fifteen lines. */
aside.pagehead__meta {
  font-family: var(--font-display);
  font-weight: 400;
  font-variation-settings: "opsz" 32;
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  line-height: 1.4;
  letter-spacing: -0.01em;
  color: var(--muted-hi);
  text-wrap: pretty;
  max-width: 26ch;
}
@media (min-width: 900px) {
  /* centred against the headline stack rather than sitting at its top
     edge, and nudged off its own left edge so it does not line up with
     the column boundary */
  aside.pagehead__meta { align-self: center; margin-left: 5%; }
}

.pagehead__meta p { margin: 0 0 1rem; }
.pagehead__meta p:last-child { margin-bottom: 0; }
.pagehead__meta strong { color: var(--text); font-weight: 600; }
.pagehead__block {
  position: absolute;
  top: 20%; right: -6%;
  width: 320px; height: 320px;
  background: var(--red);
  opacity: 0.07;
  transform: rotate(-10deg);
  z-index: 1;
  pointer-events: none;
}

/* -------------------------------------------------------------
   CASE INDEX — two entry cards
------------------------------------------------------------- */
.caseindex {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  /* no rule above: the cards are filled panels and already read as a
     separate band off the page head */
  padding-top: 2.5rem;
  /* the cards need to sit clear of the rule that opens the first case,
     otherwise they read as welded to it */
  margin-bottom: clamp(3rem, 6vw, 4.5rem);
}
@media (min-width: 720px) and (max-width: 899px) {
  .caseindex { grid-template-columns: 1fr 1fr; gap: 1.25rem; }
}
.caseindex__item {
  background: var(--surface);
  /* softer than the 4px --radius the plates and controls use: these are
     the only large filled panels on the page */
  border-radius: 10px;
  padding: 1.15rem 1.25rem 1.3rem;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  column-gap: 1rem;
  row-gap: 0.35rem;
  position: relative;
  overflow: hidden;
  transition: background 200ms ease;
}
.caseindex__item:hover { background: var(--surface-hi); }
.caseindex__item:hover .caseindex__title { color: var(--teal-soft); }
.caseindex__tag {
  font-size: var(--fs-micro);
  font-weight: 500;
  color: var(--teal);
  grid-column: 1;
}
.caseindex__arrow-wrap { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
.caseindex__arrow { width: 20px; height: 20px; transition: transform 250ms ease; }
.caseindex__item:hover .caseindex__arrow { transform: translateY(4px); }
.caseindex__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d3);
  font-size: var(--fs-d3);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0;
  grid-column: 1;
  transition: color 200ms ease;
}
.caseindex__desc {
  font-size: var(--fs-small);
  color: var(--muted-hi);
  margin: 0.15rem 0 0;
  grid-column: 1;
  text-wrap: pretty;
}

@media (min-width: 900px) {
  .caseindex { grid-template-columns: 1fr 1fr; gap: 1.25rem; }
  /* one row instead of a stack: the name sits beside its description
     rather than above it, which halves the height of the tile */
  .caseindex__item {
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    column-gap: 1.75rem;
    /* the tag and the title are one unit and want air between them. The
       gap only looked right on Design because its descriptions run four
       lines, and .caseindex__desc spans both rows: a tall description
       stretches the rows, and align-items: center then spreads the pair
       out. Short descriptions gave no such gift, so it is set here. */
    row-gap: 0.6rem;
    padding: 1.1rem 1.35rem;
  }
  .caseindex__tag { grid-column: 1; grid-row: 1; }
  .caseindex__title { grid-column: 1; grid-row: 2; }
  .caseindex__desc { grid-column: 2; grid-row: 1 / span 2; margin: 0; }
  .caseindex__arrow-wrap { grid-column: 3; grid-row: 1 / span 2; }
}

/* -------------------------------------------------------------
   CASE SUB-NAV
   The two entry cards hand off to this bar as they tuck under the
   main nav: cards lift and fade upward, the bar slides down from
   behind the nav. Only ever one of the two on screen.
   Fixed rather than sticky so it costs no layout space while hidden.
------------------------------------------------------------- */
.cases { position: relative; }

.subnav {
  position: fixed;
  top: var(--nav-h);
  left: 0; right: 0;
  z-index: 40;
  background: rgba(15, 13, 11, 0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--dim);

  /* hidden state: tucked up behind the main nav */
  visibility: hidden;
  opacity: 0;
  transform: translateY(-100%);
  transition: opacity 240ms ease, transform 300ms cubic-bezier(0.2, 0.7, 0.3, 1), visibility 0s linear 300ms;
}
.subnav.is-visible {
  visibility: visible;
  opacity: 1;
  transform: translateY(0);
  transition: opacity 200ms ease, transform 300ms cubic-bezier(0.2, 0.7, 0.3, 1), visibility 0s;
}

/* the cards being handed off. No transition here on purpose: opacity and
   offset are driven directly by scroll position, so easing them would
   make the cards lag behind the scroll. */
.caseindex { will-change: opacity, transform; }
.subnav__inner {
  max-width: 1600px;
  margin: 0 auto;
  padding: 0 var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}
.subnav__links {
  display: flex;
  gap: 1.75rem;
  list-style: none;
  margin: 0; padding: 0;
}
.subnav__link {
  display: block;
  font-size: var(--fs-small);
  color: var(--muted);
  padding: 0.8rem 0;
  position: relative;
  transition: color 180ms ease;
}
.subnav__link:hover { color: var(--text); }
.subnav__link.is-active { color: var(--text); }
.subnav__link.is-active::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  bottom: 0.35rem;
  height: 3px;
  background: var(--red);
  /* same cut edge as the main nav */
  clip-path: polygon(0 0, 8% 100%, 22% 30%, 40% 100%, 55% 20%, 70% 100%, 85% 40%, 100% 100%, 100% 0);
}
.subnav__count {
  font-size: var(--fs-micro);
  color: var(--muted);
  font-weight: 500;
  white-space: nowrap;
}
/* how much of the case studies is left, read as a filling rule */
.subnav__progress {
  position: absolute;
  left: 0; bottom: -1px;
  height: 1px;
  width: 0;
  background: var(--red);
  transform-origin: left;
}
@media (max-width: 560px) {
  .subnav__links { gap: 1.1rem; }
  .subnav__link { font-size: var(--fs-micro); }
  .subnav__count { display: none; }
}

/* -------------------------------------------------------------
   CASE STUDY
------------------------------------------------------------- */
.case {
  position: relative;
  /* transparent rather than removed: the aside's cut rule already closes
     the previous case, so a grey hairline right under it is a second
     divider doing the same job. The border stays in the box so the
     spacing does not move, and so the anchor landing still has an edge
     to turn teal. */
  border-top: 1px solid transparent;
  transition: border-top-color 800ms ease;
  /* .section above already contributes clamp(4rem, 8vw, 7rem); this is
     just the extra clearance for the anchor-landing wash and the cut
     rule, not a second full section gap */
  padding-top: clamp(1rem, 2vw, 1.5rem);
  /* the aside is ruled top and bottom now, so it needs air after it
     rather than butting straight into whatever comes next */
  padding-bottom: clamp(3.5rem, 7vw, 5.5rem);
  /* clear both bars when jumped to by anchor */
  scroll-margin-top: calc(var(--nav-h) + var(--subnav-h));
}

/* anything deep-linked from another page (#think-green) has to clear the
   two sticky bars the same way a whole .case does */
.block[id], .tag-head[id] {
  scroll-margin-top: calc(var(--nav-h) + var(--subnav-h));
}
/* where the anchor landed: a teal wash off the top edge that burns off
   as soon as the reader starts scrolling again */
.case::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  top: calc(-1 * var(--land-rise, 0px));
  height: calc(320px + var(--land-rise, 0px));
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(43, 184, 166, 0.16), rgba(43, 184, 166, 0));
  opacity: 0;
  transition: opacity 900ms ease;
}
/* a case that follows another one starts its wash at the cut rule closing
   the aside above, not at its own top edge. The rise is exactly the
   previous case's padding-bottom, since the aside is its last child. */
.case + .case { --land-rise: clamp(3.5rem, 7vw, 5.5rem); }
/* the last case ends on the pager, and the section padding below it is
   already the gap to the footer: two of them stacked left a dead screen */
.case:last-child { padding-bottom: 0; }
.case.is-landed { border-top-color: var(--teal); }
/* and then the teal edge is the cut rule itself, so the border would be a
   second teal line stranded inside the wash */
.case + .case.is-landed { border-top-color: transparent; }
.case.is-landed::after { opacity: 1; transition: opacity 220ms ease; }
.case + .case { margin-top: 0; }

.case__head {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}
@media (min-width: 900px) {
  .case__head { grid-template-columns: minmax(0, 4fr) minmax(0, 5fr); gap: clamp(2rem, 4vw, 3rem); align-items: end; }
}
.case__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d2);
  font-size: var(--fs-d2);
  line-height: 1.02;
  letter-spacing: -0.025em;
  margin: 0.75rem 0 0;
}
.case__lede {
  font-size: var(--fs-body);
  color: var(--text);
  line-height: 1.6;
  margin: 0;
  max-width: 60ch;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--fs-micro);
  font-weight: 500;
  color: var(--teal);
  border: 1px solid rgba(43, 184, 166, 0.4);
  border-radius: var(--radius);
  padding: 0.3rem 0.6rem;
  margin-top: 1rem;
}
.chip::before {
  content: '';
  width: 5px; height: 5px;
  background: var(--teal);
  border-radius: 999px;
}

/* Body copy blocks. The label used to sit in a left rail, where it was
   quiet enough to scroll straight past. It is now a ruled header directly
   over its own content, carrying the same red tick as the edition marks. */
.block { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
/* header row: the label, and where there is one, the sentence that
   introduces the section, both above the same rule */
.block__head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.4rem 1.75rem;
  margin: 0 0 1.5rem;
  padding-bottom: 0.85rem;
  border-bottom: 1px solid var(--dim);
}
/* position: relative is kept for the centred variant on Design, which
   flanks the label with its own red rules rather than leading with one */
/* a real step above body copy. At --fs-d4 these sat within a pixel or two
   of the paragraphs beneath them, so a section header read as a bold line
   rather than as the start of a section. Still below .tag-head, which is
   the bigger beat for a named body of work. */
.block__label {
  position: relative;
  flex: none;
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: "opsz" 32;
  font-size: clamp(1.4rem, 2.2vw, 1.75rem);
  letter-spacing: -0.015em;
  color: var(--text);
  margin: 0;
}
/* A centred tag flanked by short red rules, like the case-close marks, for
   a named body of work that wants its own beat on the page rather than the
   standard left-set .block__head. Used by Dear Walter and Running with
   Scissors on Studio, and Connect Everything on Design. */
.tag-head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin: clamp(2.5rem, 5vw, 4rem) 0 1.5rem;
}
.tag-head::before, .tag-head::after {
  content: '';
  flex: 1 1 0;
  max-width: 3rem;
  height: 1px;
  background: var(--red);
}
.tag-head span {
  flex: none;
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d3);
  font-size: var(--fs-d3);
  letter-spacing: -0.01em;
  color: var(--text);
}

.block__lead {
  margin: 0;
  flex: 1 1 24ch;
  color: var(--muted-hi);
  font-size: var(--fs-body);
  text-wrap: pretty;
}
@media (min-width: 900px) {
  /* pushed to the far edge so the header reads label-left, sentence-right,
     rather than as two things floating mid-row */
  .block__lead { text-align: right; }
}
.prose { max-width: 72ch; }
/* one-sentence intros: a paragraph measure just makes them orphan */
.prose--lead { max-width: 94ch; }
.prose p { margin: 0 0 1.25rem; color: var(--muted-hi); }
.prose p:last-child { margin-bottom: 0; }
.prose strong { color: var(--text); font-weight: 600; }
.prose em { color: var(--text); font-style: normal; font-weight: 500; }
.prose h4 {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d4);
  font-size: var(--fs-d4);
  letter-spacing: -0.01em;
  color: var(--text);
  margin: 2rem 0 0.75rem;
}
.prose h4:first-child { margin-top: 0; }

/* Spec list — the Harbor IA */
.spec { list-style: none; padding: 0; margin: 0; max-width: 76ch; counter-reset: spec; }
.spec li {
  counter-increment: spec;
  display: grid;
  grid-template-columns: 2.5rem 1fr;
  gap: 0 1rem;
  /* unruled: the numbers already separate the items, and nine hairlines
     under the header's own rule read as a table. The header rule stays. */
  padding: 0.7rem 0;
  font-size: var(--fs-body);
  color: var(--muted-hi);
}
/* the block header already draws a rule directly above, so the first
   item's own top border was a second hairline in the same gap */
.owned li:first-child { border-top: 0; }

.spec li::before {
  content: counter(spec, decimal-leading-zero);
  color: var(--red);
  font-size: var(--fs-micro);
  font-weight: 500;
  padding-top: 0.28rem;
}
.spec strong {
  display: block;
  color: var(--text);
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d4);
  font-size: var(--fs-d4);
  letter-spacing: -0.01em;
  margin-bottom: 0.15rem;
}

/* Plates — screenshots, framed like a print plate */
.plate {
  background: var(--surface);
  border: 1px solid var(--dim);
  position: relative;
  overflow: hidden;
  display: block;
  width: 100%;
  padding: 0;
  margin: 0;
  cursor: zoom-in;
  transition: border-color 200ms ease;
  /* these matter because most plates are button elements */
  -webkit-appearance: none;
  appearance: none;
  border-radius: var(--radius);
  color: inherit;
  font: inherit;
  text-align: left;
}
.plate:focus-visible { outline: 2px solid var(--red); outline-offset: 2px; }
.plate:hover { border-color: var(--red); }
.plate img { width: 100%; height: auto; }
/* subtle plate tooth over the screenshot, keeps it from reading as a raw screengrab */
.plate::after {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(135deg, transparent 0 14px, rgba(240, 235, 224, 0.014) 14px 15px);
  pointer-events: none;
}
.plate__zoom {
  position: absolute;
  right: 0.6rem; bottom: 0.6rem;
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15, 13, 11, 0.8);
  border: 1px solid var(--dim);
  border-radius: var(--radius);
  color: var(--text);
  /* always on: it is what says the plate opens */
  transition: color 200ms ease, border-color 200ms ease;
  pointer-events: none;
  z-index: 2;
}
.plate:hover .plate__zoom,
.plate:focus-visible .plate__zoom { color: var(--red); border-color: var(--red); }

/* Empty plate, for slots still waiting on artwork */
.plate--empty {
  aspect-ratio: 16 / 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  text-align: center;
  padding: 1.5rem;
  cursor: default;
}
.plate--empty:hover { border-color: var(--dim); }
.plate__mark {
  width: 28px; height: 28px;
  border: 1px solid var(--red);
  opacity: 0.5;
  transform: rotate(45deg);
}
.plate__note {
  font-size: var(--fs-micro);
  color: var(--muted-hi);
  max-width: 42ch;
  line-height: 1.5;
}

/* Two plates side by side inside one walkthrough slot */
.plate-pair { display: grid; grid-template-columns: 1fr; gap: 0.75rem; }
@media (min-width: 560px) { .plate-pair { grid-template-columns: 1fr 1fr; } }

/* The whole page as one sheet: a thumbnail beside the list it illustrates,
   small enough to read as a shape rather than as a screenshot, with the
   detail one click away in the lightbox. */
/* The sheet runs alongside two sections at once: it starts beside "The
   model" and carries on down past the architecture list. */
.spread { display: grid; grid-template-columns: 1fr; gap: 2rem; }
@media (min-width: 900px) {
  .spread {
    grid-template-columns: minmax(0, 1fr) minmax(0, clamp(375px, 41vw, 585px));
    column-gap: clamp(2rem, 4vw, 3.5rem);
    align-items: start;
  }
}
.spread { margin-bottom: clamp(3.5rem, 7vw, 5.5rem); }
.spread__copy > .block:last-child { margin-bottom: 0; }
/* The sheet is a full top-to-bottom capture, nearly 3.2:1 tall, so at the
   widened column it ran on for much longer than the nine-item list beside
   it: the copy ran out, and the page kept scrolling through empty space
   under it while the image scrolled past on its own. Pinning it like the
   walkthrough's viewer keeps it in view without forcing that extra scroll,
   and it stays a compact "shape," which was the point, rather than a
   full-detail read: the lightbox is still where the detail lives. */
@media (min-width: 900px) {
  .spread__shot {
    position: sticky;
    top: calc(var(--nav-h) + var(--subnav-h) + 2rem);
  }
}
.plate--sheet { display: block; }
.plate--sheet img {
  width: 100%;
  height: auto;
  max-height: calc(100vh - var(--nav-h) - var(--subnav-h) - 5rem);
  object-fit: contain;
}
.plate__enlarge {
  position: absolute;
  left: 50%; bottom: 0.75rem;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--fs-micro);
  font-weight: 500;
  color: var(--text);
  background: rgba(15, 13, 11, 0.9);
  border: 1px solid var(--dim);
  border-radius: var(--radius);
  padding: 0.35rem 0.7rem;
  white-space: nowrap;
  pointer-events: none;
  /* always on: it is the only thing telling you the sheet opens */
  transition: color 200ms ease, border-color 200ms ease;
  z-index: 2;
}
.plate--sheet:hover .plate__enlarge,
.plate--sheet:focus-visible .plate__enlarge {
  color: var(--red);
  border-color: var(--red);
}

figure { margin: 0; }
figcaption {
  font-size: var(--fs-small);
  color: var(--muted-hi);
  margin-top: 0.75rem;
  max-width: 74ch;
}
/* a second sentence starts its own line rather than trailing off the end of
   the first, which strands its opening words away from the rest of it */
figcaption .line { display: block; }


/* -------------------------------------------------------------
   WRAPPING
   The measures above set how wide text may run; these set how it
   breaks. `balance` evens out short blocks, `pretty` keeps running
   copy from ending on a single stranded word.
------------------------------------------------------------- */
.pagehead__headline, .case__title, .caseindex__title, .pull,
.prose h4, .walk__step h4, .spec strong,
.case__lede, .prose--lead, .stat__label, .plate__note {
  text-wrap: balance;
}
.prose p, .icyww p, .pagehead__meta p,
.caseindex__desc, figcaption, .spec li, .outcomes li {
  text-wrap: pretty;
}
/* -------------------------------------------------------------
   LIGHTBOX
   Doubles as a gallery for the walkthrough: the enlarged shot with its
   own heading and copy underneath, and arrows through the rest.
------------------------------------------------------------- */
.lb {
  position: fixed;
  inset: 0;
  background: rgba(15, 13, 11, 0.97);
  z-index: 100;
  display: none;
  overflow: hidden;              /* the panel manages its own scrolling */
  padding: clamp(1rem, 4vw, 3rem);
}
.lb.is-open { display: flex; }
.lb__inner {
  margin: auto;
  width: min(100%, 68rem);
  max-height: 100%;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}
/* the image gives up height first, down to a floor, so the copy below it
   always has room; it never scrolls out of view */
.lb__img {
  flex: 1 1 auto;
  min-height: 22vh;
  width: 100%;
  height: auto;
  object-fit: contain;
  object-position: center;
  border: 1px solid var(--dim);
  border-radius: var(--radius);
}
/* Gallery shots get one fixed frame rather than sizing off the flex row:
   the copy under each step is a different length, so letting the image
   give up height first made all six open at a different size even though
   they are all natively 16:10. */
.lb.has-gallery .lb__img {
  flex: none;
  align-self: center;
  width: min(100%, calc(56vh * 1.6));
  aspect-ratio: 16 / 10;
  height: auto;
  min-height: 0;
}
/* -------------------------------------------------------------
   DIAGRAM
   Coop's two explanatory graphics used to be JPEGs with the text
   baked into the pixels: not selectable, not resizable, not
   reachable by a screen reader beyond one paragraph of alt text.
   Rebuilt as real markup so the content is actual DOM text.

   Deliberately its own zone rather than another instance of the
   page's plain hairline lists: a raised surface panel, dashed cards
   on the unresolved side, a light stamped rotation, so it reads as
   an artifact set into the page rather than blending into the prose
   around it.
------------------------------------------------------------- */
/* no panel: with real boxes and lines drawn in the SVGs themselves, a
   surface card behind them read as a second, redundant container, more
   like a dashboard widget than more of the page's own text */
.diagram { }
.chip--green { color: var(--green-text); border-color: rgba(92, 147, 103, 0.5); }
.diagram__svg { width: 100%; height: auto; display: block; }
.diagram__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
}
@media (min-width: 720px) {
  .diagram__grid { grid-template-columns: 1fr 1fr; gap: clamp(2rem, 4vw, 3.5rem); }
  .diagram__grid--taxonomy { grid-template-columns: 1fr auto 1fr; }
}
.diagram__head {
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--muted);
  text-transform: uppercase;
  margin: 0 0 0.75rem;
}
/* the messy, pre-taxonomy side reads red; the resolved side reads green.
   Reinforces the before/after and people/machine splits already carried
   by the text, rather than replacing it. */
.diagram__head--before { color: var(--red); }
.diagram__head--after { color: var(--green-text); }
/* the transformation itself, between the two panels on wide screens */
.diagram__arrow {
  display: none;
}
@media (min-width: 720px) {
  .diagram__arrow {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--dim);
    font-size: 1.5rem;
  }
}
/* each row is its own bordered card, like the individual boxes the source
   diagram drew per department: a small tag, the category, then an arrow to
   what that team actually calls the product. One flat row per item read as
   thinner than the six-box original; three stacked lines reads the same. */
.diagram__rows { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.diagram__rows li {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.9rem 1.1rem;
  background: var(--bg);
  border: 1px solid var(--dim);
  border-radius: var(--radius);
}
/* the unresolved side: dashed rather than solid, like a provisional note
   rather than a settled record, tipped a couple of degrees off true so the
   stack of six reads as loose rather than as another dashboard table */
.diagram__rows--before li {
  position: relative;
  border-style: dashed;
  border-color: rgba(226, 81, 58, 0.45);
  transform: rotate(var(--tip, 0deg));
}
.diagram__rows--before li:nth-child(odd) { --tip: -0.6deg; }
.diagram__rows--before li:nth-child(even) { --tip: 0.5deg; }
/* a small conflict mark, standing in for the crossed lines the original
   diagram drew between boxes. Decorative: the "different label" fact is
   already stated in the row's own text. */
.diagram__rows--before li::after {
  content: '\00d7';
  position: absolute;
  top: 0.6rem; right: 0.75rem;
  font-size: 1rem;
  line-height: 1;
  color: var(--red);
  opacity: 0.5;
}
.diagram__dept {
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--red);
}
.diagram__dept--machine { color: var(--green-text); }
.diagram__cat {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d4);
  font-size: var(--fs-body);
  color: var(--text);
}
.diagram__val { font-size: var(--fs-small); color: var(--muted-hi); }
.diagram__sku {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d4);
  font-size: var(--fs-d4);
  color: var(--text);
  margin: 0 0 1.25rem;
}
.diagram__sku .chip { margin-top: 0; }
.diagram__sku-sub {
  font-size: var(--fs-small);
  color: var(--muted-hi);
  margin: -0.75rem 0 1.25rem;
}
.diagram__attrs { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
.diagram__attrs-label {
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--text);
  margin: 0 0 0.6rem;
}
.diagram__attrs-label span {
  font-weight: 400;
  color: var(--muted);
  font-size: var(--fs-micro);
}
.diagram__tags { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem; }
.diagram__tags li {
  font-size: var(--fs-micro);
  color: var(--muted-hi);
  background: var(--bg);
  border: 1px solid var(--dim);
  border-radius: var(--radius);
  padding: 0.3rem 0.6rem;
}

/* the full-page capture is the exception: it is meant to be scrolled */
.lb.is-tall { overflow-y: auto; }
.lb.is-tall .lb__inner { width: min(100%, 75rem); max-height: none; }
.lb.is-tall .lb__img { flex: none; min-height: 0; }
.lb.is-tall .lb__body { overflow: visible; max-height: none; min-height: 0; }

.lb__meta {
  flex: 0 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.lb__meta-head { flex: none; display: flex; align-items: baseline; gap: 0.9rem; }
.lb__num {
  font-size: var(--fs-micro);
  font-weight: 500;
  color: var(--red);
  flex: none;
}
.lb__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d4);
  font-size: var(--fs-d4);
  letter-spacing: -0.01em;
  color: var(--text);
  margin: 0;
}
/* scrolls inside itself, and never shrinks below four lines */
.lb__body {
  flex: 1 1 auto;
  min-height: 6.7em;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--dim) transparent;
}
.lb__body::-webkit-scrollbar { width: 8px; }
.lb__body::-webkit-scrollbar-track { background: transparent; }
.lb__body::-webkit-scrollbar-thumb { background: var(--dim); }
.lb__body p {
  margin: 0 0 0.9rem;
  color: var(--muted-hi);
  font-size: var(--fs-body);
  /* wider than a page measure on purpose: in a modal the copy is short
     and the container is wide, so 74ch was inventing line breaks */
  max-width: 92ch;
  text-wrap: pretty;
}
.lb__body p:last-child { margin-bottom: 0; }
.lb__body .walk__note { color: var(--muted-hi); }

/* mobile: the copy stays clamped until asked for */
.lb__more {
  display: none;
  align-self: flex-start;
  flex: none;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  border: 1px solid var(--dim);
  border-radius: var(--radius);
  padding: 0.35rem 0.7rem;
  font: inherit;
  font-size: var(--fs-micro);
  font-weight: 500;
  color: var(--text);
  cursor: pointer;
  transition: border-color 200ms ease, color 200ms ease;
}
.lb__more:hover { color: var(--red); border-color: var(--red); }
@media (max-width: 700px) {
  .lb__body { max-height: 6.7em; }
  .lb.is-expanded .lb__body { max-height: 45vh; }
  .lb.has-more .lb__more { display: inline-flex; }
}
.lb:not(.has-meta) .lb__meta-head { display: none; }

/* controls */
.lb__close, .lb__nav {
  position: fixed;
  width: 44px; height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(15, 13, 11, 0.85);
  border: 1px solid var(--dim);
  border-radius: var(--radius);
  color: var(--text);
  line-height: 1;
  cursor: pointer;
  z-index: 2;
  transition: background 200ms ease, border-color 200ms ease, opacity 200ms ease;
}
.lb__close, .lb__nav { border-radius: 50%; }
.lb__close { top: 1rem; right: 1rem; font-size: var(--fs-d4); }
.lb__nav { top: 50%; transform: translateY(-50%); }
.lb__nav--prev { left: clamp(0.5rem, 2vw, 1.75rem); }
.lb__nav--next { right: clamp(0.5rem, 2vw, 1.75rem); }
.lb__close:hover, .lb__nav:hover { background: var(--red); border-color: var(--red); }
.lb__close:focus-visible, .lb__nav:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; }
/* only the walkthrough is a gallery */
.lb:not(.has-gallery) .lb__nav { display: none; }
@media (max-width: 700px) {
  .lb__nav { top: auto; bottom: 1rem; transform: none; }
}

/* -------------------------------------------------------------
   WALKTHROUGH — sticky viewer
   Six stacked rows of copy-beside-screenshot read as one thing
   repeated six times. Instead the screenshot pins and swaps while
   the copy scrolls past it, so only one image is ever on screen.
------------------------------------------------------------- */
.walk { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
@media (min-width: 900px) {
  .walk {
    grid-template-columns: minmax(0, 4fr) minmax(0, 5fr);
    gap: clamp(2rem, 4vw, 4rem);
    align-items: start;
  }
}

.walk__pin {
  position: sticky;
  top: calc(var(--nav-h) + var(--subnav-h));
  order: -1;                    /* image above the copy on narrow screens */
  z-index: 1;
}
.walk__stage { position: relative; height: 40vh; }
/* On one column the steps scroll behind the pinned image. With nothing
   behind it they showed straight through the frame, so the pin carries the
   page's own ground and a rule under it: the copy disappears cleanly under
   the image instead of colliding with it. The stage also gives back some
   height, since the nav, the subnav and the pin were leaving little room
   to read in. */
@media (max-width: 899px) {
  .walk__pin {
    background: var(--bg);
    padding: 0.75rem 0 0.9rem;
    border-bottom: 1px solid var(--dim);
  }
  .walk__stage { height: 32vh; }
}
@media (min-width: 900px) {
  .walk__pin {
    order: 2;                   /* and beside it, on the right, on desktop */
    top: calc(var(--nav-h) + var(--subnav-h) + 2rem);
  }
  .walk__stage { height: auto; aspect-ratio: 16 / 10; }
}

/* which of the six you are on, and how many are left */
.walk__nav { display: flex; gap: 0.5rem; margin-top: 0.9rem; }
.walk__dot {
  flex: 1 1 0;
  min-width: 0;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  border: 0;
  border-top: 2px solid var(--dim);
  border-radius: 0;
  padding: 0.45rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  font: inherit;
  font-size: var(--fs-micro);
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: border-color 200ms ease;
}
.walk__dot-num { color: var(--muted); transition: color 200ms ease; }
.walk__dot-name {
  color: var(--muted);
  line-height: 1.3;
  transition: color 200ms ease;
}
.walk__dot:hover { border-top-color: var(--muted); }
.walk__dot:hover .walk__dot-name { color: var(--text); }
.walk__dot:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; }
.walk__dot.is-active { border-top-color: var(--red); }
.walk__dot.is-active .walk__dot-num { color: var(--red); }
.walk__dot.is-active .walk__dot-name { color: var(--text); }
/* names do not survive six columns on a phone; the numbers still track */
@media (max-width: 700px) {
  .walk__dot-name { display: none; }
}

.walk__frame {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  opacity: 0;
  visibility: hidden;
  transition: opacity 300ms ease, visibility 0s linear 300ms;
}
.walk__frame.is-active {
  opacity: 1;
  visibility: visible;
  transition: opacity 300ms ease, visibility 0s;
}
.walk__frame .plate { flex: 1 1 0; min-width: 0; height: 100%; }
.walk__frame img { width: 100%; height: 100%; object-fit: contain; }

.walk__steps { display: flex; flex-direction: column; }
.walk__step {
  padding: 1.75rem 0;
  border-top: 1px solid var(--dim);
}
.walk__step:first-child { border-top: 0; padding-top: 0; }
@media (min-width: 900px) {
  .walk__step {
    /* the step height is the scroll pacing: it is how far you travel
       before the pinned shot swaps, not just a gap */
    min-height: 42vh;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    padding: 0 0 1.5rem;
    opacity: 0.45;
    transition: opacity 300ms ease;
  }
  .walk__step.is-active { opacity: 1; }
  /* PRD coverage and Tag filtering lost their notes, and Ticket detail /
     DRI detail are down to one short sentence each, so at the shared height
     there is nothing to slow a reader down before the next swap fires.
     Extra room for these four; 05 (Tag filtering) is actually the thinnest
     step on the page now, same one paragraph as 03. */
  .walk__steps .walk__step:nth-child(2),
  .walk__steps .walk__step:nth-child(3),
  .walk__steps .walk__step:nth-child(4),
  .walk__steps .walk__step:nth-child(5) { min-height: 54vh; }
  /* the last step reserved a full 62vh it never used, so the pinned shot
     kept riding down through half a screen of nothing before the section
     released. It ends on its own content instead. */
  /* the tail is sized against the pinned block, not the copy: the pin
     releases when the column bottom meets it, so the last step has to be
     about as tall as the shot for its rule to arrive level with the top
     of the image. Scales on vw because the stage does. */
  .walk__step:last-child {
    min-height: 0;
    padding-bottom: clamp(6rem, 12vw, 15rem);
  }
}
.walk__num {
  display: block;
  font-size: var(--fs-micro);
  font-weight: 500;
  color: var(--red);
  margin-bottom: 0.5rem;
}
.walk__step h4 {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d4);
  font-size: var(--fs-d4);
  letter-spacing: -0.02em;
  margin: 0 0 0.75rem;
}
.walk__step p {
  margin: 0 0 1rem;
  color: var(--muted-hi);
  font-size: var(--fs-body);
  max-width: 60ch;
  text-wrap: pretty;
}
.walk__note {
  color: var(--muted-hi) !important;
  border-left: 2px solid var(--red);
  padding-left: 0.9rem;
  margin-bottom: 0 !important;
}

/* -------------------------------------------------------------
   STAT ROW — Coop outcomes
   Three equal cells inside a hairline box read as a KPI widget from
   any analytics product. These are the loudest numbers on the page,
   so they get headline scale and uneven columns instead, with the
   colour left to a red tick under each. The band opens on the same
   tiled cut rule the case index uses rather than being fenced in.
------------------------------------------------------------- */
/* the caveat sits above the figures it qualifies, not in the closing note
   at the foot of the page where a reader meets it long after the numbers */
.stats__note {
  margin: 0 0 clamp(1.5rem, 3vw, 2.25rem);
  max-width: 62ch;
  font-size: var(--fs-small);
  color: var(--muted);
  text-wrap: pretty;
}

.stats {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.25rem 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='4' viewBox='0 0 48 4'%3E%3Cpath d='M0 1.6 6 1.05 11 2.15 17 1.25 23 2.3 29 1.1 35 1.95 41 1.15 48 1.6 48 2.9 0 2.9Z' fill='%233A3630'/%3E%3C/svg%3E");
  background-repeat: repeat-x;
  background-position: left top;
  background-size: 48px 4px;
  padding-top: clamp(2.25rem, 4vw, 3.25rem);
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}
@media (min-width: 720px) {
  .stats {
    grid-template-columns: 1.15fr 1fr 1.05fr;
    column-gap: clamp(1.75rem, 4vw, 4rem);
    align-items: start;
  }
}
.stat { display: flex; flex-direction: column; align-items: flex-start; }
.stat__num {
  font-family: var(--font-display);
  font-weight: 700;
  font-variation-settings: var(--vs-d1);
  font-size: var(--fs-d1);
  line-height: 0.85;
  letter-spacing: -0.05em;
  /* no fill and no colour coding: the numbers carry at this scale on
     their own, and the colour is left to the ticks */
  color: var(--text);
}
/* a tick, not a rule: three full-width lines would read as a table again */
/* no tick above the label: the figure it belongs to is already the
   largest thing on the page, so a rule between them separated a pair that
   reads as one unit. The label takes the body step rather than the small
   one, since these carry the evidence for the numbers above them. */
.stat__label {
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--muted-hi);
  max-width: 30ch;
  margin-top: 0.9rem;
  text-wrap: pretty;
}

/* The two closing sections run side by side, uneven because the list is
   four items against a single paragraph. Their header rules line up, so
   the pair reads as one closing spread. */
.closing { display: grid; grid-template-columns: 1fr; }
@media (min-width: 900px) {
  .closing {
    grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
    column-gap: clamp(2rem, 5vw, 5rem);
    align-items: start;
  }
  .closing > .block { margin-bottom: 0; }
}
/* both give up their own measure: the column is the measure now */
.closing .outcomes, .closing .prose { max-width: none; }

/* The problem: opens on a wide lede, then sets the argument in two
   columns so the section fills its rule instead of running as one
   narrow strip down the left. */
.problem__lede {
  margin: 0 0 clamp(1.5rem, 3vw, 2.25rem);
  /* plain body copy, not the display font's medium weight at a bigger size:
     that read as bold next to the paragraphs under it */
  font-size: var(--fs-body);
  line-height: 1.55;
  color: var(--muted-hi);
  /* wide enough to span the two columns beneath it at most window sizes,
     since a short lede stranded above a full-width pair reads as a
     different section */
  max-width: 96ch;
  text-wrap: balance;
}
.problem__cols p {
  margin: 0 0 1.25rem;
  color: var(--muted-hi);
  font-size: var(--fs-body);
  text-wrap: pretty;
  /* a paragraph split across the column break is unreadable when the
     columns are this tall */
  break-inside: avoid;
}
.problem__cols p:last-child { margin-bottom: 0; }
.problem__cols strong { color: var(--text); font-weight: 600; }
.problem__list {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
}
.problem__list li {
  position: relative;
  padding-left: 1.25rem;
  margin-bottom: 0.5rem;
  color: var(--muted-hi);
  font-size: var(--fs-body);
  /* a bullet split across the column break is unreadable at this height */
  break-inside: avoid;
}
.problem__list li:last-child { margin-bottom: 0; }
.problem__list li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.55em;
  width: 7px; height: 7px;
  background: var(--red);
}
@media (min-width: 900px) {
  .problem__cols { columns: 2; column-gap: clamp(2rem, 5vw, 5rem); }
  /* forces the second column to start here, so the six-item list ahead of
     it stays whole in column one instead of the browser's own column
     balancing splitting it wherever the halfway point happens to fall */
  .problem__col-start { break-before: column; }
}

/* What I owned: heading beside its copy rather than above it, so the
   three moves read as a sequence and the section stops leaving half the
   width empty. Ruled per item, the same language as the outcomes. */
.owned { list-style: none; padding: 0; margin: 0; counter-reset: owned; }
.owned li {
  counter-increment: owned;
  padding: 1.5rem 0;
  border-top: 1px solid var(--dim);
}
.owned li:last-child { border-bottom: 1px solid var(--dim); }
@media (min-width: 900px) {
  .owned li {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr);
    column-gap: clamp(2rem, 5vw, 5rem);
    align-items: start;
  }
}
.owned h4 {
  position: relative;
  margin: 0 0 0.6rem;
  padding-left: 2.4rem;
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d4);
  font-size: var(--fs-d4);
  letter-spacing: -0.02em;
  color: var(--text);
  text-wrap: balance;
}
.owned h4::before {
  content: '0' counter(owned);
  position: absolute;
  left: 0; top: 0.15em;
  font-family: var(--font-body);
  font-size: var(--fs-micro);
  font-weight: 500;
  /* red, like every other sequence number on the page */
  color: var(--red);
}
.owned p {
  margin: 0;
  color: var(--muted-hi);
  font-size: var(--fs-body);
  text-wrap: pretty;
}
.owned strong { color: var(--text); font-weight: 600; }
@media (min-width: 900px) { .owned h4 { margin-bottom: 0; } }

/* Outcome list */
.outcomes { list-style: none; padding: 0; margin: 0; max-width: 76ch; }
.outcomes li {
  /* no rule between items: the red square already marks where each one
     starts, and a hairline as well made a four-row table of a short list */
  padding: 0.85rem 0 0.85rem 1.75rem;
  font-size: var(--fs-body);
  color: var(--muted-hi);
  position: relative;
}
.outcomes li::before {
  content: '';
  position: absolute;
  left: 0; top: 1.35rem;
  width: 9px; height: 9px;
  background: var(--red);
}
.outcomes strong { color: var(--text); font-weight: 600; }

/* Pull quote */
.pull {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d3);
  font-size: var(--fs-d3);
  line-height: 1.12;
  letter-spacing: -0.025em;
  color: var(--text);
  max-width: 22ch;
  margin: 0;
  border-left: 3px solid var(--red);
  padding-left: clamp(1.25rem, 3vw, 2rem);
}

/* In Case You Were Wondering */
/* -------------------------------------------------------------
   IN CASE YOU WERE WONDERING
   The personal aside, and the only thing on the page that steps out
   of the column structure: cut-edge teal rules running the full
   container, with the copy inset from the left inside them and signed
   with the mark. No fill and no box, so it reads as a margin note
   rather than as a callout widget.
------------------------------------------------------------- */
.icyww {
  position: relative;
  /* tucked up close to the case-close mark above, so the two rules read as
     a pair closing the page rather than as two separate dividers */
  margin: clamp(0.6rem, 1.2vw, 0.9rem) 0 0;
}

/* a pull quote set centre-stage rather than in the margin: no rail, its
   own measure, centred in the column. For a line that closes a section
   instead of commenting alongside one. */
.callout--centred {
  border-left: 0;
  padding-left: 0;
  max-width: 34ch;
  margin-inline: auto;
  margin-block: clamp(2rem, 4vw, 3rem);
  text-align: center;
  text-wrap: balance;
}

/* -------------------------------------------------------------
   VIDEO
   A video on a near-black page with a dark first frame reads as a hole
   rather than as a thing you can press. The frame gets the plate's border
   and surface so its edges are visible, and a badge marks it as a video
   before the native controls fade in on hover.
------------------------------------------------------------- */
.vid {
  position: relative;
  display: block;
  background: var(--surface);
  border: 1px solid var(--dim);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color 200ms ease;
}
.vid:hover { border-color: var(--teal); }
.vid video {
  display: block;
  width: 100%;
  height: auto;
}
/* pointer-events off so it never intercepts a click meant for the
   controls; it hides once the video is playing */
.vid__badge {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.6rem;
  font-size: var(--fs-micro);
  font-weight: 500;
  color: var(--teal);
  background: rgba(15, 13, 11, 0.72);
  border: 1px solid var(--teal-line);
  border-radius: var(--radius);
  pointer-events: none;
  transition: opacity 200ms ease;
}
.vid.is-playing .vid__badge { opacity: 0; }

/* -------------------------------------------------------------
   CASE-CLOSE
   A small closing-tag flourish marking the end of a case, where a
   second full aside used to sit. Decorative only, so the case
   boundary stays legible in the markup without a second signature
   note repeating itself on the same page.
------------------------------------------------------------- */
.case-close {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
}
/* the rules run the full container. A case is closed by this tag alone,
   not by the aside's cut rule, which only appears once per page under the
   last case, so two short stubs left the boundary reading as decoration
   rather than as the end of the case. */
.case-close__rule { flex: 1 1 0; height: 1px; background: var(--red); }
.case-close__tag {
  font-family: var(--font-body);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--muted);
}
/* the rules run the full container; the copy sits centred under the squid
   that marks the middle of them */
@media (min-width: 900px) {
  .icyww__inner {
    margin-inline: auto;
    /* one measure for the copy, so no line ends short of its neighbours */
    max-width: 48rem;
    /* centred to sit on the squid's axis. Only here: on a narrow screen
       these run to five or six lines, and centred body copy that long is
       hard to scan. */
    text-align: center;
    text-wrap: pretty;
  }
}

/* matches .block__head: same rule, same label scale, so this reads as a
   section header like every other one rather than as a smaller caption */
/* the same closing mark the cases use, with the squid centred between the
   rules instead of a tag. It sits outside .icyww__inner so the rules span
   the container rather than the inset measure the copy is set to. */
.icyww__head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin: 0 0 clamp(1.1rem, 2.2vw, 1.6rem);
}
/* teal, not red: these rules carry the squid, and the mark is teal */
.icyww__rule {
  flex: 1 1 0;
  height: 6px;
  background-image: var(--teal-wave);
  background-repeat: repeat-x;
  background-position: center;
}
.icyww__badge {
  display: block;
  flex: none;
  /* the mark is 196 x 120, so 26px wide left it about 16px tall: enough to
     be a shape, not enough to be a squid */
  width: 42px;
  height: auto;
  color: var(--teal);
  margin: 0;
}
.icyww p {
  margin: 0 0 0.9rem;
  color: var(--muted-hi);
  font-size: var(--fs-body);
  /* no separate measure: the band above is the measure, so the lines end
     where the rules do. Same reasoning as the lightbox copy, which is
     short enough that a page measure only invents line breaks. */
  max-width: none;
  text-wrap: pretty;
}
.icyww p:last-child { margin-bottom: 0; }


/* Next-page pager */
.pager {
  position: relative;
  margin-top: clamp(1.75rem, 3.5vw, 2.75rem);
  padding-top: 1.25rem;
  display: flex;
  justify-content: space-between;
  /* baseline, not end: the edition mark and the Next label are both micro
     labels, so they share a line and the display-size link hangs below.
     Aligning to end sat a 12px mark against a 40px word. */
  align-items: baseline;
  gap: 2rem;
  flex-wrap: wrap;
}
/* two teal hairlines rather than one rule across: they sit over the Next
   link and the edition mark, and the gap in the middle keeps the row from
   reading as a closed box */
.pager::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 6px;
  background-image: var(--teal-wave);
  background-repeat: repeat-x;
  background-position: center;
  /* the empty centre is masked out of the tile rather than built from
     gradient stops, so the wave stays one continuous run */
  -webkit-mask-image: linear-gradient(to right, #000 0 21%, transparent 21% 79%, #000 79% 100%);
  mask-image: linear-gradient(to right, #000 0 21%, transparent 21% 79%, #000 79% 100%);
}
.pager__label { font-size: var(--fs-micro); color: var(--muted); margin-bottom: 0.35rem; }
.pager__link {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d3);
  font-size: var(--fs-d3);
  letter-spacing: -0.025em;
  line-height: 1;
  transition: color 200ms ease;
}
.pager__link:hover { color: var(--red); }

/* -------------------------------------------------------------
   FOOTER
------------------------------------------------------------- */
/* the band runs the full width so the change of ground is legible; the
   content inside it stays on the same 1600px measure as every other section */
.footer {
  border-top: 1px solid var(--dim);
  background: var(--bg-deep);
  padding: 2.25rem 0;
  margin-top: clamp(2.5rem, 5vw, 4rem);
}
.footer__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  max-width: 1600px;
  margin: 0 auto;
  padding: 0 var(--gutter);
}
@media (min-width: 720px) {
  /* auto columns, not equal fractions: at 1fr each the three lists were
     spread across the full width with their short labels stranded at the
     left of very wide cells. Sized to their content they group together,
     and the brand takes the slack. */
  .footer__grid {
    /* 3fr against three 1fr: the brand takes half the row, so the Work
       column opens on the centre line and the three lists divide the
       right half evenly between them */
    grid-template-columns: 3fr 1fr 1fr 1fr;
    column-gap: clamp(1.5rem, 3vw, 3rem);
    row-gap: 1.25rem;
    align-items: start;
  }
}
.footer__sig {
  font-family: var(--font-display);
  font-weight: 500;
  font-variation-settings: var(--vs-d2);
  font-size: var(--fs-d2);
  line-height: 0.9;
  letter-spacing: -0.03em;
  margin: 0 0 0.5rem;
}
.footer__sig .dot { color: var(--teal); }
/* the mark under the signature, the way a chop sits under a printed one */
/* the mark sits beside the signature rather than under it, bottom-aligned
   so the two share a baseline the way a name and its stamp do */
.footer__brand {
  display: flex;
  align-items: flex-end;
  gap: clamp(0.18rem, 0.4vw, 0.3rem);
}
.footer__mark {
  display: block;
  flex: none;
  /* the signature's own step, set here only so that 1em below means one
     signature-sized em: the mark then tracks the wordmark through the
     whole clamp instead of being pinned to a fixed size */
  font-size: var(--fs-d2);
  /* sized by height, not width: the ascender of April's l down to the
     baseline of Ruback's k. That is roughly one ascender (0.75em) plus
     one line advance, and .footer__sig sets line-height 0.9. Width
     follows from the mark's own 196 x 120 ratio. */
  height: 1.65em;
  width: auto;
  /* flex-end aligns to the sig's box, but with line-height 0.9 over two
     lines that box runs about 0.2em below Ruback's baseline. Lift the mark
     by the same amount so its tail lands on the baseline and its tip on
     April's cap line. */
  margin-bottom: 0.2em;
  color: var(--teal);
  opacity: 0.8;
}
.footer__loc { font-size: var(--fs-small); color: var(--muted); }
.footer__col { font-size: var(--fs-small); }
.footer__col-title { color: var(--muted); margin-bottom: 0.55rem; font-weight: 500; }
.footer__col a { display: block; color: var(--text); padding: 0.15rem 0; }
.footer__col a:hover { color: var(--red); }
/* the gloss on Claude-set*, sitting on top of the closing rule and set to
   the right edge, the way an imprint line rides the rule in print. Taken
   out of the flow so the copyright and the edition mark keep the ends of
   the row to themselves. */
.footer__imprint {
  position: absolute;
  right: 0;
  bottom: 100%;
  margin-bottom: 0.3rem;
  font-style: italic;
  white-space: nowrap;
}

.footer__meta {
  position: relative;
  grid-column: 1 / -1;
  border-top: 1px solid var(--dim);
  padding-top: 1.25rem;
  /* just enough for the imprint line riding the rule, and no more */
  margin-top: 1.55rem;
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  font-size: var(--fs-micro);
  flex-wrap: wrap;
  gap: 1rem;
}
