/* Purpose: the chapters. Each one is art directed on its own terms - its own
   ground colour, its own spatial system, its own interaction idea.

   Scroll-driven chapters expose a single progress custom property (--p, 0 to 1)
   that JavaScript writes and CSS consumes. With no JavaScript, or under reduced
   motion, each chapter falls back to its finished composition. */

/* ===============================================================
   01 · THE DOOR
   Ground: obsidian. The hero is a built architectural entrance -
   wall, architrave, two panelled leaves with thickness, brass
   hardware, warm interior light. No photograph.

   --open  0..1  how far the leaves have swung
   --push  0..1  how far the camera has advanced through
   =============================================================== */

.door {
  --p: 0;
  --open: 0;
  --push: 0;
  /* The lock rail's centre line. The engraving and the handles both hang off
     this, so they read as one row of hardware at every width. */
  --rail: 43%;

  /* Timber. Grain is mostly dark lines of varying weight on lighter ground,
     so these are ramped rather than hard-stopped - a hard stop gives a crisp
     pinstripe, an interpolated stop gives a soft fibre. Periods 11 / 19 / 31px
     are co-prime, so the beat never visibly repeats across the leaf; even
     spacing reads as corduroy. Last layer is the slow cathedral figure a real
     board has across its width. Held at the noise floor throughout. */
  --grain:
    repeating-linear-gradient(90deg,
      transparent 0, rgba(0, 0, 0, 0.06) 4px, transparent 6px, transparent 11px),
    repeating-linear-gradient(90deg,
      transparent 0, rgba(0, 0, 0, 0.045) 9px, transparent 12px, transparent 19px),
    repeating-linear-gradient(90deg,
      transparent 0, rgba(0, 0, 0, 0.033) 15px, transparent 20px, transparent 31px),
    repeating-linear-gradient(90deg,
      transparent 0, rgba(232, 200, 137, 0.007) 12px, transparent 15px, transparent 23px),
    linear-gradient(90deg,
      rgba(0, 0, 0, 0.08) 0%, transparent 18%, rgba(255, 255, 255, 0.008) 41%,
      transparent 63%, rgba(0, 0, 0, 0.065) 86%, transparent 100%);

  position: relative;
  background: var(--c-obsidian);
}


.door__track { position: relative; height: 280svh; }

.door__viewport {
  position: sticky;
  top: 0;
  /* Exactly one screen, on every device, including mobile browser chrome. */
  height: 100svh;
  max-height: 100svh;
  overflow: clip;
  display: grid;
  place-items: center;
}

/* Everything in the doorway resolves to the page ground before the sticky
   viewport ends, so the chapter hands over with no visible edge. */
.door__falloff {
  position: absolute;
  inset: auto 0 0;
  height: 34%;
  /* Sits above the door hardware but beneath the sill, so the lede, the
     countdown and the invitation are never veiled by it. */
  z-index: var(--z-object);
  background: linear-gradient(180deg, transparent 0%, var(--c-obsidian) 78%);
  pointer-events: none;
}

.door__stage {
  position: absolute;
  inset: 0;
  perspective: 1600px;
  perspective-origin: 50% 44%;
  /* Flat, deliberately: the leaves still rotate in this perspective, but the
     backdrop can no longer intersect them in depth and slice them in half. */
  transform-style: flat;
}

/* ---------------------------------------------------------------
   The interior: a deep room described only with light.
   --------------------------------------------------------------- */

.door__interior {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, #0A0B0E 0%, #12100C 42%, #0A0B0D 68%, var(--c-obsidian) 84%, var(--c-obsidian) 100%);
  transform: scale(calc(1.04 + var(--push) * 0.3));
}

.door__glow {
  position: absolute;
  inset: 0;
  /* Held at 60% of its old strength: the room is lit, not floodlit. */
  background:
    radial-gradient(46% 54% at 50% 44%, rgba(232, 200, 137, calc(0.048 + var(--open) * 0.156)), transparent 72%),
    radial-gradient(70% 30% at 50% 88%, rgba(198, 151, 73, calc(0.024 + var(--open) * 0.036)), transparent 72%),
    linear-gradient(180deg, transparent 62%, var(--c-obsidian) 96%);
}

/* The landing state: the seam breathes, so the first frame is alive rather
   than a flat black rectangle. Stops the moment the visitor starts scrolling. */
.door__breathe {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 34vw;
  transform: translateX(-50%);
  pointer-events: none;
  /* Round, and sized against the width so it stays round. The old radii were
     percentages of this box - 38% of 34vw against 46% of the full height -
     which on a phone is a 50 x 388px splinter, and that splinter is the
     vertical streak that read as an ellipse down the middle of the hero. */
  background: radial-gradient(circle 15vw at 50% 44%,
    rgba(232, 200, 137, 0.15) 0%,
    rgba(232, 200, 137, 0.07) 46%,
    transparent 100%);
  /* The pulse is carried by filter, not opacity. A keyframe that sets opacity
     outright overrides this declaration, so the fade-out below never ran and
     the glow stayed lit through the whole chapter instead of handing over to
     the room. filter multiplies with it, so both survive. */
  opacity: clamp(0, calc(1 - var(--open) * 2), 1);
  animation: cdm-breathe 5200ms var(--ease-editorial) infinite;
}

@keyframes cdm-breathe {
  0%, 100% { filter: opacity(0.5); transform: translateX(-50%) scale(0.96); }
  50%      { filter: opacity(1);   transform: translateX(-50%) scale(1.04); }
}

/* Two motes of dust drifting in the seam light, before any scroll. */
.door__mote {
  position: absolute;
  width: 3px;
  height: 3px;
  border-radius: var(--r-full);
  background: rgba(232, 200, 137, 0.7);
  filter: blur(0.5px);
  opacity: calc(1 - var(--open) * 2);
}

.door__mote--1 { left: 47%; top: 62%; animation: cdm-drift 9000ms linear infinite; }
.door__mote--2 { left: 53%; top: 78%; animation: cdm-drift 12000ms linear infinite 2400ms; }

@keyframes cdm-drift {
  0% { transform: translateY(0) translateX(0); opacity: 0; }
  15% { opacity: 0.7; }
  85% { opacity: 0.4; }
  100% { transform: translateY(-46svh) translateX(14px); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .door__breathe, .door__mote { animation: none; }
}

/* The light through the gap. Present from the first frame as a leak. */
.door__light {
  position: absolute;
  top: 4%;
  bottom: 4%;
  left: 50%;
  width: calc(2px + var(--open) * 7vw);
  transform: translateX(-50%);
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(232, 200, 137, 0.2) 26%,
    rgba(255, 246, 214, 0.34) 50%,
    rgba(232, 200, 137, 0.2) 74%,
    transparent 100%);
  filter: blur(calc(4px + var(--open) * 7px));
  /* Strongest as a leak; hands over to the room glow once the leaves part. */
  opacity: clamp(0, calc(1.15 - var(--open) * 1.35), 1);
}

/* ---------------------------------------------------------------
   The leaves. Each has a face and an edge; the edge becomes visible
   as the leaf swings away, which is what sells the thickness.
   --------------------------------------------------------------- */

.door__leaf {
  position: absolute;
  top: 0;
  bottom: 0;
  /* Exactly half each: the two meeting stiles then sit flush and symmetric
     on the centre line, instead of overlapping and reading off to one side. */
  width: 50%;
  z-index: var(--z-object);
  transform-style: preserve-3d;
  will-change: transform;
}

.door__leaf--l {
  left: 0;
  transform-origin: left center;
  transform: translateZ(calc(var(--push) * 300px)) rotateY(calc(var(--open) * 62deg));
}

.door__leaf--r {
  right: 0;
  transform-origin: right center;
  transform: translateZ(calc(var(--push) * 300px)) rotateY(calc(var(--open) * -62deg));
}

.door__face {
  position: absolute;
  inset: 0;
  background:
    /* one broad sheen across the lacquer */
    linear-gradient(104deg, rgba(255, 255, 255, 0.03) 0%, transparent 26%, transparent 58%, rgba(255, 255, 255, 0.02) 74%, transparent 100%),
    var(--grain),
    linear-gradient(90deg, rgba(0, 0, 0, 0.5), transparent 16%, transparent 84%, rgba(0, 0, 0, 0.42)),
    linear-gradient(172deg, #16181D 0%, #101216 44%, #13151A 78%, #0C0E12 100%);
  box-shadow:
    inset 0 1px 0 rgba(232, 200, 137, 0.07),
    inset 0 -1px 0 rgba(0, 0, 0, 0.8),
    inset 0 0 110px rgba(0, 0, 0, 0.7);
  backface-visibility: hidden;
}

/* The meeting stiles: a brass edge either side of the seam. Brightens as the
   interior light lands on it, which is what reads as thickness. */
.door__leaf--l .door__face::before,
.door__leaf--r .door__face::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: calc(3px + var(--open) * 6px);
  background: linear-gradient(180deg, #72552A, #C69749 26%, #F4E3B8 50%, #C69749 74%, #72552A);
  opacity: calc(0.55 + var(--open) * 0.45);
  box-shadow: 0 0 calc(var(--open) * 24px) rgba(232, 200, 137, calc(var(--open) * 0.5));
}

.door__leaf--l .door__face::before { right: 0; }
.door__leaf--r .door__face::before { left: 0; }

/* A door turning into a lit room catches that light. The inner face rakes
   from bright at the leading edge to dark at the hinge, and the whole leaf
   lifts out of black as it swings - which is what makes the movement legible. */
.door__face::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: var(--open);
  mix-blend-mode: screen;
}

.door__leaf--l .door__face::after {
  background: linear-gradient(270deg,
    rgba(255, 236, 194, 0.3) 0%,
    rgba(232, 200, 137, 0.12) 12%,
    rgba(198, 151, 73, 0.04) 32%,
    transparent 56%);
}

.door__leaf--r .door__face::after {
  background: linear-gradient(90deg,
    rgba(255, 236, 194, 0.3) 0%,
    rgba(232, 200, 137, 0.12) 12%,
    rgba(198, 151, 73, 0.04) 32%,
    transparent 56%);
}

/* The idle cue. Until the visitor moves, the door eases off its latch and
   settles back, and the seam catches the light as it does. It answers the one
   question a still door leaves open - does this open? - in the door's own
   language, with no arrow anywhere on the page.

   1.5 degrees is deliberately small. The leaf's bounding box barely changes at
   that angle, but the box is not what reads: the face shading, the widening
   seam and the handles shifting are, and on a wide desktop leaf the inner edge
   still travels several pixels under perspective. Runs only at rest, where
   --open is 0, so the keyframe can own the transform outright; the class is
   dropped for good on the first scroll. */
.door.is-idle .door__leaf--l { animation: cdm-nudge-l 3400ms var(--ease-door) infinite; }
.door.is-idle .door__leaf--r { animation: cdm-nudge-r 3400ms var(--ease-door) infinite; }
.door.is-idle .door__face::before { animation: cdm-nudge-seam 3400ms var(--ease-door) infinite; }

/* The stage is transform-style: flat - it has to be, or the interior backdrop
   depth-sorts through the leaves - so a leaf gets no perspective from its
   parent and its projected width falls off as (1 - cos t): 0.1px at 1.5deg.
   The perspective() function inside the leaf's own transform restores the
   foreshortening without asking the stage for preserve-3d. Angle is set per
   breakpoint because the leaves are 195px wide on a phone and 720px on a
   desktop, and the same angle does not read the same on both. */
.door { --nudge: 7deg; }

@media (min-width: 900px) { .door { --nudge: 1.6deg; } }

@keyframes cdm-nudge-l {
  0%, 62%, 100% { transform: perspective(760px) rotateY(0deg); filter: brightness(1); }
  28%           { transform: perspective(760px) rotateY(var(--nudge)); filter: brightness(1.1); }
}

@keyframes cdm-nudge-r {
  0%, 62%, 100% { transform: perspective(760px) rotateY(0deg); filter: brightness(1); }
  28%           { transform: perspective(760px) rotateY(calc(-1 * var(--nudge))); filter: brightness(1.1); }
}

@keyframes cdm-nudge-seam {
  0%, 62%, 100% { opacity: 0.55; box-shadow: 0 0 0 rgba(232, 200, 137, 0); }
  28%           { opacity: 1; box-shadow: 0 0 20px rgba(232, 200, 137, 0.45); }
}

/* The leaf itself brightens as it turns, then falls back as it passes the camera. */
.door__leaf {
  filter: brightness(calc(1 + var(--open) * 0.28 - var(--push) * 0.35));
}

/* Recessed panels. */
.door__panel {
  position: absolute;
  inset-inline: 13%;
  border-radius: 1px;
  /* Cut from the same board as the face. */
  background:
    var(--grain),
    linear-gradient(176deg, #0A0C0F 0%, #0E1014 52%, #090B0E 100%);
  /* The moulding: shadow on the top lip, a fine lit edge on the bottom. */
  box-shadow:
    inset 0 3px 6px rgba(0, 0, 0, 0.85),
    inset 0 -1px 0 rgba(232, 200, 137, calc(0.1 + var(--open) * 0.3)),
    inset 2px 0 4px rgba(0, 0, 0, 0.55),
    inset -2px 0 4px rgba(0, 0, 0, 0.55),
    0 1px 0 rgba(232, 200, 137, calc(0.06 + var(--open) * 0.2));
}

.door__panel::after {
  content: "";
  position: absolute;
  inset: var(--space-8);
  border: 1px solid rgba(198, 151, 73, 0.08);
  border-top-color: rgba(0, 0, 0, 0.6);
  border-radius: 1px;
}

/* Real panelled-door proportions: narrow head rail, a deep lock rail below
   centre wide enough to carry the engraving clear of both panels, and the
   tall panel underneath. */
.door__panel--upper { top: 6%; height: 30%; }
.door__panel--lower { top: 50%; height: 40%; }

/* CLOSED and DOOR, engraved into the leaves. They travel with the swing and
   yield to the lockup the light reveals. */
.door__leafword {
  position: absolute;
  /* Centre of the lock rail, so the engraving clears both panels. */
  top: var(--rail);
  transform: translateY(-50%);
  text-align: center;
  font-family: var(--font-display);
  font-variation-settings: 'wdth' var(--wdth-condensed), 'wght' var(--wght-black);
  font-size: clamp(var(--fs-40), 7vw, var(--fs-96));
  line-height: 1;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  /* Carved: a shade lighter than the lacquer, shadowed into the cut. */
  color: #23272E;
  text-shadow:
    0 -2px 2px rgba(0, 0, 0, 0.9),
    0 1px 0 rgba(198, 151, 73, 0.22),
    0 2px 6px rgba(0, 0, 0, 0.5);
  opacity: clamp(0, calc(1 - var(--open) * 1.7), 1);
  white-space: nowrap;
}

/* Symmetric insets so each word sits on the true horizontal centre of its own
   leaf: the box is centred, and text-align does the rest. */
.door__leafword--l,
.door__leafword--r { left: 6%; right: 6%; }

/* A single thread of gold travels through the engraving - a slow ghost of
   light moving letter to letter, left leaf through to right. The letters are
   filled by a moving gradient clipped to the type; the shadow underneath keeps
   them cut into the lacquer. */
.door__leafword {
  background-image: linear-gradient(
    104deg,
    #23272E 0%,
    #23272E 34%,
    #5E4A22 41%,
    #C69749 46%,
    #F2E0B4 50%,
    #C69749 54%,
    #5E4A22 59%,
    #23272E 66%,
    #23272E 100%
  );
  background-size: 320% 100%;
  background-position: 150% 50%;
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: cdm-thread 7200ms linear infinite;
}

.door__leafword--r { animation-delay: -2400ms; }

.door__glyph { display: inline-block; color: transparent; }

@keyframes cdm-thread {
  from { background-position: 160% 50%; }
  to { background-position: -60% 50%; }
}

/* The thread belongs to the closed door; it stops as the leaves begin to move. */
.door.is-open .door__leafword { animation: none; }

@media (prefers-reduced-motion: reduce) {
  .door__leafword {
    animation: none;
    background-image: none;
    color: #23272E;
  }
  .door__glyph { color: inherit; }
}

/* Brass hardware: a single quiet handle per leaf. */
.door__handle {
  position: absolute;
  /* On the engraving's line, not the leaf's. */
  top: var(--rail);
  width: 8px;
  /* Capped against the viewport so a short screen keeps the handle inside the
     lock rail instead of letting it run over the panel edges. */
  height: min(var(--space-80), 11svh);
  transform: translateY(-50%);
  border-radius: var(--r-full);
  background: linear-gradient(90deg, #6E5322 0%, #C69749 34%, #F0DCA6 52%, #B78B41 70%, #5A431E 100%);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.85), inset 0 1px 0 rgba(255, 240, 200, 0.6);
}

/* The rose the handle is mounted on. */
.door__handle::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--space-16);
  /* Tracks the handle rather than a fixed length. */
  height: calc(100% + var(--space-8));
  transform: translate(-50%, -50%);
  border-radius: var(--r-full);
  background: linear-gradient(180deg, rgba(198, 151, 73, 0.16), rgba(114, 85, 42, 0.1));
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.6);
  z-index: -1;
}

.door__leaf--l .door__handle { right: 3.5%; }
.door__leaf--r .door__handle { left: 3.5%; }




/* ---------------------------------------------------------------
   Typography across the planes.
   --------------------------------------------------------------- */

.door__type {
  position: absolute;
  left: 50%;
  top: 40%;
  transform: translate(-50%, -50%) scale(calc(0.92 + var(--open) * 0.08));
  /* No fade: the lockup is always lit behind the doorway, and the leaves
     swinging away are what reveal it. */
  z-index: var(--z-base);
  width: min(calc(100% - (2 * var(--container-pad))), var(--container-wide));
  text-align: center;
  transform-style: preserve-3d;
  pointer-events: none;
}

.door__eyebrow {
  color: var(--c-brass);
  margin-bottom: var(--space-16);
}

.door__title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(var(--fs-56), 11vw, var(--fs-160));
  line-height: var(--lh-crush);
  letter-spacing: var(--tracking-display);
  text-transform: uppercase;
  transform-style: preserve-3d;
}

.door__word {
  display: block;
  font-variation-settings: 'wdth' var(--wdth-condensed), 'wght' var(--wght-black);
  color: var(--c-white);
  text-shadow: 0 var(--space-8) var(--space-40) rgba(0, 0, 0, 0.8);
  will-change: transform, opacity;
}

/* Once the leaves reveal it, the lockup holds its place and its strength for
   the rest of the chapter. Nothing about it dissolves on further scroll. */
.door__word--1,
.door__word--2 { transform: none; opacity: 1; }

/* MARKETING: the third line of the lockup, letterspaced brass. */
.door__word--3 {
  font-variation-settings: 'wdth' var(--wdth-wide), 'wght' 500;
  font-size: 0.26em;
  letter-spacing: 0.44em;
  text-indent: 0.44em;
  color: var(--c-brass);
  margin-top: var(--space-16);
  opacity: 1;
}

/* ---------------------------------------------------------------
   The sill bar: lede, countdown, invitation.
   --------------------------------------------------------------- */

/* Set on a phone only, and only once the door's gesture has had five seconds
   to do the job on its own: the word, with a hairline running down out of it.
   Sits directly above the sill so it never fouls the invitation. */
.door__cue {
  display: none;
  position: absolute;
  /* Centred on the seam. The two leaves meet on that line and the light runs
     down it, so the cue and the thing it is pointing at share an axis. */
  left: 50%;
  transform: translateX(-50%);
  bottom: clamp(var(--space-20), 4svh, var(--space-48));
  text-align: center;
  z-index: calc(var(--z-object) + 2);
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  /* With the sill now behind the leaves, the foot of the screen is solid
     lacquer, so the cue has to carry its own contrast: lit brass with a
     little bloom, over a soft pool that separates it from the grain. */
  color: var(--c-brass-hi);
  text-shadow: 0 0 14px rgba(232, 200, 137, 0.4), 0 1px 2px rgba(0, 0, 0, 0.9);
  opacity: 0;
  pointer-events: none;
}

@media (max-width: 899px) {
  .door.is-cue .door__cue { display: block; animation: cdm-cue-in 2800ms var(--ease-editorial) infinite; }
}

/* The hairline drops out of the word and fades, which is the instruction.
   Centred under the word rather than hung off its right edge, which read as
   a stray mark rather than a line coming out of the type. */
.door__cue span { position: relative; display: block; padding-bottom: var(--space-20); }

.door__cue span::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: calc(100% - var(--space-16));
  width: 1px;
  height: var(--space-16);
  background: linear-gradient(180deg, var(--c-brass-hi), transparent);
}

@keyframes cdm-cue-in {
  0%, 100% { opacity: 0; }
  22%, 62% { opacity: 0.85; }
}

.door__sill {
  position: absolute;
  left: 0;
  right: 0;
  /* Always clear of the bottom edge, at any viewport height. */
  bottom: clamp(var(--space-20), 4svh, var(--space-48));
  z-index: calc(var(--z-object) + 1);
  padding: var(--space-20) 0 0;
  opacity: 1;
}

.door__sill-inner {
  width: min(calc(100% - (2 * var(--container-pad))), var(--container-wide));
  margin-inline: auto;
  display: grid;
  gap: var(--space-20);
  align-items: end;
}

@media (min-width: 900px) {
  .door__sill-inner { grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-48); }
}

/* Names the room before anything else is read. Mono and small, so it reads as
   a filing note rather than a second headline. Kept at every width - it is the
   only place a phone is told what the room actually is. */
.door__note {
  margin: 0 0 var(--space-8);
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  color: var(--c-brass-hi);
}

.door__lede {
  max-width: 44ch;
  margin: 0;
  font-size: var(--step-lead);
  line-height: 1.34;
  color: var(--c-white);
}

.door__support {
  margin: var(--space-8) 0 0;
  max-width: 52ch;
  font-size: var(--fs-16);
  opacity: 0.7;
}

.door__actions {
  display: grid;
  gap: var(--space-12);
  justify-items: start;
}

@media (min-width: 900px) { .door__actions { justify-items: end; } }

.counter {
  display: inline-flex;
  border: 1px solid var(--c-hairline-strong);
  border-radius: var(--r-sm);
  background: rgba(9, 10, 12, 0.62);
  backdrop-filter: blur(6px);
  overflow: hidden;
}

.counter__unit {
  padding: var(--space-8) var(--space-16);
  text-align: center;
  border-right: 1px solid var(--c-hairline);
}

.counter__unit:last-child { border-right: 0; }

.counter__value {
  display: block;
  font-family: var(--font-display);
  font-variation-settings: 'wdth' var(--wdth-numeral), 'wght' 800;
  font-size: var(--fs-24);
  line-height: var(--lh-tight);
  color: var(--c-brass-hi);
  font-variant-numeric: tabular-nums;
}

.counter__label {
  display: block;
  margin-top: var(--space-4);
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  color: var(--c-dim);
}

.counter--open { padding: var(--space-12) var(--space-16); }
.counter--open b { display: block; font-family: var(--font-display); font-size: var(--fs-16); color: var(--c-brass-hi); }
.counter--open span { display: block; margin-top: var(--space-4); font-family: var(--font-mono); font-size: 9px; letter-spacing: var(--tracking-meta); text-transform: uppercase; color: var(--c-dim); }

.door__note {
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  color: var(--c-dim);
}

.door__note b { color: var(--c-brass); font-weight: 500; }

.door__dust {
  position: absolute;
  inset: 0;
  z-index: var(--z-raised);
  pointer-events: none;
  opacity: calc(0.25 + var(--open) * 0.4);
}

/* ---------------------------------------------------------------
   Fallbacks and small screens.
   --------------------------------------------------------------- */

.no-js .door,
.door.is-open { --open: 1; --push: 0; }

@media (prefers-reduced-motion: reduce) {
  .door { --open: 1; --push: 0; }
  .door__track { height: auto; }
  .door__viewport { position: relative; }
  .door__word--1,
  .door__word--2,
  .door__word--3 { transform: none; opacity: 1; }
}

@media (max-width: 899px) {
  /* The same scroll-driven door, on a shorter run and with a simpler scene. */
  .door__track { height: 200svh; }
  .door__viewport { position: sticky; }

  /* Shallower swing and a nearer camera read better on a narrow screen. */
  /* The leaves swing right back against the walls, so the doorway is clear
     and the reveal is not read through a narrow slot. */
  .door__leaf--l { transform: translateZ(calc(var(--push) * 190px)) rotateY(calc(var(--open) * 88deg)); }
  .door__leaf--r { transform: translateZ(calc(var(--push) * 190px)) rotateY(calc(var(--open) * -88deg)); }

  /* A phone sees the whole leaf at once, so it is set symmetrically: equal
     head and bottom rails, two panels of the same height, and the lock rail
     - with the engraving and the handles on it - on the leaf's true centre.
     Desktop keeps the taller lower panel, which is how a real door is built
     and which reads correctly when the leaf is that much wider. */
  .door { --rail: 50%; }
  .door__panel--upper { top: 8%; height: 35%; }
  .door__panel--lower { top: 57%; height: 35%; }

  .door__interior { transform: scale(calc(1.03 + var(--push) * 0.18)); }
  /* The lockup holds its place here too: lifting it on the push slid it up
     into the eyebrow. */
  .door__word--1,
  .door__word--2 { transform: none; }

  /* Full-bleed leaves, as on desktop: no gutters either side. */
  .door__leaf { width: 50%; }

  /* A narrow screen has no room for both marks at once: the engraving on the
     leaves clears before the lockup behind it resolves. */
  .door__leafword {
    opacity: clamp(0, calc(1 - var(--open) * 3), 1);
    font-size: clamp(var(--fs-24), 9vw, var(--fs-40));
  }

  /* The lockup resolves only once the doorway is wide enough to hold it, and
     it sits in front of the leaves so it is never cropped by them. */
  .door__type {
    /* Raised so the gap under the header matches the gap above the lede.
       Behind the leaves, at full strength: revealed by the swing, not a fade. */
    top: 30%;
    z-index: var(--z-base);
    text-align: left;
  }

  /* Clear of the title: the crushed line-height lets its ascenders ride up. */
  .door__eyebrow { margin-bottom: var(--space-24); }
  .door__title { padding-top: 0.08em; }

  .door__word--3 { text-indent: 0; }

  .door__title { font-size: clamp(var(--fs-40), 13.5vw, var(--fs-64)); }

  /* The invitation follows the reveal rather than sitting under the beam. */
  /* Behind the leaves at full strength, exactly like the lockup: the sill is
     uncovered by the swing rather than faded up on top of it. The falloff
     drops below it so its gradient cannot veil the invitation, and the leaves
     stop taking pointer events so nothing of theirs sits over the CTA once
     they have swung clear. */
  /* A phone holds the doorway at full width, so the room glow covers the whole
     screen rather than a panel of it, and at desktop strength it turns the
     hero into one gold wash behind the type. Held at roughly half here: the
     room still reads as lit, the lockup and the invitation keep the contrast. */
  .door__glow {
    /* A circle sized in vmin, not a percentage pair: percentages take their
       width and height from the box, so on a tall phone the declaration
       becomes a stretched oval. Size matters as much as shape - at 62vmin the
       circle was 484px across on a 390px screen, so both sides were clipped
       flat by the viewport and only the top and bottom curved, which reads as
       an ellipse however round the gradient actually is. It has to fit inside
       the screen to be seen as a circle. The extra stops shape the falloff so
       it fades like light in air rather than ending on a rim. */
    background:
      radial-gradient(circle 40vmin at 50% 40%,
        rgba(232, 200, 137, calc(0.03 + var(--open) * 0.086)) 0%,
        rgba(232, 200, 137, calc(0.018 + var(--open) * 0.05)) 34%,
        rgba(232, 200, 137, calc(0.006 + var(--open) * 0.018)) 64%,
        transparent 100%),
      radial-gradient(circle 32vmin at 50% 94%,
        rgba(198, 151, 73, calc(0.014 + var(--open) * 0.022)) 0%,
        rgba(198, 151, 73, calc(0.005 + var(--open) * 0.008)) 52%,
        transparent 100%),
      linear-gradient(180deg, transparent 58%, var(--c-obsidian) 94%);
  }

  /* The seam leak follows it down, so the two stay in proportion. */
  .door__light { opacity: clamp(0, calc(0.86 - var(--open) * 1.1), 1); }

  /* The foot of each leaf falls into shadow, which gives the scroll cue a
     clean base to sit on instead of the panel moulding and the grain. Put on
     the leaves rather than over the doorway on purpose: it travels with them
     on the swing, and it can never veil the invitation the way a bottom
     overlay across the whole chapter would. */
  .door__leaf::after {
    content: "";
    position: absolute;
    inset: auto 0 0;
    height: 20%;
    pointer-events: none;
    background: linear-gradient(180deg, transparent 0%, rgba(5, 6, 8, 0.55) 62%, rgba(5, 6, 8, 0.88) 100%);
  }

  /* Opaque for all but the first sliver of the swing, so the reveal is still
     the leaves uncovering it rather than a fade - but not visible through the
     hairline crack the idle beat opens, where a slice of the brass CTA read
     as a glitch rather than as light from the room. */
  .door__sill {
    opacity: clamp(0, calc(var(--open) * 6), 1);
    z-index: var(--z-raised);
    pointer-events: none;
  }
  .door.is-ajar .door__sill { pointer-events: auto; }
  .door__falloff { z-index: var(--z-base); }
  .door__leaf { pointer-events: none; }

  .door__leaf--l { left: 0; }
  .door__leaf--r { right: 0; }
  .door__word--3 { font-size: 0.3em; letter-spacing: 0.3em; text-indent: 0.3em; }


  .door__title { font-size: clamp(var(--fs-48), 16.5vw, var(--fs-96)); }
  .door__sill-inner { gap: var(--space-12); }
  .door__lede { font-size: var(--fs-20); }
  .door__support { display: none; }
  .door__actions { justify-items: stretch; }
  .door__actions .pull { width: 100%; justify-content: center; }

  /* The counter rules the full width and divides it evenly - content-sized
     units left the leftover space inside the last cell, which read as a
     stretched SEC. Sized down so the sill carries five things without
     shouting. */
  .counter { display: flex; width: 100%; }
  .counter__unit { flex: 1; padding: var(--space-8) var(--space-4); }
  .counter__value { font-size: var(--fs-20); }
  .counter__label { font-size: 8px; }
  .door__actions .pull { min-height: var(--space-48); padding-block: var(--space-12); }
  .door__stage { perspective: 1000px; }
  }

/* Very short desktop viewports compress the sill. */
@media (min-width: 900px) and (max-height: 760px) {
  .door__title { font-size: clamp(var(--fs-48), 10vw, var(--fs-128)); }
  .door__sill { padding-bottom: var(--space-16); }
  .door__support { display: none; }
}


/* ===============================================================
   02 · THE DISPATCH DESK
   Ground: midnight blue. Two pieces of correspondence arrive
   through a slot and open on the desk.

   Per piece:
   --enter  0..1  travel from the slot down to the desk
   --settle 0..1  extraction: the sheet leaves the envelope
   =============================================================== */

.dispatch {
  --p: 0;
  /* Continues the hero's ground exactly - there is no seam between them. */
  background:
    radial-gradient(70% 46% at 24% 4%, rgba(198, 151, 73, 0.06), transparent 66%),
    linear-gradient(180deg, var(--c-obsidian) 0%, var(--c-charcoal) 34%, var(--c-charcoal) 74%, #0D1013 100%);
  overflow: clip;
  margin-top: calc(-1 * var(--space-4));
}

.dispatch__track { position: relative; height: 240svh; }

.dispatch__viewport {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: clip;
  display: grid;
  grid-template-rows: auto 1fr;
  align-content: start;
  /* Clear the fixed corner navigation while the chapter is pinned. */
  padding-block: var(--space-64) var(--space-48);
  gap: var(--space-32);
}

.dispatch__head {
  position: relative;
  z-index: var(--z-raised);
  width: min(calc(100% - (2 * var(--container-pad))), var(--container-max));
  margin-inline: auto;
  display: grid;
  gap: var(--space-24);
}

@media (min-width: 1024px) {
  .dispatch__head {
    grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
    gap: var(--space-64);
    align-items: end;
  }
}

/* The timetable at the desk edge: three engraved rows. */
.dispatch__timetable {
  margin: 0;
  border-top: 1px solid var(--c-hairline-strong);
}

.dispatch__timetable > div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-16);
  padding-block: var(--space-12);
  border-bottom: 1px solid var(--c-hairline-faint);
}

.dispatch__timetable dt,
.dispatch__timetable dd {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
}

.dispatch__timetable dt { color: var(--c-dim); }
.dispatch__timetable dd { color: var(--c-brass-hi); text-align: right; white-space: nowrap; }

/* ---------------------------------------------------------------
   The desk: two envelopes at rest. Scroll opens the flap and draws
   the letter up out of the mouth.
   --------------------------------------------------------------- */

.desk {
  position: relative;
  width: min(calc(100% - (2 * var(--container-pad))), 1080px);
  margin: 0 auto;
  align-self: center;
  display: grid;
  gap: var(--space-40);
  justify-items: center;
  /* The pieces are sized to the space left under the head, so a full letter
     and its envelope are always on screen together. */
  --piece-max: min(420px, calc((100svh - var(--space-200) - var(--space-128)) * 0.78));
}

@media (min-width: 900px) {
  /* Both pieces sit on the same desk line, whatever their letters weigh. */
  .desk { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; gap: var(--space-64); }
}

.dispatch-piece { width: min(100%, var(--piece-max, 420px)); }

.dispatch-piece {
  --settle: 0;
  position: relative;
  transform: rotate(-0.6deg);
}

.dispatch-piece--sat { transform: rotate(0.6deg); }

/* Wednesday opens through the first half of the track, Saturday the second.
   Desktop only: these outrank the phone layout's default on specificity, so
   left unscoped they would leave both letters shut inside their envelopes on
   a phone with no JS. */
@media (min-width: 900px) {
  .js-dispatch .dispatch-piece--wed { --settle: clamp(0, calc(var(--p) * 2.4), 1); }
  .js-dispatch .dispatch-piece--sat { --settle: clamp(0, calc((var(--p) - 0.42) * 2.4), 1); }
}

/* The sheath: everything above the envelope mouth. Clips the rising letter
   at exactly the mouth line, so the illusion holds at every frame. */
/* The sheath takes its height from the letter itself, so nothing is ever
   clipped by a fixed container. It only hides the letter while it is still
   down inside the envelope. */
.dispatch-piece {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.dispatch-piece__sheath {
  position: relative;
  overflow: hidden;
  padding-top: var(--space-16);
  margin-bottom: calc(-1 * var(--space-24));
  z-index: 1;
  /* Equal height across both pieces, so the two envelopes align. */
  flex: 1;
  display: flex;
  align-items: flex-end;
}

.dispatch-piece__sheath > .dispatch-sheet { width: 100%; }

/* The wrapper only exists for the phone layout. Everywhere else it is
   transparent to layout, so the piece's own flex column is unchanged. */
.dispatch-piece__stage { display: contents; }

@media (min-width: 900px) {
  /* The lighter letter is drawn to the same size as the heavier one, so the
     two sheets top out on one line instead of stepping. Declared here rather
     than with the desk grid so it lands after the base rule it overrides. */
  .dispatch-piece__sheath { align-items: stretch; }
}

.dispatch-sheet {
  position: relative;
  display: flex;
  flex-direction: column;
  /* Promoted: this is a large opaque card with a wide shadow, moving inside a
     clipping sheath. On its own layer the phone composites the movement
     instead of repainting the card and its shadow every frame. */
  will-change: transform;
  margin-inline: var(--space-24);
  background: linear-gradient(180deg, var(--c-ivory) 0%, #EAE5D8 100%);
  color: var(--c-paper-ink);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.35);
  /* Down inside the envelope at 0, fully drawn out at 1. */
  transform: translateY(calc((1 - var(--settle)) * 100%));
}

/* The envelope: blank charcoal paper, side folds, a triangular flap and a
   brass wax seal. Nothing is printed on it - it is a sealed envelope. */
.envelope {
  position: relative;
  z-index: 2;
  min-height: var(--space-128);
  display: flex;
  align-items: flex-end;
  padding: var(--space-16) var(--space-20);
  border-radius: var(--r-sm);
  background:
    linear-gradient(160deg, rgba(255, 255, 255, 0.045), transparent 34%),
    linear-gradient(160deg, #1C1F26 0%, #14161C 56%, #0E1014 100%);
  border: 1px solid rgba(198, 151, 73, 0.32);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 24px 48px rgba(0, 0, 0, 0.5);
}



/* The back flaps: two side folds meeting in the middle of the envelope. */
.envelope__folds {
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  overflow: hidden;
  background:
    linear-gradient(to bottom right, rgba(255, 255, 255, 0.02) 0 50%, transparent 50%),
    linear-gradient(to bottom left, rgba(0, 0, 0, 0.12) 0 50%, transparent 50%);
  opacity: calc(1 - var(--settle) * 0.75);
}

/* The seams those folds make. */
.envelope__folds::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom right, transparent calc(50% - 0.5px), rgba(232, 200, 137, 0.1) 50%, transparent calc(50% + 0.5px)),
    linear-gradient(to bottom left, transparent calc(50% - 0.5px), rgba(232, 200, 137, 0.1) 50%, transparent calc(50% + 0.5px));
}

/* The flap: folded closed over the mouth; swings back as the letter leaves. */
.envelope__flap {
  position: absolute;
  inset: 0 0 auto;
  height: 62%;
  background: linear-gradient(180deg, #262A33 0%, #1A1D24 62%, #14171D 100%);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  /* A true triangular flap, its folded edge catching the light. */
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  transform-origin: top center;
  transform: rotateX(calc(var(--settle) * -170deg));
  transform-style: preserve-3d;
  backface-visibility: hidden;
  box-shadow: 0 10px 18px rgba(0, 0, 0, 0.45);
  z-index: 3;
}

/* The lit fold line down each side of the flap. */
.envelope__flap::after {
  content: "";
  position: absolute;
  inset: 0;
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  background:
    linear-gradient(to bottom left, transparent calc(50% - 0.6px), rgba(232, 200, 137, 0.3) 50%, transparent calc(50% + 0.6px)),
    linear-gradient(to bottom right, transparent calc(50% - 0.6px), rgba(232, 200, 137, 0.3) 50%, transparent calc(50% + 0.6px));
}



.envelope__seal {
  position: absolute;
  top: calc(62% - var(--space-16));
  left: 50%;
  z-index: 4;
  display: grid;
  place-items: center;
  width: var(--space-32);
  height: var(--space-32);
  margin-left: calc(-1 * var(--space-16));
  border-radius: var(--r-full);
  background: var(--surface-brass);
  box-shadow: var(--shadow-inset-brass), 0 3px 8px rgba(0, 0, 0, 0.6);
  color: #43310F;
  opacity: calc(1 - var(--settle) * 2.4);
}

/* The label on the envelope face. Hidden while the flap is sealed over it,
   revealed as the letter is drawn out. */
.envelope__mark {
  position: relative;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-12);
  width: 100%;
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--c-brass-hi);
  opacity: clamp(0, calc((var(--settle) - 0.45) * 2.6), 1);
}

.envelope__stamp {
  display: inline-grid;
  place-items: center;
  padding: var(--space-4) var(--space-8);
  border: 1px solid rgba(232, 200, 137, 0.45);
  border-radius: var(--r-sm);
  font-size: 9px;
  letter-spacing: var(--tracking-meta);
  white-space: nowrap;
}

.dispatch-sheet__plate {
  position: relative;
  aspect-ratio: 16 / 5;
  overflow: hidden;
  border-bottom: 1px solid rgba(20, 22, 26, 0.16);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
}

.dispatch-sheet__plate img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 58%;
  filter: saturate(0.6) contrast(1.06) brightness(0.92) sepia(0.1);
}


/* The foot of the letter tucks behind the envelope, so its last line needs
   clearance to stay readable. */
.dispatch-sheet__body {
  padding: var(--space-16) var(--space-24) var(--space-48);
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}

.dispatch-sheet__day {
  margin: 0;
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 96, 'wght' 800;
  font-size: var(--fs-24);
  letter-spacing: var(--tracking-heading);
  color: var(--c-paper-ink);
}

.dispatch-sheet__time {
  display: flex;
  align-items: baseline;
  gap: var(--space-8);
  margin: var(--space-8) 0 var(--space-12);
  font-family: var(--font-display);
  font-variation-settings: 'wdth' var(--wdth-numeral), 'wght' 800;
  font-size: var(--step-numeral);
  line-height: var(--lh-tight);
  color: var(--c-brass-ink);
  font-variant-numeric: tabular-nums;
}

.dispatch-sheet__time .icon { color: var(--c-brass-ink); align-self: center; }
.dispatch-sheet__text {
  margin: 0;
  /* grow-only: absorbs the extra height on the shorter letter, and stays at
     its natural height wherever the sheet is sized by its content. */
  flex: 1 0 auto;
  font-size: var(--fs-16);
  line-height: 1.52;
  color: #33383F;
  max-width: 44ch;
}

.dispatch-sheet__meta {
  margin-top: var(--space-16);
  padding-top: var(--space-12);
  border-top: 1px solid rgba(20, 22, 26, 0.16);
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  color: var(--c-brass-ink);
}

.dispatch-sheet__meta b { color: var(--c-paper-ink); font-weight: 500; }

/* ---------------------------------------------------------------
   Tablet, mobile and reduced motion: the same correspondence as a
   vertical run of opened pieces. The flap opens on arrival.
   --------------------------------------------------------------- */

@media (min-width: 900px) and (max-width: 1200px) {
  .dispatch-piece { width: min(380px, 44%); }
}

/* Short desktop viewports: the correspondence composes tighter so a whole
   letter and its envelope are always on screen together. */
@media (min-width: 900px) and (max-height: 980px) {
  .dispatch__viewport { padding-block: var(--space-56) var(--space-24); }
  .dispatch__headline { font-size: clamp(var(--fs-28), 2.6vw, var(--fs-40)); }
  .desk { gap: var(--space-40); }
  .dispatch-piece { width: min(100%, 372px); }
  .dispatch-sheet__plate { aspect-ratio: 24 / 5; }
  .dispatch-sheet__body { padding: var(--space-12) var(--space-20) var(--space-40); }
  .dispatch-sheet__day { font-size: var(--fs-20); }
  .dispatch-sheet__time { font-size: var(--fs-32); margin-block: var(--space-4) var(--space-8); }
  .dispatch-sheet__text { font-size: var(--fs-16); line-height: 1.45; }
  .dispatch-sheet__meta { margin-top: var(--space-12); padding-top: var(--space-8); }
  .envelope { min-height: var(--space-96); }
  .dispatch__timetable > div { padding-block: var(--space-8); }
}

@media (min-width: 900px) and (max-height: 820px) {
  .dispatch__head { gap: var(--space-16); }
  .dispatch__viewport { padding-block: var(--space-48) var(--space-32); gap: var(--space-20); }
  .dispatch__headline { font-size: var(--fs-28); }
  .dispatch-piece { width: min(100%, 340px); }
  .dispatch-sheet__plate { display: none; }
  .dispatch-sheet__text { font-size: var(--fs-16); line-height: 1.4; }
  .dispatch-sheet__body { padding: var(--space-12) var(--space-16) var(--space-32); }
  .envelope { min-height: var(--space-64); padding: var(--space-12) var(--space-16); }
}

@media (max-width: 899px) {
  .dispatch__track { height: auto; }
  .dispatch__viewport { position: relative; min-height: 0; height: auto; overflow: visible; padding-block: 0; }
  /* One full-width column: the letters are read, not squinted at. */
  .desk {
    /* Was 100%, which ran the envelope clean off both edges while the letter
       above it stayed inset. Both sit inside the page gutter now. */
    width: min(100% - (2 * var(--container-pad)), 560px);
    /* The first piece's runway is empty, so it is pulled up over the heading
       instead of being left as a void below it. The stage then begins in
       natural flow directly under the heading: the envelope enters as the
       heading starts to move, and the two travel together. */
    margin-top: calc(var(--space-32) - var(--piece-draw, 52svh));
    /* The last envelope clears the screen before the next chapter arrives. */
    padding-bottom: var(--space-64);
    /* No spacing between pieces. Each piece is [runway][stage], so with the
       boxes flush the outgoing stage's bottom edge and the incoming stage's
       top edge meet exactly: the first climbs away as the second rises, with
       neither a void nor an overlap between them. */
    gap: 0;
    grid-template-columns: 1fr;
    justify-items: stretch;
  }

  /* overflow:clip on the chapter makes it a clipping context, and a clipping
     context is where a sticky descendant stops sticking. Clip the axis that
     actually needs it and leave the vertical axis alone. */
  .dispatch { overflow-x: clip; overflow-y: visible; }
  .dispatch__viewport { overflow-x: clip; overflow-y: visible; }

  /* Each piece owns a scroll track. Its envelope arrives, holds at the foot
     of the screen while the letter draws out of it, then releases and the
     next one takes its place. */
  /* The standing distance between a spent letter and the one that replaced it,
     and between the heading and the first letter. */
  .dispatch { --piece-gap: 40px; }

  /* The heading is the first link in that stack: the arriving letter holds it
     off and carries it up, rather than the letter climbing over it. */
  .dispatch__head { transform: translateY(var(--hold, 0px)); }

  .dispatch-piece {
    width: 100%;
    /* flow-root, not block: the stage's top margin has to stay inside this
       box rather than collapsing out through it. */
    display: flow-root;
    transform: none;
    /* Open by default, so with no JS the letters are simply readable. The
       scroll layer closes them and then draws them out itself. */
    --settle: 1;
  }

  .dispatch-piece__stage {
    position: sticky;
    /* Clear of the sticky invite dock, which owns the foot of the screen,
       with a margin so the envelope rests above it rather than on it. */
    bottom: calc(var(--dock-h, 0px) + var(--space-16));
    /* Held off the head of the letter below it. See --hold in motion.js. */
    transform: translateY(var(--hold, 0px));
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
  }

  /* The draw runway, as an in-flow sibling ABOVE the stage. A bottom-sticky
     box is pulled UP out of a late flow position to sit at the foot of the
     screen, so the room it needs is room above it. Neither of the obvious
     alternatives works: padding on the piece falls outside the content box
     the sticky constraint is measured against, and a margin on the stage is
     counted as part of the stage's own margin box, so it buys no room at
     all. A sibling is the only one of the three that does. */
  .dispatch-piece::before {
    content: "";
    display: block;
    height: var(--piece-draw, 52svh);
  }

  /* The visible mass of a stage is the envelope at its foot; the sheath above
     it is empty until the letter draws. Lifting the next piece by one sheath
     brings its envelope to the screen's edge as the current letter starts to
     climb, instead of leaving a sheath-high void between them. The sheath is
     transparent, so the overlap this creates is not a visible one. */
  .dispatch-piece + .dispatch-piece {
    margin-top: calc(-1 * (var(--piece-draw, 52svh) - var(--space-96)));
  }

  .dispatch-piece__sheath { flex: none; transition: none; }
  .dispatch-sheet { margin-inline: var(--space-16); }
  .dispatch-sheet__plate { aspect-ratio: 3 / 1; }
  .dispatch-sheet__time { font-size: var(--fs-32); }
  .dispatch-sheet__text { max-width: none; }

  /* A shallower envelope: on a phone it is the mouth the letter comes out of,
     not a slab of empty board. */
  .envelope { min-height: var(--space-80); padding: var(--space-12) var(--space-16); }

  /* The narrowest phones: the envelope's mark is set on one line and its
     min-content width was pushing the envelope past the desk. Tightened
     rather than wrapped - a wrapped stamp reads as a mistake. */
  @media (max-width: 374px) {
    .envelope { padding-inline: var(--space-12); }
    .envelope__mark { gap: var(--space-8); font-size: 10px; letter-spacing: 0.14em; }
    .envelope__stamp { font-size: 8px; letter-spacing: 0.08em; padding-inline: var(--space-8); }
  }

  /* Once the scroll layer is live it takes over: closed at first, then drawn
     out by the piece's own track. */
  .js-dispatch-scroll .dispatch-piece { --settle: 0; }
  /*
   * On a phone the flap opens once, on its own, rather than being driven frame
   * by frame off --settle.
   *
   * It is the most expensive thing in this scene: a clip-path polygon rotating
   * in 3D with a shadow under it, which cannot be composited and so has to be
   * re-rastered on every frame it moves. At a phone's pixel density that is the
   * bulk of the raster work in the chapter. As a two-state change it animates
   * once, on the compositor, and costs nothing for the rest of the scroll.
   *
   * A transition is safe here precisely because the driver is now discrete. It
   * was not safe against --settle, where it restarted every frame and lagged.
   */
  .envelope__flap {
    transform: rotateX(0deg);
    transition: transform 620ms var(--ease-mech);
  }

  .dispatch-piece.is-open .envelope__flap { transform: rotateX(-170deg); }

  /* The envelope keeps its own layer, so the letter sliding over it does not
     drag the flap, the folds and the seal into a repaint with it. */
  .envelope { will-change: transform; }
}

/* A short phone cannot hold a full letter, its envelope and the invite dock
   at once - the stage ends up taller than the space above the dock and the
   letter is pinned with its head off the top of the screen. The plate goes
   and the setting tightens until the whole piece fits. */
@media (max-width: 899px) and (max-height: 700px) {
  .dispatch-sheet__plate { display: none; }
  .dispatch-sheet__body { padding: var(--space-12) var(--space-20) var(--space-32); }
  .dispatch-sheet__day { font-size: var(--fs-20); }
  .dispatch-sheet__time { font-size: var(--fs-28); margin-block: var(--space-4) var(--space-8); }
  .dispatch-sheet__text { line-height: 1.4; }
  .dispatch-sheet__meta { margin-top: var(--space-12); padding-top: var(--space-8); }
  .envelope { min-height: var(--space-64); }
}

@media (prefers-reduced-motion: reduce) {
  .dispatch__track { height: auto; }
  .dispatch__viewport { position: relative; height: auto; overflow: visible; }
  .dispatch-piece { --settle: 1 !important; transform: none; }
  .dispatch-sheet, .envelope__flap { transition: none; }

  /* No pinning and no runways: both letters are simply open, one after the
     other, with nothing to scroll through to reach them. */
  .dispatch-piece::before { display: none; }
  .dispatch-piece__stage { position: static; }
}

/* ===============================================================
   03 · THE RULES
   Ground: charcoal and steel. Object: a locking mechanism.
   Each rule closes one bolt. By the end, the room is secure.
   =============================================================== */

.rules {
  /* Opens on the dispatch chapter's closing tone exactly, and the tungsten
     pool starts well below the join, so the two grounds meet invisibly. */
  background:
    radial-gradient(42% 30% at 78% 48%, rgba(198, 151, 73, 0.085), transparent 74%),
    linear-gradient(180deg, #0D1013 0%, #0D1013 10%, var(--c-charcoal) 34%, #0D1013 100%);
  overflow: clip;
  margin-top: calc(-1 * var(--space-4));
  /* The sticky column already carries the closing space. */
  padding-bottom: 0;
}

.rules__track { position: relative; }
.rules__inner { width: min(calc(100% - (2 * var(--container-pad))), var(--container-wide)); margin-inline: auto; }

@media (min-width: 900px) {
  .rules__inner { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-64); align-items: start; }

  /* Held in the middle of the view for the whole chapter, so its column is
     never left standing empty once the rules run out. */
  .rules__mech {
    position: sticky;
    top: 0;
    height: 100svh;
    display: grid;
    place-items: center;
    margin-bottom: 0;
    padding-bottom: 0;
  }

  /* The sticky column needs track beyond the final rule, or the vault
     unsticks and slides away while that rule is still being read. This keeps
     it pinned until the last rule has cleared three quarters of the screen. */
  .rules__list { padding-bottom: var(--space-200); }
}

.rules__mech { display: grid; place-items: center; margin-bottom: var(--space-40); padding-bottom: var(--space-24); }

.mech { width: min(100%, 460px); height: auto; color: var(--c-brass); overflow: visible; }
.mech__ring { stroke: rgba(198, 151, 73, 0.32); fill: none; }
.mech__plate { fill: url(#cdm-steel); stroke: rgba(198, 151, 73, 0.22); }
.mech__engrave { fill: none; stroke: rgba(198, 151, 73, 0.18); }

/* Each bolt slides home as its rule is read. */
.mech__bolt {
  --locked: 0;
  transform: translate(calc(var(--dx) * (1 - var(--locked)) * 1px), calc(var(--dy) * (1 - var(--locked)) * 1px));
  transition: transform var(--dur-slower) var(--ease-mech);
}

.mech__bolt rect { fill: url(#cdm-brass); stroke: rgba(58, 42, 13, 0.8); stroke-width: 0.6; }
.mech__bolt circle { fill: rgba(232, 200, 137, 0.9); }

.mech__socket { fill: rgba(0, 0, 0, 0.55); stroke: rgba(198, 151, 73, 0.24); }

/* The core turns a little as each bolt seats. */
.mech__core {
  transform-origin: 200px 200px;
  transform: rotate(calc(var(--locked-count, 0) * 6deg));
  transition: transform var(--dur-slower) var(--ease-mech);
}

.mech__keyhole { fill: rgba(0, 0, 0, 0.8); stroke: rgba(232, 200, 137, 0.4); }

.mech__status {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  fill: var(--c-brass);
}

.rules__list { list-style: none; margin: var(--space-32) 0 0; }

.rule {
  display: grid;
  grid-template-columns: var(--space-24) var(--space-32) minmax(0, 1fr);
  gap: var(--space-16);
  align-items: start;
  padding-block: var(--space-24);
  border-top: 1px solid var(--c-hairline-faint);
  opacity: 0.42;
  transition: opacity var(--dur-slow) var(--ease-editorial);
}

.rule.is-locked { opacity: 1; }
.rule__no { font-family: var(--font-mono); font-size: var(--fs-12); letter-spacing: var(--tracking-meta); color: var(--c-brass-lo); padding-top: var(--space-4); }
.rule.is-locked .rule__no { color: var(--c-brass); }

.rule__icon {
  color: var(--c-brass-lo);
  transform: scale(0.86);
  transition: color var(--dur-slow) var(--ease-mech), transform var(--dur-slow) var(--ease-settle);
}

.rule.is-locked .rule__icon { color: var(--c-brass); transform: none; }

.rule__text { margin: 0; font-size: var(--step-body); }
.rule__text b {
  display: block;
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 96, 'wght' 700;
  font-size: var(--fs-20);
  letter-spacing: -0.01em;
  color: var(--c-white);
  margin-bottom: var(--space-4);
}

@media (min-width: 900px) {
  .rule__text b { font-size: var(--fs-24); }
}

/* ===============================================================
   04 · THE THRESHOLD - who gets in
   Ground: bottle green. Two environments, one brass seam between them.
   =============================================================== */

.threshold {
  position: relative;
  background: linear-gradient(180deg, #0D1013 0%, var(--c-charcoal) 24%, var(--c-charcoal) 76%, var(--c-obsidian) 100%);
  overflow: clip;
}

/* Follows the rules chapter directly, with no opening gap of its own. The
   extra class outranks the generic chapter-join rule in layout.css. */
.act.threshold { padding-top: 0; }

/* Those zero joins only work while the sticky vault is holding the space
   open. Without it there is nothing between the last rule and this chapter,
   so the phone layout keeps a real gap. */
@media (max-width: 899px) {
  /* The rules chapter alone carries the join, so the space is not doubled. */
  .act.rules { padding-top: 20px; padding-bottom: var(--chapter-y); }
}

.threshold__zone { position: relative; }

.threshold__stage {
  position: relative;
  z-index: var(--z-raised);
  display: grid;
  gap: var(--space-24);
  margin-top: var(--space-48);
}

@media (min-width: 900px) {
  .threshold__stage { grid-template-columns: minmax(0, 1fr) 2px minmax(0, 1fr); gap: var(--space-40); align-items: start; }
}

.threshold__seam { display: none; }

@media (min-width: 900px) {
  .threshold__seam {
    display: block;
    align-self: stretch;
    background: linear-gradient(180deg, transparent, var(--c-brass) 18%, var(--c-brass-hi) 50%, var(--c-brass) 82%, transparent);
    box-shadow: 0 0 28px 2px rgba(232, 200, 137, 0.22);
  }
}

.side__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-12); margin-bottom: var(--space-20); }

.side__title {
  font-family: var(--font-display);
  font-variation-settings: 'wdth' var(--wdth-condensed), 'wght' var(--wght-black);
  font-size: var(--step-h3);
  letter-spacing: -0.03em;
  text-transform: uppercase;
  margin: 0;
}

.side--in .side__title { color: var(--c-brass-hi); }
.side--out .side__title { color: var(--c-dim); }
.side__count { font-family: var(--font-mono); font-size: var(--fs-12); letter-spacing: var(--tracking-meta); color: var(--c-dim); }

.side__list { list-style: none; display: grid; gap: var(--space-8); }

/* Each category is a physical card that routes to its side of the threshold. */
.tile {
  --dir: -1;
  display: flex;
  align-items: center;
  gap: var(--space-12);
  padding: var(--space-16);
  border-radius: var(--r-sm);
  font-size: var(--fs-16);
  line-height: 1.3;
  opacity: 0;
  transform: translateX(calc(var(--dir) * -34%)) rotate(calc(var(--dir) * -1.4deg));
  transition: opacity var(--dur-slower) var(--ease-editorial),
              transform var(--dur-slower) var(--ease-settle),
              border-color var(--dur-base) var(--ease-ui),
              background var(--dur-base) var(--ease-ui);
}

.is-inview .tile { opacity: 1; transform: translateX(0) rotate(calc(var(--dir) * 0.4deg)); }

.side--in .tile {
  --dir: 1;
  background: linear-gradient(150deg, rgba(198, 151, 73, 0.14), rgba(20, 22, 26, 0.7));
  border: 1px solid rgba(198, 151, 73, 0.32);
  color: var(--c-paper);
}

.side--out .tile {
  --dir: -1;
  background: linear-gradient(150deg, rgba(16, 18, 22, 0.8), rgba(10, 11, 13, 0.7));
  border: 1px solid rgba(156, 151, 140, 0.18);
  border-left: 2px solid rgba(142, 51, 70, 0.5);
  color: var(--c-dim);
}

.side--in .tile:hover { border-color: var(--c-brass); transform: translateX(6px) rotate(0.4deg); }
.side--out .tile:hover { border-color: rgba(156, 151, 140, 0.36); transform: translateX(-6px) rotate(-0.4deg); }

.tile .icon { color: currentColor; opacity: 0.8; }

.side__why {
  margin: var(--space-24) 0 0;
  font-size: var(--fs-16);
  line-height: 1.5;
  font-style: italic;
  opacity: 0.82;
  max-width: 46ch;
}

/* The quote holds the screen while it reads itself in, then releases. */
.quote-track { position: relative; height: 200svh; margin-top: var(--space-64); }

.threshold__verdict {
  position: sticky;
  top: 0;
  height: 100svh;
  display: grid;
  place-items: center;
  z-index: var(--z-raised);
  margin: 0;
  width: 100%;
  text-align: center;
}

@media (max-width: 899px) { .quote-track { height: 175svh; } }

@media (prefers-reduced-motion: reduce) {
  .quote-track { height: auto; margin-top: var(--space-48); }
  .threshold__verdict { position: relative; height: auto; padding-block: var(--space-48); }
}

.threshold__verdict .t-pull {
  max-width: none;
  margin-inline: auto;
  font-size: clamp(var(--fs-24), 1.1rem + 2.6vw, var(--fs-56));
  line-height: 1.3;
  color: var(--c-white);
  text-wrap: balance;
}

/* Read word by word as the visitor scrolls through the thought. */
.threshold__verdict .w {
  opacity: 0.14;
  transition: opacity var(--dur-slow) var(--ease-editorial);
}

.threshold__verdict .w.is-lit { opacity: 1; }

.no-js .threshold__verdict .w { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .threshold__verdict .w { opacity: 1; transition: none; }
}
.threshold__verdict .t-pull em { font-style: normal; color: var(--c-brass-hi); }

@media (max-width: 899px) {
    }

/* ===============================================================
   04b · THE OWNER - full bleed
   One photograph, one line. The person the room is written for.
   =============================================================== */

.owner-band {
  position: relative;
  min-height: clamp(480px, 88svh, 880px);
  display: flex;
  align-items: flex-end;
  overflow: clip;
  background: var(--c-obsidian);
}

.owner-band__figure {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

/* Oversized and centred: the parallax shifts it, but the frame stays filled
   top and bottom, so no black margin can appear under the photograph. */
.owner-band__figure img {
  position: absolute;
  inset: -9% 0;
  width: 100%;
  height: 118%;
  object-fit: cover;
  object-position: 50% 46%;
  filter: saturate(0.32) contrast(1.12) brightness(0.52) sepia(0.22);
}

.owner-band__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, var(--c-obsidian) 0%, transparent 18%),
    linear-gradient(0deg, rgba(9, 10, 12, 0.88) 0%, rgba(9, 10, 12, 0.34) 34%, transparent 58%),
    linear-gradient(90deg, rgba(9, 10, 12, 0.5), transparent 40%);
}

.owner-band__copy {
  position: relative;
  z-index: var(--z-raised);
  margin-inline: auto;
  width: min(calc(100% - (2 * var(--container-pad))), var(--container-wide));
  padding-bottom: clamp(var(--space-48), 8svh, var(--space-96));
}

.owner-band__eyebrow { color: var(--c-brass); }

.owner-band__line {
  margin: var(--space-16) 0 0;
  max-width: 24ch;
  font-family: var(--font-body);
  font-size: clamp(var(--fs-24), 1.2rem + 1.8vw, var(--fs-48));
  font-weight: 300;
  line-height: 1.18;
  color: var(--c-ivory);
  text-wrap: balance;
}

@media (max-width: 899px) {
  .owner-band { min-height: 72svh; }
  .owner-band__figure img { object-position: 62% 30%; }
}

/* ===============================================================
   05 · THE MANIFESTO
   Ground: obsidian. Object: an engraved brass plate in the dark.
   The camera starts close and pulls back until the engraving reads.
   =============================================================== */

.manifesto {
  --p: 0;
  background: radial-gradient(60% 50% at 50% 46%, #14161B 0%, var(--c-obsidian) 72%);
  overflow: clip;
}

.manifesto__track { position: relative; height: 260svh; }
.manifesto__viewport { position: sticky; top: 0; height: 100svh; display: grid; place-items: center; }
/* The room the plate is mounted in: the supplied brass photograph, held far
   back with heavy falloff so it reads as architecture, not as an image. */
.manifesto__room { position: absolute; inset: 0; z-index: var(--z-base); overflow: hidden; }

.manifesto__room img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 46%;
  opacity: 0.3;
  transform: scale(calc(1.16 - var(--p) * 0.1));
  filter: saturate(0.5) contrast(1.1) brightness(0.6);
}

.manifesto__room::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(46% 42% at 50% 48%, rgba(9, 10, 12, 0.1), rgba(9, 10, 12, 0.86) 74%),
    linear-gradient(180deg, var(--c-obsidian), transparent 24%, transparent 76%, var(--c-obsidian));
}

.manifesto__stage {
  position: relative;
  z-index: var(--z-raised);
  display: grid;
  place-items: center;
  width: 100%;
  padding-inline: var(--container-pad);
}

/* The plate itself: machined brass, engraved, lit from the upper left. */
.plate {
  position: relative;
  width: min(760px, 66vw);
  padding: clamp(var(--space-40), 7vw, var(--space-128)) clamp(var(--space-32), 6vw, var(--space-96));
  border-radius: var(--r-md);
  background: var(--surface-brass);
  box-shadow:
    var(--shadow-inset-brass),
    0 40px 90px rgba(0, 0, 0, 0.72),
    0 4px 10px rgba(0, 0, 0, 0.5);
  /* Opens full bleed - the engraving cropped and unreadable - and pulls back
     until the whole plate reads, mounted in the dark. */
  transform: scale(calc(2.4 - var(--p) * 1.42)) rotateX(calc((1 - var(--p)) * 7deg));
  transform-origin: center;
  transition: transform 120ms linear;
}

.plate::before {
  content: "";
  position: absolute;
  inset: var(--space-12);
  border: 1px solid rgba(74, 55, 20, 0.5);
  border-radius: var(--r-sm);
  pointer-events: none;
}

.plate__line {
  margin: 0;
  text-align: center;
  /* The statement holds one line; the second line answers it after a beat. */
  white-space: nowrap;
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 96, 'wght' var(--wght-black);
  font-size: clamp(var(--fs-16), 2.9vw, var(--fs-48));
  line-height: 1.02;
  letter-spacing: -0.035em;
  text-transform: uppercase;
  color: #4A3714;
  text-shadow: 0 1px 0 rgba(255, 238, 197, 0.45), 0 -1px 1px rgba(0, 0, 0, 0.5);
}

.plate__line--em { margin-top: var(--space-24); color: #3A2A0D; opacity: 0.86; }

.plate__screw {
  position: absolute;
  width: var(--space-12);
  height: var(--space-12);
  border-radius: var(--r-full);
  background: radial-gradient(circle at 34% 30%, #F0DCAA, #7A5C28 62%, #43310F);
  box-shadow: inset 0 -1px 1px rgba(0,0,0,0.6), 0 1px 2px rgba(0,0,0,0.5);
}

.plate__screw::after {
  content: "";
  position: absolute;
  inset: 40% 18%;
  background: rgba(38, 27, 8, 0.8);
  border-radius: 1px;
  transform: rotate(28deg);
}

.plate__screw--tl { top: var(--space-20); left: var(--space-20); }
.plate__screw--tr { top: var(--space-20); right: var(--space-20); }
.plate__screw--bl { bottom: var(--space-20); left: var(--space-20); }
.plate__screw--br { bottom: var(--space-20); right: var(--space-20); }

.manifesto__meta {
  position: absolute;
  bottom: var(--space-40);
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-object);
  opacity: clamp(0, calc(var(--p) * 2 - 0.6), 1);
  text-align: center;
}

@media (max-width: 899px) {
  .manifesto__track { height: 170svh; }
  /* Tighter top and bottom on a phone: the plate is a plate, not a panel. */
  .plate {
    width: 92vw;
    padding: var(--space-20) var(--space-16);
    transform: scale(calc(1.9 - var(--p) * 0.94));
  }
  .plate::before { inset: var(--space-8); }
  .plate__screw--tl, .plate__screw--tr { top: var(--space-12); }
  .plate__screw--bl, .plate__screw--br { bottom: var(--space-12); }
  .plate__screw--tl, .plate__screw--bl { left: var(--space-12); }
  .plate__screw--tr, .plate__screw--br { right: var(--space-12); }
  .plate__line { font-size: clamp(var(--fs-16), 5.4vw, var(--fs-28)); }
  .plate__line--em { margin-top: var(--space-16); }
  .plate__screw { width: var(--space-8); height: var(--space-8); }
  .manifesto__meta { bottom: var(--space-24); width: 84%; }
}

@media (prefers-reduced-motion: reduce) {
  .manifesto__track { height: auto; padding-block: var(--space-96); }
  .manifesto__viewport { position: relative; height: auto; }
  .plate { transform: none; }
  .manifesto__meta { position: relative; bottom: auto; left: auto; transform: none; margin-top: var(--space-32); opacity: 1; }
}

/* ===============================================================
   06 · THE LEDGER - Own / Earn / Buy
   Ground: warm black. Object: a desk with three trays.
   Ten enquiries, placed one at a time.
   =============================================================== */

.ledger-act {
  position: relative;
  background:
    radial-gradient(60% 40% at 50% 0%, rgba(198, 151, 73, 0.08), transparent 68%),
    linear-gradient(180deg, var(--c-obsidian) 0%, var(--c-charcoal) 32%, #0E1013 100%);
  overflow: clip;
}

.ledger-act__environment {
  position: absolute;
  inset: 0;
  display: grid;
  align-content: center;
  gap: var(--space-8);
  padding-inline: var(--container-pad);
  z-index: var(--z-base);
  opacity: 0.7;
}

.ledger-act__environment span { line-height: 0.82; }
.ledger-act__environment span:nth-child(1) { -webkit-text-stroke-color: rgba(198, 151, 73, 0.10); }
.ledger-act__environment span:nth-child(2) { -webkit-text-stroke-color: rgba(198, 151, 73, 0.1); text-align: center; }
.ledger-act__environment span:nth-child(3) { -webkit-text-stroke-color: rgba(198, 151, 73, 0.1); text-align: right; }

.ledger-desk {
  position: relative;
  z-index: var(--z-raised);
  margin-top: var(--space-48);
  padding: var(--space-24);
  border: 1px solid var(--c-hairline);
  border-radius: var(--r-md);
  background:
    linear-gradient(180deg, rgba(198, 151, 73, 0.05), transparent 30%),
    linear-gradient(180deg, rgba(9, 10, 12, 0.7), rgba(9, 10, 12, 0.9));
  box-shadow: var(--shadow-object);
}

@media (min-width: 900px) { .ledger-desk { padding: var(--space-40); } }

.ledger-desk__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-16);
  padding-bottom: var(--space-20);
  border-bottom: 1px solid var(--c-hairline-faint);
}

.ledger-desk__title { display: flex; align-items: center; gap: var(--space-8); color: var(--c-brass); }

.ledger-desk__progress {
  font-family: var(--font-display);
  font-variation-settings: 'wdth' var(--wdth-numeral), 'wght' 800;
  font-size: var(--fs-24);
  color: var(--c-white);
  font-variant-numeric: tabular-nums;
}

.ledger-desk__progress span { color: var(--c-dim); }

.ledger-desk__instruction {
  max-width: 56ch;
  margin: var(--space-24) 0 0;
  font-size: var(--fs-20);
  line-height: 1.5;
  color: var(--c-paper);
  opacity: 0.9;
}

/* The run of ten: where the visitor is, and what they have recorded. */
.pips {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-8);
  margin: var(--space-24) 0 0;
}

.pip {
  display: grid;
  place-items: center;
  width: var(--space-32);
  height: var(--space-32);
  border-radius: var(--r-sm);
  border: 1px solid var(--c-hairline);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--c-brass-lo);
  transition: border-color var(--dur-base) var(--ease-ui),
              background var(--dur-base) var(--ease-ui),
              color var(--dur-base) var(--ease-ui);
}

.pip.is-current { border-color: var(--c-brass); color: var(--c-brass-hi); box-shadow: 0 0 0 3px rgba(198, 151, 73, 0.12); }
.pip.is-own { background: rgba(198, 151, 73, 0.28); border-color: var(--c-brass); color: var(--c-obsidian); }
.pip.is-earn { background: rgba(125, 187, 162, 0.28); border-color: #7DBBA2; color: var(--c-obsidian); }
.pip.is-buy { background: rgba(196, 138, 150, 0.28); border-color: #C48A96; color: var(--c-obsidian); }

/* The enquiry currently being placed. */
/* The current enquiry reads as one line with its question, aligned to the
   ledger rather than floating in the middle of an empty row. */
.enquiry {
  display: flex;
  align-items: center;
  gap: var(--space-24);
  padding: var(--space-24) 0;
  border-top: 1px solid var(--c-hairline-faint);
  border-bottom: 1px solid var(--c-hairline-faint);
  margin-top: var(--space-24);
}

.chip {
  flex: none;
  display: grid;
  place-items: center;
  align-content: center;
  gap: var(--space-4);
  width: var(--space-96);
  height: var(--space-96);
  border-radius: var(--r-md);
  background: linear-gradient(158deg, #23262D 0%, #16181D 52%, #1E222A 100%);
  border: 1px solid rgba(198, 151, 73, 0.34);
  box-shadow: var(--shadow-object);
  color: var(--c-brass-hi);
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
}

.chip__no {
  font-family: var(--font-display);
  font-variation-settings: 'wdth' var(--wdth-numeral), 'wght' 800;
  font-size: var(--fs-28);
  color: var(--c-white);
  line-height: 1;
}

.chip--flying {
  position: fixed;
  z-index: var(--z-cursor);
  margin: 0;
  pointer-events: none;
  animation: cdm-fly 640ms var(--ease-mech) forwards;
}

/* The enquiry is picked up, carried, and set down in its tray. */
@keyframes cdm-fly {
  0% { transform: translate3d(0, 0, 0) scale(1) rotate(0deg); opacity: 1; }
  38% { transform: translate3d(calc(var(--fx) * 0.44), calc(var(--fy) * 0.3 - 56px), 0) scale(0.82) rotate(calc(var(--fr) * 0.6)); opacity: 1; }
  82% { opacity: 0.9; }
  100% { transform: translate3d(var(--fx), var(--fy), 0) scale(0.3) rotate(var(--fr)); opacity: 0; }
}

.chip__label,
.chip__of {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  color: var(--c-brass);
  opacity: 0.85;
}

.enquiry__hint {
  margin: 0;
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 96, 'wght' 600;
  font-size: var(--fs-20);
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--c-white);
}

/* Three trays: brass, emerald, oxblood. */
.trays { display: grid; gap: var(--space-12); }

@media (min-width: 768px) { .trays { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-16); } }

.tray {
  position: relative;
  display: grid;
  gap: var(--space-8);
  padding: var(--space-20);
  min-height: var(--space-160);
  border-radius: var(--r-sm);
  border: 1px solid var(--tray-line);
  background: var(--tray-bg);
  color: var(--c-paper);
  text-align: left;
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-ui), border-color var(--dur-base) var(--ease-ui), box-shadow var(--dur-base) var(--ease-ui);
}

.tray:hover { transform: translateY(-2px); border-color: var(--tray-edge); box-shadow: 0 12px 28px rgba(0,0,0,0.45); }
.tray:active { transform: translateY(0); }
.tray:focus-visible { outline: 2px solid var(--tray-edge); outline-offset: 3px; }

.tray--own { --tray-bg: linear-gradient(170deg, rgba(198,151,73,0.16), rgba(14,16,19,0.72) 60%, rgba(9,10,12,0.7)); --tray-line: rgba(198,151,73,0.3); --tray-edge: var(--c-brass); }
.tray--earn { --tray-bg: linear-gradient(170deg, rgba(38,74,63,0.34), rgba(14,16,19,0.72) 60%, rgba(9,10,12,0.7)); --tray-line: rgba(111,181,153,0.24); --tray-edge: #7DBBA2; }
.tray--buy { --tray-bg: linear-gradient(170deg, rgba(96,46,58,0.36), rgba(14,16,19,0.72) 60%, rgba(9,10,12,0.7)); --tray-line: rgba(196,138,150,0.22); --tray-edge: #C48A96; }

.tray__head { display: flex; align-items: center; gap: var(--space-8); color: var(--tray-edge); }

.tray__label {
  font-family: var(--font-display);
  font-variation-settings: 'wdth' var(--wdth-condensed), 'wght' var(--wght-black);
  font-size: var(--fs-28);
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--tray-edge);
}

.tray__meaning {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  color: var(--c-dim);
}

.tray__examples { font-size: var(--fs-16); line-height: 1.4; opacity: 0.82; }

.tray__action {
  margin-top: var(--space-8);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  color: var(--tray-edge);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-ui);
}

.tray:hover .tray__action,
.tray:focus-visible .tray__action { opacity: 1; }

.tray__count {
  position: absolute;
  top: var(--space-16);
  right: var(--space-16);
  font-family: var(--font-display);
  font-variation-settings: 'wdth' var(--wdth-numeral), 'wght' 800;
  font-size: var(--fs-24);
  color: var(--tray-edge);
  font-variant-numeric: tabular-nums;
}

/* Placed enquiries stack up physically inside their tray. */
.tray__stack { position: relative; height: var(--space-40); margin-top: auto; }

.tray__slip {
  position: absolute;
  left: 0;
  bottom: 0;
  width: var(--space-32);
  height: var(--space-40);
  border-radius: 2px;
  background: linear-gradient(180deg, var(--tray-edge), rgba(0,0,0,0.4));
  opacity: 0.85;
  box-shadow: 0 2px 6px rgba(0,0,0,0.5);
  animation: cdm-slip 420ms var(--ease-settle) both;
}

@keyframes cdm-slip {
  from { transform: translateY(-24px) rotate(-6deg); opacity: 0; }
  to { transform: none; opacity: 0.85; }
}

.ledger-desk__foot { display: flex; justify-content: space-between; align-items: center; gap: var(--space-16); margin-top: var(--space-20); }

/* The verdict sheet prints out of the desk once ten are placed. */
.verdict {
  position: relative;
  margin-top: var(--space-24);
  background: var(--c-paper);
  color: var(--c-paper-ink);
  border-radius: var(--r-sm);
  padding: var(--space-24);
  box-shadow: var(--shadow-paper);
  animation: cdm-print 900ms var(--ease-mech) both;
}

@media (min-width: 900px) { .verdict { padding: var(--space-40); } }

@keyframes cdm-print {
  from { clip-path: inset(0 0 100% 0); transform: translateY(-8px); }
  to { clip-path: inset(0 0 0 0); transform: none; }
}

.verdict__meta {
  display: flex;
  justify-content: space-between;
  gap: var(--space-12);
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  color: var(--c-brass-ink);
  padding-bottom: var(--space-16);
  border-bottom: 1px solid rgba(20,22,26,0.18);
}

.verdict__tally { display: grid; gap: var(--space-8); margin: var(--space-24) 0; }

@media (min-width: 768px) { .verdict__tally { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-16); } }

.tally { display: flex; align-items: baseline; gap: var(--space-12); padding-left: var(--space-12); border-left: 2px solid var(--tally-c); }
.tally--own { --tally-c: var(--c-brass-ink); }
.tally--earn { --tally-c: var(--c-emerald); }
.tally--buy { --tally-c: var(--c-buy); }

.tally__value {
  font-family: var(--font-display);
  font-variation-settings: 'wdth' var(--wdth-numeral), 'wght' 800;
  font-size: var(--fs-40);
  line-height: 1;
  color: var(--c-paper-ink);
  font-variant-numeric: tabular-nums;
}

.tally__label { font-family: var(--font-mono); font-size: var(--fs-12); letter-spacing: var(--tracking-meta); text-transform: uppercase; color: var(--c-paper-muted); }

.verdict__head {
  margin: 0 0 var(--space-12);
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 96, 'wght' 700;
  font-size: var(--step-h3);
  line-height: 1.14;
  letter-spacing: -0.02em;
  color: var(--c-paper-ink);
}

.verdict__sub { max-width: 58ch; color: var(--c-paper-ink-2); }
.verdict__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-16); margin-top: var(--space-24); }

/* ===============================================================
   07 · THE DOSSIER - a real Wednesday drop
   Ground: charcoal. Object: a private folder, opened for reading.
   Motion stops the moment the document is legible.
   =============================================================== */

.dossier {
  background: linear-gradient(180deg, #0E1013 0%, var(--c-charcoal) 40%, #0D1013 100%);
  overflow: clip;
  padding-bottom: var(--chapter-y-compact);
}

.folder { position: relative; margin-top: var(--space-48); }

.folder__tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-8);
  padding: var(--space-8) var(--space-20);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  background: linear-gradient(180deg, #4A3714, #2C2109);
  border: 1px solid rgba(198, 151, 73, 0.3);
  border-bottom: 0;
  color: var(--c-brass-hi);
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.folder__body {
  position: relative;
  padding: var(--space-16);
  border: 1px solid rgba(198, 151, 73, 0.24);
  border-radius: 0 var(--r-sm) var(--r-sm) var(--r-sm);
  background: linear-gradient(160deg, rgba(74, 55, 20, 0.28), rgba(9, 10, 12, 0.6));
}

.document {
  position: relative;
  background: var(--c-ivory);
  color: var(--c-paper-ink);
  padding: var(--space-32) var(--space-24);
  box-shadow: var(--shadow-paper);
  transform: translateY(var(--space-24)) rotate(-0.4deg);
  opacity: 0;
  transition: transform var(--dur-door) var(--ease-door), opacity var(--dur-slower) var(--ease-editorial);
}

.is-inview .document { transform: none; opacity: 1; }

@media (min-width: 768px) { .document { padding: var(--space-64) var(--space-56); } }

.document__meta {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--space-16);
  padding-bottom: var(--space-16);
  margin-bottom: var(--space-32);
  border-bottom: 1px solid rgba(20, 22, 26, 0.2);
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  color: var(--c-brass-ink);
}

/* Reading is the point here: generous measure, real hierarchy, no motion. */
.document__body { max-width: 62ch; font-size: clamp(var(--fs-16), 0.95rem + 0.35vw, var(--fs-20)); line-height: 1.66; color: #262A30; }
.document__body p { margin-bottom: var(--space-24); }
.document__body p:first-of-type strong { color: var(--c-paper-ink); }
.document__body p:first-of-type::first-letter {
  float: left;
  margin: 6px var(--space-12) 0 0;
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 96, 'wght' 800;
  font-size: 3.2em;
  line-height: 0.78;
  color: var(--c-brass-ink);
}

.document__foot {
  margin-top: var(--space-32);
  padding-top: var(--space-16);
  border-top: 1px solid rgba(20, 22, 26, 0.16);
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  color: var(--c-paper-muted);
  display: flex;
  justify-content: space-between;
  gap: var(--space-12);
}

/* Struck onto the paper itself, centred in the header. */
.document .stamp {
  position: relative;
  justify-self: center;
  margin: 0;
}

.document__subject { justify-self: start; white-space: nowrap; }
.document__when { justify-self: end; text-align: right; white-space: nowrap; }

/* The stamp is a mark on the page, so it never squeezes the metadata. */
.document .stamp { transform: rotate(-7deg) scale(0.86); }
.document .stamp.is-struck { animation: cdm-stamp-doc 520ms var(--ease-mech) forwards; }

@keyframes cdm-stamp-doc {
  0% { transform: rotate(-7deg) scale(2.1); opacity: 0; }
  62% { transform: rotate(-7deg) scale(0.84); opacity: 0.9; }
  78% { transform: rotate(-7deg) scale(0.9); }
  100% { transform: rotate(-7deg) scale(0.86); opacity: 0.72; }
}

@media (max-width: 900px) {
  /* Two rows: subject then date on the left, the stamp held on the right
     inside the paper's own margin rather than hanging off its edge. */
  .document__meta {
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: var(--space-8);
    align-items: start;
  }

  /* The subject holds one line; it is the document's title, not a paragraph. */
  .document__subject {
    grid-column: 1;
    grid-row: 1;
    white-space: nowrap;
    font-size: 11px;
    letter-spacing: 0.1em;
  }
  .document__when { grid-column: 1; grid-row: 2; justify-self: start; text-align: left; }

  .document .stamp {
    grid-column: 2;
    grid-row: 1 / span 2;
    justify-self: end;
    align-self: center;
    transform: rotate(-8deg) scale(0.68);
    transform-origin: right center;
  }

  .document .stamp.is-struck { animation: cdm-stamp-doc-sm 520ms var(--ease-mech) forwards; }

  @keyframes cdm-stamp-doc-sm {
    0% { transform: rotate(-8deg) scale(1.7); opacity: 0; }
    62% { transform: rotate(-8deg) scale(0.66); opacity: 0.9; }
    100% { transform: rotate(-8deg) scale(0.68); opacity: 0.72; }
  }
}

/* ===============================================================
   08 · THE PERSON BEHIND THE DOOR
   Ground: bottle green draining to oxblood and black. Editorial.
   =============================================================== */

.founder {
  position: relative;
  padding-top: var(--chapter-y-compact);
  background:
    radial-gradient(56% 40% at 24% 18%, rgba(198, 151, 73, 0.06), transparent 68%),
    linear-gradient(180deg, #0D1013 0%, var(--c-charcoal) 34%, var(--c-obsidian) 100%);
  overflow: clip;
}

.founder__grid { position: relative; z-index: var(--z-raised); display: grid; gap: var(--space-32); }

@media (min-width: 900px) {
  .founder__grid { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-64); align-items: start; }
  .founder__portrait { position: sticky; top: 12svh; }
}

.founder__portrait { position: relative; }

.portrait {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: var(--r-sm);
  border: 1px solid var(--c-hairline);
  background: var(--c-charcoal);
  box-shadow: var(--shadow-object);
}

.portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Hold the face in frame at every crop. */
  object-position: 50% 18%;
  /* The supplied photograph is graded toward the documentary palette. */
  filter: saturate(0.55) contrast(1.12) brightness(0.82) sepia(0.16);
}

.portrait::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(74% 58% at 24% 22%, rgba(232, 200, 137, 0.22), transparent 62%),
    linear-gradient(180deg, rgba(9,10,12,0.1) 0%, rgba(9,10,12,0.5) 76%, rgba(9,10,12,0.72) 100%);
}

/* The name, set as display type at the head of the writing. */
.founder__name {
  margin: 0 0 var(--space-24);
  font-family: var(--font-display);
  font-variation-settings: 'wdth' var(--wdth-condensed), 'wght' var(--wght-black);
  font-size: clamp(var(--fs-40), 5.4vw, var(--fs-80));
  line-height: 0.9;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  color: var(--c-ivory);
}

.founder__name span { display: block; }
.founder__name span:nth-child(2) { color: var(--c-brass); }

.founder__label { margin-top: var(--space-16); }

.portrait__plate {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--space-24);
  background:
    radial-gradient(120% 90% at 20% 12%, rgba(232, 200, 137, 0.2), transparent 58%),
    linear-gradient(150deg, var(--c-ink-raise) 0%, var(--c-charcoal) 55%, var(--c-obsidian) 100%);
}

.portrait__plate::after { content: ""; position: absolute; inset: var(--space-16); border: 1px solid var(--c-hairline-strong); }
.portrait__eyebrow { position: relative; color: var(--c-brass); margin-bottom: auto; }
.portrait__name {
  position: relative;
  margin: var(--space-20) 0;
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 96, 'wght' 800;
  font-size: var(--step-h3);
  line-height: 0.98;
  letter-spacing: -0.03em;
  color: var(--c-white);
}
.portrait__foot { position: relative; color: var(--c-dim); }

.founder__body { display: grid; gap: var(--space-24); }
.founder__body p { max-width: 58ch; opacity: 0.88; }

.founder__promise {
  margin-top: var(--space-8);
  padding: var(--space-24);
  border-left: 2px solid var(--c-brass);
  background: linear-gradient(90deg, rgba(198,151,73,0.1), transparent 70%);
  font-size: var(--step-lead);
  line-height: 1.4;
  color: var(--c-white);
  max-width: 52ch;
}

.founder__stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-16); margin-top: var(--space-16); padding-top: var(--space-24); border-top: 1px solid var(--c-hairline); }
.founder__stats b { display: block; font-family: var(--font-display); font-variation-settings: 'wdth' var(--wdth-numeral), 'wght' 800; font-size: var(--fs-32); color: var(--c-white); }
.founder__stats span { display: block; margin-top: var(--space-8); font-family: var(--font-mono); font-size: var(--fs-12); letter-spacing: var(--tracking-meta); text-transform: uppercase; color: var(--c-dim); }

/* ===============================================================
   09 · THE APPLICATION
   Ground: warm ivory. Everything decorative stops here.
   =============================================================== */

.application {
  position: relative;
  background: var(--c-ivory);
  color: var(--c-paper-ink);
  padding-block: var(--chapter-y-large);
}

/* The dark world opens like a folder to reveal the page beneath. */
.application::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--space-96));
  left: 0;
  right: 0;
  height: var(--space-96);
  background: var(--c-ivory);
  /* One quiet diagonal: the page beneath the dark world, being uncovered. */
  clip-path: polygon(0 100%, 100% 100%, 100% 22%, 0 78%);
  filter: drop-shadow(0 -12px 24px rgba(9, 10, 12, 0.35));
}

.application__head { position: relative; display: grid; gap: var(--space-24); }

.application__title {
  margin: 0;
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 92, 'wght' var(--wght-black);
  font-size: clamp(var(--fs-40), 1.6rem + 4.4vw, var(--fs-96));
  line-height: 0.94;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  color: var(--c-paper-ink);
}

/* One sentence per line, each held on a single line of its own. */
.application__title-line { display: block; }

@media (max-width: 899px) {
  /* Sized so the longer sentence still holds its own line on a phone. */
  .application__title { font-size: clamp(var(--fs-28), 8.4vw, var(--fs-48)); }
}

@media (min-width: 900px) {
  .application__title-line { white-space: nowrap; }
  .application__title { font-size: clamp(var(--fs-40), 1.2rem + 4vw, var(--fs-80)); }
}

.application__lede { max-width: 52ch; font-size: var(--step-lead); line-height: 1.42; color: var(--c-paper-ink-2); }
.application .chapter-mark { color: var(--c-brass-ink); }
.application .t-meta { color: var(--c-paper-muted); }

.application__grid { display: grid; gap: var(--space-32); }

@media (min-width: 1280px) {
  .application__grid {
    grid-template-columns: minmax(0, 720px) minmax(0, 1fr);
    gap: var(--space-96);
    align-items: start;
  }
  .application__aside { position: sticky; top: var(--space-96); padding-top: var(--space-56); }
}

.application__aside { display: none; }

@media (min-width: 1280px) { .application__aside { display: block; } }

.application__aside-list { margin: 0; border-top: 1px solid var(--c-paper-line); max-width: 320px; }

.application__aside-list > div {
  display: grid;
  gap: var(--space-4);
  padding-block: var(--space-16);
  border-bottom: 1px solid var(--c-paper-line);
}

.application__aside-list dt {
  font-family: var(--font-mono);
  font-size: var(--fs-12);
  letter-spacing: var(--tracking-meta);
  text-transform: uppercase;
  color: var(--c-brass-ink);
}

.application__aside-list dd { margin: 0; font-size: var(--fs-16); color: var(--c-paper-ink-2); }

.application__form { margin-top: var(--space-48); max-width: 720px; }
.application__foot { margin-top: var(--space-24); max-width: 56ch; font-size: var(--fs-16); color: var(--c-paper-muted); }
.application__submit { margin-top: var(--space-32); }

.application__success { max-width: 720px; margin-top: var(--space-40); }
.application__success h3 {
  font-family: var(--font-display);
  font-variation-settings: 'wdth' 92, 'wght' 800;
  font-size: var(--step-h3);
  color: var(--c-paper-ink);
  margin-bottom: var(--space-16);
}
.application__success p { color: var(--c-paper-ink-2); max-width: 56ch; }
.application__success .sheet { margin-top: var(--space-32); }

@media (max-width: 899px) {
  /* The sticky invite dock sits below this, so the page closes tight. */
  .application { padding-bottom: var(--space-48); }
}

/* ===============================================================
   10 · FOOTER
   =============================================================== */

.site-footer {
  background: var(--c-ivory);
  color: var(--c-paper-muted);
  padding-block: var(--space-40) calc(var(--space-40) + var(--safe-b));
  border-top: 1px solid var(--c-paper-line);
}

.site-footer__inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-16); }
.site-footer__mark { display: flex; align-items: center; gap: var(--space-12); color: var(--c-brass-ink); }
.site-footer__mark img { height: var(--space-24); width: auto; }
.site-footer .t-meta { color: var(--c-paper-muted); }

/* Where the correspondence is signed. Brass at rest, lit on approach - the
   same behaviour as every other outbound link in the room. */
.site-footer__social {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  margin: 0;
  padding: 0;
  list-style: none;
}

.site-footer__social a {
  display: grid;
  place-items: center;
  width: var(--space-36, 36px);
  height: var(--space-36, 36px);
  border: 1px solid rgba(198, 151, 73, 0.34);
  border-radius: var(--r-full);
  color: var(--c-brass-ink);
  transition: color var(--dur-base) var(--ease-ui),
              border-color var(--dur-base) var(--ease-ui),
              background-color var(--dur-base) var(--ease-ui);
}

.site-footer__social a:hover,
.site-footer__social a:focus-visible {
  color: var(--c-ink);
  border-color: var(--c-brass);
  background: var(--c-brass);
}

/* The marks are filled shapes, not line drawings like the rest of the set. */
.site-footer__social .icon-brand { display: block; }

@media (max-width: 640px) {
  /* The three lines stack, so the marks take their own row and centre. */
  .site-footer__inner { justify-content: center; text-align: center; }
  .site-footer__social { width: 100%; justify-content: center; }
}
