/* ============================================================
   Splice — cream ground, oversized type, the real product shown.

   Phones are not decorative rectangles: each one is an actual screen
   from the app (or, for members, the actual browser page) redrawn in
   CSS, in the app's own Ember palette, inside a device frame with
   real proportions.
   ============================================================ */

/* "Quite clear" is the product standard as of 2026-08-19 (replaced "cream
   and ember") — this is the base :root now, not a toggled override.
   Mirrors @splice/design's colors.ts; keep both in sync by hand. Ink is a
   plain derived dark gray rather than either accent hue, which keeps
   green and maroon both free for the splice/Circle roles instead of one
   getting absorbed into body text. */
:root {
  --paper: #f2ede1;
  --leaf: #faf7f0;
  --ink: #1a1a1a;
  --ink-2: #666666;
  --ink-3: #cbcbcb;
  --rule: #e0dace;
  --rule-soft: #e8e3d8;
  --ember: #174d38;
  --ember-hot: #123d2c;
  --ember-wash: #e1ede8;
  --cocoa: #1a1a1a;

  /* Straight from EMBER_LIGHT + colors.ts in the app, so the mocks are
     the product rather than an impression of it. */
  --app-canvas: #f2ede1;
  --app-ink: #1a1a1a;
  --app-stone: #666666;
  --app-slate: #4d1717;
  --app-ember: #174d38;
  --app-on-ember: #f2ede1;
  --app-hairline: rgba(26, 26, 26, 0.12);
  --app-track: #e0dace; /* surfaceAlt */
  --app-surface: #faf7f0;
  --app-muted: #999999;
  --app-line: #e0dace;
  --app-success: #5e7c3a;

  /* iOS Messages, for the one section that is deliberately imitating it. */
  --ios-blue: #0b84ff;
  --ios-grey: #e9e9eb;
  --ios-ink: #000;

  --display: "Bricolage Grotesque", system-ui, sans-serif;
  --sans: "Familjen Grotesk", system-ui, sans-serif;
  --mono: "DM Mono", ui-monospace, monospace;
  --ios: -apple-system, "SF Pro Text", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --measure: 1240px;
  --gutter: clamp(20px, 5vw, 56px);
  color-scheme: light;
}

*,
*::before,
*::after { box-sizing: border-box; margin: 0; padding: 0; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Fine grain only — the warm orange glow that used to sit here read as an
   unexplained tint under other palettes, so it's gone; texture stays. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.45;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23g)' opacity='0.05'/%3E%3C/svg%3E");
}

.wrap {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

a { color: inherit; }

/* ---------------------------------------------------------------
   Type
   --------------------------------------------------------------- */

.display {
  font-family: var(--display);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 0.92;
}

.label {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ember);
}

.label--quiet { color: var(--ink-3); }

.lede {
  font-size: clamp(17px, 1.55vw, 19.5px);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 42ch;
}

.small { font-size: 15px; color: var(--ink-2); }
.fine { font-size: 13px; line-height: 1.5; color: var(--ink-3); }

/* ---------------------------------------------------------------
   Nav — floating pill
   --------------------------------------------------------------- */

.pillnav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin: 22px auto 0;
  padding: 9px 0;
}

.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-weight: 600;
  font-size: 17px;
  text-decoration: none;
  flex: none;
}

.brand svg { width: 23px; height: 23px; flex: none; }

.navlinks { display: flex; gap: 26px; font-size: 14.5px; }
.navlinks a { text-decoration: none; color: var(--ink-2); transition: color 0.16s; }
.navlinks a:hover { color: var(--ink); }

/* ---------------------------------------------------------------
   Buttons + App Store badge
   --------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 0;
  cursor: pointer;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  padding: 15px 27px;
  border-radius: 999px;
  background: var(--ember);
  color: #fff;
  text-decoration: none;
  transition: background 0.16s, transform 0.16s, opacity 0.16s;
}

.btn:hover:not(:disabled) { background: var(--ember-hot); transform: translateY(-1px); }
.btn:disabled { opacity: 0.32; cursor: not-allowed; }
.btn--sm { padding: 10px 20px; font-size: 14px; }
.btn--lg { padding: 17px 30px; font-size: 16.5px; }

/* The App Store mark inside an ember pill, for CTAs that need the brand
   recognition of the app store icon without the black badge's weight. */
.btn--store svg { width: 18px; height: 21px; fill: currentColor; flex: none; }

.diff-cta { display: flex; justify-content: center; padding: 30px 0 4px; }

.appstore {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: #000;
  color: #fff;
  border-radius: 12px;
  padding: 9px 17px 9px 15px;
  text-decoration: none;
  transition: transform 0.16s;
}

.appstore:hover { transform: translateY(-1px); }
.appstore svg { width: 22px; height: 26px; flex: none; fill: #fff; }
.appstore .t { display: flex; flex-direction: column; line-height: 1.15; text-align: left; }
.appstore .t small { font-size: 10px; opacity: 0.85; }
.appstore .t strong { font-size: 17px; font-weight: 500; letter-spacing: -0.01em; }

/* Mobile-only sticky download bar — display:none until the mobile
   breakpoint below turns it on. Same frosted-pill language as .pillnav. */
.sticky-cta {
  display: none;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 12px var(--gutter);
  padding-bottom: max(12px, env(safe-area-inset-bottom));
  background: rgba(244, 238, 225, 0.92);
  border-top: 1px solid var(--rule);
  backdrop-filter: blur(14px);
}

.sticky-cta-brand { display: flex; align-items: center; gap: 9px; min-width: 0; }
.sticky-cta-brand svg { width: 26px; height: 26px; flex: none; }
.sticky-cta-text {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ember);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.appstore--sticky { flex: none; padding: 8px 14px 8px 12px; }
.appstore--sticky svg { width: 18px; height: 21px; }
.appstore--sticky .t strong { font-size: 15px; }

/* ---------------------------------------------------------------
   Hero — type dominates left, product sits right
   --------------------------------------------------------------- */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
  gap: clamp(30px, 4vw, 60px);
  align-items: center;
  padding: clamp(38px, 5.5vw, 74px) 0 clamp(40px, 5vw, 68px);
}

.hero h1 {
  /* "for YOUR money" is the longest line — sized so it stays on one line
     at the widest hero column (measured: wraps above ~75px there). */
  font-size: clamp(30px, 5vw, 74px);
  text-transform: uppercase;
}

/* Direct children only — a nested inline accent span (e.g. .fill inside a
   line) must NOT also become block-level, or it breaks onto its own line. */
.hero h1 > span { display: block; }

.hero h1 .fill { color: var(--ember); }
.hero h1 .fill-alt { color: var(--app-slate); }

.hero .lede { margin-top: 24px; }

.ctas {
  margin-top: 30px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}

.codes { display: flex; gap: 7px; }

.codes input {
  width: clamp(40px, 3.6vw, 50px);
  height: clamp(50px, 4.4vw, 60px);
  padding: 0;
  text-align: center;
  font-family: var(--mono);
  font-size: clamp(18px, 1.7vw, 21px);
  color: var(--ink);
  background: var(--leaf);
  border: 1px solid var(--rule);
  border-radius: 10px;
  outline: none;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s;
}

.codes input:focus {
  border-color: var(--ember);
  background: #fff;
  box-shadow: 0 0 0 3px var(--ember-wash);
}

.codes input.filled { border-color: var(--ink-3); background: #fff; }

.join-note { margin-top: 10px; min-height: 18px; }
.join-note.error { color: var(--ember); }

/* Getting the app is a different decision from joining with a code, so the
   badge sits on its own line beneath the note rather than inline beside it. */
.or-row {
  margin-top: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 11px;
}

.or-row .or {
  font-size: 12.5px;
  color: var(--ember);
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* ---------------------------------------------------------------
   The device — real proportions, real chrome
   --------------------------------------------------------------- */

.phone-wrap { position: relative; justify-self: center; width: min(310px, 78vw); }

.phone-wrap::after {
  content: "";
  position: absolute;
  inset: 14% -18% -6% -18%;
  z-index: -1;
  background: radial-gradient(50% 50% at 50% 50%, rgba(244, 113, 47, 0.3), transparent 70%);
  filter: blur(34px);
}

.phone-wrap--quiet::after { opacity: 0.5; }

/* Hero's phone fades to transparent at the bottom (.iphone--half), which let
   this glow bleed through and read as a warm smudge on the screen itself
   rather than ambience behind the device. */
.phone-wrap--noglow::after { content: none; }

/* Titanium rail, glass edge, then the screen. iPhone 15/16 proportions:
   393 × 852 points, ~55pt corner radius. */
.iphone {
  position: relative;
  aspect-ratio: 393 / 852;
  padding: 3px;
  border-radius: 14.5% / 6.7%;
  background: linear-gradient(150deg, #6b6560 0%, #2a2622 22%, #4a4540 50%, #232019 78%, #5e5852 100%);
  box-shadow:
    0 42px 74px -28px rgba(28, 22, 16, 0.52),
    0 3px 10px rgba(28, 22, 16, 0.2);
}

/* Hero variant: most of the phone (~75%), dissolving into the page rather
   than a hard crop. Bottom corners are deliberately SQUARE, not rounded —
   this edge is a cut through the phone's body, not a real device corner, so
   rounding it drew a solid pill-shaped bottom the fade then had to fade OUT
   of. The mask starts right where the visible body thins out, so there's no
   flat, fully-opaque cut edge. Tilted a couple degrees so it reads as a
   product shot, not a spec sheet. */
.iphone--half {
  aspect-ratio: 393 / 639;
  border-radius: 14.5% 14.5% 0 0 / 8.9% 8.9% 0 0;
  -webkit-mask-image: linear-gradient(to bottom, #000 42%, rgba(0, 0, 0, 0.5) 68%, transparent 92%);
  mask-image: linear-gradient(to bottom, #000 42%, rgba(0, 0, 0, 0.5) 68%, transparent 92%);
  transform: rotate(2.5deg);
}

.iphone--half .iphone-screen { border-radius: 13.6% 13.6% 0 0 / 8.4% 8.4% 0 0; border-bottom: 0; }

/* The black bezel between rail and glass. */
.iphone-screen {
  position: relative;
  height: 100%;
  border-radius: 13.6% / 6.3%;
  background: var(--app-canvas);
  border: 8px solid #0a0908;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

/* Physical buttons on the rail. */
.side-btn {
  position: absolute;
  width: 2.5px;
  border-radius: 2px;
  background: linear-gradient(90deg, #6f6963, #3a3630);
}
.side-btn--silent { left: -2px; top: 15.5%; height: 3.4%; }
.side-btn--up     { left: -2px; top: 22.5%; height: 6.4%; }
.side-btn--down   { left: -2px; top: 31%;   height: 6.4%; }
.side-btn--power  { right: -2px; top: 25%;  height: 9.4%; background: linear-gradient(270deg, #6f6963, #3a3630); }

/* Shorter crop, closer to the full-phone button positions above (only a
   little higher, since 75% shows nearly the whole device). */
.iphone--half .side-btn--silent { top: 13%;   height: 4.7%; }
.iphone--half .side-btn--up     { top: 20%;   height: 8.9%; }
.iphone--half .side-btn--down   { top: 31.7%; height: 8.9%; }
.iphone--half .side-btn--power  { top: 22.2%; height: 13.1%; }

/* Status bar + Dynamic Island. */
.statusbar {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 9px 16px 2px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--app-ink);
  letter-spacing: 0.01em;
}

.island {
  position: absolute;
  left: 50%;
  top: 7px;
  transform: translateX(-50%);
  width: 30%;
  height: 20px;
  border-radius: 999px;
  background: #0a0908;
}

.island--sm {
  position: absolute;
  left: 50%;
  top: 6px;
  transform: translateX(-50%);
  width: 32%;
  height: 15px;
  border-radius: 999px;
  background: #0a0908;
  z-index: 3;
}

.indicators { display: flex; align-items: center; gap: 5px; }
.indicators svg { fill: var(--app-ink); }
.i-sig { width: 17px; height: 10px; }
.i-wifi { width: 15px; height: 11px; }

.i-batt {
  position: relative;
  width: 24px;
  height: 11.5px;
  border: 1px solid rgba(42, 33, 26, 0.4);
  border-radius: 3.5px;
  padding: 1.5px;
  display: block;
}
.i-batt::after {
  content: "";
  position: absolute;
  right: -3px;
  top: 50%;
  transform: translateY(-50%);
  width: 1.6px;
  height: 4px;
  border-radius: 0 2px 2px 0;
  background: rgba(42, 33, 26, 0.4);
}
.i-batt b { display: block; width: 72%; height: 100%; border-radius: 1.5px; background: var(--app-ink); }

.home-bar {
  flex: none;
  width: 36%;
  height: 4.5px;
  margin: 7px auto 8px;
  border-radius: 999px;
  background: rgba(42, 33, 26, 0.32);
}

/* The real app has no bundled display font yet — it renders in the OS system
   font throughout (see apps/leader/components/ui.tsx), with Georgia used only
   for a couple of specific headlines. These mockups match that: `--ios`, not
   the marketing site's own `--display`/`--mono`. */
.app {
  flex: 1;
  min-height: 0;
  padding: 6px 15px 0;
  overflow: hidden;
  color: var(--app-ink);
  font-family: var(--ios);
}

/* ---------------------------------------------------------------
   Hero: cycles between the organizer's countdown and a member's, for
   the same splice at the same moment.
   --------------------------------------------------------------- */

.hero-screens { position: relative; flex: 1; min-height: 0; }

.hero-frame {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  pointer-events: none;
}

/* Held, cross-faded, held — the pause is long enough to actually read either
   screen, matching the rest of the page's "one orchestrated moment" motion
   rather than a fast, distracting slideshow. Reduced-motion strips the
   animation globally (see the media query at the bottom of this file), which
   leaves each frame at its own base opacity below — the organizer screen
   stays put, not stuck mid-crossfade. */
.hero-frame--a { animation: heroFrameA 12s ease-in-out infinite; }
.hero-frame--b { animation: heroFrameB 12s ease-in-out infinite; opacity: 0; }

@keyframes heroFrameA {
  0%, 44% { opacity: 1; }
  50%, 94% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes heroFrameB {
  0%, 44% { opacity: 0; }
  50%, 94% { opacity: 1; }
  100% { opacity: 0; }
}

/* Caption above the phone, crossfading in sync with the two hero screens via
   the same heroFrameA/B keyframes. Tilted to match the phone's own rotation
   so the two read as one tilted object, not a straight label over a tilted
   photo. */
.hero-caption { position: relative; height: 15px; text-align: center; transform: rotate(2.5deg); }
.hero-caption--top { margin-bottom: 18px; }
.hero-caption-text { position: absolute; inset: 0; }

/* The tilt exists to sit parallel to the hero's tilted phone. Sections whose
   phone stands upright need the caption upright too. */
.hero-caption--flat { transform: none; }

.app--charge { padding: 20px 17px 0; }

.crumb {
  font-size: 9px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--app-stone);
}

.count {
  font-size: 54px;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.02;
  font-variant-numeric: tabular-nums;
  margin-top: 7px;
}

.count-sub { font-size: 15px; color: var(--app-stone); margin-top: 1px; }

.count-body {
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--app-stone);
  margin-top: 12px;
}

.agree {
  margin-top: 15px;
  background: var(--leaf);
  border: 1px solid var(--app-hairline);
  border-radius: 13px;
  padding: 10px 12px;
}

.agree-k,
.mem-k {
  font-size: 8.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--app-stone);
}

.agree-k { margin-bottom: 3px; }
.mem-k { margin: 15px 0 2px; }

.agree-row,
.mem-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 11.5px;
  padding: 5px 0;
}

.mem-row { border-bottom: 1px solid var(--app-hairline); }

.agree-row em,
.mem-row em { font-style: normal; font-size: 9.5px; color: var(--app-stone); }
.agree-row em.ok,
.mem-row em.ok { color: var(--app-success); }

/* ---------------------------------------------------------------
   Trust strip
   --------------------------------------------------------------- */

.trust {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 40px;
  padding: 22px 0 0;
  border-top: 1px solid var(--rule);
}

.trust div { font-size: 13.5px; color: var(--ink-2); }
.trust b { color: var(--ink); font-weight: 600; }

/* ---------------------------------------------------------------
   Sections
   --------------------------------------------------------------- */

section { position: relative; z-index: 1; padding: clamp(52px, 7vw, 92px) 0 0; }

.sec-head { max-width: 780px; margin-bottom: clamp(28px, 4vw, 46px); }
.sec-head h2 { margin-top: 12px; font-size: clamp(34px, 5vw, 62px); text-transform: uppercase; }
.sec-head h2 .fill { color: var(--ember); white-space: nowrap; }
.sec-head .lede { margin-top: 16px; max-width: 52ch; }
.sec-head--center { text-align: center; margin-inline: auto; }
.sec-head--center .lede { margin-inline: auto; }

/* Text left, product right. Used by the member and Circles sections. */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.82fr);
  gap: clamp(30px, 5vw, 70px);
  align-items: center;
}

/* Phone on the left, copy on the right — the mirror of the other .split
   sections, so the page doesn't always put the product on the same side. */
.split--reverse { grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr); }

.split h2 { margin: 12px 0 18px; font-size: clamp(32px, 4.4vw, 54px); text-transform: uppercase; }
/* The orange half of the line gets its own line, not just its own color —
   matches the hero's treatment of its accent line. */
.split h2 .fill { display: block; color: var(--ember); }

.ticks { list-style: none; margin-top: 24px; }

/* Marker is positioned, not a flex child: display:flex here would treat an
   inline <b> as its own flex item and inject a gap mid-sentence. */
.ticks li {
  position: relative;
  padding: 11px 0 11px 24px;
  font-size: 15px;
  color: var(--ink-2);
  border-top: 1px solid var(--rule-soft);
}

.ticks li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 19px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1.5px solid var(--ember);
}

/* ---------------------------------------------------------------
   The Splice difference — deliberately iOS Messages, so the
   before/after reads instantly as a group chat
   --------------------------------------------------------------- */

/* Both cards are the same height on purpose. The "before" chat earns that
   height; the "after" one has nothing left to say and the empty space below its
   last bubble is the whole argument. Letting the right card shrink to its
   content would read as an unfinished panel instead. */
.compare {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(20px, 3vw, 36px);
}

.imsg {
  background: #fff;
  border: 1px solid var(--rule-soft);
  border-radius: 22px;
  overflow: hidden;
  font-family: var(--ios);
  box-shadow: 0 26px 50px -30px rgba(28, 22, 16, 0.4);
  display: flex;
  flex-direction: column;
}

.imsg-top {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 16px;
  background: rgba(249, 249, 249, 0.94);
  border-bottom: 1px solid #d8d8dc;
}

.imsg-av {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  flex: none;
  display: grid;
  place-items: center;
  background: #c7c7cc;
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.imsg-av--splice { background: var(--ember); }
.imsg-av--splice svg { width: 19px; height: 19px; }

.imsg-top b { display: block; font-size: 14px; font-weight: 600; color: var(--ios-ink); }
.imsg-top small { display: block; font-size: 11.5px; color: #8e8e93; }

.imsg-body {
  flex: 1;
  padding: 16px 14px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* One bubble. `out` is you (blue, right), `in` is everyone else (grey, left). */
.im {
  position: relative;
  max-width: 78%;
  padding: 7px 13px;
  border-radius: 18px;
  font-size: 14px;
  line-height: 1.34;
  letter-spacing: -0.01em;
  word-break: break-word;
}

.im.out { align-self: flex-end; background: var(--ios-blue); color: #fff; }
.im.in { align-self: flex-start; background: var(--ios-grey); color: var(--ios-ink); }

/* Consecutive bubbles from the same side tuck together; the last of a run
   gets the tail, exactly like Messages. */
.im.out + .im.in,
.im.in + .im.out { margin-top: 7px; }

.im.out:not(:has(+ .im.out)) { border-bottom-right-radius: 5px; }
.im.in:not(:has(+ .im.in)) { border-bottom-left-radius: 5px; }

/* The Splice receipt is a system message, not a person talking. */
.im.sys {
  align-self: stretch;
  max-width: 100%;
  margin-top: 12px;
  background: var(--paper);
  border: 1px solid rgba(210, 87, 30, 0.34);
  border-radius: 16px;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 13.5px;
  padding: 12px 14px;
}

.im.sys b { font-weight: 600; }

.im.sys .ok {
  display: block;
  margin-top: 7px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--app-success);
}

/* The "before" side as four separate 1:1 threads, one square each, inside
   the one overall card — chasing four different people gets four different
   reactions (left on read, an excuse, a promise, total silence), and a
   single thread can only ever show one texture at a time. */
.dm-grid {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 9px;
  padding: 12px;
}

.dm-sq {
  background: #f7f7f9;
  border-radius: 14px;
  padding: 9px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}

.dm-sq-top { display: flex; align-items: center; gap: 7px; }
.dm-sq-top b { font-size: 12.5px; font-weight: 600; color: var(--ios-ink); }

.dm-av {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  flex: none;
  display: grid;
  place-items: center;
  background: #c7c7cc;
  color: #fff;
  font-size: 8.5px;
  font-weight: 600;
}

.im--sm {
  max-width: 100%;
  padding: 5px 8px;
  font-size: 10.5px;
  line-height: 1.22;
}

/* Group-chat rows: iOS shows an avatar beside an incoming message and the
   sender's name in small grey type ABOVE the bubble — not "Name:" prefixed
   inside it, which is an Android/SMS-gateway convention and reads as fake
   on an iMessage mock. */
.gc-row {
  display: flex;
  align-items: flex-end;
  gap: 7px;
  align-self: flex-start;
  max-width: 86%;
  margin-top: 8px;
}

.gc-av {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  flex: none;
  display: grid;
  place-items: center;
  background: #c7c7cc;
  color: #fff;
  font-size: 9px;
  font-weight: 600;
}

.gc-msg { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.gc-name { font-size: 10.5px; color: #8e8e93; padding-left: 11px; }
.gc-row .im.in { align-self: flex-start; max-width: 100%; }

/* A pasted link renders as link-colored text inside the sender's bubble. */
.im-link { text-decoration: underline; text-underline-offset: 2px; }

.dm-sq-status {
  margin-top: auto;
  font-size: 9.5px;
  font-family: var(--mono);
  letter-spacing: 0.02em;
  color: #b8b8bd;
}

/* "Read and ignored" is the sharpest sting of the four — give it real
   weight instead of burying it in the same quiet grey as "Delivered." */
.dm-sq-status--seen {
  font-size: 11px;
  font-weight: 700;
  color: var(--ios-blue);
}

.imsg-foot {
  padding: 12px 16px 14px;
  border-top: 1px solid #ececf0;
  background: rgba(249, 249, 249, 0.94);
}

.tag {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 6px 12px;
  border-radius: 999px;
  display: inline-block;
}

.tag--bad { background: #fbe6d8; color: #a8431a; }
.tag--good { background: #e8efdc; color: #4c6530; }

/* The "before" chat is taller on purpose: that length IS the point. */
.imsg--after .imsg-body { justify-content: flex-start; }

/* ---------------------------------------------------------------
   Member side — a browser page, because members install nothing
   --------------------------------------------------------------- */

.safari {
  flex: none;
  margin: 26px 10px 8px;
  padding: 7px 12px;
  border-radius: 999px;
  background: rgba(42, 33, 26, 0.07);
  font-size: 10.5px;
  color: var(--app-stone);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}

.safari .lock { display: inline-flex; }
.safari .lock svg { width: 8px; height: 9.5px; fill: var(--app-stone); }

/* The real page puts a Spacer between the amount and the action, so the button
   rests near the bottom of the screen rather than floating mid-page. */
.app--member { padding: 14px 17px 0; display: flex; flex-direction: column; }

.m-eyebrow {
  font-size: 8.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--app-stone);
}

.m-title {
  font-family: Georgia, "Times New Roman", serif;
  font-size: 24px;
  letter-spacing: -0.4px;
  margin-top: 5px;
}

.m-contrib { font-size: 10px; color: var(--app-stone); margin-top: 3px; }

.m-banner {
  margin-top: 14px;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--leaf);
  border: 1px solid var(--app-hairline);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 10px;
  color: var(--app-ink);
}

.m-banner b { font-weight: 600; white-space: nowrap; font-variant-numeric: tabular-nums; }

.m-amount { text-align: center; margin: 22px 0 8px; }
.m-amount small { display: block; font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--app-stone); }
.m-amount strong { display: block; font-size: 40px; font-weight: 700; letter-spacing: -0.02em; margin-top: 4px; }

/* The real itemized breakdown — what a member's card actually pays for,
   not a "tap for breakdown" teaser a static screenshot can't demonstrate. */
.m-breakdown {
  margin: 0 0 10px;
  padding-top: 10px;
  border-top: 1px solid var(--app-hairline);
}
.m-b-row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-size: 10.5px;
  color: var(--app-stone);
  padding: 4px 0;
}
.m-b-row b { font-weight: 500; color: var(--app-ink); font-variant-numeric: tabular-nums; }
.m-b-row--fee { border-top: 1px solid var(--app-hairline); margin-top: 2px; padding-top: 6px; }

.m-note { text-align: center; font-size: 8.5px; color: var(--app-stone); }

/* Sits directly under the amount/note, exactly like the real pay-link page —
   NOT bottom-anchored. Pinning it to the bottom of the frame both misplaced
   it against the real product and buried it in the hero phone's fade. */
.m-btn {
  margin-top: 14px;
  margin-bottom: 10px;
  background: var(--app-ember);
  color: var(--app-on-ember);
  border-radius: 999px;
  padding: 11px;
  text-align: center;
  font-size: 11px;
  font-weight: 600;
}

/* ---------------------------------------------------------------
   The organizer side — the splice screen right before you charge
   --------------------------------------------------------------- */

/* Drawn against apps/leader/app/splice/[id].tsx and components/ui.tsx rather
   than from memory. Sizes are the app's type scale (display 28 / title 20 /
   body 16 / small 13 / caption 11pt) multiplied by ~0.75, which is what a
   393pt-wide device comes to at this render width. Colours are EMBER_LIGHT:
   surface #FBF5EA, surfaceAlt #EAE1CF, inkDim #7D7266, muted #A99E8C,
   line #E0D7C4, accent #D2571E. The app has no serif and no coloured avatars. */

.app--org { padding: 10px 15px 0; display: flex; flex-direction: column; }

/* Screen puts the charge button in a pinned `footer` while the body scrolls, so
   the button stays put and the content is what runs off the bottom edge. */
.o-scroll { flex: 1; min-height: 0; overflow: hidden; }

/* Screen's own chrome: a back chevron, and the gear that opens splice settings. */
.o-nav { display: flex; align-items: center; justify-content: space-between; height: 20px; margin-bottom: 6px; }
.o-back, .o-gear { width: 13px; height: 13px; opacity: 0.55; }
.o-back {
  border-left: 1.6px solid var(--app-ink);
  border-bottom: 1.6px solid var(--app-ink);
  width: 8px; height: 8px;
  transform: rotate(45deg);
}
.o-gear {
  border-radius: 50%;
  border: 1.6px solid var(--app-ink);
  position: relative;
}
.o-gear::after {
  content: "";
  position: absolute;
  inset: 3.4px;
  border-radius: 50%;
  border: 1.4px solid var(--app-ink);
}

.o-title { font-size: 21px; letter-spacing: -0.2px; }
.o-meta { font-size: 9.5px; color: var(--app-stone); margin-top: 5px; }
.o-total { font-size: 15px; color: var(--app-stone); margin-top: 3px; }

.o-k {
  font-size: 9.5px;
  color: var(--app-muted);
  margin: 13px 0 5px;
}

.o-card {
  background: var(--app-surface);
  border-radius: 14px;
  padding: 0 11px;
}

.o-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 0;
  border-bottom: 1px solid var(--app-line);
}

.o-row:last-child { border-bottom: 0; }

/* Neutral, never ember — Avatar renders surfaceAlt behind inkDim initials.
   Initials come from splitting the name on spaces, so a single first name is
   one letter, not two. */
.o-av {
  width: 27px;
  height: 27px;
  border-radius: 50%;
  flex: none;
  display: grid;
  place-items: center;
  background: var(--app-track);
  color: var(--app-stone);
  font-size: 9.5px;
  font-weight: 400;
}

.o-t { flex: 1; min-width: 0; }
.o-t b { display: block; font-size: 12px; font-weight: 400; }
.o-t small { display: block; font-size: 8.5px; color: var(--app-muted); margin-top: 1px; }

.o-amt { font-size: 12px; flex: none; font-variant-numeric: tabular-nums; }

/* Chip: a ~13% wash of the tone behind text in that same tone. */
.o-chip {
  flex: none;
  font-size: 8.5px;
  font-weight: 500;
  color: var(--app-ember);
  background: rgba(210, 87, 30, 0.13);
  border-radius: 999px;
  padding: 2px 7px;
}

/* The call / message circles beside a member who left a phone number — real
   phone/message-circle icons (same paths as apps/leader/components/icons.tsx),
   not a clip-path approximation. */
.o-dots { display: flex; gap: 5px; flex: none; }
.o-dot {
  width: 19px;
  height: 19px;
  border-radius: 50%;
  border: 1px solid var(--app-line);
  background: var(--app-surface);
  color: var(--app-stone);
  display: grid;
  place-items: center;
}
.o-dot svg { width: 10px; height: 10px; }

.o-hint { font-size: 8.5px; color: var(--app-muted); margin-top: 6px; }

/* The remove control on an expense row, before any charge locks the splice. */
.o-minus {
  flex: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 1px solid var(--app-line);
  position: relative;
}
.o-minus::after {
  content: "";
  position: absolute;
  left: 3.5px;
  right: 3.5px;
  top: 50%;
  height: 1.3px;
  margin-top: -0.65px;
  background: #b3452a;
}


/* ---------------------------------------------------------------
   Circles
   --------------------------------------------------------------- */

/* width: 100% is load-bearing, not decorative — .split's default justify-self
   ("normal", which resolves to shrink-to-fit for a nested grid container like
   this one) left .circle-viz sized to its own content instead of its grid
   column. .ring's `width: min(340px, 100%)` then had no real containing-block
   width to resolve that 100% against, collapsed to a tiny box, and its
   aspect-ratio squared THAT — which is what actually broke on mobile: not a
   scrambled layout, a whole ring shrunk down to a sliver with every node and
   the core piled on top of each other. */
.circle-viz { display: grid; place-items: center; width: 100%; }

.ring {
  position: relative;
  width: min(340px, 100%);
  aspect-ratio: 1;
  border-radius: 50%;
  border: 1px dashed var(--rule);
  display: grid;
  place-items: center;
}

.ring::before {
  content: "";
  position: absolute;
  inset: 13%;
  border-radius: 50%;
  border: 1px solid var(--rule-soft);
}

.core {
  width: 47%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--cocoa);
  color: var(--paper);
  display: grid;
  place-content: center;
  text-align: center;
  gap: 2px;
  box-shadow: 0 20px 40px -18px rgba(28, 22, 16, 0.55);
}

.core small { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: #9c8d7d; }
.core b { font-family: var(--display); font-size: 30px; font-weight: 700; letter-spacing: -0.03em; }
.core em { font-style: normal; font-size: 11px; color: #b9ab9b; }

.node {
  position: absolute;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 12px;
  background: var(--leaf);
  border: 1px solid var(--rule);
  color: var(--ink-2);
}

/* Six seats, 60° apart, on the dashed ring. */
.n1 { top: -23px; left: 50%; margin-left: -23px; }
.n2 { top: 25%; right: -23px; margin-top: -23px; }
.n3 { bottom: 25%; right: -23px; margin-bottom: -23px; }
.n4 { bottom: -23px; left: 50%; margin-left: -23px; }
.n5 { bottom: 25%; left: -23px; margin-bottom: -23px; }
.n6 { top: 25%; left: -23px; margin-top: -23px; }

/* One live seat, so the circle reads as active rather than decorative. */
.n1 { background: var(--ember); border-color: var(--ember); color: #fff; }

/* ---------------------------------------------------------------
   What people split
   --------------------------------------------------------------- */

.tagcloud {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  max-width: 900px;
  margin: 0 auto;
}

.tagcloud span {
  font-family: var(--display);
  font-size: clamp(16px, 2vw, 26px);
  font-weight: 600;
  letter-spacing: -0.02em;
  padding: 9px 20px;
  border-radius: 999px;
  border: 1px solid var(--rule);
  color: var(--ink-2);
}

.tagcloud span:nth-child(3n) { background: var(--ember-wash); border-color: #f0cdb4; color: var(--ember); }
.tagcloud span:nth-child(5n) { background: var(--cocoa); border-color: var(--cocoa); color: var(--paper); }

/* ---------------------------------------------------------------
   FAQ
   --------------------------------------------------------------- */

.qa { max-width: 860px; margin-inline: auto; }

.qa details { border-top: 1px solid var(--rule); }
.qa details:last-child { border-bottom: 1px solid var(--rule); }

.qa summary {
  list-style: none;
  cursor: pointer;
  position: relative;
  padding: 22px 44px 22px 0;
  font-family: var(--display);
  font-size: clamp(18px, 2.1vw, 25px);
  font-weight: 600;
  letter-spacing: -0.025em;
  transition: color 0.16s;
}

.qa summary::-webkit-details-marker { display: none; }
.qa summary:hover { color: var(--ember); }

.qa summary::after,
.qa summary::before {
  content: "";
  position: absolute;
  right: 8px;
  top: 50%;
  background: var(--ember);
  transition: transform 0.22s cubic-bezier(0.2, 0.7, 0.2, 1), opacity 0.22s;
}

.qa summary::before { width: 15px; height: 1.5px; margin-top: -0.75px; }
.qa summary::after { width: 1.5px; height: 15px; margin-top: -7.5px; margin-right: 6.75px; }

.qa details[open] summary::after { transform: rotate(90deg); opacity: 0; }

.qa details p {
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 62ch;
  padding-bottom: 24px;
}

.qa details strong { color: var(--ink); font-weight: 600; }
.qa details a { color: var(--ember); text-underline-offset: 3px; }

/* ---------------------------------------------------------------
   Messaging policy page
   --------------------------------------------------------------- */

.msg-page { padding-top: clamp(34px, 5vw, 58px); }

.sms-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(250px, 26vw, 300px);
  gap: clamp(28px, 4.5vw, 64px);
  align-items: start;
}

.policy dt {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ember);
  padding-top: 18px;
}

.policy dd {
  font-size: 15px;
  color: var(--ink-2);
  padding: 5px 0 18px;
  border-bottom: 1px solid var(--rule-soft);
  max-width: 64ch;
}

.policy dd:last-of-type { border-bottom: 0; }
.policy strong { color: var(--ink); font-weight: 600; }
.policy a { color: var(--ember); text-underline-offset: 3px; }

.phone-sticky { position: sticky; top: 24px; }

/* SMS screen — the Twilio evidence. */
.scr-sms { flex: 1; min-height: 0; overflow: hidden; background: var(--cocoa); padding: 26px 13px 13px; }
.scr-sms .bar { display: flex; justify-content: space-between; padding-bottom: 11px; margin-bottom: 12px; border-bottom: 1px solid rgba(244, 238, 225, 0.1); }
.scr-sms .bar span { font-family: var(--mono); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase; color: #8a7c6c; }

.bubble {
  background: #2f251c;
  border-radius: 14px 14px 14px 4px;
  padding: 10px 12px;
  font-size: 12.5px;
  line-height: 1.5;
  color: #ded2c3;
  margin-bottom: 8px;
}
.bubble b { color: var(--paper); font-weight: 500; }
.bubble .amt { font-family: var(--mono); color: #f0a173; }
.bubble .stop { display: block; margin-top: 6px; font-size: 10.5px; color: #8a7c6c; }

.phone-sticky .home-bar { background: rgba(244, 238, 225, 0.4); }

/* Opt-in evidence */

.optin {
  margin-top: clamp(46px, 6vw, 78px);
  background: var(--cocoa);
  color: var(--paper);
  border-radius: 26px;
  padding: clamp(30px, 4.5vw, 58px);
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(260px, 28vw, 330px);
  gap: clamp(28px, 4.5vw, 60px);
  align-items: center;
}

.optin .label { color: #eb8b52; }

.optin h3 {
  font-family: var(--display);
  font-size: clamp(26px, 3.4vw, 42px);
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 1.02;
  margin: 12px 0 14px;
  text-transform: uppercase;
}

.optin p { color: #b9ab9b; font-size: 15px; max-width: 50ch; }

.optin ul { list-style: none; margin-top: 20px; border-top: 1px solid rgba(244, 238, 225, 0.12); }

.optin li {
  position: relative;
  font-size: 14.5px;
  color: #cdbfae;
  padding: 11px 0 11px 19px;
  border-bottom: 1px solid rgba(244, 238, 225, 0.08);
}

.optin li::before {
  content: "";
  position: absolute;
  left: 1px;
  top: 19px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ember-hot);
}

.optin li b { color: var(--paper); font-weight: 600; }

.replica {
  background: var(--paper);
  color: var(--ink);
  border-radius: 18px;
  padding: 22px 20px;
  box-shadow: 0 24px 46px -22px rgba(0, 0, 0, 0.55);
}

.replica h4 { font-family: var(--display); font-size: 20px; font-weight: 600; letter-spacing: -0.025em; margin: 8px 0 6px; }

.fake-field {
  background: var(--leaf);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 11px 12px;
  font-size: 14px;
  color: var(--ink-3);
  margin-top: 9px;
}

.consent {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin-top: 13px;
  padding: 12px;
  background: var(--leaf);
  border: 1px solid var(--rule);
  border-radius: 10px;
}

.consent input { flex: none; width: 16px; height: 16px; margin-top: 1px; accent-color: var(--ember); }
.consent label { font-size: 12px; line-height: 1.5; color: var(--ink-2); }
.consent a { color: var(--ember); }

.fake-btn {
  margin-top: 13px;
  border-radius: 999px;
  padding: 12px;
  text-align: center;
  font-size: 14px;
  font-weight: 600;
  background: var(--ember);
  color: #fff;
  opacity: 0.34;
}

/* ---------------------------------------------------------------
   Closing call to action
   --------------------------------------------------------------- */

/* No top rule: the FAQ already closes itself with one, and a second line a few
   pixels below it read as a double underline rather than a section break. */
.closer {
  margin-top: clamp(52px, 7vw, 92px);
  text-align: center;
  padding: clamp(40px, 6vw, 76px) 0;
}

.closer h2 { font-size: clamp(34px, 5.4vw, 66px); text-transform: uppercase; }
.closer h2 .fill { color: var(--ember); }
.closer .lede { margin: 18px auto 0; text-align: center; }
.closer .ctas { justify-content: center; margin-top: 26px; }
.closer .fud { justify-content: center; }

/* ---------------------------------------------------------------
   Footer
   --------------------------------------------------------------- */

footer {
  position: relative;
  z-index: 1;
  padding: 24px 0 52px;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px 30px;
}

.foot-links { display: flex; flex-wrap: wrap; gap: 24px; font-size: 14px; color: var(--ink-2); }
.foot-links a { text-decoration: none; }
.foot-links a:hover { color: var(--ember); }

/* ---------------------------------------------------------------
   Legal pages
   --------------------------------------------------------------- */

.legal { max-width: 68ch; padding: clamp(34px, 5vw, 58px) 0 0; }

.legal h1 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(38px, 5.6vw, 64px);
  letter-spacing: -0.04em;
  line-height: 1;
  text-transform: uppercase;
  margin-bottom: 12px;
}

.legal h2 {
  font-family: var(--display);
  font-weight: 600;
  font-size: 23px;
  letter-spacing: -0.025em;
  margin: 42px 0 12px;
  padding-top: 18px;
  border-top: 1px solid var(--rule-soft);
}

.legal h3 { font-size: 16px; font-weight: 600; margin: 24px 0 7px; }
.legal p, .legal li { font-size: 16.5px; line-height: 1.62; color: #453b30; margin-bottom: 13px; }
.legal ul { padding-left: 20px; margin-bottom: 14px; }
.legal li { margin-bottom: 7px; }
.legal a { color: var(--ember); text-underline-offset: 3px; }
.legal strong { color: var(--ink); font-weight: 600; }

.updated {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 32px;
}

.masthead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 22px 0 18px;
  border-bottom: 1px solid var(--rule);
}

.masthead .nav { display: flex; gap: 26px; font-size: 14.5px; color: var(--ink-2); }
.masthead .nav a { text-decoration: none; }
.masthead .nav a:hover { color: var(--ember); }
.brand-name { font-family: var(--display); font-weight: 700; font-size: 21px; letter-spacing: -0.03em; }

/* ---------------------------------------------------------------
   404
   --------------------------------------------------------------- */

.notfound {
  text-align: center;
  padding: clamp(64px, 12vw, 140px) 0;
}

.notfound h1 { font-size: clamp(34px, 5.4vw, 60px); text-transform: uppercase; margin: 10px 0 16px; }
.notfound h1 .fill { color: var(--ember); }
.notfound .label { display: block; }
.notfound .lede { margin: 0 auto; text-align: center; }
.notfound .ctas { justify-content: center; margin-top: 30px; }

/* ---------------------------------------------------------------
   Motion — one orchestrated load
   --------------------------------------------------------------- */

@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

.rise { animation: rise 0.68s cubic-bezier(0.2, 0.7, 0.2, 1) both; }
.d1 { animation-delay: 0.04s; }
.d2 { animation-delay: 0.12s; }
.d3 { animation-delay: 0.2s; }
.d4 { animation-delay: 0.28s; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  html { scroll-behavior: auto; }
}

/* ---------------------------------------------------------------
   Responsive
   --------------------------------------------------------------- */

@media (max-width: 1000px) {
  .hero, .sms-grid, .optin, .split { grid-template-columns: minmax(0, 1fr); }
  .hero { gap: 34px; padding-top: 30px; }
  /* Headline leads on mobile. The product shot supports it, it doesn't
     replace it as the first thing seen. */
  .phone-wrap { margin-top: 4px; }
  .phone-sticky { position: static; max-width: 300px; }
  .navlinks, .masthead .nav { display: none; }
  .compare { grid-template-columns: minmax(0, 1fr); }
  .circle-viz { max-width: 330px; margin: 8px auto 0; }
  .phone-wrap--quiet { margin: 4px auto 0; }
  .sticky-cta { display: flex; }
  /* Room for the bar itself, plus the safe-area inset it already pads
     itself with — without this the closer section's own CTA and the
     footer links sit right underneath it, unreachable. */
  body { padding-bottom: calc(66px + env(safe-area-inset-bottom)); }
}

@media (max-width: 380px) {
  /* The brand mark alone still says "this is Splice" — the tagline is the
     first thing to go when there isn't room for both it and a legible
     App Store badge on one line. */
  .sticky-cta-text { display: none; }
}

@media (max-width: 620px) {
  body { font-size: 16px; }
  .hero h1 { font-size: clamp(42px, 13vw, 62px); }
  .codes { gap: 5px; width: 100%; }
  .codes input { flex: 1 1 0; width: auto; min-width: 0; height: 54px; }
  .ctas { gap: 10px; }
  .ctas .btn { flex: 1 1 100%; }
  .optin { padding: 26px 20px; }
  .policy dd { font-size: 14.5px; }
  .tagcloud span { font-size: 15px; padding: 7px 15px; }
}
