/* TripStacker site v2 · the editorial section system.
   Loaded AFTER site.css and lens.css, so rules here win on ties.
   Everything is built from the tokens already declared in site.css.
   Motion is timing-only, var(--ease). No red, no mint. */

/* ============================================================
   0 · shared primitives
   ============================================================ */

/* the page-wide hairline grid.
   z-index:-1 keeps it under every background and under all text
   (painting step 2 of the root stacking context), and it never
   takes a pointer event, so the Lens hero keeps receiving them. */
.grid-lines {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
.grid-lines::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(1080px, 100%);
  background-image:
    linear-gradient(var(--hairline), var(--hairline)),
    linear-gradient(var(--hairline), var(--hairline)),
    linear-gradient(var(--hairline), var(--hairline));
  background-size: 1px 100%;
  background-position: 25% 0, 50% 0, 75% 0;
  background-repeat: no-repeat;
}
@media (max-width: 1024px) {
  .grid-lines::before {
    background-image: linear-gradient(var(--hairline), var(--hairline));
    background-position: 50% 0;
  }
}
@media (max-width: 640px) {
  .grid-lines { display: none; }
}

/* the hero paints its own wash so the grid does not fight the
   halftone dots. Flat wash1 is within ~1 rgb unit of the body
   gradient at this scroll depth, so nothing visibly changes. */
.hero { background: var(--wash1); }

/* opaque sections hide the fixed grid, so they carry their own */
.pacific { position: relative; }
.pacific > .wrap { position: relative; z-index: 1; }
.pacific::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(1080px, 100%);
  pointer-events: none;
  background-image:
    linear-gradient(var(--p-hairline), var(--p-hairline)),
    linear-gradient(var(--p-hairline), var(--p-hairline)),
    linear-gradient(var(--p-hairline), var(--p-hairline));
  background-size: 1px 100%;
  background-position: 25% 0, 50% 0, 75% 0;
  background-repeat: no-repeat;
}
@media (max-width: 1024px) {
  .pacific::before {
    background-image: linear-gradient(var(--p-hairline), var(--p-hairline));
    background-position: 50% 0;
  }
}
@media (max-width: 640px) { .pacific::before { display: none; } }

/* line art shared by every section illustration */
.art {
  width: 100%;
  height: auto;
  color: var(--accent);
  overflow: visible;
}
.art .cy { color: var(--cyan); }
.art .soft { opacity: 0.42; }

/* ============================================================
   1 · scroll reveal
   CSS default is VISIBLE. The bare [data-reveal] selector carries no
   opacity declaration anywhere in the build; the only rule that hides
   is [data-reveal].pre-reveal, and js/scroll.js adds that class only
   after it has confirmed it is running. So a script 404, a parse
   error, a CSP block, a missing IntersectionObserver, reduced motion,
   or this stylesheet itself failing to load ALL leave every element
   visible. scroll.js also carries a load-time backstop that clears
   any element the observer never reached.
   ============================================================ */

[data-reveal].pre-reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: none;
}
[data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  transition: opacity 600ms var(--ease), transform 600ms var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  [data-reveal].pre-reveal,
  [data-reveal].is-revealed {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ============================================================
   2 · the floating pill nav (home only)
   Additive: .site-header and .site-header.static-header keep every
   rule they already have, for the subpages.
   ============================================================ */

.pill-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
  padding: 16px 0;
  /* the bar itself never swallows a pointer event; only its links do.
     That keeps the Lens hero tracking under the nav. js/scroll.js
     bridges the remaining link hit boxes back to the hero. */
  pointer-events: none;
}
.pill-header > .wrap { display: block; }
.pill-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  width: 100%;
  max-width: 920px;
  margin: 0 auto;
  padding: 8px 8px 8px 20px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--r-pill);
  box-shadow: var(--shadow-nav);
  transition: box-shadow 250ms var(--ease);
  pointer-events: none;
}
.pill-header.is-scrolled .pill-bar {
  box-shadow: var(--shadow-nav-scrolled);
}
.pill-bar a { pointer-events: auto; }
.pill-bar .brand-lockup { font-size: 1rem; flex-shrink: 0; }
.pill-bar .brand-lockup .bm { width: 26px; height: 26px; }
.pill-links { gap: 24px; }
/* the CTA lives outside .site-nav here, so .site-nav .nav-cta does not
   reach it. This rule carries the whole button. */
.pill-bar > .nav-cta {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  white-space: nowrap;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--on-accent);
  background: var(--grad-cta);
  box-shadow: var(--shadow-cta-sm);
  padding: 12px 20px;
  border-radius: var(--r-pill);
  transition: box-shadow 150ms var(--ease);
}
.pill-bar > .nav-cta:hover {
  color: var(--on-accent);
  text-decoration: none;
  box-shadow: var(--shadow-cta-sm-hover);
}
@media (max-width: 860px) {
  .pill-links { gap: 16px; }
  .pill-bar { padding-left: 16px; }
}
/* The home page is roughly 16,300px tall at 375px. Hiding every section link
   below 640 left the footer as the only route to Pricing or the FAQ, on the
   one device where the page is longest. So the links thin out by measured
   width instead of vanishing at a single breakpoint: the two long labels go
   first, then Questions, and only under 360 is the bar genuinely too narrow
   to hold brand + one link + CTA. */
@media (max-width: 640px) {
  /* site.css hides every .site-nav link at this width for the subpage header.
     The pill nav keeps some, so it has to out-specify that rule. inline-flex,
     not inline: the 44px tap floor from site.css has to survive here. */
  .pill-header .pill-links a:not(.nav-cta) { display: inline-flex; font-size: 0.82rem; }
  .pill-header .pill-links a.pill-link-wide { display: none; }
  .pill-links { gap: 14px; }
  .pill-bar { padding: 6px 6px 6px 16px; gap: 12px; }
  /* 12px, not 9px: at 9px the CTA measured 39px tall, under the 44px floor. */
  .pill-bar > .nav-cta { padding: 12px 16px; font-size: 0.82rem; }
}
@media (max-width: 460px) {
  .pill-header .pill-links a.pill-link-mid { display: none; }
  .pill-bar { gap: 10px; }
  .pill-bar .brand-lockup { font-size: 0.94rem; }
  .pill-bar .brand-lockup .bm { width: 24px; height: 24px; }
}
@media (max-width: 359px) {
  .pill-header .pill-links a:not(.nav-cta) { display: none; }
}

/* ============================================================
   3 · SECTION A · #watch, the pinned three panel stage

   Default (no JS, narrow viewport, reduced motion) = three stacked
   blocks. The pin is opt-in via .pin-ready on <html>, stamped by a
   tiny inline script in <head> so the 300vh track exists on FIRST
   PAINT: fragment navigation (/#pricing, /#faq) and scroll
   restoration then resolve against the final geometry instead of a
   layout that is about to grow by two viewports.

   js/scroll.js owns the class from then on (resize, media-query
   change) and the head script withdraws it if scroll.js never comes
   up, so there is never a tall track with nothing painting it.
   ============================================================ */

.watch-track { position: relative; }

.watch-stage {
  display: block;
  padding: 0;
}

.watch-panel {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  align-items: center;
  gap: 56px;
  padding: 72px 0;
  border-top: 1px solid var(--hairline);
}
.watch-panel:first-of-type { border-top: none; }
.watch-panel .kicker { display: block; margin-bottom: 14px; }
.watch-panel .serif-h {
  font-size: clamp(2rem, 5vw, 3.1rem);
  margin-bottom: 16px;
}
.watch-panel .section-sub { font-size: 1.05rem; }
/* margin-left:auto cancels grid stretch, so an explicit width is needed
   or the svg falls back to its 300px intrinsic default */
.watch-art { width: 100%; max-width: 380px; margin-left: auto; }

.watch-progress {
  display: flex;
  gap: 10px;
  justify-content: center;
  padding-bottom: 8px;
}
.watch-bar {
  position: relative;
  width: 52px;
  height: var(--s-1);
  background: var(--meter-track);
  border-radius: var(--r-meter);
  overflow: hidden;
}
.watch-bar::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 300ms var(--ease);
}
.watch-bar.is-on::after { transform: scaleX(1); }

/* --- pinned mode (desktop, motion allowed) --- */
.pin-ready .watch-track { height: 300vh; }
.pin-ready .watch-track .watch-stage {
  position: sticky;
  top: 0;
  height: 100vh;   /* fallback: the track is sized in vh */
  height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow: hidden;
}
.pin-ready .watch-track .watch-panels {
  position: relative;
  flex: 1;
  min-height: 0;
  /* .wrap carries margin:0 auto, and an auto cross-axis margin cancels
     flex stretch. Without an explicit width this collapses to the
     padding box, because every panel inside is absolutely positioned. */
  width: 100%;
}
.pin-ready .watch-track .watch-panel {
  position: absolute;
  inset: 0;
  /* inset:0 resolves against the padding box, so the panel has to carry
     the .wrap gutter itself or the copy touches the viewport edge
     between 721px and 1128px */
  padding: 96px 24px 40px;
  border-top: none;
  opacity: 0;
  align-content: center;
}
.pin-ready .watch-track .watch-panel.is-front { z-index: 2; }
/* pre-first-frame state. .pin-ready is stamped in <head> but the first paint
   pass runs on the next rAF, which never arrives while the tab is hidden.
   Panel one holds the stage until then, so the section is never blank. */
.pin-ready .watch-track .watch-panel:first-of-type { opacity: 1; }
.pin-ready .watch-track .watch-progress { padding-bottom: 40px; }

/* the stacked fallback never shows the progress bars */
.watch-track:not(.pin-on) .watch-progress { display: none; }

/* Abandon the pin entirely on narrow viewports and under reduced motion.
   The head script refuses to stamp .pin-ready in either case and js/scroll.js
   refuses to keep it, so this block should never be load-bearing. It is here
   for the one case those two cannot cover: js/scroll.js writes INLINE opacity
   and transform on each panel while painting, and if the viewport narrows on a
   code path where neither the resize handler nor the media-query listener
   fires (Safari <= 13 has no MediaQueryList.addEventListener; a bfcache
   restore can skip both), those inline values survive. A class selector loses
   to an inline style, so !important is correct here and only here: without it
   the "fallback" leaves roughly 1,000px of invisible but scrollable panels. */
@media (max-width: 720px), (prefers-reduced-motion: reduce) {
  .watch-track,
  .pin-ready .watch-track { height: auto !important; }
  .pin-ready .watch-track .watch-stage {
    position: static;
    height: auto;
    display: block;
    overflow: visible;
  }
  .pin-ready .watch-track .watch-panels { width: auto; }
  .watch-track .watch-panel,
  .pin-ready .watch-track .watch-panel {
    position: static;
    opacity: 1 !important;
    transform: none !important;
    padding: 72px 0;
    border-top: 1px solid var(--hairline);
  }
  .watch-track .watch-panel:first-of-type,
  .pin-ready .watch-track .watch-panel:first-of-type { border-top: none; }
  .watch-track .watch-progress,
  .pin-ready .watch-track .watch-progress { display: none; }
}

@media (max-width: 720px) {
  .watch-track .watch-panel,
  .pin-ready .watch-track .watch-panel {
    grid-template-columns: 1fr;
    gap: 32px;
    padding: 56px 0;
  }
  .watch-art { max-width: 300px; margin: 0; }
}

/* ============================================================
   4 · SECTION B · #how, the numbered steps
   ============================================================ */

.steps { display: grid; gap: 0; }

.step-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 64px;
  padding: 64px 0;
  border-top: 1px solid var(--hairline);
}
.step-row:first-child { border-top: none; padding-top: 40px; }

.step-copy { max-width: 30em; }
.step-index {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  display: block;
  margin-bottom: 14px;
}
.step-title {
  font-size: clamp(1.35rem, 2.8vw, 1.75rem);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
  line-height: 1.22;
  margin-bottom: 8px;
}
/* editorial sub-headlines, not labels. The mono-uppercase slot on this row is
   already taken by .step-index, which earns it; putting four written lines
   through the same treatment renders them as machine output. */
.step-sub {
  font-family: var(--sans);
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--ink3-text);
  margin-bottom: 14px;
}
.step-copy p.step-text {
  color: var(--ink2);
  font-size: 1rem;
}
.step-art { max-width: 340px; width: 100%; }

/* alternate: even rows put the art on the left */
.step-row.flip .step-copy { order: 2; }
.step-row.flip .step-art { order: 1; margin-right: auto; }
.step-row:not(.flip) .step-art { margin-left: auto; }

@media (max-width: 720px) {
  .step-row {
    grid-template-columns: 1fr;
    gap: 28px;
    padding: 48px 0;
  }
  .step-row.flip .step-copy { order: 0; }
  .step-row.flip .step-art { order: 0; margin-right: 0; }
  .step-row:not(.flip) .step-art { margin-left: 0; }
  .step-art { max-width: 280px; }
}

/* ============================================================
   5 · SECTION C · #pricing
   ============================================================ */

.price-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  align-items: stretch;
}
@media (max-width: 1040px) { .price-grid { gap: 16px; } }
/* margin-inline is load-bearing, not decoration: without it the 520px column
   pins to the left of a 705px content area and leaves a 185px dead gutter down
   the right of all three cards at tablet width. */
@media (max-width: 900px) { .price-grid { grid-template-columns: 1fr; max-width: 520px; margin-inline: auto; } }

.price-card {
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
  box-shadow: var(--shadow-card);
  padding: 30px 26px 28px;
}
@media (min-width: 901px) and (max-width: 1040px) {
  .price-card { padding: 26px 20px 24px; }
  .price-list li { font-size: 0.86rem; }
}
/* an h3 so the three plans are reachable by heading navigation. The kicker
   treatment is unchanged; font-weight is pinned so the h3 default does not
   bolden it. */
.price-name {
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 16px;
}
/* 0.18em of tracking pads a plain hyphen on both sides until CARRY-ON reads as
   though it carried an em dash. The character is a hyphen (0x2d) and always
   was; only the spacing lies, so the fix is spacing. */
.tight-hyphen { letter-spacing: 0; margin-inline: -0.05em; }

/* Three cards at identical weight with nothing named is not restraint, it is
   an undecided page. Business Class carries a little more presence because it
   is where the 10x guarantee begins, which is a fact about the plan and not a
   popularity claim: there are no customers to count yet. */
.price-card-lead {
  border-color: rgb(var(--accent-rgb) / 0.28);
  box-shadow: var(--shadow-hero);
}
.price-flag {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--pill-bg);
  border-radius: var(--r-pill);
  padding: 5px 12px;
  align-self: flex-start;
  margin-bottom: 16px;
}
/* The other two cards carry the same element, emptied, so the three price rows
   line up off one measurement instead of a hardcoded padding that drifts the
   moment the flag's type changes. Below 900px the cards stack and there is
   nothing left to align, so the spacer goes. */
.price-flag-empty { visibility: hidden; }
@media (max-width: 900px) { .price-flag-empty { display: none; } }
/* Inter 800 with tabular figures, matching design/mockups/Paywall.dc.html.
   A price is data, not a verdict, so it stays out of the serif. */
.price-now {
  font-family: var(--sans);
  font-weight: 800;
  font-size: 2.5rem;
  line-height: 1;
  color: var(--ink);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.price-per {
  font-family: var(--sans);
  font-size: 1rem;
  font-weight: 500;
  color: var(--ink2);
  letter-spacing: 0;
}
.price-was {
  font-size: 0.85rem;
  color: var(--ink3-text);
  margin-top: 8px;
}
.price-sub {
  font-size: 0.85rem;
  color: var(--ink2);
  margin-top: 10px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--hairline);
}
.price-list {
  list-style: none;
  display: grid;
  gap: 11px;
  margin-top: 20px;
}
.price-list li {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 0.9rem;
  color: var(--ink2);
  line-height: 1.5;
}
/* The tick is drawn, not typed. U+2713 is in none of the four font files, so
   the character form resolved through a system fallback and every one of
   these rows set its marker in a different face from its own sentence, at a
   weight and size that changed with the reader's platform.

   Drawn, it needs its own vertical placement: the row is 0.9rem at 1.5, so
   the first line box is 21.6px and a 13px mark centres on it at 4px down. */
.price-list .tick {
  color: var(--accent);
  width: 13px;
  height: 13px;
  margin-top: 4px;
  flex-shrink: 0;
}
.price-list li.price-lead {
  color: var(--ink);
  font-weight: 600;
  padding-bottom: 2px;
}

.price-foot {
  margin-top: 36px;
  padding: 26px 28px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
}
.price-foot .price-promise {
  font-family: var(--serif);
  font-size: clamp(1.1rem, 2.4vw, 1.35rem);
  font-weight: 500;
  color: var(--ink);
  line-height: 1.35;
  margin-bottom: 10px;
}
/* a sentence with a link in it, so Inter. See .guarantee-foot. */
.price-elig {
  font-family: var(--sans);
  font-size: 0.8rem;
  color: var(--ink3-text);
}
.price-elig a { color: var(--accent); }
.price-fine {
  font-size: 0.8rem;
  color: var(--ink3-text);
  margin-top: 18px;
}

/* ============================================================
   6 · SECTION D · #faq
   ============================================================ */

.faq-list {
  max-width: 780px;
  border-top: 1px solid var(--hairline);
}
.faq-item { border-bottom: 1px solid var(--hairline); }
.faq-item > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 22px 2px;
  cursor: pointer;
  list-style: none;
  font-size: 1.02rem;
  font-weight: 600;
  color: var(--ink);
  transition: color 150ms var(--ease);
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary:hover { color: var(--accent); }
.faq-item > summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-focus);
}
.faq-chev {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--accent);
  transition: transform 250ms var(--ease);
}
.faq-item[open] > summary .faq-chev { transform: rotate(180deg); }
.faq-body {
  padding: 0 2px 24px;
  max-width: 44em;
}
.faq-body p {
  color: var(--ink2);
  font-size: 0.95rem;
  line-height: 1.7;
}
.faq-body p + p { margin-top: 10px; }

/* ============================================================
   7 · SECTION E · #close, the gradient field

   Two stops only, and they are the two ratified ones: theme3 Cerulean
   accentGrad is cyan -> accent, nothing else. The extra depth comes
   from the scrim's alpha, not from invented darker stops, so an
   accent change in theme3 carries through here instead of leaving
   this section behind on a colour nobody signed off.

   The scrim is also load-bearing for contrast: white on bare cyan is
   2.4:1. Over rgb(10,20,24) at .36 the cyan corner measures 4.86:1
   and the accent end 8.98:1, so every white line in the block clears
   AA including the 0.72rem kicker.
   ============================================================ */

.close-field {
  position: relative;
  padding: var(--s-section) 0;
  text-align: center;
  color: var(--on-accent);
  background:
    linear-gradient(
      180deg,
      rgb(var(--p-bg-rgb) / 0.36) 0%,
      rgb(var(--p-bg-rgb) / 0.30) 60%,
      rgb(var(--p-bg-rgb) / 0.26) 100%
    ),
    linear-gradient(115deg, var(--cyan) 0%, var(--accent) 100%);
}
.close-field::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(1080px, 100%);
  pointer-events: none;
  background-image:
    linear-gradient(var(--hairline-invert), var(--hairline-invert)),
    linear-gradient(var(--hairline-invert), var(--hairline-invert)),
    linear-gradient(var(--hairline-invert), var(--hairline-invert));
  background-size: 1px 100%;
  background-position: 25% 0, 50% 0, 75% 0;
  background-repeat: no-repeat;
}
@media (max-width: 1024px) {
  .close-field::before {
    background-image: linear-gradient(var(--hairline-invert), var(--hairline-invert));
    background-position: 50% 0;
  }
}
@media (max-width: 640px) { .close-field::before { display: none; } }

.close-inner {
  position: relative;
  z-index: 1;
  max-width: 34em;
  margin: 0 auto;
}
.close-field .kicker { color: var(--on-accent); display: block; margin-bottom: 18px; }
.close-h {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(2rem, 5.4vw, 3.2rem);
  line-height: 1.14;
  letter-spacing: -0.01em;
  color: var(--on-accent);
  margin-bottom: 18px;
}
.close-p {
  color: var(--on-accent);
  font-size: 1.08rem;
  line-height: 1.65;
  margin-bottom: var(--s-6);
}
.store-badge-invert {
  background: var(--on-accent);
  color: var(--ink);
  box-shadow: var(--shadow-invert);
}
.store-badge-invert .badge-note { color: var(--ink3-text); }
.close-fine {
  color: var(--on-accent);
  font-size: 0.82rem;
  margin-top: 22px;
}

/* ============================================================
   8 · footer columns
   ============================================================ */

.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, 1fr);
  gap: 32px;
  align-items: start;
}
@media (max-width: 760px) {
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 28px; }
  .footer-brand { grid-column: 1 / -1; }
}
.footer-brand .footer-tag { margin-top: 12px; max-width: 24em; }
.footer-col p {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink3-text);
  margin-bottom: 12px;
}
.footer-col a {
  display: block;
  color: var(--ink2);
  font-size: 0.87rem;
  padding: 4px 0;
  transition: color 150ms var(--ease);
}
.footer-col a:hover { color: var(--accent); text-decoration: none; }
/* On a phone these eight links measured 30px tall stacked with a 0px gap, so
   the bottom of one row was exactly the top of the next and every tap was a
   coin flip. 12px of padding takes each row to 44px and the margin puts real
   space between them. Left at 4px on the desktop footer, where the pointer is
   a mouse and 44px rows would only make the column loose. */
@media (max-width: 900px) {
  .footer-col a { padding: 12px 0; margin-bottom: 4px; }
  .footer-col a:last-child { margin-bottom: 0; }
}

.site-footer .footer-legal { border-top: 1px solid var(--hairline); padding-top: 18px; }

/* Section 9 used to live here: three "rhythm adjustment" overrides patching
   .section padding and the footer margin from this file. They are gone. Every
   section-scale value now comes from --s-section in site.css, and the footer
   margin is set once where .site-footer is declared, so the subpages get the
   same rhythm this file used to fix for index.html alone. */

/* ============================================================
   10 · the founding waitlist
   The generic form component (.wait-lead, .wait-row, .wait-input,
   .wait-btn, .wait-fine, .wait-status, .wait-pot, .wait-done) moved to
   site.css when the About page picked up a third placement. That
   page loads site.css alone, like every other subpage, so the
   component has to live in the file all of them share.
   What stays here is placement: the light card under #pricing and
   the gradient field in #close, both on the home page.
   ============================================================ */

/* The renewal disclosure is a second .price-elig directly under the
   eligibility line. Both are the same muted 0.8rem, so without this
   they set as one run-on block. */
.price-elig + .price-elig { margin-top: 7px; }

/* ---------- placement A · #pricing, on the wash ---------- */

.wait-block-slim {
  margin-top: 18px;
  padding: 22px 28px;
  background: var(--card);
  border: 1px solid var(--hairline);
  border-radius: var(--r-card);
}
@media (max-width: 640px) {
  .wait-block-slim { padding: 20px 18px; }
}

/* ---------- placement B · #close, on the gradient ---------- */

.wait-block-lead {
  margin-top: var(--s-6);
  padding-top: var(--s-5);
  border-top: 1px solid var(--hairline-invert);
}
.wait-h {
  font-family: var(--serif);
  font-weight: 500;
  font-size: clamp(1.3rem, 3.2vw, 1.7rem);
  line-height: 1.22;
  color: var(--on-accent);
  margin-bottom: 8px;
}
.wait-sub {
  color: var(--on-accent);
  font-size: 0.98rem;
  line-height: 1.62;
  margin-bottom: 18px;
}
/* Full white, not the muted inks. --ink3-text and a 60% white both
   fall under AA here, and the margin is thinner than it looks.

   Measured, not estimated. The field composites a vertical scrim
   (0.36 at the top, 0.30 at 60%, 0.26 at the bottom) over a 115deg
   cyan-to-accent ramp, so the lightest ground is the cyan corner
   under the weakest scrim: white there is 3.92:1, which is BELOW
   AA. The accent end is 8.53:1. The waitlist block never reaches
   that corner, and white across its actual span measures 5.16:1 at
   375px and 5.22:1 at 1280px.

   So the headroom comes from where this block sits, not from the
   scrim alone. Moving anything on this field up and to the left,
   or widening the section, walks toward the 3.92 corner: re-measure
   at the element's real position before trusting it. */
.close-field .wait-fine,
.close-field .wait-status,
.close-field .wait-done .wait-status { color: var(--on-accent); }

/* The focus ring, re-inked for this one field. Everywhere else the site's
   ring is --accent on a white or wash surface: the #pricing twin of this
   form measures 5.11:1. Here the 2px offset lifts the ring clear of the
   white button and the light input and draws it on the composited gradient
   instead, where accent-on-brand measures 1.10:1 at the input and 1.22:1 at
   the button. WCAG 1.4.11 wants 3:1, so a keyboard reader arriving at the
   primary capture on this page could not see where they were.
   White is the same ink already measured for the text in this block, 5.16:1
   at 375px and 5.22:1 at 1280px, so it clears 3:1 with room. Offset stays.

   [tabindex] is in the list for .wait-block, which the script focuses after a
   successful submit. That block only draws a ring in the keyboard case, and
   accent on this gradient is the same 1.10:1 as the input, so it has to be
   re-inked here alongside the controls or the ring it just gained is one a
   keyboard reader still cannot see. */
.close-field a:focus-visible,
.close-field button:focus-visible,
.close-field input:focus-visible,
.close-field [tabindex]:focus-visible {
  outline-color: var(--on-accent);
}

/* The store badge, demoted. Chip scale, no lift, and it sits below
   the fine print, so the white pill it shares a colour with reads
   as the second thing on the field rather than the first. */
.close-store { margin-top: var(--s-5); }
.store-badge-quiet {
  padding: 9px 16px;
  font-size: 0.82rem;
  box-shadow: none;
}
.store-badge-quiet svg { width: 15px; height: 15px; }
.store-badge-quiet .badge-note { font-size: 0.74rem; }
