/* Jacob's Brain. Structure follows nevo.md; the look is Swipefast's, which is the
   newest thing in the stack: Gold Front's neutral spine, the Swipefast pink, and
   Bricolage Grotesque over Satoshi. Tokens taken from swipefast-saas/src/app/globals.css
   so the two stay in step. */

/* The page is paper, deliberately, and there is no dark theme.
   Every drawing on this site is graphite on white. Blended with multiply they sink into the page
   and read as part of it, which is the whole effect. On a dark background that blend turns a
   pencil drawing into a black rectangle, so the only way to show them was to float each one on a
   white card, and a white card on a black page is exactly the thing the drawings were meant to
   avoid. Light-only is one decision instead of patching every illustration.
   To bring dark mode back, the drawings have to come back transparent first. */
:root {
  --neutral-0: #ffffff;
  --neutral-50: #fbfbfb;
  --neutral-100: #eeeff1;
  --neutral-500: #8d8e93;
  --neutral-900: #242529;

  /* Swipefast's rose rather than the old #fc176f. On a dark page the darker pink turns
     muddy, and the rose is the accent the other property already uses, so the two now
     share a palette as well as a typeface. 7.0:1 on the app surface. */
  --accent: #ff67b0;
  --accent-ink: #ff8ac4;
  --accent-fill: #d20d59;
  --accent-wash: rgba(255, 103, 176, 0.12);
  --green: #00c674;

  /* Pure black, to match the illustrations. They are drawn white-on-#000, and any
     warmer page colour shows their artboard as a square behind every one of them.
     The drawings are the loudest thing here now, so the page matches them rather
     than the other way round. Cards lift a little so they still read as cards, and
     the art carries mix-blend-mode: screen to cover that case. */
  --surface-app: #000000;
  --surface-card: #0c0c0e;
  --surface-sunk: #060607;
  --line: #2b282f;
  --line-strong: #3c3842;

  /* Paper. The illustrations are graphite on white and cannot be inverted without
     turning into X-rays, so they keep their own paper and the page goes dark around
     them. */
  --paper: #f7f4f1;

  /* 5.8:1 on the app surface. */
  --muted: #98938f;

  --ink: #f4f1ee;
  --ink-2: #c9c4c0;
  --ink-3: rgba(255, 255, 255, 0.58);

  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-pill: 999px;

  /* Borrowed from Swipefast so the two properties read as one family of things:
     Newsreader for display, Geist for everything a person operates. */
  --font-display: 'Newsreader', Georgia, 'Times New Roman', serif;
  --font-prose: 'Geist', 'Helvetica Neue', Arial, sans-serif;
  --font-ui: 'Geist', 'Helvetica Neue', Arial, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;

  /* Expo-out only: fast departure, long settle, no overshoot. */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  --page: 1080px;
  color-scheme: dark;
}

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

body {
  margin: 0;
  background: var(--surface-app);
  color: var(--ink);
  font: 400 17px/1.6 var(--font-prose);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.wrap { width: min(var(--page), 100% - 40px); margin-inline: auto; }
.narrow { width: min(680px, 100%); }

h1, h2, h3 { font-family: var(--font-display); font-weight: 600; letter-spacing: -0.012em; margin: 0; text-wrap: balance; }
h1 { font-size: clamp(2.1rem, 1.3rem + 3.4vw, 3.6rem); line-height: 1.05; }
h2 { font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.3rem); line-height: 1.12; }
h3 { font-size: 1.12rem; line-height: 1.25; letter-spacing: -0.015em; }
p { margin: 0 0 1em; color: var(--ink-2); text-wrap: pretty; }
a { color: inherit; }

.label {
  font: 500 11px/1 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ---- header ---- */
.top {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 0;
  background: color-mix(in srgb, var(--surface-app) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.mark { display: flex; align-items: center; gap: 9px; font: 600 15px/1 var(--font-ui); text-decoration: none; letter-spacing: -0.02em; }
.mark i { width: 22px; height: 22px; border-radius: 7px; background: var(--accent); display: grid; place-items: center; color: #fff; font: 600 11px/1 var(--font-mono); font-style: normal; }
/* The initials tile became his photo. Round rather than the tile's 7px corners, because a
   face in a rounded square reads as an app icon and a face in a circle reads as a person. */
.mark__face { width: 22px; height: 22px; border-radius: 50%; object-fit: cover; display: block; }
.top nav { display: flex; gap: 20px; font: 500 14px/1 var(--font-ui); }
.top nav a { color: var(--ink-2); text-decoration: none; }
.top nav a:hover { color: var(--ink); }
@media (max-width: 680px) { .top nav { display: none; } }

/* ---- hero ---- */
.hero { padding: clamp(48px, 7vw, 96px) 0 clamp(40px, 5vw, 72px); }
/* Three lines at every width from ~1000px up: a 28ch measure against a hero type size that
   stops climbing at 2.7rem. The global h1 clamp keeps going for the letter pages; this one
   is capped because the headline is long and six stacked lines read as a paragraph. */
.hero h1 { max-width: 28ch; font-size: clamp(2.1rem, 1.2rem + 2.6vw, 2.7rem); }
.hero .sub { max-width: 46ch; margin-top: 20px; font-size: 1.08rem; }

.endpoint {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 30px; padding: 7px 7px 7px 16px;
  width: min(560px, 100%);
  border: 1px solid var(--line-strong); border-radius: var(--radius-pill);
  background: var(--surface-card);
}
.endpoint code { flex: 1 1 200px; font: 400 14px/1.4 var(--font-mono); color: var(--ink); overflow-wrap: anywhere; }
.btn {
  appearance: none; border: 0; cursor: pointer;
  padding: 10px 18px; border-radius: var(--radius-pill);
  background: var(--ink); color: var(--surface-app);
  font: 500 14px/1 var(--font-ui);
  transition: transform 180ms var(--ease), opacity 180ms var(--ease);
}
.btn:active { transform: scale(0.97); }
.btn.ghost { background: transparent; color: var(--accent-ink); }
.btn[data-copied="1"] { background: var(--green); color: #fff; }
/* On a narrow screen the URL needs its own line, and a pill radius around wrapped
   text reads as broken, so the whole thing becomes a card with the buttons below. */
@media (max-width: 560px) {
  .endpoint { border-radius: var(--radius-lg); padding: 14px; row-gap: 12px; }
  .endpoint code { flex: 1 1 100%; }
  .endpoint .btn { flex: 1 1 0; text-align: center; }
}

.hero .fine { margin-top: 14px; font: 400 13.5px/1.5 var(--font-ui); color: var(--ink-3); }

/* ---- modules ---- */
.section { padding: clamp(44px, 6vw, 84px) 0; border-top: 1px solid var(--line); }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 20px; margin-bottom: 36px; }

.modules { display: grid; gap: 18px; }
.module {
  display: grid; grid-template-columns: 0.8fr 1.2fr; gap: 40px; align-items: center;
  padding: 32px; border: 1px solid var(--line); border-radius: var(--radius-lg);
  background: var(--surface-card);
}
/* Every other row turns round, so the eye zigzags down the page instead of running
   straight down one gutter. */
.module:nth-of-type(even) .module__art { order: 2; }
.module:nth-of-type(even) .module__body { order: 1; }

.module__art { margin: 0; display: flex; justify-content: center; }
.module__img {
  width: 100%; max-width: 300px; height: auto; display: block;
  mix-blend-mode: screen;
  transition: transform .5s var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .module:hover .module__img { transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) { .module__img { transition: none; } }

/* The device panel used to be the second column. It now sits under the copy it
   belongs to, which is also what lets the drawing have a whole half to itself.
   Column ordering puts the panel before the receipt without moving the markup,
   so each row still ends on the money rather than on a demo. */
.module__body { display: flex; flex-direction: column; }
.module__body .device { order: 1; margin-top: 20px; }
.module__body .receipt { order: 2; }

@media (max-width: 820px) {
  .module { grid-template-columns: 1fr; gap: 22px; padding: 24px; }
  /* Order is reset on one column: the drawing always introduces its own section. */
  .module:nth-of-type(even) .module__art,
  .module:nth-of-type(even) .module__body { order: 0; }
  .module__img { max-width: 200px; }
}
.module .claim { margin: 10px 0 12px; font-family: var(--font-display); font-size: 1.3rem; font-weight: 600; letter-spacing: -0.01em; line-height: 1.2; }
.module p { font-size: 0.97rem; margin-bottom: 0; }
.module .src { display: inline-block; margin-top: 14px; font: 500 13px/1 var(--font-ui); color: var(--accent-ink); text-decoration: none; border-bottom: 1px solid currentColor; padding-bottom: 2px; }

/* the device panel on the right of each module */
.device { padding: 20px; border-radius: var(--radius-md); background: var(--surface-sunk); border: 1px solid var(--line); }
.device .row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 9px 0; border-bottom: 1px dashed var(--line-strong); font: 400 14px/1.3 var(--font-ui); }
.device .row:last-child { border-bottom: 0; }
.device .row b { font: 500 13px/1 var(--font-mono); color: var(--ink); }
.device .row.off { color: var(--ink-3); text-decoration: line-through; text-decoration-color: var(--line-strong); }
.device .row.on b { color: var(--accent-ink); }

.chips { display: flex; flex-wrap: wrap; gap: 7px; }
.chip { padding: 5px 11px; border-radius: var(--radius-pill); background: var(--neutral-100); color: var(--ink-2); font: 500 12.5px/1 var(--font-ui); }
.chip.hot { background: var(--accent-wash); color: var(--accent-ink); }

/* A rung is the same row as the other devices, with the bar drawn behind it, so the
   label never has to share horizontal space with a growing bar. */
.device .row.rung { position: relative; padding-inline: 10px; margin-inline: -10px; border-radius: var(--radius-sm); }
.device .row.rung::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: var(--w);
  border-radius: var(--radius-sm); background: var(--accent-wash);
  transform: scaleX(0); transform-origin: left;
  transition: transform 900ms var(--ease);
}
.device .row.rung:last-child::before { background: color-mix(in srgb, var(--accent) 30%, transparent); }
.in .device .row.rung::before { transform: scaleX(1); }
.device .row.rung:nth-child(2)::before { transition-delay: 90ms; }
.device .row.rung:nth-child(3)::before { transition-delay: 180ms; }
.device .row.rung:nth-child(4)::before { transition-delay: 270ms; }
/* Load-bearing: this lifts the row's content above the bar, but it only reaches ELEMENT
   children. A bare text label stays under the ::before and the opaque --accent-wash paints
   straight over it, which is how three of the four rung labels went invisible. Every label
   in a .rung must be wrapped in a span. */
.device .row.rung > * { position: relative; }

.receipt { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
.receipt .big { font: 700 1.8rem/1 var(--font-display); letter-spacing: -0.03em; color: var(--ink); }
.receipt .cap { margin-top: 5px; font: 400 13px/1.45 var(--font-ui); color: var(--ink-3); }

/* ---- q and a ---- */
.qa { display: grid; gap: 14px; padding: 24px; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface-sunk); }
.qa .turn { display: grid; gap: 6px; }
.qa .who { font: 500 11px/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); }
.qa .you { font-family: var(--font-display); font-size: 1.12rem; font-weight: 600; letter-spacing: -0.01em; }
.qa ul { margin: 0; padding-left: 18px; }
.qa li { margin-bottom: 7px; color: var(--ink-2); font-size: 0.97rem; }
.qa .cite { font: 400 12.5px/1.4 var(--font-mono); color: var(--ink-3); }

/* ---- steps ---- */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
@media (max-width: 720px) { .steps { grid-template-columns: 1fr; } }
.step { padding: 22px; border: 1px solid var(--line); border-radius: var(--radius-lg); }
.step .n { display: grid; place-items: center; width: 26px; height: 26px; margin-bottom: 14px; border-radius: var(--radius-pill); background: var(--ink); color: var(--surface-app); font: 500 12px/1 var(--font-mono); }
.step p { margin-bottom: 0; font-size: 0.95rem; }

/* ---- connect tabs ---- */
.tabs { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 22px; }
.tab {
  appearance: none; cursor: pointer;
  padding: 8px 15px; border-radius: var(--radius-pill);
  border: 1px solid var(--line-strong); background: transparent; color: var(--ink-2);
  font: 500 13.5px/1 var(--font-ui);
  transition: background-color 160ms var(--ease), color 160ms var(--ease), border-color 160ms var(--ease);
}
.tab[aria-selected="true"] { background: var(--ink); border-color: var(--ink); color: var(--surface-app); }
.panel { padding: 24px; border: 1px solid var(--line); border-radius: var(--radius-lg); background: var(--surface-card); }
.panel[hidden] { display: none; }
.panel ol { margin: 0; padding-left: 20px; }
.panel li { margin-bottom: 9px; color: var(--ink-2); font-size: 0.97rem; }
.panel pre {
  margin: 14px 0 0; padding: 14px 16px; overflow-x: auto;
  border-radius: var(--radius-md); background: var(--neutral-900); color: #f2f3f5;
  font: 400 13px/1.55 var(--font-mono);
}

/* ---- founder ---- */
.founder { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: 36px; align-items: start; }
@media (max-width: 820px) { .founder { grid-template-columns: 1fr; gap: 20px; } }

/* ---- footer ---- */
footer { padding: 40px 0 56px; border-top: 1px solid var(--line); }
footer .links { display: flex; flex-wrap: wrap; gap: 18px; margin-top: 18px; font: 400 13.5px/1 var(--font-ui); }
footer .links a { color: var(--ink-3); }
footer .disclosure { max-width: 60ch; font: 400 13px/1.55 var(--font-ui); color: var(--ink-3); }

/* The made-by credit. Deliberately the quietest thing in the footer: 12.5px, the dimmest ink
   on the page, and the emoji at low opacity so they read as a flourish rather than as content.
   --ink-3 is the muted footer ink the links above already use, so this sits below them without
   introducing another grey. */
/* One sentence, not a row of boxes: the emoji and the name sit inside the text, so this is
   ordinary inline flow and the line wraps on a narrow screen like any other sentence would. */
.madeby {
  margin: 26px 0 0;
  font: 400 12.5px/1.8 var(--font-ui);
  color: var(--ink-3);
}
.madeby__bits { opacity: .65; letter-spacing: .04em; }
.madeby__who {
  display: inline-flex;
  align-items: center;
  /* Against a line of text rather than inside a flex row now, so it needs aligning to the
     middle of the line: on the baseline the 18px photo would hang below it. */
  vertical-align: middle;
  gap: 6px;
  color: var(--ink-2);
  font-weight: 500;
  text-decoration: none;
  transition: color .22s cubic-bezier(0.16, 1, 0.3, 1);
}
.madeby__who img { width: 18px; height: 18px; border-radius: 50%; object-fit: cover; display: block; }
@media (hover: hover) and (pointer: fine) {
  .madeby__who:hover { color: var(--accent-ink); }
}
.madeby__who:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 3px; border-radius: 4px; }
@media (prefers-reduced-motion: reduce) { .madeby__who { transition: none; } }

/* ---- draft markers. Remove class="draft" from <body> to see the page clean. ---- */
[data-todo] { font-style: normal; }
.draft [data-todo] {
  background: var(--accent-wash);
  box-shadow: inset 0 -2px 0 var(--accent);
  padding: 0 3px; border-radius: 2px; cursor: help;
}
.draft-bar {
  display: none;
  padding: 10px 0; background: var(--neutral-900); color: #fff;
  font: 500 13px/1.4 var(--font-ui); text-align: center;
}
.draft .draft-bar { display: block; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* ==========================================================================
   Illustrations. Original line art on the same geometry as the rest of the
   page, so it reads as drawn for this site rather than borrowed.
   ========================================================================== */
.hero { display: grid; grid-template-columns: 1.25fr 0.75fr; gap: 40px; align-items: center; }
@media (max-width: 900px) { .hero { grid-template-columns: 1fr; gap: 8px; } .hero-art { order: -1; max-width: 340px; } }

.hero-art svg { width: 100%; height: auto; display: block; }
svg .ink { stroke: var(--ink); }
svg .ink-soft { stroke: var(--line-strong); }
svg .accent { stroke: var(--accent); }
svg .accent-fill { fill: var(--accent); }
.spot { width: 62px; height: 62px; display: block; margin-bottom: 12px; overflow: visible; }

/* ---- motion ---- */
.reveal { opacity: 0; transform: translateY(16px); transition: opacity 700ms var(--ease), transform 700ms var(--ease); }
.reveal.in, .in .reveal { opacity: 1; transform: none; }

/* hero: the arc draws, then letters travel it */
.hero-art .arc { stroke: var(--accent); transition: stroke-dashoffset 1400ms var(--ease) 200ms; }
.in .hero-art .arc { stroke-dashoffset: 0; }

.hero-art .flyer { stroke: var(--accent); fill: var(--surface-app); opacity: 0; }
.in .hero-art .flyer {
  offset-path: path("M150 250C196 158 232 110 318 112");
  animation: travel 3.4s cubic-bezier(0.45, 0, 0.3, 1) infinite;
}
.in .hero-art .f2 { animation-delay: 1.1s; }
.in .hero-art .f3 { animation-delay: 2.2s; }
@keyframes travel {
  0% { offset-distance: 0%; opacity: 0; }
  12% { opacity: 1; }
  78% { opacity: 1; }
  92%, 100% { offset-distance: 100%; opacity: 0; }
}

.hero-art .stack { animation: float 6s ease-in-out infinite; }
@keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }

.hero-art .typed { transform: scaleX(0); transform-origin: left; transition: transform 600ms var(--ease); }
.in .hero-art .t1 { transform: scaleX(1); transition-delay: 900ms; }
.in .hero-art .t2 { transform: scaleX(1); transition-delay: 1100ms; }
.in .hero-art .t3 { transform: scaleX(1); transition-delay: 1300ms; }
.hero-art .caret { opacity: 0; }
.in .hero-art .caret { animation: blink 1.1s steps(2) 1700ms infinite; }
@keyframes blink { 0%, 50% { opacity: 1; } 51%, 100% { opacity: 0; } }

.hero-art .sparks > * { opacity: 0; transform-box: fill-box; transform-origin: center; }
.in .hero-art .sparks > * { animation: twinkle 3.2s ease-in-out infinite; }
.in .hero-art .s2 { animation-delay: 0.9s; }
.in .hero-art .s3 { animation-delay: 1.8s; }
@keyframes twinkle { 0%, 100% { opacity: 0; transform: scale(0.6); } 45% { opacity: 1; transform: scale(1); } }

/* module spots */
.spot .draw { stroke-dasharray: 60; stroke-dashoffset: 60; transition: stroke-dashoffset 700ms var(--ease) 250ms; }
.in .spot .draw { stroke-dashoffset: 0; }
.spot .rise { transform-box: fill-box; transform-origin: center; transform: translateY(8px); opacity: 0; transition: transform 600ms var(--ease) 250ms, opacity 600ms var(--ease) 250ms; }
.in .spot .rise { transform: none; opacity: 1; }
.spot .flag { transform-box: fill-box; transform-origin: right center; transform: scaleX(0); transition: transform 600ms var(--ease) 200ms; }
.in .spot .flag { transform: scaleX(1); }
.spot .spin { transform-box: fill-box; transform-origin: 52% 52%; }
.in .spot .spin { animation: spin 7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* devices reveal row by row */
.device .row { opacity: 0; transform: translateY(8px); transition: opacity 500ms var(--ease), transform 500ms var(--ease); }
.in .device .row { opacity: 1; transform: none; }
.in .device .row:nth-child(2) { transition-delay: 80ms; }
.in .device .row:nth-child(3) { transition-delay: 160ms; }
.in .device .row:nth-child(4) { transition-delay: 240ms; }
.in .device .row:nth-child(5) { transition-delay: 320ms; }

.chip { opacity: 0; transform: scale(0.9); transition: opacity 450ms var(--ease), transform 450ms var(--ease); }
.in .chip { opacity: 1; transform: none; }
.in .chip:nth-child(2) { transition-delay: 70ms; }
.in .chip:nth-child(3) { transition-delay: 140ms; }
.in .chip:nth-child(4) { transition-delay: 210ms; }
.in .chip:nth-child(5) { transition-delay: 280ms; }
.in .chip:nth-child(6) { transition-delay: 350ms; }

.step:hover, .module:hover { border-color: var(--line-strong); }
.module, .step { transition: border-color 300ms var(--ease); }

/* Motion is decoration here, so switching it off leaves the finished state. */
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
  .hero-art .arc { stroke-dashoffset: 0 !important; }
  .hero-art .flyer, .hero-art .caret, .hero-art .sparks > * { display: none; }
  .hero-art .stack, .in .spot .spin { animation: none; }
  .hero-art .typed, .spot .flag { transform: scaleX(1) !important; }
  .spot .draw { stroke-dashoffset: 0 !important; }
  .spot .rise { opacity: 1 !important; transform: none !important; }
  .device .row, .chip { opacity: 1 !important; transform: none !important; }
  .device .row.rung::before { transform: scaleX(1) !important; }
}

/* the extra pieces in each module scene */
.spot .cross { stroke-dasharray: 44; stroke-dashoffset: 44; transition: stroke-dashoffset 600ms var(--ease) 350ms; }
.in .spot .cross { stroke-dashoffset: 0; }
.spot .lift { opacity: 0; transform: translateY(6px); transition: opacity 600ms var(--ease) 420ms, transform 600ms var(--ease) 420ms; }
.in .spot .lift { opacity: 1; transform: none; }
.spot .dot { opacity: 0; transform-box: fill-box; transform-origin: center; }
.in .spot .dot { animation: feed 2.8s ease-in-out infinite; }
.in .spot .d2 { animation-delay: 0.45s; }
.in .spot .d3 { animation-delay: 0.9s; }
@keyframes feed { 0%, 100% { opacity: 0; transform: translateY(0); } 40% { opacity: 1; } 70% { opacity: 0; transform: translateY(7px); } }
@media (prefers-reduced-motion: reduce) {
  .spot .cross { stroke-dashoffset: 0 !important; }
  .spot .lift { opacity: 1 !important; transform: none !important; }
  .in .spot .dot { animation: none; opacity: 1; }
}

/* ---- receipts ----
   The calendar is the section's argument, so it gets the width and nothing is drawn around it.
   No panel, no card: the squares are the evidence and a border would only add furniture. */
.receipts-lede,
.receipts-note {
  font: 400 1.0625rem/1.6 var(--font-prose);
  color: var(--ink-2);
  max-width: 62ch;
  margin: 0 0 28px;
}
.receipts-note { margin-top: 30px; }

.cal__wrap {
  /* Two and a half years of days is wider than a phone. It scrolls, and the mask tells you so
     without adding a scrollbar or a hint that has to be translated. */
  overflow-x: auto;
  overflow-y: hidden;
  padding: 4px 0 6px;
  mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
}
@media (min-width: 1100px) {
  .cal__wrap { mask-image: none; -webkit-mask-image: none; }
}
.cal { display: block; height: auto; }
.cal__off { fill: var(--line); }
.cal__on { fill: var(--accent); opacity: 0.55; }
.cal__on--2 { opacity: 1; }
.cal__tick {
  font: 500 10px/1 var(--font-mono);
  letter-spacing: 0.08em;
  fill: var(--ink-3);
}

.tally {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  margin: 26px 0 0;
  padding-top: 22px;
  border-top: 1px solid var(--line);
}
.tally div { margin: 0; }
.tally dt {
  font: 500 11px/1 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 9px;
}
.tally dd {
  margin: 0;
  font: 700 clamp(1.1rem, 0.85rem + 0.8vw, 1.5rem)/1.15 var(--font-display);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
@media (max-width: 760px) {
  .tally { grid-template-columns: repeat(2, 1fr); gap: 20px 18px; }
}

/* A list, not a grid of tiles. Each line is a figure, what it is, and where it was said. */
.claims { list-style: none; margin: 0; padding: 0; }
.claims li {
  display: grid;
  grid-template-columns: minmax(130px, max-content) 1fr max-content;
  align-items: baseline;
  gap: 8px 22px;
  padding: 15px 0;
  border-bottom: 1px solid var(--line);
}
.claims li:first-child { border-top: 1px solid var(--line); }
.claims__n {
  font: 700 1.15rem/1.2 var(--font-display);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.claims__what { font: 400 0.9375rem/1.5 var(--font-prose); color: var(--ink-2); }
.claims__src {
  font: 500 11px/1.4 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--ink-3);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 300ms var(--ease), border-color 300ms var(--ease);
  white-space: nowrap;
}
.claims__src:hover, .claims__src:focus-visible {
  color: var(--accent-ink);
  border-bottom-color: currentColor;
}
@media (max-width: 760px) {
  .claims li { grid-template-columns: 1fr; gap: 5px; }
  .claims__src { white-space: normal; }
}

/* The calendar fills in left to right once it is on screen. Columns, not squares, so it reads
   as time passing rather than as confetti. Gated on .js and dropped under reduced motion. */
.js .cal__on { opacity: 0; }
.js .in .cal__on { animation: cal-in 520ms var(--ease) forwards; }
@keyframes cal-in {
  from { opacity: 0; transform: translateY(3px); }
  to { opacity: 0.55; transform: none; }
}
.js .in .cal__on--2 { animation-name: cal-in-2; }
@keyframes cal-in-2 {
  from { opacity: 0; transform: translateY(3px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .js .cal__on { opacity: 0.55; }
  .js .cal__on--2 { opacity: 1; }
  .js .in .cal__on, .js .in .cal__on--2 { animation: none; }
}

/* ---- a single letter ----
   A reading page. One column, generous measure, nothing in the margins competing with the words. */
.letter { padding: clamp(36px, 5vw, 64px) 0 clamp(48px, 6vw, 90px); }
.letter article { max-width: 64ch; }
.letter h1 {
  font: 700 clamp(1.5rem, 1.1rem + 1.7vw, 2.2rem)/1.14 var(--font-display);
  margin: 12px 0 28px;
  letter-spacing: -0.015em;
}
.letter .label { display: block; }
.letter__body { font: 400 1.0625rem/1.72 var(--font-prose); color: var(--ink-2); }
.letter__body p { margin: 0 0 1.15em; }
.letter__body a { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 2px; }
.letter__after {
  max-width: 64ch;
  margin-top: 44px;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font: 400 0.9375rem/1.6 var(--font-prose);
  color: var(--ink-3);
}
.letter__after p { margin: 0 0 10px; }
.letter__after strong { color: var(--ink); font-variant-numeric: tabular-nums; }

/* ==========================================================================
   The scroll story. Four chapters, one per channel. No cards: a hairline and a
   numeral in the gutter do the separating, because four bordered boxes in a row
   is the look every generated page has. Each chapter's art is a different kind
   of drawing on purpose, so the rhythm comes from the content rather than from
   a repeated template.
   ========================================================================== */
.story { list-style: none; margin: 0; padding: 0; counter-reset: chapter; }
.chapter {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr);
  gap: 0 28px;
  padding: clamp(34px, 4vw, 56px) 0;
  border-top: 1px solid var(--line);
}
.chapter:first-child { border-top: 0; padding-top: 6px; }

/* The numeral is furniture, so it sits at the weight of a caption and never competes
   with the claim beside it. */
.chapter__n {
  font: 500 12px/1 var(--font-mono);
  letter-spacing: 0.08em;
  color: var(--ink-3);
  padding-top: 6px;
}
.chapter__copy { max-width: 60ch; }
.chapter__claim {
  font: 700 clamp(1.4rem, 1.05rem + 1.3vw, 2rem)/1.13 var(--font-display);
  letter-spacing: -0.025em;
  margin: 12px 0 18px;
  text-wrap: balance;
}
.chapter__figure {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 12px;
  margin: 0 0 20px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}
.chapter__figure b {
  font: 700 clamp(1.7rem, 1.2rem + 2vw, 2.6rem)/1 var(--font-display);
  letter-spacing: -0.035em;
  color: var(--accent-ink);
  font-variant-numeric: tabular-nums;
}
.chapter__figure span { font: 400 0.9375rem/1.4 var(--font-prose); color: var(--ink-3); }
.chapter__copy p { font-size: 1.0125rem; }

.chapter__art { grid-column: 2; margin: 22px 0 0; }
/* The ring is a diagram, not a chart: stretched to the full column it becomes a lot of empty
   middle. Capped, it sits at the size it was drawn. */
.chapter__art--narrow svg { max-width: 430px; }
.chapter__art svg { display: block; width: 100%; height: auto; overflow: visible; }
.chapter__art figcaption {
  max-width: 64ch;
  margin-top: 16px;
  font: 400 13px/1.55 var(--font-ui);
  color: var(--ink-3);
}
@media (max-width: 680px) {
  .chapter { grid-template-columns: 1fr; gap: 0; }
  .chapter__n { padding-top: 0; margin-bottom: 4px; }
  .chapter__art { grid-column: 1; }
}

/* ---- the drawings ---- */
.ch__lab { font: 500 11px/1 var(--font-mono); letter-spacing: 0.06em; fill: var(--ink-3); }
.ch__num { fill: var(--ink); font-weight: 500; }
.ch__key { font: 500 10px/1 var(--font-mono); letter-spacing: 0.1em; fill: var(--ink-3); text-transform: uppercase; }
.ch__key--money { fill: var(--accent-ink); }

/* 01: two bars a row, grown from the left so the eye reads length rather than arrival */
.ch__bar { transform-box: fill-box; transform-origin: left center; }
.ch__bar--views { fill: var(--line-strong); }
.ch__bar--money { fill: var(--accent); }
.js .ch__bar { transform: scaleX(0); }
.js .in .ch__bar { transform: scaleX(1); transition: transform 900ms var(--ease); transition-delay: calc(var(--i) * 110ms); }

/* 02: the ring draws, then one dot runs it forever */
.ch__ring { stroke: var(--line-strong); stroke-width: 1.5; stroke-dasharray: 604; }
.js .ch__ring { stroke-dashoffset: 604; }
.js .in .ch__ring { stroke-dashoffset: 0; transition: stroke-dashoffset 1500ms var(--ease) 150ms; }
.ch__node { fill: var(--surface-app); stroke: var(--accent); stroke-width: 2; }
.js .ch__node { opacity: 0; }
.js .in .ch__node { opacity: 1; transition: opacity 500ms var(--ease); transition-delay: calc(900ms + var(--i) * 180ms); }
.ch__mid { font: 500 12px/1 var(--font-mono); letter-spacing: 0.04em; fill: var(--ink-3); }
.ch__orbit { fill: var(--accent); opacity: 0; }
.js .in .ch__orbit {
  offset-path: path("M 230 36 a 96 96 0 1 1 0 192 a 96 96 0 1 1 0 -192");
  animation: ch-orbit 5.5s linear 1600ms infinite;
}
@keyframes ch-orbit {
  0% { offset-distance: 0%; opacity: 0; }
  6%, 94% { opacity: 1; }
  100% { offset-distance: 100%; opacity: 0; }
}

/* 03: sixty-three dots, one per customer, filling in reading order */
.ch__dot { fill: var(--accent); }
.js .ch__dot { opacity: 0; transform: scale(0.4); transform-box: fill-box; transform-origin: center; }
.js .in .ch__dot {
  opacity: 1; transform: none;
  transition: opacity 420ms var(--ease), transform 420ms var(--ease);
  transition-delay: calc(var(--i) * 18ms);
}

/* 04: the funnel. Only the surviving bar gets the accent, so the drop is the point */
.ch__step { fill: var(--line-strong); transform-box: fill-box; transform-origin: left center; }
.ch__step--last { fill: var(--accent); }
.js .ch__step { transform: scaleX(0); }
.js .in .ch__step { transform: scaleX(1); transition: transform 850ms var(--ease); transition-delay: calc(var(--i) * 140ms); }

/* Motion here is all decoration, so switching it off has to leave the drawing finished rather
   than leave it hidden. Every rule above is gated on .js for the same reason. */
@media (prefers-reduced-motion: reduce) {
  .js .ch__bar, .js .ch__step { transform: scaleX(1) !important; }
  .js .ch__ring { stroke-dashoffset: 0 !important; }
  .js .ch__node { opacity: 1 !important; }
  .js .ch__dot { opacity: 1 !important; transform: none !important; }
  .js .in .ch__orbit { animation: none; display: none; }
}

/* ---- the hero brain ---- */
/* The SVG underneath is the fallback and stays in the markup. brain.js adds .is-live only after
   it has drawn a real frame, so the drawing is never hidden in front of a blank canvas. */
.hero-art { position: relative; }
.hero-art canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.hero-art > svg { transition: opacity .45s cubic-bezier(0.16, 1, 0.3, 1); }
.hero-art.is-live > svg { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .hero-art > svg { transition: none; } }

/* ---- the drawings ---- */
/* Flat PNGs on white. multiply drops the white out so they sit on the card rather than in a box,
   and the dark-theme rule puts the paper back behind them, because multiply on a dark background
   turns a pencil drawing into a black rectangle. */

@media (hover: hover) and (pointer: fine) {
  .module:hover }
@media (prefers-reduced-motion: reduce) {  .module:hover  }

/* The chapter drawings sit in the copy column, above the claim, so the charts in .chapter__art
   keep their place. Those charts carry the actual figures; these carry the tone. As a direct
   child of .chapter__copy the vignette is picked up by the existing stagger in site.js, so it
   reveals with the rest of the chapter rather than needing its own rule. */
.chapter__vignette {
  width: 104px; height: 104px; display: block; margin: 0 0 10px -6px;
  mix-blend-mode: screen;
}

@media (max-width: 720px) { .chapter__vignette { width: 84px; height: 84px; } }

/* The hero drawing. Not aria-hidden any more: it is the picture of the thing, so it gets a real
   alt. A slow float, because a drawing held up like a trophy wants to hang in the air a little. */
.hero-art__img {
  width: 100%; height: auto; display: block;
  mix-blend-mode: screen;
  animation: hero-float 7s ease-in-out infinite;
}

@keyframes hero-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
@media (prefers-reduced-motion: reduce) { .hero-art__img { animation: none; } }

/* ---- the scene ---- */
/* Four channel nodes wired into one brain. The .in class comes from the IntersectionObserver in
   site.js, so the whole thing is gated on .js: with scripting off every node renders finished and
   in place, which is why the hidden states live under .js and not on the element itself. */
.scene { margin: 54px 0 10px; }
.scene__stage { position: relative; width: 100%; max-width: 620px; margin: 0 auto; aspect-ratio: 1 / 0.82; }

.scene__wires { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.scene__wires path {
  fill: none; stroke: var(--accent); stroke-width: 0.35; stroke-linecap: round; opacity: 0.5;
  vector-effect: non-scaling-stroke;
}
/* Each wire draws itself from the node towards the brain. 160 is comfortably longer than the
   longest path in a 100x100 box, so one number does for all four. */
.js .scene__wires path { stroke-dasharray: 160; stroke-dashoffset: 160; }
.js .scene.in .scene__wires path { transition: stroke-dashoffset 1.1s cubic-bezier(0.16, 1, 0.3, 1) .25s; stroke-dashoffset: 0; }

.scene__core, .scene__node { position: absolute; transform: translate(-50%, -50%); text-align: center; }
.scene__core { left: 50%; top: 50%; width: 38%; }
.scene__core img {
  width: 100%; height: auto; display: block;
  mix-blend-mode: screen;
}
.scene__core b { display: block; margin-top: 2px; font: 500 11px/1 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--accent-ink); }

.scene__node { left: var(--x); top: var(--y); width: 22%; min-width: 104px; }
@media (max-width: 520px) {
  /* The nodes are centred on a percentage of the stage, so once the 104px floor and the
     label's own text make one wider than its share, the outermost ones hang past the
     stage edge. That was the page's 6px of horizontal scroll on a phone. */
  .scene__node { min-width: 0; max-width: 38vw; }
}
.scene__node img {
  width: 74px; height: 74px; margin: 0 auto; display: block;
  mix-blend-mode: screen;
}
.scene__node b { display: block; margin-top: 4px; font-family: var(--font-display); font-weight: 600; font-size: 1rem; letter-spacing: -0.01em; }
.scene__node span { display: block; font: 400 12.5px/1.35 var(--font-ui); color: var(--muted, #6b6d76); }

.js .scene__node { opacity: 0; transform: translate(-50%, -50%) translate(var(--dx), var(--dy)); }
.js .scene.in .scene__node { opacity: 1; transform: translate(-50%, -50%); transition: opacity .7s cubic-bezier(0.16, 1, 0.3, 1), transform .7s cubic-bezier(0.16, 1, 0.3, 1); }
.js .scene.in .scene__node:nth-of-type(2) { transition-delay: .08s; }
.js .scene.in .scene__node:nth-of-type(3) { transition-delay: .16s; }
.js .scene.in .scene__node:nth-of-type(4) { transition-delay: .24s; }
.js .scene.in .scene__node:nth-of-type(5) { transition-delay: .32s; }

.scene figcaption { max-width: 48ch; margin: 18px auto 0; text-align: center; font-size: .92rem; color: var(--muted, #6b6d76); }

/* Four absolutely-positioned nodes on a phone is a pile. Below 720 it is a plain grid. */
@media (max-width: 720px) {
  .scene__stage { aspect-ratio: auto; display: grid; grid-template-columns: 1fr 1fr; gap: 22px 12px; }
  .scene__wires { display: none; }
  .scene__core, .scene__node { position: static; transform: none; width: auto; }
  .scene__core { grid-column: 1 / -1; width: 54%; margin: 0 auto 6px; }
  .js .scene__node { transform: translate(var(--dx), var(--dy)); }
  .js .scene.in .scene__node { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .js .scene__node, .js .scene.in .scene__node { opacity: 1 !important; transform: translate(-50%, -50%) !important; transition: none !important; }
  .js .scene__wires path { stroke-dashoffset: 0 !important; transition: none !important; }
  @media (max-width: 720px) {
    .js .scene__node, .js .scene.in .scene__node { transform: none !important; }
  }
}


/* ---- the about video ---- */
/* A facade, not an embed. The iframe is created on click by site.js, so the page itself makes no
   request to Google and the privacy notice stays true for anyone who does not press play. */
.video { margin: 20px 0 0; }
.video__play {
  position: relative; display: block; width: 100%; padding: 0; border: 0; background: none;
  cursor: pointer; border-radius: 14px; overflow: hidden; line-height: 0;
  box-shadow: 0 1px 0 var(--line, #eeeff1), 0 18px 40px -28px rgba(0,0,0,.5);
}
.video__play img { width: 100%; height: auto; display: block; transition: transform .6s var(--ease); }
@media (hover: hover) and (pointer: fine) { .video__play:hover img { transform: scale(1.02); } }
.video__play:focus-visible img { transform: scale(1.02); }
.video__btn {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 62px; height: 62px; border-radius: 50%; background: var(--accent); color: #fff;
  display: grid; place-items: center; transition: transform .4s var(--ease);
}
.video__btn svg { width: 26px; height: 26px; margin-left: 2px; }
@media (hover: hover) and (pointer: fine) {
  .video__play:hover .video__btn { transform: translate(-50%, -50%) scale(1.07); }
}
/* Visible to screen readers, off the screen for everyone else: the button needs a real name. */
.video__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.video__cap { margin: 10px 2px 0; font: 400 13px/1.5 var(--font-ui); color: var(--muted, #6b6d76); }
/* A credit, not a caption: it should read as the small print under the frame, so it sits
   a step down from .video__cap in both size and weight of attention. */
.video__credit { margin: 4px 2px 0; font: 400 11px/1.4 var(--font-ui); letter-spacing: .01em; color: var(--muted); }
.video iframe { width: 100%; aspect-ratio: 16 / 9; border: 0; border-radius: 14px; display: block; }
@media (prefers-reduced-motion: reduce) {
  .video__play img, .video__btn { transition: none; }
  .video__play:hover img { transform: none; }
}


/* Where the thinking is published in the first place. rel="me" so the links are a claim of
   identity rather than just navigation. */
.whoami { display: flex; flex-wrap: wrap; gap: 18px; margin: 18px 0 0; }

/* The social row as glyphs. The link is 36px square while the icon is 20px, because the tap
   target is what WCAG 2.5.8 measures and a 20px one fails it: the padding is load-bearing,
   not decoration. --muted is 5.15:1 on white, well clear of the 3:1 that 1.4.11 asks of an
   icon that carries meaning. */
.whoami--icons { gap: 6px; align-items: center; }
.iconlink {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  margin-left: -8px;  /* pull the first glyph back to the text margin, since the box is padded */
  border-radius: 10px;
  color: var(--muted);
  /* Expo-out. Never a bounce: this is a row of links, not a toy. */
  transition: color .22s cubic-bezier(0.16, 1, 0.3, 1), background-color .22s cubic-bezier(0.16, 1, 0.3, 1);
}
.iconlink svg { width: 20px; height: 20px; display: block; }
@media (hover: hover) and (pointer: fine) {
  .iconlink:hover { color: var(--accent-ink); background: var(--accent-wash); }
}
.iconlink:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .iconlink { transition: none; } }


/* ---- what works, what stopped ---- */
/* Two columns of judgement. The pink marks the keeps and a struck grey marks the drops, so the
   shape of the opinion reads before any of the words do. */
.verdict { display: grid; grid-template-columns: 1fr 1fr; gap: 28px; margin-top: 26px; }
.verdict__col h3 { font-family: var(--font-display); font-weight: 600; font-size: 1.12rem; letter-spacing: -0.01em; margin: 0 0 12px; }
.verdict__col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.verdict__col li { position: relative; padding-left: 26px; font-size: .98rem; line-height: 1.45; }
.verdict__col li::before { position: absolute; left: 0; top: 0; font: 500 13px/1.5 var(--font-mono); }
.verdict__col--yes li::before { content: "+"; color: var(--accent-ink); }
.verdict__col--no li::before { content: "\2013"; color: var(--muted); }
.verdict__col--no li { color: var(--muted); }
/* The note underneath is a separate thought from the columns and needs the air to say so. */
#working .fine { margin-top: 26px; }
@media (max-width: 720px) { .verdict { grid-template-columns: 1fr; gap: 22px; } }

/* ---- prose pages: /docs and /privacy ----
   One column at a reading measure, headings that can be scanned from the nav, and code
   set in the mono role so a thing you paste never looks like a thing you read.
   .page is the shared frame; .doc adds what only the reference page needs. */
/* Its own width rather than .wrap plus .narrow: putting both on one element lets
   .narrow's min(680px, 100%) win, which takes the side gutter with it on a phone. */
.page { width: min(680px, 100% - 40px); margin-inline: auto; padding: 40px 0 72px; }
.page > .label { display: block; margin-bottom: 10px; }
.page h1 { margin-bottom: 18px; }
.page__lede { font-size: 1.08rem; max-width: 60ch; }
.page h2 {
  margin: 56px 0 14px;
  padding-top: 26px;
  border-top: 1px solid var(--line);
  scroll-margin-top: 78px;
}
.page h3 { margin: 30px 0 8px; }
.page h3 code { font-size: 1rem; }
.page ul { margin: 0 0 1em; padding-left: 20px; color: var(--ink-2); }
.page li { margin-bottom: .5em; text-wrap: pretty; }
.page li strong { color: var(--ink); }
.page .endpoint { margin: 24px 0 8px; }

/* Inline code is a noun in a sentence; a block is something you copy. Different jobs,
   so only the block gets a container. */
.page code {
  font: 500 13.5px/1.5 var(--font-mono);
  background: var(--accent-wash);
  color: var(--accent-ink);
  padding: 2px 5px;
  border-radius: 5px;
}
.page pre {
  margin: 0 0 1em;
  padding: 14px 16px;
  background: var(--surface-sunk);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  overflow-x: auto;
}
.page pre code { background: none; color: var(--ink); padding: 0; font-size: 13px; }

.doc__table { width: 100%; margin: 0 0 1.4em; border-collapse: collapse; font: 400 14.5px/1.5 var(--font-ui); }
.doc__table th {
  text-align: left; padding: 0 12px 8px 0;
  font: 500 11px/1 var(--font-mono); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3);
  border-bottom: 1px solid var(--line-strong);
}
.doc__table td { padding: 10px 12px 10px 0; border-bottom: 1px solid var(--line); color: var(--ink-2); vertical-align: top; }
.doc__table td:first-child { color: var(--ink); white-space: nowrap; }
.doc__table tr:last-child td { border-bottom: 0; }
@media (max-width: 560px) {
  /* Three columns of prose do not fit a phone, and a table that scrolls sideways inside a
     page that does not is worse than one that wraps. */
  .doc__table td:first-child { white-space: normal; }
  .doc__table { font-size: 13.5px; }
}

.doc__prompts { list-style: none; padding-left: 0; }
.doc__prompts li {
  padding: 10px 14px; margin-bottom: 8px;
  background: var(--surface-sunk); border: 1px solid var(--line); border-radius: var(--radius-md);
  font: 400 15px/1.45 var(--font-ui); color: var(--ink-2);
}
.page__foot {
  display: flex; gap: 22px; flex-wrap: wrap;
  margin-top: 64px; padding-top: 22px; border-top: 1px solid var(--line);
  font: 500 14px/1 var(--font-ui);
}
.page__foot a { color: var(--ink-3); text-decoration: none; transition: color 160ms var(--ease); }
.page__foot a:hover { color: var(--ink); }

/* ---- why this exists. The one block on the page that is not selling anything, so it gets
   a narrower measure and bigger type than the rest and otherwise stays out of the way. ---- */
/* Text and photographs side by side. The measure stays at 62ch whatever the column
   does, because that is what makes a long passage readable. */
.why {
  display: grid;
  grid-template-columns: minmax(0, 62ch) minmax(0, 300px);
  gap: 48px;
  align-items: start;
}
.why__text { max-width: 62ch; }

.why__shots { display: grid; gap: 18px; }
.shot { margin: 0; }
.shot img {
  width: 100%; height: auto; display: block;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
}
.shot figcaption {
  margin-top: 8px;
  font: 400 13px/1.5 var(--font-ui);
  color: var(--muted);
}

/* Below this the photographs would be squeezed into a gutter, so they go under the
   passage at full width instead. */
@media (max-width: 900px) {
  .why { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .why__shots { grid-template-columns: 1fr 1fr; align-items: start; }
}
@media (max-width: 560px) {
  .why__shots { grid-template-columns: 1fr; }
}
.why__h2 {
  margin: 10px 0 22px;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.75rem, 1.1rem + 2.4vw, 2.6rem);
  line-height: 1.12;
  letter-spacing: -.015em;
  color: var(--ink);
}
.why__body p {
  margin: 0 0 20px;
  font-family: var(--font-prose);
  font-size: 1.1rem;
  line-height: 1.68;
  color: var(--ink-2);
}
/* The last line is the point of the section, so it carries the page's own ink rather than
   the softer body colour. */
.why__body p:last-child { margin-bottom: 0; color: var(--ink); }
@media (max-width: 720px) {
  .why__body p { font-size: 1.02rem; }
}
