/* ==========================================================================
   WELV funnel pages: /reserve, /thank-you, /mock-checkout, /privacy, /terms.
   Load AFTER base.css and welv.css: the fonts (@font-face) and the protected
   ground (.welv-ground and its glows) live in welv.css.

   Look: docs/design-system.md (ds-1). /reserve and /thank-you are graphite
   pages, "the ground at night"; /privacy and /terms sit on the protected
   cream ground like the Soon pages. Motion: docs/motion-spec.md, restrained
   here: the reservation's first screen stays still except press feedback
   and the one seat-strip fill (motion-spec section 9).

   Every class is prefixed fn- and every token is set on html.fn-root, so
   nothing here touches the landing page or collides with its components.
   This file is unlayered, so it wins over base.css (all in @layer) whatever
   the specificity; base.css's [hidden] rule is !important in a layer and still
   wins, which is what the pages rely on.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. TOKENS (design-system 3.1-3.4, motion-spec 2)
   -------------------------------------------------------------------------- */

html.fn-root {
  --ground: #f7f1e8; --ground-2: #efe6db; --paper: #fefaef;
  --ink-1: #1b1d1a; --ink-2: #4a4741; --ink-3: #6e6b65;
  --hair: rgb(74 71 65 / .16); --hair-2: rgb(74 71 65 / .28);
  --band-0: #1c1b1a; --band-1: #2a2927; --band-lit: #3a3837;
  --on-band-1: #f3efe9; --on-band-2: rgb(243 239 233 / .74); --on-band-3: rgb(243 239 233 / .62);
  --hair-band: rgb(243 239 233 / .12); --field-line: rgb(243 239 233 / .38);
  --signal: #ffb648; --signal-hover: #ffc266; --signal-press: #f2a531; --signal-ink: #1b1d1a;
  --err: #b3261e; --err-on-band: #ff9b85;
  --sh-1: 0 1px 2px rgb(74 71 65 / .06), 0 8px 24px -12px rgb(74 71 65 / .18);
  --edge-dark: inset 0 1px 0 rgb(255 255 255 / .06), 0 0 0 1px rgb(243 239 233 / .08);
  --glow-signal: inset 0 0 0 1px rgb(255 226 178 / .35), 0 12px 32px -10px rgb(255 182 72 / .55);
  --r-pill: 999px; --r-card: 16px; --r-slab: 32px; --r-founder: 22px;
  --gutter: 24px;
  /* the web fonts first, then welv.css's metric-adjusted stand-ins, so lines break the same way
     before the fonts arrive (Codex perf note) */
  --font-sans: "Hanken Grotesk", "Hanken Grotesk Fallback", sans-serif;
  --font-serif: "Newsreader", "Newsreader Fallback", serif;
  --ease-settle: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in: cubic-bezier(0.5, 0, 0.75, 0);
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --nums: "kern" 1, "liga" off, "tnum" 1, "lnum" 1;
  font-synthesis: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
@media (max-width: 360px) { html.fn-root { --gutter: 16px; } }
@media (min-width: 1024px) { html.fn-root { --gutter: 48px; --r-slab: 48px; } }
@media (min-width: 1440px) { html.fn-root { --gutter: 64px; } }


/* --------------------------------------------------------------------------
   2. PAGE SURFACES AND BROWSER SURFACES
   -------------------------------------------------------------------------- */

/* Graphite pages. The surface recipe (design-system 3.1) is painted on a fixed
   layer the size of the viewport, so the lit corner, the gold ember and the
   cool edge keep their proportions however long the page is. html carries the
   base colour so overscroll shows graphite, not the cream welv.css sets. */
html.fn-root--dark {
  background-color: var(--band-0);
  color-scheme: dark;
  scrollbar-color: rgb(243 239 233 / .24) transparent;
  scrollbar-gutter: stable; /* the page does not shift sideways when the sheet locks scrolling */
}
html.fn-root--dark body {
  background: transparent;
  color: var(--on-band-1);
  caret-color: var(--on-band-1);
}
html.fn-root--dark body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(110% 80% at 10% 0%, #3a3837 0%, rgb(58 56 55 / 0) 62%),
    radial-gradient(60% 55% at 92% 100%, rgb(255 182 72 / .12) 0%, rgb(255 182 72 / 0) 70%),
    radial-gradient(45% 50% at 0% 70%, rgb(182 207 221 / .08) 0%, rgb(182 207 221 / 0) 70%),
    #1c1b1a;
}
html.fn-root--dark ::selection { background: rgb(181 228 254 / .28); color: inherit; }

/* Light pages (privacy, terms, the test checkout). */
html.fn-root--light { scrollbar-color: rgb(74 71 65 / .3) transparent; }
html.fn-root--light body { caret-color: var(--ink-1); }
html.fn-root--light ::selection { background: rgb(181 228 254 / .6); color: inherit; }

body.fn {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 16px;
  line-height: 24px;
  letter-spacing: 0;
}
/* No automatic hyphenation anywhere in these pages ("pur-chase"). */
body.fn, .fn-sheet, .fn-doc { -webkit-hyphens: manual; hyphens: manual; }
/* Running text sets without a lone last word where the browser can. */
.fn-l3, .fn-l4, .fn-reassure, .fn-lead, .fn-step__text, .fn-faq p, .fn-g__text,
.fn-card p, .fn-return__line, .fn-gate__line, .fn-act__under, .fn-sheet__line { text-wrap: pretty; }
/* Headings that take focus by script (tabindex="-1") show no ring: they are not controls. */
.fn [tabindex="-1"]:focus, .fn-sheet [tabindex="-1"]:focus { outline: none; }

/* Focus: 2 px ring in the surface's strongest ink, following the radius. */
.fn :focus:not(:focus-visible),
.fn-sheet :focus:not(:focus-visible),
.fn-doc :focus:not(:focus-visible) { outline: none; }
.fn :focus-visible,
.fn-sheet :focus-visible { outline: 2px solid var(--on-band-1); outline-offset: 3px; }
.fn-doc :focus-visible,
html.fn-root--light .fn :focus-visible { outline: 2px solid var(--ink-1); outline-offset: 3px; }

/* Running-text links. */
.fn-main a:not([class]),
.fn-sheet a:not([class]) {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
@media (hover: hover) and (pointer: fine) {
  .fn-main a:not([class]):hover, .fn-sheet a:not([class]):hover { text-decoration-thickness: 2px; }
}

.fn-sr {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.fn-ico { display: inline-block; flex: none; width: 16px; height: 16px; vertical-align: -3px; }

/* Parts that exist only with, or only without, JavaScript. reserve.js and
   thankyou.js add html.fn-js as their first act. */
html:not(.fn-js) .fn-jsonly,
html.fn-js .fn-nojs { display: none !important; }


/* --------------------------------------------------------------------------
   3. TOP BAR (logo-only header on /reserve and /thank-you)
   -------------------------------------------------------------------------- */

.fn-top {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  box-sizing: content-box;
  height: 56px;
  padding: env(safe-area-inset-top) max(var(--gutter), env(safe-area-inset-right)) 0 max(var(--gutter), env(safe-area-inset-left));
  max-width: 1440px;
  margin: 0 auto;
}
.fn-top__logo {
  display: block;
  width: 64px; /* the landing's size (VQ-29); 80 px from 1024 */
  padding: 14px 0;
  color: var(--on-band-1);
}
.fn-top__logo svg { display: block; width: 100%; height: auto; }
.fn-top__back {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 15px;
  line-height: 20px;
  color: var(--on-band-2);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  transition: color 200ms linear;
}
@media (hover: hover) and (pointer: fine) { .fn-top__back:hover { color: var(--on-band-1); } }
@media (min-width: 1024px) {
  .fn-top { height: 80px; }
  .fn-top__logo { width: 80px; }
  /* The logo and "Back to the page" sit on the edges of the page's own column, not on the wider
     page gutters (VIS-15): /reserve's 1180 px (section 5), /thank-you's 1040 px (section 7). */
  .fn-top:has(+ .fn-reserve) { max-width: 1180px; }
  .fn-top:has(+ .fn-thanks) { max-width: 1040px; }
}


/* --------------------------------------------------------------------------
   4. SHARED CONTROLS: buttons, text buttons, messages (design-system 5.1)
   -------------------------------------------------------------------------- */

.fn-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  height: 56px;
  padding: 0 24px;
  border: 0;
  border-radius: var(--r-pill);
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 16px;
  line-height: 20px;
  letter-spacing: .005em;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
  transition: transform 120ms var(--ease-out), background-color 200ms linear, box-shadow 200ms linear, opacity 200ms linear;
}
.fn-btn--block { display: flex; width: 100%; padding: 0 20px; }
.fn-btn--signal { background: var(--signal); color: var(--signal-ink); box-shadow: var(--glow-signal); }
.fn-btn--cream { background: var(--on-band-1); color: var(--ink-1); }
.fn-btn:active { transform: scale(.97); }
.fn-btn--signal:active { background: var(--signal-press); }
.fn-btn--cream:active { background: #e6e1da; }
@media (hover: hover) and (pointer: fine) {
  .fn-btn--signal:hover {
    background: var(--signal-hover);
    transform: translateY(-1px);
    box-shadow: inset 0 0 0 1px rgb(255 226 178 / .5), 0 16px 40px -12px rgb(255 182 72 / .6);
  }
  .fn-btn--cream:hover { background: #fffdf8; }
}
.fn-btn[aria-disabled="true"] { opacity: .72; cursor: progress; transform: none; }
@media (max-width: 340px) { .fn-btn { font-size: 15px; } .fn-btn--block { padding: 0 14px; } }
@media (min-width: 1024px) { .fn-btn { font-size: 17px; } }

/* "No thanks" (night decision A3): a quiet outlined button, 48 px, so the gold button stays the
   only filled control. On the narrowest phones the label wraps rather than overflows. */
.fn-btn--ghost {
  height: auto;
  min-height: 48px;
  padding: 12px 20px;
  background: transparent;
  box-shadow: inset 0 0 0 1px rgb(243 239 233 / .28);
  color: var(--on-band-1);
  font-size: 15px;
  white-space: normal;
  text-align: center;
}
.fn-btn--ghost:active { background: rgb(243 239 233 / .08); }
@media (hover: hover) and (pointer: fine) { .fn-btn--ghost:hover { box-shadow: inset 0 0 0 1px rgb(243 239 233 / .45); } }
@media (max-width: 340px) { .fn-btn--ghost { padding: 12px 14px; } }

.fn-textlink {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 20px;
  color: var(--on-band-2);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  cursor: pointer;
  touch-action: manipulation;
  transition: color 200ms linear;
}
@media (hover: hover) and (pointer: fine) { .fn-textlink:hover { color: var(--on-band-1); } }

/* Press feedback wherever a finger lands, with no change at rest (iOS shows :active only
   because reserve.js, thankyou.js and checkout.js register a touchstart listener), and no
   text selection or link preview on a long press. Running text stays selectable. */
.fn-faq summary:active, .fn-disclose summary:active, .fn-textlink:active, .fn-top__back:active,
.fn-sheet__x:active, .fn-status__not:active { opacity: .6; transition-duration: 0s; }
.fn-pill:active span { background: rgb(243 239 233 / .14); transition-duration: 0s; }
.fn-btn, .fn-textlink, .fn-top__back, .fn-status__not { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }

/* A message line under a control: empty until there is something to say,
   then it appears at once (fields and their messages never animate). */
.fn-msg { margin: 10px 0 0; font-size: 14px; line-height: 20px; color: var(--err-on-band); }
.fn-msg:empty { margin: 0; }

/* The calm notice: a payment that did not go through, the seats running out.
   Light text in a quiet frame, the colour only on the glyph. */
.fn-notice {
  display: flex;
  gap: 10px;
  margin: 16px 0 0;
  padding: 12px 14px;
  border-radius: 14px;
  background: rgb(255 155 133 / .08);
  box-shadow: inset 0 0 0 1px rgb(255 155 133 / .28);
  font-size: 14px;
  line-height: 20px;
  color: var(--on-band-1);
}
.fn-notice .fn-ico { margin-top: 2px; color: var(--err-on-band); }
.fn-notice p { margin: 0; }
.fn-cta .fn-notice { margin: 0 0 14px; }


/* --------------------------------------------------------------------------
   5. /reserve: column, decision screen, gate, below the fold (design-system 5.14)
   -------------------------------------------------------------------------- */

.fn-main { position: relative; z-index: 1; }
.fn-col {
  box-sizing: border-box;
  width: 100%;
  max-width: calc(440px + 2 * var(--gutter));
  margin: 0 auto;
  padding: 0 max(var(--gutter), env(safe-area-inset-right)) 0 max(var(--gutter), env(safe-area-inset-left));
}
.fn-reserve { padding: 8px 0 32px; } /* VQ-24, K7: about 46 px of graphite under "Back to the page", no more */
@media (min-width: 1024px) { .fn-reserve { padding: 56px 0 112px; } }

/* States (reserve.js): data-fn-state="decision" | "gate" on <html>, tier on
   data-tier ("founding" by default, "standard" after the 100 founding seats). */
html[data-fn-state="gate"] .fn-decision,
html[data-fn-state="gate"] .fn-more { display: none; }
html:not([data-fn-state="gate"]) .fn-gate { display: none; }
html:not([data-tier="standard"]) [data-tier-only="standard"],
html[data-tier="standard"] [data-tier-only="founding"] { display: none !important; }
/* Shipping (every funnel page, /terms too): the server writes data-ship="open" | "closed" on
   <html>; after the December 25 cut-off "Founding members ship first." replaces the date. A
   page without the attribute reads as open. */
html[data-ship="closed"] [data-ship-only="open"],
html:not([data-ship="closed"]) [data-ship-only="closed"] { display: none !important; }

/* The anchor lines follow offer.anchorMode, written on main[data-anchor]:
   "strike" shows the struck future rate, "competitors" the dated comparison,
   "both" both. The value line below the fold carries the comparison only
   when the first screen does not; after the founding seats (standard tier)
   the first screen has no anchor and the value line always shows. */
[data-anchor="strike"] [data-anchor-only="competitors"],
[data-anchor="competitors"] [data-anchor-only="strike"],
[data-anchor="competitors"] [data-value-line],
[data-anchor="both"] [data-value-line] { display: none; }
html[data-tier="standard"] .fn-anchor { display: none; }
html[data-tier="standard"] [data-value-line] { display: block; }
/* Competitor figures exist only once reserve.js has them from the API. */
html:not([data-competitors="yes"]) [data-comp] { display: none !important; }

.fn-status {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 16px; /* VQ-11: room above the price */
  font-size: 13px;
  line-height: 18px;
  letter-spacing: .005em;
  color: var(--on-band-2);
}
@media (min-width: 1024px) { .fn-status { margin-bottom: 24px; } }
.fn-status .fn-ico { color: var(--on-band-1); }
/* One line at every width: a long address ends in an ellipsis instead of wrapping, so the
   decision does not move when the API answers (MN-8, UX-10). The whole address stays in the text. */
.fn-status__text, .fn-status__who { display: flex; align-items: center; min-width: 0; white-space: nowrap; }
.fn-status__lead, .fn-status__sep, .fn-status__not { flex: none; }
.fn-status__sep { white-space: pre; }
.fn-status__email { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* "Not you?": a text button inside the 18 px line. Its hit area is 44 px tall, and the
   negative margins keep the line, and the first screen below it, where they were. */
.fn-status__not {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin: -13px 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: var(--on-band-1);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  cursor: pointer;
  touch-action: manipulation;
  vertical-align: baseline;
}
@media (hover: hover) and (pointer: fine) { .fn-status__not:hover { text-decoration-thickness: 2px; } }
.fn-status__not[aria-disabled="true"] { opacity: .72; cursor: progress; }
.fn-status + .fn-msg { margin: -4px 0 12px; }
.fn-status + .fn-msg:empty { margin: 0; }

/* Line 1, the H1: "$149/year" over "first 100 founding members". */
.fn-price { margin: 0; font-weight: 400; }
.fn-price__tier { display: block; }
.fn-price__row { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 6px; }
.fn-price__num {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 64px;
  line-height: 60px;
  letter-spacing: -0.016em;
  color: var(--on-band-1);
  font-variant-numeric: lining-nums tabular-nums;
  font-feature-settings: var(--nums);
}
.fn-price__per { font-size: 17px; line-height: 24px; color: var(--on-band-2); }
.fn-price__sub { display: block; margin-top: 4px; font-size: 14px; line-height: 20px; color: var(--on-band-2); }
@media (min-width: 1024px) {
  .fn-price__num { font-size: 96px; line-height: 88px; }
  .fn-price__per { font-size: 19px; }
  .fn-price__sub { font-size: 15px; line-height: 22px; margin-top: 6px; }
}

/* The price row (night A2): the H1 and, beside it, the shown finish on a soft warm light, with
   no card and no border, so Obsidian reads on graphite. About 150 px wide (120 at 360 px and
   under) and never squeezing the H1. From 1024 px the stage stands beside the decision instead. */
.fn-pricerow { display: grid; grid-template-columns: max-content minmax(0, 150px); justify-content: space-between; align-items: center; column-gap: 12px; }
.fn-pricefig { display: grid; place-items: center; background: radial-gradient(closest-side, rgb(255 226 190 / .16), rgb(255 226 190 / 0)); }
.fn-pricefig img { grid-area: 1 / 1; display: block; width: 100%; height: auto; filter: drop-shadow(0 6px 8px rgb(0 0 0 / .45)); }
@media (max-width: 360px) { .fn-pricerow { grid-template-columns: max-content minmax(0, 120px); } }
@media (min-width: 1024px) { .fn-pricerow { display: block; } .fn-pricefig { display: none; } }
/* A payment that did not go through (reserve.js: main.has-notice): the notice joins the first
   screen above the button, and the price-row picture steps aside (night A2, Codex #5). */
.fn-reserve.has-notice .fn-pricerow { display: block; }
.fn-reserve.has-notice .fn-pricefig { display: none; }

/* Seat line and the hundred-cell strip (design-system 5.13). The mask sits
   on the strip, so the claimed layer can scale without squashing cells. */
.fn-seats { margin-top: 8px; }
.fn-seats[data-pending] { visibility: hidden; }
.fn-seats__line {
  margin: 0;
  font-size: 14px;
  line-height: 20px;
  color: var(--on-band-1);
}
.fn-strip {
  position: relative;
  height: 12px;
  margin-top: 8px;
  -webkit-mask-image: linear-gradient(90deg, #000 0 58%, transparent 58%);
  mask-image: linear-gradient(90deg, #000 0 58%, transparent 58%);
  -webkit-mask-size: 1% 100%;
  mask-size: 1% 100%;
  -webkit-mask-repeat: repeat-x;
  mask-repeat: repeat-x;
}
.fn-strip > i { position: absolute; top: 0; bottom: 0; left: 0; display: block; }
.fn-strip__open { width: 100%; background: rgb(243 239 233 / .16); }
/* Claimed seats in green, as on the landing (the founder's choice of 2026-10-08, design-system 5.13). */
.fn-strip__claimed { width: var(--claimed, 0%); background: #4cc38a; transform-origin: 0 50%; }

/* Line 2, right under the price (UM-02, TASTE-05): the struck future rate and its label; or
   the dated comparison. The label wraps as one unit, beside the strike or under it, never
   half under it (VQ-12). The struck rate is the saving, so it is set as a price, in the price's
   face, a step up from its label (DQ-06). */
.fn-anchor { margin: 8px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); }
.fn-anchor--strike { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 8px; }
.fn-anchor s {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 22px;
  line-height: 24px;
  letter-spacing: -0.004em;
  color: var(--on-band-2);
  white-space: nowrap;
  text-decoration-line: line-through;
  text-decoration-thickness: 1.5px;
  text-decoration-color: rgb(243 239 233 / .7);
  font-feature-settings: var(--nums);
}
@media (min-width: 1024px) { .fn-anchor s { font-size: 24px; line-height: 28px; } }
.fn-anchor + .fn-anchor { margin-top: 8px; }
/* The dated comparison (anchorMode "competitors" or "both"; the founder's ask of 2026-10-08): it reads
   at once as other headbands, in the serif italic and cream, with its source right under it instead
   of a footnote further down. The range never breaks. */
.fn-decision .fn-anchor--comp { margin-top: 12px; }
.fn-comp__line {
  display: block;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 200;
  font-size: 19px;
  line-height: 24px;
  color: var(--on-band-1);
}
.fn-comp__src { display: block; margin-top: 4px; font-size: 13px; line-height: 18px; color: var(--on-band-2); }
.fn-nowrap { white-space: nowrap; }
@media (min-width: 1024px) { .fn-comp__line { font-size: 20px; line-height: 26px; } }

.fn-l3 { margin: 8px 0 0; font-size: 16px; line-height: 24px; color: var(--on-band-1); }
.fn-l4 { margin: 6px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); }
.fn-cta { margin: 20px 0 0; }
/* The risk answer under the button is body-sized, not fine print (UX-11, Codex #14), and a step
   brighter than the lines around it (Codex verdict). */
.fn-reassure { margin: 8px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-1); }

/* The finish picker (night A2): the sample's variant row, right above the button. Six 28 px
   dots in 44 px targets 8 px apart, in the landing's swatch colours. The unselected ring is the
   field line (3:1), so Obsidian shows on graphite; the selected dot gets a 2 px gap and a
   1.5 px cream ring. JavaScript only (reserve.js swaps the renders). */
.fn-picker { min-width: 0; margin: 8px 0 0; padding: 0; border: 0; }
.fn-picker__label { margin: 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); }
.fn-picker__name { color: var(--on-band-1); }
.fn-picker__dots { display: flex; gap: 8px; margin: -2px 0 0 -8px; }
.fn-picker__dot {
  position: relative;
  display: grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  margin: 0;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  outline: none; /* the shell's blue label:has(:focus-visible) ring; the dot carries the focus ring */
}
.fn-picker__dot input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.fn-picker__dot i {
  display: block;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--c);
  box-shadow: inset 0 0 0 1px var(--field-line);
  pointer-events: none;
  transition: transform 120ms var(--ease-out), box-shadow 120ms linear;
}
.fn-picker__dot input[value="obsidian-still"] + i { --c: #2f2f2f; }
.fn-picker__dot input[value="ivory-ease"] + i { --c: #d2c8bb; }
.fn-picker__dot input[value="mint-calm"] + i { --c: #81cdcc; }
.fn-picker__dot input[value="fuchsia-joy"] + i { --c: #ef78c3; }
.fn-picker__dot input[value="amber-presence"] + i { --c: #f2a65a; }
.fn-picker__dot input[value="indigo-depth"] + i { --c: #445074; }
.fn-picker__dot input:checked + i { outline: 1.5px solid var(--on-band-1); outline-offset: 2px; }
/* Keyboard focus rings the whole 44 px target, as the landing's swatches do, well clear of the
   selected ring around the dot (CM-6). */
.fn-picker__dot:has(input:focus-visible) { outline: 2px solid var(--on-band-1); outline-offset: 0; border-radius: 50%; }
@supports not selector(:has(*)) {
  .fn-picker__dot input:focus-visible + i { outline: 2px solid var(--on-band-1); outline-offset: 6px; }
}
.fn-picker__dot:active i { transform: scale(.9); transition-duration: 0s; }
@media (hover: hover) and (pointer: fine) {
  .fn-picker__dot:hover input:not(:checked) + i { box-shadow: inset 0 0 0 1px rgb(243 239 233 / .6); }
}
@media (prefers-reduced-motion: reduce) { .fn-picker__dot:active i { transform: none; opacity: .7; } }
/* While a checkout request is on its way the picker rests, like the button (reserve.js, Codex #3). */
.fn-picker:disabled .fn-picker__dots { opacity: .72; }
.fn-picker:disabled .fn-picker__dot, .fn-picker:disabled .fn-picker__dot input { cursor: progress; }
.fn-picker:disabled .fn-picker__dot:active i { transform: none; }
/* 8 px between the dots' 44 px targets and the button (CM-4). */
html.fn-js .fn-picker + .fn-cta { margin-top: 8px; }

/* "What if I cancel membership?": compact disclosure. The plus says it opens; no link underline,
   like the money questions (VQ-13). The 21 px above keeps its target 8 px clear of the terms
   link's 45 px one (CM-4). */
.fn-disclose { margin-top: 21px; }
.fn-disclose summary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  list-style: none;
  cursor: pointer;
  font-size: 14px;
  line-height: 20px;
  color: var(--on-band-2);
  -webkit-user-select: none;
  user-select: none;
  transition: color 200ms linear;
}
@media (hover: hover) and (pointer: fine) { .fn-disclose summary:hover { color: var(--on-band-1); } }
.fn-disclose summary::-webkit-details-marker { display: none; }
.fn-disclose p { margin: 0 0 8px; max-width: 40ch; font-size: 14px; line-height: 20px; color: var(--on-band-1); }

/* "No thanks" is the last item of the decision (A3; the button itself is in section 4). */
.fn-decline { margin: 12px 0 0; }

/* Plus icon for every accordion: two 1.5 px bars, turning 45 degrees open. */
.fn-plus { position: relative; display: inline-block; flex: none; width: 14px; height: 14px; transition: transform 200ms var(--ease-out); }
.fn-plus::before, .fn-plus::after {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 100%; height: 1.5px;
  border-radius: 1px;
  background: currentColor;
  transform: translate(-50%, -50%);
}
.fn-plus::after { transform: translate(-50%, -50%) rotate(90deg); }
details[open] > summary .fn-plus { transform: rotate(45deg); }

/* Trust line, right under the reassurance (deck 20: "beside the button"; p5 A-F1). The terms
   link keeps the 18 px line and reaches a 44 px hit area through padding (IMP-12): an inline
   box's padding adds to its 13 px text box, not to the 18 px line, so 13 + 2 x 16 = 45 px. */
.fn-secure {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 0 0;
  font-size: 13px;
  line-height: 18px;
  color: var(--on-band-2);
}
.fn-secure .fn-ico { color: var(--on-band-1); }
.fn-secure a { padding-block: 16px; }

/* The product stage (night A2): the shown finish on lit graphite. Phone: 342 x 214 under the
   decision with the finish named under it, or 342 x 170 above the email gate. The renders stack
   in one grid cell, so reserve.js can crossfade them. */
.fn-showcase { margin: 32px 0 0; }
.fn-showcase__light {
  display: grid;
  place-items: center;
  aspect-ratio: 342 / 214;
  border-radius: var(--r-card);
  background: radial-gradient(70% 75% at 50% 45%, #3a3837 0%, rgb(58 56 55 / .45) 55%, rgb(58 56 55 / 0) 100%);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / .06);
  overflow: hidden;
}
.fn-showcase__light img { grid-area: 1 / 1; display: block; width: 86%; height: auto; filter: drop-shadow(0 16px 20px rgb(0 0 0 / .45)); }
.fn-showcase__name { margin: 10px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); text-align: center; }
@media (max-width: 1023.98px) {
  html[data-fn-state="gate"] .fn-showcase { margin-top: 8px; }
  html[data-fn-state="gate"] .fn-showcase__light { aspect-ratio: 342 / 170; }
  html[data-fn-state="gate"] .fn-showcase__light img { width: 72%; }
  html[data-fn-state="gate"] .fn-showcase__name { display: none; }
}
/* Short phones: a lower gate stage keeps the consent line in the first screen with the button. */
@media (max-width: 1023.98px) and (max-height: 700px) {
  html[data-fn-state="gate"] .fn-showcase__light { aspect-ratio: 342 / 136; }
  html[data-fn-state="gate"] .fn-showcase__light img { width: 58%; }
}
/* Shorter still (CM-3: an iPhone SE in Safari shows 375 x 548): the price, the anchor and the
   button stay in the first screen, the reassurance with them. The price steps down, the gaps
   tighten and the picker's name line goes (the stage below names the finish; the legend and the
   live name stay for screen readers); the gate drops its stage. */
@media (max-width: 1023.98px) and (max-height: 600px) {
  .fn-status { margin-bottom: 10px; }
  .fn-price__num { font-size: 52px; line-height: 48px; }
  .fn-picker__label { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .fn-picker__dots { margin-top: 0; }
  html[data-fn-state="gate"] .fn-showcase { display: none; }
  /* a payment that did not go through: its notice takes the seat count's place (Codex #5) */
  .fn-reserve.has-notice .fn-seats { display: none; }
}

/* Below the fold. Each block brings its own top margin; the stage above already sets it apart
   from the decision. */
.fn-more { margin-top: 8px; }

/* The card's edge is drawn inside the box, as on the stage and the founding card above or below
   it, so stacked edges line up (VIS-02); --edge-dark stays for the capsule and the sheet. */
.fn-card {
  margin-top: 24px;
  padding: 20px;
  border-radius: var(--r-card);
  background: var(--band-1);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .06), inset 0 0 0 1px rgb(243 239 233 / .08);
}
.fn-card__title { margin: 0; font-family: var(--font-sans); font-weight: 400; font-size: 16px; line-height: 24px; color: var(--on-band-1); }
.fn-card p { margin: 6px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); }
/* The founding perks (K6): the same words as three items, each behind the status line's check. */
.fn-perks { display: grid; gap: 8px; margin: 10px 0 0; padding: 0; list-style: none; }
.fn-perks li { display: flex; gap: 10px; margin: 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); text-wrap: pretty; }
.fn-perks .fn-ico { margin-top: 2px; color: var(--on-band-1); }

.fn-value { margin: 24px 0 0; font-size: 16px; line-height: 24px; color: var(--on-band-1); }
.fn-note { margin: 8px 0 0; font-size: 13px; line-height: 18px; letter-spacing: .005em; color: var(--on-band-3); }
.fn-num { white-space: nowrap; }
/* Tabular lining figures on digits only: the old sans face widened the space too under tnum. */
.fn-tnum { font-variant-numeric: lining-nums tabular-nums; font-feature-settings: var(--nums); }

.fn-guarantees { display: grid; gap: 20px; margin: 32px 0 0; padding: 0; list-style: none; }
.fn-guarantees li { margin: 0; }
.fn-guarantees strong { display: block; font-weight: 400; font-size: 16px; line-height: 24px; color: var(--on-band-1); }
.fn-g__text { display: block; margin-top: 2px; font-size: 14px; line-height: 20px; color: var(--on-band-2); }

.fn-h2 {
  margin: 48px 0 0;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 28px;
  line-height: 32px;
  letter-spacing: -0.008em;
  color: var(--on-band-1);
  text-wrap: balance;
}
.fn-h2 em, .fn-h1 em { font-style: italic; font-weight: 200; letter-spacing: -0.004em; padding-right: .04em; }

/* Money questions: the FAQ component in graphite (design-system 5.12). */
.fn-faq { margin-top: 12px; }
.fn-faq details + details { border-top: 1px solid var(--hair-band); }
.fn-faq summary {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 64px;
  padding: 18px 0;
  list-style: none;
  cursor: pointer;
  font-size: 17px;
  line-height: 24px;
  color: var(--on-band-1);
  -webkit-user-select: none;
  user-select: none;
}
.fn-faq summary::-webkit-details-marker { display: none; }
.fn-faq summary .fn-plus { width: 16px; height: 16px; color: var(--on-band-2); }
.fn-faq details p {
  margin: 0;
  padding: 0 32px 20px 0;
  max-width: 60ch;
  font-size: 16px;
  line-height: 25px;
  letter-spacing: .005em;
  color: var(--on-band-2);
}

.fn-contact { margin: 40px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); }
.fn-contact a, .fn-terms a { color: var(--on-band-1); }
.fn-terms { margin: 12px 0 0; font-size: 13px; line-height: 18px; color: var(--on-band-3); }
.fn-back { margin: 24px 0 0; }

/* Phones close the money questions with the decision's call to action again (DQ-03): the price
   line, its figure in the price's face, then the gold button and the reassurance. From 1024 px
   the decision stays in view beside the questions, so nothing repeats there. */
.fn-repeat { margin: 40px 0 0; }
.fn-repeat__price { margin: 0 0 14px; font-size: 15px; line-height: 22px; color: var(--on-band-2); }
.fn-repeat__num {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 32px;
  line-height: 36px;
  letter-spacing: -0.012em;
  color: var(--on-band-1);
  font-feature-settings: var(--nums);
}
@media (min-width: 1024px) { .fn-repeat { display: none; } }

/* The email gate (no lead cookie): the landing's act capsule, on graphite. */
.fn-gate { padding-top: 24px; }
.fn-h1 {
  margin: 0;
  max-width: 18ch;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 34px;
  line-height: 37px;
  letter-spacing: -0.012em;
  color: var(--on-band-1);
  text-wrap: balance;
  -webkit-hyphens: manual;
  hyphens: manual;
}
@media (min-width: 1024px) { .fn-h1 { font-size: 48px; line-height: 52px; } }
.fn-gate__line { margin: 16px 0 0; max-width: 34ch; font-size: 17px; line-height: 24px; color: var(--on-band-2); }

.fn-act { margin-top: 24px; }
.fn-act__capsule {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 6px;
  border-radius: 34px;
  background: var(--band-1);
  box-shadow: var(--edge-dark);
}
.fn-act__field {
  box-sizing: border-box;
  width: 100%;
  height: 56px;
  margin: 0;
  padding: 0 22px;
  border: 1px solid var(--field-line);
  border-radius: 28px;
  background: rgb(243 239 233 / .06);
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 17px;
  line-height: 22px;
  color: var(--on-band-1);
  caret-color: var(--on-band-1);
  -webkit-appearance: none;
  appearance: none;
}
.fn-act__field::placeholder { color: rgb(243 239 233 / .62); opacity: 1; }
.fn-act__field:focus { outline: none; border-color: var(--on-band-1); box-shadow: inset 0 0 0 1px rgb(243 239 233 / .9); }
.fn-act__field[aria-invalid="true"] { border-color: var(--err-on-band); }
.fn-act__field[aria-invalid="true"]:focus { box-shadow: inset 0 0 0 1px var(--err-on-band); }
.fn-act__field:-webkit-autofill,
.fn-act__field:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 40px #363533 inset;
  -webkit-text-fill-color: #f3efe9;
  caret-color: #f3efe9;
}
.fn-act__under { margin: 12px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); }
.fn-act__consent { margin: 10px 0 0; font-size: 13px; line-height: 18px; letter-spacing: .005em; color: var(--on-band-3); }
.fn-act__consent a { color: var(--on-band-2); }
.fn-hp { position: absolute !important; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* 1024 px and up (night A2, K1): the sample's two columns. The left column flows: the stage and
   its caption, the guarantees, the perk, the value line, the money questions and the closing
   lines. The right column holds only the decision (or the gate), which spans every row and stays
   in view while the left column scrolls, where the window is tall enough for all of it (760 px).
   The DOM keeps the phone order (decision, stage, more), so the price is still read first. */
@media (min-width: 1024px) {
  .fn-reserve .fn-col {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 400px;
    grid-template-rows: auto auto auto 1fr;
    grid-template-areas: "stage main" "side main" "perk main" "money main";
    column-gap: 56px;
    align-items: start;
    max-width: calc(1180px + 2 * var(--gutter));
  }
  .fn-decision, .fn-gate { grid-area: main; }
  .fn-gate { padding-top: 0; }
  .fn-stagecol { grid-area: stage; }
  .fn-showcase { margin: 0; }
  .fn-showcase__light { aspect-ratio: 4 / 3; border-radius: 24px; }
  .fn-showcase__light img { width: 84%; filter: drop-shadow(0 28px 32px rgb(0 0 0 / .5)); }
  .fn-more { display: contents; }
  .fn-guarantees { grid-area: side; margin-top: 40px; }
  .fn-perk { grid-area: perk; }
  .fn-questions { grid-area: money; }
}
@media (min-width: 1024px) and (min-height: 760px) {
  .fn-decision { position: sticky; top: 104px; }
}
@media (min-width: 1280px) {
  .fn-reserve .fn-col { grid-template-columns: minmax(0, 640px) 440px; column-gap: 100px; justify-content: center; }
}
/* The decision column beside the stage (DQ-01): a middle step in the type and space between its
   groups (price and anchor; seats; what is included; then the finish and the button under a
   hairline, as in the sample), so the deal scans instead of reading as one block of fine print.
   Only in the 440 px column and where it, held in view from 104 px, still fits the window with
   it (860 px); the 400 px column keeps the compact spacing. */
@media (min-width: 1280px) and (min-height: 860px) {
  .fn-decision .fn-anchor { margin-top: 12px; }
  .fn-decision .fn-seats { margin-top: 24px; }
  .fn-decision .fn-l3 { margin-top: 24px; font-size: 18px; line-height: 26px; }
  .fn-decision .fn-l4 { font-size: 15px; line-height: 22px; }
  .fn-decision .fn-picker { margin-top: 20px; padding-top: 20px; border-top: 1px solid var(--hair-band); }
  .fn-decision .fn-reassure { font-size: 15px; line-height: 22px; }
}
/* anchorMode "both" (the founder's trial of 2026-10-08) adds the comparison under the struck rate;
   a little less air around it keeps the decision's budgets: at 390x664 down to "Secure checkout",
   at 1440x900 down to "No thanks". */
[data-anchor="both"] .fn-decision .fn-anchor--comp { margin-top: 8px; }
[data-anchor="both"] .fn-comp__line { font-size: 18px; line-height: 21px; }
[data-anchor="both"] .fn-comp__src { margin-top: 2px; }
[data-anchor="both"] .fn-seats { margin-top: 10px; }
[data-anchor="both"] .fn-picker { margin-top: 4px; }
@media (min-width: 1280px) and (min-height: 860px) {
  [data-anchor="both"] .fn-decision .fn-anchor--comp { margin-top: 10px; }
  [data-anchor="both"] .fn-comp__line { font-size: 19px; line-height: 24px; }
  [data-anchor="both"] .fn-decision .fn-seats { margin-top: 16px; }
  [data-anchor="both"] .fn-decision .fn-l3 { margin-top: 16px; }
  [data-anchor="both"] .fn-decision .fn-picker { margin-top: 14px; padding-top: 14px; }
}
/* The 400 px column (1024-1279 px): the struck rate's label wraps under it there (DQ-06), so a
   little less air above the price keeps the column, held in view, inside a 768 px window (K1). */
@media (min-width: 1024px) and (max-width: 1279.98px) {
  .fn-status { margin-bottom: 16px; }
  .fn-anchor s { line-height: 24px; }
}
/* With the payment notice the column outgrows what a window under 900 px holds in view: there it
   scrolls with the page, so "No thanks" is never held below the fold (Codex #5, K1). */
@media (min-width: 1024px) and (max-height: 899.98px) {
  .fn-reserve.has-notice .fn-decision { position: static; }
}


/* --------------------------------------------------------------------------
   6. "NO THANKS" SURVEY SHEET AND RETURN CARD (design-system 5.15, motion E14)
   -------------------------------------------------------------------------- */

.fn-sheet {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  align-items: end;
  justify-items: stretch;
}
html.fn-js .fn-sheet.is-open,
html:not(.fn-js) .fn-sheet:target { display: grid; }
.fn-sheet__backdrop {
  position: absolute;
  inset: 0;
  background: rgb(0 0 0 / .5);
  touch-action: none;
}
html:not(.fn-js) .fn-sheet__backdrop { pointer-events: none; }
.fn-sheet__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  width: 100%;
  height: calc(100% - 8px - env(safe-area-inset-top));
  border-radius: var(--r-slab) var(--r-slab) 0 0;
  background: var(--band-1);
  box-shadow: var(--edge-dark), 0 -24px 64px -24px rgb(0 0 0 / .6);
  color: var(--on-band-1);
  overflow: hidden;
}
.fn-sheet.is-return .fn-sheet__panel { height: auto; max-height: calc(100% - 8px - env(safe-area-inset-top)); }
.fn-sheet__x {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--on-band-1);
  cursor: pointer;
  touch-action: manipulation;
  transition: background-color 200ms linear;
}
.fn-sheet__x .fn-ico { width: 20px; height: 20px; }
@media (hover: hover) and (pointer: fine) { .fn-sheet__x:hover { background: rgb(243 239 233 / .08); } }

.fn-sheet__form { display: flex; flex-direction: column; flex: 1; min-height: 0; margin: 0; }
.fn-sheet__scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 28px max(var(--gutter), env(safe-area-inset-right)) 28px max(var(--gutter), env(safe-area-inset-left));
}
/* MN-4: while more waits below, the lower edge fades (survey.js sets .is-more), so the list
   reads as one that scrolls. */
.fn-sheet__scroll.is-more {
  -webkit-mask-image: linear-gradient(#000 calc(100% - 24px), transparent);
  mask-image: linear-gradient(#000 calc(100% - 24px), transparent);
}
/* The title breaks only after "Before you go:" (VQ-14). */
.fn-nowrap { white-space: nowrap; }
.fn-sheet__title {
  margin: 0;
  padding-right: 40px;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 28px;
  line-height: 32px;
  letter-spacing: -0.008em;
  color: var(--on-band-1);
  text-wrap: balance;
}
.fn-sheet__line { margin: 8px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); }
/* "Tell us more (optional)": the three optional questions, closed by default (p5 A-F2). */
.fn-sheet__more { margin-top: 20px; }
.fn-sheet__more > summary { font-size: 15px; }
.fn-sheet__more > summary + .fn-q { margin-top: 12px; }
.fn-sheet__foot {
  flex: none;
  display: grid;
  justify-items: center;
  gap: 4px;
  padding: 12px max(var(--gutter), env(safe-area-inset-right)) calc(8px + env(safe-area-inset-bottom)) max(var(--gutter), env(safe-area-inset-left));
  border-top: 1px solid var(--hair-band);
  background: var(--band-1);
}

/* Questions and choice pills (shared with /thank-you). */
.fn-q { margin: 28px 0 0; padding: 0; border: 0; min-width: 0; }
.fn-q__label {
  display: block;
  margin: 0 0 12px;
  padding: 0;
  font-size: 17px;
  line-height: 24px;
  color: var(--on-band-1);
}
.fn-q__hint { margin: -8px 0 12px; font-size: 13px; line-height: 18px; color: var(--on-band-3); }
.fn-pills { display: flex; flex-wrap: wrap; gap: 8px; }
.fn-pill { position: relative; display: inline-flex; margin: 0; cursor: pointer; touch-action: manipulation; }
.fn-pill input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.fn-pill span {
  display: inline-flex;
  align-items: center;
  box-sizing: border-box;
  min-height: 48px;
  padding: 12px 18px;
  border-radius: var(--r-pill);
  box-shadow: inset 0 0 0 1px rgb(243 239 233 / .22);
  font-size: 15px;
  line-height: 20px;
  color: var(--on-band-1);
  -webkit-user-select: none;
  user-select: none;
  transition: background-color 120ms linear, color 120ms linear, box-shadow 120ms linear;
}
.fn-pill input:checked + span { background: var(--on-band-1); color: var(--ink-1); box-shadow: none; }
.fn-pill input:focus-visible + span { outline: 2px solid var(--on-band-1); outline-offset: 3px; }
@media (hover: hover) and (pointer: fine) {
  .fn-pill:hover input:not(:checked) + span { box-shadow: inset 0 0 0 1px rgb(243 239 233 / .5); }
}
.fn-q .fn-msg { margin: -4px 0 12px; }

.fn-field {
  box-sizing: border-box;
  width: 100%;
  height: 56px;
  margin: 0;
  padding: 0 22px;
  border: 1px solid var(--field-line);
  border-radius: 28px;
  background: rgb(243 239 233 / .06);
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 22px;
  color: var(--on-band-1);
  -webkit-appearance: none;
  appearance: none;
}
.fn-field::placeholder { color: rgb(243 239 233 / .62); opacity: 1; }
.fn-field:focus { outline: none; border-color: var(--on-band-1); box-shadow: inset 0 0 0 1px rgb(243 239 233 / .9); }

/* The pill's own ring shows focus, not the shell's blue label:has(:focus-visible) frame. */
.fn-sheet .fn-pill { outline: none; }
/* The sheet's reasons: one tidy column of full-width rows at every width, not a staircase of
   random widths (TASTE-11, K2). At 390 x 844 all eight and Send show at once (MN-4); the dialog
   from 768 px sets them a little tighter, so all eight fit it at 1440 x 900. */
[data-reasons] .fn-pills { display: grid; grid-template-columns: minmax(0, 1fr); }
[data-reasons] .fn-pill span { width: 100%; padding-inline: 20px; }
/* Short phones (MN-4): a smaller head, tighter answers and the footer in one row (Skip, then
   Send), so the eight answers fit above it. */
@media (max-width: 767.98px) and (max-height: 740px) {
  .fn-sheet__scroll { padding-top: 22px; }
  .fn-sheet__title { font-size: 26px; line-height: 30px; }
  .fn-sheet .fn-q { margin-top: 20px; }
  .fn-sheet .fn-pills { gap: 6px; }
  .fn-sheet .fn-pill span { min-height: 44px; padding-block: 10px; }
  .fn-sheet__foot { grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: 16px; padding-top: 10px; }
  .fn-sheet__foot [data-survey-send] { order: 2; }
}

/* The return card replaces the questions. Taller than its capped panel (a phone held sideways,
   large text, a long line or an error), it scrolls inside it, so every action stays reachable
   (Codex #8, CM-2); while more waits below, its lower edge fades (survey.js sets .is-more). */
.fn-return {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 32px max(var(--gutter), env(safe-area-inset-right)) calc(16px + env(safe-area-inset-bottom)) max(var(--gutter), env(safe-area-inset-left));
}
.fn-return.is-more {
  -webkit-mask-image: linear-gradient(#000 calc(100% - 24px), transparent);
  mask-image: linear-gradient(#000 calc(100% - 24px), transparent);
}
.fn-return__title {
  margin: 0;
  padding-right: 40px;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 26px;
  line-height: 30px;
  letter-spacing: -0.008em;
  color: var(--on-band-1);
  text-wrap: balance;
}
.fn-return__line { margin: 12px 0 0; max-width: 46ch; font-size: 16px; line-height: 25px; color: var(--on-band-2); }
.fn-return__line a { color: var(--on-band-1); }
.fn-return__note { margin-top: 10px; }
/* The decision's button, reassurance and terms line again (VQ-16, Codex #22), centred under the
   full-width button together with "Back to the page", like "Skip and go back" (VQ-15, VIS-01).
   "Back to the page" keeps 8 px clear of the terms link's 45 px target (CM-4). */
.fn-return [data-return-reserve] { margin-top: 24px; }
.fn-return .fn-msg, .fn-return .fn-reassure { text-align: center; }
.fn-return .fn-reassure { margin-top: 10px; }
.fn-return .fn-secure { justify-content: center; }
.fn-return__back { display: flex; justify-content: center; width: 100%; margin-top: 22px; }

@media (min-width: 768px) {
  .fn-sheet { align-items: center; justify-items: center; }
  .fn-sheet__panel,
  .fn-sheet.is-return .fn-sheet__panel {
    width: min(560px, calc(100vw - 48px));
    height: auto;
    max-height: 90vh;
    max-height: 90svh;
    border-radius: 32px;
    box-shadow: var(--edge-dark), 0 40px 100px -30px rgb(0 0 0 / .8);
  }
  .fn-sheet__scroll { padding: 40px 40px 28px; }
  [data-reasons] .fn-pills { gap: 6px; }
  [data-reasons] .fn-pill span { min-height: 44px; padding-block: 10px; }
  .fn-sheet__foot { padding: 16px 40px 20px; }
  .fn-return { padding: 40px; }
  .fn-sheet__x { top: 16px; right: 16px; }
}
/* Page scroll lock while the sheet is open (survey.js sets the class). */
html.fn-locked, html.fn-locked body { overflow: hidden; }


/* --------------------------------------------------------------------------
   7. /thank-you (design-system 5.16, motion E19, E21)
   -------------------------------------------------------------------------- */

.fn-thanks { padding: 16px 0 64px; } /* VQ-24: no tall empty graphite under the last line */
@media (min-width: 1024px) { .fn-thanks { padding: 56px 0 112px; } }
.fn-col--wide { max-width: calc(560px + 2 * var(--gutter)); }

/* While the payment confirms. The line shows only if confirming takes longer
   than 300 ms, so a quick answer never flashes it. */
.fn-confirming { display: grid; gap: 24px; justify-items: start; }
.fn-confirming__line {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 16px;
  line-height: 24px;
  color: var(--on-band-2);
  animation: fn-appear 0s linear 300ms both;
}
.fn-confirming .fn-founder { animation: fn-appear 0s linear 300ms both; }
@keyframes fn-appear { from { visibility: hidden; } to { visibility: visible; } }
/* data-ty (thankyou.js): "done" (this browser's reservation, founding or standard by the
   payment's own tier on html[data-tier]), "received" (a browser that only typed a known
   address: its $3 is confirmed, never a number), "pending"; none while confirming. */
html[data-ty="done"] .fn-confirming,
html[data-ty="received"] .fn-confirming,
html[data-ty="pending"] .fn-confirming { display: none; }
html:not([data-ty="done"]) .fn-done { display: none; }
html:not([data-ty="received"]) .fn-received { display: none; }
html:not([data-ty="pending"]) .fn-pending { display: none; }

.fn-pending__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 24px; margin-top: 24px; }

.fn-done .fn-h1 { max-width: 16ch; }
.fn-done .fn-h1 .fn-num { white-space: nowrap; }

/* Money first (p5 A-F3), as two lines (Codex #30): what was paid and what remains, then when
   the balance is charged. Above the card on phones, at the top of the right column on desktop. */
.fn-money { margin: 14px 0 0; max-width: 40ch; }
.fn-money__line { margin: 0; font-size: 15px; line-height: 22px; color: var(--on-band-1); }
.fn-money__when { margin: 2px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); text-wrap: pretty; }
.fn-money__dot { color: var(--on-band-3); }

/* The founding card. */
.fn-founder {
  position: relative;
  box-sizing: border-box;
  width: min(342px, 100%);
  aspect-ratio: 1.586;
  margin-top: 28px;
  padding: 20px 22px;
  border-radius: var(--r-founder);
  overflow: hidden;
  isolation: isolate;
  background:
    radial-gradient(120% 90% at 0% 0%, #3a3837 0%, rgb(58 56 55 / 0) 60%),
    radial-gradient(70% 60% at 100% 100%, rgb(255 182 72 / .22) 0%, rgb(255 182 72 / 0) 70%),
    radial-gradient(60% 50% at 0% 100%, rgb(182 207 221 / .14) 0%, rgb(182 207 221 / 0) 70%),
    #151413;
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / .08), 0 40px 80px -30px rgb(0 0 0 / .7);
  color: var(--on-band-1);
}
.fn-founder__logo { position: absolute; top: 20px; left: 22px; width: 64px; color: var(--on-band-2); }
.fn-founder__logo svg { display: block; width: 100%; height: auto; }
.fn-founder__label {
  position: absolute;
  top: 22px;
  right: 22px;
  font-size: 11px;
  line-height: 14px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--on-band-2);
}
.fn-founder__num {
  position: absolute;
  left: 22px;
  bottom: 30px;
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0;
}
.fn-founder__n {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 64px;
  line-height: 56px;
  letter-spacing: -0.016em;
  color: var(--signal);
  font-feature-settings: var(--nums);
}
.fn-founder__of { font-size: 15px; line-height: 20px; color: var(--on-band-2); }
/* A hundred ticks along the bottom edge, the member's own one in gold. */
.fn-founder__ticks {
  position: absolute;
  left: 22px;
  right: 22px;
  bottom: 16px;
  height: 4px;
  -webkit-mask-image: linear-gradient(90deg, #000 0 50%, transparent 50%);
  mask-image: linear-gradient(90deg, #000 0 50%, transparent 50%);
  -webkit-mask-size: 1% 100%;
  mask-size: 1% 100%;
  -webkit-mask-repeat: repeat-x;
  mask-repeat: repeat-x;
  background: rgb(243 239 233 / .16);
}
.fn-founder__ticks i {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--at, 0%);
  width: 1%;
  background: var(--signal);
}
/* The skeleton while confirming: same size, quiet fill, one moving light. */
.fn-founder--skeleton {
  margin-top: 0;
  background: var(--band-1);
  box-shadow: var(--edge-dark);
}
.fn-founder--skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, rgb(243 239 233 / 0) 30%, rgb(243 239 233 / .07) 50%, rgb(243 239 233 / 0) 70%);
  transform: translateX(-100%);
}
@media (min-width: 1024px) {
  .fn-founder { width: 420px; padding: 24px 28px; }
  .fn-founder__logo { top: 26px; left: 28px; width: 72px; }
  .fn-founder__label { top: 28px; right: 28px; }
  .fn-founder__num { left: 28px; bottom: 36px; }
  .fn-founder__n { font-size: 80px; line-height: 70px; }
  .fn-founder__ticks { left: 28px; right: 28px; bottom: 20px; }
}

/* The reserved headband right under the card (IMP-08, UM-13): an object resting in a pool of
   lit graphite, not a second card (Codex #7, DQ-05): no frame, radius or card shape, and on
   phones a 128 px stage, so the founding-price line and "What happens next" stay near the
   first screen. The finish is named under it, centred like /reserve's stage caption, only once
   one was chosen (K3); thankyou.js picks the finish and shows the name. */
.fn-mine { width: min(342px, 100%); margin: 8px 0 0; }
.fn-mine__stage {
  display: grid;
  place-items: center;
  height: 128px;
  background: radial-gradient(closest-side, rgb(58 56 55 / .9), rgb(58 56 55 / 0));
}
.fn-mine__img { display: block; width: auto; height: 108px; filter: drop-shadow(0 12px 14px rgb(0 0 0 / .45)); }
.fn-mine__name { margin: 4px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); text-align: center; }
/* No finish chosen: no name, but the line stays, so a name arriving on a tap far below moves
   nothing (iOS Safari has no scroll anchoring). */
.fn-mine__name.is-unnamed { visibility: hidden; }
@media (min-width: 1024px) {
  .fn-mine { width: 420px; }
  .fn-mine__stage { height: 192px; }
  .fn-mine__img { height: 168px; filter: drop-shadow(0 16px 20px rgb(0 0 0 / .45)); }
  .fn-mine__name { margin-top: 6px; }
}

.fn-lead { margin: 28px 0 0; max-width: 40ch; font-size: 17px; line-height: 25px; color: var(--on-band-1); }

/* What happens next: three steps on a thread (design-system 5.10, in graphite). */
.fn-steps { position: relative; margin: 20px 0 0; padding: 0 0 0 32px; list-style: none; }
.fn-steps::before {
  content: "";
  position: absolute;
  left: 8px;
  top: 10px;
  bottom: 10px;
  width: 2px;
  border-radius: 1px;
  background: var(--hair-band);
}
.fn-step { position: relative; margin: 0; padding: 0 0 24px; }
.fn-step:last-child { padding-bottom: 0; }
.fn-step::before {
  content: "";
  position: absolute;
  left: -28px;
  top: 9px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--band-0);
  box-shadow: inset 0 0 0 1.5px var(--on-band-2);
}
.fn-step:first-child::before { background: var(--on-band-1); box-shadow: none; }
.fn-step__title {
  display: block;
  margin: 0;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 22px;
  line-height: 28px;
  letter-spacing: -0.004em;
  color: var(--on-band-1);
}
.fn-step__text { display: block; margin-top: 4px; max-width: 40ch; font-size: 16px; line-height: 25px; color: var(--on-band-2); }

.fn-refund { margin: 28px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); }

.fn-taps__form { margin: 0; }
.fn-taps__line { margin: 6px 0 0; font-size: 14px; line-height: 20px; color: var(--on-band-2); }
.fn-taps__send { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px; margin-top: 28px; }
.fn-taps__done { margin: 0; font-size: 15px; line-height: 20px; color: var(--on-band-1); }
/* Send as wide as its column at every width, like the sheet's (VQ-17, DQ-07); the status line
   goes under it. */
.fn-taps__send .fn-btn { width: 100%; }
/* "What made you reserve?" (data-rows): on phones one tidy column of full-width rows, like the
   sheet's reasons (VIS-06, TASTE-11); the short answers below stay pills. */
@media (max-width: 479.98px) {
  .fn-taps [data-rows] .fn-pills { display: grid; grid-template-columns: minmax(0, 1fr); }
  .fn-taps [data-rows] .fn-pill span { width: 100%; padding-inline: 20px; }
}
/* "Which finish do you want?": each finish shows its colour, the landing's swatches (TASTE-13,
   VQ-40, UX-07). The ring keeps Obsidian visible on graphite and Ivory on the checked cream. */
.fn-swatch {
  flex: none;
  width: 16px;
  height: 16px;
  margin: 0 10px 0 -4px;
  border-radius: 50%;
  background: var(--c);
  box-shadow: inset 0 0 0 1px var(--field-line);
}
.fn-pill input:checked + span .fn-swatch { box-shadow: inset 0 0 0 1px rgb(27 29 26 / .3); }

/* One width for the cards in the phone column (VQ-34); on desktop the referral card fills
   the right column. */
.fn-ref { width: min(342px, 100%); margin-top: 48px; }
.fn-ref .fn-card__title { font-family: var(--font-serif); font-weight: 300; font-size: 24px; line-height: 28px; letter-spacing: -0.004em; }
.fn-ref p { font-size: 16px; line-height: 24px; }

.fn-pending .fn-lead { color: var(--on-band-2); }

/* Desktop (Codex #29): two columns, 440 + 520 inside 1040. The H1, then the card and the
   headband on the left; the money lines at the top right, everything after them under it.
   The left pair stays in view while the right column scrolls, where the window is tall enough.
   The phone stack above is unchanged. */
@media (min-width: 1024px) {
  .fn-col--wide { max-width: calc(1040px + 2 * var(--gutter)); }
  .fn-done {
    display: grid;
    grid-template-columns: minmax(0, 440px) minmax(0, 520px);
    grid-template-rows: auto auto 1fr;
    grid-template-areas: "title money" "title main" "keep main";
    justify-content: space-between;
    column-gap: 48px;
    align-items: start;
  }
  .fn-done > .fn-h1 { grid-area: title; }
  .fn-done > .fn-money { grid-area: money; margin-top: 10px; }
  .fn-money__line { font-size: 17px; line-height: 24px; }
  .fn-money__when { font-size: 15px; line-height: 22px; }
  .fn-done__keep { grid-area: keep; }
  .fn-done__main { grid-area: main; }
  .fn-ref { width: auto; }
}
@media (min-width: 1024px) and (min-height: 760px) {
  .fn-done__keep { position: sticky; top: 32px; }
}


/* --------------------------------------------------------------------------
   8. /privacy and /terms: readable pages on the protected ground
   -------------------------------------------------------------------------- */

/* Side padding clears the notch on a phone held in landscape (safe-area insets, p5 A-F10). */
.fn-doc {
  position: relative;
  z-index: 1; /* above the ground's absolutely positioned glows */
  padding: 112px max(24px, env(safe-area-inset-right)) 128px max(24px, env(safe-area-inset-left));
  color: var(--ink-2);
  -webkit-font-smoothing: antialiased;
}
@media (min-width: 768px) { .fn-doc { padding-left: max(56px, env(safe-area-inset-left)); padding-right: max(56px, env(safe-area-inset-right)); } }
@media (min-width: 1024px) { .fn-doc { padding: 144px max(64px, calc((100% - 1440px) / 2)) 160px; } }
.fn-doc__inner { max-width: 680px; }
/* "Back to the page" above the heading (Codex #33): the Text button, 44 px tall. doc.js points
   it at the visitor's form section (welv_back) or "/", or goes back to our page it came from. */
.fn-doc__back {
  display: flex;
  align-items: center;
  width: fit-content;
  min-height: 44px;
  margin: 0 0 16px;
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 20px;
  color: var(--ink-2);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  transition: color 200ms linear;
}
.fn-doc__back:active { opacity: .6; transition-duration: 0s; }
@media (hover: hover) and (pointer: fine) { .fn-doc__back:hover { color: var(--ink-1); } }
.fn-doc h1 {
  margin: 0;
  max-width: 14ch;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: clamp(2.5rem, 1.6rem + 3.6vw, 4rem);
  line-height: 1.04;
  letter-spacing: -0.012em;
  color: var(--ink-2);
  text-wrap: balance;
}
.fn-doc h1 em { font-style: italic; font-weight: 200; letter-spacing: -0.004em; padding-right: .04em; }
.fn-doc__lead { margin: 28px 0 0; max-width: 56ch; font-size: 19px; line-height: 28px; color: var(--ink-2); }
.fn-doc h2 {
  margin: 48px 0 0;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 26px;
  line-height: 30px;
  letter-spacing: -0.004em;
  color: var(--ink-2);
}
.fn-doc p { margin: 12px 0 0; max-width: 60ch; font-size: 17px; line-height: 26px; color: var(--ink-2); text-wrap: pretty; }
.fn-doc a:not([class]) { color: var(--ink-1); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.fn-doc__list { margin: 36px 0 0; padding: 0; list-style: none; border-top: 1px solid var(--hair); }
/* Every rule spans the 680 px column, the one under the heading too (VIS-12). */
.fn-doc__list li { margin: 0; padding: 18px 0; border-bottom: 1px solid var(--hair); font-size: 17px; line-height: 26px; color: var(--ink-2); }
.fn-doc__list strong { font-weight: 400; color: var(--ink-1); }
/* /privacy: the three cookies, name then lifetime and purpose. */
.fn-doc__cookies { display: grid; gap: 10px; margin: 12px 0 0; }
.fn-doc__cookies div { display: grid; grid-template-columns: 8.5em minmax(0, 1fr); gap: 0 16px; }
.fn-doc__cookies dt { margin: 0; color: var(--ink-1); overflow-wrap: anywhere; }
.fn-doc__cookies dd { margin: 0; color: var(--ink-2); }
@media (max-width: 479.98px) { .fn-doc__cookies div { grid-template-columns: minmax(0, 1fr); } }
.fn-doc__meta { margin: 64px 0 0; padding-top: 24px; border-top: 1px solid var(--hair-2); max-width: 60ch; }
.fn-doc__list + .fn-doc__meta { margin-top: 32px; padding-top: 0; border-top: 0; }
.fn-doc__meta p { margin: 0; font-size: 15px; line-height: 22px; }
.fn-doc__meta p + p { margin-top: 8px; }
/* ink-2, not ink-3: the date can sit on the ground's gold glow, where ink-3 drops to about 4.1:1. */
.fn-doc__date { color: var(--ink-2); font-size: 14px !important; }
/* The home-indicator inset under the footer, in the footer's own end colour (MN-10, K5; the
   landing's .footer-frame in site.css). On <body> the same padding showed the cream page as a
   band under the graphite footer. */
.fn-footframe::after { content: ""; display: block; height: env(safe-area-inset-bottom, 0px); background: #1c1b1a; }


/* --------------------------------------------------------------------------
   9. /mock-checkout (lab only): a plain page that cannot be mistaken for the
   real thing.
   -------------------------------------------------------------------------- */

html.fn-root--test { background-color: #e9e2d8; }
.fn-test {
  box-sizing: border-box;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: 24px max(16px, env(safe-area-inset-right)) 24px max(16px, env(safe-area-inset-left));
  color: var(--ink-2);
}
.fn-test__card {
  box-sizing: border-box;
  width: min(400px, 100%);
  padding: 28px 24px 20px;
  border-radius: 24px;
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--hair), var(--sh-1);
  background-image: repeating-linear-gradient(-45deg, rgb(179 38 30 / .9) 0 10px, rgb(254 250 239 / 0) 10px 20px);
  background-size: 100% 8px;
  background-repeat: no-repeat;
}
.fn-test__tag {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  border-radius: var(--r-pill);
  background: var(--err);
  color: #fff;
  font-size: 12px;
  line-height: 16px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.fn-test h1 {
  margin: 14px 0 0;
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: 30px;
  line-height: 34px;
  letter-spacing: -0.008em;
  color: var(--ink-1);
}
.fn-test__amount { margin: 16px 0 0; font-size: 16px; line-height: 24px; color: var(--ink-2); }
.fn-test__amount b { font-weight: 400; color: var(--ink-1); }
.fn-test__actions { display: grid; gap: 10px; margin-top: 24px; }
.fn-test .fn-btn { font-size: 16px; }
.fn-test__pay { background: var(--ink-1); color: var(--paper); }
.fn-test__fail { background: transparent; color: var(--ink-1); box-shadow: inset 0 0 0 1px var(--ink-2); }
@media (hover: hover) and (pointer: fine) {
  .fn-test__pay:hover { background: #33352f; }
  .fn-test__fail:hover { background: rgb(74 71 65 / .06); }
}
.fn-test .fn-btn:disabled { opacity: .45; cursor: not-allowed; transform: none; }
.fn-test .fn-btn[aria-busy="true"] { opacity: .72; cursor: progress; }
.fn-test .fn-textlink { color: var(--ink-2); justify-self: center; }
.fn-test .fn-msg { color: var(--err); }
.fn-test__note { margin: 16px 0 0; font-size: 13px; line-height: 18px; color: var(--ink-3); }


/* --------------------------------------------------------------------------
   10. MOTION. Everything that moves sits behind no-preference, so under
   reduced motion every part shows its final state (motion-spec section 8).
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  /* E18: the one moving part of the reservation's first screen. */
  .fn-seats.is-filled .fn-strip__claimed { animation: fn-seat-fill 600ms var(--ease-settle) 120ms both; }

  /* E21: one light band over the skeleton card while confirming. */
  .fn-founder--skeleton::after { animation: fn-shimmer 1600ms linear infinite; }

  /* E19: the card arrives as an object, then one foil sweep. */
  .fn-founder.is-in { animation: fn-card-in 800ms var(--ease-settle) both; }
  .fn-founder.is-in::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(105deg, rgb(255 236 204 / 0) 35%, rgb(255 236 204 / .16) 48%, rgb(255 255 255 / .22) 50%, rgb(255 236 204 / 0) 65%);
    transform: translateX(-120%);
    animation: fn-foil 1200ms var(--ease-inout) 400ms 1 both;
  }

  /* E15: accordions open by height where the browser can animate to auto. */
  @supports (interpolate-size: allow-keywords) {
    html.fn-root { interpolate-size: allow-keywords; }
    .fn-faq details::details-content,
    .fn-disclose::details-content {
      height: 0;
      overflow: clip;
      transition: height 280ms var(--ease-out), content-visibility 280ms allow-discrete;
    }
    .fn-faq details[open]::details-content,
    .fn-disclose[open]::details-content { height: auto; }
  }
}
@media (prefers-reduced-motion: reduce) {
  .fn-btn, .fn-pill span, .fn-plus { transition: background-color 120ms linear, color 120ms linear, opacity 120ms linear; }
  .fn-btn:active, .fn-btn--signal:hover { transform: none; }
}
@keyframes fn-seat-fill { from { transform: scaleX(0); } }
@keyframes fn-shimmer { to { transform: translateX(100%); } }
@keyframes fn-card-in { from { opacity: 0; transform: translateY(24px) scale(.96); } }
@keyframes fn-foil { to { transform: translateX(120%); } }

/* E4: below-the-fold groups wait hidden only once JS has parked them. */
html.fn-js [data-fn-reveal="wait"] > * { opacity: 0; }
