/* cachemoney landing page: layout and sections. The palette, the type and the fonts are in
   tokens.css, which the wallet at /app reads too, so the two faces are one look with one
   source (D-099). The design handoff is the spec for everything here: colours, type, spacing
   and copy come from it. Static markup and CSS, no framework and no runtime dependency, which
   is what that handoff asks the landing page to be. */

:root { --pad: clamp(20px, 4vw, 48px); }

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

body { font-size: 16px; line-height: 1.5; }

a { color: inherit; text-decoration: none; }
a:hover { color: var(--text); }

h1, h2, h3 { margin: 0; font-weight: 500; }
p { margin: 0; }

/* Every interactive target clears 44px, counting the padding around small links. */
.nav a, .brand { display: inline-flex; align-items: center; min-height: 44px; }

/* Header */

.header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 26px clamp(28px, 5vw, 56px);
}

.brand { gap: 10px; }

/* The mark: a 5 x 2 grid of 5px squares, one lavender leaf at index 3. */
.mark {
  display: grid;
  grid-template-columns: repeat(5, 5px);
  grid-auto-rows: 5px;
  gap: 2px;
}
.mark span { background: rgba(255, 255, 255, 0.16); }
.mark .lit { background: var(--accent); }

.wordmark {
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: 17px;
  letter-spacing: -0.02em;
  text-transform: lowercase;
}

/* `min-width: 0` because a flex item will not shrink below its content otherwise: without it
   the nav kept its full width on a narrow phone and ran off the side, cutting "Wallet, soon"
   to "Wallet, s". Wrapping is what should happen instead. */
.nav { display: flex; flex-wrap: wrap; align-items: center; gap: clamp(16px, 2vw, 28px); min-width: 0; }
/* The X mark and the wallet button, the only two things in the header now. An inline SVG
   rather than an icon font or a hosted sprite: nothing on this page loads from another host
   (D-121). */
.icon-link { display: inline-flex; align-items: center; color: var(--faint); }
.icon-link:hover { color: var(--text); }
.button-ghost {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 0 16px;
  border: 1px solid var(--line-strong);
  color: var(--text);
  font-size: 14px;
}
.button-ghost:hover { border-color: var(--text); }
.nav a { font-size: 14px; color: var(--muted); }

.button-solid {
  min-height: 38px;
  padding: 0 16px;
  background: var(--text);
  color: var(--bg);
  border-radius: var(--radius);
  font-size: 14px;
  font-weight: 500;
}
.button-solid:hover { color: var(--bg); opacity: 0.9; }

/* Page */

.page { max-width: 1440px; margin: 0 auto; padding: 0 var(--pad); }

/* Hero */

.hero {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  gap: clamp(40px, 6vw, 72px);
  align-items: end;
  min-height: clamp(560px, 82svh, 900px);
  padding-bottom: clamp(36px, 5vw, 64px);
  border-bottom: 1px solid var(--line);
}

.hero-say { display: flex; flex-direction: column; gap: clamp(26px, 3vw, 40px); }

h1 {
  font-size: clamp(64px, 11vw, 150px);
  line-height: 0.9;
  letter-spacing: -0.055em;
}

.marker { display: flex; align-items: center; gap: 14px; font-size: clamp(16px, 2vw, 18px); }
.diamond { width: 14px; height: 14px; background: var(--accent); transform: rotate(45deg); flex: none; }

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: clamp(18px, 3vw, 32px); }

.button-accent {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 52px;
  min-width: 220px;
  padding: 0 24px;
  background: var(--accent);
  color: var(--bg);
  border-radius: var(--radius);
  font-size: 16px;
  font-weight: 500;
}
.button-accent:hover { color: var(--bg); opacity: 0.92; }

.button-plain { display: inline-flex; align-items: center; min-height: 44px; font-size: 16px; color: var(--text); }
.button-plain:hover { color: var(--accent-text); }

/* The pool, drawn: one square per leaf, the mark's own geometry at the size the chain says.
   It is the product's whole idea in a picture. Your note is one commitment among the others,
   and when there are few, the picture is small and says so. The lit square is leaf 103, the
   note the receipt in section 03 proves. */
.pool { display: flex; flex-direction: column; gap: 18px; align-self: stretch; justify-content: flex-end; }

.leaves {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9px, 1fr));
  grid-auto-rows: 1fr;
  gap: 4px;
}
.leaves span { aspect-ratio: 1; background: rgba(255, 255, 255, 0.16); }
.leaves .lit {
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(145, 132, 217, 0.22);
}

.pool-count { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; }
.pool-count b {
  font-size: clamp(32px, 4.6vw, 68px);
  line-height: 1;
  letter-spacing: -0.035em;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.pool-count span { font-size: 14px; color: var(--muted); }
.pool-note { font-family: var(--font-mono); font-size: 12px; color: var(--faint); }

/* Leaves drifting through the empty space above the grid. They fade out well before the grid,
   so the drift is weather and never reads as leaves arriving in a pool that has 142 of them.
   The count below is still whatever the pool's own account said at build time. */
.fall {
  position: relative;
  flex: 1 1 auto;
  min-height: 120px;
  overflow: hidden;
  pointer-events: none;
}

/* What falls is a leaf in the protocol's sense, not a botanical one: a single commitment
   square, the same geometry as the mark and as the grid below it. Nothing to draw and nothing
   to recognise. --s is its size, 12px near and 7px far, which is the only depth cue here; --dx
   is how far it wanders on the way down. */
.fall i {
  --leaf: rgba(255, 255, 255, 0.15);
  --s: 12px;
  --dx: 20px;
  --fy: 320px;
  position: absolute;
  top: 0;
  width: var(--s);
  height: var(--s);
  background: var(--leaf);
  animation-name: drift;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

.fall i:nth-child(1) { left: 4%; animation-duration: 15s; animation-delay: -0s; }
.fall i:nth-child(2) { left: 21%; animation-duration: 19.5s; animation-delay: -3.4s; }
.fall i:nth-child(3) { left: 34%; animation-duration: 13.5s; animation-delay: -7.1s; }
.fall i:nth-child(4) { left: 47%; animation-duration: 21s; animation-delay: -1.6s; }
.fall i:nth-child(5) { left: 60%; animation-duration: 16.5s; animation-delay: -9.3s; }
.fall i:nth-child(6) { left: 71%; animation-duration: 14s; animation-delay: -5.2s; }
.fall i:nth-child(7) { left: 82%; animation-duration: 20s; animation-delay: -11.8s; }
.fall i:nth-child(8) { left: 91%; animation-duration: 17.5s; animation-delay: -8s; }
.fall i:nth-child(9) { left: 13%; animation-duration: 18.5s; animation-delay: -14.5s; }
.fall i:nth-child(10) { left: 28%; animation-duration: 16s; animation-delay: -6.4s; }
.fall i:nth-child(11) { left: 55%; animation-duration: 22s; animation-delay: -12.9s; }
.fall i:nth-child(12) { left: 76%; animation-duration: 15.5s; animation-delay: -2.8s; }

/* The far ones: smaller and fainter. */
.fall i:nth-child(3),
.fall i:nth-child(5),
.fall i:nth-child(8),
.fall i:nth-child(9),
.fall i:nth-child(11) {
  --s: 7px;
  --leaf: rgba(255, 255, 255, 0.09);
}

/* One leaf in the accent, the mark's lit leaf loose in the air. Exactly one, ever. */
.fall i.accent {
  --leaf: rgba(145, 132, 217, 0.55);
  --s: 12px;
}

@keyframes drift {
  0% { transform: translate3d(0, -34px, 0); opacity: 0; }
  16% { opacity: 1; }
  58% { opacity: 1; }
  100% { transform: translate3d(var(--dx), var(--fy), 0); opacity: 0; }
}

/* The grid itself: every square answers to the pointer, and the lit one names itself. */
.leaves span { transition: background 140ms ease; }
.leaves span:hover { background: rgba(255, 255, 255, 0.36); }

.leaves .lit {
  position: relative;
  animation: litpulse 5s ease-in-out infinite;
}
.leaves .lit:hover { background: var(--accent); }

@keyframes litpulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(145, 132, 217, 0.18); }
  50% { box-shadow: 0 0 0 6px rgba(145, 132, 217, 0.32); }
}

.leaves .lit::after {
  content: "leaf 103";
  position: absolute;
  bottom: calc(100% + 9px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  padding: 5px 8px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text);
  white-space: nowrap;
  opacity: 0;
  transition: opacity 140ms ease;
  pointer-events: none;
}
.leaves .lit:hover::after { opacity: 1; }

/* Nothing moves for a visitor who asked for no motion: the leaves stay where they are and the
   lit square stops breathing. The hero still says everything it says. */
@media (prefers-reduced-motion: reduce) {
  .fall i,
  .leaves .lit { animation: none; }
}

/* Sections */

.section { padding: clamp(56px, 8vw, 104px) 0; border-bottom: 1px solid var(--line); }

.rule {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 14px;
  margin-bottom: clamp(28px, 4vw, 48px);
  border-bottom: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 12px;
}
.rule .num { color: var(--faint); }
.rule .name { color: var(--text); }

h2 { font-size: clamp(24px, 3vw, 32px); letter-spacing: -0.025em; }

.lede { margin-top: 16px; max-width: 68ch; color: var(--muted); font-size: 15px; line-height: 1.6; }

/* 01, the film */

.film { border: 1px solid var(--line); }
.film video { display: block; width: 100%; aspect-ratio: 16 / 9; background: var(--bg); }
.caption { margin-top: 14px; font-family: var(--font-mono); font-size: 12px; color: var(--faint); }

/* 02, how it works: the flow as one strip, and the refusal that stops it.

   Four boxes of prose was a table pretending to be a diagram, and it buried the one thing
   nothing else here does: the send the wallet declines. So the three moves run along a single
   track, wallet to pool to a new address, and a fourth beat halts against the check that sits
   between the wallet and the pool. The strip freezes there and holds for a quarter of the loop,
   because the stop is the product.

   One clock drives every element, `--flow` below, so the beats cannot drift apart
   and no script is involved. The accent means one thing throughout: a real note. The refused
   send is hollow and stays hollow. */

/* The strip is a centred block, so its heading centres with it rather than sitting off to one
   side of it. Section 03 keeps its left-aligned h2; that one heads a full-width card. */
#how h2 { text-align: center; }

/* The loop's one speed. Every animation below reads it, so the beats cannot drift apart and
   the whole strip changes pace from here. 26s, not the design's 18s: the owner asked for slower
   and a caption has to be readable before its beat ends (D-127). */
.flow { --flow: 26s; margin: clamp(28px, 4vw, 44px) auto 0; max-width: 900px; }

.track { position: relative; height: 96px; }

/* Two rails, stopping short of the stations so the squares sit on a line and not inside it. */
.track::before,
.track::after {
  content: "";
  position: absolute;
  top: 50%;
  height: 1px;
  background: var(--line);
}
.track::before { left: 22px; width: calc(50% - 77px); }
.track::after { left: calc(50% + 55px); right: 22px; }

.node {
  position: absolute;
  top: 50%;
  width: 16px;
  height: 16px;
  margin-top: -8px;
}
.node-wallet { left: 0; background: rgba(255, 255, 255, 0.3); }

/* Empty until something arrives. */
.node-out {
  right: 0;
  box-sizing: border-box;
  border: 1px solid var(--line-strong);
  animation: node-out var(--flow) linear infinite;
}

/* The pool, the same geometry as the mark and the hero grid. Two leaves light per payment,
   because two outputs go out every time. */
.poolgrid {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  grid-template-columns: repeat(7, 11px);
  grid-auto-rows: 11px;
  gap: 4px;
}
.poolgrid span { background: rgba(255, 255, 255, 0.16); }
.poolgrid .a { animation: leaf-a var(--flow) linear infinite; }
.poolgrid .b { animation: leaf-b var(--flow) linear infinite; }

/* The check that runs before every send, drawn where it runs. Faint while a good note passes
   through it, lit when it stops one. */
.wall {
  position: absolute;
  left: 30%;
  top: 50%;
  width: 1px;
  height: 30px;
  margin-top: -15px;
  background: var(--muted);
  opacity: 0.22;
  animation: wall var(--flow) linear infinite;
}

.note {
  position: absolute;
  top: 50%;
  width: 13px;
  height: 13px;
  margin-top: -6.5px;
  background: var(--accent);
  opacity: 0;
}
.note-in { animation: note-in var(--flow) linear infinite; }
.note-out { animation: note-out var(--flow) linear infinite; }

/* Hollow: it never became a note. */
.note-stop {
  background: transparent;
  box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.45);
  animation: note-stop var(--flow) linear infinite;
}

@keyframes note-in {
  0% { left: 22px; opacity: 0; }
  2% { left: 22px; opacity: 1; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); }
  13% { left: calc(50% - 59px); opacity: 1; }
  16%, 100% { left: calc(50% - 53px); opacity: 0; }
}

@keyframes note-out {
  0%, 45% { left: calc(50% + 53px); opacity: 0; }
  47% { left: calc(50% + 53px); opacity: 1; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); }
  57% { left: calc(100% - 35px); opacity: 1; }
  60%, 100% { left: calc(100% - 29px); opacity: 0; }
}

/* Out of the wallet, then a hard deceleration into the check, then nothing for the rest of the
   loop. The holding is the whole point: do not shorten it. */
@keyframes note-stop {
  0%, 67% { left: 22px; opacity: 0; }
  69% { left: 22px; opacity: 1; animation-timing-function: cubic-bezier(0.1, 0.75, 0.2, 1); }
  75%, 96% { left: calc(30% - 18px); opacity: 1; }
  98%, 100% { left: calc(30% - 18px); opacity: 0; }
}

@keyframes leaf-a {
  0%, 15% { background: rgba(255, 255, 255, 0.16); }
  19%, 96% { background: var(--accent); }
  99%, 100% { background: rgba(255, 255, 255, 0.16); }
}
@keyframes leaf-b {
  0%, 19% { background: rgba(255, 255, 255, 0.16); }
  23%, 96% { background: var(--accent); }
  99%, 100% { background: rgba(255, 255, 255, 0.16); }
}

@keyframes node-out {
  0%, 57% { background: transparent; border-color: var(--line-strong); }
  60%, 96% { background: var(--accent); border-color: var(--accent); }
  99%, 100% { background: transparent; border-color: var(--line-strong); }
}

@keyframes wall {
  0%, 5% { opacity: 0.22; }
  9%, 13% { opacity: 0.7; }
  18%, 68% { opacity: 0.22; }
  72%, 96% { opacity: 1; }
  99%, 100% { opacity: 0.22; }
}

.stations {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--faint);
}
.stations span:nth-child(2) { text-align: center; }
.stations span:nth-child(3) { text-align: right; }

.beats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 26px;
  margin-top: clamp(22px, 3vw, 30px);
  font-family: var(--font-mono);
  font-size: 12px;
}
.beats span {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--faint);
}
.beats span::before {
  content: "";
  width: 6px;
  height: 6px;
  background: rgba(255, 255, 255, 0.2);
}
.beats .b1 { animation: beat1 var(--flow) linear infinite; }
.beats .b2 { animation: beat2 var(--flow) linear infinite; }
.beats .b3 { animation: beat3 var(--flow) linear infinite; }
.beats .b4 { animation: beat4 var(--flow) linear infinite; }
.beats .b1::before { animation: dot1 var(--flow) linear infinite; }
.beats .b2::before { animation: dot2 var(--flow) linear infinite; }
.beats .b3::before { animation: dot3 var(--flow) linear infinite; }
.beats .b4::before { animation: dot4 var(--flow) linear infinite; }

@keyframes beat1 { 0% { color: var(--faint); } 2%, 19% { color: var(--text); } 21%, 100% { color: var(--faint); } }
@keyframes beat2 { 0%, 21% { color: var(--faint); } 23%, 43% { color: var(--text); } 45%, 100% { color: var(--faint); } }
@keyframes beat3 { 0%, 45% { color: var(--faint); } 47%, 65% { color: var(--text); } 67%, 100% { color: var(--faint); } }
@keyframes beat4 { 0%, 67% { color: var(--faint); } 69%, 96% { color: var(--text); } 98%, 100% { color: var(--faint); } }

@keyframes dot1 { 0% { background: rgba(255, 255, 255, 0.2); } 2%, 19% { background: var(--accent); } 21%, 100% { background: rgba(255, 255, 255, 0.2); } }
@keyframes dot2 { 0%, 21% { background: rgba(255, 255, 255, 0.2); } 23%, 43% { background: var(--accent); } 45%, 100% { background: rgba(255, 255, 255, 0.2); } }
@keyframes dot3 { 0%, 45% { background: rgba(255, 255, 255, 0.2); } 47%, 65% { background: var(--accent); } 67%, 100% { background: rgba(255, 255, 255, 0.2); } }

/* The fourth beat never lights lavender. Nothing became a note. */
@keyframes dot4 { 0%, 67% { background: rgba(255, 255, 255, 0.2); } 69%, 96% { background: rgba(255, 255, 255, 0.55); } 98%, 100% { background: rgba(255, 255, 255, 0.2); } }

/* One line at a time, in a slot tall enough for the longest so nothing below it moves. All four
   are real text in the document, in order, whether or not they are the one showing. */
.says {
  position: relative;
  min-height: 78px;
  margin: 18px auto 0;
  max-width: 68ch;
  text-align: center;
}
.says p {
  position: absolute;
  inset: 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--muted);
  opacity: 0;
}
.says b { color: var(--text); font-weight: 500; }
.says .s1 { animation: say1 var(--flow) linear infinite; }
.says .s2 { animation: say2 var(--flow) linear infinite; }
.says .s3 { animation: say3 var(--flow) linear infinite; }
.says .s4 { animation: say4 var(--flow) linear infinite; }

/* Each line is fully out before the next starts in, so two sentences are never superimposed:
   they share one box, and a cross-dissolve there is unreadable. The ~0.36s of nothing between
   beats is deliberate. Beat labels and dots use the same windows so a label never names a line
   other than the one showing. */
@keyframes say1 { 0% { opacity: 0; } 2%, 19% { opacity: 1; } 21%, 100% { opacity: 0; } }
@keyframes say2 { 0%, 21% { opacity: 0; } 23%, 43% { opacity: 1; } 45%, 100% { opacity: 0; } }
@keyframes say3 { 0%, 45% { opacity: 0; } 47%, 65% { opacity: 1; } 67%, 100% { opacity: 0; } }
@keyframes say4 { 0%, 67% { opacity: 0; } 69%, 96% { opacity: 1; } 98%, 100% { opacity: 0; } }

/* No motion: the finished strip, and all four lines at once. The refused send is not drawn,
   because a still frame cannot show a thing stopping; the check stays lit and the last line
   says what it does. */
@media (prefers-reduced-motion: reduce) {
  .note, .wall, .poolgrid span, .node-out,
  .beats span, .beats span::before, .says p { animation: none; }
  .note { display: none; }
  .poolgrid .a, .poolgrid .b { background: var(--accent); }
  .node-out { background: var(--accent); border-color: var(--accent); }
  .wall { opacity: 1; }
  .beats span { color: var(--muted); }
  .says { min-height: 0; display: grid; gap: 14px; }
  .says p { position: static; opacity: 1; }
}

/* 03, the receipt */

.verdict {
  margin-top: clamp(28px, 4vw, 44px);
  padding: clamp(20px, 3vw, 28px);
  border: 1px solid var(--accent-border);
  background: var(--accent-bg);
  border-radius: var(--radius);
}
.verdict-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 16px; }
.yes { font-size: 32px; font-weight: 500; color: var(--accent-text); letter-spacing: -0.02em; }
.claim { font-size: 16px; }

.rows {
  display: grid;
  grid-template-columns: minmax(96px, 120px) minmax(0, 1fr);
  gap: 10px 20px;
  margin: clamp(20px, 3vw, 28px) 0 0;
}
.rows dt { font-size: 13px; color: var(--muted); }
.rows dd { margin: 0; font-family: var(--font-mono); font-size: 12px; word-break: break-all; }
.rows dd a { color: var(--accent-text); text-decoration: underline; text-underline-offset: 2px; }

.verdict-foot {
  margin-top: clamp(20px, 3vw, 28px);
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-size: 13px;
  line-height: 20px;
  color: var(--faint);
}

/* Not a link and not a button: the wallet is not here yet and the page does not pretend. */
.soon { font-family: var(--font-mono); font-size: 13px; color: var(--faint); }

/* The constants, once, in a line: they belong to the protocol and not to the hero. */
.spec {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 26px;
  padding: 22px 0;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--faint);
}
.spec b { color: var(--muted); font-weight: 400; }

/* The one qualifying sentence the page owes, where a reader who got this far will see it. */
.honest { padding: 18px 0 0; max-width: 68ch; font-size: 14px; line-height: 22px; color: var(--faint); }

/* Footer */

.footer { max-width: 1440px; margin: 0 auto; padding: clamp(32px, 5vw, 56px) var(--pad) clamp(40px, 6vw, 72px); }
.footer-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; }
.disclaimer { margin-top: clamp(20px, 3vw, 32px); font-family: var(--font-mono); font-size: 12px; line-height: 20px; color: var(--faint); }

/* Narrow. Most first visitors arrive here, so this is a designed layout and not a fallback.

   What changes, and why:

   - The hero's rows stop stretching. The desktop hero is one tall row and leans on that: the
     drift field takes the leftover height, which is what makes it as tall as the viewport
     allows. Stacked, the same rule hands half the free height to the headline's row and the
     words float in dead air. Here the rows are content-sized and the whole block is anchored to
     the bottom, which is where the desktop anchors it too.
   - The drift becomes a fixed band between the headline and the grid, and the story is better
     than the desktop one: squares fall out of the words and into the pool they belong to. Eight
     of them, not twelve, because the field is 350px wide instead of 600 and the same count
     reads as a swarm.
   - The headline drops to a clamp that survives a 320px phone. "Private" at 64px mono is 269px
     of glyph, which is the whole screen minus the padding, and one more character would clip.
   - The nav links go. Four anchors to sections of a page you reach by scrolling, wrapping onto
     their own line under the brand, are noise; the brand and the one action stay.
   - The film button goes full width, because it is the only thing to press. */
@media (max-width: 600px) {
  .header { padding: 20px var(--pad); }
  .nav { display: none; }

  .hero {
    align-content: end;
    gap: 32px;
    min-height: clamp(520px, 88svh, 760px);
  }

  h1 { font-size: clamp(44px, 13.5vw, 64px); }

  .hero-say { gap: 24px; }

  .actions { gap: 16px; }
  .button-accent { width: 100%; min-width: 0; }

  /* A band, not a column that grows: the rows are content-sized now, so the field has to name
     its own height. */
  .fall { flex: none; height: 84px; min-height: 0; }
  .fall i:nth-child(n + 9) { display: none; }

  /* No hover on a phone, so the lit leaf says which one it is in the line below the grid. */
  .leaves .lit::after { display: none; }
}

/* Narrow: the figures stay a 2 x 2 so the quadrant rules keep their meaning. */
@media (max-width: 480px) {
  .figure { padding: 18px 14px; }
  .rows { grid-template-columns: 1fr; gap: 4px 0; }
  .rows dd { margin-bottom: 8px; }
}

/* The 404. The hero's drift on its CSS lanes behind a mark and one line: no count, no receipt,
   nothing that can go stale, and nothing a script has to start (D-127). */
.notfound {
  position: relative;
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 18px;
  min-height: 100svh;
  padding: var(--pad);
  text-align: center;
}
.notfound .fall {
  position: absolute;
  inset: 0;
  flex: none;
  min-height: 0;
  z-index: 0;
}
.notfound > :not(.fall) { position: relative; z-index: 1; }
.notfound .label { font-family: var(--font-mono); color: var(--faint); }
