:root {
  --bg: #0A0A0B;
  --surface: #141416;
  --hairline: #26262A;
  --text: #F5F5F2;
  --muted: #8E8E93;
  --accent: #C8FF4D;
  --on-accent: #0A0A0B;
  --gutter: 20px;
  --gl: max(var(--gutter), env(safe-area-inset-left, 0px));
  --gr: max(var(--gutter), env(safe-area-inset-right, 0px));
  --ease: cubic-bezier(.32,.72,0,1);
  color-scheme: dark;
}
@media (min-width: 720px) { :root { --gutter: 40px; } }

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: calc(88px + env(safe-area-inset-top, 0px)); }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 17px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}
h1, h2, h3, p, ol, figure { margin: 0; padding: 0; }
h1, h2, h3, b, strong, summary { font-weight: 500; }
small { font-size: inherit; }
button, input { font: inherit; color: inherit; }
a { color: inherit; text-underline-offset: 3px; text-decoration-thickness: 1px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px; }

.wrap { width: 100%; max-width: 1280px; margin: 0 auto; padding: 0 var(--gr) 0 var(--gl); }
.skip {
  position: absolute; left: 12px; top: -60px; z-index: 20;
  background: var(--text); color: var(--bg); padding: 10px 14px; border-radius: 8px;
}
.skip:focus { top: 12px; }

.eyebrow { color: var(--muted); font-size: 15px; margin-bottom: 20px; }
h1 {
  font-size: clamp(46px, 6.6vw, 92px);
  line-height: 0.98;
  letter-spacing: -0.042em;
  max-width: 13ch;
}
h2 {
  font-size: clamp(34px, 4.2vw, 56px);
  line-height: 1.04;
  letter-spacing: -0.034em;
}
h3 { font-size: 19px; line-height: 1.25; letter-spacing: -0.012em; }

/* Nav */
.nav {
  position: sticky; top: 0; z-index: 10;
  background: var(--bg);
  border-bottom: 1px solid var(--hairline);
  padding-top: env(safe-area-inset-top, 0px);
}
/* Safari on iPhone can draw page content above the sticky bar, under its own top bar. A tall black
   strip rising from the bar's top edge covers that area, so nothing shows through above the nav. */
.nav::before { content: ""; position: absolute; left: 0; right: 0; bottom: 100%; height: 100vh; background: var(--bg); pointer-events: none; }
.nav-row { display: flex; align-items: center; justify-content: space-between; height: 64px; gap: 16px; }
.brand { display: inline-flex; align-items: center; min-height: 44px; gap: 9px; font-weight: 500; font-size: 18px; letter-spacing: -0.02em; text-decoration: none; }
.brand-mark { width: 22px; height: 22px; fill: var(--text); }
.brand-cut { fill: var(--bg); }
.nav-links { display: flex; align-items: center; gap: 28px; font-size: 15px; }
.nav-links a { display: inline-flex; align-items: center; min-height: 44px; text-decoration: none; color: var(--muted); }
@media (hover: hover) { .nav-links a:hover { color: var(--text); } }
.nav-links .nav-cta { color: var(--text); }
@media (max-width: 719px) { .nav-links a:not(.nav-cta) { display: none; } }

/* Hero */
.hero { padding: 72px 0 88px; }
.hero-grid { display: grid; gap: 64px; align-items: center; }
.lede { color: var(--muted); font-size: clamp(18px, 1.6vw, 21px); line-height: 1.42; margin-top: 28px; max-width: 34em; }
.hero .waitlist { margin-top: 40px; max-width: 520px; }
@media (min-width: 1000px) {
  .hero { padding: 104px 0 128px; }
  .hero-grid { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: 72px; }
}

/* Waitlist form */
.waitlist label { display: block; font-size: 15px; margin-bottom: 8px; }
.field-row { display: flex; flex-direction: column; gap: 10px; }
.waitlist input[type=email] {
  flex: 1 1 auto; min-width: 0; width: 100%; height: 52px; padding: 0 16px;
  background: var(--surface);
  /* #8E8E93 rather than the hairline: a field boundary needs 3:1 against the page. */
  border: 1px solid var(--muted);
  border-radius: 10px;
}
.waitlist input[type=email]::placeholder { color: var(--muted); opacity: 1; }
.waitlist input[aria-invalid=true] { border-color: var(--text); border-width: 2px; padding: 0 15px; }
.waitlist button {
  height: 52px; padding: 0 22px; flex: none;
  background: var(--accent); color: var(--on-accent);
  font-weight: 500; border: 0; border-radius: 10px; cursor: pointer;
}
@media (hover: hover) { .waitlist button:not([disabled]):hover { background: var(--text); } }
.waitlist button[disabled] { opacity: .7; cursor: progress; }
@media (min-width: 480px) { .field-row { flex-direction: row; } }
.form-msg { margin-top: 12px; font-size: 15px; }
.form-msg:empty { display: none; }
.form-msg.is-error::before { content: "! "; font-weight: 500; }
.waitlist.is-done label, .waitlist.is-done .field-row, .waitlist.is-done .fine { display: none; }
.waitlist.is-done .form-msg {
  margin: 0; padding: 16px 18px; font-size: 17px;
  background: var(--surface); border: 1px solid var(--hairline); border-left: 2px solid var(--accent); border-radius: 10px;
}
.fine { margin-top: 12px; font-size: 14px; color: var(--muted); }
/* A 44px touch area around a short inline link, without moving the text around it. */
.fine a, .updated a { display: inline-block; padding: 12px 0; margin: -12px 0; }
.noscript-msg { display: block; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Hero card stack */
.stack { justify-self: center; width: 100%; max-width: 440px; }
/* The negative margin and matching padding make room for the live stack's hover lift and focus
   ring. They're here, not only on the live stack, so upgrading doesn't change this box. */
.stack-cards { display: flex; flex-direction: column; margin: -12px -12px 0; padding: 12px 12px 0; }
.scard {
  display: flex; justify-content: space-between; gap: 12px;
  height: 84px; margin-bottom: -28px; padding: 15px 20px;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 16px;
  font-size: 15px;
}
.stack-cards:not(.is-live) .scard > span:last-child { color: var(--muted); }
.scard > span { line-height: 26px; }
.scard > span:first-child, .scard-head span { font-size: 17px; font-weight: 500; letter-spacing: -0.01em; }
.scard-top {
  flex-direction: column; height: auto; aspect-ratio: 1.586; margin: 0; padding: 15px 20px 20px;
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}
.scard-top span:last-child { color: var(--on-accent); }
.scard-head { display: flex; justify-content: space-between; align-items: center; min-height: 26px; }
.scard-head svg, .scard-lime .scard-mark { width: 30px; height: 30px; fill: var(--on-accent); }
.scard-foot { display: flex; flex-direction: column; gap: 2px; font-size: 15px; font-weight: 400; }
.scard-num { font-size: clamp(38px, 11vw, 52px); font-weight: 500; letter-spacing: -0.035em; line-height: 1; }

/* Live stack (built by site.js from the static cards above). Like a wallet: every card is a
   full-size card the whole time, and the stacking order never changes. Cards behind the chosen
   one peek out above it; cards in front of it slide down out of its way and peek out below,
   tucked under the bottom edge. Choosing a card only moves cards with translate3d and fades the
   lime layer, so there is nothing to reflow, repaint or re-stack mid-move. The box keeps the
   static stack's height, so upgrading can't shift the page. */
.stack-cards { --peek: 56px; --swap: 650ms; --swap-ease: cubic-bezier(.45,0,.25,1); }
.stack-cards.is-live { display: block; position: relative; overflow: hidden; }
.stack-cards.is-live::before { content: ""; display: block; padding-top: calc(3 * var(--peek) + 100% / 1.586); }
.stack-cards.is-live .scard {
  display: block; position: absolute; top: 12px; left: 12px; width: calc(100% - 24px); height: auto; aspect-ratio: 1.586;
  margin: 0; padding: 0; background: none; border: 0; border-radius: 16px; text-align: left; color: var(--text); cursor: pointer;
  /* --a strips of peek plus --b card heights (a translate percentage is the card's own height). */
  transform: translate3d(0, calc(var(--a, 0) * var(--peek) + var(--b, 0) * 100%), 0);
  transition: transform var(--swap) var(--swap-ease);
  will-change: transform;
}
/* The faces are layers of their own and would paint over the button's outline, so the ring is
   drawn on a layer above them, and it moves with the hover lift. */
.stack-cards.is-live .scard:focus-visible { outline: 0; }
.scard-inner::after { content: ""; position: absolute; inset: 3px; border-radius: 13px; pointer-events: none; }
.scard:focus-visible .scard-inner::after { box-shadow: 0 0 0 2px var(--accent); }
.scard.is-selected:focus-visible .scard-inner::after { box-shadow: 0 0 0 2px var(--on-accent); }
.scard-inner { position: absolute; inset: 0; display: block; transition: transform .3s var(--swap-ease); }
/* Two faces with the same layout, so the text sits in the same place on both: the dark one is
   always there, and the lime one lies on top and only fades. */
.scard-face, .scard-lime {
  position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-between;
  padding: 15px 20px 20px; border-radius: 16px; font-size: 15px;
}
.scard-face { background: var(--surface); border: 1px solid var(--hairline); }
/* The lime never dims mid-swap: the chosen card turns lime early, while little of it is uncovered,
   and the card it replaces stays lime until it's mostly covered or tucked away, then fades. */
.scard-lime {
  background: var(--accent); border: 1px solid var(--accent);
  opacity: 0; transition: opacity 360ms ease-in-out 280ms; will-change: opacity;
}
.scard.is-selected .scard-lime { opacity: 1; transition: opacity 340ms cubic-bezier(.3,0,.3,1); }
/* Passed over by a quick second tap before it had turned fully lime: it lets go at once. */
.scard.is-passed .scard-lime { transition: opacity 240ms ease-out; }
.scard-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; min-height: 26px; }
.scard-name { font-size: 17px; font-weight: 500; letter-spacing: -0.01em; }
.stack-cards.is-live .scard-face .scard-meta, .stack-cards.is-live .scard-face .scard-foot span:last-child { color: var(--muted); }
.stack-cards.is-live .scard-lime, .stack-cards.is-live .scard-lime span { color: var(--on-accent); }
.stack-cards.is-live .scard-foot { font-size: 15px; }
/* The lift sits on an inner layer, so it can't disturb a card's travel or move its hit area. */
@media (hover: hover) {
  .stack-cards.is-live .scard:hover .scard-inner { transform: translate3d(0, -5px, 0); }
}

/* Sections */
.demos, .how, .faq, .join { border-top: 1px solid var(--hairline); padding: 80px 0; }
@media (min-width: 1000px) { .demos, .how, .faq, .join { padding: 120px 0; } }
.sec-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end; gap: 24px 48px; margin-bottom: 56px; }
.demos-note { max-width: 390px; color: var(--muted); font-size: 15px; }

/* Demos */
.demo-grid { display: grid; gap: 64px 24px; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 680px) { .demo-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1180px) { .demo-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* Phones: a swipe carousel, bleeding to the screen edge so the next card peeks in. */
@media (max-width: 679px) {
  .demo-grid {
    display: flex; gap: 16px;
    margin: 0 calc(-1 * var(--gr)) 0 calc(-1 * var(--gl));
    padding: 0 var(--gr) 0 var(--gl);
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory; scroll-padding: 0 var(--gr) 0 var(--gl);
    overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .demo-grid::-webkit-scrollbar { display: none; }
  .demo { flex: 0 0 min(286px, calc(100% - 44px)); scroll-snap-align: start; scroll-snap-stop: always; }
}
.demo h3 { margin-top: 24px; }
.demo h3 span { color: var(--muted); font-weight: 400; margin-right: 10px; }
.demo > p { margin-top: 8px; color: var(--muted); font-size: 15px; line-height: 1.45; max-width: 30em; }

.phone {
  position: relative; overflow: hidden;
  width: 100%; max-width: 286px; height: 520px;
  background: var(--surface);
  border: 1px solid var(--hairline); border-radius: 38px;
  font-size: 14px; line-height: 1.3;
}
@media (max-width: 679px) { .phone { margin: 0 auto; } }
.phone::before {
  content: ""; position: absolute; z-index: 2; top: 11px; left: 50%;
  width: 70px; height: 20px; margin-left: -35px;
  background: var(--bg); border-radius: 12px;
}
/* Every change of screen is the same soft crossfade, opacity only. Screens are opaque, and the
   incoming one fades in on top while the outgoing one stays put underneath until it's covered,
   so the phone never dims or goes blank in between. --xease matches RESET_EASE in site.js. */
.phone { --xfade: 1000ms; --xease: cubic-bezier(.45,0,.55,1); }
.screen {
  position: absolute; inset: 0; z-index: 0; display: flex; flex-direction: column; gap: 10px;
  padding: 52px 16px 20px; background: var(--surface);
  opacity: 0; visibility: hidden;
  transition: opacity 0s linear var(--xfade), visibility 0s linear var(--xfade);
}
.screen.on { z-index: 1; opacity: 1; visibility: visible; transition: opacity var(--xfade) var(--xease); }
/* The loop's way back to the start: a still copy of the finished screen fades out over the
   first screen, which was reset underneath it while it couldn't be seen. */
.phone-shot { position: absolute; inset: 0; z-index: 1; background: var(--surface); pointer-events: none; }
.phone-shot *, .phone.is-instant, .phone.is-instant * { transition: none !important; }
.phone-shot * { animation: none !important; }
/* Typing: the whole text is laid out from the start and each character only changes opacity, so
   nothing reflows and nothing is edited per frame. Text is only cleared while it can't be seen. */
.ty { position: relative; display: inline-block; white-space: pre-wrap; color: var(--text); }
.ty i { font-style: normal; opacity: 0; }
.ty.typed i { opacity: 1; transition: opacity .08s linear; transition-delay: calc(var(--n) * var(--speed, 72ms)); }
.ty-ph { position: absolute; left: 0; top: 0; color: var(--muted); white-space: nowrap; transition: opacity .08s linear; }
.ty.typed .ty-ph { opacity: 0; }
.ty-caret { position: absolute; left: 0; top: .1em; width: 1.5px; height: 1.05em; background: var(--text); opacity: 0; }
.ty-caret.on { opacity: 1; }
.p-sub { color: var(--muted); font-size: 13px; }
.p-title { font-size: 21px; font-weight: 500; letter-spacing: -0.02em; margin-bottom: 8px; }
.p-input, .p-field, .p-row {
  background: var(--bg); border: 1px solid var(--hairline); border-radius: 12px; padding: 12px;
}
.p-input { color: var(--muted); }
.p-row { display: flex; align-items: center; gap: 10px; min-height: 58px; }
.p-row-plain { min-height: 52px; }
.p-grow { flex: 1; min-width: 0; }
.p-grow small, .p-field small, .p-split small { display: block; color: var(--muted); font-size: 12px; }
.p-field { display: flex; flex-direction: column; gap: 2px; font-size: 16px; }
.p-avatar {
  flex: none; width: 30px; height: 30px; display: grid; place-items: center;
  background: var(--surface); border: 1px solid var(--hairline); border-radius: 50%; font-size: 13px;
}
.p-spin {
  flex: none; width: 16px; height: 16px; border: 2px solid var(--hairline); border-top-color: var(--text); border-radius: 50%;
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.phone.is-paused .p-spin { animation-play-state: paused; }
.p-check {
  position: relative; flex: none; width: 20px; height: 20px; border-radius: 50%;
  background: none; border: 1px solid var(--muted);
  transition: background .35s ease, border-color .35s ease;
}
.p-check.on { background: var(--text); border-color: var(--text); }
.p-check.on::after {
  content: ""; position: absolute; left: 6px; top: 2.5px; width: 5px; height: 10px;
  border: solid var(--bg); border-width: 0 1.5px 1.5px 0; transform: rotate(42deg);
}
[data-in]:not(.screen):not(.p-check) { opacity: 0; transform: translateY(6px); transition: opacity .45s var(--ease), transform .45s var(--ease); }
[data-in].on:not(.screen) { opacity: 1; transform: none; }
.p-bottom { margin-top: auto; }
.p-note { color: var(--muted); font-size: 13px; margin-top: 6px; }
.p-done { color: var(--text); font-size: 14px; text-align: center; padding: 12px; border-top: 1px solid var(--hairline); }
.p-btn {
  display: block; text-align: center; padding: 12px; border-radius: 12px;
  background: var(--text); color: var(--bg); font-weight: 500;
}
.p-btn-line { background: none; color: var(--text); border: 1px solid var(--muted); }
.p-split { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.p-splitbar, .p-bar { height: 6px; background: var(--hairline); border-radius: 3px; overflow: hidden; }
.p-splitbar i, .p-bar i {
  display: block; height: 100%; background: var(--text); border-radius: 3px;
  transform: scaleX(0); transform-origin: left; transition: transform .8s var(--ease);
}
.b40 { transform: scaleX(.4) !important; }
.b43 { transform: scaleX(.4267) !important; }
.b48 { transform: scaleX(.48) !important; }
.b50 { transform: scaleX(.5) !important; }
.b57 { transform: scaleX(.5728) !important; }
.p-splitrow { display: flex; justify-content: space-between; gap: 8px; font-size: 12.5px; color: var(--muted); }
.p-splitrow b { color: var(--text); min-width: 4ch; text-align: right; }
.p-row b, .p-tx b { font-weight: 500; }

.pcard {
  display: flex; flex-direction: column; justify-content: space-between;
  aspect-ratio: 1.586; padding: 14px 16px; border-radius: 14px; font-size: 16px; font-weight: 500;
}
.pcard-accent { background: var(--accent); color: var(--on-accent); }
.pcard-foot { display: flex; justify-content: space-between; font-size: 12.5px; font-weight: 400; }
.pcard-rise.is-rising { animation: rise .75s var(--ease); }
@keyframes rise { from { transform: translateY(26px); opacity: 0; } }

.wallet { display: flex; flex-direction: column; margin-top: 2px; }
.wallet-card {
  height: 54px; margin-bottom: -10px; padding: 12px 16px;
  background: var(--bg); border: 1px solid var(--hairline); border-radius: 14px 14px 0 0; color: var(--muted); font-size: 13px;
}
.wallet .pcard { position: relative; }
.pay-state { position: relative; flex: 1; display: grid; place-items: center; text-align: center; color: var(--muted); }
.pay-state > * { grid-area: 1 / 1; }
.pay-done { display: flex; flex-direction: column; align-items: center; gap: 10px; color: var(--text); }
.pay-done b { font-size: 24px; letter-spacing: -0.02em; }

.p-hero { display: flex; flex-direction: column; font-size: 42px; font-weight: 500; letter-spacing: -0.035em; line-height: 1.05; margin: 2px 0 8px; }
.p-hero small { font-size: 13px; font-weight: 400; letter-spacing: 0; color: var(--muted); margin-top: 4px; }
.p-pair { display: flex; justify-content: space-between; gap: 8px; margin-top: 4px; color: var(--muted); font-size: 13px; }
.p-pair b { color: var(--text); min-width: 7ch; text-align: right; }
.p-tx { display: flex; align-items: center; gap: 8px; margin-top: 10px; padding: 12px; background: var(--bg); border: 1px solid var(--hairline); border-radius: 12px; }
.rep { display: flex; flex-direction: column; gap: 16px; margin-top: 8px; }
.rep-row { display: grid; grid-template-columns: 1fr auto; gap: 6px 8px; font-size: 13.5px; }
.rep-row b { font-weight: 400; color: var(--muted); font-size: 12.5px; align-self: center; }
.rep-row .p-bar { grid-column: 1 / -1; }

/* Wallet mockups: stack first, tapped card second. Each PNG carries 8% clear margin on each side for the device shadow. */
.wallet-shot { display: grid; gap: 24px; align-items: center; margin-top: 56px; padding-top: 56px; border-top: 1px solid var(--hairline); }
.wallet-copy h3 { font-size: clamp(30px, 3.4vw, 44px); line-height: 1.06; letter-spacing: -0.03em; max-width: 13em; }
.wallet-copy p { margin-top: 14px; color: var(--muted); max-width: 26em; }
.wallet-figs { display: grid; gap: 32px; justify-items: center; min-width: 0; }
.wallet-shot figure { width: 100%; max-width: 420px; text-align: center; }
.wallet-shot .wallet-fig-2 { max-width: 320px; }
.wallet-shot img { display: block; width: 100%; height: auto; }
.wallet-shot figcaption { color: var(--muted); font-size: 14px; }
@media (min-width: 860px) {
  .wallet-shot { grid-template-columns: minmax(0, 3fr) minmax(0, 7fr); gap: 48px; margin-top: 88px; padding-top: 72px; }
  .wallet-figs { grid-template-columns: minmax(0, 5fr) minmax(0, 4fr); gap: 24px; align-items: end; justify-items: stretch; }
  .wallet-shot figure, .wallet-shot .wallet-fig-2 { max-width: none; }
}

/* How it works */
.steps { list-style: none; display: grid; border-top: 1px solid var(--hairline); }
.steps li { padding: 32px 0; border-bottom: 1px solid var(--hairline); }
.step-n { display: block; color: var(--muted); margin-bottom: 40px; }
.steps h3 { font-size: 24px; letter-spacing: -0.02em; }
.steps p { color: var(--muted); margin-top: 10px; max-width: 30em; }
@media (min-width: 860px) {
  .steps { grid-template-columns: repeat(3, 1fr); border-bottom: 1px solid var(--hairline); }
  .steps li { border-bottom: 0; padding: 32px 32px 40px; }
  .steps li:first-child { padding-left: 0; }
  .steps li:last-child { padding-right: 0; }
  .steps li + li { border-left: 1px solid var(--hairline); }
  .step-n { margin-bottom: 88px; }
}

/* FAQ. Same ruled grid as the steps above: the heading fills the first third and the
   list starts on the same line as the second step's text. */
.faq-note { color: var(--muted); margin-top: 16px; max-width: 19em; }
.faq-grid { display: grid; gap: 28px; }
/* Rows are opaque and positioned so that, while an answer opens, the rows below slide over it.
   The rows carry the rules themselves, so the lines move with them. */
details, .faq-end { position: relative; background: var(--bg); border-top: 1px solid var(--hairline); }
summary {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 24px;
  min-height: 44px; padding: 18px 0; cursor: pointer; list-style: none;
  font-size: 18px; line-height: 1.35; letter-spacing: -0.012em;
}
summary::-webkit-details-marker { display: none; }
/* Lifted so the next opaque row can't paint over the ring; the offset clears the icon. */
summary:focus-visible { position: relative; z-index: 1; outline-offset: 4px; }
.faq-icon {
  position: relative; flex: none; width: 28px; height: 28px; margin-top: -1px;
  border: 1px solid var(--hairline); border-radius: 50%;
  transition: transform .28s var(--ease);
}
.faq-icon::before, .faq-icon::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 10px; height: 1.5px; margin: -.75px 0 0 -5px;
  background: var(--text); transition: transform .28s var(--ease), opacity .2s ease;
}
.faq-icon::after { transform: rotate(90deg); }
/* Plus to minus: the mark turns a half while its upright stroke collapses, leaving a level bar. */
details[open]:not(.is-closing) .faq-icon { transform: rotate(180deg); }
details[open]:not(.is-closing) .faq-icon::after { transform: rotate(90deg) scaleX(0); opacity: 0; }
@media (hover: hover) { summary:hover .faq-icon { border-color: var(--muted); } }
details p { color: var(--muted); padding: 0 0 24px; max-width: 36em; }
@media (min-width: 860px) {
  .faq-grid { grid-template-columns: 1fr 2fr; gap: 0; border-top: 1px solid var(--hairline); }
  .faq-head { padding: 32px 32px 0 0; }
  details, .faq-end { border-left: 1px solid var(--hairline); }
  details:first-child { border-top: 0; }
  summary { padding: 24px 0 24px 32px; font-size: 19px; }
  details p { padding: 0 60px 32px 32px; }
}

/* Join */
.join, .foot { position: relative; }
.join-grid { display: grid; gap: 40px; align-items: end; }
.join h2 { max-width: 13ch; }
@media (min-width: 860px) { .join-grid { grid-template-columns: 7fr 5fr; gap: 72px; } }

/* Footer */
.foot { border-top: 1px solid var(--hairline); padding: 40px 0 calc(48px + env(safe-area-inset-bottom, 0px)); color: var(--muted); font-size: 14px; }
.foot-grid { display: grid; gap: 20px; }
.foot-legal { max-width: 46em; }
.foot nav { display: flex; flex-wrap: wrap; gap: 0 24px; }
.foot nav a { display: inline-flex; align-items: center; min-width: 44px; min-height: 44px; color: var(--text); }
@media (min-width: 860px) {
  .foot-grid { grid-template-columns: 1fr auto; }
  .foot-copy { grid-column: 1 / -1; }
}
/* Footer glow: a dome of lime light from the page's bottom edge, rising out of the footer into
   the bottom of the waitlist section. It sits at z-index -1 in the root stacking context, so it
   paints over the page background but under every block, text run and control above it; that is
   why .join and .foot carry no background of their own (body's is the same colour). The layer
   only grows upward, so it adds no scroll height and, at left/right 0, no sideways overflow.
   Two radial gradients: a brighter core and a wide, soft halo, both fading to nothing before
   the layer's edges. glow.js sets --glow from the scroll; only opacity changes, on a layer of its
   own. The short transition only smooths mouse-wheel steps. Peak alpha is set so the footer
   text and the waitlist's fine print stay above 4.5:1 on the brightest pixel behind them. */
.foot {
  --muted: #B0B0B5;
  --glow-h: 64vh; --glow-core: 95% 58%; --glow-halo: 150% 100%;
}
@media (min-width: 720px) { .foot { --glow-h: 54vh; --glow-core: 46% 62%; --glow-halo: 78% 100%; } }
.foot::before {
  content: ""; position: absolute; z-index: -1; left: 0; right: 0; bottom: 0;
  height: max(100%, var(--glow-h)); pointer-events: none;
  background:
    radial-gradient(var(--glow-core) at 50% 100%,
      rgba(200, 255, 77, .17) 0%, rgba(200, 255, 77, .141) 10%, rgba(200, 255, 77, .114) 20%,
      rgba(200, 255, 77, .089) 30%, rgba(200, 255, 77, .068) 40%, rgba(200, 255, 77, .049) 50%,
      rgba(200, 255, 77, .033) 60%, rgba(200, 255, 77, .019) 70%, rgba(200, 255, 77, .009) 80%,
      rgba(200, 255, 77, .003) 90%, rgba(200, 255, 77, 0) 100%),
    radial-gradient(var(--glow-halo) at 50% 100%,
      rgba(200, 255, 77, .11) 0%, rgba(200, 255, 77, .107) 10%, rgba(200, 255, 77, .099) 20%,
      rgba(200, 255, 77, .086) 30%, rgba(200, 255, 77, .071) 40%, rgba(200, 255, 77, .055) 50%,
      rgba(200, 255, 77, .039) 60%, rgba(200, 255, 77, .024) 70%, rgba(200, 255, 77, .011) 80%,
      rgba(200, 255, 77, .003) 90%, rgba(200, 255, 77, 0) 100%);
  opacity: var(--glow, 0); transition: opacity .2s linear; will-change: opacity;
}
.foot > .wrap { position: relative; }
/* Short pages (404, privacy on tall screens) push the footer to the bottom of the screen, so the
   glow sits on the screen's bottom edge rather than ending in a hard line mid-screen. */
body { display: flex; flex-direction: column; min-height: 100vh; }
body > main { flex: 1 0 auto; }
@media (prefers-reduced-motion: reduce) { .foot::before { opacity: .5; } }
@media print, (forced-colors: active) { .foot::before { display: none; } }

/* Legal pages and 404 */
.doc { padding: 72px 0 104px; }
.doc-body { max-width: 680px; }
.doc h1 { font-size: clamp(40px, 5vw, 60px); max-width: none; }
.doc .updated { color: var(--muted); margin: 16px 0 48px; font-size: 15px; }
.doc h2 { font-size: 22px; letter-spacing: -0.015em; line-height: 1.25; margin: 40px 0 10px; }
.doc p { color: var(--muted); margin-bottom: 14px; }
.doc ul { color: var(--muted); margin: 0 0 14px; padding-left: 20px; }
.doc li { margin-bottom: 6px; }
.doc p a, .doc li a { color: var(--text); }

/* Phones: tighter vertical rhythm */
@media (max-width: 719px) {
  .eyebrow { margin-bottom: 14px; }
  .hero { padding: 40px 0 56px; }
  .hero-grid { gap: 44px; }
  .lede { margin-top: 20px; }
  .hero .waitlist { margin-top: 28px; }
  .scard { height: 76px; margin-bottom: -32px; padding: 9px 18px; }
  .scard-top { height: auto; margin: 0; padding: 9px 18px 18px; }
  .stack-cards { --peek: 44px; }
  .scard-face, .scard-lime { padding: 9px 18px 18px; }
  .demos, .how, .faq, .join { padding: 56px 0; }
  .sec-head { margin-bottom: 28px; gap: 14px 48px; }
  .steps li { padding: 22px 0; }
  .step-n { margin-bottom: 12px; }
  .steps h3 { font-size: 22px; }
  .join-grid { gap: 24px; }
  .foot { padding-top: 28px; padding-bottom: calc(28px + env(safe-area-inset-bottom, 0px)); }
  .foot-grid { gap: 12px; }
}

/* Press and hover. Transform and opacity only; colour swaps stay instant. */
a, button, summary { -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
.waitlist button, .nav-cta, .brand { transition: transform .18s var(--ease); }
summary, .foot nav a { transition: opacity .18s ease; }
@media (hover: hover) {
  .waitlist button:not([disabled]):hover, .nav-cta:hover { transform: translate3d(0, -1px, 0); }
}
.waitlist button:not([disabled]):active, .nav-cta:active, .brand:active { transform: scale(.97); transition-duration: .06s; }
summary:active, .foot nav a:active { opacity: .6; transition-duration: .06s; }

/* Entrance and scroll motion. Every hidden state hangs off .js-anim (set by boot.js) or
   .reveal (set by site.js), so with no JS, or reduced motion, nothing is ever hidden. */
@keyframes fade-rise { from { opacity: 0; transform: translate3d(0, 14px, 0); } }
/* Cards only rise; the stack fades in as one, so no card is ever see-through over another. */
@keyframes card-settle { from { transform: translate3d(0, 44px, 0); } }
@keyframes fade-in { from { opacity: 0; } }

.js-anim .hero .eyebrow { animation: fade-rise .6s var(--ease) .04s backwards; }
.js-anim .hero .lede { animation: fade-rise .7s var(--ease) .36s backwards; }
.js-anim .hero .waitlist { animation: fade-rise .7s var(--ease) .44s backwards; }
.js-anim .hero h1 { animation: fade-rise .7s var(--ease) .06s backwards; }
.js-anim .stack-cards { animation: fade-in .7s ease .18s backwards; }
.js-anim .scard { animation: card-settle .8s var(--ease) backwards; }
.js-anim .scard:nth-child(1) { animation-delay: .18s; }
.js-anim .scard:nth-child(2) { animation-delay: .25s; }
.js-anim .scard:nth-child(3) { animation-delay: .32s; }
.js-anim .scard:nth-child(4) { animation-delay: .39s; }
.js-anim .scard:nth-child(5) { animation-delay: .46s; }
/* Live cards rise on an inner layer, so a tap during load-in never fights the card's own transform.
   site.js hands over the static card's progress, so upgrading doesn't restart the rise. */
.js-anim .stack-cards.is-live .scard { animation: none; }
.js-anim .stack-cards.is-live:not(.no-entrance) .scard-inner { animation: card-settle .8s var(--ease) backwards; }
.js-anim .stack-cards.is-live:not(.no-entrance) .scard:nth-child(1) .scard-inner { animation-delay: .18s; }
.js-anim .stack-cards.is-live:not(.no-entrance) .scard:nth-child(2) .scard-inner { animation-delay: .25s; }
.js-anim .stack-cards.is-live:not(.no-entrance) .scard:nth-child(3) .scard-inner { animation-delay: .32s; }
.js-anim .stack-cards.is-live:not(.no-entrance) .scard:nth-child(4) .scard-inner { animation-delay: .39s; }
.js-anim .stack-cards.is-live:not(.no-entrance) .scard:nth-child(5) .scard-inner { animation-delay: .46s; }

.reveal {
  opacity: 0; transform: translate3d(0, 18px, 0);
  transition: opacity .7s ease var(--d, 0ms), transform .7s var(--ease) var(--d, 0ms);
}
.reveal.in { opacity: 1; transform: none; }
@media print { .reveal { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0s !important; animation-iteration-count: 1 !important;
    transition-duration: 0s !important; transition-delay: 0s !important;
  }
  .p-spin { animation: none; }
  .reveal { opacity: 1; transform: none; }
}

/* ==========================================================================
   Flow graphic ("How it works"). Self-contained: only .flow* selectors, so it
   can be lifted out or merged on its own. Phones read top to bottom, wide
   screens left to right. The connectors are inline SVG on fixed row heights,
   so their ends always land on node centres. The lime light path is the only
   motion: see its block at the end of this section.
   ========================================================================== */
.flow { margin-bottom: 56px; padding: 28px 20px 0; border: 1px solid var(--hairline); border-radius: 20px; }
.flow-sr {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.flow-graph {
  --row: 64px;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: 8px;
  max-width: 440px; margin: 0 auto; font-size: 15px; line-height: 1.25;
}
.flow-label { display: none; color: var(--muted); font-size: 14px; }
.flow-node, .flow-card { position: relative; z-index: 1; }
.flow-node { background: var(--surface); border: 1px solid var(--hairline); border-radius: 12px; }

.flow-src {
  grid-column: 1 / -1; justify-self: center;
  display: flex; align-items: center; gap: 10px; padding: 13px 18px;
}
.flow-glyph { flex: none; width: 20px; height: 20px; fill: none; stroke: var(--muted); stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }

.flow-bucket {
  height: var(--row); display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 3px;
  padding: 0 8px; text-align: center;
}
.flow-bucket small { color: var(--muted); font-size: 13px; }

.flow-card {
  aspect-ratio: 1.586; display: flex; flex-direction: column; justify-content: space-between;
  padding: 9px 10px; border-radius: 9px; font-size: 13px; font-weight: 500;
  background: var(--surface); border: 1px solid var(--hairline);
}
.flow-card i { width: 15px; height: 11px; border: 1px solid var(--muted); border-radius: 3px; }
.flow-card.is-key { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.flow-card.is-key i { border-color: var(--on-accent); }
.flow-card.is-stopped { background: var(--bg); border-style: dashed; border-color: var(--muted); color: var(--muted); }
.flow-card em, .flow-cap-key { font-style: normal; font-weight: 400; }
.flow-card em { display: inline-flex; align-items: center; gap: 5px; color: var(--text); font-size: 12px; }
.flow-card em::before, .flow-cap-key {
  content: ""; flex: none; box-sizing: border-box; width: 11px; height: 11px;
  border: 1.4px solid currentColor; border-radius: 50%;
  background: linear-gradient(45deg, transparent calc(50% - .7px), currentColor calc(50% - .7px), currentColor calc(50% + .7px), transparent calc(50% + .7px));
}

/* Connectors. Each link holds one SVG per direction; vector-effect keeps the
   strokes 1.5px however far the SVG is stretched. On phones the fan and the
   rails span from the first column's centre to the third's, so 0, 50% and 100%
   of the SVG sit on the three column centres. */
.flow-link { position: relative; z-index: 0; grid-column: 1 / -1; height: 36px; margin: 0 calc((100% - 16px) / 6); }
.flow-link svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.flow-link path { fill: none; stroke: #3A3A40; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.flow-link .fk-h { display: none; }
.fk-1 { height: 40px; }

.flow-pay { grid-column: 1 / -1; padding: 16px 18px 18px; }
.fp-row { display: flex; justify-content: space-between; gap: 12px; font-weight: 500; padding-bottom: 14px; margin-bottom: 14px; border-bottom: 1px solid var(--hairline); }
.fp-sub { color: var(--muted); font-size: 13px; }
.fp-left { margin-top: 4px; color: var(--muted); }
.fp-left span { color: var(--text); font-weight: 500; font-size: 22px; letter-spacing: -0.02em; margin-right: 2px; }
.fp-bar { display: block; height: 4px; margin: 10px 0 14px; border-radius: 2px; background: var(--hairline); overflow: hidden; }
/* 213.60 of 500 left: the bar shows what's left, like the app screens above. */
.fp-bar i { display: block; width: 42.72%; height: 100%; border-radius: 2px; background: var(--text); }
.fp-done { display: flex; align-items: center; gap: 6px; }
.fp-done svg { width: 14px; height: 14px; fill: none; stroke: var(--text); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }

.flow-cap {
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: baseline; gap: 10px;
  margin: 28px -20px 0; padding: 16px 20px; border-top: 1px solid var(--hairline); font-size: 15px;
}
.flow-cap-key { display: inline-block; color: var(--muted); }
.flow-cap-key { transform: translateY(1px); }

/* Wide screens: one row, left to right, from 1100px where every label fits on one
   line. Rows are a fixed height, so the connectors' 252-unit viewBox maps 1:1 to
   pixels vertically. */
@media (min-width: 1100px) {
  .flow { margin-bottom: 72px; padding: 40px 40px 0; }
  .flow-graph {
    --row: 76px;
    max-width: none;
    grid-template-columns: minmax(0, .95fr) minmax(40px, .6fr) minmax(0, 1fr) minmax(28px, .38fr) 132px minmax(28px, .38fr) minmax(0, 1.3fr);
    grid-template-rows: auto var(--row) var(--row) var(--row);
    column-gap: 0; row-gap: 12px;
  }
  .flow-label { display: block; grid-row: 1; padding-bottom: 6px; }
  .fl-src { grid-column: 1; } .fl-bk { grid-column: 3; } .fl-cd { grid-column: 5; } .fl-pay { grid-column: 7; }
  .flow-src { grid-column: 1; grid-row: 2 / 5; align-self: center; justify-self: stretch; flex-direction: column; align-items: flex-start; gap: 16px; padding: 18px; }
  .flow-src span { max-width: 9em; }
  .flow-link { grid-row: 2 / 5; height: auto; margin: 0; }
  .fk-1 { grid-column: 2; } .fk-2 { grid-column: 4; } .fk-3 { grid-column: 6; }
  .flow-link .fk-h { display: block; }
  .flow-link .fk-v { display: none; }
  .flow-bucket { grid-column: 3; flex-direction: row; justify-content: space-between; padding: 0 18px; text-align: left; }
  .fb-1 { grid-row: 2; } .fb-2 { grid-row: 3; } .fb-3 { grid-row: 4; }
  .flow-bucket small { font-size: 14px; }
  .flow-card { grid-column: 5; height: var(--row); aspect-ratio: auto; }
  .fc-1 { grid-row: 2; } .fc-2 { grid-row: 3; } .fc-3 { grid-row: 4; }
  .flow-pay { grid-column: 7; grid-row: 2 / 5; align-self: center; }
  .flow-cap { margin: 40px -40px 0; padding: 18px 40px; }
}
.flow-bucket small, .fp-row span { white-space: nowrap; }
@media (max-width: 419px) { .fb-of { display: none; } }

/* The light path, on the Groceries route. Everything here is lit by default, so no JS,
   reduced motion and print show the whole path. Only the block below, under .js-anim
   (boot.js), takes it back to neutral and plays it while .is-playing (flow.js) is set.
   Borders are overlays, so nothing changes size. Beams are straight, so they scale along
   their length and their ends sit on the node edges. */
.flow-src::after, .fb-2::after, .fc-2::after, .flow-pay::after {
  content: ""; position: absolute; inset: -1px; border: 1px solid var(--accent); border-radius: inherit; pointer-events: none;
}
.flow-beam { position: absolute; left: calc(50% - .75px); top: 0; bottom: 0; width: 1.5px; background: var(--accent); transform-origin: 50% 0; --off: scale3d(1, 0, 1); }
@media (min-width: 1100px) {
  .flow-beam { left: 0; right: 0; top: calc(50% - .75px); bottom: auto; width: auto; height: 1.5px; transform-origin: 0 50%; --off: scale3d(0, 1, 1); }
}
@media screen and (prefers-reduced-motion: no-preference) {
  /* Neutral: until it plays, and when it scrolls away. */
  .js-anim .flow-src::after, .js-anim .fb-2::after, .js-anim .fc-2::after, .js-anim .flow-pay::after, .js-anim .fc-2::before, .js-anim .flow-beam { opacity: 0; }
  .js-anim .flow-card.is-key { background: var(--surface); border-color: var(--hairline); color: var(--text); }
  .js-anim .flow-card.is-key i { border-color: var(--muted); }
  .js-anim .fc-2::before { content: ""; position: absolute; z-index: -1; inset: -1px; border-radius: inherit; background: var(--accent); }

  /* One 7s timeline: 3.1s sweep, 2.3s hold, .6s fade, 1s pause. Each step starts just
     before the last one ends, so the light never stops moving. */
  .js-anim .flow.is-playing .flow-src::after { animation: flow-lit-bank 7s linear infinite; }
  .js-anim .flow.is-playing .fk-1 .flow-beam { animation: flow-draw-1 7s linear infinite; will-change: transform, opacity; }
  .js-anim .flow.is-playing .fb-2::after { animation: flow-lit-bucket 7s linear infinite; }
  .js-anim .flow.is-playing .fk-2 .flow-beam { animation: flow-draw-2 7s linear infinite; will-change: transform, opacity; }
  .js-anim .flow.is-playing .fc-2::after { animation: flow-lit-card 7s linear infinite; }
  .js-anim .flow.is-playing .fc-2::before { animation: flow-fill 7s linear infinite; }
  .js-anim .flow.is-playing .flow-card.is-key { animation: flow-ink 7s linear infinite; }
  .js-anim .flow.is-playing .flow-card.is-key i { animation: flow-chip 7s linear infinite; }
  .js-anim .flow.is-playing .fk-3 .flow-beam { animation: flow-draw-3 7s linear infinite; will-change: transform, opacity; }
  .js-anim .flow.is-playing .flow-pay::after { animation: flow-lit-pay 7s linear infinite; }

  @keyframes flow-lit-bank { 0% { opacity: 0; animation-timing-function: ease-out; } 6.43%, 77.14% { opacity: 1; animation-timing-function: ease-in-out; } 85.71%, 100% { opacity: 0; } }
  @keyframes flow-lit-bucket { 0%, 12.14% { opacity: 0; animation-timing-function: ease-out; } 17.86%, 77.14% { opacity: 1; animation-timing-function: ease-in-out; } 85.71%, 100% { opacity: 0; } }
  @keyframes flow-lit-card { 0%, 23.57% { opacity: 0; animation-timing-function: ease-out; } 28.57%, 77.14% { opacity: 1; animation-timing-function: ease-in-out; } 85.71%, 100% { opacity: 0; } }
  @keyframes flow-lit-pay { 0%, 38.57% { opacity: 0; animation-timing-function: ease-out; } 44.29%, 77.14% { opacity: 1; animation-timing-function: ease-in-out; } 85.71%, 100% { opacity: 0; } }
  @keyframes flow-fill { 0%, 27.14% { opacity: 0; animation-timing-function: ease-in-out; } 33.57%, 77.14% { opacity: 1; animation-timing-function: ease-in-out; } 85.71%, 100% { opacity: 0; } }
  /* Text flips quickly at the middle of the fill's fade, so it never sits mid-grey on olive. */
  @keyframes flow-ink { 0%, 30.2% { color: var(--text); } 31.4%, 81% { color: var(--on-accent); } 82.2%, 100% { color: var(--text); } }
  @keyframes flow-chip { 0%, 30.2% { border-color: var(--muted); } 31.4%, 81% { border-color: var(--on-accent); } 82.2%, 100% { border-color: var(--muted); } }
  @keyframes flow-draw-1 {
    0%, 5.7% { opacity: 0; transform: var(--off); } 5.71% { opacity: 1; transform: var(--off); animation-timing-function: cubic-bezier(.4, 0, .6, 1); }
    12.86% { opacity: 1; transform: none; } 77.14% { opacity: 1; transform: none; animation-timing-function: ease-in-out; } 85.71%, 100% { opacity: 0; transform: none; }
  }
  @keyframes flow-draw-2 {
    0%, 17.13% { opacity: 0; transform: var(--off); } 17.14% { opacity: 1; transform: var(--off); animation-timing-function: cubic-bezier(.4, 0, .6, 1); }
    24.29% { opacity: 1; transform: none; } 77.14% { opacity: 1; transform: none; animation-timing-function: ease-in-out; } 85.71%, 100% { opacity: 0; transform: none; }
  }
  @keyframes flow-draw-3 {
    0%, 32.13% { opacity: 0; transform: var(--off); } 32.14% { opacity: 1; transform: var(--off); animation-timing-function: cubic-bezier(.4, 0, .6, 1); }
    39.29% { opacity: 1; transform: none; } 77.14% { opacity: 1; transform: none; animation-timing-function: ease-in-out; } 85.71%, 100% { opacity: 0; transform: none; }
  }
}
/* End flow graphic */

/* ==========================================================================
   Mobile menu: below 720px, where the full nav doesn't fit. Desktop is untouched.
   Motion is transform and opacity only. The global reduced-motion rule zeroes it all.
   ========================================================================== */
.nav-toggle, .menu, .menu-scrim { display: none; }
@media (max-width: 719px) {
  :root { --nav-h: calc(65px + env(safe-area-inset-top, 0px)); }
  html.menu-open { overflow: hidden; scrollbar-gutter: stable; overflow-anchor: none; }

  /* Anchor jumps: same landing on every section, heading clear of the header. */
  #demos, #how, #faq, #join { scroll-margin-top: -48px; }

  .nav-links { display: none; }
  .nav-toggle {
    display: block; position: relative; flex: none;
    width: 44px; height: 44px; margin-right: -11px; padding: 0;
    background: none; border: 0; border-radius: 10px; cursor: pointer;
  }
  .nav-toggle-bar {
    position: absolute; left: 11px; top: 21.25px; width: 22px; height: 1.5px;
    background: var(--text); border-radius: 1px;
    transform: translate3d(0, -4px, 0);
    transition: transform .42s var(--ease);
  }
  .nav-toggle-bar + .nav-toggle-bar { transform: translate3d(0, 4px, 0); }
  .menu-open .nav-toggle-bar { transform: rotate(45deg); }
  .menu-open .nav-toggle-bar + .nav-toggle-bar { transform: rotate(-45deg); }

  .menu-scrim {
    display: block; position: fixed; inset: 0; z-index: 8;
    background: var(--bg); opacity: 0; visibility: hidden;
    transition: opacity .36s ease, visibility 0s linear .36s;
  }
  .menu-open .menu-scrim { opacity: .78; visibility: visible; transition: opacity .42s ease, visibility 0s; }

  /* Sits under the header (z-index 10) and slides out from behind it. */
  .menu {
    display: flex; flex-direction: column;
    position: fixed; z-index: 9; left: 0; right: 0; top: var(--nav-h);
    min-height: calc(52vh - var(--nav-h)); min-height: calc(52dvh - var(--nav-h));
    max-height: calc(100vh - var(--nav-h)); max-height: calc(100dvh - var(--nav-h));
    padding: 4px var(--gr) max(10px, env(safe-area-inset-bottom, 0px)) var(--gl);
    background: var(--surface); border-bottom: 1px solid var(--hairline); border-radius: 0 0 20px 20px;
    overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
    transform: translate3d(0, -100%, 0); visibility: hidden;
    transition: transform .36s var(--ease), visibility 0s linear .36s;
  }
  .menu-open .menu { transform: none; visibility: visible; transition: transform .42s var(--ease), visibility 0s; }

  /* Rows share any spare height, so the panel never has a dead gap above the button. */
  .menu-list { flex: 1 0 auto; display: flex; flex-direction: column; list-style: none; margin: 0; padding: 0; }
  .menu-list li { flex: 1 0 auto; display: flex; }
  .menu-list li + li { border-top: 1px solid var(--hairline); }
  .menu-list a {
    flex: 1; display: flex; align-items: center; min-height: 60px;
    font-size: 24px; font-weight: 500; line-height: 1.2; letter-spacing: -0.024em; text-decoration: none;
    transition: opacity .18s ease;
  }
  .menu-list a:active { opacity: .6; transition-duration: .06s; }
  .menu a:focus-visible { outline-offset: -2px; }
  .menu-foot { flex: none; padding-top: 8px; }
  .menu-cta {
    display: flex; align-items: center; justify-content: center; height: 52px;
    background: var(--accent); color: var(--on-accent); font-weight: 500;
    border-radius: 10px; text-decoration: none;
    transition: transform .18s var(--ease);
  }
  .menu a.menu-cta:focus-visible { outline-offset: 3px; }
  .menu-cta:active { transform: scale(.97); transition-duration: .06s; }
  .menu-legal { display: flex; justify-content: center; gap: 24px; margin-top: 2px; font-size: 13px; }
  .menu-legal a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 4px; color: var(--muted); text-decoration: none; }

  /* Rows settle in behind the panel, then leave together with no stagger. */
  .menu-list li, .menu-foot {
    opacity: 0; transform: translate3d(0, -10px, 0);
    transition: opacity .2s ease, transform .2s ease;
  }
  .menu-open .menu-list li, .menu-open .menu-foot {
    opacity: 1; transform: none;
    transition: opacity .36s ease var(--menu-d, 60ms), transform .42s var(--ease) var(--menu-d, 60ms);
  }
  .menu-list li:nth-child(2) { --menu-d: 95ms; }
  .menu-list li:nth-child(3) { --menu-d: 130ms; }
  .menu-foot { --menu-d: 165ms; }
}
@media (forced-colors: active) { .nav-toggle-bar { background: CanvasText; } }
@media print { .nav-toggle, .menu, .menu-scrim { display: none !important; } }
/* End mobile menu */

/* Big card glyph tucked into the lime card's bottom right, as on the Wallet mockup card art.
   Same glyph as the nav mark, one shade off the lime, behind the text. */
.scard-top, .scard-lime { position: relative; overflow: hidden; }
.stack-cards.is-live .scard-lime { position: absolute; }
.scard-emboss { position: absolute; z-index: 0; right: -6%; bottom: -19%; width: 58%; aspect-ratio: 1; fill: #C0F547; pointer-events: none; }
.scard-top > :not(.scard-emboss), .scard-lime > :not(.scard-emboss) { position: relative; z-index: 1; }
