/* The site stylesheet. One file, in this order:
   1. font and tokens  2. base  3. shared pieces  4. sections  5. mobile overrides  6. reduced motion.
   New section styles go in part 4, above the mobile block. */

/* 1. Font and tokens ------------------------------------------------------ */
/* Type sizes are in rem on the browser's 16px root, so a visitor's text size setting scales them;
   nothing is set under .875rem (14px). Spacing and rules stay in px. */

/* Satoshi: the official Fontshare file, served unmodified (license: no subsetting or conversion). */
@font-face {
  font-family: "Satoshi";
  src: url("../assets/fonts/Satoshi-Variable.woff2") format("woff2");
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}
/* JetBrains Mono (OFL): timecodes, spec readouts and other technical meta, 14 px and up. */
@font-face {
  font-family: "JetBrains Mono";
  src: url("../assets/fonts/jetbrains-mono-latin-wght.woff2") format("woff2");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #DDDFDE;
  --panel: #CDD0CF;
  --ink: #121314;
  --muted: #545859;
  --line: #B4B8B8;
  --accent: #B23300;
  --head-h: 116px;                /* the site header's height (one row of 84px logo); anchors clear it */
  --anchor-gap: 24px;
  --dark: #0D0E10;
  --on-dark: #ECECEA;
  --on-dark-muted: #8D9096;
  --entry-bg: #0A0A0B;
  --entry-ink: #EDEDEA;
  --entry-muted: #A7A8A6;
  --rule-dark: #2A2D31;     /* hairlines inside dark bands */
  --frame-bg: #17191C;      /* an empty 16:9 frame before its image arrives */

  --sans: "Satoshi", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --track-display: -.035em;
  /* Type steps between 14 and 21px: four, in rem. Nothing is set under --text-sm. */
  --text-sm: .875rem;       /* 14: mono, labels on the rail, the title block */
  --text-base: 1rem;        /* 16: labels, navigation, captions, secondary text */
  --text-md: 1.125rem;      /* 18: body and ledes */
  --text-lg: 1.3125rem;     /* 21: row titles, the make paragraph, the story's closing line */
  /* Display sizes: the only sizes above --text-lg. The vw floor (min(rem, vw)) keeps the longest
     word of a heading inside a phone at any text size. tools/type_probe.mjs fails on any other size. */
  --display: clamp(min(2.125rem, 12vw), 3.6vw, 3.5rem);           /* section headings */
  --display-entry: clamp(min(2.5rem, 13vw), 5.6vw, 6rem);         /* the entry headline, the Work and Contact titles; 13vw keeps it above --display at 200% text */
  --display-page: clamp(min(3rem, 16vw), 8vw, 8rem);              /* page titles */
  --statement: clamp(min(1.875rem, 11vw), 3.4vw, 3.25rem);        /* the About story */
  --display-contact: clamp(1.75rem, 5vw, 4.5rem);                 /* the address on /contact/ */

  --accent-hover: #8F2900;
  --gutter: clamp(16px, 3.3vw, 48px);
  --ease-out: cubic-bezier(.2, .7, .2, 1);
}

/* 2. Base ----------------------------------------------------------------- */

/* Page to page: a short cross-fade of the page while the header stays put (it has a name of its own
   and is the same on every page). Browsers without cross-document view transitions just load the
   page. The opt-in, @view-transition { navigation: auto } inside prefers-reduced-motion:
   no-preference, is an inline <style> in each page's head: from this file Chrome often misses it
   (a style pass runs before the file applies and cancels the transition). */
::view-transition-old(root),
::view-transition-new(root) { animation-duration: 220ms; animation-timing-function: var(--ease-out); }
::view-transition-group(site-head) { animation: none; }
::view-transition-old(site-head) { display: none; }
::view-transition-new(site-head) { animation: none; }

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

html {
  background: var(--bg);
  color: var(--ink);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--text-md);
  line-height: 1.5;
  font-weight: 400;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, p, ul, ol, dl, dd, figure { margin: 0; }
ul, ol { padding: 0; }
img, video, canvas { display: block; max-width: 100%; }

a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
  transition: text-underline-offset 160ms var(--ease-out), color 160ms var(--ease-out);
}
a:hover { text-underline-offset: .32em; }

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}

.skip {
  position: absolute;
  left: var(--gutter);
  top: -100px;
  padding: 10px 14px;
  background: var(--ink);
  color: var(--bg);
  z-index: 10;
}
.skip:focus { top: 12px; }
.skip:focus-visible { outline-color: var(--entry-ink); }   /* it lands on the dark entry or header band */
/* Text for assistive tech only: the logo links are named "<site name>, home". */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* 3. Shared pieces -------------------------------------------------------- */

.wrap {
  max-width: 1440px;
  margin: 0 auto;
  padding: 0 clamp(16px, 3.3vw, 48px);
}

/* Display headlines: Satoshi bold, tight. */
.display {
  font-weight: 700;
  line-height: .96;
  letter-spacing: var(--track-display);
  font-size: var(--display);
  text-wrap: balance;
  overflow-wrap: break-word;
}

/* Technical meta: timecodes, spec readouts. */
.mono {
  font-family: var(--mono);
  font-size: var(--text-sm);
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}

.lede {
  font-size: var(--text-md);
  line-height: 1.5;
  color: var(--muted);
  max-width: 30em;
}


.band-dark {
  background: var(--dark);
  color: var(--on-dark);
}
.band-dark a { color: var(--on-dark); }
.band-dark .lede { color: var(--on-dark-muted); }
.band-dark :focus-visible { outline-color: var(--on-dark); }

/* A ruled list: one hairline above, one under every row. */
.ruled {
  list-style: none;
  border-top: 1px solid var(--line);
}
.ruled > * {
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
}
.band-dark .ruled,
.band-dark .ruled > * { border-color: var(--rule-dark); }

/* 4. Sections ------------------------------------------------------------- */

/* Header: the same markup on every page. A dark band at the top of the page; on the home page
   (body.page-home) it sits over the entry instead and fades with it. On-dark colors; the only
   orange is the brand mark's own, inside the logo (a mark, not an action). The 84px logo sets the
   row height: 16 + 84 + 16 = 116px. */
.site-head {
  view-transition-name: site-head;   /* held still across page changes */
  container: site-head / inline-size;   /* the compact phone header below asks how many rem fit */
  position: relative;
  z-index: 4;
  display: flex;
  flex-wrap: wrap;               /* with enlarged text the nav takes a row of its own, never cut */
  justify-content: space-between;
  align-items: center;
  gap: 30px 24px;                /* rows: 8px between the 44px hit boxes */
  padding: 16px clamp(16px, 2.5vw, 36px);
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--entry-ink);
  background: var(--dark);
}
.page-home .site-head {
  position: absolute;
  top: 0; left: 0; right: 0;
  background: none;
  transition: opacity 600ms var(--ease-out);
}
.site-head :focus-visible { outline-color: var(--entry-ink); }
.mark {
  display: block;
  color: var(--entry-ink);
  text-decoration: none;
}
/* The header logo: the full logo on dark (lynx, Hyperlynx and DESIGN), with more room between the lynx
   and the lettering than the stacked source (tools/make_lockup.py --stacked). Sized near the footer's. */
.mark img { display: block; width: auto; height: 84px; }
.site-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 30px 28px;
}
.site-nav a {
  color: var(--entry-muted);
  text-decoration-color: transparent;
}
.site-nav a:hover { color: var(--entry-ink); text-decoration-color: currentColor; }
/* Touch targets: the wordmark and the nav links take at least 44px of hit height (and the short
   ones 44px of width). The padding grows the box and the matching negative margin gives the room
   back, so nothing on the page moves. */
.mark { padding-block: 0; margin-block: 0; }   /* the 84px logo is the hit height */
.site-nav a { padding: 11px 8px; margin: -11px -8px; }
/* The current page: full ink and a quiet underline, set lower than the hover one. */
.site-nav a[aria-current="page"] {
  color: var(--entry-ink);
  text-decoration-color: currentColor;
  text-underline-offset: .5em;
}

/* Entry: a dark studio. The headline and the two actions sit on the left; a fast montage of the film
   plays in a large area on the right (about two thirds of the width, vertically centred), dimmed by an
   overlay and feathered into the dark on every edge, most of all on the left under the type, so it reads
   as light coming out of the dark rather than a frame on the page. No radius, frame or shadow.
   Default is the finished entry. html.entry-intro (set in <head>, lifted by entry.js) holds the headline
   below its masks and the montage out; html.entry-out fades the entry before the Work page opens. */
.entry {
  --media-w: min(66vw, calc((100svh - 120px) * 16 / 9));   /* never taller than the room minus the header */
  --media-h: calc(var(--media-w) * 9 / 16);
  --media-top: calc(50% + 20px - var(--media-h) / 2);      /* centred, nudged below the header */
  /* Room kept under the header, which sits over the entry: it grows with the text size, so with
     enlarged text (when the nav wraps) the headline still starts below it. */
  --head-clear: calc(52px + 4.25rem);
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: max(560px, 100vh);
  min-height: max(560px, 100svh);
  padding: var(--head-clear) clamp(16px, 2.5vw, 36px) clamp(34px, 7vh, 72px);
  overflow: hidden;
  background: var(--entry-bg);
  color: var(--entry-ink);
}
.entry-media {
  position: absolute;
  top: var(--media-top);
  right: 0;
  width: var(--media-w);
  height: var(--media-h);
  /* Two ramps, intersected: across (long on the left, short on the right) and down (top and bottom). */
  -webkit-mask-image:
    linear-gradient(to right, transparent 0, rgba(0, 0, 0, .3) 16%, rgba(0, 0, 0, .8) 32%, #000 40%, #000 90%, transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 16%, #000 82%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent 0, rgba(0, 0, 0, .3) 16%, rgba(0, 0, 0, .8) 32%, #000 40%, #000 90%, transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 16%, #000 82%, transparent 100%);
  mask-composite: intersect;
  transition: opacity 900ms var(--ease-out) 450ms;   /* the timecode fades in after the headline has risen; the leave fade uses it too */
}
/* The poster is a <picture> under the montage (phones get the 4:5 crop); the video is transparent
   until its first frame, so the poster shows through. */
.entry-still,
.entry-still img,
.entry-loop {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  object-fit: cover;
}
.entry-loop { background: transparent; opacity: 0; transition: opacity 300ms var(--ease-out); }
.entry-media.is-live .entry-loop { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .entry-loop { transition: none; } }
/* The dim: the montage at about nine tenths of its brightness, a little lower towards its edges. */
.entry-dim {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 75% 80% at 58% 50%, rgba(10, 10, 11, 0), rgba(10, 10, 11, .24)),
    rgba(10, 10, 11, .1);
}
/* The running timecode: mono, top right of the picture, with the Pause / Play control before it. */
.entry-tc {
  position: absolute;
  z-index: 3;
  top: calc(var(--media-top) + 18px);
  right: clamp(16px, 2.5vw, 36px);
  display: flex;
  align-items: baseline;
  gap: 24px;
  color: var(--entry-ink);
  font-size: var(--text-sm);
  transition: opacity 900ms var(--ease-out) 450ms;   /* arrives with the picture */
}
.entry-tc .mono { font-size: inherit; }
/* Pause / Play: a mono text toggle, underlined like a link. 44px of hit height from its padding,
   given back by the margin, so the timecode beside it never moves. Hidden without JS. */
.entry-pause {
  padding: 11px 8px;
  margin: -11px -8px;
  border: 0;
  background: none;
  color: var(--entry-ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
  cursor: pointer;
  transition: text-underline-offset 160ms var(--ease-out);
}
.entry-pause:hover { text-underline-offset: .32em; }
.entry-pause[hidden] { display: none; }

.entry-foot {
  position: relative;      /* in flow at the foot of the room, so a taller headline grows the room */
  z-index: 3;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: 40px;
}
.entry-title {
  font-size: var(--display-entry);
  font-weight: 700;
  line-height: .96;
  overflow-wrap: break-word;
  letter-spacing: var(--track-display);
}
.entry-title .line {
  display: block;
  overflow: hidden;
  padding-bottom: .2em;      /* room for descenders inside the mask */
  margin-bottom: -.16em;     /* the line spacing stays as set */
}
.entry-title .line > span {
  display: block;
  transition: transform 1.1s cubic-bezier(.2, .7, .1, 1);
}
.entry-title .line:nth-child(2) > span { transition-delay: 80ms; }
.entry-sub {
  margin-top: 18px;
  max-width: 44em;
  color: var(--entry-muted);
}
.entry-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 36px;
  margin-top: clamp(24px, 3.4vh, 36px);
}
/* Start your project: the one orange element on the entry, a solid square button. */
.btn-start {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  padding: 0 26px;
  background: var(--accent);
  color: #fff;
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  transition: background-color 160ms var(--ease-out);
}
.btn-start:hover { background: var(--accent-hover); }
/* One text colour on the orange everywhere: the dark bands' link ink (.band-dark a) must not win. */
.band-dark .btn-start { color: #fff; }
.entry-meta {
  text-align: right;
  color: var(--entry-muted);
  line-height: 1.7;
}
.enter {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--entry-ink);
  font-family: var(--sans);
  font-size: var(--text-base);
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
}
.enter::before {
  content: "";
  width: 44px;
  height: 1px;
  background: currentColor;
  transform-origin: 100% 50%;      /* it grows to the left, so the label never moves */
  transition: transform 400ms var(--ease-out);
}
.enter:hover::before,
.enter:focus-visible::before { transform: scaleX(1.6364); }   /* 44 to 72px, transform only */
.entry :focus-visible { outline-color: var(--entry-ink); }

.entry-foot { transition: opacity 400ms var(--ease-out); }

/* Opening: headline lines below their masks. The poster (and the montage after it) is on screen from
   the first paint; only the timecode waits. */
.entry-intro .entry-tc { opacity: 0; transition: none; }
.entry-intro .entry-title .line > span { transform: translateY(calc(100% + .32em)); }   /* clear of the taller mask */

/* Leaving for the film on the Work page: the montage and the UI fade together
   (entry.js navigates after 480 ms). */
.entry-out .entry-media,
.entry-out .entry-tc { opacity: 0; transition-delay: 0s; transition-duration: .45s; }
.entry-out .entry-ui,
.entry-out .site-head { opacity: 0; pointer-events: none; }

/* The film (Work page): the screening.
   Default (no JS, reduced motion) is a plain stack. .is-staged is added by script. */
.screening { padding-top: clamp(72px, 9vw, 144px); }
.work-lede {
  margin-top: clamp(16px, 1.6vw, 26px);
  max-width: 34em;
  font-size: var(--text-md);
  line-height: 1.5;
  color: var(--on-dark-muted);
}
.screening-frame {
  max-width: 1440px;
  margin: clamp(36px, 4vw, 64px) auto 0;
  padding: 0 var(--gutter);
  position: relative;
}
.screening-media { position: relative; background: #000; }
.screening-video {
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
}
.screening-poster,
.screening-scrim { display: none; }

/* Timecodes in mono, tabular. */
.screening-tc,
.tc {
  font-family: var(--mono);
  font-size: var(--text-sm);
  font-weight: 400;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}
.screening-tc {
  max-width: 1440px;
  margin: 14px auto 0;
  padding: 0 var(--gutter);
  color: var(--on-dark-muted);
}

/* Staged screening: a sticky stage; screening.js drives transform, clip and opacity. */
.screening.is-staged {
  height: 240vh;
  padding-top: 0;
}
.is-staged .screening-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
}
.is-staged .screening-head {
  position: absolute;
  left: 0; right: 0;
  top: clamp(28px, 6vh, 72px);
  will-change: transform, opacity;
}
.is-staged .screening-frame {
  position: absolute;
  inset: 0;
  max-width: none;
  margin: 0;
  padding: 0;
}
.is-staged .screening-media {
  position: absolute;
  left: 0; top: 0;
  width: 100%; height: 100%;
  overflow: hidden;
  transform-origin: 50% 50%;
  will-change: transform, clip-path;
}
.is-staged .screening-poster {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.is-staged .screening-video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  aspect-ratio: auto;
  object-fit: contain;
  visibility: hidden;
}
.is-staged .screening-scrim {
  display: block;
  position: absolute;
  inset: 0;
  background: rgba(13, 14, 16, .12);
  opacity: 0;
}
.is-staged.is-playing .screening-video { visibility: visible; }
/* The playing frame can fill the screen, where an outer ring would fall off the edge: draw it inside. */
.is-staged .screening-video:focus-visible { outline-offset: -3px; }
.is-staged.is-playing .screening-poster,
.is-staged.is-playing .screening-scrim { visibility: hidden; }

.is-staged .screening-tc {
  position: absolute;
  left: 0; top: 0;
  margin: 0;
  padding: 9px 11px 8px;
  background: rgba(13, 14, 16, .88);
  color: var(--on-dark);
  will-change: transform;
}
.is-staged.is-playing .screening-tc { opacity: 0; }

/* Compact screening: no scroll expansion, the poster and play control in a plain 16:9 frame.
   screening.js sets .is-compact on phones, and at every width on a [data-fixed] screening. */
.screening.is-staged.is-compact { height: auto; padding-top: clamp(72px, 9vw, 144px); }
.is-compact .screening-stage { position: relative; height: auto; overflow: visible; }
.is-compact .screening-head { position: static; }
.is-compact .screening-frame {
  position: relative;
  inset: auto;
  margin-top: 32px;
  aspect-ratio: 16 / 9;
}
.is-compact .screening-tc { position: absolute; }

/* The play control: a dark disc, a ring that draws itself, label and running time. */
.play {
  --size: 176px;
  position: absolute;
  left: 50%; top: 50%;
  width: var(--size); height: var(--size);
  margin: calc(var(--size) / -2) 0 0 calc(var(--size) / -2);
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--on-dark);
  font: inherit;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  will-change: transform;
  transition: opacity 420ms var(--ease-out);
}
.play.is-ready,
.play:focus-visible { opacity: 1; pointer-events: auto; }
/* While the film plays the control is out of the tab order, so Enter cannot restart it. */
.is-playing .play { opacity: 0; visibility: hidden; pointer-events: none; }
.play-disc {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  border-radius: 50%;
  background: rgba(13, 14, 16, .9);
  transform: scale(.86);
  transition: transform 520ms var(--ease-out), background-color 200ms var(--ease-out);
}
.play.is-ready .play-disc,
.play:focus-visible .play-disc { transform: scale(1); }
.play.is-ready:hover .play-disc { transform: scale(1.07); background: var(--dark); }
.play-ring {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  transform: rotate(-90deg);
  overflow: visible;
}
.play-ring circle {
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 900ms var(--ease-out) 80ms;
}
.play.is-ready .play-ring circle,
.play:focus-visible .play-ring circle { stroke-dashoffset: 0; }
.play-tri {
  width: 0; height: 0;
  margin: 0 0 6px 4px;
  border-style: solid;
  border-width: 9px 0 9px 15px;
  border-color: transparent transparent transparent currentColor;
}
.play-label {
  font-size: var(--text-md);
  font-weight: 500;
  line-height: 1;
}
.play-time {
  font-family: var(--mono);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  color: var(--on-dark-muted);
}

/* Teardown: the machine apart and back together, in eight chapters.
   Default (no JS, reduced motion): heading, the chapters as a ruled list, then three stills.
   teardown.js adds .is-live once the first frame has decoded: a sticky stage, the copy and the
   chapter timeline beside a canvas the scroll scrubs, the chapter label over it and a segmented rail under it. */
.teardown {
  border-top: 1px solid var(--rule-dark);
  padding-bottom: clamp(80px, 9vw, 152px);
}
.teardown-stage {
  max-width: 1440px;
  margin: 0 auto;
  padding: clamp(80px, 9vw, 152px) var(--gutter) 0;
}
.teardown-title { max-width: 12em; }
.teardown-body {
  margin-top: clamp(16px, 1.6vw, 24px);
  max-width: 30em;
  text-wrap: pretty;
  font-size: var(--text-md);
  line-height: 1.5;
  color: var(--on-dark-muted);
}
.teardown-screen { display: none; }

/* The chapters, static: a ruled list in two columns, index, name and its line. */
.teardown-chapters {
  list-style: none;
  margin-top: clamp(32px, 3.6vw, 52px);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(24px, 3vw, 48px);
}
.teardown-chapters > li {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  align-items: baseline;
  padding: 14px 0 16px;
  border-top: 1px solid var(--rule-dark);
}
.td-ch-num { font-size: var(--text-sm); color: var(--on-dark-muted); }
.td-ch-name { font-size: var(--text-base); font-weight: 600; line-height: 1.35; color: var(--on-dark); }
.td-ch-line {
  grid-column: 2;
  text-wrap: pretty;
  margin-top: 2px;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--on-dark-muted);
}
/* Announces the chapter to screen readers; never seen. */
.teardown-live {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.teardown-static {
  list-style: none;
  max-width: 1440px;
  margin: clamp(40px, 4.5vw, 72px) auto 0;
  padding: 0 var(--gutter);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(12px, 1.4vw, 20px);
}
.teardown-static img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  background: var(--frame-bg);
}
.teardown-static figcaption {
  margin-top: 12px;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--on-dark-muted);
}
.teardown-static .tc {
  display: inline-block;
  margin-right: 10px;
  color: var(--on-dark);
}

/* Live: a 360vh track (260vh of scroll), the stage pinned for the whole run. Each chapter takes
   its own frames plus a little reading room of that run (teardown.js PAD), the rail in the same shares.
   On desktop the copy and the chapter timeline are a side column (1fr) beside the frame (2fr), so the
   frame's own burned-in title is the only headline over the picture. The frame is the largest 16:9
   box its column and the stage height allow with the label over it and the rail under it
   (teardown.js measures it into --td-w), so the film's labels are never cropped. Below 1000px it
   stacks (see the mobile block). */
.teardown.is-live { padding-bottom: 0; }
.is-live .teardown-static { display: none; }
.is-live .teardown-track { height: 360vh; }
.is-live .teardown-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  padding: clamp(24px, 5vh, 56px) var(--gutter);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  column-gap: clamp(32px, 4vw, 64px);
  align-content: center;
  align-items: center;
}
.is-live .teardown-body { margin-top: clamp(14px, 1.4vw, 20px); font-size: var(--text-md); }

/* The chapter timeline, live: a hairline joins the eight markers. Done chapters carry a check on
   the line, the lit one a filled dot in a ring, upcoming ones an empty ring. The line fills down
   through the lit chapter with the scrub (--td-fill, set by teardown.js). The lit chapter's name
   goes to ink and its line fades in under it (opacity and transform only): the room for it is
   reserved at the foot of the list, and the chapters after the lit one slide down into it by a
   transform, so the list never lays out again and nothing beside it moves. */
.is-live .teardown-chapters {
  --td-slot: calc(4.5 * var(--text-base) + 8px);   /* three lines of the chapter's line, and air */
  display: block;
  margin-top: clamp(24px, 3.4vh, 40px);
  padding-bottom: var(--td-slot);
}
.is-live .teardown-chapters > li {
  --td-dot: 22px;           /* the marker's centre, from the top of the item */
  display: block;
  position: relative;
  padding: 0 0 0 30px;
  border-top: 0;
  transition: transform 300ms var(--ease-out);
}
.is-live .teardown-chapters > .is-active ~ li { transform: translateY(var(--td-slot)); }
/* The line from this marker to the next, and its fill. */
.is-live .teardown-chapters > li::before,
.is-live .teardown-chapters > li::after {
  content: "";
  position: absolute;
  left: 7px;
  top: var(--td-dot);
  bottom: calc(var(--td-dot) * -1 - var(--td-slot));   /* always long enough for the lit chapter's stretch */
  width: 1px;
  background: var(--rule-dark);
  /* Cut back to the next marker unless lit. A clip, not a size, so no layout property changes; it
     switches once the next chapter has slid back up (a delayed step, never interpolated). */
  clip-path: inset(0 0 var(--td-slot) 0);
  transition: clip-path 0s linear 300ms;
}
/* The lit chapter's stretch of line runs on past its line to the next marker. */
.is-live .teardown-chapters > li.is-active::before,
.is-live .teardown-chapters > li.is-active::after { clip-path: inset(0); transition-delay: 0s; }
.is-live .teardown-chapters > li::after {
  background: var(--on-dark);
  transform-origin: 50% 0;
  transform: scaleY(var(--td-fill, 0));
}
.is-live .teardown-chapters > li:last-child::before,
.is-live .teardown-chapters > li:last-child::after { display: none; }
.td-ch-btn {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr);
  align-items: baseline;
  width: 100%;
  min-height: 44px;         /* the Touch Target Rule */
  padding: 11px 0 9px;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
/* The marker, centred on the line: an empty ring (upcoming), a dot in a ring (lit), a check on a
   Dark Rule disc (done). */
.is-live .td-ch-btn::before,
.is-live .td-ch-btn::after {
  content: "";
  position: absolute;
  z-index: 1;
  box-sizing: border-box;
}
.is-live .td-ch-btn::before {
  left: 1px;
  top: calc(var(--td-dot) - 6.5px);
  width: 13px;
  height: 13px;
  border: 1px solid var(--on-dark-muted);
  border-radius: 50%;
  background: var(--dark);
  transition: border-color 300ms var(--ease-out), transform 300ms var(--ease-out);
}
.is-live .is-active .td-ch-btn::before { border-color: var(--on-dark); transform: scale(1.25); }
.is-live .is-done .td-ch-btn::before { border-color: var(--rule-dark); background: var(--rule-dark); transform: scale(1.15); }
.is-live .td-ch-btn::after {
  opacity: 0;
  transition: opacity 300ms var(--ease-out);
}
.is-live .is-active .td-ch-btn::after {
  left: 5px;
  top: calc(var(--td-dot) - 2.5px);
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--on-dark);
  opacity: 1;
}
.is-live .is-done .td-ch-btn::after {
  left: 4px;
  top: calc(var(--td-dot) - 3.5px);
  width: 7px;
  height: 4px;
  border: solid var(--on-dark);
  border-width: 0 0 1.5px 1.5px;
  transform: rotate(-45deg);
  opacity: 1;
}
.is-live .td-ch-name {
  font-weight: 500;
  color: var(--on-dark-muted);
  transition: color 300ms var(--ease-out);
}
.td-ch-btn:hover .td-ch-name,
.is-active .td-ch-name { color: var(--on-dark); }
.is-active .td-ch-name { font-weight: 600; }
.is-active .td-ch-num { color: var(--on-dark); }
.is-live .td-ch-line {
  display: block;
  position: absolute;
  top: 44px;
  left: 66px;
  right: 0;
  margin: 0;
  opacity: 0;
  transform: translateY(-6px);
  font-size: var(--text-base);
  pointer-events: none;
  transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out);
}
.is-live .is-active .td-ch-line { opacity: 1; transform: none; }

.is-live .teardown-screen {
  display: block;
  justify-self: end;
  width: min(100%, var(--td-w, 100%));
}
/* Over the frame's top right corner: the lit chapter's name in a square hairline box. It keeps its
   room when nothing is lit, so the frame never moves. */
.teardown-head {
  display: flex;
  justify-content: flex-end;
  height: 28px;
  margin-bottom: 18px;
}
.teardown-label {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 10px;
  border: 1px solid var(--rule-dark);
  font-size: var(--text-sm);
  line-height: 1;
  white-space: nowrap;
  color: var(--on-dark);
  opacity: 0;
  transition: opacity 300ms var(--ease-out);
}
.is-lit .teardown-label { opacity: 1; }
.teardown-view {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--entry-bg);
}
.teardown-canvas {
  display: block;
  width: 100%;
  height: 100%;
}
/* The cover: a still of the machine apart, every system named, over the canvas at the top of the
   run. It fades out in 300ms as the scrub begins and back in when the visitor returns to the top. */
.teardown-cover {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms var(--ease-out);
}
.is-covered .teardown-cover { opacity: 1; }
/* Viewfinder: four hairline L brackets just outside the picture. */
.td-corners,
.td-corners > span {
  position: absolute;
  inset: -8px;
  pointer-events: none;
}
.td-corners > span { inset: 0; }
.td-corners::before,
.td-corners::after,
.td-corners > span::before,
.td-corners > span::after {
  content: "";
  position: absolute;
  width: 14px;
  height: 14px;
  border: 0 solid var(--on-dark-muted);
}
.td-corners::before { left: 0; top: 0; border-width: 1px 0 0 1px; }
.td-corners::after { right: 0; top: 0; border-width: 1px 1px 0 0; }
.td-corners > span::before { left: 0; bottom: 0; border-width: 0 0 1px 1px; }
.td-corners > span::after { right: 0; bottom: 0; border-width: 0 1px 1px 0; }

/* The rail: one segment per chapter, each as wide as the chapter's share of the scroll, split by
   small gaps; filled in On Dark as far as the scrub, with a knob (a dot in a ring, like the lit
   marker) at the scrub. The chapter numbers sit under each segment's start, the lit one in ink.
   Each segment with its number is a button, for the pointer. */
.teardown-rail {
  position: relative;
  height: 40px;
  margin-top: 18px;
}
.td-bar,
.td-fill {
  position: absolute;
  left: 0;
  right: 0;
  top: 7px;
  height: 2px;
  background: var(--rule-dark);
}
.td-fill {
  background: var(--on-dark);
  transform-origin: 0 50%;
  transform: scaleX(0);
}
/* Each segment's hit strip runs 8px above the bar to below its number (48px tall), inset 4px at
   both ends so neighbouring strips sit 8px apart; the bar itself stays 2px. */
.td-tick {
  position: absolute;
  top: -8px;
  height: 48px;
  margin-left: 4px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--on-dark-muted);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
/* The gap that opens each segment (none before the first). */
.td-tick::before {
  content: "";
  position: absolute;
  left: -6px;
  top: 14px;
  width: 4px;
  height: 4px;
  background: var(--dark);
}
.td-tick:first-of-type::before { display: none; }
.td-tick-num {
  position: absolute;
  left: -4px;
  top: 30px;
  font-family: var(--mono);
  font-size: var(--text-sm);
  line-height: 1;
  transition: color 300ms var(--ease-out);
}
.td-tick.is-active,
.td-tick:hover { color: var(--on-dark); }
/* Under 600px the rail only shows progress: the lit chapter's 44px button is the control. */
@media (max-width: 599px) {
  .td-tick { pointer-events: none; cursor: default; }
}
.td-knob {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 16px;
  pointer-events: none;
  transform: translateX(0);
}
.td-knob::before,
.td-knob::after {
  content: "";
  position: absolute;
  box-sizing: border-box;
  border-radius: 50%;
}
.td-knob::before {
  left: -8px;
  top: 0;
  width: 16px;
  height: 16px;
  border: 1px solid var(--on-dark);
  background: var(--dark);
}
.td-knob::after {
  left: -3px;
  top: 5px;
  width: 6px;
  height: 6px;
  background: var(--on-dark);
}

/* The reading room: aluminum-gray sections between the dark bands, with a hard edge where they
   meet. A two-column row: the heading with its lede on the left, the content on the right.
   No motion here. */
.sheet {
  padding-top: clamp(72px, 9vw, 144px);
}
.sheet-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  column-gap: clamp(32px, 4vw, 64px);
  align-items: start;
}
.sheet-title { max-width: 9em; }
/* One lede treatment everywhere: 19px muted, directly under the section title. */
.display + .lede { margin-top: clamp(16px, 1.6vw, 24px); }
.sheet-head .lede { max-width: 24em; }

/* Ruled rows on one grid: the term column, then the sentence. Spec terms are Satoshi labels;
   the three points of #why put a 21px title in the same column. */
.spec > div,
.points > li {
  display: grid;
  grid-template-columns: 248px minmax(0, 1fr);
  column-gap: 24px;
  align-items: baseline;
}
.spec dt {
  font-size: var(--text-base);
  font-weight: 500;
  line-height: 1.5;
  color: var(--muted);
}
.spec dd,
.points p {
  margin: 0;
  max-width: 30em;              /* a reading line of about 60 to 75 characters (in em: Satoshi's 1ch, a wide zero, would allow 100) */
  text-wrap: pretty;            /* no word left alone on the last line */
  font-size: var(--text-md);
  line-height: 1.5;
}
.points { list-style: none; }
.point-title {
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.25;
}
.sheet-note {
  margin-top: clamp(28px, 3vw, 40px);
  max-width: 34em;
  font-size: var(--text-md);
  line-height: 1.5;
  color: var(--ink);
}

/* Home: the process in one row, on the light ground after the dark engineers band: the heading, then
   the five stages, a mono index over each name, every name a link to its row on /process/. */
.process { padding: clamp(72px, 8vw, 128px) 0; }
.teaser-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  column-gap: clamp(32px, 4vw, 64px);
  align-items: start;
}
.stage-row {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  column-gap: clamp(16px, 2vw, 32px);
  border-top: 1px solid var(--line);
}
.stage-row li { padding-top: 16px; }
.stage-row a {
  display: block;
  font-size: var(--text-md);
  font-weight: 500;
  line-height: 1.3;
  text-decoration-color: transparent;
}
.stage-row a:hover { text-decoration-color: currentColor; }
.stage-row .mono { display: block; margin-bottom: 8px; color: var(--muted); }

/* Contact: the address, large, in ink (the orange on /contact/ is the Email this brief button in the header). */
.contact { padding-bottom: clamp(80px, 9vw, 152px); }
.contact .lede { max-width: 34em; }
.contact-mail {
  margin-top: clamp(40px, 5vw, 80px);
  padding-top: clamp(24px, 2.6vw, 36px);
  border-top: 1px solid var(--line);
  font-size: var(--display-contact);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: var(--track-display);
  overflow-wrap: anywhere;
}
.contact-mail a {
  color: var(--ink);
  text-decoration-thickness: 2px;
  text-underline-offset: .14em;
}
.contact-mail a:hover {
  color: var(--ink);
  text-underline-offset: .22em;
}
.contact-short :focus-visible { outline-color: var(--ink); }   /* ink, like the address above it */
.contact-short {
  margin-top: 20px;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--muted);
}

/* Footer: the same markup on every page, on the gray ground under a hairline. The wordmark and
   one line on the left, the four pages and the address on the right, then the small print. */
.site-foot { background: var(--bg); color: var(--ink); }
.foot-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  column-gap: clamp(32px, 5vw, 80px);
  row-gap: clamp(40px, 4.5vw, 64px);
  align-items: start;                     /* the logo is an image; the text columns hang from its top */
  padding-bottom: 36px;
  font-size: var(--text-base);
  line-height: 1.5;
}
.foot-grid::before {                     /* the hairline, its own row, inside the gutter like every other rule */
  content: "";
  grid-column: 1 / -1;
  border-top: 1px solid var(--line);
}
/* The footer logo: the full logo in its own colours on Aluminium, DESIGN line included (its caps
   set at about 7px at 240px wide, 6px at 200px on phones). */
.foot-mark { display: block; width: fit-content; max-width: 100%; text-decoration: none; }
.foot-mark img { display: block; width: 240px; max-width: 100%; height: auto; }
.foot-desc {
  margin-top: 16px;
  color: var(--muted);
  max-width: 28em;
}
.foot-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
}
.foot-nav a {
  padding: 12px 8px;            /* 44px hit height and width; the margin gives the room back */
  margin: -12px -8px;
  text-decoration-color: transparent;
}
.foot-nav a:hover { text-decoration-color: currentColor; }
/* The current page (FAQ, which is in the footer only): the header's quiet underline. */
.foot-nav a[aria-current="page"] { text-decoration-color: currentColor; text-underline-offset: .5em; }
/* Inline links in the footer and in running text: vertical padding on an inline box adds hit
   height without touching the line, so these reach 44px with nothing moved. */
.foot-mail a,
.faq-line a,
.contact-short a,
.contact-mail a,
.lead-pdf a,
.film-brief a,
.brief-actions a { padding-block: 13px; }
.foot-mail { overflow-wrap: anywhere; }
.foot-meta {
  grid-column: 1 / 3;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 24px;
  color: var(--muted);
}
.foot-legal {
  justify-self: end;
  color: var(--muted);
}
.site-foot :focus-visible { outline-color: var(--ink); }   /* a call to action above may be the orange on this screen */

/* Work page. The film is a compact screening (data-fixed: no scroll expansion) held to the
   content width, under a mono "Selected work" label; five ruled rows and the teardown follow. */
.case-film { padding-bottom: clamp(56px, 6vw, 96px); }
.case-film .screening,
.case-film .screening.is-staged.is-compact { padding-top: clamp(40px, 5vw, 88px); }
.film-brief {
  margin-top: 20px;
  font-size: var(--text-base);
  line-height: 1.5;
}
.case-label {
  margin-bottom: clamp(16px, 1.8vw, 28px);
  font-size: var(--text-sm);
  color: var(--on-dark-muted);
}
.case-title {
  font-size: var(--display-entry);
  max-width: 14em;
}
.spec-num {
  font-family: var(--mono);
  font-size: var(--text-base);
  font-variant-numeric: tabular-nums;
}
.case-film .is-compact .screening-frame {
  width: min(calc(100% - 2 * var(--gutter)), 1344px);
  margin: clamp(36px, 4vw, 64px) auto 0;
}

/* Page header (/process/, /about/, /contact/), in type only: a dark band under the site header.
   A mono index and the page name over a dark-rule hairline, on the reading grid (1fr / 2fr); the
   page title large; the lede in the second column; then a title block of four facts, ruled like
   the one in the corner of an engineering drawing. No film frames on these pages. */
.page-lead { padding: clamp(24px, 3vw, 48px) 0 clamp(64px, 7vw, 112px); }
.page-lead > .wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  column-gap: clamp(32px, 4vw, 64px);
}
.page-index {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--rule-dark);
  font-size: var(--text-sm);
  line-height: 1;
  color: var(--on-dark-muted);
}
.page-index span:first-child { color: var(--on-dark); }
.page-title {
  grid-column: 1 / -1;
  margin-top: clamp(56px, 8vw, 128px);
  font-size: var(--display-page);
  font-weight: 700;
  line-height: .96;
  letter-spacing: var(--track-display);
  max-width: 11em;
  text-wrap: balance;
  overflow-wrap: break-word;
}
.page-lede {
  grid-column: 2;
  margin-top: clamp(28px, 3vw, 48px);
  max-width: 34em;
  font-size: var(--text-md);
  line-height: 1.5;
  color: var(--on-dark-muted);
}
/* Process header: the one way in, the start button under the lede. */
.lead-action {
  grid-column: 2;
  margin-top: clamp(24px, 2.4vw, 32px);
}
/* Contact header: the same start button, "Email this brief", with a short line beside it, and the
   PDF as an ink link under them. */
.lead-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 24px;
}
/* The reply time, directly under the button: the one promise the site makes. */
.lead-reply {
  margin-top: 12px;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--on-dark);
}
.lead-note {
  margin-top: 16px;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--on-dark-muted);
}
/* The address beside the button, in ink, to read or copy; Copy address is a small text button. */
.lead-address {
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--on-dark);
  overflow-wrap: anywhere;
}
.text-btn {
  margin: -11px 0 -11px 12px;
  padding: 11px 0;              /* 44px hit height; the margin gives the room back */
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
  cursor: pointer;
  transition: text-underline-offset 160ms var(--ease-out);
}
.text-btn:hover { text-underline-offset: .32em; }
.text-btn[hidden] { display: none; }
.copy-status { margin-left: 10px; color: var(--on-dark-muted); }
/* After a click on a brief mailto: what to do if no email app opened (empty until then). */
.mail-note { font-size: var(--text-base); line-height: 1.5; color: var(--muted); max-width: 34em; }
.mail-note:not(:empty) { margin-top: 14px; }
.band-dark .mail-note { color: var(--on-dark); }
.lead-pdf {
  margin-top: 20px;
  font-size: var(--text-base);
  line-height: 1.5;
}
.title-block {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-top: clamp(48px, 5.5vw, 88px);
  border-top: 1px solid var(--rule-dark);
  border-bottom: 1px solid var(--rule-dark);
}
.title-block > div {
  padding: 14px 20px 16px;
  border-left: 1px solid var(--rule-dark);
}
.title-block > div:first-child { border-left: 0; padding-left: 0; }
.title-block dt {
  font-size: var(--text-sm);
  color: var(--on-dark-muted);
}
.title-block dd {
  margin: 4px 0 0;
  font-size: var(--text-sm);
  color: var(--on-dark);
}

/* Contact header, desktop: the title on the left, the lede, the start button and the PDF link on the
   right, top-aligned to the title, so the whole header and its button fit the first screen. */
@media (min-width: 901px) {
  .page-lead-split { padding-bottom: clamp(32px, 3.4vw, 56px); }
  .page-lead-split > .wrap {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    grid-template-rows: auto auto 1fr;
  }
  .page-lead-split .page-title {
    grid-column: 1;
    grid-row: 2 / 4;
    margin-top: clamp(28px, 4vw, 64px);
    font-size: var(--display-entry);
    max-width: 8em;
  }
  .page-lead-split .page-lede {
    grid-column: 2;
    grid-row: 2;
    margin-top: calc(clamp(28px, 4vw, 64px) + .3em);
  }
  .page-lead-split .lead-action { grid-column: 2; grid-row: 3; align-self: start; margin-top: 24px; }
  .page-lead-split .title-block { grid-row: 4; margin-top: clamp(28px, 3.4vw, 56px); }
}

/* A reading section in the dark room, in type and rules only: the usual heading and content row.
   Used where a page needs the dark between two gray sections. */
.sheet + .band-sheet { margin-top: clamp(72px, 9vw, 144px); }
.band-sheet { padding: clamp(72px, 9vw, 144px) 0 clamp(80px, 9vw, 152px); }
/* Two gray sections in a row: a hairline across the reading grid divides them. */
.sheet + .sheet > .sheet-row::before {
  content: "";
  grid-column: 1 / -1;
  border-top: 1px solid var(--line);
  margin-bottom: clamp(28px, 3vw, 44px);
}

/* About: why we started. The label on the left; the story set large on the right, the problem in
   muted ink and the answer in full ink; what a CAD film can do closes it at reading size. */
.story { padding-top: clamp(96px, 11vw, 176px); }
.story-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  column-gap: clamp(32px, 4vw, 64px);
  align-items: baseline;
}
.story-title {
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.3;
}
.story-text p {
  max-width: 19em;
  font-size: var(--statement);
  font-weight: 700;
  line-height: 1.08;
  overflow-wrap: break-word;
  letter-spacing: -.03em;
  text-wrap: pretty;
}
.story-problem { color: var(--muted); }
.story-answer { margin-top: .6em; }
.story-text .story-answer + .story-problem {
  margin-top: clamp(32px, 3.5vw, 56px);
  max-width: 30em;
  font-size: var(--text-lg);
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: -.01em;
}

/* Home: what we make. One paragraph, then the lengths on offer drawn as a scale: a datum tick
   at zero, a tick every 15 seconds, the offered range (15 to 90) drawn in full ink. */
.make-text {
  max-width: 30em;
  font-size: var(--text-lg);
  line-height: 1.4;
}
.scale { margin-top: clamp(48px, 5.5vw, 88px); }
.scale-ticks {
  position: relative;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  font-size: var(--text-sm);
  line-height: 1;
  color: var(--ink);
}
.scale-ticks::before {               /* the datum: a taller tick at zero */
  content: "";
  position: absolute;
  left: 0; top: -8px;
  width: 1px; height: 17px;
  background: var(--muted);
}
.scale-ticks li {
  position: relative;
  display: flex;
  justify-content: flex-end;
  padding-top: 20px;
  border-top: 1px solid var(--ink);
}
.scale-ticks li:first-child { border-top-color: var(--line); }
.scale-ticks li::after {
  content: "";
  position: absolute;
  right: 0; top: -5px;
  width: 1px; height: 9px;
  background: var(--ink);
}
.scale-ticks li:first-child::after,
.scale-ticks li:last-child::after { top: -8px; height: 17px; }
.scale-ticks span { transform: translateX(50%); }
.scale-ticks li:last-child span { transform: none; }
.scale-cap {
  margin-top: 18px;
  max-width: 36em;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--muted);
}

/* Work page: the five rows sit on the gray between the film and the teardown. */
.sheet + .teardown { margin-top: clamp(72px, 9vw, 144px); border-top: 0; }

.band-dark .spec dt { color: var(--on-dark-muted); }
.sub-title {
  margin-top: clamp(40px, 4.5vw, 64px);
  margin-bottom: 16px;
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.25;
}
.sheet-body > .sub-title:first-child { margin-top: 0; }

/* The five stages: full-width ruled rows of mono number, the title with one sentence under it, and
   what comes from you and what is delivered. */
.stages { list-style: none; margin-top: clamp(36px, 4vw, 56px); }
.stages > li {
  display: grid;
  grid-template-columns: 56px minmax(0, 1.25fr) minmax(0, 1.5fr);
  column-gap: clamp(20px, 2.4vw, 40px);
  align-items: start;
  padding: 26px 0 30px;
}
.stage-num {
  font-size: var(--text-sm);
  line-height: 1.6;
  padding-top: 3px;
  color: var(--muted);
}
.stage-title {
  font-size: var(--text-lg);
  font-weight: 700;
  line-height: 1.25;
}
.stage-line {
  margin-top: 6px;
  max-width: 30em;
  font-size: var(--text-md);
  line-height: 1.5;
}
.stage-io dt {
  font-size: var(--text-base);
  font-weight: 500;
  line-height: 1.5;
  color: var(--muted);
}
.stage-io dd {
  margin: 2px 0 14px;
  max-width: 30em;              /* the same reading line as the ruled rows */
  text-wrap: pretty;
  font-size: var(--text-base);
  line-height: 1.5;
}
.stage-io dd:last-child { margin-bottom: 0; }

/* CAD formats: a small ruled table, format then notes. */
.formats {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
}
.formats th,
.formats td {
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
  vertical-align: baseline;
}
.formats thead th {
  padding-top: 0;
  padding-bottom: 12px;
  font-size: var(--text-base);
  font-weight: 500;
  color: var(--muted);
}
.formats tbody th {
  width: 248px;
  padding-right: 24px;
  font-size: var(--text-md);
  font-weight: 600;
}
.formats tbody th .mono {
  display: block;
  margin-top: 2px;
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--muted);
}
.formats td { font-size: var(--text-md); line-height: 1.5; }
.formats caption { margin-top: 0; text-align: left; }

/* Questions: native details rows; a mono + in the gutter, a minus when open. */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 64px;
  padding: 12px 0 12px 60px;
  cursor: pointer;
  list-style: none;
  font-size: var(--text-md);
  font-weight: 600;
  line-height: 1.3;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::before {          /* drawn in the 60px gutter, so the question never shifts */
  content: "+";
  content: "+" / "";            /* the open state is native to details; the marker is not read out */
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--mono);
  font-size: var(--text-md);
  font-weight: 400;
  line-height: 1;
  color: var(--muted);
  transition: color 160ms var(--ease-out);
}
.faq details[open] summary::before {
  content: "\2212";             /* U+2212 minus sign */
  content: "\2212" / "";
}
.faq summary:hover::before,
.faq summary:focus-visible::before,
.faq details[open] summary::before { color: var(--ink); }
.faq details p {
  max-width: 36em;
  padding: 0 0 24px 60px;
  font-size: var(--text-md);
  line-height: 1.5;
}

/* Questions in a dark band (/faq/): the same rows on dark-rule hairlines. */
.band-dark .faq,
.band-dark .faq details { border-color: var(--rule-dark); }
.band-dark .faq summary::before { color: var(--on-dark-muted); }
.band-dark .faq summary:hover::before,
.band-dark .faq summary:focus-visible::before,
.band-dark .faq details[open] summary::before { color: var(--on-dark); }

/* A quiet pointer to the FAQ (end of /process/, under the brief on /contact/): muted, an ink link. */
.faq-line {
  margin-top: clamp(40px, 4.5vw, 64px);
  max-width: 34em;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--muted);
}
.faq-line :focus-visible { outline-color: var(--ink); }   /* the call to action or the address is the orange */

/* Closing call to action: a hairline, the heading beside a lede and the start button to /contact/. */
.cta { padding-bottom: clamp(80px, 9vw, 152px); }
.cta-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  column-gap: clamp(32px, 4vw, 64px);
  align-items: start;
}
.cta-row::before {
  content: "";
  grid-column: 1 / -1;
  border-top: 1px solid var(--line);
  margin-bottom: clamp(28px, 3vw, 44px);
}
.band-dark + .cta .cta-row::before { display: none; }   /* after a dark band the edge already divides */
/* Where the section before is gray (Home, Process, About, FAQ), the call to action is a dark band, so the
   page alternates gray and dark to the footer; the band's edge divides, so no hairline. */
.band-dark.cta .cta-row::before { display: none; }
.process + .band-sheet { margin-top: 0; }   /* the process row keeps its own bottom padding */
/* After a gray section that ends on a rule (a ruled list, the questions), that rule divides. */
.sheet:has(> .sheet-row > .sheet-body.faq, > .sheet-row > .sheet-body > .ruled:last-child) + .cta .cta-row::before { display: none; }
.cta-title { max-width: 9em; }
.cta-action { margin-top: clamp(24px, 2.6vw, 36px); }
.cta .lede { max-width: 30em; }

/* Contact page: the machine brief, ruled like a form on an engineering drawing: a mono item number,
   the item in Satoshi, its example in muted, one row per item. Then three ink actions (email, copy,
   PDF) and the address, which stays the one orange element. */
.brief-list { list-style: none; }
.brief-list > li {
  display: grid;
  grid-template-columns: 40px minmax(0, 15em) minmax(0, 1fr);
  column-gap: 16px;
  align-items: baseline;
}
.brief-num { font-size: var(--text-sm); color: var(--muted); font-variant-numeric: tabular-nums; }
.brief-label {
  font-size: var(--text-md);
  font-weight: 600;
  line-height: 1.35;
}
.brief-hint {
  max-width: 34em;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--muted);
}
.brief-actions {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px 40px;
  margin-top: clamp(28px, 3vw, 40px);
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.5;
}
.brief-actions [hidden] { display: none; }
.brief-actions :focus-visible { outline-color: var(--ink); }   /* ink, like the address below */
.brief-copy {
  padding: 11px 0;              /* 44px hit height; the margin gives the room back */
  margin: -11px 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: .2em;
  cursor: pointer;
  transition: text-underline-offset 160ms var(--ease-out);
}
.brief-copy:hover { text-underline-offset: .32em; }
.brief-status {
  margin-left: 10px;
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--muted);
}
.contact-page .contact-mail { margin-top: clamp(48px, 5.5vw, 88px); }
.contact-note {
  margin-top: clamp(32px, 3.6vw, 52px);
  max-width: 34em;
  font-size: var(--text-md);
  line-height: 1.5;
}
.contact-note + .contact-note { margin-top: 8px; color: var(--muted); }

/* The brief composer (/contact/, JS only): the ten items as real fields, in the same ruled language
   as the list it replaces: a mono item number, the item in Satoshi 18px 600, its example in 16px
   muted, then the fields: square 1px boxes in Graphite Muted (5.6:1 on Aluminium, so the box reads
   as a control), 18px type (no zoom on a phone), 48px tall. A wrong answer gets a 2px ink box and its
   message in ink under it; there is no red and no orange in the form but the one button. */
.composer[hidden],
[data-brief-static][hidden] { display: none; }
.composer:focus { outline: none; }              /* focused only as the target of the header button */
.composer :focus-visible { outline-color: var(--ink); }   /* the orange is the submit button */
.composer-list { list-style: none; }
.composer-list > li {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  column-gap: 16px;
  align-items: start;
  padding: 22px 0 26px;
}
.composer-list .brief-num { padding-top: 4px; }
.cq { min-width: 0; margin: 0; padding: 0; border: 0; }
.cq > legend { padding: 0; }
.cq-label {
  display: block;
  font-size: var(--text-md);
  font-weight: 600;
  line-height: 1.35;
}
.cq-hint {
  margin-top: 4px;
  max-width: 34em;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--muted);
}
.cq-fields { margin-top: 14px; }
.cq-sub { margin-top: 18px; }
.cq-sublabel,
.field > label:not(.cq-label) {
  font-size: var(--text-base);
  font-weight: 500;
  line-height: 1.5;
}
.req {
  margin-left: 6px;
  font-family: var(--mono);
  font-size: var(--text-sm);
  font-weight: 400;
  color: var(--muted);
}
.cq-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px 24px;
}
.field { display: grid; align-content: start; row-gap: 6px; }
.cq.field > textarea,
.cq.field > input { margin-top: 8px; }
.composer input:not([type="checkbox"]):not([type="radio"]),
.composer textarea {
  width: 100%;
  min-height: 48px;
  margin: 0;
  padding: 11px 12px;
  border: 1px solid var(--muted);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: var(--text-md);
  line-height: 1.4;
  scroll-margin-top: 96px;
  transition: border-color 160ms var(--ease-out);
}
.composer input:not([type="checkbox"]):not([type="radio"]) { height: 48px; }
.composer textarea { resize: vertical; }
.composer input:not([type="checkbox"]):not([type="radio"]):hover,
.composer textarea:hover,
.composer input:not([type="checkbox"]):not([type="radio"]):focus,
.composer textarea:focus { border-color: var(--ink); }
.composer input:focus-visible,
.composer textarea:focus-visible,
.composer input[type="date"]:focus,
.composer input[type="date"]:focus-within { outline: 2px solid var(--ink); outline-offset: 2px; }   /* the date field's focus sits on its inner parts, where :focus-visible does not reach the box */
.composer input::-webkit-calendar-picker-indicator { cursor: pointer; }
/* A wrong answer: a 2px ink box (padding gives the extra pixel back) and the message under it. */
.composer .is-invalid input,
.composer .is-invalid textarea { border-width: 2px; border-color: var(--ink); padding: 10px 11px; }
.field-error {
  font-size: var(--text-base);
  font-weight: 600;
  line-height: 1.5;
  color: var(--ink);
}
.field-error:empty { display: none; }
/* Choices: native boxes and dots in ink, each label a 44px target, 8px or more apart. */
.choices {
  display: flex;
  flex-wrap: wrap;
  gap: 0 24px;
}
.cq-sub .choices { margin-top: 4px; }
.choice {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  font-size: var(--text-md);
  line-height: 1.3;
  cursor: pointer;
}
.choice .mono { font-size: var(--text-md); }
.choice input {
  flex: none;
  width: 18px;
  height: 18px;
  margin: 0;
  accent-color: var(--ink);
  cursor: pointer;
}
/* The summary of what to fix, at the top on a failed submit: ruled, in ink, a link per answer. */
.composer-errors {
  margin-bottom: 28px;
  padding: 18px 0 0;
  border-top: 2px solid var(--ink);
  scroll-margin-top: 96px;
}
.composer-errors:focus { outline: none; }
.composer-errors:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }
.composer-errors-title { font-size: var(--text-md); font-weight: 700; line-height: 1.35; }
.composer-errors-list { list-style: none; margin-top: 8px; }
.composer-errors-list a {
  display: inline-block;
  padding: 10px 0;              /* 44px rows, nothing given back: the list is short */
  font-size: var(--text-base);
  font-weight: 500;
  line-height: 1.5;
}
/* The actions: the one orange button on this screen, then Copy the brief as an ink text button. */
.composer-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 32px;
  margin-top: clamp(28px, 3vw, 40px);
}
.composer .btn-start { border: 0; font-family: var(--sans); cursor: pointer; }
.composer-copy { margin-left: 0; font-size: var(--text-base); font-weight: 600; color: var(--ink); }
.composer .copy-status { margin-left: 0; color: var(--muted); }
.composer-draft,
.composer-pdf {
  margin-top: 18px;
  max-width: 40em;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--muted);
}
.composer-draft .text-btn { color: var(--ink); margin-left: 4px; }
/* The 44px hit box stays on the button; its focus ring is drawn tight round the words (an inner span). */
.composer-draft .text-btn:focus-visible { outline: 0; }
.composer-draft .text-btn:focus-visible > span { outline: 2px solid var(--ink); outline-offset: 1px; }
.composer-draft .copy-status .text-btn { margin-left: 2px; }
.composer-pdf a { padding-block: 13px; }
.composer .mail-note:not(:empty) { color: var(--ink); }

/* Back to top: the end of the long pages (Work, Process, FAQ), a quiet ink link on the right under
   the call to action, to the top of the page (the body is #top). */
.cta:has(+ .to-top) { padding-bottom: clamp(40px, 4.5vw, 72px); }
.to-top {
  display: flex;
  justify-content: flex-end;
  padding-bottom: 32px;
  font-size: var(--text-base);
  line-height: 1.5;
}
.to-top a { padding-block: 11px; margin-block: -11px; text-decoration-color: currentColor; }
.to-top :focus-visible { outline-color: var(--ink); }   /* the call to action above is the orange */
/* Inside a dark call to action band: under the row, in the band's own colours. */
.cta > .to-top { margin-top: clamp(40px, 4.5vw, 72px); padding-bottom: 0; }
.band-dark .to-top :focus-visible { outline-color: var(--on-dark); }

/* 5. Mobile overrides ----------------------------------------------------- */

/* Phone entry: the 4:5 montage under the header, darker, fading out at the bottom into the page;
   the headline sits over that fade and the actions stack full width. */
@media (max-width: 760px) {
  /* Phones: the 48px logo and the five links in 14px. Each
     link's hit box is 45px tall (12px of padding around the 21px line) and 10px wider each side, all
     given back by the margin; 28px between the words leaves 8px between the hit boxes, and 32px
     between wrapped rows (enlarged text) the same. One row from 481px: 12 + 48 + 12 = 72px. */
  .site-head { padding: 12px 16px; gap: 22px 16px; font-size: var(--text-sm); }
  .mark img { height: 48px; }
  .mark { padding-block: 0; margin-block: 0; }
  .site-nav { gap: 32px 28px; }
  :root { --head-h: 72px; }
  .site-nav a { padding: 12px 10px; margin: -12px -10px; }
  /* The picture's fade runs under the headline: its foot sits about 230 px above the bottom of the room
     (the headline's middle on a 844 px phone), never higher than just under the header. */
  /* Never lower than just under the timecode, so with enlarged text (a taller room) the picture stays
     at the top and its fade, not its brightest part, runs behind the headline. */
  .entry { --media-w: 100vw; --media-h: calc(100vw * 1.25); --media-top: clamp(44px, calc(100% - 100vw * 1.25 - 230px), calc(var(--head-clear) + 40px)); }
  .entry-media {
    left: 0;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 10%, #000 54%, rgba(0, 0, 0, .45) 78%, transparent 98%);
    mask-image: linear-gradient(to bottom, transparent 0, #000 10%, #000 54%, rgba(0, 0, 0, .45) 78%, transparent 98%);
  }
  /* Darker than on desktop, and darker again towards the foot, where the headline sits on it. */
  .entry-dim { background: linear-gradient(to bottom, rgba(10, 10, 11, .2) 0, rgba(10, 10, 11, .2) 45%, rgba(10, 10, 11, .7) 85%); }
  /* The timecode and Pause sit just under the header, and the room keeps a row for them above the
     headline, so at any text size the headline starts below them. */
  .entry { --head-clear: calc(96px + 4.25rem); padding: calc(var(--head-clear) + 1.6em + 20px) 16px 28px; }
  .entry-tc { top: var(--head-clear); right: 16px; }
  .entry-foot {
    grid-template-columns: 1fr;
    gap: 18px;
  }
  /* A dim that travels with the copy: wherever the headline and sub line end up (enlarged text
     pushes them up over the picture), the room behind them darkens, so they keep their contrast. */
  .entry-foot::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: -72px -16px -28px;
    background: linear-gradient(to bottom, rgba(10, 10, 11, 0), rgba(10, 10, 11, .82) 72px);
    pointer-events: none;
  }
  .entry-title { font-size: var(--display-entry); }   /* one step above the section headings (--display) */
  .entry-sub { margin-top: 14px; font-size: var(--text-base); }
  .entry-actions { flex-direction: column; align-items: stretch; gap: 8px; margin-top: 22px; }
  .entry-actions .enter { justify-content: center; }
  .entry-meta { display: none; }
}

/* Narrow phones: two header rows, the logo, then the five links across the full width, the first
   and last on the gutter. The 22px row gap keeps 8px between the logo's hit box and the links'.
   12 + 48 + 22 + 21 + 12 = 115px. */
@media (max-width: 480px) {
  :root { --head-h: 115px; }
  .site-nav { flex: 1 0 100%; justify-content: space-between; }
}
/* Large text on a phone (the header narrower than 22rem: about 1.1x text and up on a 390px phone,
   so the nav would wrap): a compact header. The logo drops to 32px; each link's padding shrinks to
   what still makes a 44px hit box (none needed once the line itself is 44px), and the row gaps
   shrink with it, keeping 8px between hit boxes. At 200% text on a 390px phone the header is
   162px, was 202px. A container query, because the root's rem is what grows, not the screen. */
@container site-head (max-width: 22rem) {
  .mark,
  .site-nav { --pad: max(2px, calc((44px - 1.5em) / 2)); }
  .mark img { height: 32px; }
  /* The logo keeps a 44px hit box (6px of padding, given back above); below it the 22px row gap
     loses what the links' padding no longer needs, so the hit boxes stay 8px apart. */
  .mark { padding-block: 6px; margin-top: -6px; margin-bottom: calc(var(--pad) - 14px); }
  .site-nav { gap: calc(8px + 2 * var(--pad)) 24px; }
  .site-nav a { padding: var(--pad) 8px; margin: calc(-1 * var(--pad)) -8px; }
}

/* Short screens (landscape phones): the room drops its 560px floor and the copy moves up, so the
   headline and Start your project are on the first screen (844 x 390: the button ends at 370px). */
@media (max-height: 560px) {
  .entry { min-height: 100vh; min-height: 100svh; padding-bottom: 20px; }
  .entry-actions { margin-top: 16px; }
}
@media (max-width: 760px) and (max-height: 560px) {
  .entry { --head-clear: calc(24px + 4.25rem); padding: calc(var(--head-clear) + 1.6em + 12px) 16px 16px; }
}

/* Phone: the film's play control. */
@media (max-width: 760px) {
  .work-lede { font-size: var(--text-base); }
  /* Phone play control: a 64px disc at the frame's bottom-right corner (screening.js places it),
     the triangle and running time only; the timecode chip stays off the small frame. */
  .play { --size: 64px; }
  .play-disc { gap: 3px; }
  .play-label { display: none; }
  .play-tri { border-width: 6px 0 6px 10px; margin: 0 0 1px 3px; }
  .is-compact .screening-tc { display: none; }
}

/* Teardown below desktop: one column, the heading over the frame (with its label and corners), the
   rail under it, then the active chapter alone (the list collapses to it; the rail carries the rest). */
@media (max-width: 1000px) {
  .teardown-chapters { grid-template-columns: minmax(0, 1fr); }
  .is-live .teardown-stage {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    align-content: center;
    align-items: start;
  }
  .is-live .teardown-copy { display: contents; }
  .is-live .teardown-title,
  .is-live .teardown-body,
  .is-live .teardown-chapters { width: min(100%, var(--td-w, 100%)); }
  .is-live .teardown-title,
  .is-live .teardown-body { max-width: none; }
  .is-live .teardown-title { order: 1; }
  .is-live .teardown-body { order: 2; margin-top: 12px; font-size: var(--text-base); }
  .is-live .teardown-screen { order: 3; justify-self: center; margin-top: clamp(16px, 2.6vh, 28px); }
  .is-live .teardown-chapters { order: 4; margin-top: 4px; }
  .is-live .teardown-chapters > li { display: none; padding-left: 0; }
  .is-live .teardown-chapters > li::before,
  .is-live .teardown-chapters > li::after,
  .is-live .td-ch-btn::before,
  .is-live .td-ch-btn::after { display: none; }
  .is-live .teardown-chapters > li.is-active,
  .is-live.is-covered .teardown-chapters > li:first-child { display: block; }
  /* Room for three lines, lit or not, so the frame above never moves. */
  .is-live .teardown-chapters { padding-bottom: 0; }
  .is-live .teardown-chapters > li,
  .is-live .teardown-chapters > .is-active ~ li { transform: none; transition: none; }
  .is-live .teardown-chapters > li .td-ch-line { position: static; height: calc(4.5em + 4px); margin-left: 36px; transform: none; transition: none; }
  .is-live.is-covered .td-ch-line { opacity: 0; }
  .is-live .td-ch-btn { min-height: 44px; padding: 11px 0 9px; }
  .teardown-head { margin-bottom: 14px; }
  .teardown-rail { margin-top: 14px; }
}
/* Short landscape screens: the heading stays, the body gives the frame its room. */
@media (max-height: 560px) {
  .is-live .teardown-body { display: none; }
}
/* Portrait phones: the picture is the focus. The frame runs edge to edge (still 16:9: a taller crop
   would cut the film's burned-in labels, which run to both edges), the label and the rail keep the
   gutter, and the corner marks, which would fall off the screen, are dropped. teardown.js measures
   the frame from the screen's full width here. */
@media (max-width: 760px) and (orientation: portrait) {
  .is-live .teardown-screen {
    justify-self: start;
    width: var(--td-w, 100%);
    margin-left: calc((100% - var(--td-w, 100%)) / 2);
  }
  .is-live .teardown-head,
  .is-live .teardown-rail { margin-left: var(--gutter); margin-right: var(--gutter); }
  .is-live .td-corners { display: none; }
}
/* Landscape phones: the copy and the lit chapter beside the frame, as on desktop, so the frame takes
   the screen's full height instead of a sliver under the heading. teardown.js uses the side
   measurement here too (the same query). */
@media (max-width: 1000px) and (max-height: 560px) and (orientation: landscape) {
  .is-live .teardown-stage {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
    justify-items: stretch;
    align-items: center;
  }
  .is-live .teardown-copy { display: block; }
  .is-live .teardown-title,
  .is-live .teardown-chapters { width: auto; }
  .is-live .teardown-chapters { margin-top: 12px; }
  .is-live .teardown-screen { order: 0; margin-top: 0; justify-self: end; }
}
@media (max-width: 760px) {
  .teardown-body { font-size: var(--text-base); }
  .teardown-static { grid-template-columns: 1fr; gap: 32px; }
  .teardown-label { height: 26px; }
  .teardown-head { height: 26px; }
}

/* Reading room below desktop: the heading stacks over its content, the steps pair up. */
@media (max-width: 1000px) {
  .stages > li { grid-template-columns: 48px minmax(0, 1fr) minmax(0, 1.2fr); }
}
@media (max-width: 900px) {
  .sheet-row,
  .cta-row,
  .story-row,
  .teaser-row { grid-template-columns: minmax(0, 1fr); row-gap: 28px; }
  .page-lead > .wrap { grid-template-columns: minmax(0, 1fr); }
  .page-index { grid-template-columns: 48px minmax(0, 1fr); }
  .page-lede,
  .lead-action { grid-column: 1; }
  .title-block { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .title-block > div:nth-child(3) { border-left: 0; padding-left: 0; }
  .title-block > div:nth-child(n+3) { border-top: 1px solid var(--rule-dark); }
  .stage-row { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 24px; }
  .sheet-title,
  .cta-title { max-width: 12em; }
  .foot-grid { grid-template-columns: minmax(0, 1fr) auto; }
  .foot-brand { grid-column: 1 / -1; }
  .foot-mail { justify-self: end; }
  .foot-meta { grid-column: 1; }
}
@media (max-width: 760px) {
  .spec > div,
  .points > li { grid-template-columns: minmax(0, 1fr); row-gap: 6px; }
  .spec dd,
  .points p { font-size: var(--text-base); }
  .point-title { font-size: var(--text-md); }
  .stages > li { grid-template-columns: minmax(0, 1fr); row-gap: 12px; padding: 22px 0 24px; }
  .stage-line { margin-top: 4px; }
  .stage-title { font-size: var(--text-md); }
  .stage-line { font-size: var(--text-base); }
  .formats tbody th { width: 128px; padding-right: 16px; font-size: var(--text-base); }
  .formats td { font-size: var(--text-base); }
  .brief-list > li { grid-template-columns: 36px minmax(0, 1fr); row-gap: 4px; }
  .brief-hint { grid-column: 2; }
  .brief-label { font-size: var(--text-base); }
  .brief-actions { flex-direction: column; gap: 22px; }   /* stacked, their 44px hit boxes do not overlap */
  .composer-list > li { grid-template-columns: 36px minmax(0, 1fr); column-gap: 8px; padding: 20px 0 22px; }
  .cq-label { font-size: var(--text-base); }
  .cq-grid { grid-template-columns: minmax(0, 1fr); gap: 14px; }
  .choices { gap: 0 20px; }
  .composer-actions { flex-direction: column; align-items: stretch; gap: 20px; }   /* Copy the brief's 44px hit box stays 9px clear of the button */
  .composer-actions .btn-start { width: 100%; }
  .composer-copy { align-self: center; }
  .faq summary { padding-left: 48px; }
  .faq details p { padding-left: 48px; font-size: var(--text-base); }
  .page-lede { font-size: var(--text-base); }
  .title-block > div { padding-left: 14px; padding-right: 8px; }
  .title-block > div:nth-child(odd) { padding-left: 0; }
  .make-text { font-size: var(--text-md); }
  .stage-row { grid-template-columns: minmax(0, 1fr); row-gap: 0; }
  .stage-row li { padding: 0; border-bottom: 1px solid var(--line); }
  .stage-row a { display: flex; align-items: baseline; gap: 16px; padding: 12px 0; }
  .stage-row .mono { flex: none; margin: 0; }
  .foot-grid { grid-template-columns: minmax(0, 1fr); row-gap: 28px; }
  .foot-mark img { width: 200px; }
  .foot-mail,
  .foot-meta,
  .foot-legal { grid-column: 1; justify-self: start; }
}

/* Work page on a phone: the film goes full bleed. */
@media (max-width: 760px) {
  .case-film .is-compact .screening-frame { width: auto; margin-top: 32px; }
}

/* 6. Reduced motion: nothing moves. Keep this block last. ----------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after,
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
}

/* Deep links (/faq/#nda, /process/#quote, /work/press-brake/#hydraulics) land below the header with
   room to breathe, not flush against the top edge. The header is --head-h tall (116 / 72 / 115px). */
.faq details,
.stages > li,
.teardown-chapters > li { scroll-margin-top: calc(var(--head-h) + var(--anchor-gap)); }
