/* P1-618 — the White look's FLOW stylesheet.
 *
 * A port of the approved mockup `_redesign/mockup/flow2/src/flow.css` +
 * `proposed.css`, covering the quiz, the wait page, the preview and
 * paywall, the redo page and the after-payment screens. Ported by script,
 * and these are every transformation it applied:
 *
 *   1. Comments stripped.
 *   2. 5 `@font-face` blocks DROPPED. `next/font` supplies DM Sans and
 *      Lora with the fallback metrics (`size-adjust`) that a bare
 *      `@font-face` cannot, which is what stops the layout shifting as
 *      Lora arrives.
 *   3. `'DM Sans'` and `'Lora'` rewritten to `var(--white-sans, …)` /
 *      `var(--white-serif, …)`, the variables `app/_white/fonts.ts` sets.
 *   4. The mockup's OWN chrome dropped — `.mk*` (its toolbar), `.ov*` (its
 *      all-screens overview), `body.mode-all`.
 *   5. EVERY rule scoped under `.sb-white`, INCLUDING the ones inside
 *      `@media`, `@supports` and `@container`.
 *
 * ⚠ THAT LAST WORD COST A WHOLE LAYOUT. The first version of this porter
 * recursed into `@media` and `@supports` but NOT `@container`, so the 62
 * rules inside the mockup's seventeen `@container` blocks came out
 * UNSCOPED — and unscoped is not merely untidy, it is DEAD: a bare
 * `.qz-main` is specificity (0,1,0) and loses to this file's own scoped
 * `.sb-white .qz-main` at (0,2,0), whatever the source order. The
 * mockup uses container queries for its entire wide layout, so the quiz
 * silently had no desktop: 640px main column instead of 800px, two-across
 * options instead of four, 30px titles instead of 42px.
 *
 * It survived a 36-of-36 property comparison against the mockup because
 * that comparison was run at 390px, where container queries do not fire.
 * The founder found it by looking at a desktop screenshot. **Compare at
 * more than one width, and check what an at-rule you did not plan for
 * did to its contents.**
 *
 * WHY THIS FILE LIVES IN `public/` AND IS LINKED, NOT IMPORTED: an
 * `import` puts a stylesheet into the ROUTE's CSS, because Next collects a
 * route's CSS from its entire module graph at build time. On the landing
 * that shipped ~1,000 White-look rules to every visitor of today's page
 * to render nothing (R10).
 *
 * THE COST OF LEAVING THE CSS PIPELINE: no content hash. `WHITE_FLOW_CSS`
 * in `app/_white/fonts.ts` carries a manual `?v=` — BUMP IT ON EVERY EDIT
 * TO THIS FILE or browsers keep the old one.
 *
 * Checked before porting, because both would have been silent failures:
 *   - `app/create/funnel.css` has ZERO unscoped element selectors (every
 *     rule is under `.funnel-scope`), so it cannot bleed into this
 *     subtree.
 *   - Zero custom-property name collisions: `funnel.css` uses `--sb-*`,
 *     this file uses bare names (`--navy`, `--line`, `--font`).
 */

.sb-white {--navy:#0A2540; --ink2:#33475B; --muted:#4A5B6E; --line:#A3B1C2; --hair:#E3E8EE; --surface:#F6F9FC; --page:#FFFFFF; --ground:#E9EEF4;
  --blurple:#635BFF; --blurple-h:#5449E6; --blurple-d:#4A40D1; --tint:#F1F0FF; --green:#00B67A; --error:#B42318;
  --font:var(--white-sans, 'DM Sans'),-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;
  --ring:0 0 0 4px rgba(99,91,255,.30);
  color-scheme:light;}
.sb-white *, .sb-white *::before, .sb-white *::after {box-sizing:border-box}
.sb-white {background:var(--page)}
.sb-white {margin:0;background:var(--page);color:var(--navy);font-family:var(--font);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
.sb-white button {font-family:inherit}
@media (prefers-reduced-motion:reduce) {
.sb-white *, .sb-white *::before, .sb-white *::after {transition:none!important;animation:none!important}
}
.sb-white .qz {container-type:inline-size;position:relative;display:flex;flex-direction:column;min-height:calc(100dvh - 52px);background:var(--page);color:var(--navy)}
.sb-white .qz--frame {min-height:100%}
.sb-white .qz-top {position:sticky;top:env(safe-area-inset-top,0px);z-index:5;background:var(--page)}
.sb-white .qz--frame .qz-top {top:0}
.sb-white .qz-top__in {max-width:800px;margin:0 auto;padding:10px 14px;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:10px}
.sb-white .qz-back {justify-self:start;display:inline-flex;align-items:center;gap:2px;min-height:44px;padding:0 8px 0 2px;border:0;border-radius:10px;background:none;color:var(--navy);font:500 16px/1 var(--font);cursor:pointer}
.sb-white .qz-back svg {width:22px;height:22px}
.sb-white .qz-back:hover {color:var(--blurple-d)}
.sb-white .qz-logo {display:block;height:26px;width:auto}
.sb-white .qz-count {justify-self:end;font:500 14px/1.2 var(--font);color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
.sb-white .qz-bar {height:6px;background:#E6EBF1}
.sb-white .qz-bar i {display:block;height:100%;width:0;background:var(--blurple);border-radius:0 3px 3px 0;transition:width 400ms cubic-bezier(.2,.8,.2,1)}
.sb-white .qz-main {flex:1;width:100%;max-width:640px;margin:0 auto;padding:22px 20px 28px;display:flex;flex-direction:column;gap:18px}
.sb-white .qz-phase {margin:0;font:700 16px/1.2 var(--font);color:var(--blurple-d)}
.sb-white .qz-title {margin:0;font:700 30px/1.15 var(--font);letter-spacing:-0.03em;color:var(--navy);text-wrap:pretty}
.sb-white .qz-sub {margin:-6px 0 0;font:400 19px/1.5 var(--font);color:var(--ink2);text-wrap:pretty}
.sb-white .qz-hint {margin:-4px 0 0;font:400 17px/1.5 var(--font);color:var(--muted)}
.sb-white .qz-proof {align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin:0;padding:8px 16px 8px 10px;border-radius:100px;background:var(--tint);color:var(--blurple-d);font:700 16px/1.25 var(--font)}
.sb-white .qz-proof svg {width:20px;height:20px;flex:none}
.sb-white .qz-proof--rv {flex-wrap:wrap;gap:8px 10px;padding:0;border-radius:0;background:none;color:var(--navy);font-weight:500;font-size:17px}
.sb-white .qz-stars {display:inline-flex;gap:2px}
.sb-white .qz-stars span {display:grid;place-items:center;width:20px;height:20px;background:var(--green)}
.sb-white .qz-stars svg {width:13px;height:13px}
.sb-white .qz-grid {display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.sb-white .qz-opt {position:relative;display:flex;align-items:center;gap:10px;min-height:60px;padding:12px 14px;border:1.5px solid var(--line);border-radius:14px;background:var(--page);color:var(--navy);font:500 18px/1.25 var(--font);text-align:left;cursor:pointer;transition:border-color 160ms ease,background 160ms ease,color 160ms ease}
.sb-white .qz-opt:hover {border-color:var(--navy)}
.sb-white .qz-opt .qz-tick {display:none}
.sb-white .qz-opt[aria-pressed="true"] {background:var(--blurple);border-color:var(--blurple);color:#FFFFFF}
.sb-white .qz-opt[aria-pressed="true"] .qz-tick {display:block}
.sb-white .qz-tick {width:20px;height:20px;flex:none}
.sb-white .qz-opt:focus-visible, .sb-white .qz-pill:focus-visible, .sb-white .qz-btn:focus-visible, .sb-white .qz-back:focus-visible, .sb-white .qz-link:focus-visible, .sb-white .qz-row:focus-visible, .sb-white .qz-x:focus-visible {outline:none;box-shadow:var(--ring)}
.sb-white .qz-pills {display:flex;flex-wrap:wrap;gap:10px}
.sb-white .qz-pill {display:inline-flex;align-items:center;gap:8px;min-height:52px;padding:8px 20px;border:1.5px solid var(--line);border-radius:100px;background:var(--page);color:var(--navy);font:500 18px/1.2 var(--font);cursor:pointer;transition:border-color 160ms ease,background 160ms ease,color 160ms ease}
.sb-white .qz-pill:hover {border-color:var(--navy)}
.sb-white .qz-pill .qz-tick {display:none;width:18px;height:18px;margin-left:-4px}
.sb-white .qz-pill[aria-pressed="true"] {background:var(--blurple);border-color:var(--blurple);color:#FFFFFF;padding-left:14px}
.sb-white .qz-pill[aria-pressed="true"] .qz-tick {display:block}
.sb-white .qz-label {margin:4px 0 -8px;font:700 17px/1.3 var(--font);color:var(--navy)}
.sb-white .qz-field {display:flex;flex-direction:column;gap:10px}
.sb-white .qz-input, .sb-white .qz-area {width:100%;border:1.5px solid var(--line);border-radius:14px;background:var(--page);color:var(--navy);font:400 20px/1.4 var(--font);transition:border-color 160ms ease,box-shadow 160ms ease}
.sb-white .qz-input {min-height:62px;padding:14px 16px}
.sb-white .qz-area {min-height:200px;padding:16px;font-size:19px;line-height:1.55;resize:vertical}
.sb-white .qz-input::placeholder, .sb-white .qz-area::placeholder {color:#7A8A9C;opacity:1}
.sb-white .qz-input:focus, .sb-white .qz-area:focus {outline:none;border-color:var(--blurple);box-shadow:var(--ring)}
.sb-white .qz-inline {display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:4px 16px}
.sb-white .qz-note {margin:0;font:400 16px/1.45 var(--font);color:var(--muted)}
.sb-white .qz-link {display:inline-flex;align-items:center;min-height:44px;padding:0;border:0;background:none;color:var(--blurple-d);font:500 17px/1.2 var(--font);text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:1.5px;cursor:pointer}
.sb-white .qz-err {margin:0;font:500 17px/1.4 var(--font);color:var(--error)}
.sb-white .qz-smart {display:flex;flex-direction:column;gap:12px;padding:16px;border-radius:14px;background:var(--surface);border:1px solid var(--hair);font:500 18px/1.35 var(--font)}
.sb-white .qz-smart__acts {display:flex;flex-wrap:wrap;gap:8px}
.sb-white .qz-smart__acts button {min-height:48px;padding:0 18px;border:1.5px solid var(--line);border-radius:100px;background:var(--page);color:var(--navy);font:500 17px/1 var(--font);cursor:pointer}
.sb-white .qz-smart__acts .qz-keep {border-color:transparent;background:none;text-decoration:underline;text-underline-offset:4px;color:var(--muted)}
.sb-white .qz-picked {display:flex;align-items:center;justify-content:space-between;gap:14px;padding:12px 16px;border-radius:14px;background:var(--surface);border:1px solid var(--hair)}
.sb-white .qz-picked__k {display:block;font:700 15px/1.2 var(--font);color:var(--muted)}
.sb-white .qz-picked__v {display:block;margin-top:3px;font:700 19px/1.25 var(--font);color:var(--navy)}
.sb-white .qz-group {display:flex;flex-direction:column;gap:12px}
.sb-white .qz-group__t {margin:6px 0 0;font:700 20px/1.2 var(--font);color:var(--navy)}
.sb-white .qz-rows {display:flex;flex-direction:column;border:1.5px solid var(--hair);border-radius:16px;overflow:hidden;background:var(--page)}
.sb-white .qz-row {display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:14px;padding:16px 18px;border:0;border-top:1px solid var(--hair);background:var(--page);color:var(--navy);text-align:left;cursor:pointer}
.sb-white .qz-row:first-child {border-top:0}
.sb-white .qz-row:hover {background:var(--surface)}
.sb-white .qz-row__k {display:block;font:700 15px/1.2 var(--font);color:var(--muted)}
.sb-white .qz-row__v {display:-webkit-box;margin-top:4px;font:400 19px/1.4 var(--font);color:var(--navy);-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
.sb-white .qz-row__v--soft {color:var(--muted)}
.sb-white .qz-row__c {font:500 17px/1 var(--font);color:var(--blurple-d);text-decoration:underline;text-underline-offset:4px}
.sb-white .qz-foot {position:sticky;bottom:0;z-index:4;background:rgba(255,255,255,.97);border-top:1px solid var(--hair);padding:12px 20px calc(12px + env(safe-area-inset-bottom,0px))}
.sb-white .qz-foot__in {max-width:600px;margin:0 auto;display:flex;flex-direction:column;align-items:stretch;gap:8px}
.sb-white .qz-btn {display:inline-flex;align-items:center;justify-content:center;gap:10px;min-height:64px;padding:0 28px;border:0;border-radius:14px;background:var(--blurple);color:#FFFFFF;font:700 20px/1.2 var(--font);box-shadow:0 14px 28px -14px rgba(99,91,255,.9);cursor:pointer;transition:background 160ms ease}
.sb-white .qz-btn:hover {background:var(--blurple-h)}
.sb-white .qz-btn svg {width:22px;height:22px;flex:none}
.sb-white .qz-btn[disabled], .sb-white .qz-btn[aria-disabled="true"] {background:#E3E8EE;color:#6B7B8D;box-shadow:none;cursor:not-allowed}
.sb-white .qz-under {margin:0;font:500 16px/1.4 var(--font);color:var(--muted);text-align:center;text-wrap:balance}
.sb-white .qz-inlinebtn {display:flex;flex-direction:column;gap:8px;margin-top:4px}
.sb-white .qz-modal {position:fixed;inset:0;z-index:20;display:flex;align-items:flex-end;justify-content:center;background:rgba(10,37,64,.55)}
.sb-white .qz--frame .qz-modal {position:absolute}
.sb-white .qz-sheet {position:relative;width:100%;max-height:100%;overflow:auto;display:flex;flex-direction:column;gap:14px;padding:30px 22px calc(26px + env(safe-area-inset-bottom,0px));border-radius:24px 24px 0 0;background:var(--page);box-shadow:0 -20px 60px -30px rgba(10,37,64,.6)}
.sb-white .qz-x {position:absolute;top:14px;right:14px;display:grid;place-items:center;width:48px;height:48px;border:1.5px solid var(--line);border-radius:50%;background:var(--page);color:var(--navy);cursor:pointer}
.sb-white .qz-x svg {width:20px;height:20px}
.sb-white .qz-sheet h2 {margin:6px 60px 0 0;font:700 30px/1.15 var(--font);letter-spacing:-0.03em}
.sb-white .qz-sheet p {margin:0}
.sb-white .qz-sheet .qz-sub {margin:0}
.sb-white .qz-fine {font:500 16px/1.4 var(--font);color:var(--muted);text-align:center}
@container (min-width:700px) {
.sb-white .qz-top__in {padding:14px 24px}
.sb-white .qz-logo {height:28px}
.sb-white .qz-count {font-size:15px}
.sb-white .qz-main {max-width:800px;padding:40px 32px 12px;gap:22px}
.sb-white .qz-title {font-size:42px;line-height:1.1}
.sb-white .qz-sub {font-size:21px}
.sb-white .qz-grid {grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}
.sb-white .qz-grid--3 {grid-template-columns:repeat(3,minmax(0,1fr))}
.sb-white .qz-opt {min-height:64px;font-size:19px;padding:14px 16px}
.sb-white .qz-main {flex:0 0 auto}
.sb-white .qz-foot {background:rgba(255,255,255,.97);border-top:0;padding:16px 0 28px;margin-bottom:48px}
.sb-white .qz-foot__in {max-width:800px;padding:0 32px;flex-direction:row;align-items:center;gap:22px}
.sb-white .qz-btn {min-width:340px}
.sb-white .qz-under {text-align:left}
.sb-white .qz-modal {align-items:center;padding:24px}
.sb-white .qz-sheet {max-width:500px;border-radius:24px;padding:40px 36px 34px;box-shadow:0 40px 80px -40px rgba(10,37,64,.7)}
}
@container (min-width:520px) and (max-width:699.98px) {
.sb-white .qz-grid {grid-template-columns:repeat(3,minmax(0,1fr))}
}
.sb-white {--navy2:#12355A;--navy3:#0E2C4B;--onnavy:#E8EEF5;--onnavy2:#ADBDCC;--cyan:#00D4FF}
.sb-white .fl-main {flex:1;width:100%;max-width:600px;margin:0 auto;padding:22px 20px 40px;display:flex;flex-direction:column;gap:18px}
.sb-white .fl-h {margin:0;font:700 30px/1.15 var(--font);letter-spacing:-0.03em;color:var(--navy);text-wrap:pretty}
.sb-white .fl-p {margin:0;font:400 19px/1.5 var(--font);color:var(--ink2);text-wrap:pretty}
/* Visible to a screen reader, invisible to everyone else. The lyrics
 * page's `<h1>` lives here: the founder took the visible heading away —
 * it told the buyer what they had just done, and cost the fold — and a
 * page with NO heading is a worse page than one with a wasted line.
 * `clip-path` rather than `display:none`, which would hide it from
 * assistive tech too, and rather than a negative text-indent, which
 * leaves a 1px scrollable box behind. */
.sb-white .fl-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.sb-white .fl-small {margin:0;font:500 16px/1.45 var(--font);color:var(--muted)}
.sb-white .fl-top {position:sticky;top:env(safe-area-inset-top,0px);z-index:5;background:var(--page);border-bottom:1px solid var(--hair)}
.sb-white .qz--frame .fl-top {top:0}
.sb-white .fl-top__in {max-width:800px;margin:0 auto;padding:10px 14px;display:flex;align-items:center;gap:12px}
.sb-white .fl-top .qz-logo {margin-right:auto}
.sb-white .fl-top__right {font:500 15px/1.2 var(--font);color:var(--muted)}
.sb-white .fl-btn2 {display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:60px;padding:0 24px;border:2px solid var(--navy);border-radius:14px;background:var(--page);color:var(--navy);font:700 19px/1.2 var(--font);cursor:pointer}
.sb-white .fl-btn2:hover {background:var(--surface)}
.sb-white .fl-textlink {align-self:center;min-height:48px;padding:0 8px;border:0;background:none;color:var(--muted);font:500 17px/1.2 var(--font);text-decoration:underline;text-underline-offset:4px;cursor:pointer}
.sb-white .fl-textlink:hover {color:var(--navy)}
.sb-white .qz-btn.fl-wide, .sb-white .fl-btn2.fl-wide {width:100%}
.sb-white .wt-status {display:flex;flex-direction:column;gap:10px}
.sb-white .wt-row {display:flex;align-items:center;justify-content:space-between;gap:12px}
.sb-white .wt-stage {display:inline-flex;align-items:center;gap:10px;font:700 15px/1.2 var(--font);letter-spacing:.08em;text-transform:uppercase;color:var(--blurple-d)}
.sb-white .wt-dot {width:10px;height:10px;border-radius:50%;background:var(--blurple);animation:wtPulse 1.6s ease-in-out infinite}
@keyframes wtPulse {0%,100%{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.8)}}
.sb-white .wt-pct {font:700 26px/1 var(--font);color:var(--blurple-d);font-variant-numeric:tabular-nums}
.sb-white .wt-bar {height:10px;border-radius:10px;background:#E6EBF1;overflow:hidden}
.sb-white .wt-bar i {display:block;height:100%;background:linear-gradient(90deg,var(--blurple),#8C85FF);border-radius:10px;transition:width 300ms linear}
.sb-white .wt-soon {display:flex;align-items:center;gap:12px;margin:0;padding:14px 16px;border-radius:14px;background:var(--tint);color:var(--blurple-d);font:700 17px/1.4 var(--font)}
.sb-white .wt-soon svg {width:22px;height:22px;flex:none}
.sb-white .wt-ready .wt-stage {color:#0B7A55}
.sb-white .wt-ready .wt-pct {color:#0B7A55}
.sb-white .wt-ready .wt-bar i {background:var(--green)}
.sb-white .bd {display:flex;flex-direction:column;gap:16px;animation:bdIn 360ms cubic-bezier(.2,.8,.2,1)}
@keyframes bdIn {from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.sb-white .bd-dots {display:flex;justify-content:center;gap:10px;padding:6px 0 0}
.sb-white .bd-dots i {width:10px;height:10px;border-radius:50%;background:#CBD5E1}
.sb-white .bd-dots i.on {background:var(--blurple);width:26px;border-radius:10px}
.sb-white .bd-intro {display:grid;grid-template-columns:auto 1fr;gap:18px;align-items:center}
.sb-white .bd-mini {width:132px;transform:rotate(-2.5deg);border-radius:14px;overflow:hidden;box-shadow:0 18px 36px -18px rgba(10,37,64,.6)}
.sb-white .bd-lead {margin:0;font:700 28px/1.15 var(--font);letter-spacing:-0.03em;color:var(--navy);text-wrap:balance}
.sb-white .bd-lead span {display:block;margin-top:6px;font:400 19px/1.4 var(--font);letter-spacing:0;color:var(--ink2)}
.sb-white .bd-photo {position:relative;border-radius:20px;overflow:hidden;box-shadow:0 24px 48px -30px rgba(10,37,64,.55)}
.sb-white .bd-photo > img {display:block;width:100%;aspect-ratio:1/1;object-fit:cover}
.sb-white .bd-plus {position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:grid;place-items:center;width:84px;height:84px;border-radius:50%;border:0;background:#FFFFFF;color:var(--navy);box-shadow:0 12px 30px -10px rgba(0,0,0,.5);cursor:pointer}
.sb-white .bd-plus svg {width:34px;height:34px}
.sb-white .bd-plus span {position:absolute;top:100%;margin-top:10px;white-space:nowrap;font:700 17px/1 var(--font);color:#FFFFFF;text-shadow:0 1px 8px rgba(0,0,0,.5)}
.sb-white .bd-pills {position:absolute;left:12px;right:12px;bottom:12px;display:flex;gap:8px;justify-content:center}
.sb-white .bd-pills button {min-height:44px;padding:0 16px;border:0;border-radius:100px;background:rgba(255,255,255,.94);color:var(--navy);font:700 16px/1 var(--font);cursor:pointer}
.sb-white .bd-file {position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}
.sb-white .bd-signpills {display:flex;flex-wrap:wrap;gap:10px}
.sb-white .bd-actions {display:flex;flex-direction:column;gap:6px;margin-top:4px}
.sb-white .cv {position:relative;aspect-ratio:1/1;width:100%;display:flex;flex-direction:column;justify-content:center;align-items:center;gap:12px;padding:10%;text-align:center;color:#FFFFFF;background:radial-gradient(90% 70% at 50% 18%,rgba(99,91,255,.55),rgba(99,91,255,0) 62%),radial-gradient(70% 50% at 80% 100%,rgba(0,212,255,.22),rgba(0,212,255,0) 60%),var(--navy);overflow:hidden}
.sb-white .cv__k {font:700 clamp(10px,3.4cqi,15px)/1.2 var(--font);letter-spacing:.16em;text-transform:uppercase;color:var(--cyan)}
.sb-white .cv__t {font:700 clamp(22px,11cqi,52px)/1.02 var(--font);letter-spacing:-0.035em}
.sb-white .cv__rule {width:18%;height:2px;background:rgba(255,255,255,.4)}
.sb-white .cv__wave {display:flex;align-items:center;gap:3%;height:14%;width:62%}
.sb-white .cv__wave i {flex:1;border-radius:3px;background:var(--cyan);opacity:.9}
.sb-white .cv .cv__logo {position:absolute;bottom:6%;left:50%;transform:translateX(-50%);width:24%;height:auto;max-width:none;opacity:.85;filter:brightness(0) invert(1)}
.sb-white .cvwrap {container-type:inline-size}
.sb-white .gp {display:flex;flex-direction:column;gap:14px}
.sb-white .gp-title {margin:0;text-align:center;font:700 30px/1.12 var(--font);letter-spacing:-0.03em;color:var(--navy);text-wrap:balance}
.sb-white .gp-for {margin:-6px 0 0;text-align:center;font:500 18px/1.3 var(--font);color:var(--ink2)}
.sb-white .gp-for b {color:#E0457B;font-weight:700}
.sb-white .gp-note {position:relative;margin:0;padding:22px 20px 18px;border-radius:16px;background:#FFFFFF;border:1px solid var(--hair);box-shadow:0 20px 40px -32px rgba(10,37,64,.5);text-align:left;cursor:pointer}
.sb-white .gp-note p {margin:0;font:400 19px/1.55 var(--font);color:var(--navy);white-space:pre-line}
.sb-white .gp-note .gp-sign {margin-top:12px;font:700 15px/1.2 var(--font);letter-spacing:.1em;text-transform:uppercase;color:var(--blurple-d);font-style:normal}
.sb-white .gp-addnote {align-self:center}
.sb-white .gp-foot {margin:0;text-align:center;font:500 16px/1.45 var(--font);color:var(--muted)}
.sb-white .pl {display:flex;flex-direction:column;gap:10px;padding:14px 16px;border-radius:16px;background:var(--surface);border:1px solid var(--hair)}
.sb-white .pl-times {display:flex;align-items:center;gap:12px;font:500 15px/1 var(--font);color:var(--muted);font-variant-numeric:tabular-nums}
.sb-white .pl-track {position:relative;flex:1;height:6px;border-radius:6px;background:#D9E1EA}
.sb-white .pl-track i {position:absolute;left:0;top:0;bottom:0;border-radius:6px;background:var(--blurple)}
.sb-white .pl-track b {position:absolute;top:50%;width:14px;height:14px;margin:-7px 0 0 -7px;border-radius:50%;background:var(--blurple)}
.sb-white .pl-ctrl {display:flex;align-items:center;justify-content:center;gap:26px}
.sb-white .pl-ctrl button {display:grid;place-items:center;border:0;background:none;color:var(--navy);cursor:pointer;width:48px;height:48px;border-radius:50%}
.sb-white .pl-ctrl button svg {width:24px;height:24px}
.sb-white .pl-ctrl .pl-play {width:72px;height:72px;background:var(--blurple);color:#FFFFFF;box-shadow:0 14px 28px -14px rgba(99,91,255,.9)}
.sb-white .pl-ctrl .pl-play svg {width:30px;height:30px}
.sb-white .pl--off {opacity:.55}
.sb-white .rv {background:var(--navy);color:var(--onnavy);min-height:100%}
.sb-white .rv-strip {max-width:600px;margin:0 auto;padding:14px 20px 4px;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px 14px}
.sb-white .rv-strip span {font:700 13px/1.3 var(--font);letter-spacing:.12em;text-transform:uppercase;color:var(--onnavy2)}
.sb-white .rv-strip button {display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0;border:0;background:none;color:#FFFFFF;font:700 16px/1.2 var(--font);text-decoration:underline;text-underline-offset:4px;cursor:pointer}
.sb-white .rv-strip button svg {width:18px;height:18px}
.sb-white .rv-main {max-width:600px;margin:0 auto;padding:10px 20px 48px;display:flex;flex-direction:column;gap:18px}
.sb-white .rv-photo {border-radius:20px;overflow:hidden;box-shadow:0 30px 60px -30px rgba(0,0,0,.8)}
.sb-white .rv-photo > img {display:block;width:100%;aspect-ratio:1/1;object-fit:cover}
.sb-white .rv .gp-title {color:#FFFFFF;font-size:34px}
.sb-white .rv .gp-for {color:var(--onnavy)}
.sb-white .rv .gp-for b {color:#FF8FB5}
.sb-white .rv .pl {background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.12)}
.sb-white .rv .pl-times {color:var(--onnavy2)}
.sb-white .rv .pl-track {background:rgba(255,255,255,.18)}
.sb-white .rv .pl-track i, .sb-white .rv .pl-track b {background:var(--cyan)}
.sb-white .rv .pl-ctrl button {color:#FFFFFF}
.sb-white .rv .pl-ctrl .pl-play {background:#FFFFFF;color:var(--navy);box-shadow:0 14px 30px -12px rgba(0,0,0,.7)}
.sb-white .rv .gp-note {background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.14);box-shadow:none}
.sb-white .rv .gp-note p {color:#FFFFFF}
.sb-white .rv .gp-note .gp-sign {color:#B7B2FF}
.sb-white .rv-more {align-self:flex-start;min-height:44px;padding:0;border:0;background:none;color:#FFFFFF;font:700 16px/1.2 var(--font);text-decoration:underline;text-underline-offset:4px;cursor:pointer}
.sb-white .rv-card {border-radius:16px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.12);overflow:hidden}
.sb-white .rv-card__h {width:100%;display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:60px;padding:0 18px;border:0;background:none;color:#FFFFFF;font:700 16px/1 var(--font);letter-spacing:.12em;text-transform:uppercase;cursor:pointer}
.sb-white .rv-card__h svg {width:22px;height:22px;transition:transform 200ms ease}
.sb-white .rv-card__h[aria-expanded="true"] svg {transform:rotate(180deg)}
.sb-white .rv-lyrics {padding:0 18px 20px;font:400 19px/1.65 var(--font);color:var(--onnavy);white-space:pre-line}
.sb-white .rv-keep {display:flex;flex-wrap:wrap;gap:10px}
/* ⚠ `:is(a, button)`, AND THE FOUNDER'S FIRST SALE IS WHY.
 * These three rules said `button`. On the RECIPIENT's gift page two of
 * the three keepsakes are links — `<a href={downloadHref}>` and the
 * lyric sheet's `<a href={pdfHref}>` — so they matched nothing: no pill,
 * no border, no min-height, and NO ICON SIZE. A viewBox-only <svg> with
 * no size falls back to 300x150px, and a flex row squeezes its width but
 * not its height, so the download arrow rendered as a giant bare
 * chevron and dragged "Share" into a tall oval beside it. That is what a
 * paying customer's gift page looked like.
 * Fourth time in this sheet that a rule was written for one element type
 * while the markup used another (see `.qz-smart__acts button`). Style the
 * ROLE, not the tag. */
.sb-white .rv-keep :is(a, button) {display:inline-flex;align-items:center;gap:8px;min-height:50px;padding:0 18px;border:1.5px solid rgba(255,255,255,.35);border-radius:100px;background:none;color:#FFFFFF;font:500 17px/1 var(--font);text-decoration:none;cursor:pointer}
.sb-white .rv-keep :is(a, button) svg {flex:none;width:20px;height:20px}
.sb-white .rv-unlock {display:inline-flex;align-items:center;justify-content:center;gap:10px;min-height:66px;border:0;border-radius:16px;background:var(--blurple);color:#FFFFFF;font:700 20px/1.2 var(--font);box-shadow:0 18px 36px -16px rgba(99,91,255,1);cursor:pointer}
.sb-white .rv-unlock svg {width:22px;height:22px}
.sb-white .rv-redo {align-self:center;min-height:48px;border:0;background:none;color:var(--onnavy2);font:500 17px/1.2 var(--font);text-decoration:underline;text-underline-offset:4px;cursor:pointer}
.sb-white .rv-saved {margin:0;padding:14px 16px;border-radius:14px;background:rgba(255,255,255,.08);font:500 17px/1.45 var(--font);color:#FFFFFF}
.sb-white .sh-scrim {position:fixed;inset:0;z-index:30;display:flex;align-items:flex-end;justify-content:center;background:rgba(6,20,38,.62)}
.sb-white .qz--frame .sh-scrim {position:absolute}
.sb-white .sh {position:relative;width:100%;max-width:600px;max-height:88%;overflow:auto;display:flex;flex-direction:column;gap:14px;padding:26px 22px calc(24px + env(safe-area-inset-bottom,0px));border-radius:24px 24px 0 0;background:var(--page);color:var(--navy);box-shadow:0 -24px 60px -30px rgba(0,0,0,.7);scroll-padding-bottom:calc(160px + env(safe-area-inset-bottom,0px))}
.sb-white .sh--center {align-self:center;border-radius:24px;margin:16px;max-width:520px}

/* ── EVERY SHEET CENTRES ON A BIG SCREEN (founder, launch day) ────────
 * *"even on desktop, the reveal text comes from the bottom... I think
 * that is not how the gift page should be shown."*
 *
 * Right. `.sh-scrim` is `align-items: flex-end` at EVERY width, so on a
 * 1400px monitor the recipient's opening sheet was glued to the bottom
 * edge and stretched the full width — a phone pattern on a desktop, on
 * the one screen the person receiving a gift sees first.
 *
 * `.sh--center` above already described exactly the right thing and WAS
 * USED NOWHERE (INS-137 again: a class in the sheet with no markup
 * behind it). Rather than hand it to three call sites, its declarations
 * become the rule for every sheet above 640px — so a sheet added later
 * cannot get this wrong.
 *
 * 640px is `.sh-stick`'s own breakpoint, deliberately: the sticky pay bar
 * changes its offsets at the same width, so the two cannot disagree.
 * `.sh-stick` is untouched — it sticks to the sheet's scrollport either
 * way. */
@media (min-width: 640px) {
  .sb-white .sh-scrim {
    align-items: center;
  }
  .sb-white .sh {
    border-radius: 24px;
    margin: 16px;
    max-width: 520px;
    /* 88% of the SCRIM was right for a sheet anchored to the bottom.
     * Centred, the margin has to come off both ends or the sheet can
     * sit taller than the space it is centred in. */
    max-height: calc(100% - 32px);
  }
  /* A grab handle is a swipe affordance. There is nothing to swipe on a
   * centred dialog, so it goes — the close button below is the control. */
  .sb-white .sh-grab {
    display: none;
  }
}
.sb-white .sh-grab {width:44px;height:5px;margin:-12px auto 4px;border-radius:5px;background:#CBD5E1}
.sb-white .sh-h {margin:0;font:700 28px/1.15 var(--font);letter-spacing:-0.03em;text-wrap:pretty}
.sb-white .sh-pill {align-self:flex-start;display:inline-flex;align-items:center;gap:8px;padding:6px 14px;border-radius:100px;background:var(--tint);color:var(--blurple-d);font:700 14px/1.2 var(--font);letter-spacing:.1em;text-transform:uppercase}
.sb-white .sh-pill--ok {background:#E6F7F0;color:#0B6B4B}
.sb-white .sh-pill--ok i {width:8px;height:8px;border-radius:50%;background:var(--green)}
.sb-white .sh-rows {display:flex;flex-direction:column}
.sb-white .sh-row {display:grid;grid-template-columns:auto 1fr;gap:12px;padding:12px 0;border-top:1px solid var(--hair);font:400 17px/1.4 var(--font)}
.sb-white .sh-row:first-child {border-top:0}
.sb-white .sh-row b {font:700 14px/1.6 var(--font);letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.sb-white .sh-row span {text-align:right;color:var(--navy)}
.sb-white .ben {display:flex;flex-direction:column;gap:12px;margin:0;padding:0;list-style:none}
.sb-white .ben li {display:grid;grid-template-columns:32px 1fr;gap:12px;align-items:start;font:400 18px/1.45 var(--font);color:var(--ink2)}
.sb-white .ben li b {color:var(--navy)}
.sb-white .ben li i {display:grid;place-items:center;width:32px;height:32px;border-radius:50%;background:#E6F7F0;color:#0B7A55}
.sb-white .ben li i svg {width:18px;height:18px}
.sb-white .price {display:flex;align-items:baseline;justify-content:center;gap:14px;margin:4px 0 0}
.sb-white .price s {font:500 22px/1 var(--font);color:#7A8A9C}
.sb-white .price b {font:700 44px/1 var(--font);letter-spacing:-0.03em;color:var(--navy)}
.sb-white .center {text-align:center}
.sb-white .tp {display:flex;flex-direction:column;gap:10px;padding:16px 18px;border-radius:16px;background:var(--surface);border:1px solid var(--hair)}
.sb-white .tp q {font:500 18px/1.5 var(--font);color:var(--navy);quotes:"“" "”"}
.sb-white .tp small {font:500 15px/1.3 var(--font);color:var(--muted)}
.sb-white .sh-foot {display:flex;align-items:center;justify-content:space-between;gap:12px}
.sb-white .sh-foot button {min-height:48px;padding:0;border:0;background:none;color:var(--blurple-d);font:700 17px/1.2 var(--font);text-decoration:underline;text-underline-offset:4px;cursor:pointer}
.sb-white .sh-foot span {font:500 16px/1.3 var(--font);color:var(--muted)}
.sb-white .sh-x {position:absolute;top:14px;right:14px;display:grid;place-items:center;width:48px;height:48px;border:1.5px solid var(--line);border-radius:50%;background:var(--page);color:var(--navy);cursor:pointer}
.sb-white .sh-x svg {width:20px;height:20px}
.sb-white .sh-back {display:grid;grid-template-columns:48px 1fr 48px;align-items:center;gap:8px}
.sb-white .sh-back button {display:grid;place-items:center;width:48px;height:48px;border:1.5px solid var(--line);border-radius:50%;background:var(--page);color:var(--navy);cursor:pointer}
.sb-white .sh-back button svg {width:22px;height:22px}
.sb-white .sh-back h2 {margin:0;text-align:center;font:700 24px/1.2 var(--font)}
.sb-white .crop {position:relative;width:100%;aspect-ratio:1/1;border-radius:16px;overflow:hidden;background:#000;touch-action:none;cursor:grab}
.sb-white .crop img {position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transform-origin:center;user-select:none;pointer-events:none}
.sb-white .crop::after {content:'';position:absolute;inset:0;border:3px solid rgba(255,255,255,.9);border-radius:16px;pointer-events:none}
.sb-white .crop-zoom {width:100%;accent-color:var(--blurple);height:32px}
.sb-white .sh-2btn {display:grid;grid-template-columns:1fr 1.6fr;gap:10px}
.sb-white .wallet {display:flex;flex-direction:column;gap:10px}
.sb-white .wallet button {min-height:56px;border-radius:12px;font:700 19px/1 var(--font);cursor:pointer}
.sb-white .wallet .w-a {background:#000000;color:#FFFFFF;border:0}
.sb-white .wallet .w-g {background:#FFFFFF;color:#1F1F1F;border:1.5px solid #DADCE0}
.sb-white .or {display:flex;align-items:center;gap:12px;font:500 16px/1 var(--font);color:var(--muted)}
.sb-white .or::before, .sb-white .or::after {content:'';flex:1;height:1px;background:var(--hair)}
.sb-white .cardf {display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.sb-white .cardf label {display:flex;flex-direction:column;gap:6px;font:500 16px/1.2 var(--font);color:var(--ink2)}
.sb-white .cardf label.full {grid-column:1/-1}
.sb-white .cardf input, .sb-white .cardf select {width:100%;min-width:0;min-height:56px;padding:0 14px;border:1.5px solid var(--line);border-radius:10px;background:var(--page);color:var(--navy);font:400 18px/1 var(--font)}
.sb-white .cardf input:focus, .sb-white .cardf select:focus {outline:none;border-color:var(--blurple);box-shadow:var(--ring)}
.sb-white .fine {margin:0;text-align:center;font:500 15px/1.45 var(--font);color:var(--muted)}
.sb-white .stripe-note {margin:0;text-align:center;font:500 13px/1.4 var(--font);color:#7A8A9C}
.sb-white .pp-card {display:flex;flex-direction:column;gap:14px;padding:22px 20px;border-radius:18px;background:var(--page);border:1px solid var(--hair);box-shadow:0 24px 48px -40px rgba(10,37,64,.6)}
.sb-white .pp-lbl {display:flex;align-items:center;justify-content:space-between;gap:10px;font:700 14px/1.2 var(--font);letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.sb-white .pp-lbl button {min-height:44px;padding:0;border:0;background:none;color:var(--blurple-d);font:700 16px/1 var(--font);letter-spacing:0;text-transform:none;text-decoration:underline;text-underline-offset:4px;cursor:pointer}
.sb-white .pp-ro {padding:16px;border-radius:12px;background:var(--surface);border:1px solid var(--hair);font:500 19px/1.3 var(--font);color:var(--navy);overflow-wrap:anywhere}
.sb-white .pp-kick {margin:0;font:500 20px/1.3 var(--font);color:var(--ink2)}
.sb-white .pp-kick em {font-style:normal;font-weight:700;color:var(--blurple-d)}
.sb-white .pp-h {margin:0;font:700 32px/1.12 var(--font);letter-spacing:-0.03em;color:var(--navy);text-wrap:pretty}
.sb-white .pp-h em {font-style:normal;color:var(--blurple)}
.sb-white .pp-save {margin:0;text-align:center;font:700 19px/1.2 var(--font);color:#0B7A55}
.sb-white .pp-rule {height:1px;background:var(--hair)}
.sb-white .pp-sum {display:flex;align-items:center;justify-content:space-between;gap:12px;padding-bottom:14px;border-bottom:1px solid var(--hair)}
.sb-white .pp-sum b {display:block;font:700 18px/1.3 var(--font)}
.sb-white .pp-sum span {font:400 16px/1.3 var(--font);color:var(--muted)}
.sb-white .pp-sum strong {font:700 30px/1 var(--font)}
.sb-white .pp-code {display:flex;flex-direction:column;align-items:center;gap:6px;padding:18px;border:2px dashed #9AA9BA;border-radius:14px;background:var(--surface);cursor:pointer}
.sb-white .pp-code b {font:700 26px/1 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.06em;color:var(--navy)}
.sb-white .pp-code span {font:500 15px/1 var(--font);color:var(--muted)}
.sb-white .pp-song {display:flex;flex-direction:column;gap:12px;padding:20px;border-radius:18px;background:var(--navy);color:#FFFFFF}
.sb-white .pp-song h2 {margin:0;font:700 22px/1.2 var(--font)}
.sb-white .pp-song .pl {background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.12)}
.sb-white .pp-song .pl-times {color:var(--onnavy2)}
.sb-white .pp-song .pl-track {background:rgba(255,255,255,.18)}
.sb-white .pp-song .pl-track i, .sb-white .pp-song .pl-track b {background:var(--cyan)}
.sb-white .pp-song .pl-ctrl button {color:#FFFFFF}
.sb-white .pp-song .pl-ctrl .pl-play {background:#FFFFFF;color:var(--navy)}
.sb-white .pp-song a, .sb-white .pp-song .pp-dl {align-self:flex-start;min-height:44px;display:inline-flex;align-items:center;gap:8px;padding:0;border:0;background:none;color:#FFFFFF;font:700 17px/1.2 var(--font);text-decoration:underline;text-underline-offset:4px;cursor:pointer}
.sb-white .pp-song .pp-dl svg {width:20px;height:20px}
.sb-white .pp-list {display:flex;flex-direction:column;gap:10px;margin:0;padding:0;list-style:none}
.sb-white .pp-list li {display:grid;grid-template-columns:28px 1fr;gap:10px;font:400 18px/1.4 var(--font);color:var(--navy)}
.sb-white .pp-list li i {display:grid;place-items:center;width:28px;height:28px;border-radius:50%;background:#E6F7F0;color:#0B7A55}
.sb-white .pp-list li i svg {width:16px;height:16px}
.sb-white .pp-list li.todo i {background:none;border:2px solid #B9C6D4}
.sb-white .pp-list li.todo {color:var(--ink2)}
.sb-white .pp-close {margin:0;text-align:center;font:400 17px/1.5 var(--font);color:var(--ink2)}
.sb-white .spin {width:44px;height:44px;border-radius:50%;border:4px solid #E6EBF1;border-top-color:var(--blurple);animation:spin 900ms linear infinite;align-self:center}
@keyframes spin {to{transform:rotate(360deg)}}
.sb-white .prop {position:relative;border-radius:16px;outline:2px dashed #B7B2FF;outline-offset:6px}
.sb-white .prop-tag {position:absolute;top:-16px;right:4px;z-index:2;padding:2px 10px;border-radius:100px;background:var(--blurple);color:#FFFFFF;font:700 12px/1.6 var(--font);letter-spacing:.06em;text-transform:uppercase}
.sb-white .fr {display:flex;flex-direction:column;gap:12px}
.sb-white .seg {display:grid;grid-template-columns:1fr 1fr;gap:10px}
.sb-white .songcard {display:grid;grid-template-columns:auto 1fr;gap:16px;align-items:center;padding:16px;border-radius:18px;background:var(--navy);color:#FFFFFF}
.sb-white .songcard .cvwrap {width:92px;border-radius:12px;overflow:hidden}
.sb-white .songcard .cvwrap > img {display:block;width:100%;aspect-ratio:1/1;object-fit:cover}
.sb-white .songcard b {display:block;font:700 13px/1.3 var(--font);letter-spacing:.14em;text-transform:uppercase;color:var(--cyan)}
.sb-white .songcard strong {display:block;margin-top:4px;font:700 24px/1.15 var(--font);letter-spacing:-0.02em}
.sb-white .songcard span {display:block;margin-top:6px;font:500 16px/1.35 var(--font);color:var(--onnavy2)}
.sb-white .prompts {display:flex;flex-wrap:wrap;gap:8px}
.sb-white .prompts button {display:inline-flex;align-items:center;gap:6px;min-height:46px;padding:0 16px;border:1.5px dashed var(--line);border-radius:100px;background:var(--page);color:var(--navy);font:500 16px/1.2 var(--font);cursor:pointer}
.sb-white .prompts button svg {width:16px;height:16px;color:var(--blurple-d)}
.sb-white .trustline {display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:8px;font:500 16px/1.3 var(--font);color:var(--navy)}
@container (min-width:700px) {
.sb-white .fl-main {padding:44px 32px 64px;gap:20px}
.sb-white .fl-h {font-size:38px}
.sb-white .pp-h {font-size:40px}
.sb-white .rv-main {padding:18px 32px 64px}
.sb-white .rv .gp-title {font-size:42px}
.sb-white .sh-scrim {align-items:center}
.sb-white .sh {border-radius:24px;max-width:560px;padding:32px 30px 28px}
.sb-white .sh-grab {display:none}
.sb-white .bd-mini {width:170px}
.sb-white .bd-lead {font-size:34px}
}
.sb-white .qz--navy {background:var(--navy)}
.sb-white .qz--navy .rv {min-height:calc(100dvh - 52px)}
.sb-white .qz--frame.qz--navy .rv {min-height:100%}
.sb-white .qz-grid--dense {grid-auto-flow:row dense}
.sb-white .qz-from {grid-column:1/-1;display:flex;flex-direction:column;gap:12px;margin:6px 0 8px;padding:16px;border-radius:16px;background:var(--tint);outline-offset:4px;animation:bdIn 260ms cubic-bezier(.2,.8,.2,1)}
.sb-white .qz-from .qz-pill {background:var(--page)}
.sb-white .qz-from .qz-pill[aria-pressed="true"] {background:var(--blurple)}
.sb-white .qz-mhead {display:flex;flex-direction:column;gap:8px}
.sb-white .qz-mhead .qz-title {font-size:28px}
.sb-white .qz-mhead .qz-sub {margin:0;font-size:18px;line-height:1.45;color:var(--muted)}
.sb-white .qz-mfield {gap:8px}
.sb-white .qz-mfield .qz-area {min-height:170px}
@container (min-width:700px) {
.sb-white .qz-mhead .qz-title {font-size:38px}
.sb-white .qz-mfield .qz-area {min-height:190px}
}
.sb-white .cv--mini {padding:18%;background:radial-gradient(90% 80% at 30% 20%,rgba(99,91,255,.7),rgba(99,91,255,0) 65%),radial-gradient(80% 60% at 90% 100%,rgba(0,212,255,.35),rgba(0,212,255,0) 60%),#0E2C4B}
.sb-white .cv--mini .cv__wave {width:100%;height:46%;gap:7%}
.sb-white .songcard .cvwrap {width:84px;height:84px}
.sb-white .songcard .cvwrap .cv {height:100%}
.sb-white .qz-from {grid-column:auto;margin:0}
.sb-white .prompts button {text-align:left;padding:10px 16px;line-height:1.3}
.sb-white .qz-track {display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.sb-white .qz-seg {display:flex;flex-direction:column;align-items:flex-start;gap:4px;min-height:66px;padding:10px 12px;border-radius:14px;border:1.5px dashed #C4CFDB;background:var(--page);color:var(--muted);text-align:left;font-family:var(--font)}
.sb-white .qz-seg__k {display:inline-flex;align-items:center;gap:6px;font:700 14px/1.2 var(--font)}
.sb-white .qz-seg__k i {display:grid;place-items:center;width:20px;height:20px;border-radius:50%;background:#E6EBF1;color:var(--muted);font:700 12px/1 var(--font);font-style:normal}
.sb-white .qz-seg__k svg {width:18px;height:18px;color:#0B7A55}
.sb-white .qz-seg__v {font:700 16px/1.2 var(--font);color:var(--navy);overflow-wrap:anywhere;max-width:100%}
.sb-white .qz-seg--now {border:2px solid var(--blurple);background:var(--tint);color:var(--blurple-d)}
.sb-white .qz-seg--now .qz-seg__k i {background:var(--blurple);color:#FFFFFF}
.sb-white .qz-seg--now .qz-seg__v {color:var(--blurple-d);font-weight:500}
.sb-white .qz-seg--done {border:1.5px solid var(--line);cursor:pointer}
.sb-white .qz-seg--done:hover {border-color:var(--navy)}
.sb-white .qz-seg--done::after {content:"Change";font:500 13px/1 var(--font);color:var(--blurple-d);text-decoration:underline;text-underline-offset:3px}
.sb-white .qz-seg:disabled {cursor:default}
/* ── A LONG NAME MUST WRAP, NOT PUSH THE PAGE SIDEWAYS ───────────────
 * Founder, with an Android photo of step 6 of 7: *"this is on the story
 * page in the form. its going out of the window."* The heading read
 * "Tell us about Honey Baby Husband" and ran off the right edge, taking
 * the textarea and the Continue button with it — the whole page was
 * wider than the phone.
 *
 * `.qz-one` exists to keep this ONE heading on a single line, because
 * "Tell us about / Mom" breaking after three words read as a bug. The
 * `nowrap` that enforced it cannot survive a name the buyer chose:
 * `who` is `e.draft.callName`, typed by them, and "Honey Baby Husband"
 * is a real order. An unwrappable heading is not a heading that is too
 * big — it is a page with horizontal scroll, which on a phone means the
 * Continue button is off-screen.
 *
 * So the size stays and the `nowrap` goes. `.qz-title` already carries
 * `text-wrap: pretty`, so a short name still sits on one line (it fits)
 * and a long one wraps into a balanced two — which is what the rule
 * wanted in the first place. Nothing else uses `.qz-one`; measured, one
 * consumer, WhiteScreen.tsx's memory screen. */
.sb-white .qz-mhead .qz-title.qz-one {font-size:clamp(20px,6.1vw,28px)}
@container (min-width:700px) {
.sb-white .qz-mhead .qz-title.qz-one {font-size:38px}
}
.sb-white .up-tag {align-self:flex-start;margin:0 0 -4px;padding:4px 12px;border-radius:100px;border:1.5px dashed #B7B2FF;color:var(--blurple-d);font:700 13px/1.4 var(--font)}
.sb-white .up-pair {display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.sb-white .up-song {min-width:0;display:flex;flex-direction:column;gap:6px;padding:12px;border-radius:16px;background:var(--navy);color:#FFFFFF}
.sb-white .up-song b {font:700 18px/1.2 var(--font)}
.sb-white .up-song span {font:500 15px/1.35 var(--font);color:var(--onnavy2)}
.sb-white .up-art {aspect-ratio:1/1;border-radius:12px;overflow:hidden}
.sb-white .up-art img {display:block;width:100%;height:100%;object-fit:cover}
.sb-white .up-art .cv {height:100%}
.sb-white .up-done {display:inline-flex;align-items:center;gap:6px;color:#7BE0B8!important;font-weight:700!important}
.sb-white .up-done svg {width:16px;height:16px}
.sb-white .up-song--next {background:var(--page);color:var(--navy);border:2px dashed #9AA9BA}
.sb-white .up-song--next span {color:var(--ink2)}
.sb-white .up-art--next {display:grid;place-items:center;background:var(--tint);color:var(--blurple)}
.sb-white .up-art--next svg {width:44px;height:44px}
.sb-white .up-yes {white-space:nowrap;padding-inline:14px;font-size:clamp(13px,calc(5.9cqw - 6px),20px)}
@container (max-width:699.98px) {
.sb-white .up-card {padding-inline:14px}
}
.sb-white {--lav:#F6F5FF;--lav2:#EEEDFF;--lavline:#E2E0FF;--okbg:#E8F7F0;--okfg:#0B6B4B;--okline:#C9EBDB}
.sb-white .prop {outline:none}
.sb-white .prop-tag {display:none}
.sb-white .cv {color:var(--navy);background:radial-gradient(90% 70% at 50% 10%,#E2DFFF 0%,rgba(226,223,255,0) 70%),radial-gradient(70% 55% at 92% 100%,#DDF2FF 0%,rgba(221,242,255,0) 70%),linear-gradient(180deg,#FBFBFF,#F1F0FF)}
.sb-white .cv__k {color:var(--blurple-d)}
.sb-white .cv__rule {background:rgba(10,37,64,.16)}
.sb-white .cv__wave i {background:var(--blurple);opacity:.8}
.sb-white .cv .cv__logo {filter:none;opacity:.85}
.sb-white .cv--mini {background:radial-gradient(90% 80% at 30% 18%,#E2DFFF,rgba(226,223,255,0) 70%),linear-gradient(180deg,#FBFBFF,#EEEDFF)}
.sb-white .qz-mhead .qz-title.qz-one {font-size:clamp(20px,6.1cqw,28px)}
.sb-white .qz-eg {margin:-4px 0 0;padding:14px 16px;border-radius:16px;background:var(--lav)}
.sb-white .qz-eg figcaption {margin:0 0 4px;font:500 15px/1.3 var(--font);color:var(--muted)}
.sb-white .qz-eg p {margin:0;font:400 17.5px/1.5 var(--font);color:var(--ink2);text-wrap:pretty}
.sb-white .qz-mfield .qz-area {min-height:150px}
.sb-white .qz-reassure {margin:-8px 0 0;font:400 16px/1.45 var(--font);color:var(--muted);text-wrap:pretty}
.sb-white .wt2 {flex:1;width:100%;max-width:640px;margin:0 auto;padding:18px 20px 48px;display:flex;flex-direction:column;gap:24px}
.sb-white .wt2-l, .sb-white .wt2-r {display:flex;flex-direction:column;gap:12px;min-width:0}
.sb-white .ws {display:flex;flex-direction:column;gap:14px;padding:22px 20px 20px;border-radius:24px;background:linear-gradient(180deg,var(--lav) 0%,#FFFFFF 92%);border:1px solid var(--lavline);box-shadow:0 26px 50px -42px rgba(74,64,209,.6)}
.sb-white .ws-head {display:flex;align-items:center;gap:14px}
.sb-white .ws-orb {position:relative;flex:none;display:flex;align-items:center;justify-content:center;gap:3px;width:60px;height:60px;border-radius:50%;background:#FFFFFF;border:1px solid var(--lavline);box-shadow:0 10px 22px -12px rgba(99,91,255,.65)}
.sb-white .ws-orb::before {content:"";position:absolute;inset:-7px;border-radius:50%;border:2px solid rgba(99,91,255,.28);animation:wsRing 2.4s ease-out infinite}
.sb-white .ws-orb i {width:4px;height:22px;border-radius:3px;background:var(--blurple);animation:wsEq 1.1s ease-in-out infinite}
.sb-white .ws-orb i:nth-child(2) {height:30px;animation-delay:-.3s}
.sb-white .ws-orb i:nth-child(3) {height:18px;animation-delay:-.6s}
.sb-white .ws-orb i:nth-child(4) {height:26px;animation-delay:-.85s}
.sb-white .ws-orb i:nth-child(5) {height:14px;animation-delay:-.45s}
@keyframes wsEq {0%,100%{transform:scaleY(.4)}50%{transform:scaleY(1)}}
@keyframes wsRing {0%{transform:scale(.92);opacity:.9}100%{transform:scale(1.22);opacity:0}}
.sb-white .ws-orb--ok {background:var(--green);border-color:var(--green);color:#FFFFFF;box-shadow:0 10px 22px -12px rgba(0,182,122,.8)}
.sb-white .ws-orb--ok::before {display:none}
.sb-white .ws-orb svg {width:30px;height:30px}
.sb-white .ws-h {margin:0;font:700 26px/1.15 var(--font);letter-spacing:-0.025em;color:var(--navy);text-wrap:balance}
.sb-white .ws-sub {margin:0;font:500 18px/1.45 var(--font);color:var(--ink2);text-wrap:pretty}
.sb-white .ws-steps {list-style:none;margin:2px 0 0;padding:0;display:flex;flex-direction:column;gap:12px}
.sb-white .ws-steps li {display:grid;grid-template-columns:30px minmax(0,1fr);gap:12px;align-items:center;font:500 18px/1.3 var(--font);color:var(--muted)}
.sb-white .ws-steps li i {display:grid;place-items:center;width:30px;height:30px;border-radius:50%;border:2px solid #CBD5E1;background:#FFFFFF;color:#FFFFFF}
.sb-white .ws-steps li i svg {width:16px;height:16px}
.sb-white .ws-steps li.done {color:var(--ink2)}
.sb-white .ws-steps li.done i {background:var(--green);border-color:var(--green)}
.sb-white .ws-steps li.on {color:var(--navy);font-weight:700}
.sb-white .ws-steps li.on i {border-color:var(--blurple)}
.sb-white .ws-steps li.on i::after {content:"";width:10px;height:10px;border-radius:50%;background:var(--blurple);animation:wtPulse 1.6s ease-in-out infinite}
.sb-white .ws-steps small {display:block;margin-top:2px;font:500 15px/1.3 var(--font);color:var(--blurple-d)}
.sb-white .ws-meter {display:flex;align-items:center;gap:12px;margin-top:2px}
.sb-white .ws-bar {flex:1;height:10px;border-radius:10px;background:#E6E4FF;overflow:hidden}
.sb-white .ws-bar i {display:block;height:100%;border-radius:10px;background:linear-gradient(90deg,var(--blurple),#8C85FF);transition:width 300ms linear}
.sb-white .ws-pct {flex:none;min-width:3em;text-align:right;font:700 17px/1 var(--font);color:var(--blurple-d);font-variant-numeric:tabular-nums}
.sb-white .ws--ready {background:linear-gradient(180deg,#EDF9F3 0%,#FFFFFF 92%);border-color:var(--okline)}
.sb-white .ws .qz-btn svg {width:22px;height:22px}
.sb-white .ws--compact {flex-direction:row;align-items:center;gap:14px;padding:12px 14px;border-radius:18px}
.sb-white .ws--compact .ws-orb {width:44px;height:44px;gap:2px}
.sb-white .ws--compact .ws-orb::before {inset:-5px}
.sb-white .ws--compact .ws-orb i {width:3px;height:16px}
.sb-white .ws--compact .ws-orb i:nth-child(2) {height:22px}
.sb-white .ws--compact .ws-orb i:nth-child(3) {height:13px}
.sb-white .ws--compact .ws-orb i:nth-child(4) {height:19px}
.sb-white .ws--compact .ws-orb i:nth-child(5) {height:10px}
.sb-white .ws--compact .ws-orb svg {width:22px;height:22px}
.sb-white .ws-c {flex:1;min-width:0;display:flex;flex-direction:column;gap:8px}
.sb-white .ws-now {margin:0;font:700 17px/1.25 var(--font);color:var(--navy)}
.sb-white .ws-go {flex:none;display:inline-flex;align-items:center;gap:6px;min-height:48px;padding:0 18px;border:0;border-radius:100px;background:var(--blurple);color:#FFFFFF;font:700 17px/1 var(--font);cursor:pointer}
.sb-white .ws-go svg {width:20px;height:20px}
.sb-white .wt2.is-editing .ws:not(.ws--compact) {display:none}
.sb-white .gs {display:flex;flex-direction:column;gap:10px}
.sb-white .gs-eye {margin:0;font:700 16px/1.2 var(--font);color:var(--blurple-d)}
.sb-white .gs-h {margin:0;font:700 26px/1.15 var(--font);letter-spacing:-0.025em;color:var(--navy);text-wrap:pretty}
.sb-white .gs-sub {margin:0 0 6px;font:400 18px/1.5 var(--font);color:var(--ink2);text-wrap:pretty}
.sb-white .gs-card {display:flex;flex-direction:column;border-radius:22px;background:#FFFFFF;border:1px solid var(--hair);box-shadow:0 26px 50px -42px rgba(10,37,64,.55);overflow:hidden}
.sb-white .mp {display:flex;flex-direction:column;gap:12px;padding:16px;background:linear-gradient(180deg,#FBFBFF,var(--lav));border-bottom:1px solid var(--hair)}
.sb-white .mp-top {display:grid;grid-template-columns:96px minmax(0,1fr);gap:14px;align-items:center}
.sb-white .mp-pic {width:96px;aspect-ratio:1/1;border-radius:14px;overflow:hidden;background:#FFFFFF;box-shadow:0 12px 24px -16px rgba(10,37,64,.6)}
.sb-white .mp-pic > img {display:block;width:100%;height:100%;object-fit:cover}
.sb-white .mp-txt {min-width:0;display:flex;flex-direction:column;gap:3px}
.sb-white .mp-k {margin:0;font:700 13px/1.3 var(--font);letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.sb-white .mp-t {margin:0;font:700 20px/1.2 var(--font);letter-spacing:-0.02em;color:var(--navy);text-wrap:balance}
.sb-white .mp-for {margin:0;font:500 16px/1.3 var(--font);color:var(--ink2)}
.sb-white .mp-for b {color:#E0457B}
.sb-white .mp-play {display:inline-flex;align-items:center;gap:6px;margin:4px 0 0;font:500 15px/1.2 var(--font);color:var(--muted)}
.sb-white .mp-play svg {width:16px;height:16px;color:var(--blurple)}
.sb-white .mp-msg {padding:12px 14px;border-radius:14px;background:#FFFFFF;border:1px solid var(--hair)}
.sb-white .mp-note {margin:0;font:400 16px/1.5 var(--font);color:var(--navy);white-space:pre-line;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.sb-white .mp-sign {margin:8px 0 0;font:700 13px/1.2 var(--font);letter-spacing:.1em;text-transform:uppercase;color:var(--blurple-d)}
.sb-white .gs-rows {list-style:none;margin:0;padding:4px 0}
.sb-white .gs-rows li + li {border-top:1px solid var(--hair)}
.sb-white .gs-row {width:100%;display:grid;grid-template-columns:44px minmax(0,1fr) auto;gap:14px;align-items:center;min-height:80px;padding:12px 16px;border:0;background:none;text-align:left;color:var(--navy);cursor:pointer}
.sb-white .gs-row:hover {background:#FAFAFF}
.sb-white .gs-row:focus-visible {outline:3px solid rgba(99,91,255,.45);outline-offset:-3px}
.sb-white .gs-ic {display:grid;place-items:center;width:44px;height:44px;border-radius:50%;background:var(--tint);color:var(--blurple-d)}
.sb-white .gs-ic svg {width:22px;height:22px}
.sb-white .gs-row.is-done .gs-ic {background:var(--green);color:#FFFFFF}
.sb-white .gs-tx {display:flex;flex-direction:column;gap:3px;min-width:0}
.sb-white .gs-tx b {font:700 18px/1.25 var(--font);color:var(--navy);overflow-wrap:anywhere}
.sb-white .gs-tx small {font:400 15.5px/1.4 var(--font);color:var(--muted)}
.sb-white .gs-row.is-done .gs-tx small {white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sb-white .gs-add {display:inline-flex;align-items:center;justify-content:center;min-height:44px;min-width:72px;padding:0 18px;border-radius:100px;border:1.5px solid var(--line);background:#FFFFFF;color:var(--navy);font:700 16px/1 var(--font)}
.sb-white .gs-chg {font:700 16px/1 var(--font);color:var(--blurple-d);text-decoration:underline;text-underline-offset:4px}
/* P1-636 put "Remove" in a column under "Change"; P1-640 moved it onto the
   thumbnail as a ×, so the trailing column holds one "Change" again — the
   same shape as the note row. The done row is still a <div> (it holds
   more than one button), so the whole-row hover is still killed here. */
.sb-white div.gs-row:hover {background:none}
/* 10px, not the row's 14px. Measured at 320px: "Photo added" wants 113px
   and the text column had 110px, so it wrapped to two lines and the row
   grew to 98px. It was ALREADY inside a pixel of wrapping before this
   ticket (114px available, 113px needed) — the stacked column only
   tipped it over. Two gaps at 10px hand the label 122px, which is 9px of
   headroom instead of 1px of luck. */
.sb-white div.gs-row {column-gap:10px}
.sb-white .gs-thumb--btn {padding:0;border:0;cursor:pointer}
.sb-white .gs-thumb--btn:focus-visible {outline:3px solid rgba(99,91,255,.45);outline-offset:2px}
.sb-white .gs-thumb--btn:disabled {cursor:default}
.sb-white .gs-okline {display:flex;align-items:flex-start;gap:10px;margin:4px 0 0;padding:14px 16px;border-radius:16px;background:var(--okbg);border:1px solid var(--okline);color:var(--okfg);font:500 17px/1.45 var(--font)}
.sb-white .gs-okline svg {flex:none;width:22px;height:22px;margin-top:1px}
.sb-white .gs .fl-textlink {margin-top:4px}
.sb-white .ge-top {display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:-4px}
.sb-white .ge-back {display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0 6px 0 0;border:0;background:none;color:var(--blurple-d);font:700 17px/1.2 var(--font);cursor:pointer}
.sb-white .ge-back svg {width:20px;height:20px}
.sb-white .ge-n {flex:none;font:700 15px/1 var(--font);color:var(--muted)}
.sb-white .bd-drop {position:relative}
.sb-white .bd-drop button {width:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;aspect-ratio:4/3;padding:16px;border:2px dashed #B7B2FF;border-radius:22px;background:var(--lav);color:var(--navy);cursor:pointer}
.sb-white .bd-drop button:hover {background:var(--lav2)}
.sb-white .bd-drop__i {display:grid;place-items:center;width:76px;height:76px;margin-bottom:4px;border-radius:50%;background:#FFFFFF;color:var(--blurple);box-shadow:0 12px 26px -14px rgba(99,91,255,.75)}
.sb-white .bd-drop__i svg {width:34px;height:34px}
.sb-white .bd-drop b {font:700 21px/1.2 var(--font)}
.sb-white .bd-drop small {font:400 16px/1.3 var(--font);color:var(--muted)}
.sb-white .sh--ready {align-items:center;text-align:center}
.sb-white .sh--ready .sh-pill {align-self:center}
.sb-white .sh--ready .fl-p {max-width:26em}
.sb-white .sh--ready .qz-btn {align-self:stretch}
.sb-white .sh--ready .qz-btn svg {width:22px;height:22px}
.sb-white .rd-pic {position:relative;width:112px;margin:2px auto 0}
.sb-white .rd-pic > img, .sb-white .rd-pic .cvwrap {display:block;width:112px;border-radius:18px;overflow:hidden;box-shadow:0 16px 32px -18px rgba(10,37,64,.6)}
.sb-white .rd-pic > img {aspect-ratio:1/1;object-fit:cover}
.sb-white .rd-ok {position:absolute;right:-10px;bottom:-10px;display:grid;place-items:center;width:42px;height:42px;border-radius:50%;background:var(--green);color:#FFFFFF;border:3px solid #FFFFFF}
.sb-white .rd-ok svg {width:20px;height:20px}
.sb-white .qz--navy {background:var(--page)}
.sb-white .rv {background:linear-gradient(180deg,var(--lav) 0,#FFFFFF 440px);color:var(--navy)}
/* ── AND THE STRIP ABOVE IT (founder: "what is there a white space at
 * the very top?") ──────────────────────────────────────────────────
 *
 * `.rv-strip` carries `margin: 14px auto 0`, and `.rv` has no padding,
 * no border and is not a block-formatting context — so that top margin
 * COLLAPSES THROUGH `.rv`'s top edge, pushing the whole gradient down
 * 14px and exposing what is behind it. On `/preview` that is
 * `funnel-scope`, whose background is the old look's cream, which is why
 * the founder read it as a cream strip rather than a white one.
 *
 * `display: flow-root` is block layout that establishes a BFC, so the
 * child's margin is contained instead of escaping. One declaration, no
 * layout change, and it does not depend on any descendant's margins
 * staying what they are today. */
.sb-white .rv {display:flow-root}
.sb-white .rv-strip {width:calc(100% - 40px);max-width:560px;margin:14px auto 0;padding:8px 8px 8px 16px;border-radius:16px;background:#FFFFFF;border:1px solid var(--lavline)}
.sb-white .rv-strip span {color:var(--muted)}
.sb-white .rv-strip button {min-height:44px;padding:0 14px;border:1.5px solid var(--lavline);border-radius:100px;background:var(--lav);color:var(--blurple-d);text-decoration:none}
.sb-white .rv-photo {box-shadow:0 30px 60px -36px rgba(10,37,64,.55)}
.sb-white .rv .gp-title {color:var(--navy)}
.sb-white .rv .gp-for {color:var(--ink2)}
.sb-white .rv .gp-for b {color:#E0457B}
.sb-white .rv .gp-note {background:#FFFFFF;border-color:var(--hair);box-shadow:0 20px 40px -32px rgba(10,37,64,.5)}
.sb-white .rv .gp-note p {color:var(--navy)}
.sb-white .rv .gp-note .gp-sign {color:var(--blurple-d)}
.sb-white .rv-more {color:var(--blurple-d)}

/* ── THE GIFT PAGE'S ONE WAY BACK TO US ───────────────────────────────
 * Founder: *"Make one for someone you love at the bottom of the gift
 * page. Please make it aesthetic and make it suit the rest of the
 * website."*
 *
 * It was `.fl-textlink` — muted grey, underlined — which in this look is
 * the style for "no thanks" and "never mind". The gift page is the ONLY
 * page a non-customer ever sees, so that link is the whole referral
 * surface, and it was dressed as a decline.
 *
 * This is the look's secondary button, which already exists as a shape
 * on the lyrics page (`.lyp-ghost`) — same 50px pill,
 * same lavender hairline, same navy ink on white. Its OWN class rather
 * than borrowing one of those: borrowing a class is borrowing every
 * assumption behind it, which is how three screens broke earlier in this
 * ticket.
 *
 * Space, not a rule, sets it apart — see the note further down.      */
.sb-white .rv-make {
  /* FULL WIDTH, and measured, not chosen. `align-self: center` with
   * `inline-flex` starved the label: at 320/360/390/430 the pill came out
   * 232-332px wide and the words wrapped to THREE lines, overflowing a
   * 50px pill — visibly worse than the grey link it replaced. Stretching
   * it gives the label the whole column, which is also what this look
   * does for every other button of consequence (`fl-wide`). */
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* BUILT FOR TWO LINES, because MEASURED it needs them. The label wants
   * 260px on one line. A full-width pill gives it 262px at 390px once
   * the arrow is gone (228px with it — which is why the arrow went), and
   * 232px at 320px. So it fits on one line from 390px and needs two
   * below, and a FIXED height made it overflow — text spilling out of
   * the pill, visibly worse than the grey link this replaced.
   * Vertical padding instead of a fixed height, so the pill grows to fit
   * whatever it holds; `text-wrap: balance` so two lines come out even
   * rather than one long and one short. Nothing overflows at any width. */
  min-height: 54px;
  margin: 10px 0 2px;
  padding: 13px 20px;
  line-height: 1.35;
  text-align: center;
  text-wrap: balance;
  border: 1.5px solid var(--lavline);
  border-radius: 100px;
  background: #FFFFFF;
  color: var(--navy);
  font: 700 17px/1.35 var(--font);
  text-decoration: none;
  cursor: pointer;
}
.sb-white .rv-make svg {
  flex: none;
  width: 18px;
  height: 18px;
  color: var(--blurple-d);
}
.sb-white .rv-make:hover,
.sb-white .rv-make:focus-visible {
  border-color: var(--blurple);
  background: var(--lav);
}
/* Room, not a rule. I wrote a comment here claiming a hairline above the
 * button and then three declarations that drew nothing — dead CSS, in the
 * same breath as citing INS-137 about dead CSS. Space does the job on a
 * page that is already a column of cards: 26px of it, so the invitation
 * sits apart from the keepsakes above rather than reading as a fourth
 * one. */
.sb-white .rv-lyrics + .rv-make {
  margin-top: 26px;
}
.sb-white .rv-card {background:#FFFFFF;border-color:var(--hair)}
.sb-white .rv-card__h {color:var(--navy)}
.sb-white .rv-lyrics {color:var(--ink2)}
.sb-white .rv-keep :is(a, button) {border-color:var(--line);background:#FFFFFF;color:var(--navy)}
.sb-white .rv-redo {color:var(--muted)}
.sb-white .rv-saved {background:var(--okbg);color:var(--okfg)}
.sb-white .pl2 {display:flex;flex-direction:column;gap:14px;padding:16px;border-radius:20px;background:#FFFFFF;border:1px solid var(--lavline);box-shadow:0 20px 40px -34px rgba(74,64,209,.7)}
.sb-white .pl2-btn {display:flex;align-items:center;justify-content:center;gap:12px;width:100%;min-height:66px;padding:0 20px;border:0;border-radius:16px;background:var(--navy);color:#FFFFFF;font:700 21px/1.2 var(--font);cursor:pointer;box-shadow:0 16px 30px -18px rgba(10,37,64,.9)}
.sb-white .pl2-btn:hover {background:#12355A}
.sb-white .pl2-btn svg {flex:none;width:26px;height:26px}
.sb-white .pl2-btn.is-on {background:var(--lav);color:var(--navy);border:2px solid var(--lavline);box-shadow:none}
.sb-white .pl2 .pl-times {color:var(--muted)}
.sb-white .pl2 .pl-track {background:#DDDAFF}
.sb-white .ab {border:1px solid var(--hair);border-radius:16px;background:#FFFFFF}
.sb-white .ab-q {display:flex;align-items:center;justify-content:space-between;gap:12px;min-height:60px;padding:0 18px;color:var(--navy);font:700 18px/1.3 var(--font);cursor:pointer;list-style:none}
.sb-white .ab-q::-webkit-details-marker {display:none}
.sb-white .ab-q:focus-visible {outline:none;box-shadow:var(--ring);border-radius:16px}
.sb-white .ab-q span::before {content:"+";font:500 28px/1 var(--font);color:var(--blurple)}
.sb-white .ab[open] .ab-q span::before {content:"−"}
.sb-white .ab-a {display:flex;flex-direction:column;gap:12px;padding:0 18px 18px}
.sb-white .ab-a ol {list-style:none;counter-reset:ab;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.sb-white .ab-a li {counter-increment:ab;display:grid;grid-template-columns:30px minmax(0,1fr);gap:12px;align-items:start;font:400 17px/1.45 var(--font);color:var(--ink2)}
.sb-white .ab-a li::before {content:counter(ab);display:grid;place-items:center;width:30px;height:30px;border-radius:50%;background:var(--tint);color:var(--blurple-d);font:700 15px/1 var(--font)}
.sb-white .ab-a p {margin:0;padding-top:12px;border-top:1px solid var(--hair);font:500 16px/1.45 var(--font);color:var(--muted)}
/* THE PAGE BEHIND A SHEET IS GLASS, NOT A WINDOW.
 * Founder: "when we click Unlock, the new page opens, and behind that, at
 * the top, the old page is visible as well. I think the old page maybe
 * should be slightly blurred, like the glass morphism effect."
 * ─────────────────────────────────────────────────────────────────────
 * The sheet is 88% tall, so a ~100px strip of the page it came from is
 * always showing — and that strip is the loudest thing on the screen: a
 * dark stage with a song cover on it, legible enough to still read as a
 * page you could tap. A tint alone cannot fix that; blur can, because it
 * destroys the DETAIL that makes it read as a live page while keeping
 * the colour that says where you are.
 * 10px is the value that stops the cover art resolving at arm's length
 * without turning the strip to mud. The tint drops to .30 because blur
 * and tint compound — at .34 the two together read as a black bar.
 * `-webkit-` first: iOS 15 still needs it, and iOS is most of our
 * traffic. Where `backdrop-filter` is unsupported the @supports block
 * below puts the tint back up, so those browsers keep today's clean
 * separation rather than getting a paler one. */
.sb-white .sh-scrim, .sb-white .qz-modal {
  background: rgba(10, 37, 64, .30);
  -webkit-backdrop-filter: blur(10px) saturate(115%);
  backdrop-filter: blur(10px) saturate(115%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .sb-white .sh-scrim, .sb-white .qz-modal {background: rgba(10, 37, 64, .46)}
}
.sb-white .rd-pic > .cv {display:block;width:112px;border-radius:18px;overflow:hidden;box-shadow:0 16px 32px -18px rgba(10,37,64,.6)}
.sb-white .pp-song {background:var(--lav);color:var(--navy);border:1px solid var(--lavline)}
.sb-white .pp-song h2 {color:var(--navy)}
.sb-white .pp-song a, .sb-white .pp-song .pp-dl {color:var(--blurple-d)}
.sb-white .pp-song .pl-track {background:#DDDAFF}
.sb-white .pp-song .pl-track i, .sb-white .pp-song .pl-track b {background:var(--blurple)}
.sb-white .pp-song .pl-times {color:var(--muted)}
@container (min-width:700px) {
.sb-white .wt2 .qz-btn {min-width:0}
.sb-white .ws-h {font-size:30px}
.sb-white .gs-h {font-size:32px}
.sb-white .mp {padding:20px}
.sb-white .mp-top {grid-template-columns:140px minmax(0,1fr);gap:20px}
.sb-white .mp-pic {width:140px}
.sb-white .mp-t {font-size:24px}
}
@container (min-width:900px) {
.sb-white .wt2 {max-width:1080px;display:grid;grid-template-columns:minmax(0,410px) minmax(0,1fr);gap:40px;align-items:start;padding:40px 32px 64px}
.sb-white .wt2-l {position:sticky;top:84px}
.sb-white .wt2.is-editing .ws:not(.ws--compact) {display:flex}
.sb-white .wt2 .ws--compact {display:none}
.sb-white .wt2--solo {grid-template-columns:minmax(0,640px);justify-content:center}
.sb-white .fl-top--wide .fl-top__in {max-width:1080px;padding-left:32px;padding-right:32px}
.sb-white .ws {padding:28px 26px 26px}
}
.sb-white .rv .pl-track {background:#DDDAFF}
.sb-white .rv .pl-track i, .sb-white .rv .pl-track b {background:var(--blurple)}
.sb-white .rv .pl-times {color:var(--muted)}
.sb-white .qz-btn:not(.up-yes) {white-space:nowrap;padding-inline:clamp(14px,4.6cqw,28px);font-size:clamp(17px,5.3cqw,20px)}
/* ── A BUTTON CARRYING A NAME MUST WRAP TOO ──────────────────────────
 * Founder, second Android photo: the resume screen's button read
 * "ten to Honey Baby Husband's song" — CUT OFF AT BOTH ENDS.
 *
 * `.qz-btn` is `nowrap` above so "Continue" never breaks mid-row, and
 * this rule already undid it for the footer and the sheet. `.qz-main`
 * was the gap: `WhiteResume`'s button lives there, and it is the ONE
 * button in the whole White look whose label interpolates a name —
 * checked across every `.qz-btn` in `app/_white/`, not assumed.
 * `Listen to ${who}'s song`, where `who` is `offer.recipientName`.
 *
 * With `nowrap` the text item's min-content IS its full width, so it
 * cannot shrink and the flex row overflows in both directions —
 * `justify-content: center` is why it lost the start as well as the end.
 * Short labels are unaffected: they fit, so they do not wrap. */
.sb-white .qz-foot .qz-btn, .sb-white .qz-sheet .qz-btn, .sb-white .qz-main .qz-btn {white-space:normal;text-wrap:balance}
.sb-white .pl2-btn {white-space:nowrap;padding-inline:clamp(14px,4.2cqw,20px);font-size:clamp(17px,5.4cqw,21px)}
.sb-white .qz-sheet {align-items:stretch;text-align:center;gap:16px;padding-top:34px}
.sb-white .qz-sheet h2 {margin:4px 44px 0}
.sb-white .qz-sheet .qz-sub {text-align:center}
.sb-white .qz-sheet .qz-input {text-align:left}
.sb-white .qz-sheet [data-slot="gatebtn"] .qz-btn {width:100%}
.sb-white .qz-sheet [data-slot="gateerr"]:empty {display:none}
.sb-white .qz-sheet .qz-err {text-align:left}
.sb-white .qz-sheet .qz-fine {margin-top:-4px}
.sb-white .qz-sheet .prop {margin-top:-4px}
.sb-white .qz-x {top:12px;right:12px;width:44px;height:44px;border:0;background:var(--surface);color:var(--ink2)}
.sb-white .qz-x:hover {background:var(--hair);color:var(--navy)}
@container (min-width:700px) {
.sb-white .qz-sheet {max-width:520px}
}
.sb-white .rv-side {display:flex;flex-direction:column;gap:18px;min-width:0}
.sb-white .gh {position:relative;display:flex;min-height:0;aspect-ratio:3/4;border-radius:28px;overflow:hidden;background:var(--navy);color:#FFFFFF;box-shadow:0 44px 80px -44px rgba(10,37,64,.75)}
.sb-white .gh-photo {position:absolute;inset:0;display:block;width:100%;height:100%;object-fit:cover}
.sb-white .gh-scrim {position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(10,37,64,.42) 0%,rgba(10,37,64,0) 26%,rgba(10,37,64,.1) 46%,rgba(10,37,64,.95) 100%)}
.sb-white .gh-in {position:relative;flex:1;min-width:0;display:flex;flex-direction:column;justify-content:space-between;gap:24px}
.sb-white .gh-kicker {margin:0;padding:22px 20px 0;text-align:center;font:700 13px/1.35 var(--font);letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.94)}
.sb-white .gh-bottom {display:flex;flex-direction:column;gap:6px;padding:0 clamp(14px,4.6cqw,22px) 22px}
.sb-white .gh-title {margin:0;font:700 clamp(28px,8.4cqw,36px)/1.05 var(--font);letter-spacing:-0.035em;color:#FFFFFF;text-wrap:balance}
.sb-white .gh-meta {margin:0 0 12px;font:500 17px/1.3 var(--font);color:rgba(255,255,255,.88)}
.sb-white .gh-meta b {color:#FF9DBF}
.sb-white .gh .pl2 {padding:0;background:none;border:0;box-shadow:none;gap:12px}
.sb-white .gh .pl2-btn {background:#FFFFFF;color:var(--navy);box-shadow:0 16px 30px -16px rgba(0,0,0,.7)}
.sb-white .gh .pl2-btn:hover {background:#F1F0FF}
.sb-white .gh .pl2-btn.is-on {background:rgba(255,255,255,.16);color:#FFFFFF;border:1.5px solid rgba(255,255,255,.55);box-shadow:none}
.sb-white .gh .pl-times {color:rgba(255,255,255,.78)}
.sb-white .gh .pl-track {height:4px;background:rgba(255,255,255,.3)}
.sb-white .gh .pl-track i, .sb-white .gh .pl-track b {background:#FFFFFF}
.sb-white .gh--plain {color:var(--navy);border:1px solid var(--lavline);box-shadow:0 34px 64px -44px rgba(74,64,209,.7);background:radial-gradient(90% 60% at 50% 12%,#E2DFFF 0%,rgba(226,223,255,0) 70%),radial-gradient(70% 50% at 92% 100%,#DDF2FF 0%,rgba(221,242,255,0) 70%),linear-gradient(180deg,#FBFBFF,#EEEDFF)}
.sb-white .gh--plain .gh-kicker {color:var(--blurple-d)}
.sb-white .gh-wave {flex:1;align-self:center;display:flex;align-items:center;gap:3.2%;width:58%;max-height:34%;min-height:60px}
.sb-white .gh-wave i {flex:1;border-radius:4px;background:var(--blurple);opacity:.75}
.sb-white .gh--plain .gh-title {color:var(--navy)}
.sb-white .gh--plain .gh-meta {color:var(--ink2)}
.sb-white .gh--plain .gh-meta b {color:#E0457B}
.sb-white .gh--plain .pl2-btn {background:var(--navy);color:#FFFFFF}
.sb-white .gh--plain .pl2-btn:hover {background:#12355A}
/* PLAYING has to look different from PAUSED, and option C nearly cost
 * that. The old pair flipped navy -> white, which was unmistakable. With
 * the idle button now white too, a white "playing" state left the two
 * almost identical — measured: white/blurple-border against
 * white/lavender-border. So the engaged state takes the lavender FILL
 * and keeps the blurple ring: same shape, plainly pressed. */
.sb-white .gh--plain .pl2-btn.is-on {
  background: #FFFFFF;
  color: var(--navy);
  border: 2px solid var(--lavline);
  box-shadow: none;
}
.sb-white .gh--plain .pl2-btn.is-on svg {
  color: var(--navy);
}
/* ── THE PLAY BUTTON STOPS OUT-SHOUTING THE NAME (founder, option C) ──
 * *"can we do something about that Play free preview button. i think its
 * too big and contrasting."*
 *
 * It was a solid navy block, 66px tall at 21px — measured 14% of the
 * card's height and, on a near-white card, the highest-contrast thing on
 * it. Louder than the recipient's own name, which is the one thing that
 * card exists to show.
 *
 * So: white fill, a blurple hairline, blurple label and icon, 56px at
 * 19px. Still unmistakably a button and still a 56px touch target, but
 * it now reads as the SECOND thing on the card rather than the first.
 *
 * Blurple is the action colour (brand rule 4) and the real primary — the
 * unlock button further down the page — is a SOLID blurple fill, so a
 * white button with a blurple outline sits clearly below it in the
 * hierarchy rather than competing with it.
 *
 * PHOTO CARDS ARE UNTOUCHED: `.gh .pl2-btn` (a white button on a
 * photograph) is a different rule and stays as it is. This is the
 * no-photo card only, which is what `.gh--plain` means. */
.sb-white .gh--plain .pl2-btn {
  background: var(--navy);
  color: #FFFFFF;
  border: 0;
  min-height: 56px;
  font-size: 18px;
  box-shadow: 0 10px 22px -16px rgba(10, 37, 64, .7);
}
.sb-white .gh--plain .pl2-btn:hover {
  background: #12355A;
}
.sb-white .gh--plain .pl2-btn svg {
  width: 22px;
  height: 22px;
  color: #FFFFFF;
}
.sb-white .gh--plain .pl-times {color:var(--muted)}
.sb-white .gh--plain .pl-track {background:#DDDAFF}
.sb-white .gh--plain .pl-track i, .sb-white .gh--plain .pl-track b {background:var(--blurple)}
@container (min-width:900px) {
.sb-white .rv-strip {max-width:976px}
.sb-white .rv-main {max-width:1040px;display:grid;grid-template-columns:minmax(0,440px) minmax(0,1fr);gap:40px;align-items:start;padding:24px 32px 64px}
.sb-white .rv-hero {position:sticky;top:20px}
.sb-white .rv-side {padding-top:4px}
.sb-white .rv-keep :is(a, button) {padding:0 14px}
}
.sb-white .pp-song {padding:20px clamp(14px,4.6cqw,20px)}
.sb-white .pp-song .pl2 {padding:0;background:none;border:0;box-shadow:none}
@container (max-width:339.98px) {
.sb-white .up-card {padding-inline:10px}
.sb-white .up-yes {padding-inline:10px;font-size:12.5px}
}
.sb-white .qz-msg {margin:-2px 0 0}
.sb-white .qz-msg summary {display:inline-flex;align-items:center;gap:10px;min-height:48px;list-style:none;cursor:pointer;color:var(--blurple-d);font:700 18px/1.3 var(--font)}
.sb-white .qz-msg summary::-webkit-details-marker {display:none}
.sb-white .qz-msg summary small {font:400 16px/1.3 var(--font);color:var(--muted)}
.sb-white .qz-msg summary:focus-visible {outline:none;box-shadow:var(--ring);border-radius:10px}
.sb-white .qz-msg__plus {position:relative;flex:none;width:26px;height:26px;border-radius:50%;background:var(--tint)}
.sb-white .qz-msg__plus::before, .sb-white .qz-msg__plus::after {content:"";position:absolute;left:50%;top:50%;width:12px;height:2.4px;margin:-1.2px 0 0 -6px;border-radius:2px;background:var(--blurple-d)}
.sb-white .qz-msg__plus::after {transform:rotate(90deg);transition:transform 160ms ease}
.sb-white .qz-msg[open] .qz-msg__plus::after {transform:rotate(0deg)}
.sb-white .qz-msg .qz-msg__box {min-height:110px;margin-top:6px}
.sb-white .qz-msg__help {margin:8px 0 0;font:400 16px/1.45 var(--font);color:var(--muted)}
.sb-white .gs-opt {display:flex;align-items:flex-start;gap:10px;margin:-2px 0 8px;font:400 17px/1.45 var(--font);color:var(--ink2)}
.sb-white .gs-opt svg {flex:none;width:20px;height:20px;margin-top:2px;color:#0B7A55}
.sb-white .rx {display:grid;grid-template-columns:132px minmax(0,1fr);gap:18px;align-items:center;margin-top:18px;padding-top:24px;border-top:1px solid var(--hair)}
.sb-white .rx-vid {position:relative;border-radius:18px;overflow:hidden;background:var(--navy);box-shadow:0 18px 36px -22px rgba(10,37,64,.7)}
.sb-white .rx-vid video {display:block;width:100%;aspect-ratio:9/16;object-fit:cover;background:var(--navy)}
.sb-white .rx-play {position:absolute;left:50%;top:50%;display:grid;place-items:center;width:60px;height:60px;margin:-30px 0 0 -30px;border:0;border-radius:50%;background:rgba(255,255,255,.95);color:var(--navy);box-shadow:0 12px 26px -10px rgba(0,0,0,.6);cursor:pointer}
.sb-white .rx-play svg {width:28px;height:28px;margin-left:3px}
.sb-white .rx-play:focus-visible {outline:none;box-shadow:0 0 0 4px rgba(255,255,255,.7)}
.sb-white .rx-txt {min-width:0;display:flex;flex-direction:column;gap:8px}
.sb-white .rx-h {margin:0;font:700 22px/1.2 var(--font);letter-spacing:-0.02em;color:var(--navy);text-wrap:pretty}
.sb-white .rx-p {margin:0;font:400 17px/1.5 var(--font);color:var(--ink2);text-wrap:pretty}
.sb-white .rx-who {margin:2px 0 0;font:700 15px/1.3 var(--font);color:var(--blurple-d)}
.sb-white .ts {display:grid;grid-template-columns:1fr;gap:6px;margin-top:18px;padding:18px 18px;border-radius:18px;background:var(--surface);border:1px solid var(--hair);text-align:center}
.sb-white .ts p {margin:0;font:400 17px/1.45 var(--font);color:var(--ink2)}
.sb-white .ts .ts-row {display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:8px 10px;color:var(--navy)}
.sb-white .ts .ts-row b {font:700 17px/1.3 var(--font)}
@container (min-width:900px) {
.sb-white .rx {grid-template-columns:170px minmax(0,1fr);gap:24px}
.sb-white .rx-h {font-size:24px}
}
.sb-white .rx2 {display:flex;flex-direction:column;gap:8px;margin-top:18px;padding-top:24px;border-top:1px solid var(--hair)}
.sb-white .rx2 .rx-p {margin-bottom:6px}
.sb-white .rx-row {display:flex;gap:12px;overflow-x:auto;scroll-snap-type:x mandatory;scroll-padding-inline:20px;overscroll-behavior-x:contain;margin:0 -20px;padding:4px 20px 12px;scrollbar-width:thin}
.sb-white .rx-card {flex:0 0 152px;margin:0;scroll-snap-align:start;display:flex;flex-direction:column;gap:8px}
.sb-white .rx-card .rx-vid {border-radius:16px}
.sb-white .rx-card figcaption {display:flex;flex-direction:column;gap:4px}
.sb-white .rx-card q {font:400 15px/1.4 var(--font);color:var(--ink2);quotes:"“" "”";display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden}
.sb-white .rx-card b {font:700 14px/1.3 var(--font);color:var(--blurple-d)}
.sb-white .rx-card .rx-play {width:52px;height:52px;margin:-26px 0 0 -26px}
.sb-white .rx-card .rx-play svg {width:24px;height:24px}
@container (min-width:900px) {
.sb-white .rx-row {margin:0;padding:4px 0 12px;scroll-padding-inline:0}
.sb-white .rx-card {flex-basis:160px}
}
.sb-white .gs-rows li.gs-open {display:flex;flex-direction:column;gap:12px;padding:16px 16px 18px;background:#FCFCFF}
.sb-white .gs-edh {display:grid;grid-template-columns:44px minmax(0,1fr);gap:14px;align-items:center}
.sb-white .gs-edh b {font:700 18px/1.25 var(--font);color:var(--navy)}
.sb-white .gs-open .qz-area {min-height:130px}
.sb-white .gs-open .bd-signpills {margin-top:-2px}
.sb-white .gs-done {margin-top:2px}
.sb-white .wt2--one {max-width:640px;display:flex;flex-direction:column;gap:20px}
.sb-white .ws--mini {flex-direction:row;align-items:center;gap:14px;padding:14px 16px;border-radius:18px;background:linear-gradient(180deg,var(--lav) 0%,#FFFFFF 100%)}
.sb-white .ws--mini .ws-orb {width:46px;height:46px;gap:2px}
.sb-white .ws--mini .ws-orb::before {inset:-5px}
.sb-white .ws--mini .ws-orb i {width:3px;height:16px}
.sb-white .ws--mini .ws-orb i:nth-child(2) {height:22px}
.sb-white .ws--mini .ws-orb i:nth-child(3) {height:13px}
.sb-white .ws--mini .ws-orb i:nth-child(4) {height:19px}
.sb-white .ws--mini .ws-orb i:nth-child(5) {height:10px}
.sb-white .ws--mini .ws-orb svg {width:24px;height:24px}
.sb-white .ws--mini .ws-c {gap:7px}
.sb-white .ws-line {display:flex;align-items:baseline;justify-content:space-between;gap:10px}
.sb-white .ws--mini .ws-now {font:700 18px/1.25 var(--font)}
.sb-white .ws--mini .ws-pct {min-width:0;font-size:16px}
.sb-white .ws--mini .ws-bar {height:8px}
.sb-white .ws-when {margin:0;font:500 15px/1.3 var(--font);color:var(--muted)}
.sb-white .ws--mini.ws--ready .ws-now {flex:1;min-width:0}
.sb-white .gs-h {font-size:24px}
.sb-white .gs-sub {margin:-2px 0 6px;font-size:17px;color:var(--ink2)}
.sb-white .gs-sig {display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:12px}
.sb-white .gs-sig span {font:700 16px/1.2 var(--font);color:var(--muted)}
.sb-white .gs-sig .qz-input {min-height:54px;font-size:18px}
@container (min-width:900px) {
.sb-white .wt2.wt2--one {display:flex;max-width:680px;padding:32px 32px 64px}
.sb-white .gs-h {font-size:28px}
}
.sb-white .qz-from .qz-pills {display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.sb-white .qz-from .qz-pill {justify-content:center;width:100%;min-width:0}
.sb-white .qz-from .qz-pill[data-v="__type"], .sb-white .qz-from .qz-pill[data-v*=" and "] {grid-column:1/-1}
.sb-white .tp-pill {align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin:0;padding:7px 16px 7px 8px;border-radius:100px;background:#FFFFFF;border:1px solid var(--hair);box-shadow:0 8px 20px -14px rgba(10,37,64,.4);font:500 15px/1.2 var(--font);color:var(--navy);white-space:nowrap}
.sb-white .tp-pill b {font-weight:700}
.sb-white .tp-pill .qz-stars span {width:18px;height:18px}
.sb-white .tp-pill .qz-stars svg {width:12px;height:12px}
.sb-white .qz-sheet .tp-pill, .sb-white .ts .tp-pill {align-self:center}
.sb-white .ts {justify-items:center;gap:10px;padding:18px}
.sb-white .ts p:not(.tp-pill) {font:500 15px/1.3 var(--font);color:var(--muted)}
.sb-white .tp {gap:12px}
.sb-white .tp q {font:500 18px/1.5 var(--font)}
.sb-white .tp-by {display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px;margin:0;font:500 15px/1.3 var(--font);color:var(--muted)}
.sb-white .tp-by .qz-stars span {width:16px;height:16px}
.sb-white .tp-by .qz-stars svg {width:11px;height:11px}
.sb-white .qz-sheet h2 + .qz-sub {margin-top:-10px}
.sb-white .ws--mini .ws-bar {flex:none;height:8px}
.sb-white .ws--mini .ws-now {font-size:17px}
.sb-white .ob {border:1px solid var(--hair);border-radius:20px;background:#FFFFFF;overflow:hidden;box-shadow:0 20px 40px -34px rgba(10,37,64,.5)}
.sb-white .ob-main {display:grid;grid-template-columns:44px minmax(0,1fr) auto;gap:12px;align-items:center;padding:16px}
.sb-white .ob-ic {display:grid;place-items:center;width:44px;height:44px;border-radius:12px;background:var(--tint);color:var(--blurple-d)}
.sb-white .ob-ic svg {width:22px;height:22px}
.sb-white .ob-tx {display:flex;flex-direction:column;gap:2px;min-width:0}
.sb-white .ob-tx b {font:700 18px/1.25 var(--font);color:var(--navy)}
.sb-white .ob-tx small {font:400 15px/1.35 var(--font);color:var(--muted)}
.sb-white .ob-pr {display:flex;flex-direction:column;align-items:flex-end;gap:3px}
.sb-white .ob-pr s {font:500 15px/1 var(--font);color:#7A8A9C}
.sb-white .ob-pr b {font:700 21px/1.1 var(--font);color:var(--navy);font-variant-numeric:tabular-nums}
.sb-white .ob-incw {padding:12px 16px 8px;background:var(--lav);border-top:1px solid var(--lavline);border-bottom:1px solid var(--lavline)}
.sb-white .ob-k {margin:0 0 2px;font:700 13px/1.3 var(--font);letter-spacing:.1em;text-transform:uppercase;color:var(--blurple-d)}
.sb-white .ob-inc {list-style:none;margin:0;padding:0}
.sb-white .ob-inc li {display:grid;grid-template-columns:28px minmax(0,1fr) auto;gap:12px;align-items:center;padding:11px 0}
.sb-white .ob-inc li + li {border-top:1px solid #E4E2FF}
.sb-white .ob-box {display:grid;place-items:center;width:28px;height:28px;border-radius:8px;background:var(--blurple);color:#FFFFFF;box-shadow:0 6px 12px -8px rgba(99,91,255,.9)}
.sb-white .ob-box svg {width:17px;height:17px}
.sb-white .ob-inc .ob-tx b {font-size:17px}
.sb-white .ob-free {padding:5px 11px;border-radius:100px;background:#DDF4EA;color:#0B6B4B;font:700 13px/1.2 var(--font);letter-spacing:.08em;text-transform:uppercase}
.sb-white .ob-total {display:flex;align-items:baseline;justify-content:space-between;gap:12px;padding:14px 16px 2px}
.sb-white .ob-total span {font:700 18px/1.2 var(--font);color:var(--navy)}
.sb-white .ob-total b {font:700 32px/1 var(--font);letter-spacing:-0.02em;color:var(--navy);font-variant-numeric:tabular-nums}
.sb-white .ob-save {margin:0;padding:4px 16px 14px;text-align:right;font:700 15px/1.3 var(--font);color:#0B6B4B}
.sb-white .sh > *, .sb-white .qz-sheet > * {flex-shrink:0}
.sb-white .wt2.wt2--one {align-items:stretch}
.sb-white .rx2, .sb-white .ts, .sb-white .gs {min-width:0;max-width:100%}
.sb-white .tp-pill {max-width:100%;flex-wrap:wrap;justify-content:center;row-gap:4px;white-space:normal;text-align:center}
@container (min-width:900px) {
/* Founder: the logo on the $0 step "is slightly smaller". It is the
 * same 24px as every other white header — but this one rule inset it
 * 32px from the edge instead of 14px, and a wordmark with twice the
 * gutter around it reads as a smaller wordmark. The 680px column is
 * what this class is for; the padding was never part of that. */
.sb-white .fl-top--one .fl-top__in {max-width:680px}
}
.sb-white .ws--mini .ws-now {font:700 17px/1.3 var(--font);color:var(--navy);text-wrap:balance}
.sb-white .ws-line2 {display:flex;align-items:center;gap:10px}
.sb-white .ws-line2 .ws-bar {flex:1 1 auto;height:8px}
.sb-white .ws-line2 .ws-pct {min-width:2.6em;font-size:15px}
.sb-white .ws--mini .ws-when {font-size:15px}
.sb-white .gs-sub {display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;margin:-4px 0 8px}
.sb-white .gs-optional {display:inline-flex;align-items:center;padding:3px 10px;border-radius:100px;background:var(--surface);border:1px solid var(--hair);font:700 13px/1.3 var(--font);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.sb-white .gs-thumb {display:block;width:44px;height:44px;border-radius:12px;overflow:hidden;box-shadow:0 6px 14px -8px rgba(10,37,64,.6)}
.sb-white .gs-thumb img {display:block;width:100%;height:100%;object-fit:cover}
.sb-white .gs-row.is-done .gs-ic {background:var(--green);color:#FFFFFF}
.sb-white .gs-optional {align-self:flex-start;margin-bottom:2px}
.sb-white .rx-card figcaption {gap:2px}
.sb-white .rx-card figcaption b {font:700 16px/1.3 var(--font);color:var(--navy)}
.sb-white .rx-card figcaption span {font:400 15px/1.3 var(--font);color:var(--muted)}
.sb-white .sh-pill {font-size:15px;letter-spacing:.02em;text-transform:none}
.sb-white .pp-lbl {font-size:16px;letter-spacing:0;text-transform:none;color:var(--ink2)}
.sb-white .gs-optional {font-size:15px;letter-spacing:.02em;text-transform:none;padding:3px 12px}
.sb-white .rv-strip span {font-size:15px;letter-spacing:0;text-transform:none;font-weight:700}
.sb-white .gh-kicker {font-size:15px;letter-spacing:.12em}
.sb-white .ob-k {font-size:15px;letter-spacing:0;text-transform:none}
.sb-white .ob-free {font-size:15px;letter-spacing:.02em;text-transform:none;padding:4px 12px}
.sb-white .mp-k {font-size:15px}
.sb-white .crop-zoom {height:44px}
.sb-white .qz-sheet .qz-fine {white-space:nowrap;font-size:clamp(14px,4.6cqw,16px)}
.sb-white .rv-strip {width:calc(100% - 40px);max-width:560px;margin:14px auto 0;padding:0;background:none;border:0;box-shadow:none;justify-content:center}
/* ── PERSONALIZE, BELOW THE CARD, AS A LINK ──────────────────────────
 * It was a lavender PILL (`.rv-edit`), then briefly a blurple link at the
 * top of the page, and it is here because the founder saw both:
 * *"It's not looking good in purple. Also, it's taking a lot of
 * attention. Maybe it's better below. Like earlier."*
 *
 * All three of those are one point. Blurple is the ACTION colour and the
 * action on this page is unlocking; a pill competed with the unlock
 * button for the same job; and the top of the page belongs to the card,
 * because the card is the reveal. So: navy, underlined, below.
 *
 * The pencil stays blurple — the founder's standing rule ("I want
 * blurple icons everywhere") — which also gives the row one small point
 * of colour without the words shouting.
 *
 * 44px minimum height: a real tap target even though it draws as text. */
.sb-white .rv-editlink {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--navy);
  font: 700 16px/1.2 var(--font);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1.5px;
  text-decoration-color: #B9C2CE;
  cursor: pointer;
}
.sb-white .rv-editlink:hover {text-decoration-color:var(--navy)}
.sb-white .rv-editlink svg {flex:none;width:16px;height:16px;color:var(--blurple)}
.sb-white .rv-editlink:focus-visible {outline:none;box-shadow:var(--ring);border-radius:8px}
.sb-white .rv-strip span {font:500 15px/1.3 var(--font);letter-spacing:0;text-transform:none;color:var(--muted);text-align:center}
/* `.rv-edit` — the soft pill that used to hold "Personalize X's gift"
 * under the card — is GONE, because the founder moved that control into
 * a link below the card (see `.rv-editlink`). Its three rules went with the
 * markup: a class in the sheet with no markup behind it is a trap for
 * the next reader (INS-137), and this is the fourth time in this file. */
@container (min-width:900px) {
.sb-white .rv-strip {max-width:976px;justify-content:flex-start}
}
.sb-white .rv-lyrics {padding:0 16px 22px;white-space:normal}
.sb-white .ly {display:flex;flex-direction:column;gap:22px;text-align:center}
.sb-white .ly-st {display:flex;flex-direction:column;gap:6px}
.sb-white .ly-lab {margin:0;font:700 15px/1.2 var(--font);letter-spacing:.1em;text-transform:uppercase;color:var(--blurple-d)}
.sb-white .ly-lines {display:flex;flex-direction:column;gap:9px;margin:0}
.sb-white .ly-lines span {font:400 19px/1.4 var(--white-serif, 'Lora'),Georgia,'Times New Roman',serif;color:var(--navy);text-wrap:balance}
@container (min-width:700px) {
.sb-white .ly-lines span {font-size:20px}
}
.sb-white .ly-ch {padding:16px 14px 18px;border-radius:18px;background:var(--lav);border:1px solid var(--lavline)}
.sb-white .ly-ch .ly-lines span {font-weight:500}
.sb-white .ty-more {margin:4px 0 0;text-align:center;font:400 16px/1.5 var(--font);color:var(--muted);text-wrap:balance}
.sb-white .ty-link {min-height:44px;padding:0 2px;border:0;background:none;color:var(--blurple-d);font:700 16px/1.4 var(--font);text-decoration:underline;text-underline-offset:4px;cursor:pointer}
.sb-white .gh--A, .sb-white .gh--B, .sb-white .gh--C {border:1px solid #E6E2F7;box-shadow:0 34px 64px -44px rgba(74,64,209,.5);background:linear-gradient(180deg,#FFFDFA 0%,#FAF7FF 58%,#F4F1FF 100%)}
/* ── ONE BORDER, NOT TWO (founder) ───────────────────────────────────
 * *"2 borders and 'For you' does not make sense."*
 *
 * There were genuinely two: `.gh--A`'s own `1px solid #E6E2F7`, and a
 * second ring drawn by `::before` inset 12px in #E7E2FA. The inner one
 * was meant to read as card stock — a printed frame inside the card's
 * edge, which is a real device on paper. On screen, 12px inside another
 * border of almost the same colour, it is a box in a box: the third time
 * that pattern has been caught on this look (the $0 email card and the
 * discount field were the others). The outer border and the shadow are
 * already the card, so the ring goes.                                 */
/* ── ONE ACCENT PER CARD (founder: "Everything looks blurple") ───────
 * Counted, on the card as #645 left it: THREE blurple elements — this
 * kicker, the play button and the Personalize link. A hue repeated
 * everywhere is not a hierarchy, it is a theme.
 *
 * The founder picked option E: the button goes back to NAVY (small, 56px
 * at 18px, so it is no longer the 66px slab they called too big), and
 * blurple is left to the links. Which means this kicker has to stop
 * competing: it is a LABEL — who the song is from — not an action, and
 * `--muted` is what every other label on this card already uses. The
 * name is then the only strong thing in the middle, which is the point.
 *
 * Measured after: one blurple element on the card, not three. */
.sb-white .gh--A .gh-kicker, .sb-white .gh--B .gh-kicker, .sb-white .gh--C .gh-kicker {color:var(--muted)}
.sb-white .gh-card {display:flex;flex-direction:column;align-items:center;gap:14px;padding:0 24px;text-align:center}
/* ── THE VOID IN THE MIDDLE OF THE GIFT PAGE'S COVER ─────────────────
 * Founder, with a screenshot: *"why the hell is gift page looking like
 * this?"* — the name at the very top, then a vast empty band, then "A
 * song for you" and the player at the very bottom.
 *
 * It is not the 3:4 ratio. `.gh-in` is `justify-content: space-between`,
 * which is right when the card has THREE groups (kicker, name, bottom)
 * and wrong when it has two. The PAYWALL always has a kicker — "FROM
 * MOM" — because it is handed a `senderRole`. THE GIFT PAGE OFTEN HAS
 * NONE: `app/gift/[token]/page.tsx` passes `senderRole={null}` (P1-622,
 * so a dedication is never prefixed), and `.gh-kicker` renders nothing
 * unless there is a sender or it is a memorial. Two children, so
 * space-between puts one at each end and all the slack in between.
 *
 * Fixing `.gh-in` would mean choosing between the two cases. Giving the
 * NAME the slack instead works for both: the kicker stays pinned to the
 * top when it exists, the player stays pinned to the bottom, and the
 * name takes whatever is left and centres in it. With three groups it
 * looks as it does today; with two the void becomes margin around the
 * name, which is what a card should do. */
.sb-white .gh--A .gh-card, .sb-white .gh--B .gh-card, .sb-white .gh--C .gh-card {
  flex: 1;
  justify-content: center;
}
.sb-white .gh-card__t {margin:0;display:flex;flex-direction:column;align-items:center;gap:6px}
.sb-white .gh-occ {font:400 clamp(21px,6.4cqw,26px)/1.2 var(--white-serif, 'Lora'),Georgia,serif;color:#41546A}
.sb-white .gh-name {font:500 clamp(48px,16cqw,72px)/1.02 var(--white-serif, 'Lora'),Georgia,serif;letter-spacing:-0.01em;color:var(--navy);text-wrap:balance;overflow-wrap:anywhere}
/* The line–heart–line ornament, exactly as it has always been. The
 * founder asked for the lines off and then straight back on the same
 * night ("lets keep option c AND LETS have those 2 lines beside heart"),
 * so nothing here changed in the end.
 *
 * WHAT DID CHANGE: P1-627 left a DUPLICATE of this block in the file.
 * The rules were deleted in #640 — which was REVERTED, so they were
 * never actually gone from `main` — and P1-627 restored them anyway, so
 * the sheet carried two identical copies. Harmless (same declarations,
 * the later one wins) and removed here. The lesson is the cheap one:
 * before restoring a rule, grep for it. */
.sb-white .gh-orn {display:flex;align-items:center;justify-content:center;gap:10px;color:#E0457B}
.sb-white .gh-orn i {width:44px;height:1px;background:#D8D2F5}
.sb-white .gh-orn svg {width:15px;height:15px;vertical-align:0}
.sb-white .gh--A .gh-meta {margin:0 0 12px;text-align:center;font:500 17px/1.3 var(--font);color:var(--ink2)}
.sb-white .gh-art {flex:1;min-height:0;display:grid;place-items:center;padding:0 20px}
.sb-white .gh-art svg {width:min(52%,200px);height:auto;max-height:100%}
.sb-white .gh-seal {align-self:center;display:grid;place-items:center;width:clamp(120px,40cqw,168px);aspect-ratio:1/1;border-radius:50%;background:rgba(255,255,255,.75);border:1.5px solid #CFC8F7;box-shadow:inset 0 0 0 7px #FFFFFF,inset 0 0 0 8.5px #E3DEFA,0 20px 40px -26px rgba(74,64,209,.55)}
.sb-white .gh-seal b {font:500 clamp(58px,19cqw,80px)/1 var(--white-serif, 'Lora'),Georgia,serif;color:var(--navy);transform:translateY(-2%)}
.sb-white .gh--C {background:radial-gradient(70% 45% at 50% 34%,#FFFFFF 0%,rgba(255,255,255,0) 72%),linear-gradient(170deg,#F3F1FF 0%,#FBF3F8 100%)}
.sb-white .gh--A .gh-title, .sb-white .gh--B .gh-title, .sb-white .gh--C .gh-title {color:var(--navy)}
.sb-white .cvm {container-type:inline-size;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8%;width:100%;aspect-ratio:1/1;padding:10%;text-align:center;background:linear-gradient(180deg,#FFFDFA 0%,#F4F1FF 100%)}
.sb-white .cvm--A::before {content:"";position:absolute;inset:7%;border:1px solid #E3DEF7;border-radius:10px;pointer-events:none}
.sb-white .cvm--A b {font:500 26cqw/1 var(--white-serif, 'Lora'),Georgia,serif;color:var(--navy);overflow-wrap:anywhere}
.sb-white .cvm .gh-orn svg {width:12cqw;height:12cqw}
.sb-white .cvm--B svg {width:78%;height:auto}
.sb-white .cvm--C .gh-seal {width:74%;box-shadow:inset 0 0 0 5px #FFFFFF,inset 0 0 0 6px #E3DEFA}
.sb-white .cvm--C .gh-seal b {font-size:40cqw}
.sb-white .rd-pic .cvm {display:flex;width:112px;border-radius:18px;overflow:hidden;box-shadow:0 16px 32px -18px rgba(10,37,64,.6)}
/* P1-626 — THE NO-PHOTO COVER GETS ITS HEIGHT BACK.
 *
 * Founder: *"the cover is really looking bad on preview. I think we
 * should use the earlier height and style."* And earlier, on the same
 * card: *"the cover photo is looking too small."* Same complaint, and it
 * was never the PHOTO cover — that one keeps `.gh`'s own 3/4 and always
 * has. It is the NO-PHOTO one, and `aspect-ratio: auto` is why: the card
 * became exactly as tall as its contents, so with no photo it collapsed
 * to a squat band while the photo version beside it — the SAME
 * component, one branch apart — stood at 3/4. On the paywall, where this
 * card IS the product, that reads as the page having lost its hero.
 *
 * ── WHY A SPACER AND NOT `aspect-ratio` ─────────────────────────────
 *
 * Because the ratio has to be a FLOOR, not a height. `.gh` sets
 * `min-height: 0`, and with that in force an `aspect-ratio` is a hard
 * height that content cannot grow past — so a long name either spills
 * out of the card or, the moment anything sets `overflow: hidden` on it,
 * is CUT OFF. Measured at 392px with "Wolstenholme-Fitzgerald": content
 * 565px against a 467px box. A name cut in half on the recipient's own
 * cover is worse than a squat card, and one rule away is too close.
 *
 * `min-height` cannot fix it. `auto` is a no-op on a block box (it means
 * something only for a flex or grid ITEM), and Chromium accepts
 * `fit-content` / `max-content` / `min-content` for `min-height` and
 * then resolves them to zero. All four were tried in a browser; all four
 * still clipped at 565/467.
 *
 * So the ratio goes back the way it was originally expressed here: a
 * zero-width `::after` whose PERCENTAGE PADDING resolves against the
 * card's own width. As a flex item it contributes 133.333% of the width
 * as height, which sets the 3:4 floor, and because it is only an item in
 * the line, `.gh-in` growing past it takes the line with it.
 *
 * Measured, same browser, same cases: short names 352x469 (0.751),
 * "Wolstenholme-Fitzgerald" 352x571 and NOT clipped, photo card
 * untouched at 352x469. Tall by default, never cut. */
.sb-white .gh--A, .sb-white .gh--B, .sb-white .gh--C {
  overflow: visible;
  aspect-ratio: auto;
}
.sb-white .gh--A::after, .sb-white .gh--B::after, .sb-white .gh--C::after {
  content: "";
  flex: 0 0 0px;
  width: 0;
  padding-top: 133.333%;
}
.sb-white .tp--buyer .tp-by {gap:4px 10px}
.sb-white .tp--buyer .tp-by b {font:700 16px/1.3 var(--font);color:var(--navy)}
.sb-white .tp--buyer .tp-by span {font:500 15px/1.3 var(--font);color:var(--muted)}
.sb-white .tp--buyer .tp-src {flex-basis:100%;color:#1E8E5A!important}
.sb-white .lyp {gap:18px}
.sb-white .lyp-card {display:flex;flex-direction:column;gap:4px;padding:18px 16px 6px;border:1px solid var(--lavline);border-radius:22px;background:#FFFFFF;box-shadow:0 18px 40px -30px rgba(74,64,209,.45);transition:opacity 200ms ease}
.sb-white .lyp-card.is-dim {opacity:.45}
.sb-white .lyp-head {display:flex;align-items:center;gap:8px;margin:0 0 2px 4px;font:700 16px/1.3 var(--font);color:var(--blurple-d)}
.sb-white .lyp-head svg {width:18px;height:18px}
.sb-white .lyp-actions, .sb-white .lyp-reasons {display:flex;flex-direction:column;gap:12px}
.sb-white .lyp-hint {margin:0;font:400 17px/1.5 var(--font);color:var(--ink2);text-wrap:pretty}
.sb-white .lyp-btns, .sb-white .lyp-chips {display:flex;flex-wrap:wrap;gap:10px}
.sb-white .lyp-ghost {display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:50px;padding:0 22px;border:1.5px solid var(--lavline);border-radius:100px;background:#FFFFFF;color:var(--navy);font:700 17px/1 var(--font);cursor:pointer}
.sb-white .lyp-ghost svg {width:18px;height:18px;color:var(--blurple-d)}
.sb-white .lyp-ghost--strong {border-color:var(--blurple);background:var(--blurple);color:#FFFFFF}
.sb-white .lyp-chip {min-height:46px;padding:0 18px;border:1.5px solid var(--lavline);border-radius:100px;background:#FFFFFF;color:var(--navy);font:500 17px/1.2 var(--font);cursor:pointer}
.sb-white .lyp-ghost:focus-visible, .sb-white .lyp-chip:focus-visible {outline:none;box-shadow:0 0 0 4px rgba(99,91,255,.25)}
.sb-white .lyp-status {display:flex;align-items:center;gap:10px;margin:0;font:500 17px/1.4 var(--font);color:var(--ink2)}
.sb-white .lyp-status i {flex:none;width:10px;height:10px;border-radius:50%;background:var(--blurple);animation:lypPulse 1.2s ease-in-out infinite}
.sb-white .qz-area.lyp-edit {min-height:440px;font:400 18px/1.7 var(--white-serif, 'Lora'),Georgia,serif;color:var(--navy)}
.sb-white .lyp--wait {align-items:center;text-align:center}
.sb-white .lyp-pulse {width:64px;height:64px;border-radius:50%;background:radial-gradient(circle,#B9B4FF 0%,rgba(185,180,255,0) 70%);animation:lypPulse 1.4s ease-in-out infinite}
.sb-white .lyp-empty {width:100%;min-height:260px;display:grid;place-items:center;padding:20px;border:1.5px dashed var(--lavline);border-radius:22px;background:#FCFCFF}
.sb-white .lyp-empty span {font:400 18px/1.4 var(--white-serif, 'Lora'),Georgia,serif;color:var(--muted)}
@keyframes lypPulse {0%,100%{transform:scale(.85);opacity:.6}50%{transform:scale(1);opacity:1}}
@media (prefers-reduced-motion:reduce) {
.sb-white .lyp-pulse, .sb-white .lyp-status i {animation:none}
}
.sb-white .rx-row {scrollbar-width:none;-ms-overflow-style:none}
.sb-white .rx-row::-webkit-scrollbar {display:none}
.sb-white .rx-head {display:flex;align-items:flex-end;justify-content:space-between;gap:16px}
.sb-white .rx-titles {display:flex;flex-direction:column;gap:8px;min-width:0}
.sb-white .rx2 .rx-titles .rx-p {margin-bottom:6px}
.sb-white .rx-arrows {display:none;gap:10px;flex:none;margin-bottom:8px}
@media (hover:hover) and (pointer:fine) {
.sb-white .rx-arrows {display:flex}
}
.sb-white .rx-arr {display:grid;place-items:center;width:46px;height:46px;padding:0;border:1.5px solid var(--lavline);border-radius:50%;background:#FFFFFF;color:var(--navy);cursor:pointer;transition:opacity 160ms ease,border-color 160ms ease}
.sb-white .rx-arr:hover:not(:disabled) {border-color:var(--blurple);color:var(--blurple-d)}
.sb-white .rx-arr:focus-visible {outline:none;box-shadow:0 0 0 4px rgba(99,91,255,.25)}
.sb-white .rx-arr svg {width:20px;height:20px}
.sb-white .rx-arr:disabled {opacity:.35;cursor:default}

/* ═══════════════════════════════════════════════════════════════════════
 * POST-APPROVAL CHANGES — founder, 2026-09-20, from looking at the built
 * screen. Appended rather than edited into the port above, so the
 * verbatim port stays auditable and source order gives these the win.
 * ═══════════════════════════════════════════════════════════════════════ */

/* ── The from-question's pills hug their text, like every other pill ────
 *
 * Founder, on "Mom and Dad" and "Type your own" running the full width:
 * *"can we make it like others only around the text and not extending to
 * full width?"*
 *
 * THIS REVERSES A LINE OF THE BRIEF, deliberately and on their word. §2.2
 * step 1 says "the options fill the width (singles side by side; the pair
 * and 'Type your own' full width)", which the port implemented with a
 * two-column grid plus `grid-column: 1/-1` on those two. The founder is
 * looking at the built screen and the brief was looking at a mockup; the
 * later word wins (same as the Trustpilot score going 5.0 → 4.9).
 *
 * The fix is to STOP OVERRIDING, not to add anything: `.qz-pills` is
 * already `display: flex; flex-wrap: wrap` and `.qz-pill` is already
 * `inline-flex`, which is exactly "around the text" — it is how the
 * traits pills and the name screen's quick picks have always behaved.
 * Removing the from-question's own grid simply returns it to the family.
 *
 * `data-v` stays on the pills even though the layout no longer reads it.
 * It costs nothing, it documents which value each pill carries, and it is
 * what makes this one line reversible if the founder wants the wide rows
 * back after seeing both.                                               */
.sb-white .qz-from .qz-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  grid-template-columns: none;
}
.sb-white .qz-from .qz-pill {
  justify-content: flex-start;
  width: auto;
}
.sb-white .qz-from .qz-pill[data-v="__type"],
.sb-white .qz-from .qz-pill[data-v*=" and "] {
  grid-column: auto;
}

/* ── The 52px of cream under the quiz ──────────────────────────────────
 *
 * Founder, on the name screen: *"why is the bottom looking in cream
 * color?"* Measured at 390×844: the white quiz was 792px tall inside an
 * 844px viewport, and the 52px it did not cover showed `.funnel-scope`,
 * today's funnel wrapper, whose background is #FFF7EE.
 *
 * 844 − 792 = 52. THAT NUMBER CAME FROM THE MOCKUP'S OWN TOOLBAR.
 * `_redesign/mockup/flow/site/index.html` opens with
 * `<div class="mk" role="region" aria-label="Mockup controls">` — the
 * navy strip carrying "App mockup", "Tap through / All screens", "Quiz
 * as today / + My changes" and "Start over". It is 52px tall, so the
 * mockup sized its quiz `calc(100dvh - 52px)` to sit under it.
 *
 * That bar does not exist in the app, so the port carried a hole exactly
 * its size. This is the SECOND time the mockup's own scaffolding has
 * shipped as a bug — the first was the `@container` blocks the porter
 * emitted unscoped, which cost the quiz its whole desktop layout. A
 * mockup is a page, not a component: everything it needs to BE a page
 * has to be found and left behind, and a verbatim porter cannot tell the
 * two apart.
 *
 * Two rules, doing two different jobs, so neither is a copy of the other:
 *
 *   1. `.qz` — remove the offset. The quiz is a full screen; it was only
 *      ever short because something else was standing on it. `--frame`
 *      keeps its 100% (that is the mockup's "All screens" grid, where a
 *      screen really is boxed) even though our port never renders it.
 *   2. `.sb-white` — the safety net, and the one that generalises. Every
 *      white page in this lane renders inside today's cream funnel
 *      wrapper, the wait page and the paywall included. Guaranteeing the
 *      ROOT covers the viewport means no white screen can ever let the
 *      cream through again, whatever its content height.               */
.sb-white {
  min-height: 100dvh;
  background: var(--page);
}
.sb-white .qz:not(.qz--frame) {
  min-height: 100dvh;
}
.sb-white .qz--navy .rv {
  min-height: 100dvh;
}

/* ── The wait page's "song is ready" bar ───────────────────────────────
 *
 * The mockup wrote this row's layout inline on the element
 * (`flex-direction:row;align-items:center;justify-content:space-between`
 * plus a `font:700 18px/1.3` on the <b>), because it builds its DOM from
 * strings and had nowhere else to put it. We have a stylesheet, so it
 * goes here — same result, and one place to change it.               */
.sb-white .qz-foot__in.gs-readyfoot {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}
.sb-white .gs-readyfoot b {
  font: 700 18px/1.3 var(--font);
  color: var(--navy);
}
.sb-white .gs-readyfoot .qz-btn {
  min-width: 0;
  flex: none;
}

/* ── THE THANK-YOU PAGE'S PLAYER ───────────────────────────────────────
 *
 * This block used to style a bare `<audio controls>` and argue for it:
 * "what someone wants from a track they are keeping is a scrubber and a
 * volume slider — not a single tasteful button."
 *
 * Founder: *"on the thank you page, the song player is too basic. I
 * think it can be better."*
 *
 * The argument was half right, and the half it got wrong is why the
 * screen looked given-up-on: a SCRUBBER is exactly right here, so
 * `WhiteSongPlayer` has one — tap, drag and keyboard. A volume slider no
 * phone renders, and a download menu we already offer better, are not.
 *
 * What was really wrong is that the transport had been in this file the
 * whole time. `.pl-ctrl`, `.pl-ctrl button` (48px) and `.pl-ctrl
 * .pl-play` (72px, blurple) are the mockup's own three controls, ported
 * here, and `.pl-ctrl` appeared in NO component. The stylesheet was
 * ready and the markup never arrived.
 *
 * ⚠ AND WIRING IT UP WOULD HAVE SHIPPED WHITE ICONS ON A LAVENDER CARD.
 * `.pp-song` is navy at line ~350, where `.pp-song .pl-ctrl button` was
 * given `color:#FFFFFF`. A later block re-themed `.pp-song` to LAVENDER
 * and reverted `h2`, `a`, `.pl-track` and `.pl-times` — but not
 * `.pl-ctrl`. So the two side buttons would have been white on #EDEBFF:
 * present, 48px, correctly labelled, and invisible (INS-136, the
 * second time today). The three rules below finish that re-theme. */
.sb-white .pp-song .pl {
  background: #FFFFFF;
  border-color: var(--lavline);
}
.sb-white .pp-song .pl-ctrl button {color: var(--navy)}
.sb-white .pp-song .pl-ctrl .pl-play {
  background: var(--blurple);
  color: #FFFFFF;
  box-shadow: 0 14px 28px -14px rgba(99, 91, 255, .9);
}

/* A 6px bar is not a touch target. The hit area grows 18px above and
 * below through a pseudo-element, so the BAR stays 6px and the thumb
 * stays 14px — the mockup's proportions, unchanged — while a thumb lands
 * on it. The fill and the thumb stop swallowing the pointer, or a drag
 * that starts on the played part never reaches the track at all. */
.sb-white .pl-track--seek {
  cursor: pointer;
  touch-action: none;
}
.sb-white .pl-track--seek::after {
  content: "";
  position: absolute;
  inset: -18px 0;
}
.sb-white .pl-track--seek i,
.sb-white .pl-track--seek b {pointer-events: none}
.sb-white .pl-track--seek:focus-visible {
  outline: none;
  box-shadow: var(--ring);
}

/* ══ The two commerce blocks, restyled rather than rewritten ══════════
 *
 * `ExtraSongOffer` (the second song at 30% off) and `SecondSongCard`
 * (the free style variant) are money paths. §2.5 asks for them in
 * "today's words", and the brief does not describe their layout — so
 * their MARKUP IS NOT TOUCHED. Not one class renamed, not one element
 * moved, not one `look ?` ternary threaded through a purchase flow.
 * What changes is what those classes look like inside `.sb-white`.
 *
 * Restyling instead of rewriting is the smaller risk by a distance: a
 * CSS rule cannot drop a button, reorder a step, or lose a handler, and
 * every one of these blocks can be reverted by deleting this section.
 *
 * SPECIFICITY, because it is load-bearing: funnel.css writes these as
 * `.funnel-scope .f-extra-card`, which is (0,2,0). `/preview/layout.tsx`
 * imports funnel.css, and every white page on that route therefore
 * renders INSIDE `.funnel-scope`. A bare `.sb-white .f-extra-card` is
 * also (0,2,0) and would be decided by document order — which is not
 * something to leave to a <link> in the body. `.funnel-scope .sb-white`
 * is (0,3,0) and wins outright; the unprefixed twin below it covers any
 * route where the wrapper is absent.                                  */
.funnel-scope .sb-white .f-extra,
.sb-white .f-extra,
.funnel-scope .sb-white .f-offer,
.sb-white .f-offer {
  background: var(--page);
  border-color: var(--hair);
  color: var(--navy);
  font-family: var(--font);
}
.funnel-scope .sb-white .f-extra-kicker,
.sb-white .f-extra-kicker {
  color: var(--blurple-d);
  font: 700 14px/1.2 var(--font);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.funnel-scope .sb-white .f-extra-head,
.sb-white .f-extra-head,
.funnel-scope .sb-white .f-offer-title,
.sb-white .f-offer-title {
  color: var(--navy);
  font: 700 30px/1.15 var(--font);
  letter-spacing: -0.03em;
}
.funnel-scope .sb-white .f-extra-head-pct,
.sb-white .f-extra-head-pct {
  color: var(--blurple);
}
.funnel-scope .sb-white .f-extra-lead,
.sb-white .f-extra-lead,
.funnel-scope .sb-white .f-thanks-gift-copy,
.sb-white .f-thanks-gift-copy,
.funnel-scope .sb-white .f-helper,
.sb-white .f-helper {
  color: var(--ink2);
  font: 400 19px/1.5 var(--font);
}
.funnel-scope .sb-white .f-extra-card,
.sb-white .f-extra-card {
  background: var(--page);
  border: 1px solid var(--lavline);
  border-radius: 22px;
  box-shadow: 0 24px 48px -36px rgba(74, 64, 209, 0.55);
}
.funnel-scope .sb-white .f-extra-price-now,
.sb-white .f-extra-price-now,
.funnel-scope .sb-white .f-extra-summary-price,
.sb-white .f-extra-summary-price {
  color: var(--navy);
  font-family: var(--font);
  font-weight: 700;
}
.funnel-scope .sb-white .f-extra-price-was,
.sb-white .f-extra-price-was {
  color: var(--muted);
  font-family: var(--font);
}
.funnel-scope .sb-white .f-extra-save,
.sb-white .f-extra-save {
  color: #0b6b4b;
  background: #e6f7f0;
  font: 700 15px/1 var(--font);
}
.funnel-scope .sb-white .f-extra-rule,
.sb-white .f-extra-rule {
  background: var(--hair);
}
/* Every primary button in these blocks becomes the look's own button —
 * same element, same handler, same words. */
.funnel-scope .sb-white .f-btn,
.sb-white .f-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 64px;
  padding: 0 28px;
  border: 0;
  border-radius: 14px;
  background: var(--blurple);
  color: #ffffff;
  font: 700 20px/1.2 var(--font);
  box-shadow: 0 14px 28px -14px rgba(99, 91, 255, 0.9);
  cursor: pointer;
}
.funnel-scope .sb-white .f-btn:hover,
.sb-white .f-btn:hover {
  background: var(--blurple-h);
}
.funnel-scope .sb-white .f-extra-decline,
.sb-white .f-extra-decline,
.funnel-scope .sb-white .f-extra-next,
.sb-white .f-extra-next {
  background: none;
  border: 0;
  color: var(--muted);
  font: 500 17px/1.2 var(--font);
  text-decoration: underline;
  text-underline-offset: 4px;
  min-height: 48px;
}
.funnel-scope .sb-white .f-extra-decline:hover,
.sb-white .f-extra-decline:hover,
.funnel-scope .sb-white .f-extra-next:hover,
.sb-white .f-extra-next:hover {
  color: var(--navy);
}
.funnel-scope .sb-white .f-error,
.sb-white .f-error,
.funnel-scope .sb-white .f-pay-error,
.sb-white .f-pay-error {
  color: var(--error);
  font: 500 17px/1.4 var(--font);
}
.funnel-scope .sb-white .f-input,
.sb-white .f-input {
  min-height: 62px;
  padding: 14px 16px;
  border: 1.5px solid var(--line);
  border-radius: 14px;
  background: var(--page);
  color: var(--navy);
  font: 400 18px/1.35 var(--font);
}
.funnel-scope .sb-white .f-extra-code,
.sb-white .f-extra-code,
.funnel-scope .sb-white .f-code-label,
.sb-white .f-code-label {
  color: var(--navy);
  font-family: var(--font);
}

/* ── The payment step's own pieces ─────────────────────────────────────
 *
 * `CheckoutPanel`'s markup is today's, deliberately (a money path is not
 * rewritten for a look), so these five classes had NO white rules at all
 * — which is why the founder's screenshot showed a cream "Apply" button
 * beside a white input, and a discount link so quiet they called it
 * "sort of hidden".                                                    */
.sb-white .f-pay {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
/* "or pay with card". The rules are hairlines, not the cream's colour. */
.sb-white .f-pay-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 2px 0;
  color: var(--muted);
  font: 500 15px/1 var(--font);
}
.sb-white .f-pay-divider::before,
.sb-white .f-pay-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--hair);
}
.sb-white .f-pay-code {
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* funnel.css's own `.f-pay-code { margin-top: 14px }` is UNSCOPED, and
   * `/preview/layout.tsx` imports that file — so it lands here too, on
   * top of `.f-pay`'s 14px flex gap. Spacing is the container's job in
   * both of this block's homes. */
  margin-top: 0;
}
/* ⚠ THE OUTER WRAPPER THE FOUNDER SAW. funnel.css gives this group a
 * 1px border, a 12px radius, `overflow: hidden` and a white fill — one
 * joined input group, which is right in the cream look, where the input
 * and the button inside it are borderless. The white look borders the
 * input and the button THEMSELVES, so the group's own frame became a
 * third box around them. Four rules of cream leaking through one class
 * that the white rule only ever set `display` and `gap` on. */
.sb-white .f-pay-code-group {
  display: flex;
  gap: 8px;
  border: 0;
  border-radius: 0;
  overflow: visible;
  background: none;
}
/* Same leak, same fix: the error's 12px top margin, inside a flex column
 * that already has a gap. Scoped to the code block, because `.f-error`
 * shares the white rule and other surfaces do lean on its margin. */
.sb-white .f-pay-code .f-pay-error {
  margin: 0;
}

/* ── ONE LOOK FOR THE CODE ROW, IN BOTH OF ITS HOMES ─────────────────
 *
 * Founder: *"I like the discount code block on the continue to payment
 * page, why are we not using same block on payment page as well instead
 * of the underlined link?"* Because the styling I wrote was scoped to
 * the summary's slot, and the payment step is the SAME MARKUP in a
 * different parent.
 *
 * WHY IT LANDS THERE AT ALL. One block is portaled into the order
 * summary while that sheet is up. Pressing "Continue to payment"
 * unmounts the sheet (`paywallOpen={e.paywallOpen && !e.payOpen}`), the
 * slot's ref fires null, and `CheckoutPanel` falls back to rendering it
 * in place — which is the right behaviour (a buyer who remembers their
 * code at the payment step must not have to go back) and was wearing
 * the old naked-link style.
 *
 * So the ROW itself is defined here, once, for both homes. Each home
 * adds only its container treatment below: the summary wants a row of
 * a card, the payment step wants a control of a form. Typography, the
 * "+" and the tap target cannot drift, because there is one copy.   */
.sb-white .f-pay-code-toggle {
  display: flex;
  align-items: center;
  gap: 9px;
  align-self: stretch;
  width: 100%;
  min-height: 52px;
  margin: 0;
  padding: 0 16px;
  border: 0;
  background: none;
  color: var(--blurple-d);
  /* 500, not 600: a row in a receipt, not a second call to action.
   * Present for the buyer who has a code, quiet for the one who does
   * not — a loud one asks everybody whether they are paying too much.
   * 16px stays: this audience is 55–65+. */
  font: 500 16px/1.2 var(--font);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.sb-white .f-pay-code-toggle::before {
  content: "+";
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 7px;
  background: var(--tint);
  font: 600 17px/1 var(--font);
}
.sb-white .f-pay-code-toggle:hover {
  color: var(--navy);
}

/* ── "HOME 1" IS GONE, AND THAT IS THE FOUNDER'S OVERLAP FIX ──────────
 * There used to be a second home here: `.sb-white .f-pay >
 * .f-pay-code-toggle`, giving the row its own hairline and 14px radius
 * "like the Stripe fields above it" — for the payment step, where the
 * block landed whenever the summary's portal node was missing.
 *
 * Founder: *"the coupon code block is slightly overlapping with the
 * payment form underneath."* Nothing was overlapping in the z sense —
 * measured, every gap in `.f-pay`'s flex column is positive. What they
 * were seeing is that this row, bordered and rounded exactly like a
 * Stripe field, sat 14px under Stripe's Country field and read as part
 * of the form. And it should not have been on that screen at all: the
 * founder's option A puts the code with the price, one step earlier,
 * and the white lane was showing it in BOTH places.
 *
 * `CheckoutPanel` now renders nothing there in the new look (see the
 * long note at its portal), so these two rules can no longer match:
 * inside `.sb-white` the block is always portalled into `.ob-code`, and
 * every call site that renders it in `.f-pay` is a cream one, outside
 * this wrapper. Left in place they would be paint for a component that
 * cannot exist — INS-137, the second time in this sheet. The `.ob-code`
 * home's rules are further down and untouched.                        */

/* The open pair, in both homes: ONE bordered thing. The input keeps its
 * border and takes the page's own fill; "Apply" is the tint chip this
 * look already uses on `.ob-ic`, not a 2px navy outline that competed
 * with the pay button. */
.sb-white .f-pay-code-input {
  flex: 1;
  min-width: 0;
  min-height: 48px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: var(--surface);
  color: var(--navy);
  font: 500 16px/1 var(--font);
  /* Beats funnel.css's own `text-transform: uppercase` — same
   * specificity there, so the `.sb-white` scope is what wins. It
   * SHOUTED "DISCOUNT CODE" at a buyer who had typed nothing. What they
   * type is still capitalised, by `autoCapitalize` on the input. */
  text-transform: none;
  letter-spacing: 0.02em;
}
.sb-white .f-pay-code-input::placeholder {
  color: var(--muted);
  text-transform: none;
  letter-spacing: 0;
}
.sb-white .f-pay-code-input:focus-visible {
  outline: none;
  border-color: var(--blurple);
  box-shadow: var(--ring);
}
.sb-white .f-pay-code-apply {
  flex: none;
  min-height: 48px;
  padding: 0 16px;
  border: 0;
  border-radius: 11px;
  background: var(--tint);
  color: var(--blurple-d);
  font: 700 16px/1 var(--font);
  cursor: pointer;
}
/* Waiting, not broken: it keeps its shape and loses its colour. */
.sb-white .f-pay-code-apply:disabled {
  background: var(--surface);
  color: var(--muted);
  cursor: default;
}

/* ── The sheet's action stays on screen ───────────────────────────────
 *
 * Founder, on the unlock sheet: *"its important for the payment button to
 * be visible and a scroll should not be needed."*
 *
 * The sheet is `max-height: 88%` with `overflow: auto`, which is right —
 * an order summary can be taller than a phone and must be readable. What
 * was wrong is that the ACTION scrolled away with it, so on a 390×844
 * screen "Continue to payment" sat below the fold and the sheet looked
 * like it had no button.
 *
 * Sticky rather than a fixed footer: the summary keeps scrolling behind
 * it, nothing is cropped, and the markup does not change shape. The
 * background is opaque and the shadow is the hint that there is more
 * above — without it the button appears to float over half a word.     */
/* ⚠ AND `.sb-white .sh` CARRIES `scroll-padding-bottom` BECAUSE OF THIS
 * BAR. A sticky footer with an opaque background is invisible to
 * `scrollIntoView`: the browser puts the target flush against the
 * scrollport's bottom edge, which is underneath this. `scroll-padding`
 * is the one declaration that tells every scroll — the browser's own
 * when a field takes focus, and ours — to keep that strip clear. 160px
 * is this bar measured (126px) plus its negative offset, and it is set
 * on the SHEET rather than per-call so a control added later inherits it
 * instead of rediscovering the bug.
 *
 * It cannot make anything worse than it was: where a scroller cannot
 * scroll that far it clamps to its maximum, which is exactly today's
 * behaviour. Verified for `block: "end"` (the redo doors) as well as
 * `"center"` (the discount field).                                     */
.sb-white .sh-stick {
  position: sticky;
  bottom: calc(-24px - env(safe-area-inset-bottom, 0px));
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 -22px;
  padding: 14px 22px calc(18px + env(safe-area-inset-bottom, 0px));
  background: var(--page);
  box-shadow: 0 -16px 24px -18px rgba(10, 37, 64, 0.35);
}
/* THE HORIZONTAL SCROLLBAR ON DESKTOP WAS THIS, AND IT WAS ARITHMETIC.
 * Founder: *"This scroll on the right and bottom on desktop looks
 * ancient. There has to be a better way."*
 *
 * The bar bleeds past the sheet's padding on purpose, so its white band
 * reaches the sheet's edges — which means its negative margin has to
 * EQUAL that padding. `.sh` is `padding: 26px 22px`, at every width: the
 * 640px block above changes radius, margin, max-width and max-height,
 * and never touches padding. So `-30px` overhung by 8px a side, 16px of
 * content wider than the scrollport, and `overflow: auto` did the only
 * thing it can — it offered a horizontal scrollbar.
 *
 * -22px to match, and the padding with it, which also lines the button
 * up with the card above it instead of insetting it a further 8px.
 *
 * `overflow-x` is deliberately NOT hidden here. Hiding it would have
 * silenced this symptom while still clipping 8px of a future bar, and
 * the next person would be hunting a missing edge instead of reading a
 * scrollbar that told them the truth. */
@media (min-width: 640px) {
  .sb-white .sh-stick {
    bottom: -28px;
    margin: 0 -22px;
    padding: 16px 22px 26px;
  }
}

/* THE VERTICAL ONE IS REAL AND HAS TO STAY — it is the only sign that
 * there is more sheet below. But it was the OS default: 15px wide,
 * square, grey, sitting on top of a 24px rounded corner. Thin, inset and
 * in the palette instead. `scrollbar-color` covers Firefox;
 * `::-webkit-scrollbar` covers Chrome, Edge and Safari-on-Windows. On
 * iOS and macOS the overlay scrollbar already fades itself, so this only
 * changes the platforms that were showing the ancient one. */
.sb-white .sh {
  scrollbar-width: thin;
  scrollbar-color: #C3CEDA transparent;
}
.sb-white .sh::-webkit-scrollbar {
  width: 12px;
}
.sb-white .sh::-webkit-scrollbar-track {
  background: transparent;
}
.sb-white .sh::-webkit-scrollbar-thumb {
  border-radius: 100px;
  background: #C3CEDA;
  /* A transparent border, not a margin: it insets the thumb inside the
   * 12px track so it reads as a floating pill rather than a bar wedged
   * against the sheet's rounded edge. `background-clip: padding-box` is
   * what stops the thumb painting under that border. */
  border: 3px solid transparent;
  background-clip: padding-box;
}
.sb-white .sh::-webkit-scrollbar-thumb:hover {
  background: #9FB0C4;
  background-clip: padding-box;
}

/* The applied discount, and the tax receipt when Stripe has taxed the
 * order. Both were unstyled too — the same missing-rules bug as the
 * code field, found by listing every class `CheckoutPanel` emits rather
 * than by guessing which ones mattered. */
.sb-white .f-pay-discount {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 0;
  /* The third leak: funnel.css rings this row in `#cfe0cf`, its own
   * green. A cream border around a white-look fill. */
  border: 0;
  padding: 12px 16px;
  border-radius: 14px;
  background: #e6f7f0;
  color: #0b6b4b;
  font: 500 16px/1.35 var(--font);
}
.sb-white .f-pay-discount-main strong {
  font-weight: 700;
}
.sb-white .f-pay-discount-remove {
  flex: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: -6px -8px -6px 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: #0b6b4b;
  font-size: 17px;
  cursor: pointer;
}
.sb-white .f-pay-summary {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px;
  border-radius: 16px;
  background: var(--surface);
}
.sb-white .f-pay-summary-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  font: 500 16px/1.3 var(--font);
  color: var(--ink2);
  font-variant-numeric: tabular-nums;
}
.sb-white .f-pay-summary-row:last-child {
  padding-top: 8px;
  border-top: 1px solid var(--hair);
  color: var(--navy);
  font-weight: 700;
  font-size: 18px;
}

/* The last five, each found by listing what the panel emits rather than
 * by guessing: the error/loading states, the retry button, the email row
 * on the zero-total path, and the summary's total row. */
.sb-white .f-pay-loading {
  align-items: center;
  padding: 18px 0;
  color: var(--muted);
  font: 500 17px/1.4 var(--font);
  text-align: center;
}
.sb-white .f-sheet-fine {
  margin: 0;
  color: var(--muted);
  font: 500 15px/1.45 var(--font);
  text-align: center;
  text-wrap: pretty;
}
.sb-white .f-offer-cta {
  width: 100%;
}
.sb-white .f-pay-email {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sb-white .f-pay-email label,
.sb-white .f-pay-email p {
  margin: 0;
  color: var(--ink2);
  font: 500 16px/1.4 var(--font);
}
.sb-white .f-pay-summary-row.f-pay-summary-total {
  padding-top: 8px;
  border-top: 1px solid var(--hair);
  color: var(--navy);
  font-weight: 700;
  font-size: 18px;
}

/* ── Home 2 ─ the code row INSIDE the order summary ──────────────
 *
 * Founder, on the first cut: *"'Have a discount code' link looks
 * unnatural and out of place … when we enter the coupon code the block
 * looks messy and cluttered i THINK BECAUSE OF THE OUTER WRAPPER."*
 * Right on both counts, and the second diagnosis was exact — there was
 * a real wrapper, `.f-pay-code-group`, keeping four of funnel.css's
 * rules (see the de-leak above).
 *
 * WHAT ELSE WAS WRONG. This slot had no horizontal padding of its own,
 * so everything portaled into it ran edge to edge against the card's
 * border: an underlined link touching the card's bottom edge, which is
 * a stray hyperlink glued to a receipt, and — open — boxes whose sides
 * coincided exactly with the card's sides, which is what makes a nested
 * box look nested.
 *
 * WHAT THE STANDARD IS. Stripe's own hosted Checkout, Shopify checkout
 * and Amazon all do one thing: the code is a quiet ROW INSIDE the order
 * summary, above the total, in the summary's padding and rhythm — never
 * a floating link, never a card inside a card. Opening it swaps the row
 * for a field in place.
 *
 * The row's own look (typography, the "+", 52px, the open pair) now
 * lives in the shared rules above, so this block is only what makes it
 * a row OF THIS CARD rather than a control of a form.               */
.sb-white .ob-code {
  display: flex;
  flex-direction: column;
  /* A row of the card. The hairline below separates it from the total;
   * `.ob-incw`'s own bottom border does the job above. The children
   * carry the card's 16px side padding, so nothing touches its border. */
  border-bottom: 1px solid var(--hair);
}
/* One frame passes before the payment panel portals into this node.
 * Without this the card would draw a hairline across nothing. */
.sb-white .ob-code:empty {
  display: none;
}
/* No border of its own here — the card supplies it — so the hover
 * feedback is the underline the resting state gave up. */
.sb-white .ob-code .f-pay-code-toggle:hover,
.sb-white .ob-code .f-pay-code-toggle:focus-visible {
  color: var(--navy);
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 4px;
}
/* The open pair sits on the card's own 16px, so the field is inset from
 * the border instead of touching it. */
.sb-white .ob-code .f-pay-code {
  padding: 10px 16px 12px;
}
/* Applied: a receipt line, full-bleed. This card already speaks in
 * full-width tinted bands — `.ob-incw`'s lavender — so a green one
 * belongs to it. The same green as a rounded pill inset inside a
 * rounded card is the nested box again, in a colour. */
.sb-white .ob-code .f-pay-discount {
  padding: 13px 16px;
  border-radius: 0;
  background: var(--okbg);
  color: var(--okfg);
}
.sb-white .ob-code .f-pay-discount-remove {
  color: var(--okfg);
}

/* ── The total's own bottom, when it is the card's last row ───────
 *
 * Founder: *"is there not enough space below the Total today line? it
 * looks like the text is touching the border below."* It was 2px, and
 * they are right.
 *
 * `.ob-total` carries `padding: 14px 16px 2px` because something was
 * always meant to follow it — "You save $30.00", with its own 14px
 * bottom. But that line HIDES the moment a code moves the total (two
 * savings stacked in one card is arithmetic nobody asked for), and it
 * never renders at all for a session with no compare-at anchor. In both
 * cases the total became the last row in the card, 2px above the border,
 * with a 32px number on `line-height: 1` — so the digits' own descender
 * space is all that was left. Moving the discount row ABOVE the total
 * made this visible on every applied code.
 *
 * `:last-child` rather than a blanket padding: when the saving IS there
 * it still owns the bottom, and the two can never both add it. */
.sb-white .ob-total:last-child {
  padding-bottom: 16px;
}

/* ── The sheet's close ────────────────────────────────────────────────
 *
 * Founder: "should there be a small back option on this?" Yes. Tapping
 * the scrim works, but at 88% sheet height the scrim is a ~100px strip
 * at the top of the screen — undiscoverable, and for a 55–65+ buyer
 * effectively absent. Top RIGHT, because "Love it?" holds the left.
 *
 * 44px, as everything tappable in this look is, and it sits above the
 * sheet's own scroll so it stays reachable however long the summary
 * gets.                                                               */
.sb-white .sh-close {
  position: sticky;
  top: 0;
  align-self: flex-end;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: -14px -6px -32px 0;
  border: 0;
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink2);
  cursor: pointer;
}
.sb-white .sh-close:hover {
  background: var(--ground);
  color: var(--navy);
}
.sb-white .sh-close:focus-visible {
  outline: none;
  box-shadow: var(--ring);
}
.sb-white .sh-close svg {
  width: 20px;
  height: 20px;
}

/* ── P1-556's two doors, in the White look ───────────────────────
 *
 * The first cut of §2.4 had ONE link that went straight to the answers
 * summary — i.e. "Change Music" with no choice offered and no lyrics
 * door at all. That shape has already been measured: when it shipped in
 * P1-538 redo activity fell from 13.7% of everyone who heard a song to
 * 9.3% (z = -5.7) and the lyrics door was used 4 times against a
 * baseline of 5-10. Restored to the founder's ruling — Redo first, then
 * two options — in both places it appears.
 *
 * ⚠ THE REVEAL PAGE IS LIGHT, NOT NAVY. I wrote these chips white-on-
 * transparent first, reasoning from the `rv-*` block near the top of
 * this file, where the stage IS navy. It is overridden further down:
 * `.sb-white .rv { background: linear-gradient(180deg, var(--lav) 0,
 * #FFFFFF 440px); color: var(--navy) }` re-themes the whole page light,
 * and every `rv-*` colour with it. So the doors rendered invisible —
 * white text and a white border on white — while every measurement
 * (present, 46px tall, both labels right) passed. Only the screenshot
 * showed it. They now join `.rv-keep button`'s family, which is what
 * "Download the song", "Lyric sheet" and "Share" already are.        */
.sb-white .rv-doors {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.sb-white .rv-doorlead {
  margin: 0;
  /* The same colour the link it replaces carries on this page. */
  color: var(--muted);
  font: 500 16px/1.3 var(--font);
}
.sb-white .rv-doorrow {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
}
/* 44px minimum like everything tappable in this look, and an outline
 * rather than a fill: neither door competes with "Unlock the full song"
 * directly above them. */
.sb-white .rv-door {
  min-height: 46px;
  padding: 0 18px;
  border: 1.5px solid var(--line);
  border-radius: 100px;
  background: #FFFFFF;
  color: var(--navy);
  font: 600 16px/1.2 var(--font);
  cursor: pointer;
}
.sb-white .rv-door:hover {
  border-color: var(--navy);
  background: var(--surface);
}

/* The same three classes serve the unlock sheet, where the doors sit on
 * their own rows under the footer rather than in Redo's slot. Squeezed
 * into that slot they FITTED — every button on screen, 48px tall — and
 * looked wretched: "Hear it again" broke over two lines and the pair
 * stacked in a column beside it at 390px. Measured fine, looked wrong;
 * the screenshot is the only thing that said so. */
.sb-white .sh .rv-doors {
  margin-top: 2px;
}

/* ── The second-song offer: two leaks the founder walked into ────────
 *
 * Both found on their production walk, 2026-09-21, and both are the same
 * shape as the discount block's: a cream rule that the white look only
 * PARTLY overrode. `ExtraSongOffer` is restyled rather than rewritten
 * (deliberately — a CSS rule cannot drop a button or lose a handler),
 * and the cost of that choice is exactly this: every cream declaration
 * the white sheet does not name survives.
 *
 * ── 1. "the button text is flowing off the screen" ─────────────
 *
 * The label read "es, add my second song — $27.9" — clipped at BOTH
 * edges, i.e. wider than the phone. A specificity collision:
 *
 *   funnel.css  .funnel-scope .f-extra-cta          (0,2,0)
 *               white-space: nowrap
 *               font-size: clamp(14px, 4.2vw, 17px)   ← the safety valve
 *               padding: 0 10px
 *
 *   flow.css    .funnel-scope .sb-white .f-btn       (0,3,0)  ← wins
 *               font: 700 20px/1.2                    ← kills the clamp
 *               padding: 0 28px                       ← and widens it
 *
 * So the white lane kept "this label must never wrap" and threw away
 * "shrink the type on a narrow phone", which is the only reason the
 * cream one fits. The label carries a PRICE, and funnel.css is right
 * that a price must not wrap mid-figure — so the fix restores the valve
 * rather than allowing the wrap. Three classes deep, to beat `.f-btn`.  */
.funnel-scope .sb-white .f-extra-cta,
.sb-white .f-extra-cta {
  /* Same shape as the cream rule, sized for this look's bigger button:
   * 20px where there is room, down to 14px on a 320px phone. */
  font-size: clamp(14px, 4.2vw, 20px);
  padding-left: 12px;
  padding-right: 12px;
}

/* ── 2. "the name in italics does not look good" ────────────────
 *
 * Right, and there was a second fault they did not name: the white sheet
 * styles `.f-extra-kicker` but never its `em`, so the cream rule
 * survived in full —
 *
 *   .funnel-scope .f-extra-kicker em { font-style: italic; color: var(--sb-cta) }
 *
 * and `--sb-cta` is #A85549, the CREAM brand's terracotta. So the buyer's
 * own name was rendering in italic terracotta inside an otherwise blurple
 * uppercase line: the wrong brand's colour on the one word that should
 * feel like it was written for them.
 *
 * Founder: "to grab their attention, I think the name is important."
 * So the name stops being decoration and starts being the loudest thing
 * on the line:
 *
 *   * NOT uppercase. This is the real readability win. The parent line is
 *     `text-transform: uppercase`, which turned "Ajinkya" into
 *     "AJINKYA" — and a name is a proper noun, not a label. Uppercasing
 *     one costs the word-shape a reader recognises, and costs most on
 *     exactly the names a form letter would get wrong.
 *   * NOT italic, and navy rather than another brand's accent.
 *   * Heavier and a little larger than the label it sits in, so the eye
 *     lands on the name first and "ONE LAST THING" reads as the aside it
 *     is.                                                              */
.funnel-scope .sb-white .f-extra-kicker em,
.sb-white .f-extra-kicker em {
  font-style: normal;
  text-transform: none;
  color: var(--navy);
  font-weight: 800;
  font-size: 1.2em;
  /* A label wants 0.1em of tracking; a name does not. */
  letter-spacing: 0.01em;
}

/* ── "Where should we send your song?" gets its OWN rules ───────────
 *
 * Founder's production walk, 2026-09-21, on the $0 checkout: the "Your
 * name" label overlapped the input's border and "Send my song" overlapped
 * the email address.
 *
 * A THIRD failure mode, distinct from the other two this walk found. Not
 * a missing white rule, and not a surviving cream one — a BORROWED one.
 * `OfferVerifyStep`'s white branch reached for classes built on other
 * screens, and inherited assumptions that do not hold here:
 *
 *   .gs-card  the WAIT page's card. `display: flex; overflow: hidden`
 *             and NO padding and NO gap, because on that page its
 *             children (`.gs-rows` and friends) each supply their own.
 *             Used as a form container, the label, the input, the email
 *             row and the button therefore all sat flush against the
 *             card's edges with nothing between them — exactly the
 *             overlap in the screenshot.
 *   .gs-sig   the wait page's two-column signature ROW:
 *             `display: grid; grid-template-columns: auto minmax(0,1fr)`.
 *             Used as a plain <label> over an input, a grid is simply
 *             the wrong box.
 *   .gp-foot  the GIFT page's centred footer text. Used for the hint
 *             lines, which is why "Double check to confirm your email is
 *             accurate" rendered centred while the labels beside it were
 *             left-aligned — visible in the founder's photo.
 *
 * So this form now says what it is. Borrowing a class is borrowing every
 * assumption behind it, and on a screen that only appears after a $0
 * checkout nobody was going to notice until a buyer did.              */
/* NO BOX OF ITS OWN. Founder: *"there is no need for the outer
 * rectangular border box. Right now, this is looking ugly."*
 *
 * Right, and it was costing more than looks. On a 390px phone this card
 * was THREE nested bordered boxes: `.fl-main` (40px of padding),
 * `.pp-card` (42px), `.pp-form` (34px), and then the grey email row
 * (34px) — 150px of a 390px screen gone before a single character, and
 * the reason the address could not fit on one line.
 *
 * `.pp-card` around it is already a card. This stays as a LAYOUT
 * container — the column and its gap — and gives its 34px back. */
.sb-white .pp-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* A label, not a row. Left-aligned, above its field, with the breathing
 * room a grid was never going to give it. */
.sb-white .pp-form .pp-label {
  display: block;
  margin: 0 0 2px;
  color: var(--navy);
  font: 600 16px/1.3 var(--font);
  text-align: left;
}
/* The second label sits in a row with its "Edit" link, so it must not
 * add its own bottom margin there. */
.sb-white .pp-form .qz-inline .pp-label {
  margin: 0;
}
/* The hints: left-aligned with the fields they explain, and quiet. */
.sb-white .pp-form .pp-hint {
  margin: 0;
  color: var(--muted);
  font: 500 15px/1.4 var(--font);
  text-align: left;
}
/* The address we are about to send to is the one thing on this card the
 * buyer must actually READ, so it is ink, not a hint. */
.sb-white .pp-form .pp-shown {
  margin: 0;
  color: var(--navy);
  font: 600 16px/1.4 var(--font);
  text-align: left;
  word-break: break-all;
}
/* The button earns its own space away from the address above it. */
.sb-white .pp-form .qz-btn {
  margin-top: 10px;
}

/* ── FOUR ICONS WITH NO SIZE ─────────────────────────────────
 *
 * Founder, on the Change Lyrics page: "the page opens and it is all
 * broken." One rule short, and here is the mechanism, because it will
 * happen again otherwise.
 *
 * 22 of the look's 24 icon components are declared like this —
 *
 *     <svg viewBox="0 0 24 24" aria-hidden="true">
 *
 * with a viewBox and NO width or height. An SVG with no intrinsic size
 * and no CSS size falls back to the CSS default for a replaced element:
 * 300x150px. So `IconPen` rendered 150px tall inside a
 * `border-radius: 100px` button — the giant oval in the founder's
 * screenshot, with "Edit it myself" shoved out of it.
 *
 * The look sizes icons per context, and does it 52 times. These four
 * were missed. Found by sweeping every icon render against every
 * `svg` rule in BOTH white stylesheets — a first sweep read only
 * flow.css and produced a false positive on `.lp-stars`, which
 * landing.css sizes perfectly well.
 *
 * TWO OF THESE ARE ON THE QUIZ, and both are the tick that appears when
 * an answer is SELECTED — which is why neither the founder nor I had
 * seen them: you have to choose something and then look. They would have
 * met every buyer the moment the switch went on.
 *
 * `flex: none` on each, as `.qz-btn svg` already does, so a flex parent
 * cannot squash them either.                                          */
.sb-white .qz-smart__acts button svg {
  flex: none;
  width: 20px;
  height: 20px;
}
.sb-white .qz-opt svg {
  flex: none;
  width: 20px;
  height: 20px;
}
.sb-white .qz-pill svg {
  flex: none;
  width: 18px;
  height: 18px;
}
.sb-white .fl-textlink svg {
  flex: none;
  width: 18px;
  height: 18px;
}


/* ── THE WAIT RAIL'S SOUND PILL (P1-618, founder walk) ────────────────
 * Founder: *"if we keep them played on by default with sound off and
 * sound on icon at top just like we have on homepage… For videos, the
 * reason I say that we should leave it on play by default is because
 * right now the play button is hiding the face and the most important
 * thing."*
 *
 * So the rail autoplays muted and the 52px play disc no longer sits over
 * anybody's face. What replaces it is this: the homepage's pill, in the
 * same corner, at the size a 152px card can carry.
 *
 * 34px, not the 46px the WCAG target size wants. The card is 152px wide;
 * a 46px disc is a third of it and lands on the face we just uncovered.
 * The trade is paid for elsewhere — nothing here is reachable ONLY by
 * this pill: every clip plays without it, and the CAPTION below each
 * card names the person, so a visitor who never finds the pill has lost
 * sound, not content. `top`/`right` at 8px keeps the whole disc clear of
 * the 16px corner radius.
 *
 * Pressed = blurple, because this is the flow lane and `--blurple` is
 * its one accent; the landing's pill goes cyan, which belongs to the
 * landing's palette and would read as a different product here. */
.sb-white .rx-snd {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 3;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(10, 37, 64, 0.62);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: #FFFFFF;
  cursor: pointer;
  transition: background 160ms ease, color 160ms ease;
}
.sb-white .rx-snd svg {width: 17px; height: 17px}
.sb-white .rx-snd:hover {background: rgba(10, 37, 64, 0.82)}
.sb-white .rx-snd:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.9);
}
.sb-white .rx-snd[aria-pressed="true"] {
  background: var(--blurple);
  color: #FFFFFF;
}
/* The play disc is now the EXCEPTION — a clip that is genuinely not
 * running (reduced motion, or a refused autoplay). It keeps its old size
 * because in that state it is the only thing to do with the card. */

/* ── PLAIN LYRICS, ON THE SCREEN WHERE THEY ARE READ CLOSELY ──────────
 * Founder: *"the lyrics shown on the Edit Lyrics page, I think, should be
 * simple, plain, editable, and readable, like how we have on the live
 * website."*
 *
 * The live page's own numbers (`funnel.css .f-lyrics`): 17px, line-height
 * 1.75, the page's sans, left-aligned, one block. Repainted in the white
 * lane's tokens and nothing else changed — "like the live website" is
 * meant literally, because that page has been read by every buyer who
 * ever changed a word and nobody has complained about reading it.
 *
 * `.fl-ly span` is `display: block` with a `min-height`, so a blank line
 * between stanzas keeps its height instead of collapsing — the stanza
 * breaks are the only structure left once `displayLyrics` has taken the
 * [Verse] tags out, and they are what makes a sheet skimmable.
 *
 * NOT the Lora sheet (`.ly`). That one stays exactly as it is on the
 * reveal and the gift page, where it is the thing being unveiled. */
.sb-white .fl-ly {
  display: flex;
  flex-direction: column;
  font: 400 17px/1.75 var(--font);
  color: var(--navy);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.sb-white .fl-ly span {display: block; min-height: 1em}

/* ── "QUESTIONS PEOPLE ASK HERE" (P1-618, founder walk) ───────────────
 * Founder: *"is there any way we can answer these questions on this
 * page? I don't want them to lose the song after they come on this
 * page."*
 *
 * Three `<details>` in the same `.ab` accordion the unlock sheet uses, so
 * a buyer meets one accordion in this funnel and not two. A top rule and
 * a gap are all this needs on top of that: the questions are the last
 * thing on the page and must read as a footer, not as a fourth offer. */
.sb-white .ty-help {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 8px;
  padding-top: 22px;
  border-top: 1px solid var(--hair);
}
.sb-white .ty-help > .fl-h {font-size: 22px}
.sb-white .ty-help .ab-a p {
  margin: 0;
  font: 400 17px/1.5 var(--font);
  color: var(--ink2);
  text-wrap: pretty;
}
.sb-white .ty-help .ab-a strong {color: var(--navy); font-weight: 700}
.sb-white .ty-help .pp-form {margin-top: 4px}

/* `.ty-url` is GONE — the raw link is no longer printed on screen.
 * Founder: *"I think the links look ugly. Instead of that, we should just
 * keep the button… and open share options wherever they want to send
 * it."* Right, and better than prettier: a link sent to your own
 * WhatsApp or Notes survives the tab closing, which 70 characters of
 * base62 on screen does not — nobody retypes that off a screenshot.
 * See the `share` callback in `WhiteThanksHelp`. */
.sb-white .ty-help .fl-btn2 {min-height: 52px; font-size: 17px}

/* The green confirmation, reused from the top of this page. Inside an
 * answer it needs its own margin — the `.ab-a` padding is the card's,
 * not the line's. */
.sb-white .ty-help .gs-okline {margin: 0}

/* ── THE EMAIL, READ BACK AT A SIZE AN OLDER EYE CAN CHECK ────────────
 * Founder: *"the edit button for email should be in front of email, and
 * email should be, I think, in a slightly bigger font and a separate
 * field, so it's clearly readable as they have typed. Our visitors are
 * elderly people."*
 *
 * The row itself is `.qz-picked` — the quiz's own settled-value row, so
 * nothing new is invented and the buyer meets a shape they already know.
 * These three rules are only what `.qz-picked` never had to handle,
 * because the quiz only ever put SHORT words in it ("Pop", "Female
 * voice"):
 *
 *   1. `min-width: 0` on the text column. In a flex row a child's
 *      default `min-width: auto` refuses to shrink below its content, so
 *      a long address would push "Edit" off the card rather than wrap.
 *      This is the single most common flex overflow there is.
 *   2. `overflow-wrap: anywhere` on the value — an address has no spaces
 *      to break at. NOT `break-all`, which would hyphenate a short
 *      address that fits perfectly well.
 *   3. `flex: none` on the link, so "Edit" keeps its full 44px target
 *      whatever the address does. An older thumb loses that fight
 *      otherwise.
 *
 * The value stays at `.qz-picked__v`'s own 19px — the same size as the
 * name field directly above it, which is the comparison the founder was
 * actually making. It is a token, not a number typed here, so the two
 * cannot drift apart later. */
/* A COLUMN, NOT A ROW — and that is the fix for "the email should be in
 * a single line".
 *
 * It used to be a flex ROW: the address and "Edit" as siblings with
 * `flex: 1 1 13em` and `flex-wrap`, so whether Edit dropped to its own
 * line decided how much width the address had. 13em sits close enough to
 * a phone's available width that small changes flip it, and they flipped
 * the wrong way: MEASURED, at 390px the address fitted on one line, and
 * removing padding to give it MORE room made it wrap — because the wider
 * row let Edit back onto it and took 78px away. A layout that gets worse
 * when you give it space is not a layout.
 *
 * So the competition is removed rather than tuned. The label and Edit
 * share the top line (both short, both fixed); the address owns the one
 * below and gets the whole box. It needs 185px and now has 204px even at
 * 320px — one line at every size, with Edit still right beside it, which
 * is what the founder asked for to begin with. */
.sb-white .pp-form .pp-picked {
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
}
.sb-white .pp-form .pp-picked__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 28px;
}
.sb-white .pp-form .pp-picked .qz-picked__v {
  font-size: 20px;
  /* 500, not `.qz-picked__v`'s own 700, AND THE REASON IS A SCREENSHOT.
   * Every number passed at 700: 20px, on the address row, contrast
   * 14.7:1, no overflow at 52 characters. And the render broke
   * `ajinkyathete@gmail.com` after the "o", stranding a single "m" on a
   * second line — because at 700 that string is ~250px in a ~246px
   * column. `overflow-wrap: anywhere` had done its job (nothing spills)
   * and the result was still unreadable, which is the whole point of
   * this card: an older buyer checking their own address one character
   * at a time cannot do it if the address is snapped in half.
   * 500 is ~12% narrower and fits. It is also the right weight for the
   * job — bold is emphasis, and this is data to be read. */
  font-weight: 500;
  overflow-wrap: anywhere;
}

/* ── THE LYRICS PAGE'S "WANT SOMETHING CHANGED?" BLOCK ────────────────
 * Founder: *"the buttons look off and editing themselves is confusing as
 * well."*
 *
 * The buttons were `.qz-smart__acts` — byte for byte `.qz-pill`, the
 * quiz's ANSWER CHIP (1.5px hairline, 100px radius, white). That class
 * earns its shape in the quiz, where it holds name alternatives to pick
 * between; wrapping two actions in it made them read as options to weigh.
 * They are now one blurple `.qz-btn` and one `.fl-textlink`, which is
 * what every other action pair in this look is.
 *
 * These rules are only the column: the card is `.rv-card`, which was
 * built for the lyric sheet and has no opinion about stacked controls. */
.sb-white .fl-ask {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: stretch;
}
.sb-white .fl-ask .fl-p {text-wrap: pretty}
.sb-white .fl-ask__box {min-height: 132px}
/* The text link centres itself under a full-width button rather than
 * hanging off the left edge of a stretched column. */
.sb-white .fl-ask .fl-textlink {align-self: center}
/* Beside the label, not above it. `.fl-textlink` is a plain button, so
 * an icon inside it stacks — the same omission that put the pencil over
 * "Edit it myself" in the founder's screenshot. */
.sb-white .fl-textlink {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.sb-white .fl-textlink svg {flex: none; width: 18px; height: 18px}

/* ── THE FOOTER IS OPAQUE, NOT 97% OPAQUE ─────────────────────────────
 * In the founder's screenshot a line of lyrics ghosts through the sticky
 * footer under the blurple button. `.qz-foot` is
 * `background: rgba(255,255,255,.97)` — the mockup's value, and on a
 * page whose content scrolls UNDER it that 3% is enough to read text
 * through. It looks like a rendering fault rather than a translucency
 * effect, and there is nothing behind it worth seeing. */
.sb-white .qz-foot {background: var(--page)}

/* ── THE WAIT PAGE'S STATUS BLOCK IS DARK ─────────────────────────────
 * Founder, twice. The first time I talked them out of it and changed the
 * TYPE SIZE instead, arguing that a dark block at the top of a white
 * page is the learned signal for a warning. Their answer, on seeing it:
 *
 *   "what you have done is you just increased the font size and made two
 *    lines into three. That is what I was not talking about. I liked the
 *    earlier box, and the size earlier was perfect. No need to make that
 *    box bigger. What I wanted is, instead of the white background, can
 *    we use the dark background for that particular tab?"
 *
 * So the sizes are reverted to exactly what they were (17/18px `.ws-now`,
 * 16px `.ws-pct`, the `.gs-h` untouched) and the block goes dark, which
 * is what was asked for both times.
 *
 * ⚠ DARK MEANS EVERY CHILD, and that is the whole risk here — the same
 * failure that shipped white-on-lavender icons earlier in this ticket
 * (INS-136). This block has seven coloured parts, all of them tuned for
 * a lavender-to-white card: the equaliser bars, the ring around them, the
 * headline, the caption, the progress track, its fill, and the
 * percentage. Every one is re-stated below rather than left to inherit,
 * because a child that keeps its light-mode colour on a navy card is
 * invisible and passes every geometric assertion while being so.
 *
 * `--navy2` / `--onnavy2` / `--cyan` already exist for exactly this — the
 * reveal's dark stage uses them — so no new colour enters the look. */
.sb-white .ws--mini {
  background: var(--navy);
  border-color: var(--navy2);
  box-shadow: 0 18px 40px -30px rgba(10, 37, 64, .8);
}
/* The headline and the caption. */
.sb-white .ws--mini .ws-now {color: #FFFFFF}
.sb-white .ws--mini .ws-when {color: var(--onnavy2)}
/* The orb: a translucent disc on navy rather than a white one, so it
 * reads as part of the card instead of a hole in it. Its equaliser bars
 * and its pulsing ring both go cyan — blurple on navy is 1.7:1. */
.sb-white .ws--mini .ws-orb {
  background: rgba(255, 255, 255, .08);
  border-color: rgba(255, 255, 255, .18);
  box-shadow: none;
}
.sb-white .ws--mini .ws-orb::before {border-color: rgba(0, 212, 255, .35)}
.sb-white .ws--mini .ws-orb i {background: var(--cyan)}
/* The progress track and its fill. The track has to be light enough to
 * read as an empty container on navy, and the fill bright enough to read
 * as progress against it. */
.sb-white .ws--mini .ws-bar {background: rgba(255, 255, 255, .16)}
.sb-white .ws--mini .ws-bar i {background: linear-gradient(90deg, var(--cyan), #7FE9FF)}
.sb-white .ws--mini .ws-pct {color: var(--cyan)}
/* READY state: the green tick orb keeps its green — it is already a
 * strong colour on navy — but the checkmark needs to stay white. */
.sb-white .ws--mini.ws--ready .ws-orb--ok {
  background: var(--green);
  border-color: var(--green);
  color: #FFFFFF;
}

/* ── AN ICON IN A BUTTON THAT HAD NEVER HELD ONE ──────────────────────
 * `.fl-btn2` and `.qz-link` had NO `svg` size rule, because until now
 * nothing had put an icon inside either. The moment one went in, the
 * button rendered 118px tall at 320px, 174px at 390px and 207px at
 * 430px — taller on a WIDER screen, which is the tell.
 *
 * An `<svg>` with a `viewBox` but no width/height attribute and no CSS
 * size has no intrinsic size, so it falls back to the CSS default for a
 * replaced element: 300x150px. In a flex row its width gets squeezed by
 * the row and its HEIGHT does not, so the button grows to 150px of icon
 * plus padding — and grows further as the row gives the icon more width
 * to keep its ratio. It is the same trap that sized four flow icons
 * wrong earlier in P1-618, and the reason is worth keeping: a missing
 * size on an SVG does not render small, it renders enormous.
 *
 * Every other icon-bearing class in this sheet already has its rule
 * (`.qz-btn`, `.qz-back`, `.ws-go`, `.fl-textlink`, `.qz-smart__acts`,
 * `.qz-opt`, `.qz-pill`, `.rx-snd`). These are the last two. */
.sb-white .fl-btn2 svg {flex: none; width: 22px; height: 22px}
.sb-white .qz-link svg {flex: none; width: 18px; height: 18px}

/* ── THE "15" IN THE SKIP ICONS ───────────────────────────────────────
 * The only `<text>` inside an SVG in this look, and it needs saying
 * because SVG text does NOT pick up a font from thin air: nothing
 * between it and `.sb-white` sets `font-family`, so without this rule it
 * inherits the page's default rather than ours.
 *
 * The icon it replaced hardcoded `font-family="DM Sans"` — a name that
 * is not registered anywhere, because `next/font` generates its own
 * family name and exposes it as `--white-sans`. So the number rendered
 * in whatever the phone had, at metrics the author never saw, which is
 * part of why it looked wrong next to its neighbour.
 *
 * `--font` is the same token every other string in this sheet resolves
 * through, so there is exactly one place for it to be wrong. */
.sb-white .pl-ctrl svg text {
  font-family: var(--font);
  /* Tabular figures so "15" has the same width as any other two digits
   * a future skip length might use, and so the two mirrored icons are
   * the same width as each other to the pixel. */
  font-variant-numeric: tabular-nums;
}

/* The one line that says WHICH link "Send my song" sends. It has to read
 * as a footnote to the button, not as another sentence of the answer —
 * and `.sb-white .ty-help .ab-a p` (0,3,1) already outranks
 * `.sb-white .fl-small` (0,2,0), so without this it would come out at
 * the answer's own 17px ink. */
.sb-white .ty-help .ab-a .fl-small {
  font-size: 15px;
  line-height: 1.4;
  color: var(--muted);
}

/* ════════════════════════════════════════════════════════════════════
 * P1-621 — THE GIFT PAGE'S COLUMN, as the founder approved on the mockup.
 *
 * What it replaces was counted, not guessed: seven near-identical white
 * cards after the hero, two orphaned lines floating between them with no
 * container, three border treatments, the note open while the lyrics were
 * shut although they are peers, and three buttons in a ragged 1 + 2.
 *
 * READ → KEEP → PASS ON. One card with tabs, one row of three tiles, one
 * quiet footer.
 * ════════════════════════════════════════════════════════════════════ */

/* The special date, above the card rather than wedged between two of
 * them. It is context for what follows, so it sits with it. PR 2 moves it
 * onto the cover, where the mockup has it. */
.sb-white .gp-date {
  margin: 2px 0 -4px;
  text-align: center;
  font: 500 16px/1.45 var(--font);
  color: var(--muted);
}

.sb-white .gt {
  border-radius: 20px;
  background: var(--page);
  box-shadow: 0 0 0 1px var(--hair);
  overflow: hidden;
}
.sb-white .gt-tabs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  background: var(--surface);
  border-bottom: 1px solid var(--hair);
}
.sb-white .gt-tabs button {
  min-height: 56px;
  padding: 0 12px;
  border: 0;
  background: none;
  color: var(--muted);
  font: 700 16px/1.25 var(--font);
  cursor: pointer;
  /* A long sign-off truncates rather than breaking the two-column grid.
   * The TSX already falls back to "The note" over 18 characters, so this
   * is the belt for a name that is short in characters and wide in
   * glyphs. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sb-white .gt-tabs button.is-on {
  background: var(--page);
  color: var(--navy);
  /* Inset rather than a border, so the selected tab does not shift the
   * row by a pixel when it changes. */
  box-shadow: inset 0 -3px 0 var(--blurple);
}
.sb-white .gt-tabs button:focus-visible {
  outline: none;
  box-shadow: var(--ring);
}
/* ── P1-624: A CLOSED CARD IS A REAL STATE ───────────────────────────
 * Founder: *"lyrics tab should be closed by default."*
 *
 * With plain tabs something is always open, so a gift with no note opened
 * straight onto the lyric sheet — a wall of words before the recipient
 * had done anything. P1-556 measured that mistake in another shape:
 * showing the content instead of the door took redo activity from 13.7%
 * to 9.3%.
 *
 * Shut, the tab row is the whole card, so its dividing line has nothing
 * left to divide. */
.sb-white .gt--shut .gt-tabs {
  border-bottom: 0;
}

/* ONE of the two, so no tablist — but a BUTTON, not a label, because its
 * panel can be shut and a control that opens something has to look like
 * one. The +/− is `.ab-q`'s, so this reads the same as the thank-you
 * page's answers. */
.sb-white .gt-one {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 56px;
  margin: 0;
  padding: 0 20px;
  border: 0;
  background: none;
  color: var(--navy);
  font: 700 12px/1.2 var(--font);
  letter-spacing: .16em;
  text-transform: uppercase;
  cursor: pointer;
}
.sb-white .gt-one span::before {
  content: "+";
  font: 500 26px/1 var(--font);
  letter-spacing: 0;
  color: var(--blurple);
}
.sb-white .gt-one.is-on span::before {
  content: "\2212";
}
.sb-white .gt-one:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: 20px;
}

/* ── THE NOTE IS A LETTER ─────────────────────────────────────────────
 * Founder: *"The note sounds very generic. It's an emotional custom
 * message."*
 *
 * It was. It was typeset as body copy at the size of the UI text around
 * it, and the sign-off was a caption. Three things fix that and none of
 * them is a colour: an address line, a bigger serif on a wider measure,
 * and a signature that sits where a signature sits. */
.sb-white .gt-note {
  position: relative;
  margin: 0;
  padding: 26px 24px 24px;
  display: flex;
  flex-direction: column;
}
/* Their words, marked as theirs. Low enough to be texture rather than a
 * glyph you have to read past, and `aria-hidden` by being a ::before. */
.sb-white .gt-note::before {
  content: "\201C";
  position: absolute;
  top: 2px;
  left: 14px;
  font: 500 96px/1 var(--white-serif, 'Lora'), Georgia, serif;
  color: rgba(99, 91, 255, .11);
  pointer-events: none;
}
.sb-white .gt-to {
  position: relative;
  margin: 0 0 12px;
  font: 400 27px/1.15 var(--white-serif, 'Lora'), Georgia, serif;
  letter-spacing: -0.01em;
  color: var(--navy);
}
.sb-white .gt-body {
  position: relative;
  margin: 0;
  font: 400 20px/1.75 var(--white-serif, 'Lora'), Georgia, serif;
  color: #1E3A55;
  white-space: pre-line;
  text-wrap: pretty;
}
/* A SIGNATURE, not a caption. Right-aligned under a short rule with real
 * space above it — that is where a signature sits on a letter, and it is
 * the half that makes the whole block read as one. */
.sb-white .gt-sign {
  align-self: flex-end;
  max-width: 100%;
  margin: 26px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--lavline);
  text-align: right;
  font: 400 21px/1.3 var(--white-serif, 'Lora'), Georgia, serif;
  font-style: italic;
  color: var(--blurple-d);
  overflow-wrap: anywhere;
}
.sb-white .gt-note .rv-more {
  align-self: flex-start;
  margin-top: 12px;
}

.sb-white .gt-ly {
  padding: 22px 20px 24px;
}
/* LEFT, AND NOT BALANCED — in this panel only.
 *
 * `WhiteLyrics` centres its lines with `text-wrap: balance`, which is
 * right on the reveal: there the sheet is full width and it is the thing
 * being unveiled. Inside a tab panel it has ~40px less measure, and
 * balance spends that by splitting a line that fits — "The morning light
 * on Sycamore Street" came out as two, which reads as a lyric break that
 * is not in the song.
 *
 * Scoped to `.gt-ly` rather than changed on `.ly-lines`, because
 * `WhiteLyrics` is the PAYWALL's component too and the founder approved
 * its centring there. Same sheet, one panel that gives it a straight
 * left edge to read down. */
.sb-white .gt-ly .ly {
  text-align: left;
}
.sb-white .gt-ly .ly-lines span {
  text-wrap: pretty;
}
/* The fold's own top padding is gone with the accordion, so the sheet
 * starts where the panel does. */
.sb-white .gt-ly .ly {
  margin: 0;
}

/* ── YOURS TO KEEP: three equal tiles ────────────────────────────────
 * The ragged 1 + 2 implied a hierarchy that does not exist. These are
 * three things a recipient may want, not one thing and two afterthoughts.
 * A grid rather than flex-wrap, so the third tile cannot drop to its own
 * line and re-create the raggedness at a narrow width. */
.sb-white .gt-keep {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.sb-white .gt-keep__h {
  font: 700 12px/1.2 var(--font);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
}
.sb-white .gt-keep__row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.sb-white .gt-keep__row :is(a, button) {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 92px;
  padding: 12px 6px;
  border: 1px solid var(--hair);
  border-radius: 16px;
  background: var(--page);
  color: var(--navy);
  font: 500 14px/1.25 var(--font);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
.sb-white .gt-keep__row :is(a, button):hover {
  background: var(--surface);
}
.sb-white .gt-keep__row :is(a, button):focus-visible {
  outline: none;
  box-shadow: var(--ring);
}
/* Blurple, because these are actions. Sized here rather than left to the
 * viewBox — an unsized SVG in a flex column takes the full width and a
 * 1:1 viewBox makes it just as tall (INS from #628, which drew a 392px
 * heart on a 392px phone). */
.sb-white .gt-keep__row :is(a, button) svg {
  flex: none;
  width: 24px;
  height: 24px;
  color: var(--blurple);
}

/* ── PASS IT ON ──────────────────────────────────────────────────────
 * The QR and the referral together on their own ground, full width,
 * outside `.rv-main`. Both are AFTERWARDS actions: giving them one quiet
 * footer is what stops them competing with the song. */
/* The column's own bottom padding was 48px (64px above 640px), written
 * when the referral link WAS the end of the page. The footer is the end
 * now and carries its own 26px, so that padding became 78px of nothing
 * above a visible band — measured, not guessed. Scoped to `.rv--gift`
 * because `.rv-main` is the paywall's column too. */
.sb-white .rv--gift .rv-main {
  padding-bottom: 0;
}
.sb-white .gt-foot {
  margin-top: 26px;
  padding: 26px 16px calc(32px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--hair);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 18px;
}
.sb-white .gt-qr {
  display: flex;
  align-items: center;
  gap: 16px;
  max-width: 520px;
  width: 100%;
  margin: 0 auto;
}
/* `:is(img, svg)`, because the QR is a data-URL <img> and a rule written
 * for `svg` alone matches nothing — exactly the bug #634 fixed on
 * `.rv-qr`, and the reason this one is not written that way. */
.sb-white .gt-qr :is(img, svg) {
  flex: none;
  width: 84px;
  height: 84px;
  padding: 5px;
  border-radius: 12px;
  background: #FFFFFF;
  box-shadow: 0 0 0 1px var(--hair);
}
.sb-white .gt-qr span {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  font: 400 15px/1.45 var(--font);
  color: var(--muted);
}
.sb-white .gt-qr b {
  font: 700 16px/1.3 var(--font);
  color: var(--navy);
}
.sb-white .gt-foot .rv-make {
  max-width: 520px;
  width: 100%;
  margin: 0 auto;
}
.sb-white .gt-brand {
  margin: 0;
  text-align: center;
  font: 400 14px/1.4 var(--font);
  color: var(--muted);
}

@media (min-width: 640px) {
  .sb-white .gt-foot {
    padding-inline: 24px;
  }
}

/* ════════════════════════════════════════════════════════════════════
 * P1-621 — THE BUYER'S OTHER SIX PHOTOS, in the white look.
 *
 * Founder: *"what happens to the 6 photos the buyer uploads from the
 * order page they receive?"* — nothing did. They have been saved since
 * P1-275 (migration 0059) and handed only to the cream components, so a
 * buyer chose seven images (six here plus the cover, which is its own
 * column) and six of them went nowhere.
 *
 * THE STRUCTURE BELOW IS PORTED, NOT INVENTED, and every line of it is
 * a scar. `gift.css`'s `.sb-gal` rules carry four tickets of findings —
 * P1-275 → P1-277 → P1-283 → P1-284 — about where an aspect-ratio may
 * live before iOS Safari collapses the box. Only the PALETTE changes
 * here. The component itself is the same one (`GiftGallery`, with
 * `prefix="gg"`), so the scroll-sync cannot drift between the looks.
 *
 * WHY A SEPARATE CLASS STEM at all: the white gift page sits INSIDE
 * `.gift-scope` — the gift layout wraps both looks — so
 * `.gift-scope .sb-gal` and `.sb-white .sb-gal` would be (0,2,0) against
 * (0,2,0): equal specificity, settled only by which stylesheet loads
 * last. `funnel.css` already has sixteen collisions of that shape logged
 * as debt. This does not add a seventeenth.
 * ════════════════════════════════════════════════════════════════════ */

.sb-white .gg-wrap {
  display: flex;
  flex-direction: column;
  gap: 12px;
  /* Full width, out past `.rv-main`'s 20px: on a phone the track is one
   * photo per screen and the 86% slide leaves a sliver of the next one.
   * Card padding either side would eat exactly that sliver, which is the
   * only thing telling a recipient to swipe. */
  margin-inline: -20px;
}
.sb-white .gg-h {
  padding-inline: 20px;
  font: 700 12px/1.2 var(--font);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
}
.sb-white .gg {
  width: 100%;
}
.sb-white .gg-track {
  display: flex;
  gap: 10px;
  padding: 0 20px 2px;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 20px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.sb-white .gg-track::-webkit-scrollbar {
  display: none;
}
.sb-white .gg-slide {
  /* 86%, not 100%: the sliver of the next photo is what tells a
   * recipient there IS a next photo. Dots alone do not carry that. */
  flex: 0 0 86%;
  scroll-snap-align: start;
  /* THE RATIO LIVES ON THE FRAME, and the frame is a plain <div> with a
   * definite width. P1-283 put it on the <img> instead: Chrome was
   * happy, iOS Safari was not — an aspect-ratio on a replaced element
   * whose natural size is not known yet (`loading="lazy"`, off screen)
   * collapsed the box, and the founder saw six empty strips. P1-284
   * settled it here. Do not move it. */
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: 16px;
  overflow: hidden;
  /* A MOUNT, NOT A GAP. Nothing is cropped — `object-fit: contain`
   * letterboxes instead, because faces sit in the top third of a phone
   * photo and a centre crop takes the chin and the wall behind it
   * (P1-277). The letterbox therefore has to read as a deliberate mount,
   * so it is the look's own ground rather than white-on-white. */
  background: var(--ground);
  box-shadow: 0 14px 32px -18px rgba(10, 37, 64, .35);
}
.sb-white .gg-slide img {
  /* Absolutely positioned, so the box comes from the frame's edges
   * rather than from a percentage resolving against a height the frame
   * is still working out (P1-277's cycle) or from the image's own
   * natural size (P1-283's Safari collapse). `inset: 0` is unambiguous
   * in every engine, and object-fit finally has a real box. */
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.sb-white .gg-dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 7px;
  margin-top: 2px;
}
.sb-white .gg-dot {
  width: 7px;
  height: 7px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--line);
  cursor: pointer;
  transition: width 200ms ease, background-color 200ms ease;
}
.sb-white .gg-dot[aria-current="true"] {
  width: 20px;
  background: var(--blurple);
}
.sb-white .gg-dot:focus-visible {
  outline: none;
  box-shadow: var(--ring);
}
@media (prefers-reduced-motion: reduce) {
  .sb-white .gg-dot {
    transition: none;
  }
}

@media (min-width: 620px) {
  /* Horizontal scrolling is hostile to a mouse, so the same frames
   * become a grid. `auto-fit`, not `1fr 1fr`: with a single photo a
   * fixed two-column grid left it at half width beside an empty column,
   * which reads as a broken layout (P1-275 follow-up). auto-fit
   * collapses the empty track — one photo fills the row, two sit side by
   * side, three go 2 + 1. */
  .sb-white .gg-wrap {
    margin-inline: 0;
  }
  .sb-white .gg-h {
    padding-inline: 0;
  }
  .sb-white .gg-track {
    display: grid;
    gap: 12px;
    padding: 0;
    overflow: visible;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  }
  .sb-white .gg-slide {
    flex: none;
  }
  .sb-white .gg-dots {
    display: none;
  }
}


/* ════════════════════════════════════════════════════════════════════
 * P1-625 — THE LYRIC EDITOR, back to the page that worked.
 *
 * Founder: *"I want exactly what we had earlier. By earlier, I mean
 * before switching to these new colors and everything."* — the cream
 * funnel's `LyricsClient`, repainted. Then: *"let's go with Courier
 * Prime"* and *"the edit options, I think, should be at the top."*
 *
 * The complaint that started it was about size: *"I think the fonts are
 * the same size for everything."* Counted, they nearly were — heading 30,
 * body 19, lyrics 17, button 19, link 17. Four of five within two pixels,
 * all in one typeface, so the lyrics did not read as a separate thing
 * from the interface talking about them.
 *
 * FOUR LEVELS INSTEAD, and a different family for the one that matters:
 *
 *   heading            28  sans bold
 *   instruction        16  sans, muted
 *   section labels     11  sans bold, uppercase, tracked, blurple
 *   THE LYRICS         16  MONO, 1.85 line-height
 *
 * MONO MEANS DRAFT, LORA MEANS FINISHED. The editor is typed; the reveal
 * and the gift page are set. THAT SYSTEM IS GONE as of 2026-09-21 —
 * the founder asked for the simple font on this page, so the editor is
 * the look's own sans now. The reveal's Lora sheet is still untouched,
 * which keeps the useful half of the distinction: the finished thing is
 * set in a serif, the working copy is not.
 * ════════════════════════════════════════════════════════════════════ */

/* The sheet, and the textarea, in the same face at the same size — so
 * tapping "Edit it myself" does not change the shape of what you are
 * reading. The white page had the sheet in DM Sans 17 and the box in Lora
 * 19: two faces and two sizes for one document.
 *
 * NOT MONO ANY MORE. P1-625 set this in Courier Prime on a
 * draft-versus-finished argument — typed means editable, set means done.
 * The founder overruled it: *"let's not use the typewriter font. Let's
 * use the simple font."* So the look's own sans, which was already
 * loaded and needs no fourth family for one screen.
 *
 * 17px/1.8 rather than the body's 19px/1.5: slightly smaller and more
 * tightly led than the page around it, so the sheet still reads as a
 * DOCUMENT INSIDE the page rather than as more page. That separation is
 * what the mono was doing; this is the quiet version of it. */
.sb-white .fl-ly,
.sb-white .qz-area.lyp-edit {
  font: 400 16px/1.75 var(--font);
}
/* ── AND THE SHEET GETS ITS MARGINS ──────────────────────────────────
 * Founder: *"The lyrics below are actually very close to the border on
 * the left as well as the right... It is touching the left and right
 * borders and definitely not looking good."*
 *
 * They were touching, exactly. The card is `.rv-card`, which carries NO
 * padding of its own — the same trap that put the ask block's hint 1px
 * from the border in P1-631. Its two children here are `.lyp-card__h`,
 * which has `padding: 0 18px`, and `.fl-ly`, which had none. So the
 * heading was inset and the words it introduced were not.
 *
 * 18px to match the header exactly, so the sheet's left edge lines up
 * with "YOUR LYRICS" above it rather than nearly lining up.
 *
 * WORTH RECORDING WHY I MISSED IT: my P1-631 probe wrote the sheet as
 * `rv-lyrics fl-ly`, and `.rv-lyrics` DOES carry padding. The real
 * component renders `fl-ly` alone. A hand-written fixture that is one
 * class off from the component is not a test of the component — the same
 * mistake, twice in one night. Copy the markup, do not retype it.
 *
 * The textarea needs nothing: `.qz-area` already has `padding: 16px`. */
.sb-white .fl-ly {
  padding: 0 18px 20px;
}
.sb-white .fl-ly {
  color: var(--navy);
}

/* ── THE DIFF. The one thing the white repaint lost. ──────────────────
 * The removed line struck through, the line that replaced it marked,
 * both inline so a swap reads as a swap. P1-456 read 148 revision
 * requests: two thirds are one wrong word or line — exactly what a full
 * sheet hides.
 *
 * The highlight is `inline` inside a block line, so it hugs the words
 * rather than the column. Lavender rather than the cream page's amber,
 * because in this look the tint IS the "look here" ground (`.ly-ch` uses
 * it for the chorus). */
.sb-white .fl-ly__new {
  display: inline;
  margin: 1px -6px;
  padding: 1px 6px;
  border-radius: 6px;
  background: var(--lav2);
  box-shadow: inset 0 0 0 1px var(--lavline);
  font-weight: 700;
}
.sb-white .fl-ly__old {
  display: inline;
  color: var(--line);
  text-decoration: line-through;
  text-decoration-color: var(--line);
}

/* ── THE DOORS, AND THEY ARE TWO MODEST PILLS ─────────────────────────
 * The cream page had `.f-ghost` + `.f-ghost-strong`: two small
 * side-by-side buttons, left-aligned. The white repaint made it a
 * full-width outlined button plus a centred text link — a lot of
 * ceremony for "I fixed a typo", and it pushed the sheet down the page.
 *
 * Back to a row. `flex-wrap`, so at 320px they stack rather than
 * squashing the labels. */
/* ── THE ASK BLOCK, PORTED FROM THE CREAM PAGE ───────────────────────
 * Founder, on a screenshot of the live page: *"The buttons and the text
 * are all touching the borders, and it is looking really, really bad.
 * One button is without a background, and the other button has a
 * background. I think the button and text font are the same size."*
 *
 * Three faults, and all three are mine from P1-625.
 *
 * 1. NOTHING TOUCHES A BORDER BY ACCIDENT — the container is
 *    `rv-card fl-ask`, and `.rv-card` carries NO padding: on the paywall
 *    its children (`.rv-card__h`, `.rv-lyrics`) each bring their own
 *    `padding: 0 18px`. `.fl-ask`'s children are a bare `<p>` and a
 *    `<div>`, so they sat flush against the border. The card gets the
 *    padding here, once, rather than every future child remembering.
 *
 * 2. TWO BUTTONS, ONE STYLE. The cream page uses two `.f-ghost` — same
 *    hairline pill, same size, left-aligned — and the founder asked for
 *    that page. P1-625 made one of them a blurple `.is-go` on the
 *    argument that a pair of equals reads as a choice to weigh. That
 *    argument was wrong here: these two ARE equals. "Tell us what to
 *    change" and "Edit it myself" are two routes to the same outcome,
 *    not a recommendation and a fallback, and dressing one as primary
 *    told the buyer we had a preference we do not have.
 *
 * 3. THE TYPE SCALE. The hint was `.fl-p` — 19px, the body size — beside
 *    16px buttons and a 30px heading, so the hint and the buttons read
 *    as one weight. The cream page's hint is 15px and muted. Matched.
 *
 * Metrics taken from `funnel.css`, not invented: `.f-ghost` is 48px tall,
 * `0 20px`, `1.5px` hairline, `999px` radius, white ground;
 * `.f-inline-actions` is `flex-wrap` with a 10px gap; `.f-inline-left`
 * left-aligns it; the hint is 15px muted. */
.sb-white .rv-card.fl-ask {
  padding: 18px;
  gap: 10px;
}
.sb-white .fl-ask .fl-ask__hint {
  margin: 0;
  font: 400 15px/1.5 var(--font);
  color: var(--muted);
  text-wrap: pretty;
}
.sb-white .fl-ask__row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: flex-start;
}
.sb-white .fl-ask__row button {
  min-height: 48px;
  padding: 0 20px;
  border: 1.5px solid var(--line);
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--navy);
  font: 500 16px/1 var(--font);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.sb-white .fl-ask__row button:hover:not(:disabled) {
  border-color: var(--navy);
}
.sb-white .fl-ask__row button:disabled {
  opacity: .5;
  cursor: default;
}
.sb-white .fl-ask__row button svg {
  flex: none;
  width: 16px;
  height: 16px;
}
/* `.is-go` no longer paints differently on THIS row — see fault 2
 * above. The class stays in the markup because the Save/Make-the-change
 * button still needs to be addressable (it is the one that is disabled
 * on an empty field), it just is not dressed as a primary any more. */
.sb-white .fl-ask__row button:focus-visible {
  outline: none;
  box-shadow: var(--ring);
}

/* The card head: 16/600 sentence case, as the cream page had it — not
 * the uppercase letterspaced label the repaint used. A quiet title, not
 * a system category. */
.sb-white .lyp-card__h {
  display: flex;
  align-items: center;
  gap: 9px;
  min-height: 52px;
  padding: 0 18px;
  border-bottom: 1px solid var(--hair);
  background: var(--surface);
  font: 600 16px/1 var(--font);
  color: var(--navy);
}
/* ── THE HEADER NOW HOLDS A CONTROL ──────────────────────────────────
 * It was a decorative label; it now carries "Edit", so the row becomes
 * label-left / action-right. The label is wrapped in its own <span> so
 * the flex row has two children rather than three loose ones (the icon
 * would otherwise be spaced away from its own words). */
.sb-white .lyp-card__h {
  justify-content: space-between;
}
.sb-white .lyp-card__h > span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.sb-white .lyp-editlink {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 0 2px;
  border: 0;
  background: none;
  color: var(--navy);
  font: 700 15px/1 var(--font);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1.5px;
  text-decoration-color: #B9C2CE;
  cursor: pointer;
  letter-spacing: 0;
  text-transform: none;
}
.sb-white .lyp-editlink:hover {text-decoration-color:var(--navy)}
.sb-white .lyp-editlink svg {flex:none;width:14px;height:14px;color:var(--blurple)}
.sb-white .lyp-editlink:focus-visible {outline:none;box-shadow:var(--ring);border-radius:8px}

/* ── AND THE SHEET IS TAPPABLE ───────────────────────────────────────
 * Founder: *"If they directly click on the lyrics box, I think they
 * should be able to edit it."*
 *
 * NO `cursor: pointer`. That is the one thing this must not do: a
 * pointer cursor over a block of prose says "this is a link, do not try
 * to select me", and selecting a line to re-read it is a thing buyers
 * genuinely do on this page. So no cursor is set at all — `auto`, which
 * is a text caret over text, measured. The component's `onSheetTap`
 * carries the guards (drag-select and double-click both cancel it), and
 * the "Edit" button above is the honest, keyboard-reachable control.
 *
 * So the only paint here is a hover tint — enough to say "something
 * happens if you tap" without claiming to be a button. Absent for
 * anyone who cannot hover, which is exactly the phone, where the tap is
 * the obvious gesture anyway. */
@media (hover: hover) {
  .sb-white .fl-ly--tap {
    border-radius: 12px;
    transition: background 140ms ease;
  }
  .sb-white .fl-ly--tap:hover {
    background: var(--lav);
  }
}
.sb-white .lyp-card__h svg {
  flex: none;
  width: 18px;
  height: 18px;
  color: var(--blurple-d);
}
/* The header's own second line, which the repaint dropped. */

/* ═══ P1-640 — the consistency set (founder walk, 2026-09-22) ═════════════
 * Five things the founder felt as "inconsistencies" in the new skin, all
 * the same root cause: three ways of drawing the same role. One pill, one
 * text link, one primary button, one settled-row pattern, one way to
 * remove a photo. Appended, not edited in place, so the file's own later-
 * wins order does the work at equal specificity.
 * ───────────────────────────────────────────────────────────────────── */
/* One proof pill. `.tp-pill` was the third pill style in the flow (white,
 * bordered, SHADOWED) and sat above the step-7 title where every other
 * step puts its phase label. It now wears `.qz-proof`'s tint and lives in
 * the email card (WhiteQuiz), centred by the rule this file already had. */
.sb-white .tp-pill {background:var(--tint);border-color:var(--tint);box-shadow:none;color:var(--blurple-d);font:600 15px/1.2 var(--font)}
/* One text-link style — five weights and sizes across the quiz, the wait
 * page, the sheet and the thank-you page were one role drawn five ways. */
.sb-white :is(.qz-link, .qz-row__c, .gs-chg, .sh-foot button, .ty-link, .rv-more, .pp-lbl button) {font:700 16px/1.2 var(--font);color:var(--blurple-d);text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:1.5px}
/* One primary button: the unlock button matches `.qz-btn` (64px, 14px). */
.sb-white .rv-unlock {min-height:64px;border-radius:14px;box-shadow:0 14px 28px -14px rgba(99,91,255,.9)}
/* The done photo row: the × on the thumbnail's corner. */
.sb-white .gs-thumbwrap {position:relative;display:block;width:44px;height:44px}
.sb-white .gs-rmx {position:absolute;top:-8px;right:-8px;display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:2px solid #FFFFFF;border-radius:50%;background:var(--navy);color:#FFFFFF;cursor:pointer;box-shadow:0 4px 10px -4px rgba(10,37,64,.6)}
.sb-white .gs-rmx svg {width:12px;height:12px}
.sb-white .gs-rmx:hover {background:#12355A}
.sb-white .gs-rmx:focus-visible {outline:3px solid rgba(99,91,255,.45);outline-offset:1px}
/* The keepsakes on the song page are locked, and say so. */
.sb-white .rv-keepwrap {display:flex;flex-direction:column;gap:8px}
.sb-white .rv-keep__k {margin:0;display:inline-flex;align-items:center;gap:6px;font:700 13px/1.3 var(--font);letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
.sb-white .rv-keep__k svg {width:14px;height:14px}

/* ═══ P1-642 — the wait page's reviews rail ═══════════════════════════════
 * Under the reaction clips: the same swipe rail (snap, no scrollbar), text
 * only. One score in the heading with Trustpilot's stars; no stars per card. */
.sb-white .wr {display:flex;flex-direction:column;gap:8px;margin-top:18px;padding-top:24px;border-top:1px solid var(--hair);min-width:0;max-width:100%}
.sb-white .wr-h {margin:0;display:flex;align-items:center;gap:8px;font:700 16px/1.3 var(--font);color:var(--navy)}
.sb-white .wr-p {margin:0 0 6px;font:400 15px/1.4 var(--font);color:var(--muted);text-wrap:pretty}
.sb-white .wr-row {display:flex;gap:12px;overflow-x:auto;scroll-snap-type:x mandatory;scroll-padding-inline:20px;overscroll-behavior-x:contain;margin:0 -20px;padding:4px 20px 12px;scrollbar-width:none;-ms-overflow-style:none}
.sb-white .wr-row::-webkit-scrollbar {display:none}
.sb-white .wr-card {flex:0 0 280px;margin:0;scroll-snap-align:start;display:flex;flex-direction:column;gap:10px;padding:16px;border-radius:16px;background:var(--surface);border:1px solid var(--hair)}
.sb-white .wr-q {margin:0;font:400 15px/1.5 var(--font);color:var(--ink2);display:-webkit-box;-webkit-line-clamp:8;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
.sb-white .wr-q::before {content:"\201C"}
.sb-white .wr-q::after {content:"\201D"}
.sb-white .wr-by {display:flex;flex-direction:column;gap:2px;font:400 14px/1.3 var(--font);color:var(--muted)}
.sb-white .wr-by b {font-weight:700;color:var(--navy)}
.sb-white .wr-src {margin-top:2px;font:700 11.5px/1.3 var(--font);letter-spacing:.06em;text-transform:uppercase;color:#7A8A9C}
@media (min-width:700px) {
  .sb-white .wr-row {margin:0;padding:4px 0 12px;scroll-padding-inline:0}
}

/* ═══ P1-644 — the unlock screen: one page where two sheets were ═══════════
 * Renders IN PLACE of the song page (WhiteReveal), so the page scrolls
 * normally, there is no sheet scrolling inside a page, and the pay button
 * sticks to the bottom of the viewport. `.ob*` (the order card) and
 * `.sh-stick` (the pay bar) are the sheet's own rules, reused; what is
 * new is the frame around them and the two-column split from 900px. */
.sb-white .un {min-height:100vh;min-height:100dvh;display:flex;flex-direction:column;background:var(--page);color:var(--navy)}
.sb-white .un-top {position:sticky;top:0;z-index:5;display:grid;grid-template-columns:76px minmax(0,1fr) 76px;align-items:center;min-height:56px;padding:0 8px;background:rgba(255,255,255,.97);border-bottom:1px solid var(--hair)}
.sb-white .un-back {justify-self:start;display:inline-flex;align-items:center;gap:2px;min-height:44px;padding:0 12px 0 4px;border:0;background:none;color:var(--navy);font:500 17px/1 var(--font);cursor:pointer}
.sb-white .un-back svg {width:22px;height:22px}
.sb-white .un-back:focus-visible {outline:none;box-shadow:var(--ring);border-radius:10px}
.sb-white .un-h {margin:0;text-align:center;font:700 17px/1.2 var(--font);color:var(--navy);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sb-white .un-body {width:100%;max-width:600px;margin:0 auto;padding:16px 20px 40px;display:flex;flex-direction:column;gap:14px;box-sizing:border-box}
.sb-white .un-left {display:none}
.sb-white .un-main {display:flex;flex-direction:column;gap:14px;min-width:0}
.sb-white .ob-thumb {display:block;width:44px;height:44px;border-radius:12px;object-fit:cover}
.sb-white .ob-inc2 {list-style:none;margin:0;padding:2px 0 4px;display:flex;flex-direction:column;gap:7px}
.sb-white .ob-inc2 li {display:flex;align-items:center;gap:8px;font:400 15px/1.35 var(--font);color:var(--navy)}
.sb-white .ob-inc2 svg {flex:none;width:16px;height:16px;color:var(--okfg)}
/* The pay bar sticks to the bottom of the PAGE now, not of a sheet:
 * `.sh-stick` was written for `.sh`'s 22px padding and -24px overhang. */
.sb-white .un .sh-stick {bottom:0;margin:0 -20px;padding:12px 20px calc(18px + env(safe-area-inset-bottom,0px))}
.sb-white .un-how {display:flex;flex-direction:column;gap:10px}
.sb-white .un-how__h {margin:0;font:700 15px/1.3 var(--font);color:var(--navy)}
.sb-white .un-how span {display:flex;align-items:center;gap:10px;font:400 15px/1.4 var(--font);color:var(--ink2)}
.sb-white .un-how i {flex:none;display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:50%;background:var(--surface);border:1px solid var(--hair);color:var(--navy);font-style:normal}
.sb-white .un-how i svg {width:16px;height:16px}
/* A `@media` query, deliberately — the paywall's `@container` rules never
 * matched (INS: no container-type ancestor) and this screen must not
 * repeat that. */
@media (min-width:900px) {
  .sb-white .un-top {grid-template-columns:200px minmax(0,1fr) 200px;min-height:64px;padding:0 40px}
  .sb-white .un-body {max-width:1100px;display:grid;grid-template-columns:minmax(0,460px) minmax(0,520px);gap:64px;justify-content:center;align-items:start;padding:40px 48px 64px}
  .sb-white .un-left {display:flex;flex-direction:column;gap:22px;min-width:0}
  .sb-white .un-main .un-review {display:none}
  .sb-white .un .sh-stick {position:static;margin:0;padding:6px 0 0;box-shadow:none}
}

/* ═══ 2026-09-22, after the founder's preview walk ════════════════════════
 * A picked chip does not change width. The tick used to appear inline
 * (+18px, +8px gap, −4px margin, −6px padding = +16px), so the row
 * re-wrapped under the buyer's thumb. Now the tick sits over the left
 * padding and the padding moves from right to left: the chip keeps its
 * width, nothing moves. */
.sb-white .qz-pill {position:relative}
.sb-white .qz-pill[aria-pressed="true"] {padding:8px 10px 8px 30px}
.sb-white .qz-pill .qz-tick {display:block;position:absolute;left:9px;top:50%;width:16px;height:16px;margin:-8px 0 0;opacity:0;transition:opacity 120ms ease}
.sb-white .qz-pill[aria-pressed="true"] .qz-tick {opacity:1}
/* Step 1's "Free to hear · Pay only if you love it" is one quiet line,
 * not a two-line pill: no box, 15px, the note glyph in blurple. */
.sb-white .qz-proof {padding:0;border-radius:0;background:none;color:var(--ink2);font:500 15px/1.3 var(--font);gap:8px;white-space:nowrap}
.sb-white .qz-proof svg {width:18px;height:18px;color:var(--blurple)}
/* The unlock screen: "Included free" a shade stronger, and the two ways
 * out under the review are buttons, not underlined words. */
.sb-white .un .ob-incw {background:#EEEDFF;border-color:#DEDBFF}
.sb-white .un-acts {display:grid;grid-template-columns:1fr 1fr;gap:10px}
.sb-white .un-act {display:inline-flex;align-items:center;justify-content:center;min-height:50px;padding:0 14px;border:1.5px solid var(--line);border-radius:100px;background:#FFFFFF;color:var(--navy);font:700 16px/1.2 var(--font);cursor:pointer;text-align:center}
.sb-white .un-act:hover {border-color:var(--navy)}
.sb-white .un-act:focus-visible {outline:none;box-shadow:var(--ring)}


/* ═══ 2026-09-22, the founder's second walk ═══════════════════════════════
 * "Who's it from?": the pills fill the tinted box in two columns again —
 * hugging pills left the right half of the box empty ("too much space on
 * the right side"). The two long ones span both columns. A full-width
 * pill has no width to keep, so its tick goes back inline beside the
 * centred label instead of over the left padding. */
.sb-white .qz-from .qz-pills {display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
.sb-white .qz-from .qz-pill {justify-content:center;width:100%;min-width:0}
.sb-white .qz-from .qz-pill[data-v="__type"], .sb-white .qz-from .qz-pill[data-v*=" and "] {grid-column:1/-1}
.sb-white .qz-from .qz-pill[aria-pressed="true"] {padding:8px 20px}
.sb-white .qz-from .qz-pill .qz-tick {position:static;margin:0 0 0 -4px;width:18px;height:18px}
/* The example card reads as an example: a small caps label, the quote
 * smaller and italic, both a step quieter than the buyer's own words. */
.sb-white .qz-eg figcaption {font:700 12.5px/1.3 var(--font);letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}
.sb-white .qz-eg p {font:italic 400 15.5px/1.5 var(--font);color:var(--muted)}
/* The line under Continue fits one line on a phone. */
.sb-white .qz-under {font-size:15px}

/* ═══ 2026-09-22, the founder's second walk: the reviews rail ═════════════
 * "It looks all gray right now." White cards on a lavender band, a blurple
 * opening quote, the relationship as a small tag, "Trustpilot review" in
 * Trustpilot's green. Still no stars per review and never "verified" —
 * the rail's rules (P1-642). */
.sb-white .wr {margin:18px -20px 0;padding:22px 20px 2px;border-top:0;background:var(--lav);max-width:none}
.sb-white .wr-h {font-size:17px}
.sb-white .wr-p {color:var(--ink2)}
.sb-white .wr-row {padding:6px 20px 20px}
.sb-white .wr-card {position:relative;padding:40px 16px 16px;background:#FFFFFF;border-color:var(--lavline);box-shadow:0 12px 26px -20px rgba(74,64,209,.5)}
.sb-white .wr-card::before {content:"\201C";position:absolute;left:14px;top:4px;font:700 46px/1 var(--font);color:var(--blurple)}
.sb-white .wr-q {font-size:15.5px;color:var(--navy)}
.sb-white .wr-q::before, .sb-white .wr-q::after {content:none}
.sb-white .wr-by {flex-direction:row;flex-wrap:wrap;align-items:center;gap:6px 8px;font-size:14px}
.sb-white .wr-by b {font-size:15px}
.sb-white .wr-who {display:inline-flex;align-items:center;padding:3px 9px;border-radius:100px;background:var(--tint);color:var(--blurple-d);font:700 12.5px/1.2 var(--font)}
.sb-white .wr-where {color:var(--muted)}
.sb-white .wr-src {flex-basis:100%;margin-top:4px;color:#1E8E5A}

/* ═══ 2026-09-22, the founder's third walk: the payment step ═════════════
 * The wallet row hides once Stripe says there are no wallets; the pay
 * bar's edge is a hairline instead of a heavy shadow; the line under the
 * button is one line. */
.sb-white .f-pay-express--none {display:none}
.sb-white .un .sh-stick {box-shadow:0 -1px 0 var(--hair),0 -14px 24px -20px rgba(10,37,64,.25)}
.sb-white .un .fine {font-size:14px}

/* ═══ 2026-09-22, the founder's pick from the five payment styles ═════════
 * The order on a lavender panel (5): no border, no shadow — "the shadows
 * were creating the problem". The extras as receipt lines with FREE where
 * a price would sit (3). Under the pay button the guarantee alone, as a
 * green line with a shield (2). `.ob-free` was already the old FREE pill
 * of the retired list, so the lines are `.ob-lines`. */
.sb-white .un .ob--panel {border:0;box-shadow:none;background:var(--lav)}
.sb-white .un .ob--panel .ob-code {border-bottom-color:var(--lavline)}
.sb-white .ob-lines {list-style:none;margin:0;padding:6px 16px;border-top:1px solid var(--lavline);border-bottom:1px solid var(--lavline);display:flex;flex-direction:column}
.sb-white .ob-lines li {display:flex;align-items:center;gap:8px;padding:5px 0;font:400 14px/1.35 var(--font);color:var(--ink2)}
.sb-white .ob-lines svg {flex:none;width:14px;height:14px;color:var(--okfg)}
.sb-white .ob-lines span {flex:1;min-width:0}
.sb-white .ob-lines b {flex:none;font:700 12px/1 var(--font);letter-spacing:.06em;text-transform:uppercase;color:var(--okfg)}
.sb-white .un-guar {margin:0;display:flex;align-items:center;justify-content:center;gap:8px;padding:9px 12px;border-radius:12px;background:var(--okbg);color:var(--okfg);font:700 14.5px/1.3 var(--font)}
.sb-white .un-guar svg {flex:none;width:18px;height:18px}

/* The no-photo thumbnail on the lavender panel: a white square with the
 * panel's own hairline (the old lavender fill was one shade off the panel
 * and vanished), the recipient's initial in the card's own navy, or the
 * note glyph when there is no name yet. */
.sb-white .un .ob--panel .ob-ic {background:#FFFFFF;border:1px solid var(--lavline);box-sizing:border-box}
.sb-white .ob-ic--mono {font:700 20px/1 var(--font);color:var(--navy);letter-spacing:-.02em}

/* Founder, on the built panel: "The tick mark itself suggests it's
 * included, right?" — the three FREE labels go; the word stays once, as a
 * small-caps line above the ticks. The hairlines move to the wrapper. */
.sb-white .ob-linesw {padding:10px 16px 6px;border-top:1px solid var(--lavline);border-bottom:1px solid var(--lavline)}
.sb-white .ob-lines {padding:0;border:0}
.sb-white .ob-lines__k {margin:0 0 2px;font:700 11.5px/1.3 var(--font);letter-spacing:.1em;text-transform:uppercase;color:var(--blurple-d)}

/* Founder: "the discount code is too much in the face … not standard
 * practice to show it that boldly." On the panel it is a quiet grey text
 * link — no plus box, 14px, underlined — present for the buyer with a
 * code, invisible to the one without. The applied (green) row is unchanged. */
.sb-white .un .ob--panel .f-pay-code-toggle {min-height:40px;padding:0 16px;gap:0;color:var(--muted);font:500 14px/1.2 var(--font);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px}
.sb-white .un .ob--panel .f-pay-code-toggle::before {content:none}
.sb-white .un .ob--panel .f-pay-code-toggle:hover {color:var(--navy)}

/* Founder: the guarantee under the pay button is mockup 3's band, as it
 * was drawn — the shield, the guarantee in bold, "One payment, no
 * subscription." beneath, on the soft lavender band. */
.sb-white .un-band {margin:4px 0 0;display:flex;align-items:center;gap:12px;padding:12px 14px;border-radius:14px;background:var(--lav);border:1px solid var(--lavline)}
.sb-white .un-band > svg {flex:none;width:24px;height:24px;color:var(--blurple)}
.sb-white .un-band__t {display:flex;flex-direction:column;gap:2px;min-width:0}
.sb-white .un-band__t b {font:700 15.5px/1.25 var(--font);color:var(--navy)}
.sb-white .un-band__t span {font:400 13.5px/1.3 var(--font);color:var(--muted)}

/* Founder: the boxed band "looks like it is competing with the checkout
 * button". Same words, no box: a footnote under the button, centred, the
 * guarantee in medium navy, the second line muted. */
.sb-white .un-band--quiet {display:block;margin:0;padding:4px 0 0;text-align:center;background:none;border:0}
.sb-white .un-band--quiet > svg {display:inline-block;vertical-align:-4px;width:18px;height:18px;margin-right:6px}
.sb-white .un-band--quiet .un-band__t {display:inline}
.sb-white .un-band--quiet .un-band__t b {display:inline;font:600 14.5px/1.3 var(--font)}
.sb-white .un-band--quiet .un-band__t span {display:block;font:400 13.5px/1.3 var(--font)}
