/* =========================================================================
   Rajesh Dora — prepress & plate room
   Creative idea: the page is seen at loupe distance. Everything is macro,
   nothing is wide. Square geometry throughout; one circle, once — the lens.
   Palette is sampled from the plate photography, not chosen from a mood.
   The hero holds while four words pass, because the argument is that you
   have to stay with something before you see it.
   ========================================================================= */

/* ---------- Faces ----------------------------------------------------- */
/* Self-hosted: no third-party request, no render-blocking external CSS.
   Archivo and IBM Plex Mono are both SIL Open Font Licence — see
   fonts/*-LICENSE.txt. */

@font-face {
  font-family: "Archivo";
  src: url("fonts/archivo-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}

@font-face {
  font-family: "Archivo";
  src: url("fonts/archivo-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("fonts/ibm-plex-mono-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}

/* ---------- Tokens ---------------------------------------------------- */

:root {
  /* Ground and ink — sampled from the hero photograph */
  --ground:        #0a0908;
  --ink:           #e7dfd2;
  --ink-muted:     #a89887;
  --ink-faint:     #8a7c6f;
  --amber:         #c0873f;
  --rule:          rgba(231, 223, 210, 0.11);

  /* Type */
  --font-sans: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --size-label:     0.6875rem;
  --size-body:      clamp(1.0313rem, 0.99rem + 0.2vw, 1.125rem);
  --size-statement: clamp(1.7rem, 1.28rem + 1.95vw, 3rem);
  --size-display:   clamp(2rem, 1.45rem + 2.3vw, 3.15rem);
  --size-word:      clamp(3.25rem, 15vw, 12.5rem);
  --size-beat-line: clamp(0.95rem, 0.85rem + 0.5vw, 1.25rem);
  --size-email:     clamp(1.25rem, 1rem + 1.15vw, 1.85rem);

  /* Rhythm */
  --gutter:  clamp(1.5rem, 1.05rem + 2.1vw, 3.5rem);
  --measure: 62ch;
  --section-y: clamp(5rem, 3.4rem + 7.4vw, 11rem);
  --spine: 11rem;
  --spine-gap: clamp(2rem, 0.9rem + 3.4vw, 4rem);
  --max: 1240px;

  /* Hero sequence — five words and the headline */
  --hero-scroll: 450vh;
  --p: 0;

  /* Motion */
  --ease: cubic-bezier(0.2, 0.6, 0.2, 1);
}

/* ---------- Base ------------------------------------------------------ */

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

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

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--size-body);
  font-weight: 400;
  line-height: 1.72;
  letter-spacing: 0.004em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

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

p { margin: 0 0 1.3em; }
p:last-child { margin-bottom: 0; }

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

:focus-visible { outline: 2px solid var(--amber); outline-offset: 4px; }

::selection { background: var(--amber); color: #0a0908; }

/* ---------- Utilities ------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.label {
  margin: 0 0 clamp(1.75rem, 1.4rem + 1.6vw, 2.75rem);
  font-family: var(--font-mono);
  font-size: var(--size-label);
  font-weight: 400;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

.skip-link {
  position: absolute;
  left: -9999px; top: 0; z-index: 20;
  padding: 0.75rem 1.25rem;
  background: var(--ink);
  color: var(--ground);
  font-family: var(--font-mono);
  font-size: var(--size-label);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.skip-link:focus { left: var(--gutter); top: 0.75rem; }

/* ---------- Masthead -------------------------------------------------- */
/* No navigation: one page, four movements. A nav bar here would be
   furniture, not wayfinding. */

/* The name holds for the whole page — there is no menu, so this is the only
   permanent mark of whose page it is. */
/* Only fixed when script can ink it over the paper passages — otherwise it
   scrolls away with the hero rather than sitting invisible on a light
   ground. */
.js .masthead { position: fixed; }

.masthead {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 5;
  padding-block: clamp(1.5rem, 1.1rem + 1.7vw, 2.5rem);
  pointer-events: none;
}

/* Section labels sit in the same top-left corner, so the fixed name carries
   a short fade of the current ground to pass over them cleanly. */
.js .masthead::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  z-index: -1;
  height: calc(100% + 1.75rem);
  background: linear-gradient(to bottom, var(--ground) 42%, rgba(10, 9, 8, 0));
  pointer-events: none;
}

/* Where it crosses a passage printed on paper, it inks over. */
.masthead--on-paper .masthead__name {
  color: #16120f;
}

.js .masthead--on-paper::before {
  background: linear-gradient(to bottom, #ebe8e1 42%, rgba(235, 232, 225, 0));
}

.masthead__name {
  margin: 0;
  text-align: right;
  transition: color 260ms var(--ease);
  font-family: var(--font-sans);
  font-size: clamp(1.15rem, 1.05rem + 0.35vw, 1.375rem);
  font-weight: 500;
  letter-spacing: -0.016em;
  color: var(--ink);
}

.masthead__name em { font-style: normal; color: var(--amber); }
.masthead--on-paper .masthead__name em { color: #875719; }

/* What the page is, for whoever has just landed on it. It holds while the
   hero is on screen and then retires, because by then the page has said it
   at full length and a fixed sentence over every photograph is furniture. */
.masthead__line {
  max-width: 44ch;
  margin: 0.3rem 0 0 auto;
  text-align: right;
  font-size: clamp(0.78rem, 0.74rem + 0.16vw, 0.875rem);
  line-height: 1.45;
  letter-spacing: 0;
  color: var(--ink-muted);
  text-wrap: pretty;
  transition: opacity 420ms var(--ease), color 260ms var(--ease);
}

.masthead--on-paper .masthead__line { color: #5f564c; }

.js .masthead--past-hero .masthead__line { opacity: 0; }

/* =========================================================================
   Hero
   Default (no JS, or reduced motion): an ordinary stacked sequence. The pin
   is added only when .hero-pinned is set on the root.
   ========================================================================= */

.hero { position: relative; }

.hero__stage {
  position: relative;
  min-height: 100svh;
  overflow: hidden;
  isolation: isolate;
}

.hero__media { position: absolute; inset: 0; z-index: -2; }

.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  /* The frame closes in across the whole sequence — the page argues that you
     see more by staying with something, so the photograph does the same. */
  transform: scale(calc(1 + var(--p) * 0.26));
  transform-origin: 42% 56%;
  will-change: transform;
}

/* Scrim: top-down on narrow screens, from the right on wide ones, plus a
   bottom fade at every size so the photograph dissolves into the page.
   It deepens as the sequence progresses — further in, darker room. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to bottom,
      rgba(10, 9, 8, 0.92) 0%,
      rgba(10, 9, 8, 0.78) 30%,
      rgba(10, 9, 8, 0.12) 58%),
    linear-gradient(to bottom,
      rgba(10, 9, 8, 0) 62%,
      rgba(10, 9, 8, 0.92) 96%,
      var(--ground) 100%);
}

/* The words stand where the photograph is brightest, so a flat veil carries
   them — and it deepens as the sequence runs: further in, darker room. */
.hero__scrim::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ground);
  opacity: 0.52;
}

.hero-pinned .hero__scrim::after {
  opacity: calc(0.36 + var(--p) * 0.26);
}

/* --- The four words --- */

.beats {
  margin: 0;
  padding: 0;
  list-style: none;
}

.beat {
  padding: clamp(4rem, 3rem + 6vw, 8rem) var(--gutter);
}

.beat__word {
  margin: 0 0 0.6rem;
  font-size: var(--size-word);
  font-weight: 500;
  line-height: 0.9;
  letter-spacing: -0.05em;
  color: var(--ink);
}

.beat__line {
  max-width: 40ch;
  margin: 0;
  font-size: var(--size-beat-line);
  line-height: 1.5;
  color: var(--ink-muted);
  text-wrap: balance;
}

/* --- The resolve: eyebrow and headline --- */

.hero__resolve {
  padding-block: clamp(4rem, 3rem + 6vw, 8rem);
}

.hero__eyebrow {
  margin: 0 0 clamp(1.1rem, 0.9rem + 0.9vw, 1.6rem);
  font-family: var(--font-mono);
  font-size: var(--size-label);
  font-weight: 400;
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--amber);
}

.hero__headline {
  margin: 0;
  font-size: var(--size-display);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.023em;
  text-wrap: pretty;
}

/* One emphasis language across the whole page: amber marks what to look at —
   the marks that head a passage, the dates, and the emphasised words inside a
   statement — and everything the reader is touching. */
.hero__headline em {
  font-style: normal;
  color: var(--amber);
}

/* --- Counter: only meaningful while the hero is pinned --- */

.hero__gauge { display: none; }

/* =========================================================================
   Hero — pinned
   ========================================================================= */

.hero-pinned .hero {
  height: var(--hero-scroll);
}

.hero-pinned .hero__stage {
  position: sticky;
  top: 0;
  height: 100svh;
  min-height: 0;
}

.hero-pinned .beats,
.hero-pinned .hero__resolve {
  position: absolute;
  inset: 0;
}

/* Opacity and transform are written by script from scroll position, so no
   CSS transition here — a transition on top of a scroll-linked value fights
   the scroll and reintroduces the lag it is meant to remove. */
.hero-pinned .beat {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-rows: 1fr auto;
  align-content: center;
  padding: clamp(6rem, 5rem + 5vw, 9rem) var(--gutter) clamp(2.5rem, 2rem + 2.5vw, 4rem);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  will-change: opacity;
}

.hero-pinned .beat__word {
  align-self: center;
  will-change: transform;
}

.hero-pinned .beat__line {
  justify-self: end;
  text-align: right;
  color: var(--ink);
  will-change: transform;
}

/* The headline sits low in the frame, where the one-liners have been all
   along — so the sequence resolves into the same place it has been speaking
   from. It also has to be the last thing to leave: the stage is sticky, and
   a centred headline scrolls off the top while half the stage is still
   passing, which left a near-empty screen before the plate arrived. */
.hero-pinned .hero__resolve {
  display: flex;
  align-items: flex-end;
  padding-block: 0 clamp(2.5rem, 1.6rem + 4.5vh, 6rem);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  will-change: opacity;
}

.hero-pinned .hero__resolve > .shell { width: 100%; }
.hero-pinned .hero__type { will-change: transform; }

/* A gauge, not a counter: the page measures things, so the hero says where
   you are with a scale rather than a number. */
.hero-pinned .hero__gauge {
  display: grid;
  gap: clamp(0.7rem, 0.6rem + 0.4vw, 1rem);
  position: absolute;
  right: clamp(1rem, 0.6rem + 1.4vw, 2rem);
  top: 50%;
  transform: translateY(-50%);
  transition: opacity 420ms var(--ease);
}

.hero-pinned .hero__gauge span {
  display: block;
  width: 14px;
  height: 1px;
  background: var(--ink);
  opacity: 0.3;
  transform-origin: right center;
  transition: width 480ms var(--ease), background-color 480ms var(--ease),
              opacity 480ms var(--ease);
}

.hero-pinned .hero__gauge span.is-on {
  width: 30px;
  background: var(--amber);
  opacity: 1;
}

.hero-pinned .hero.is-resolved .hero__gauge { opacity: 0; }

/* ---------- Sections -------------------------------------------------- */

.section { padding-block: var(--section-y); }

/* One section is printed on paper.
   The page is plates and ink in a dark room; this passage is the sheet
   itself, in daylight. The ground is sampled from the paper in the loupe
   photograph, so the circle melts into the page and only the dots and the
   barrel shadow remain. */
.section--paper {
  --ink:       #16120f;
  --ink-muted: #5f564c;
  --ink-faint: #6b6157;
  --amber:     #875719;
  --rule:      rgba(22, 18, 15, 0.16);

  color: var(--ink);
  padding-block: calc(var(--section-y) * 1.18);

  /* Two offset dot screens at very low contrast. This passage is the printed
     sheet, so it carries the texture of one — close enough to read as paper
     under ink, far from being a pattern for its own sake. */
  background-color: #ebe8e1;
  background-image:
    radial-gradient(circle at 1px 1px, rgba(22, 18, 15, 0.055) 1px, transparent 1.6px),
    radial-gradient(circle at 1px 1px, rgba(22, 18, 15, 0.035) 1px, transparent 1.6px);
  background-size: 9px 9px, 13px 13px;
  background-position: 0 0, 4px 6px;
}

/* Two passages on the same ground belong to one movement, so the seam
   between them closes up rather than opening a hole. */
.section:not(.section--paper) + .section:not(.section--paper) {
  padding-top: calc(var(--section-y) * 0.45);
}

/* Resolution, not another chapter: the closing section sits tighter. */
.section--close { padding-block: calc(var(--section-y) * 0.72); }
.section--paper.section--close { padding-block: calc(var(--section-y) * 0.95); }

.prose { max-width: var(--measure); color: var(--ink); }

/* The proposition. Given room and scale because it is the argument the
   whole page exists to make. */
.statement {
  max-width: 30ch;
  margin: clamp(3.5rem, 2.6rem + 3.8vw, 6.5rem) 0 0;
  font-size: var(--size-statement);
  font-weight: 400;
  line-height: 1.34;
  letter-spacing: -0.018em;
  text-wrap: pretty;
}

.statement em { font-style: normal; color: var(--amber); }

/* ---------- Interlude ------------------------------------------------- */
/* The plate at full height, with the one sentence that is about plate rooms
   set into the dark side of the frame — so the picture and the claim are the
   same object rather than two things stacked. It settles as it passes. */

.interlude {
  position: relative;
  margin: 0;
  min-height: 100svh;
  overflow: hidden;
  background: var(--ground);
  display: grid;
}

.interlude picture {
  position: absolute;
  inset: 0;
  display: block;
}

.interlude img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 38% 68%;
  transform: scale(1.09);
  will-change: transform;
}

/* Emerges from the dark above it rather than butting against it — but only
   just: a long fade here left a screen of nothing before the sentence. */
/* The image is transformed, which makes it paint above ordinary siblings —
   so the overlays are positioned to sit back on top of it. */
.interlude__scrim {
  grid-area: 1 / 1;
  position: relative;
  z-index: 1;
  background:
    linear-gradient(to bottom, var(--ground) 0%, rgba(10, 9, 8, 0) 11%),
    linear-gradient(to bottom, rgba(10, 9, 8, 0) 72%, rgba(10, 9, 8, 0.9) 97%, var(--ground) 100%),
    linear-gradient(to top, rgba(10, 9, 8, 0.72), rgba(10, 9, 8, 0.34));
}

.interlude__caption {
  grid-area: 1 / 1;
  position: relative;
  z-index: 2;
  align-self: end;
  width: 100%;
  padding-block: clamp(4rem, 3rem + 6vw, 7rem);
}

.interlude__caption .statement {
  max-width: 22ch;
  margin: 0;
  font-size: clamp(1.85rem, 1.35rem + 2.4vw, 3.4rem);
  line-height: 1.18;
  letter-spacing: -0.028em;
}

/* ---------- What I keep seeing ---------------------------------------- */
/* A vertical accordion, built on native <details> so it needs no script,
   works with a keyboard and stays open to search. Nothing is hidden: each
   headline carries the point on its own, and opening a row gives the whole
   observation. */

.seen { display: grid; gap: clamp(2.5rem, 1.8rem + 3vw, 4rem); }

.seam {
  border-top: 1px solid var(--rule);
}

.seam:last-of-type { border-bottom: 1px solid var(--rule); }

.seam summary {
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr) 1.25rem;
  align-items: baseline;
  gap: 0 1rem;
  padding-block: clamp(1.1rem, 0.9rem + 1vw, 1.75rem);
  cursor: pointer;
  list-style: none;
}

.seam summary::-webkit-details-marker { display: none; }

.seam summary:focus-visible {
  outline: 2px solid var(--amber);
  outline-offset: 4px;
}

.seam__mark {
  font-family: var(--font-mono);
  font-size: var(--size-label);
  letter-spacing: 0.19em;
  color: var(--ink-faint);
  transition: color 260ms var(--ease);
}

.seam__head {
  font-size: clamp(1.15rem, 0.95rem + 1vw, 1.85rem);
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-wrap: pretty;
}

/* A plus that becomes a minus — square, like everything but the lens. */
.seam__sign {
  position: relative;
  justify-self: end;
  align-self: center;
  width: 13px;
  height: 13px;
}

.seam__sign::before,
.seam__sign::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 1px;
  background: var(--ink-muted);
  transition: transform 320ms var(--ease), background-color 260ms var(--ease);
}

.seam__sign::after { transform: rotate(90deg); }

.seam[open] .seam__mark { color: var(--amber); }
.seam[open] .seam__sign::before,
.seam[open] .seam__sign::after { background: var(--amber); }
.seam[open] .seam__sign::after { transform: rotate(0deg); }

.seam__body {
  padding: 0 1.25rem clamp(1.5rem, 1.2rem + 1.2vw, 2.25rem) calc(3.25rem + 1rem);
  animation: seam-in 380ms var(--ease) both;
}

.seam__body p {
  max-width: 52ch;
  margin: 0;
  color: var(--ink-muted);
  text-wrap: pretty;
}

@keyframes seam-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

.seen__close {
  max-width: 30ch;
  margin: 0;
  font-size: var(--size-statement);
  line-height: 1.34;
  letter-spacing: -0.018em;
  color: var(--ink);
  text-wrap: pretty;
}

/* ---------- The lens -------------------------------------------------- */
/* The only circle on the page. Everything else is square. */

.lens {
  position: relative;
  width: clamp(220px, 56vw, 300px);
  margin: 0;
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
}

.lens img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(0.96);
}

/* Barrel edge — a hairline and a soft rim shadow, so the aperture reads as
   an instrument held over the sheet rather than a circular crop. */
.lens::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow:
    inset 0 0 0 1px rgba(22, 18, 15, 0.18),
    inset 0 0 26px 2px rgba(22, 18, 15, 0.16);
}

/* ---------- Bio: a record, not an article ----------------------------- */
/* Prose in a column read as a newspaper page. This is a dated record
   instead — mono markers, ruled rows, no padding words. The portrait holds
   still while the years pass beside it, which is the point: one person,
   one industry, thirty years. */

.bio { display: grid; gap: clamp(2.5rem, 2rem + 2.4vw, 3.5rem); }

.portrait {
  margin: 0;
  width: clamp(240px, 72vw, 340px);
}

.portrait img { width: 100%; height: auto; }

.record { margin: 0; }

.record__row {
  display: grid;
  gap: 0.25rem 1.5rem;
  padding-block: clamp(1.1rem, 0.9rem + 0.9vw, 1.6rem);
  border-top: 1px solid var(--rule);
}

.record__row:last-child { border-bottom: 1px solid var(--rule); }

.record dt {
  font-family: var(--font-mono);
  font-size: var(--size-label);
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--amber);
  padding-top: 0.4em;
}

.record dd {
  margin: 0;
  max-width: 52ch;
  color: var(--ink-muted);
  text-wrap: pretty;
}

.record__row:last-child dd { color: var(--ink); }

/* ---------- Where I start -------------------------------------------- */
/* A route, not an essay. Each stop is marked and set further in than the
   last, so the indent walks from the office to the floor. */

.route {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(2rem, 1.5rem + 2.2vw, 3.25rem);
}

.route__stop {
  border-left: 1px solid var(--rule);
  padding-left: clamp(1.25rem, 1rem + 1vw, 2rem);
}

.route__stop p:last-child {
  max-width: 44ch;
  margin: 0;
  color: var(--ink);
}

/* The route walks from the office to the floor, so the ground under it
   coarsens as it goes: a fine screen at the top resolving into a coarse one
   by the last stop. Two layers, each masked to its own end of the fade, so
   the change reads as one ramp and not as two patterns. */
.section--screen { position: relative; }

.section--screen::before,
.section--screen::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* The base tone: a fine screen across the whole passage, only just there. */
.section--screen::before {
  background-image: radial-gradient(circle at 1px 1px, rgba(231, 223, 210, 0.055) 1px, transparent 1.5px);
  background-size: 9px 9px;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
          mask-image: linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
}

/* The ramp: the plate from the interlude, screened. Not a photograph behind
   the text — a halftone of one, which is what a plate room would make of it.
   It builds from nothing at the first stop to its full weight at the last, so
   the ground gathers as the walk goes on, and it sits to the right of the
   measure where the route has already left the page empty. */
.section--screen::after {
  background-image: url("images/screen-plate.png");
  background-image: image-set(url("images/screen-plate.webp") type("image/webp"),
                              url("images/screen-plate.png")  type("image/png"));
  background-repeat: no-repeat;
  background-position: calc(100% + 620px) top;
  opacity: 0.1;
  -webkit-mask-image: linear-gradient(to bottom, transparent 6%, #000 74%, #000 86%, transparent);
          mask-image: linear-gradient(to bottom, transparent 6%, #000 74%, #000 86%, transparent);
}

/* The screen is ground, so the route sits on top of it. */
.section--screen > .shell { position: relative; z-index: 1; }

.route__mark {
  margin: 0 0 0.5rem;
  font-family: var(--font-mono);
  font-size: var(--size-label);
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--amber);
}

/* The walk ends on a finding, not on a summary. It returns to the left edge
   the route started from, and it is the largest type in the passage because
   it is the one thing a plate room owner is unlikely to have been told. */
.route__close {
  margin: clamp(3rem, 2.3rem + 3vw, 5rem) 0 0;
}

.route__claim {
  max-width: 17ch;
  margin: 0 0 clamp(1.5rem, 1.2rem + 1.4vw, 2.25rem);
  font-size: clamp(2.15rem, 1.4rem + 3.4vw, 4.15rem);
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.032em;
  text-wrap: pretty;
}

.route__claim em { font-style: normal; color: var(--amber); }

.route__gloss {
  max-width: 44ch;
  margin: 0;
  color: var(--ink-muted);
  text-wrap: pretty;
}

/* ---------- What you get ---------------------------------------------- */
/* Four things, side by side rather than stepped — this is a list of what
   lands on their desk, not another walk through the shop. */

.gets {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(2rem, 1.6rem + 1.8vw, 3rem);
}

.gets li { max-width: 42ch; }

/* These marks are whole phrases, not single-word tabs, so they are set as
   small headlines rather than in the tracked mono used elsewhere — five
   uppercase words at label size is work to read, and work is not attention.
   Amber, like every other mark on the page. */
.gets__mark {
  margin: 0 0 0.45rem;
  font-size: clamp(1.1rem, 1.03rem + 0.35vw, 1.3rem);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.014em;
  color: var(--amber);
}

.gets li p:last-child { margin: 0; color: var(--ink-muted); }

.gets__note {
  margin: clamp(2.5rem, 2rem + 2.2vw, 3.75rem) 0 0;
  padding-top: clamp(1.5rem, 1.2rem + 1.4vw, 2.25rem);
  border-top: 1px solid var(--rule);
  max-width: 34ch;
  font-size: var(--size-statement);
  line-height: 1.35;
  letter-spacing: -0.016em;
  text-wrap: pretty;
}

/* ---------- When this does not work ----------------------------------- */
/* Subtraction, so it is set quieter than anything it sits between. */

.unfit {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: 52ch;
  color: var(--ink-muted);
}

.unfit li {
  padding-block: clamp(1rem, 0.85rem + 0.7vw, 1.4rem);
  border-top: 1px solid var(--rule);
}

.unfit li:last-child { border-bottom: 1px solid var(--rule); }

/* ---------- Checks ---------------------------------------------------- */
/* A numbered record rather than a ruled table, so it reads differently from
   "Where it sits" a screen earlier. */

.measure__intro { margin-bottom: clamp(2.5rem, 2rem + 2.4vw, 4rem); }

.checks {
  counter-reset: check;
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(1.1rem, 0.9rem + 0.8vw, 1.6rem);
}

.checks li {
  counter-increment: check;
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr);
  align-items: baseline;
  max-width: 46ch;
}

.checks li::before {
  content: counter(check, decimal-leading-zero);
  font-family: var(--font-mono);
  font-size: var(--size-label);
  letter-spacing: 0.19em;
  color: var(--ink-faint);
}

.checks__prompt { color: var(--ink-muted); }

/* Square, like everything else that is not the lens. */
.check {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.85rem;
  align-items: baseline;
  cursor: pointer;
}

.check input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.check__box {
  width: 0.85em;
  height: 0.85em;
  translate: 0 0.06em;
  border: 1px solid currentColor;
  opacity: 0.45;
  transition: background-color 200ms var(--ease), opacity 200ms var(--ease),
              border-color 200ms var(--ease);
}

.check:hover .check__box { opacity: 0.75; }

.check input:checked + .check__box {
  background: var(--amber);
  border-color: var(--amber);
  opacity: 1;
}

.check input:focus-visible + .check__box {
  outline: 2px solid var(--amber);
  outline-offset: 3px;
  opacity: 1;
}

/* What the ticking is for: the page counts, and says nothing else. */
/* The score is the size of a section closer; the reason it gives is set at
   reading size, so the two do not compete and the eye lands on the count. */
.readout {
  max-width: 46ch;
  margin: clamp(2.25rem, 1.8rem + 2vw, 3.25rem) 0 0;
}

.readout__head {
  display: block;
  font-size: var(--size-statement);
  line-height: 1.24;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-wrap: pretty;
}

.readout__note {
  display: block;
  margin-top: clamp(0.7rem, 0.6rem + 0.4vw, 1rem);
  color: var(--ink-muted);
  text-wrap: pretty;
}

.readout__count { color: var(--ink); }
.readout__verdict { color: var(--amber); }

/* ---------- Close ----------------------------------------------------- */
/* The four words come back small, then the page asks one question and
   stops. No offer, no button — the address is the whole invitation. */

/* The five words return inside the sentence rather than as a row of labels,
   so their purpose is grammatical and nobody has to guess at it. */
.close__list { color: var(--ink-muted); }

.close__ask {
  max-width: 26ch;
  margin: 0 0 clamp(2.25rem, 1.8rem + 2vw, 3.5rem);
  font-size: var(--size-statement);
  font-weight: 400;
  line-height: 1.28;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-wrap: pretty;
}

.close__next {
  max-width: 46ch;
  margin: 0 0 clamp(2.25rem, 1.8rem + 2vw, 3.25rem);
  color: var(--ink-muted);
}

/* The last hesitation before writing is who else will hear about it. */
.close__trust { color: var(--ink); }

/* ---------- Contact --------------------------------------------------- */

.contact__email {
  display: inline-block;
  font-size: var(--size-email);
  font-weight: 400;
  letter-spacing: -0.014em;
  line-height: 1.3;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 0.18em;
  transition: border-color 340ms var(--ease), color 340ms var(--ease);
}

.contact__email:hover,
.contact__email:focus-visible {
  color: var(--amber);
  border-bottom-color: var(--amber);
}

.contact__where {
  margin: clamp(1.4rem, 1.1rem + 1.2vw, 2rem) 0 0;
  font-family: var(--font-mono);
  font-size: var(--size-label);
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ---------- Footer ---------------------------------------------------- */
/* The whole page is built as a record — dated rows, ruled lists, a
   checklist. Records get signed at the bottom. So the name is large, but it
   is a signature closing a document rather than a wordmark, and it draws
   itself left to right as you arrive. */

.footer {
  border-top: 1px solid var(--rule);
  padding-block: clamp(3rem, 2.2rem + 3.4vw, 5.5rem) clamp(2rem, 1.6rem + 1.8vw, 3rem);
}

/* Set as SVG so it is exactly flush to both margins at every width — type
   that is nearly full width reads as a mistake; type that is precisely full
   width reads as a decision. */
.signature {
  margin: 0 0 clamp(1.5rem, 1.2rem + 1.4vw, 2.5rem);
}

.signature__mark {
  display: block;
  width: 100%;
  height: auto;
}

.signature__mark text {
  font-family: var(--font-sans);
  font-size: 100px;
  font-weight: 500;
  fill: var(--ink);
}

.signature__mark tspan { fill: var(--amber); }

.footer__base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem 2rem;
  padding-top: clamp(1.5rem, 1.2rem + 1.2vw, 2.25rem);
  border-top: 1px solid var(--rule);
}

.footer__note {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--size-label);
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* Marks, not badges: drawn in one hairline weight so they sit with the rules
   and the type rather than importing three brands' colour and mass. */
.social {
  display: flex;
  gap: 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.social a {
  display: block;
  color: var(--ink-faint);
  transition: color 260ms var(--ease);
}

.social a:hover,
.social a:focus-visible { color: var(--amber); }

.social svg {
  width: 20px;
  height: 20px;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.colophon {
  margin: clamp(2rem, 1.6rem + 1.8vw, 3rem) 0 0;
  font-family: var(--font-mono);
  font-size: var(--size-label);
  letter-spacing: 0.19em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.colophon a {
  border-bottom: 1px solid var(--rule);
  padding-bottom: 0.2em;
  transition: color 260ms var(--ease), border-color 260ms var(--ease);
}

.colophon a:hover,
.colophon a:focus-visible {
  color: var(--amber);
  border-bottom-color: var(--amber);
}

/* ---------- Reveal ---------------------------------------------------- */
/* A handful of blocks, not everything. Movement marks the arrival of a new
   thought, so only whole thoughts move. Scoped to .js so the page is fully
   legible without JavaScript. */

.js .reveal { opacity: 0; transform: translateY(12px); }

/* The clip sits on an inner span, not on the observed element — clipping the
   observed box to zero area stops it ever intersecting, so it would never
   un-clip itself. */
.js .signature.reveal { opacity: 1; transform: none; }

.js .signature.reveal .signature__mark {
  display: inline-block;
  clip-path: inset(0 100% 0 0);
}

.js .signature.reveal.is-in .signature__mark {
  clip-path: inset(0 0 0 0);
  transition: clip-path 1200ms var(--ease);
}

.js .reveal.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 820ms var(--ease), transform 820ms var(--ease);
}

/* =========================================================================
   Breakpoints — each size is composed, not inherited
   ========================================================================= */

/* Narrow screens: the counter and the line both live along the bottom edge,
   so the line is lifted clear of it rather than sharing its baseline. */
@media (max-width: 719px) {
  .hero-pinned .beat { padding-bottom: 5.75rem; }
  .hero-pinned .beat__line { text-align: left; justify-self: start; }
}

@media (min-width: 480px) {
  .lens { width: clamp(240px, 50vw, 320px); }
}

/* Tablet portrait and up: the hero photograph switches to landscape, so the
   scrim comes from the right and the resolve headline sits in that darkness. */
@media (min-width: 720px) {
  :root { --hero-scroll: 540vh; }

  .hero__scrim {
    background:
      linear-gradient(to left,
        rgba(10, 9, 8, 0.9) 0%,
        rgba(10, 9, 8, 0.62) 36%,
        rgba(10, 9, 8, 0.12) 68%,
        rgba(10, 9, 8, 0) 88%),
      linear-gradient(to bottom,
        rgba(10, 9, 8, 0) 66%,
        rgba(10, 9, 8, 0.85) 94%,
        var(--ground) 100%);
  }

  .hero__media img { object-position: 46% 50%; }

  .hero__resolve .hero__type { width: min(58%, 620px); margin-left: auto; }

  .hero-pinned .beat {
    padding-inline: max(var(--gutter), calc((100% - var(--max)) / 2 + var(--gutter)));
  }


  /* Portrait first and held still; the years run past it. */
  .bio {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
    column-gap: clamp(2.5rem, 1.2rem + 4.4vw, 4.5rem);
  }

  .portrait {
    position: sticky;
    top: clamp(5rem, 4rem + 4vw, 7rem);
    width: clamp(240px, 28vw, 360px);
  }

  .record__row { grid-template-columns: 6.5rem minmax(0, 1fr); }

  .interlude__caption .statement { max-width: 24ch; }
  .lens { width: clamp(200px, 24vw, 300px); }
}

/* Wide enough to place things rather than stack them. */
@media (min-width: 900px) {
  .seen {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "rows lens"
      "close close";
    column-gap: clamp(2.5rem, 1.2rem + 4.4vw, 5rem);
    row-gap: clamp(3rem, 2rem + 3.2vw, 5rem);
    align-items: start;
  }

  .seam__set { grid-area: rows; }
  .seen .lens { grid-area: lens; position: sticky; top: clamp(5rem, 4rem + 4vw, 7rem); }
  .seen__close { grid-area: close; }

  /* Each stop sits further in than the last, and its rule steps with it —
     the indent draws the walk from the office to the floor. */
  .route__stop:nth-child(2) { margin-left: 5%; }
  .route__stop:nth-child(3) { margin-left: 10%; }
  .route__stop:nth-child(4) { margin-left: 15%; }
  .route__stop:nth-child(5) { margin-left: 20%; }

  /* More room, so the screen opens up. */
  .section--screen::before { background-size: 10px 10px; }
}

/* Laptop and up: an editorial spine. Labels sit in their own column so the
   page reads as a set of marked passages rather than a stack of blocks. */
@media (min-width: 1024px) {
  .section > .shell {
    display: grid;
    grid-template-columns: var(--spine) minmax(0, 1fr);
    column-gap: var(--spine-gap);
    align-items: start;
  }

  .section > .shell > .label {
    grid-column: 1;
    grid-row: 1;
    margin-bottom: 0;
    padding-top: 0.55rem;
  }

  .section > .shell > *:not(.label) { grid-column: 2; }

  /* These two break the spine and take the full measure of the page. */
  .seen,
  .route { grid-column: 1 / -1; }

  /* Four short items read as a set when they are paired, not as a queue. */
  .gets {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--spine-gap);
  }

  /* The measure clears the right margin here, so the screen can come in —
     but only as far as the text. The dots stay off the reading line. */
  .section--screen::after {
    background-position: calc(100% + 260px) top;
    opacity: 0.15;
  }

  .statement { max-width: 26ch; }
}

@media (min-width: 1440px) {
  /* Wide enough that the screen can sit fully in the margin. */
  .section--screen::after { background-position: calc(100% + 90px) top; }
}

@media (min-width: 1600px) {
  :root { --max: 1360px; --spine: 13rem; }
}

/* ---------- Reduced motion ------------------------------------------- */
/* The pin is removed in script as well, so the sequence becomes four
   ordinary blocks with the same words in the same order. */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .seam__body { animation: none; }

  .js .reveal,
  /* The clip sits on an inner span, not on the observed element — clipping the
   observed box to zero area stops it ever intersecting, so it would never
   un-clip itself. */
.js .signature.reveal { opacity: 1; transform: none; }

.js .signature.reveal .signature__mark {
  display: inline-block;
  clip-path: inset(0 100% 0 0);
}

.js .signature.reveal.is-in .signature__mark {
  clip-path: inset(0 0 0 0);
  transition: clip-path 1200ms var(--ease);
}

.js .reveal.is-in {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .hero__media img,
  .interlude img { transform: none; }

  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
