/* ════════════════════════════════════════════════════════════════════
   THESWEETNOTE.COM — B2B platform marketing site
   ────────────────────────────────────────────────────────────────────
   SaaS-platform visual identity:
     · Confident sans-serif (Inter) over editorial serifs
     · Darker hero (deep navy ground) for the SaaS-platform feel
     · Structural / grid-based layout
     · Code blocks for API examples
     · Sharper buttons (no soft-glow gradients)

   Tokens come from tokens.css (navy + gold + paper). The SaaS-style
   proportions and typography are scoped to this file only.

   This CSS is self-contained: no relative imports beyond ./tokens.css
   and the Google Fonts CDN.
   ════════════════════════════════════════════════════════════════════ */

/* ───── RESET + BASE ─────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html {
  font-size: 16px;
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-size-adjust: 100%;
  /* Belt-and-suspenders with body's overflow-x:hidden below: the CSS
     overflow-propagation rule that's supposed to lift body's overflow-x
     up to the viewport doesn't reliably suppress horizontal scroll for a
     longhand-only (`overflow-x`, no `overflow-y`) declaration, so an
     absolutely-positioned element that bleeds past the viewport (e.g. a
     decorative glow, an edge-anchored tooltip) can still open a stray
     horizontal scroll even with body clipped. Setting it here directly
     closes that gap without touching vertical scroll or sticky/fixed
     positioning. Found via the 375/390/768 mobile pass (S2, 2026-08-17)
     on faq.html's glossary-tooltip overflow at 768px. */
  /* ⚑ clip, NOT hidden — FINISHING the 2026-08-26 d3 sticky fix (founder
     2026-09-10: "the filter bar still shakes on iOS"). That pass changed `body`
     and `.cl-main` to `clip` for exactly this reason but deliberately left the
     root on `hidden`, reasoning that "the root's overflow is the viewport's, and
     sticky against the viewport scrollport works." That is true in Chrome — and it
     is why the headless sweep of the filter bar came back clean, one tidy .is-stuck
     flip across 6,371px. Safari is the exception: `overflow-x: hidden` on the ROOT
     computes to `hidden auto`, which makes <html> a scroll container, and a sticky
     element inside a non-viewport scroller is repositioned on the main thread every
     frame instead of by the compositor. That lag IS the wobble, and it is why the
     paint-cost fixes in the previous pass (gradients, box-shadow transition, forced
     layout on resize) helped but could not remove it — they were treating symptoms
     of a main-thread sticky.
     `clip` clips the identical horizontal bleed, establishes NO scroll container,
     and does not force the other axis to auto — so the viewport goes back to being
     the scroller and sticky is composited again. `hidden` is declared first as the
     fallback for Safari < 16, which does not know `clip` and would otherwise drop
     the declaration and let the stray horizontal scroll back in. */
  overflow-x: hidden;
  overflow-x: clip;
}
body {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  color: var(--sn-ink-dark);
  background: var(--sn-paper);
  min-height: 100vh;
  /* clip, NOT hidden (d3 sticky fix, 2026-08-26): `overflow-x: hidden`
     computes to `hidden auto`, which made BODY a scroll container — and a
     position:sticky descendant sticks to its NEAREST scroll-container
     ancestor, so every sticky element in body (portal .cl-topbar, the
     dashboard .dl-detail-controls filter bar, the examples copies) was
     silently pinned to a body scrollport that never scrolls, i.e. sticky
     never engaged (measured headless 2026-08-26: topbar left the viewport
     at scrollY 600 on dashboards.html). This is the same trap already
     documented — and solved the same way — on .cl-main in
     clients/styles/client.css ("clip, not hidden, so it doesn't create a
     scroll container or break sticky/position"). `clip` clips horizontal
     bleed identically but establishes NO scroll container, so sticky
     resolves against the viewport again. html's own overflow-x:hidden
     above stays — the root's overflow is the viewport's, and sticky
     against the viewport scrollport works. */
  overflow-x: clip;
}

/* SaaS-site emphasis is delivered via WEIGHT, not italic. Browsers'
   default UA stylesheet renders <em> italic — override across the site
   so any <em> in marketing copy reads upright + bold. */
h1 em, h2 em, h3 em, h4 em, h5 em, p em {
  font-style: normal;
  font-weight: 700;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }

/* Global keyboard-focus indicator (WCAG 2.4.7). A site-wide safety net so
   every link and button shows a visible focus ring under keyboard nav;
   components with their own :focus-visible (sn-term, sn-toc, sn-btn, etc.)
   override this by specificity. :focus-visible (not :focus) keeps the ring
   off mouse clicks. The cyan ring is 3.68:1 on white — above the 3:1 floor
   WCAG sets for focus indicators. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--sn-spark-deep);
  outline-offset: 2px;
  border-radius: 3px;
}

/* Skip-to-content link (WCAG 2.4.1 Bypass Blocks). Visually hidden until
   keyboard focus, then slides in at top-left. Mirrors the portal's
   .cl-skip-link so the public site and the app behave identically. First
   focusable element on every marketing page; targets <main id="main">. */
.sn-skip-link {
  position: absolute; top: -48px; left: 12px; z-index: 9999;
  padding: 9px 16px; font-size: 13px; font-weight: 600;
  background: var(--sn-ink-darkest, #0A2540); color: #FFFFFF;
  border-radius: 0 0 8px 8px; text-decoration: none;
  transition: top 0.15s ease;
}
.sn-skip-link:focus { top: 0; outline: 2px solid var(--sn-spark-deep); outline-offset: 2px; }

/* ───── DESIGN TOKENS — Stripe-aligned (v9, April 28, 2026) ──────────
     Direct port of Stripe's homepage visual language:
       - Pure white #FFFFFF body, #F6F9FC alternating section bg
       - Slate-navy #0A2540 headers, #425466 cool-grey body text
       - Stripe-purple #635BFF primary accent (brand + CTAs + emphasis)
       - Cool gradient (purple → blue → cyan → mint), never warm
       - Hairline cool-grey #E3E8EE borders on white cards
       - Inter sans-serif throughout, weight-only emphasis (no italic)

     The SaaS site reads as "modern measurement infrastructure" — same
     trust-language as Stripe / Mercury / Linear / Vercel.
     ───────────────────────────────────────────────────────────────────── */
:root {
  --sn-container: 1240px;
  --sn-container-narrow: 880px;
  --sn-radius-sm: 4px;
  --sn-radius-md: 8px;
  --sn-radius-lg: 12px;
  /* Header height — used by every sticky in-page nav (research/methods/
     how-it-works/pricing) so their `top:` offset always clears the
     site header instead of disappearing behind it. The header is
     padding 14px top + 14px bottom + ~32px logo = ~60px. Bumped to 64
     so the sticky nav top edge has a small breathing gap below the
     header bottom border.  */
  --sn-header-h: 64px;
  --sn-shadow-sm: 0 1px 2px rgba(60, 66, 87, 0.04), 0 1px 3px rgba(0, 0, 0, 0.04);
  --sn-shadow-md: 0 4px 12px rgba(60, 66, 87, 0.08), 0 1px 4px rgba(0, 0, 0, 0.04);
  --sn-shadow-lg: 0 16px 48px rgba(60, 66, 87, 0.12), 0 4px 16px rgba(0, 0, 0, 0.04);

  /* ─── INK / SLATE — Stripe's actual text palette ───
     Stripe uses near-black slate for headers and a cool mid-grey for body.
     The cool-toned greys (425466, 697386) read as "technical" and
     "trustworthy" against pure white — what we want here. */
  --sn-ink-darkest: #0A2540;     /* deepest slate — hero dark sections */
  --sn-ink-dark: #0A2540;        /* primary header color — Stripe slate */
  --sn-ink: #1A1F36;             /* slight lift for hover/elevated surfaces */
  --sn-ink-soft: #425466;        /* body text — Stripe's exact body grey */
  --sn-ink-muted: #697386;       /* meta / secondary text */
  --sn-ink-faint: #8792A2;       /* tertiary, captions */

  /* ─── PAPER — pure white + cool light grey (Stripe-exact) ───
     Stripe's body bg is pure #FFFFFF. Section alternation is #F6F9FC
     (the famous "Stripe blue-tinted off-white"). Cards are white with
     a hairline cool-grey border, never warm. */
  --sn-paper: #FFFFFF;           /* primary page background — pure white */
  --sn-paper-deep: #F6F9FC;      /* alternating section bg — Stripe's signature */
  --sn-paper-warm: #EBEEF2;      /* deeper surface for callouts (cool grey) */
  --sn-cream: #FFFFFF;           /* card surfaces — white on Stripe */
  --sn-cream-soft: #F6F9FC;      /* light surface variant */
  --sn-white: #FFFFFF;

  /* ─── LINES — cool grey, Stripe's exact divider ─── */
  --sn-line: #E3E8EE;            /* hairline border — Stripe's exact line */
  --sn-line-soft: rgba(10, 37, 64, 0.06);
  --sn-line-on-dark: rgba(255, 255, 255, 0.10);

  /* ─── ACCENT — NAVY PRIMARY (Stripe-pattern brand color) ───
     Navy is the primary brand commitment color: CTAs, eyebrows,
     link emphasis, focus rings. The visual category research-brand
     competitors don't own — Ipsos / Sapio / Forsta all sit in
     cyan-teal land. Navy primary is the single fastest way to break
     out of "looks like a research brand" and into "modern
     infrastructure" (Stripe / Mercury / Linear / Vercel). */
  --sn-accent: #0A2540;          /* slate navy — primary brand */
  --sn-accent-soft: #15324B;     /* hover — slightly lifted navy */
  --sn-accent-deep: #061827;     /* deepest — for hover-press / dark borders */
  --sn-accent-tint: rgba(10, 37, 64, 0.06);

  /* ─── SPARK — BRIGHT TURQUOISE (the "fresh moment" accent) ───
     The energy color, deployed sparingly: gradient text shimmer, card
     icons, step number badges, pricing dots, card-hover borders, hero
     illustration wash. Navy carries trust; turquoise carries
     interactivity and freshness. Same role Stripe-purple plays inside
     a navy-primary system. */
  --sn-spark: #06B6D4;           /* cyan-500 — bright turquoise */
  --sn-spark-soft: #22D3EE;      /* cyan-400 — lighter for hover/illustrations */
  --sn-spark-deep: #0891B2;      /* cyan-600 — chrome accent (buttons, borders,
                                    icons, large/heading text). 3.68:1 on white:
                                    OK for UI + large text (≥3:1), NOT for small
                                    body links. Use --sn-link for inline text. */
  --sn-link: #0E7490;            /* cyan-700 — AA-compliant link/body-text cyan
                                    (5.3:1 on white). Use for inline <a> text on
                                    light surfaces. Keep --sn-spark-deep for chrome. */
  --sn-spark-tint: rgba(6, 182, 212, 0.10);
  --sn-error: #B33A3A;           /* form-error red — 5.86:1 on white (AA). Was
                                    referenced via fallback in login.html; now a
                                    real token so error text isn't fallback-only. */

  /* ─── VERDICT PALETTE — settled-report decision states ───
     One base per state; the CI illustration and the decision cards on the
     dashboard-reading + after-the-readout playbook pages derive their tints
     and borders from these via color-mix, so the diagram and the cards read
     as one palette. Maps to the engine's resolveState (portal-data.js). */
  --sn-verdict-win: #2F6B48;     /* SIGNIFICANT — CI on the difference clears zero */
  --sn-verdict-equiv: #4A6E82;   /* EQUIVALENT — whole CI inside the ±5pp margin */
  --sn-verdict-warn: #B04A2A;    /* INCONCLUSIVE — spans zero, wider than the margin */
  --sn-verdict-armb: #A85968;    /* second-variation accent in CI illustrations */

  /* ─── CAMPAIGN-STATUS PALETTE — calendar timeline bars + legend ───
     One source of truth for the three calendar bar styles (timeline bar
     classes + legend swatches in clients/campaigns/calendar.html).
     Changing a status color is a one-line edit here. Bars are a single
     solid color — no two-tone outcome tail (it drew a messy vertical line
     down the middle of each outcome row; the Day-30/90 milestones are
     carried by the tick pills instead). */
  --sn-cal-live-a:        #2F6B48;             /* in-flight bar — green start */
  --sn-cal-live-b:        #4F8061;             /* in-flight bar — green end */
  --sn-cal-closed-a:      #697386;             /* closed bar — slate start */
  --sn-cal-closed-b:      #495362;             /* closed bar — slate end */
  --sn-cal-draft-a:       #C9D2DE;             /* draft bar — striped tone A */
  --sn-cal-draft-b:       #DDE4ED;             /* draft bar — striped tone B */

  /* ─── SPECTRUM — navy-anchored, turquoise-bright cool flow ───
     The hero gradient flows navy → mid-blue → turquoise → cyan-bright.
     Navy anchors the dark end; turquoise is the freshness moment. */
  --sn-spectrum-navy: #0A2540;   /* deepest stop — anchors the gradient */
  --sn-spectrum-blue: #0369A1;   /* sky-700 — mid-cool */
  --sn-spectrum-turquoise: #06B6D4; /* the spark stop — bright turquoise */
  --sn-spectrum-cyan: #22D3EE;   /* cyan-400 — lighter */
  --sn-spectrum-mint: #5EEAD4;   /* teal-300 — freshness, used sparingly */

  /* ─── GRADIENTS ───
     Hero illustration: subtle blue → turquoise → cyan flow in the
     BACKGROUND wash. The text gradient flows blue → turquoise → cyan —
     starts where H1 navy text ends, brightens through. Visible against
     the navy text without disappearing into it. */
  --sn-gradient-hero: linear-gradient(120deg,
    var(--sn-spectrum-navy) 0%,
    var(--sn-spectrum-blue) 35%,
    var(--sn-spectrum-turquoise) 70%,
    var(--sn-spectrum-cyan) 100%);
  --sn-gradient-hero-soft: linear-gradient(120deg,
    rgba(10, 37, 64, 0.10) 0%,
    rgba(3, 105, 161, 0.10) 35%,
    rgba(6, 182, 212, 0.12) 70%,
    rgba(34, 211, 238, 0.10) 100%);
  --sn-gradient-text: linear-gradient(95deg,
    var(--sn-spectrum-blue) 0%,
    var(--sn-spectrum-turquoise) 55%,
    var(--sn-spectrum-cyan) 100%);

  /* ─── BACKWARD COMPAT (keep refs valid; map to new tokens) ─── */
  --sn-cool-accent: #FFFFFF;
  --sn-cool-accent-mist: rgba(255, 255, 255, 0.10);
  --sn-gold: var(--sn-accent);
  --sn-gold-light: var(--sn-accent-soft);
  --sn-gold-deep: var(--sn-accent-deep);

  /* ─── SUCCESS / WARN — semantic status colors ───
     Canonical tokens for green/amber alongside spark cyan. The greens
     are emerald-500/700 — bright enough to harmonize with spark cyan
     in a row of status dots, dark enough on white for AAA. The ambers
     are amber-500/700 — warm but not aggressive (this isn't an alert;
     it's a "watch this" signal).

     Surfaces that consume these:
       • clients/insights/dashboards.html — card recency dots
         (active=success, idle=warn) + A/B-arm SIG/n.s. nuance pill
         + window-progress overdue tint.
       • Future: any campaign-status pill that maps to
         green=ACTIVE / amber=IDLE.
       • (retired) the public share-report URL once used this for a
         disabled-button success state — removed 2026-05-30 in favor
         of the authed PDF; listed here only as historical context.
       • clients/settings/security.html — destructive-action ghost
         button (warn).

     If a new surface needs another semantic color (e.g. error red,
     info blue), extend the scale here — don't introduce page-scoped
     vars in component CSS. */
  --sn-success:      #10B981;                    /* emerald-500 — primary green */
  --sn-success-deep: #047857;                    /* emerald-700 — AAA on white */
  --sn-success-tint: rgba(16, 185, 129, 0.10);   /* 10% tint — surface wash */
  --sn-warn:         #F59E0B;                    /* amber-500 — primary warn */
  --sn-warn-deep:    #B45309;                    /* amber-700 — AAA on white */
  --sn-warn-tint:    rgba(245, 158, 11, 0.10);   /* 10% tint — surface wash */

  /* ═════════════════════════════════════════════════════════════════
     DESIGN-SYSTEM USAGE GUIDE — read before editing any component CSS

     The B2B site is built on a fixed vocabulary so every page reads as
     one product. When extending to a new page, do not introduce
     bespoke values — pull from the tokens declared just below.

     COLORS:
       Page bg                → --sn-paper
       Alternating section bg → --sn-paper-deep
       Card surface           → --sn-paper (white) on light bg
       Body text              → --sn-ink-soft
       Headlines              → --sn-ink-dark / --sn-ink-darkest
       Muted / meta           → --sn-ink-muted, --sn-ink-faint
       Borders / hairlines    → --sn-line, --sn-line-soft, --sn-line-on-dark
       Accent (CTA / brand)   → --sn-accent (slate navy)
       Spark (energy / link)  → --sn-spark, --sn-spark-deep
       Gradient text          → --sn-gradient-text
       Dark editorial bands   → --sn-band-dark-bg, --sn-band-dark-edge,
                                --sn-band-dark-text, --sn-band-dark-eyebrow

     TYPE:
       Hero H1                → --sn-text-display-2xl
       Section H2             → --sn-text-display-xl
       Card H3 highlight      → --sn-text-display-lg
       Stat numbers           → --sn-text-display-md / --sn-text-display-mega
       Lede / subhead         → --sn-text-18
       Body                   → --sn-text-15
       Card detail            → --sn-text-13 / --sn-text-14
       Caption / meta         → --sn-text-12
       Eyebrow / mono labels  → --sn-text-11 (mono)
       Tiny mono              → --sn-text-9 / --sn-text-10

     SPACING (4pt base, doubles past space-7):
       Inside card padding    → --sn-space-5 / --sn-space-6
       Card-to-card gap       → --sn-space-3 / --sn-space-4
       Section head margin    → --sn-space-9
       Section vertical pad   → --sn-space-section / --sn-space-section-tight
       Between sub-sections   → --sn-space-7 / --sn-space-8

     RADIUS:
       Tiny chip / dot        → --sn-radius-xs / --sn-radius-sm
       Default card           → --sn-radius-md (8px)
       Pricing / list card    → --sn-radius-lg (12px)
       Glass widget           → --sn-radius-xl (14px)
       Feature card           → --sn-radius-2xl (18px)
       Phone surface          → --sn-radius-3xl (24px)
       Status pill            → --sn-radius-pill

     TRANSITIONS:
       Hover / micro          → --sn-transition-fast
       Card lift / state      → --sn-transition-base
       Section reveal         → --sn-transition-reveal
       (Curve = --sn-ease — Stripe's signature easeOutQuad)

     SHADOWS:
       Subtle card            → --sn-shadow-sm
       Lifted card            → --sn-shadow-md
       Modal / large card     → --sn-shadow-lg
       Glass widget           → --sn-shadow-glass
       Cyan brand glow        → --sn-shadow-glow-cyan
       Card lift (cyan)       → --sn-shadow-card-lift
       Card press (cyan)      → --sn-shadow-card-press

     TRACKING (letter-spacing):
       Hero / megastat        → --sn-tracking-tighter
       Display headlines      → --sn-tracking-tight
       Sub-headlines          → --sn-tracking-snug
       Body emphasis          → --sn-tracking-base
       Mono timestamps        → --sn-tracking-wide
       Mono labels            → --sn-tracking-wider
       Eyebrows (uppercase)   → --sn-tracking-widest
       Proof-band eyebrows    → --sn-tracking-mega

     If a value isn't covered by an existing token, extend the scale at
     the source — don't add a new bespoke value in component CSS.
     ═════════════════════════════════════════════════════════════════ */

  /* ─── TYPOGRAPHY — sans-serif throughout, weight-emphasis only ───
     Stripe is sans-serif headers + sans-serif body. No editorial italic
     display font, no Cormorant. Emphasis is delivered by weight (700/800)
     and gradient text-clip, never by italic. */
  --sn-font-display: 'Inter', system-ui, -apple-system, sans-serif;
  --sn-font-body: 'Inter', system-ui, -apple-system, sans-serif;
  --sn-font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;

  /* ─── SECTION RHYTHM — vertical breathing tokens ───
     Stripe is religiously consistent: ~120px between major sections,
     ~80px for tighter "subsection" stacking, ~48px hero-to-first-section.
     Every page-level section CSS rule should reference these instead
     of bare px values so the whole site can be re-tuned in one place. */
  --sn-space-section:        clamp(72px, 10vw, 120px);
  --sn-space-section-tight:  clamp(56px, 7vw, 88px);
  --sn-space-hero-bottom:    clamp(48px, 6vw, 72px);

  /* ═════════════════════════════════════════════════════════════════
     DESIGN-SYSTEM TOKENS

     Everything below is the canonical vocabulary every page on the
     B2B site should pull from. Do not introduce new arbitrary values
     in component CSS — pick the closest token, or extend the scale
     here and use the new token everywhere. The whole point is that
     a single edit to a token re-tunes every page that consumes it.
     ═════════════════════════════════════════════════════════════════ */

  /* ─── TYPE SCALE — fixed body sizes + responsive display sizes ───
     Body sizes are fixed-px (px values stay consistent across screens);
     display sizes are clamp()'d (scale with viewport for hero impact).
     Use these instead of bare font-size: 14px / 0.875rem etc. */
  --sn-text-9:               9px;        /* mono micro — counter pills, footnote markers */
  --sn-text-10:              10px;       /* mono nano — feed timestamps, KPI footnote */
  --sn-text-11:              11px;       /* eyebrow / fine-print mono */
  --sn-text-12:              12px;       /* caption, supporting metadata */
  --sn-text-13:              13px;       /* small body — card detail */
  --sn-text-14:              14px;       /* small body emphasis */
  --sn-text-15:              15px;       /* body default — Stripe's exact body size */
  --sn-text-16:              16px;       /* body emphasis */
  --sn-text-18:              18px;       /* lede / subhead */
  /* Display sizes scale with viewport — hero gets bigger on big screens */
  --sn-text-display-sm:      clamp(20px, 2vw, 24px);     /* small headline / dashboard tile */
  --sn-text-display-md:      clamp(22px, 2.4vw, 30px);   /* feature stat number */
  --sn-text-display-lg:      clamp(28px, 3vw, 38px);     /* card H3 highlight */
  --sn-text-display-xl:      clamp(36px, 4vw, 48px);     /* section H2 */
  --sn-text-display-2xl:     clamp(44px, 5vw, 60px);     /* hero H1 */
  --sn-text-display-mega:    clamp(56px, 8vw, 96px);     /* proof-band impact stat */

  /* ─── SPACING SCALE — 4pt base, doubles past space-7 ───
     Use these instead of bare px values for padding, gap, margin.
     The whole vertical rhythm of the site is built from these. */
  --sn-space-1:              4px;
  --sn-space-2:              8px;
  --sn-space-3:              12px;
  --sn-space-4:              16px;
  --sn-space-5:              20px;
  --sn-space-6:              24px;
  --sn-space-7:              32px;
  --sn-space-8:              40px;
  --sn-space-9:              48px;
  --sn-space-10:             64px;
  --sn-space-11:             80px;
  --sn-space-12:             96px;
  --sn-space-13:             120px;

  /* ─── RADIUS SCALE — extended from sm/md/lg ─── */
  --sn-radius-xs:            3px;
  /* sm: 4px, md: 8px, lg: 12px already declared above */
  --sn-radius-xl:            14px;       /* glass-card / event-feed widget */
  --sn-radius-2xl:           18px;       /* large feature cards */
  --sn-radius-3xl:           24px;       /* hero illustrations / phone surfaces */
  --sn-radius-pill:          999px;      /* counter pills, status pills */

  /* ─── TRANSITIONS — easing + duration tokens ───
     Stripe's signature curve is cubic-bezier(0.22, 1, 0.36, 1) — an
     easeOutQuad-style decel that feels "settled" rather than springy.
     We use it everywhere motion is involved. */
  --sn-ease:                 cubic-bezier(0.22, 1, 0.36, 1);
  --sn-transition-fast:      150ms var(--sn-ease);
  --sn-transition-base:      240ms var(--sn-ease);
  --sn-transition-slow:      400ms var(--sn-ease);
  --sn-transition-reveal:    700ms var(--sn-ease);

  /* ─── TRACKING — letter-spacing scale ─── */
  --sn-tracking-tighter:     -0.035em;   /* hero / megastat */
  --sn-tracking-tight:       -0.02em;    /* large display headings */
  --sn-tracking-snug:        -0.015em;   /* sub-headlines */
  --sn-tracking-base:        -0.005em;   /* body emphasis */
  --sn-tracking-normal:      0;
  --sn-tracking-wide:        0.04em;     /* small mono timestamps */
  --sn-tracking-wider:       0.06em;     /* mono labels */
  --sn-tracking-widest:      0.10em;     /* uppercase eyebrows */
  --sn-tracking-mega:        0.16em;     /* proof-band eyebrows, "WHAT WE DON'T DO" badges */

  /* ─── ELEVATION — extended glass + dark-band shadow tokens ─── */
  --sn-shadow-glass:
    inset 0 1px 0 rgba(255, 255, 255, 0.95),
    0 1px 2px rgba(10, 37, 64, 0.04),
    0 18px 40px -12px rgba(10, 37, 64, 0.16);
  --sn-shadow-glow-cyan:     0 24px 56px -28px rgba(6, 182, 212, 0.32);
  --sn-shadow-card-lift:     0 18px 48px -22px rgba(6, 182, 212, 0.18);
  --sn-shadow-card-press:    0 0 0 4px rgba(6, 182, 212, 0.06);

  /* ─── DARK-BAND PALETTE — for the two dark-tone editorial moments
     (problem statement at top, dogfood proof near bottom). Keeps both
     bands matching without having to remember the exact gradients. */
  --sn-band-dark-bg:
    radial-gradient(1200px 600px at 30% 0%, rgba(34, 211, 238, 0.12), transparent 60%),
    radial-gradient(1000px 500px at 80% 100%, rgba(6, 182, 212, 0.10), transparent 65%),
    linear-gradient(180deg, #0A2540 0%, #061321 100%);
  --sn-band-dark-edge:
    linear-gradient(90deg, transparent 0%, rgba(34, 211, 238, 0.32) 50%, transparent 100%);
  --sn-band-dark-text:       rgba(255, 255, 255, 0.72);
  --sn-band-dark-text-faint: rgba(255, 255, 255, 0.55);
  --sn-band-dark-eyebrow:    rgba(34, 211, 238, 0.90);
}

/* Logo-mark styling moved below alongside .sn-logo. Use the <img> element
   directly (see line ~365) so the image always loads regardless of CSS
   cascade order. */

/* ─── Article spine ───────────────────────────────────────────────────
   Long-form article pages (research, methods) use a single-column flow
   with multiple sequential sections. A subtle cyan left-border ties
   the sections together as ONE journey instead of reading as stacked
   blocks. Desktop only — on narrow viewports the layout is already
   vertical-flow and a spine would just feel like a hairline against
   the screen edge.

   How-it-works is excluded from this rule — its full-white article
   column reads cleaner without the spine, and the page carries a
   right-side cyan gradient mirroring the homepage hero instead. See
   body.hiw-bg below.
   ─────────────────────────────────────────────────────────────────── */
@media (min-width: 981px) {
  .rs-app > article {
    border-left: 1px solid rgba(10, 37, 64, 0.10);
    padding-left: clamp(28px, 3vw, 44px);
  }
}

/* ─── Promise cards — for the independence claims ─── */
.sn-promise-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
  margin: 40px 0;
}
/* 3-on-top / 2-on-bottom centered variant. Used on the about page where
   there are exactly five values and a balanced pyramid layout reads
   better than five-across or two/three rotated. Falls back to a single
   column on narrow viewports via the min-width clamp on the items. */
.sn-promise-grid.is-3-2-centered {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
.sn-promise-grid.is-3-2-centered > .sn-promise {
  flex: 0 1 calc((100% - 48px) / 3);
  min-width: 280px;
}
@media (max-width: 720px) {
  .sn-promise-grid.is-3-2-centered > .sn-promise {
    flex: 1 1 100%;
  }
}

.sn-promise {
  padding: 32px 28px;
  background: #FFFFFF;
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-md);
  box-shadow: 0 1px 2px rgba(10, 37, 64, 0.04), 0 1px 3px rgba(0, 0, 0, 0.03);
  display: flex;
  flex-direction: column;
  gap: 14px;
  transition: box-shadow 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}
/* When a card opens with a step-num or icon container, give it a touch
   more breathing room before the rest of the content stacks below. The
   icon/step is its own visual moment; the mark + headline + body that
   follow are the "content group" and should read together. */
.sn-promise > .sn-step-num,
.sn-promise > .sn-card-icon {
  margin-bottom: 4px;
}
/* Mark + h3 are tightly related (label + headline of the same point) —
   pull them visually closer than the default card gap. */
.sn-promise-mark + h3 { margin-top: -6px; }
.sn-promise:hover {
  border-color: var(--sn-spark);
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(10, 37, 64, 0.10), 0 4px 8px rgba(0, 0, 0, 0.04);
}
.sn-promise-mark {
  font-family: 'Inter', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sn-ink-dark);
  display: flex;
  align-items: center;
  gap: 8px;
}
.sn-promise-mark::before {
  content: '';
  display: inline-block;
  width: 18px;
  height: 1px;
  background: var(--sn-ink-dark);
}
.sn-promise h3 {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.2;
  color: var(--sn-ink-dark);
}
.sn-promise p {
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--sn-ink-soft);
}

/* ═══════════════════════════════════════════════════════════════════
   STRIPE × DEEPMIND v7 — disciplined motion + cinematic artifacts
   Stripe: single subtle wave gradient in hero (one layer, slow flow).
   DeepMind: auto-advancing brand carousel inside the hero phone mockup.
   Both: count-up motion on stats; bigger hero type.
   ═══════════════════════════════════════════════════════════════════ */

/* ─── Gradient text — navy-anchored, turquoise-bright, weight-only emphasis ───
   Used sparingly: ONE phrase in the hero H1, ONE phrase in the final CTA.
   The gradient starts at sky-blue (lifted off the navy text color so the
   shift is visible) and brightens through turquoise to cyan. No italic —
   emphasis comes from the color shift + the brightness lift. */
.sn-gradient-text {
  background: linear-gradient(95deg,
    var(--sn-spectrum-blue) 0%,
    var(--sn-spectrum-turquoise) 55%,
    var(--sn-spectrum-cyan) 100%);
  background-size: 200% 200%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  /* Use `inline` (not inline-block) so the span flows with surrounding
     text and inline punctuation (e.g. trailing period) doesn't get
     orphaned to its own line. */
  display: inline;
  font-style: normal;
  font-weight: inherit;
  animation: sn-gradient-shimmer 10s ease-in-out infinite alternate;
  /* Webkit clips descenders ('g', 'y', 'p', 'j', 'q') when
     `-webkit-background-clip: text` is applied — the mask box is
     calculated from text bounds without descender allowance. Inline
     padding-bottom extends the painted region so descenders render
     fully without affecting line layout. */
  padding-bottom: 0.08em;
}
@keyframes sn-gradient-shimmer {
  0% { background-position: 0% 50%; }
  100% { background-position: 100% 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .sn-gradient-text { animation: none; background-position: 0% 50%; }
}

/* Hero containment + single subtle wave gradient (Stripe-style) */
.sn-hero {
  position: relative;
  overflow: hidden;
}
.sn-hero::before {
  content: '';
  position: absolute;
  top: -30%;
  right: -20%;
  width: 80%;
  height: 140%;
  background: radial-gradient(ellipse at 70% 30%,
    rgba(34, 211, 238, 0.30) 0%,
    rgba(6, 182, 212, 0.22) 35%,
    rgba(3, 105, 161, 0.12) 65%,
    rgba(10, 37, 64, 0.04) 85%,
    transparent 100%);
  filter: blur(58px);
  z-index: 0;
  animation: sn-wave-flow 24s ease-in-out infinite alternate;
  pointer-events: none;
}
@keyframes sn-wave-flow {
  0% { transform: translate(0, 0) scale(1); }
  100% { transform: translate(-4%, 3%) scale(1.06); }
}
.sn-hero-inner {
  position: relative;
  z-index: 1;
}

/* Hero H1 — sized so the full hero (eyebrow + h1 + lede + CTAs)
   lands above the fold on a typical 13–14" laptop (820–900px viewport
   after the nav bar). Earlier 5.25rem max overshot — at 1440px desktop
   it pushed the CTAs below the first viewport. Tightened max to 3.75rem
   (60px) — still confident statement type, but the CTAs are now
   visible on first paint. */
.sn-hero h1 {
  /* Canonical hero H1 scale — unified across every page so the headline
     reads at the same size site-wide (May 2026 cohesion pass). */
  font-size: clamp(2.5rem, 5vw, 4rem);
  letter-spacing: -0.03em;
  /* Unified to 1.05 to match every other page's hero (how-it-works 1.04,
     methods/research/pricing 1.05) — 1.15 made the home + about headlines
     read visibly looser than the rest even at the same font size. Descenders
     (the gradient-mask clip on "g/j/q/p/y") stay protected by the
     padding-bottom below, same as the other heroes at ~1.05. */
  line-height: 1.05;
  /* Auto-balance line lengths across multi-line H1s so emphasis phrases
     don't break with one orphan word on the last line. Modern browsers
     (Chrome 114+, Safari 17.5+, Firefox 121+) will compute a balanced
     wrap; older browsers fall back to default flow. */
  text-wrap: balance;
  /* Belt-and-suspenders: padding-bottom on the h1 so descenders on the
     last line aren't clipped by overflow:hidden on the hero wrapper. */
  padding-bottom: 0.12em;
}
/* Index hero headline — a hand-set break (after "send") puts "into" at the
   head of line 2. The gradient phrase must be inline, not inline-block, so it
   can share that line with the preceding "into" and wrap word-by-word. The
   base .sn-gradient-text utility (line ~2467) sets display:inline-block, which
   made the whole phrase an unbreakable box that dropped to its own line and
   orphaned "into". Restore inline here (scoped to this headline only); the
   inherited text-wrap:balance then wraps the remainder into even lines that
   never overflow the column on narrow screens. */
.sn-hero h1.sn-hero-headline .sn-gradient-text { display: inline; }
/* The canonical hero scale (clamp 2.5–4rem) was tuned for balanced wrapping,
   but this headline carries a hand-set break, so line 1 ("Turn what you send")
   must fit on ONE line at every width or the forced break produces an ugly
   double-wrap. The hero's left column is only ~1.1fr with a 48px inset, so the
   text box is narrow (~568px at a 1280 viewport) — 64px overflowed it. This
   clamp scales the headline with the viewport so line 1 always fits: ≈31px on
   small phones, up through ≈58px on wide desktops. Scoped to this headline. */
/* Canonical hero scale — was clamp(1.95rem, 4.5vw, 3.6rem), which rendered the
   home headline visibly smaller than every other page's hero. Unified to match
   methods / research / how-it-works. (Mobile handled by the ≤740 override,
   which now lists this selector too.) */
.sn-hero h1.sn-hero-headline { font-size: clamp(2.5rem, 5vw, 4rem); }
.sn-hero .sn-lede {
  font-size: clamp(1.0625rem, 1.5vw, 1.375rem);
  line-height: 1.5;
  max-width: 580px;
  text-wrap: pretty;
}
/* Coda lede — a short punchy follow-up paragraph that hits beneath
   the main hero lede. Tighter top margin to read as connected, with
   a thin accent rule on the left so it visually separates from the
   prose above without feeling like a new section. */
.sn-hero .sn-lede-coda {
  margin-top: 14px;
  padding-left: 14px;
  border-left: 2px solid rgba(10, 37, 64, 0.16);
  font-size: clamp(1rem, 1.35vw, 1.25rem);
  line-height: 1.45;
  color: var(--sn-ink-dark);
}
.sn-hero .sn-lede-coda strong { font-weight: 600; }
/* Subdued inline aside inside a lede — used for clarifying notes that
   shouldn't read at the same weight as the main prose (e.g. "cohort
   tags travel as metadata; recipients never see them"). Smaller,
   muted, with a thin top divider to separate it from the lede. */
.sn-lede-aside {
  display: block;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed rgba(10, 37, 64, 0.14);
  font-size: 0.82em;
  color: var(--sn-ink-soft, rgba(10, 37, 64, 0.62));
  font-style: italic;
}
/* Hero sub-headline — sits between H1 and lede. Carries the load-
   bearing platform claim ("recipients see your brand / your team
   sees SweetNote") that previously lived four sections deep. */
.sn-hero-subhead {
  font-family: 'Inter', sans-serif;
  font-size: clamp(1.0625rem, 1.4vw, 1.25rem);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--sn-ink-dark);
  margin: 18px 0 14px;
  max-width: 580px;
  text-wrap: balance;
}
/* Cyan-spark gradient text — used inline within the subhead to
   mirror the .sn-gradient-text accent on the H1 with a slightly
   different hue so the eye reads "two related claims, not the same
   one twice." */
.sn-spark-text {
  background: linear-gradient(135deg, var(--sn-spark) 0%, var(--sn-spark-deep) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* ─── Trust strip — five compliance pills directly under the hero,
   continuously scrolling left as a marquee. The HTML markup contains
   ONE list of pills; we duplicate it via JS on first paint so the
   visual loop is seamless (the duplicate fills in as the original
   scrolls off, then loops). Edge fade-out masks the in/out points
   so pills appear to flow from one side to the other. Honors
   prefers-reduced-motion (falls back to a static centered row).
   Container is overflow:hidden; pause-on-hover keeps the row
   readable. */
.sn-trust-strip {
  /* Stronger cyan wash, deeper hairlines, more vertical breathing —
     the trust thesis should feel substantial, not like a CSS
     animation flourish. */
  background: linear-gradient(180deg, rgba(6, 182, 212, 0.07) 0%, rgba(6, 182, 212, 0.02) 100%);
  border-top: 1px solid rgba(6, 182, 212, 0.22);
  border-bottom: 1px solid rgba(6, 182, 212, 0.22);
  padding: 24px 0;
  overflow: hidden;
  /* Edge-fade mask so pills appear to flow in/out smoothly rather
     than appearing and disappearing at the container edges. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 8%, #000 92%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 8%, #000 92%, transparent 100%);
}
.sn-trust-track {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  width: max-content;
  /* Slowed from 36s → 48s — more dignified pace, the buyer's eye has
     time to land on each commitment. */
  animation: sn-trust-marquee 48s linear infinite;
}
.sn-trust-track:hover { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .sn-trust-strip {
    -webkit-mask-image: none;
    mask-image: none;
  }
  .sn-trust-track {
    animation: none;
    width: 100%;
    justify-content: center;
    flex-wrap: wrap;
    gap: 14px 26px;
  }
}
@keyframes sn-trust-marquee {
  /* The track contains TWO copies of the pill list (the JS clones the
     first list into the same track). At 0% the first copy is at left;
     at 100% we've scrolled exactly one copy width to the left, which
     puts the second copy in the same starting position — seamless. */
  0%   { transform: translate3d(0, 0, 0); }
  100% { transform: translate3d(-50%, 0, 0); }
}
.sn-trust-pills {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  font-family: 'Inter', sans-serif;
  /* Each list copy keeps consistent gap; gap also applied between the
     two copies via padding on the second copy below. */
  gap: 0;
}
.sn-trust-pill {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  /* Sized down from 14.5px — the marquee is a quiet trust strip, not a
     headline; at 14.5 the long commitments ("reveal page reaches all 50
     states…") read as oversized on the trust page. */
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--sn-ink-dark);
  white-space: nowrap;
  /* Even spacing between pills regardless of pill width. */
  padding: 0 34px;
  flex-shrink: 0;
}
.sn-trust-pill svg {
  width: 16px;
  height: 16px;
  color: var(--sn-spark-deep);
  flex-shrink: 0;
}
@media (max-width: 720px) {
  .sn-trust-pill {
    font-size: 12px;
    padding: 0 22px;
    gap: 8px;
  }
  .sn-trust-pill svg {
    width: 15px;
    height: 15px;
  }
  .sn-trust-track { animation-duration: 36s; }
}
@media (max-width: 540px) {
  .sn-trust-strip { padding: 18px 0; }
  .sn-trust-pill {
    font-size: 11px;
    padding: 0 16px;
    letter-spacing: -0.005em;
  }
  .sn-trust-pill svg {
    width: 13px;
    height: 13px;
  }
  .sn-trust-track { animation-duration: 28s; }
}

/* ─── Bulk-upload personalization widget — replaces the 3-card +
   math-row layout with a literal CSV → reveal-page demonstration.
   Two columns on wide viewports: a CSV-spreadsheet mockup on the
   left, a phone reveal page on the right. The active CSV row and
   the phone's greeting/cohort sync via JS — every ~3 seconds the
   highlight advances and the phone's per-recipient fields update.
   Below the widget, a small stats bar makes the bulk math literal:
   "1,247 recipients · 1 video · 0 extra creative." */
.sn-bulk-widget {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) auto minmax(0, 0.9fr);
  gap: 28px;
  align-items: center;
  margin-top: 36px;
}
@media (max-width: 920px) {
  .sn-bulk-widget {
    grid-template-columns: 1fr;
    gap: 20px;
    align-items: stretch;
  }
}

/* CSV spreadsheet mockup. Looks deliberately spreadsheet-y: cell
   borders, monospace font, header row with bg, file-tab strip at
   the top with filename + recipient count. */
.sn-bulk-csv {
  background: #FFFFFF;
  border: 1px solid var(--sn-line);
  border-radius: 10px;
  overflow: hidden;
  box-shadow:
    0 1px 2px rgba(10, 37, 64, 0.04),
    0 18px 48px -22px rgba(10, 37, 64, 0.18);
}
.sn-bulk-csv-chrome {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: #F6F8FB;
  border-bottom: 1px solid var(--sn-line);
}
.sn-bulk-csv-icon {
  width: 18px;
  height: 22px;
  color: var(--sn-spark-deep);
  flex-shrink: 0;
}
.sn-bulk-csv-name {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px;
  font-weight: 600;
  color: var(--sn-ink-dark);
  letter-spacing: 0.005em;
}
.sn-bulk-csv-count {
  margin-left: auto;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
@media (prefers-reduced-motion: reduce) {
}

.sn-bulk-csv-table {
  width: 100%;
  border-collapse: collapse;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12.5px;
  line-height: 1.4;
}
.sn-bulk-csv-table th,
.sn-bulk-csv-table td {
  padding: 10px 14px;
  border-right: 1px solid var(--sn-line);
  border-bottom: 1px solid var(--sn-line-soft);
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
}
.sn-bulk-csv-table th:last-child,
.sn-bulk-csv-table td:last-child { border-right: none; }
.sn-bulk-csv-table thead th {
  background: #FAFCFE;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
}
.sn-bulk-csv-table td {
  color: var(--sn-ink-dark);
  transition: background 0.4s ease;
}
.sn-bulk-csv-table .sn-bulk-csv-cohort {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sn-spark-deep);
  padding: 2px 8px;
  background: rgba(6, 182, 212, 0.08);
  border-radius: 999px;
  display: inline-block;
}
.sn-bulk-csv-row.is-active td {
  background: linear-gradient(90deg, rgba(6, 182, 212, 0.10), rgba(6, 182, 212, 0.04));
}
.sn-bulk-csv-row.is-active td:first-child {
  position: relative;
}
.sn-bulk-csv-row.is-active td:first-child::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--sn-spark);
}
.sn-bulk-csv-table tbody tr:last-child td {
  border-bottom: none;
}
.sn-bulk-csv-more {
  padding: 12px 14px;
  background: #FAFCFE;
  border-top: 1px solid var(--sn-line);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  font-weight: 500;
  color: var(--sn-ink-muted);
  display: flex;
  align-items: center;
  gap: 8px;
}
.sn-bulk-csv-more-dot {
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--sn-ink-muted);
}

/* Connector arrow column. On wide viewports it's a horizontal arrow
   between CSV and phone. On mobile we hide it (the stack tells the
   story). */
.sn-bulk-arrow {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: var(--sn-spark-deep);
}
.sn-bulk-arrow svg {
  width: 32px;
  height: 32px;
}
.sn-bulk-arrow-label {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-spark-deep);
  text-align: center;
  line-height: 1.3;
}
@media (max-width: 920px) {
  .sn-bulk-arrow {
    flex-direction: row;
    justify-content: center;
  }
  .sn-bulk-arrow svg { transform: rotate(90deg); }
}

/* Phone container — uses the existing sn-phone styling but wrapped so
   we can apply the cyan-spark drop-shadow. The reveal-mock fields
   inside (greeting, from, cohort badge) update via JS data
   attributes. */
.sn-bulk-phone {
  margin: 0 auto;
  max-width: 280px;
  width: 100%;
}
.sn-bulk-phone .sn-phone-screen {
  transition: opacity 0.3s ease;
}
.sn-bulk-phone.is-fading .sn-phone-screen {
  opacity: 0.65;
}
.sn-bulk-phone .sn-reveal-mock-greeting span {
  transition: color 0.4s ease;
}
.sn-bulk-phone.is-flashing .sn-reveal-mock-greeting span {
  color: var(--sn-spark-deep);
}

/* Stats strip below the widget. Three cells, each with a number +
   label. Inline with the widget's visual rhythm. */
.sn-bulk-stats {
  margin-top: 22px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  background: #FFFFFF;
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-md);
  overflow: hidden;
}
@media (max-width: 600px) { .sn-bulk-stats { grid-template-columns: 1fr; } }
.sn-bulk-stats-cell {
  padding: 18px 22px;
  border-right: 1px solid var(--sn-line);
}
.sn-bulk-stats-cell:last-child { border-right: none; }
@media (max-width: 600px) {
  .sn-bulk-stats-cell { border-right: none; border-bottom: 1px solid var(--sn-line); }
  .sn-bulk-stats-cell:last-child { border-bottom: none; }
}
.sn-bulk-stats-num {
  font-family: 'Inter', sans-serif;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1;
  color: var(--sn-ink-dark);
  margin-bottom: 6px;
  font-feature-settings: 'tnum' 1, 'lnum' 1;
}
.sn-bulk-stats-num .sn-bulk-stats-spark {
  background: linear-gradient(135deg, var(--sn-spark) 0%, var(--sn-spark-deep) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}
.sn-bulk-stats-label {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--sn-ink-soft);
}

/* ─── Homepage personalization-at-scale module — three card row
   showing the per-recipient personalization (greeting / sender /
   cohort tag) plus a 1→N math strip below it. Mirrors the playbook's
   pb-personalize but tighter — the homepage version is the elevator
   pitch; the playbook explains how to use it. */
.sn-personalize {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-top: 36px;
}
@media (max-width: 760px) { .sn-personalize { grid-template-columns: 1fr; } }
.sn-personalize-card {
  background: #FFFFFF;
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-lg);
  padding: 22px 22px 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.sn-personalize-tag {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-spark-deep);
}
.sn-personalize-card h3 {
  font-size: 16px;
  font-weight: 600;
  color: var(--sn-ink-dark);
  margin: 0;
  letter-spacing: -0.005em;
  line-height: 1.3;
}
.sn-personalize-card p {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--sn-ink-soft);
  margin: 0;
}
.sn-personalize-sample {
  margin-top: 4px;
  padding: 10px 12px;
  background: #0A2540;
  border-radius: 6px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11.5px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.92);
  overflow-x: auto;
  white-space: pre;
}
.sn-personalize-sample .sn-tok { color: var(--sn-spark); }
.sn-personalize-sample .sn-str { color: #A7F3D0; }
.sn-personalize-sample .sn-cmt { color: rgba(255, 255, 255, 0.42); }

.sn-personalize-math {
  margin-top: 24px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  background: #FFFFFF;
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-md);
  overflow: hidden;
}
@media (max-width: 600px) { .sn-personalize-math { grid-template-columns: 1fr; } }
.sn-personalize-math-cell {
  padding: 18px 24px;
  border-right: 1px solid var(--sn-line);
}
.sn-personalize-math-cell:last-child { border-right: none; }
@media (max-width: 600px) {
  .sn-personalize-math-cell { border-right: none; border-bottom: 1px solid var(--sn-line); }
  .sn-personalize-math-cell:last-child { border-bottom: none; }
}
.sn-personalize-math-num {
  font-family: 'Inter', sans-serif;
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1;
  color: var(--sn-ink-dark);
  margin-bottom: 6px;
  font-feature-settings: 'tnum' 1, 'lnum' 1;
}
.sn-personalize-math-num .sn-personalize-spark {
  background: linear-gradient(135deg, var(--sn-spark) 0%, var(--sn-spark-deep) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}
.sn-personalize-math-label {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--sn-ink-soft);
}

/* ─── Audience cards — replaces the prior icon+label pill row with
   five buyer-persona cards each carrying a one-line "what we do for
   you" framing. A corporate gifting PM, donor stewardship director,
   HR exec, loyalty manager, or DTC CMO should see themselves in two
   seconds. */
/* Audience cards as compact accordions, centered flex-wrap layout.
   3 cards on row 1, 2 centered cards on row 2 — with flexbox, the
   second row centers its overflow cards within the row instead of
   leaving an orphan slot to the right. */
.sn-audience-cards {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sn-space-3);
  margin-top: var(--sn-space-7);
}
.sn-audience-card {
  flex: 0 1 calc((100% - 24px) / 3);
  min-width: 240px;
  max-width: 380px;
}
@media (max-width: 720px) {
  .sn-audience-card { flex-basis: calc((100% - 12px) / 2); }
}
@media (max-width: 480px) {
  .sn-audience-card { flex-basis: 100%; }
}
.sn-audience-card {
  background: var(--sn-paper);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-lg);
  transition: border-color var(--sn-transition-fast), transform var(--sn-transition-base), box-shadow var(--sn-transition-base);
}
.sn-audience-card:hover,
.sn-audience-card[open] {
  border-color: rgba(6, 182, 212, 0.45);
  transform: translateY(-2px);
  box-shadow: 0 1px 2px rgba(10, 37, 64, 0.04), 0 12px 24px -16px rgba(10, 37, 64, 0.10);
}
/* Vertical-stacked summary: icon centered at top, name centered
   below, quiet chevron at bottom. A horizontal icon | name | cyan-+
   row layout would let the bright cyan + steal visual focus from the
   actual content. */
.sn-audience-card > summary {
  list-style: none;
  cursor: pointer;
  padding: var(--sn-space-6) var(--sn-space-5) var(--sn-space-4);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--sn-space-3);
}
.sn-audience-card > summary::-webkit-details-marker { display: none; }
.sn-audience-card-icon {
  width: 44px;
  height: 44px;
  border-radius: var(--sn-radius-md);
  background: var(--sn-spark-tint);
  color: var(--sn-spark-deep);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.sn-audience-card-icon svg { width: 20px; height: 20px; }
.sn-audience-card-name {
  font-size: var(--sn-text-15);
  font-weight: 600;
  color: var(--sn-ink-dark);
  letter-spacing: var(--sn-tracking-base);
  margin: 0;
  line-height: 1.25;
}
/* Quiet chevron at the bottom — the affordance for "this expands"
   without competing with the icon + name for attention. Slate gray
   at low opacity, rotates 180° on open. */
.sn-audience-card-chev {
  width: 14px;
  height: 14px;
  color: var(--sn-ink-faint);
  transition: transform var(--sn-transition-base), color var(--sn-transition-fast);
  margin-top: var(--sn-space-1);
}
.sn-audience-card:hover .sn-audience-card-chev { color: var(--sn-spark-deep); }
.sn-audience-card[open] .sn-audience-card-chev {
  transform: rotate(180deg);
  color: var(--sn-spark-deep);
}
.sn-audience-card-detail {
  font-size: var(--sn-text-13);
  line-height: 1.6;
  color: var(--sn-ink-soft);
  margin: 0;
  padding: 0 var(--sn-space-5) var(--sn-space-5);
  text-align: center;
}

/* ═══════════════════════════════════════════════════════════════════
   SCROLL PROGRESS INDICATOR — Linear/Framer-style hairline
   3px cyan-gradient bar fixed at the top of the viewport, fills
   left-to-right as the reader scrolls down the page. The bar's width
   uses transform: scaleX so the GPU handles every frame; JS only
   updates a single CSS custom property. Sits above the header z-stack
   so it shows over the sticky nav. Hidden under prefers-reduced-
   motion (the bar isn't decorative, but the constant repaint isn't
   strictly necessary either; the reader can still scroll without it).
   ═══════════════════════════════════════════════════════════════════ */
.sn-scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 1000;
  pointer-events: none;
  background: transparent;
}
.sn-scroll-progress::after {
  content: "";
  display: block;
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, var(--sn-spectrum-blue) 0%, var(--sn-spectrum-cyan) 100%);
  transform-origin: left center;
  transform: scaleX(var(--sn-scroll-progress, 0));
  transition: transform 80ms linear;
  /* Soft inset glow so the bar reads as a "finished" element rather
     than a flat fill — picks up the brand cyan glow used on the
     proof-band hairlines. */
  box-shadow: 0 0 8px rgba(34, 211, 238, 0.45);
}
@media (prefers-reduced-motion: reduce) {
  .sn-scroll-progress { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════
   SCROLL-REVEAL MOTION — universal section fade-up
   Each homepage section starts at opacity 0 + translateY(20px), then
   eases up to its final position when it crosses ~12% into the
   viewport. The hero is excluded (always visible on load). Cubic-
   bezier (0.22, 1, 0.36, 1) is the easeOutQuad curve Stripe uses —
   decelerates over the last 60% of the animation so the section
   feels like it's "settling into place" rather than launching.
   prefers-reduced-motion completely disables.
   ═══════════════════════════════════════════════════════════════════ */
.sn-reveal {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 700ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.sn-reveal.sn-reveal-shown {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .sn-reveal,
  .sn-reveal.sn-reveal-shown {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════
   HOMEPAGE CAMPAIGN-DESIGNS ROW — compact cards, each scoped to one
   research design. Progressive disclosure: first paint shows
   headline + sample size + buyer's question; "Show details" expands
   the buyer-context examples and the methodology backing.
   ═══════════════════════════════════════════════════════════════════ */
.home-campaigns {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--sn-space-3);
  margin-top: var(--sn-space-8);
}
@media (max-width: 960px) { .home-campaigns { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 540px) { .home-campaigns { grid-template-columns: 1fr; } }
.home-campaign {
  background: var(--sn-paper);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-md);
  padding: var(--sn-space-5) var(--sn-space-5) var(--sn-space-4);
  display: flex;
  flex-direction: column;
  gap: var(--sn-space-2);
  transition: border-color var(--sn-transition-fast), transform var(--sn-transition-base);
}
.home-campaign:hover {
  border-color: rgba(6, 182, 212, 0.45);
  transform: translateY(-2px);
}
.home-campaign-icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: rgba(6, 182, 212, 0.08);
  color: var(--sn-spark-deep);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 2px;
}
.home-campaign-icon svg { width: 16px; height: 16px; }
.home-campaign-tag {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-spark-deep);
}
.home-campaign h3 {
  font-size: 15px;
  font-weight: 600;
  color: var(--sn-ink-dark);
  letter-spacing: -0.005em;
  margin: 0;
  line-height: 1.25;
}
.home-campaign p {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--sn-ink-soft);
  margin: 0;
}
/* "You'll need …" — the recipient-count requirement in plain English
   so the buyer can self-qualify before clicking through. Cyan tint
   because it's the practical qualifier (does this fit my list?). */
.home-campaign-need {
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--sn-spark-deep);
  margin: 0;
  padding: 6px 10px;
  background: var(--sn-mist, #F6F9FC);
  border-radius: 6px;
  border: 1px solid var(--sn-hairline, #E3E8EE);
}
.home-campaign-need strong {
  color: var(--sn-spark-deep);
  font-weight: 700;
}
/* "Show details" disclosure — both the buyer-context "Best when"
   examples and the technical methodology now live here so first
   paint shows just headline + lead + sample-size qualifier + the
   buyer's question. */
.home-campaign-tech {
  font-size: 11px;
  line-height: 1.55;
  color: var(--sn-ink-muted);
  margin: 0;
}
.home-campaign-tech summary {
  cursor: pointer;
  color: var(--sn-spark-deep);
  font-weight: 600;
  font-size: 10.5px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  list-style: none;
}
.home-campaign-tech summary::-webkit-details-marker { display: none; }
.home-campaign-tech summary::before {
  content: '+ ';
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  margin-right: 2px;
}
.home-campaign-tech[open] summary::before { content: '− '; }
.home-campaign-tech p {
  margin: 8px 0 0;
  font-size: 11px;
  line-height: 1.55;
  color: var(--sn-ink-muted);
}
.home-campaign-q {
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--sn-line-soft);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--sn-ink-muted);
  font-style: italic;
}
.home-campaigns-foot {
  margin-top: 22px;
  display: flex;
  flex-wrap: wrap;
  gap: 14px 22px;
  align-items: center;
  font-size: 13.5px;
  color: var(--sn-ink-soft);
}
.home-campaigns-foot a {
  color: var(--sn-spark-deep);
  text-decoration: none;
  font-weight: 600;
  border-bottom: 1px solid rgba(6, 182, 212, 0.32);
}
.home-campaigns-foot a:hover { border-bottom-color: var(--sn-spark-deep); }

/* ═══════════════════════════════════════════════════════════════════
   HOW IT WORKS — 5-step operational section. Numbered section with
   eyebrow + header + subline + 5 step cards. No arrows between steps
   because the numbered badges (1-5) carry the order on their own;
   arrows would make 9 elements in a row at 5-up which would be too
   dense. Cascades to 3-col, then 2-col, then single column on narrow
   viewports.
   ═══════════════════════════════════════════════════════════════════ */
.sn-howitworks-steps {
  list-style: none;
  margin: var(--sn-space-9) auto 0;
  padding: 0;
  max-width: 1180px;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--sn-space-3);
}
@media (max-width: 1080px) {
  .sn-howitworks-steps { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 720px) {
  .sn-howitworks-steps { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .sn-howitworks-steps { grid-template-columns: 1fr; }
}
.sn-howitworks-step {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sn-space-3);
  padding: var(--sn-space-5);
  background: var(--sn-paper);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-lg);
  transition: border-color var(--sn-transition-fast), transform var(--sn-transition-base), box-shadow var(--sn-transition-base);
}
.sn-howitworks-step:hover {
  border-color: rgba(6, 182, 212, 0.35);
  transform: translateY(-2px);
  box-shadow: 0 1px 2px rgba(10, 37, 64, 0.04), 0 12px 24px -16px rgba(10, 37, 64, 0.10);
}
/* Flow connector — chevron rendered in the gap between consecutive
   cards, so the section reads as a sequence (1 → 2 → 3 → 4 → 5),
   not five disconnected cards. The chevron sits in the 12px gap
   between cards using right: -10px (which puts it ~2px outside the
   right edge of the card, centered in the gap). Only shown at the
   wide breakpoint where 5 cards are in a single row — hidden when
   cards wrap to multi-line layouts. */
@media (min-width: 1081px) {
  .sn-howitworks-step:not(:last-child)::after {
    content: "";
    position: absolute;
    top: 50%;
    right: -11px;
    width: 8px;
    height: 8px;
    border-right: 1.75px solid rgba(6, 182, 212, 0.55);
    border-top: 1.75px solid rgba(6, 182, 212, 0.55);
    transform: translateY(-50%) rotate(45deg);
    pointer-events: none;
    z-index: 2;
  }
}
.sn-howitworks-num {
  font-family: var(--sn-font-mono);
  font-size: var(--sn-text-10);
  font-weight: 700;
  letter-spacing: var(--sn-tracking-widest);
  color: var(--sn-spark-deep);
  background: var(--sn-spark-tint);
  padding: 3px var(--sn-space-2);
  border-radius: var(--sn-radius-pill);
  align-self: flex-start;
}
.sn-howitworks-icon {
  width: 36px;
  height: 36px;
  border-radius: var(--sn-radius-md);
  background: var(--sn-spark-tint);
  color: var(--sn-spark-deep);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.sn-howitworks-icon svg { width: 18px; height: 18px; }
.sn-howitworks-body {
  display: flex;
  flex-direction: column;
  gap: var(--sn-space-1);
}
.sn-howitworks-h {
  font-size: var(--sn-text-15);
  font-weight: 600;
  color: var(--sn-ink-dark);
  letter-spacing: var(--sn-tracking-base);
  line-height: 1.3;
}
.sn-howitworks-cap {
  font-size: var(--sn-text-13);
  line-height: 1.5;
  color: var(--sn-ink-muted);
}

/* ═══════════════════════════════════════════════════════════════════
   HOMEPAGE PRICING TEASER — two-column layout: left side is the
   section head + CTAs; right side is the published-formula card
   (line-item list that previews what the calculator produces).

   Uses design tokens — no hardcoded sizes, spacing, or radii. */
.sn-pricing-teaser {
  max-width: 1080px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: var(--sn-space-8);
  align-items: center;
}
@media (max-width: 820px) {
  .sn-pricing-teaser { grid-template-columns: 1fr; }
}
/* Published-formula card — vertical line-item list like a quote or
   invoice: Base / Per recipient / Methodology premium. */
.sn-pricing-teaser-formula {
  padding: var(--sn-space-7) var(--sn-space-7) var(--sn-space-6);
  background: linear-gradient(180deg, var(--sn-paper) 0%, #FBFCFD 100%);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-lg);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.85),
    0 1px 2px rgba(10, 37, 64, 0.04),
    0 16px 40px -22px rgba(10, 37, 64, 0.12);
}
.sn-pricing-teaser-formula-label {
  display: inline-flex;
  align-items: center;
  gap: var(--sn-space-2);
  font-family: var(--sn-font-mono);
  font-size: var(--sn-text-11);
  font-weight: 700;
  letter-spacing: var(--sn-tracking-widest);
  text-transform: uppercase;
  color: var(--sn-spark-deep);
  margin-bottom: var(--sn-space-5);
}
.sn-pricing-teaser-formula-label-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--sn-spark);
}
.sn-pricing-teaser-formula-list {
  list-style: none;
  margin: 0 0 var(--sn-space-4);
  padding: 0;
}
.sn-pricing-teaser-formula-line {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--sn-space-4);
  align-items: baseline;
  padding: var(--sn-space-4) 0;
  border-bottom: 1px solid var(--sn-line-soft);
}
.sn-pricing-teaser-formula-line:last-child {
  border-bottom: 0;
}
.sn-pricing-teaser-formula-line-name-main {
  font-size: var(--sn-text-14);
  font-weight: 500;
  color: var(--sn-ink-dark);
  letter-spacing: var(--sn-tracking-base);
}
.sn-pricing-teaser-formula-line-val {
  font-family: var(--sn-font-display);
  font-size: var(--sn-text-18);
  font-weight: 600;
  letter-spacing: var(--sn-tracking-tight);
  color: var(--sn-ink-darkest);
  line-height: 1;
  white-space: nowrap;
}
.sn-pricing-teaser-formula-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sn-space-3);
  padding-top: var(--sn-space-4);
  border-top: 1px dashed var(--sn-line);
  font-size: var(--sn-text-12);
  color: var(--sn-ink-muted);
}
.sn-pricing-teaser-formula-foot strong {
  color: var(--sn-ink-dark);
  font-weight: 600;
}
.sn-pricing-teaser-formula-foot a {
  color: var(--sn-spark-deep);
  font-weight: 600;
  text-decoration: none;
  flex-shrink: 0;
}

/* ─── Methodology footer cite — sits as a quiet two-part row under
   the methodology trio. Left side: provenance citation. Right side:
   "see full methodology →" link. Stacks on narrow widths. */
.sn-method-foot-cite {
  margin: 32px auto 0;
  max-width: 980px;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--sn-ink-muted);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px 24px;
  padding-top: 18px;
  border-top: 1px dashed var(--sn-line);
}
.sn-method-foot-cite a {
  color: var(--sn-spark-deep);
  text-decoration: none;
  font-weight: 600;
  white-space: nowrap;
  border-bottom: 1px solid rgba(6, 182, 212, 0.32);
}
.sn-method-foot-cite a:hover { border-bottom-color: var(--sn-spark-deep); }

/* ═══════════════════════════════════════════════════════════════════
   METHODOLOGY TRIO — 3-column comparison.
   Three equal-weight columns. Surveys + Biometrics rendered in a
   muted treatment with struck-through headlines so the rejection is
   visual, not textual. SweetNote column lifts forward with a cyan
   accent band, brighter ink, and a subtle inner glow — reads as the
   answer of the three without needing a "vs" badge.
   ═══════════════════════════════════════════════════════════════════ */
.sn-method-trio {
  display: grid;
  grid-template-columns: 1fr 1.18fr 1fr;
  gap: var(--sn-space-5);
  margin-top: var(--sn-space-9);
  align-items: stretch;
}
@media (max-width: 920px) {
  .sn-method-trio { grid-template-columns: 1fr; gap: var(--sn-space-3); }
}
.sn-method-col {
  display: flex;
  flex-direction: column;
  gap: var(--sn-space-3);
  background: var(--sn-paper);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-xl);
  padding: var(--sn-space-6) var(--sn-space-6) var(--sn-space-5);
  position: relative;
  transition: transform var(--sn-transition-base), box-shadow var(--sn-transition-base);
}
.sn-method-col.is-rejected {
  background: var(--sn-paper-deep);
  border-color: rgba(105, 115, 134, 0.16);
  opacity: 0.94;
}
.sn-method-col.is-answer {
  background:
    linear-gradient(180deg, rgba(6, 182, 212, 0.07) 0%, rgba(34, 211, 238, 0.02) 60%, var(--sn-paper) 100%);
  border-color: rgba(6, 182, 212, 0.42);
  box-shadow:
    var(--sn-shadow-card-press),
    var(--sn-shadow-card-lift);
  transform: translateY(-4px);
}
@media (max-width: 920px) {
  .sn-method-col.is-answer { transform: none; }
}
/* Cyan top accent on the answer column — a 3px horizontal stroke
   that visually crowns it without needing a "WINNER" badge. */
.sn-method-col.is-answer::before {
  content: "";
  position: absolute;
  top: -1px;
  left: -1px;
  right: -1px;
  height: 3px;
  border-radius: var(--sn-radius-xl) var(--sn-radius-xl) 0 0;
  background: linear-gradient(90deg, var(--sn-spectrum-blue) 0%, var(--sn-spectrum-cyan) 100%);
}
.sn-method-col-head {
  display: grid;
  grid-template-columns: 36px 1fr;
  grid-template-areas:
    "icon label"
    "icon verdict";
  align-items: center;
  column-gap: var(--sn-space-3);
  row-gap: var(--sn-space-1);
}
.sn-method-col-icon {
  grid-area: icon;
  width: 36px;
  height: 36px;
  border-radius: var(--sn-radius-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(105, 115, 134, 0.10);
  color: rgba(105, 115, 134, 0.72);
}
.sn-method-col-icon svg { width: 18px; height: 18px; }
.sn-method-col.is-answer .sn-method-col-icon {
  background: var(--sn-spark-tint);
  color: var(--sn-spark-deep);
}
.sn-method-col-label {
  grid-area: label;
  font-family: var(--sn-font-mono);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  line-height: 1;
}
.sn-method-col.is-answer .sn-method-col-label {
  color: var(--sn-spark-deep);
}
.sn-method-col-verdict {
  grid-area: verdict;
  font-family: var(--sn-font-mono);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: var(--sn-tracking-widest);
  text-transform: uppercase;
  color: rgba(176, 74, 42, 0.85);
  line-height: 1;
}
.sn-method-col-verdict.is-answer {
  color: var(--sn-spark-deep);
}
.sn-method-col-h {
  margin: var(--sn-space-1) 0 0;
  font-size: var(--sn-text-18);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.25;
  color: var(--sn-ink-dark);
}
.sn-method-col.is-rejected .sn-method-col-h {
  color: var(--sn-ink-muted);
  text-decoration: line-through;
  text-decoration-color: rgba(105, 115, 134, 0.32);
  text-decoration-thickness: 1px;
}
.sn-method-col.is-answer .sn-method-col-h {
  font-size: 20px;
  letter-spacing: var(--sn-tracking-snug);
}
.sn-method-col-cap {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--sn-ink-soft);
  flex: 1;
}
.sn-method-col.is-rejected .sn-method-col-cap {
  color: var(--sn-ink-muted);
}
.sn-method-col-cap em { font-style: italic; }
.sn-method-col-stat {
  margin-top: var(--sn-space-2);
  padding-top: var(--sn-space-4);
  border-top: 1px solid var(--sn-line-soft);
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.sn-method-col.is-answer .sn-method-col-stat {
  border-top-color: rgba(6, 182, 212, 0.20);
}
.sn-method-col-stat-num {
  font-family: var(--sn-font-display);
  font-size: var(--sn-text-display-md);
  font-weight: 500;
  letter-spacing: var(--sn-tracking-tight);
  line-height: 1.05;
  color: var(--sn-ink-dark);
  white-space: nowrap;
}
.sn-method-col.is-rejected .sn-method-col-stat-num {
  color: rgba(105, 115, 134, 0.80);
}
.sn-method-col.is-answer .sn-method-col-stat-num {
  background: var(--sn-gradient-text);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  padding-bottom: 0.08em;
}
.sn-method-col-stat-cap {
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--sn-ink-muted);
}

/* ─── Count-up animation on proof band ─── */
.sn-proof-band .sn-proof-num {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.8s ease 0.1s, transform 0.8s ease 0.1s;
}
.sn-proof-band.is-visible .sn-proof-num {
  opacity: 1;
  transform: translateY(0);
}
.sn-proof-band .sn-proof-tile:nth-child(1) .sn-proof-num { transition-delay: 0.1s; }
.sn-proof-band .sn-proof-tile:nth-child(2) .sn-proof-num { transition-delay: 0.2s; }
.sn-proof-band .sn-proof-tile:nth-child(3) .sn-proof-num { transition-delay: 0.3s; }
.sn-proof-band .sn-proof-tile:nth-child(4) .sn-proof-num { transition-delay: 0.4s; }

/* ─── Hero single-brand journey ────────────────────────────────────────
   Replaces the 3-brand carousel (April 2026). One phone shows a frozen
   reveal page; the first reaction ("Sweet") pulses to suggest a tap; a small
   floating event-feed card to the right shows the captured event
   landing in the brand's dashboard. Tells the platform pipeline story
   (recipient → reveal → reaction → dashboard event) in one frame.
   ─────────────────────────────────────────────────────────────────── */
.sn-hero-journey {
  position: relative;
  width: 280px;
  margin: 0 auto;
}
/* Hero phone gentle float — pure vertical float, ±4px on a slow 9s
   sine cycle. No rotation: even at ±0.6° it reads as a wobble. Phone
   reads as a solid product mock that subtly hovers, no axial movement
   to feel shaky. Disabled under reduced-motion. */
.sn-hero-visual {
  perspective: 1400px;
  perspective-origin: 50% 50%;
}
.sn-hero-visual .sn-hero-journey {
  animation: sn-hero-float 9s ease-in-out infinite;
  will-change: transform;
}
@keyframes sn-hero-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
  .sn-hero-visual .sn-hero-journey {
    animation: none;
    transform: none;
  }
}
.sn-hero-journey-phone {
  position: relative;
  z-index: 1;
}
/* Pulsing tap on the first reaction ("Sweet") — communicates that this
   reaction was the one captured, without needing a literal cursor.
   Uses the brand-accent color so it reads as the recipient's choice
   inside the reveal, not a SweetNote-side overlay. */
.sn-hero-journey-tap {
  position: relative;
  animation: sn-hero-journey-tap 5s ease-in-out infinite;
}
@keyframes sn-hero-journey-tap {
  0%, 60%, 100% {
    background: var(--brand-mock-card);
    border-color: var(--brand-mock-line);
    transform: scale(1);
  }
  62% {
    background: var(--brand-mock-card);
    transform: scale(0.96);
  }
  68%, 92% {
    background: var(--brand-mock-accent);
    border-color: var(--brand-mock-accent);
    color: #FFFFFF;
    transform: scale(1.02);
  }
}
.sn-hero-journey-tap::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: inherit;
  border: 2px solid var(--brand-mock-accent);
  opacity: 0;
  animation: sn-hero-journey-ring 5s ease-out infinite;
  pointer-events: none;
}
@keyframes sn-hero-journey-ring {
  0%, 60%, 100% { opacity: 0; transform: scale(0.96); }
  68% { opacity: 0.55; transform: scale(1); }
  82%, 100% { opacity: 0; transform: scale(1.18); }
}

/* Live-capture widget — overlaps the phone's bottom-right corner.
   Glass-effect (semi-transparent white + backdrop blur) so the
   gradient hero ground shows through subtly, like a real product
   card hovering above the page. Each event row uses a 2-line
   layout: primary action ("Reaction logged") on top, secondary
   metadata ("Sweet · just now") below. Header has a counter
   on the right so the widget reads like a tiny dashboard pane. */
.sn-hero-journey-feed {
  position: absolute;
  bottom: 24px;
  right: -72px;
  width: 234px;
  background: rgba(255, 255, 255, 0.86);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, 0.95);
  border-radius: var(--sn-radius-xl);
  box-shadow: var(--sn-shadow-glass), var(--sn-shadow-glow-cyan);
  padding: var(--sn-space-3) var(--sn-space-4);
  z-index: 2;
}
/* Header row: pulse + title on the left, "2 events" counter on the right */
.sn-hero-journey-feed-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding-bottom: 10px;
  margin-bottom: 4px;
  border-bottom: 1px solid rgba(10, 37, 64, 0.06);
}
.sn-hero-journey-feed-head-left {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}
.sn-hero-journey-feed-title {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sn-ink-dark);
}
/* "2 events" counter — quiet mono number on the right of the header.
   Reads as "this is a list with N items" without being a button. */
.sn-hero-journey-feed-counter {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  background: rgba(10, 37, 64, 0.05);
  padding: 2px 6px;
  border-radius: 10px;
  white-space: nowrap;
}
.sn-hero-journey-feed-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
/* Each event row is now a 2-line block: bold action + lighter meta.
   Reads like a real dashboard log entry. */
.sn-hero-journey-feed-row {
  display: grid;
  grid-template-columns: 14px 1fr;
  align-items: flex-start;
  gap: 8px;
  padding: 8px 6px 8px 4px;
  border-radius: 8px;
  position: relative;
  transition: background 0.3s ease;
}
.sn-hero-journey-feed-row-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.sn-hero-journey-feed-row-fresh {
  animation: sn-hero-journey-fresh 5s ease-out infinite;
}
@keyframes sn-hero-journey-fresh {
  0%, 60% { background: transparent; }
  68% { background: rgba(6, 182, 212, 0.10); }
  88%, 100% { background: transparent; }
}
/* Cyan dot with a soft outer ring on the fresh (top) row — reads as
   "this is the just-captured event." The non-fresh row gets a quieter
   slate dot. Both align to the top of the row body. */
.sn-hero-journey-feed-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(105, 115, 134, 0.45);
  justify-self: center;
  margin-top: 4px;
  position: relative;
  flex-shrink: 0;
}
.sn-hero-journey-feed-row-fresh .sn-hero-journey-feed-dot {
  background: var(--sn-spark);
  box-shadow: 0 0 0 3px rgba(6, 182, 212, 0.16);
}
.sn-hero-journey-feed-event {
  font-family: 'Inter', sans-serif;
  font-size: 12px;
  font-weight: 600;
  color: var(--sn-ink-dark);
  letter-spacing: -0.005em;
  line-height: 1.25;
}
/* Secondary metadata line — value + timestamp, lighter weight. */
.sn-hero-journey-feed-meta {
  font-size: 10.5px;
  line-height: 1.35;
  color: var(--sn-ink-muted);
}
.sn-hero-journey-feed-time {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--sn-ink-muted);
}
@media (max-width: 1100px) {
  .sn-hero-journey-feed {
    right: auto;
    left: 50%;
    bottom: -16px;
    transform: translate(-50%, 100%);
  }
  .sn-hero-journey { margin-bottom: 132px; }
}
@media (prefers-reduced-motion: reduce) {
  .sn-hero-journey-tap,
  .sn-hero-journey-tap::after,
  .sn-hero-journey-feed-row-fresh {
    animation: none;
  }
}

/* Hero section inner override — phone instead of dashboard mockup.
   Two-column at desktop; stacks vertically below 880px so the copy
   reads first and the journey visual sits below it without squeezing
   either column into illegible widths. */
.sn-hero-inner {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: clamp(40px, 6vw, 80px);
  align-items: center;
}
@media (max-width: 880px) {
  .sn-hero-inner {
    grid-template-columns: 1fr;
    gap: 48px;
  }
}
/* Single-column hero variant — used on /faq where there's no phone stack
   and the page is an index, not a statement. */
.sn-hero-inner-single { grid-template-columns: 1fr; }
.sn-hero-copy-narrow { max-width: 720px; }

/* Centered statement-style hero — used on /about. Larger H1, copy
   centered, room for a "value pill" row underneath. Different visual
   register from the homepage split-layout hero so users feel they've
   moved to a different kind of page. */
.sn-hero-inner-centered {
  grid-template-columns: 1fr;
  text-align: center;
  max-width: 920px;
  margin-left: auto;
  margin-right: auto;
}
.sn-hero-inner-centered .sn-eyebrow,
.sn-hero-inner-centered .sn-lede {
  margin-left: auto;
  margin-right: auto;
}
.sn-hero-inner-centered h1 {
  /* Match the canonical hero H1 scale (clamp 2.5–4rem) so centered
     statement heroes (about / trust / security / onboard) read at the
     same size as the split heroes. */
  font-size: clamp(2.5rem, 5vw, 4rem);
}

/* Value-pill row — small horizontal strip of icon+label pills shown
   under the centered hero. Previews the values cards below at a glance,
   giving the centered hero "weight" without adding more prose. */
.sn-hero-value-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 36px;
}
.sn-hero-value-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--sn-spark-tint);
  color: var(--sn-accent);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: 1px solid rgba(6, 182, 212, 0.16);
}
.sn-hero-value-pill svg {
  width: 14px;
  height: 14px;
  color: var(--sn-spark-deep);
  flex-shrink: 0;
}

/* ─── FAQ HERO — split-layout objections / written-answers ───────
   Left column shows the objection chips a procurement reviewer walks
   in with. Right column shows answer cards that pop in on page load
   with staggered delays — visual proof of the "answered in writing"
   promise. Reuses .sn-hero-inner's 1.2fr/1fr grid by default; on FAQ
   we want the columns roughly equal so the answer stack reads as a
   peer to the headline, not a sidebar. */
.sn-hero-inner-faq { grid-template-columns: 1fr 1.1fr; }

.sn-faq-objection-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 32px;
  align-items: center;
}
.sn-faq-objection-label,
.sn-faq-answers-label {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  margin-right: 4px;
}
.sn-faq-objection {
  display: inline-flex;
  padding: 7px 14px;
  border-radius: 999px;
  background: var(--sn-paper);
  color: var(--sn-ink-soft);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  border: 1px dashed rgba(105, 115, 134, 0.32);
  white-space: nowrap;
}
/* Chip count is held to 4 in HTML (matching the 4 answer cards 1:1) so the
   row reads as a clean single line at desktop width and a tidy two-line
   wrap on narrow viewports without orphaning a single chip on its own
   row. If a 5th chip is added back, audit at ~880px–1100px viewport
   widths to make sure the wrap doesn't strand the last item. */

.sn-faq-answers {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 4px 0;
  align-items: stretch;
}
.sn-faq-answers-label {
  margin: 0 0 6px 4px;
  opacity: 0;
  animation: sn-faq-answer-pop 0.45s ease-out forwards;
  animation-delay: 0.15s;
}
.sn-faq-answer-card {
  background: #FFFFFF;
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-lg);
  padding: 22px 26px;
  box-shadow:
    0 1px 2px rgba(10, 37, 64, 0.04),
    0 12px 32px rgba(10, 37, 64, 0.07);
  display: flex;
  flex-direction: column;
  gap: 8px;
  opacity: 0;
  transform: translateX(24px) translateY(4px);
  animation: sn-faq-answer-pop 0.65s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
  animation-delay: var(--delay, 0s);
  text-align: left;
}
.sn-faq-answer-tag {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sn-spark-deep);
}
.sn-faq-answer-card p {
  margin: 0;
  color: var(--sn-ink-dark);
  font-family: var(--sn-font-display);
  font-size: clamp(20px, 1.5vw, 24px);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -0.01em;
}

@keyframes sn-faq-answer-pop {
  to {
    opacity: 1;
    transform: translateX(0) translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .sn-faq-answer-card,
  .sn-faq-answers-label {
    opacity: 1;
    transform: none;
    animation: none;
  }
}

@media (max-width: 880px) {
  .sn-hero-inner-faq { grid-template-columns: 1fr; }
  .sn-faq-answer-card p { font-size: 19px; }
}

/* Split hero with a single static phone artifact (vs. homepage's
   auto-rotating stack). Used on /case-study to show a reveal page
   at rest. Reuses .sn-hero-inner's 1.2fr/1fr grid. */
.sn-hero-phone-static {
  position: relative;
  width: 280px;
  height: 580px;
  margin: 0 auto;
}
.sn-hero-phone-static .sn-phone {
  position: relative;
  width: 100%;
  height: 100%;
}

/* Two-column form layout — used on /contact. Form on left, "what to
   expect" reassurance panel on right. Visual variety from the
   prior centered-only treatment. */
.sn-form-layout {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: clamp(40px, 6vw, 72px);
  align-items: start;
  max-width: 1080px;
  margin: 0 auto;
}
.sn-form-aside-panel {
  background: var(--sn-paper-deep);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-lg);
  padding: 32px 28px;
  position: sticky;
  top: 96px;
}
.sn-form-aside-panel h3 {
  font-size: 16px;
  margin-bottom: 14px;
}
.sn-form-aside-panel ol {
  list-style: none;
  counter-reset: form-step;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.sn-form-aside-panel ol li {
  counter-increment: form-step;
  position: relative;
  padding-left: 36px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--sn-ink-soft);
}
.sn-form-aside-panel ol li::before {
  content: counter(form-step, decimal-leading-zero);
  position: absolute;
  left: 0;
  top: -2px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--sn-spark-tint);
  color: var(--sn-spark-deep);
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.sn-form-aside-panel strong {
  color: var(--sn-ink-dark);
  font-weight: 600;
}
@media (max-width: 880px) {
  .sn-form-layout { grid-template-columns: 1fr; gap: 32px; }
  .sn-form-aside-panel { position: static; }
}
@media (max-width: 880px) {
  .sn-hero-inner { grid-template-columns: 1fr; gap: 40px; }
  .sn-hero-journey { margin-top: 24px; transform: scale(0.85); transform-origin: top center; }
}
@media (prefers-reduced-motion: reduce) {
  .sn-hero::before { animation: none; }
  .sn-proof-band .sn-proof-num { opacity: 1; transform: none; }
}

/* Specific-callout — small block that highlights a screenshot-worthy
   procurement-grade specific. Sits inline with section copy with a
   subtle gold left-edge so it reads as a "fineprint that's actually
   load-bearing" moment. Use sparingly: max one per page. */
.sn-spec-callout {
  margin: 24px 0 0;
  padding: 14px 18px 14px 20px;
  background: var(--sn-mist, #F6F9FC);
  border: 1px solid var(--sn-hairline, #E3E8EE);
  border-radius: var(--sn-radius-md);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--sn-ink-soft);
  max-width: 720px;
}
.sn-spec-callout strong {
  color: var(--sn-ink-dark);
  font-weight: 600;
}
.sn-spec-callout-mark {
  display: inline-block;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sn-gold-deep, #0891B2);
  margin-right: 8px;
}

/* Gradient text utility — for hero italic emphasis */
.sn-gradient-text {
  background: var(--sn-gradient-text);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  background-size: 200% 200%;
  animation: sn-gradient-shimmer 6s ease-in-out infinite alternate;
  display: inline-block;
}
@keyframes sn-gradient-shimmer {
  0% { background-position: 0% 50%; }
  100% { background-position: 100% 50%; }
}

/* Card hover lift for engagement */
.sn-promise,
.sn-product-tile,
.sn-audience-card {
  transition: border-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}
.sn-promise:hover,
.sn-product-tile:hover,
.sn-audience-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 32px -12px rgba(10, 37, 64, 0.14);
}

/* Multi-brand phones — gentle scale on hover for engagement */
.sn-multibrand-phone {
  transition: transform 0.4s ease;
}
.sn-multibrand-phone:hover {
  transform: translateY(-6px) scale(1.02);
}

/* Spectrum dot — for "live" indicators, more energetic than coral pulse */

/* ═══════════════════════════════════════════════════════════════════
   PROOF BAND — Stripe-pattern Section 2
   Four-tile stats grid right after hero. Big Inter numbers, tiny
   uppercase labels in JetBrains Mono. Generous padding. The proof
   layer that earns the hero's claim immediately.
   ═══════════════════════════════════════════════════════════════════ */
.sn-proof-band {
  background: var(--sn-paper-deep);
  border-top: 1px solid var(--sn-line);
  border-bottom: 1px solid var(--sn-line);
  padding: clamp(72px, 9vw, 108px) 24px;
}

/* ─── Dark variant of the proof band ─────────────────────────────────
   Homepage problem-statement (post-hero) tonal pivot. Slate-navy
   ground via --sn-band-dark-bg token; cyan-edged hairlines top/bottom
   via --sn-band-dark-edge. Light text colors ride on the band-dark-*
   tokens so any future dark surface inherits the same palette. */
.sn-proof-band-dark {
  /* Dot pattern over solid dark base — clean, flat editorial band.
     The cyan atmospheric drift I tried during Tier-2 was reverted
     because the gradient blob's edges showed as "cut off" inside
     the section. The eyebrow's cyan text is enough live signal. */
  background:
    radial-gradient(rgba(255,255,255,0.05) 1.1px, transparent 1.4px) 0 0 / 27px 27px,
    var(--sn-band-dark-bg);
  border-top: 0;
  border-bottom: 0;
  color: var(--sn-paper);
  position: relative;
  overflow: hidden;
}
.sn-proof-band-dark > .sn-container { position: relative; z-index: 1; }
.sn-proof-band-dark::before,
.sn-proof-band-dark::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--sn-band-dark-edge);
  pointer-events: none;
}
.sn-proof-band-dark::before { top: 0; }
.sn-proof-band-dark::after { bottom: 0; }
.sn-proof-band-dark .sn-proof-band-eyebrow { color: var(--sn-band-dark-eyebrow); }
.sn-proof-band-dark .sn-proof-band-headline { color: var(--sn-paper); }
.sn-proof-band-dark .sn-proof-band-sub { color: var(--sn-band-dark-text); }
.sn-proof-band-dark .sn-proof-tile-large .sn-proof-num,
.sn-proof-band-dark .sn-proof-num { color: var(--sn-paper); }
.sn-proof-band-dark .sn-proof-tile-large .sn-proof-label { color: rgba(255, 255, 255, 0.82); }
.sn-proof-band-dark .sn-proof-sub { color: rgba(34, 211, 238, 0.85); }
.sn-proof-band-dark .sn-proof-band-vs { color: var(--sn-band-dark-text-faint); }
.sn-proof-band-dark .sn-proof-band-vs-line {
  background: linear-gradient(180deg, transparent 0%, rgba(255, 255, 255, 0.28) 50%, transparent 100%);
}
@media (max-width: 720px) {
  .sn-proof-band-dark .sn-proof-band-vs-line {
    background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.28) 50%, transparent 100%);
  }
}
.sn-proof-band-dark .sn-proof-band-vs-label { color: var(--sn-band-dark-text-faint); }

/* Subhead under the headline — gives the problem statement a "here's
   the prose" beat between the headline and the two big numbers. */
.sn-proof-band-sub {
  font-size: clamp(0.95rem, 1.35vw, 1.0625rem);
  line-height: 1.55;
  color: var(--sn-ink-soft);
  max-width: 640px;
  margin: var(--sn-space-1) auto 0;
  text-wrap: balance;
}

/* ═══════════════════════════════════════════════════════════════════
   MOAT BAND — second dark editorial moment.
   Mirrors the problem-statement dark band structurally (uses the same
   --sn-band-dark-* tokens) but more compact: one headline, one
   subhead, two stats inline. The page reads as dark/light/dark/light
   for tonal rhythm without overusing dark.
   ═══════════════════════════════════════════════════════════════════ */
.sn-moat-band {
  position: relative;
  background: var(--sn-band-dark-bg);
  padding: var(--sn-space-section-tight) var(--sn-space-6);
  color: var(--sn-paper);
}
.sn-moat-band::before,
.sn-moat-band::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--sn-band-dark-edge);
  pointer-events: none;
}
.sn-moat-band::before { top: 0; }
.sn-moat-band::after { bottom: 0; }
.sn-moat-band-inner {
  max-width: 880px;
  margin: 0 auto;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sn-space-4);
}
.sn-moat-band-eyebrow {
  font-family: var(--sn-font-mono);
  font-size: var(--sn-text-11);
  font-weight: 700;
  letter-spacing: var(--sn-tracking-mega);
  text-transform: uppercase;
  color: var(--sn-band-dark-eyebrow);
}
.sn-moat-band-headline {
  font-family: var(--sn-font-display);
  font-size: var(--sn-text-display-xl);
  font-weight: 600;
  letter-spacing: var(--sn-tracking-tight);
  line-height: 1.15;
  color: var(--sn-paper);
  max-width: 720px;
  margin: 0;
  text-wrap: balance;
}
.sn-moat-band-sub {
  font-size: clamp(0.95rem, 1.35vw, 1.0625rem);
  line-height: 1.55;
  color: var(--sn-band-dark-text);
  max-width: 600px;
  margin: var(--sn-space-1) 0 0;
  text-wrap: balance;
}
.sn-moat-band-sub strong {
  color: var(--sn-paper);
  font-weight: 600;
}
.sn-moat-band-stats {
  display: flex;
  gap: clamp(28px, 5vw, 56px);
  align-items: center;
  margin-top: var(--sn-space-6);
}
@media (max-width: 640px) {
  .sn-moat-band-stats { flex-direction: column; gap: var(--sn-space-7); }
}
.sn-moat-band-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sn-space-1);
  text-align: center;
  max-width: 280px;
}
.sn-moat-band-stat-num {
  font-family: var(--sn-font-display);
  font-size: var(--sn-text-display-md);
  font-weight: 500;
  letter-spacing: var(--sn-tracking-tight);
  line-height: 1;
  background: var(--sn-gradient-text);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  white-space: nowrap;
}
.sn-moat-band-stat-cap {
  font-size: var(--sn-text-12);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.65);
}
.sn-moat-band-stat-divider {
  width: 1px;
  height: 56px;
  background: linear-gradient(180deg, transparent 0%, rgba(255, 255, 255, 0.22) 50%, transparent 100%);
  flex-shrink: 0;
}
@media (max-width: 640px) {
  .sn-moat-band-stat-divider {
    width: 56px;
    height: 1px;
    background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.22) 50%, transparent 100%);
  }
}
/* Inline link inside the dogfood subhead — uses the cyan spectrum to
   match the gradient stats below; underlined so it reads as a link
   without competing with the body text. */
.sn-moat-band-sub-link {
  color: rgba(34, 211, 238, 0.95);
  text-decoration: none;
  border-bottom: 1px solid rgba(34, 211, 238, 0.40);
  transition: border-color 0.2s ease;
}
.sn-moat-band-sub-link:hover {
  border-bottom-color: rgba(34, 211, 238, 0.95);
}
/* "Read the case study →" CTA below the stats — quiet underlined link
   in cyan, sits as the click-through to the dogfood proof page. */
.sn-moat-band-cta {
  margin-top: 28px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: rgba(34, 211, 238, 0.95);
  text-decoration: none;
  border-bottom: 1px solid rgba(34, 211, 238, 0.40);
  padding-bottom: 4px;
  transition: border-color 0.2s ease, transform 0.2s ease;
}
.sn-moat-band-cta:hover {
  border-bottom-color: rgba(34, 211, 238, 0.95);
}
.sn-moat-band-cta .arrow {
  transition: transform 0.2s ease;
}
.sn-moat-band-cta:hover .arrow {
  transform: translateX(3px);
}
.sn-proof-band .sn-container {
  max-width: var(--sn-container);
  margin: 0 auto;
}
.sn-proof-band-header {
  margin-bottom: clamp(48px, 6vw, 72px);
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: center;
}
.sn-proof-band-eyebrow {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
}
.sn-proof-band-headline {
  font-family: var(--sn-font-display, 'Inter', sans-serif);
  font-size: clamp(1.75rem, 3.5vw, 2.5rem);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.15;
  color: var(--sn-ink-darkest, #0A2540);
  max-width: 720px;
  margin: 0;
  text-wrap: balance;
}
/* Two-column contrast band: $300B on the left, ~0% on the right, with
   a vertical "the gap" connector between them. The gap IS the story —
   negative space between the two numbers makes the visual point that
   verbal copy alone can't. */
.sn-proof-band-2col {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: clamp(40px, 8vw, 96px);
  align-items: center;
  max-width: 1080px;
  margin: 0 auto;
}
@media (max-width: 720px) {
  .sn-proof-band-2col {
    grid-template-columns: 1fr;
    gap: 32px;
    text-align: center;
  }
}
.sn-proof-tile-large {
  text-align: center;
  align-items: center;
}
.sn-proof-tile-large .sn-proof-num {
  font-size: clamp(3.5rem, 8vw, 6rem);
  letter-spacing: -0.045em;
  line-height: 0.9;
  margin-bottom: 6px;
}
.sn-proof-tile-large .sn-proof-label {
  font-family: 'Inter', sans-serif;
  font-size: clamp(0.95rem, 1.3vw, 1.0625rem);
  font-weight: 500;
  letter-spacing: -0.005em;
  text-transform: none;
  color: var(--sn-ink-soft);
  line-height: 1.45;
  max-width: 28ch;
  text-align: center;
}
.sn-proof-sub {
  margin-top: 4px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  text-align: center;
}
/* The "gap" connector between the two stats. Two thin vertical lines
   with a tiny mono label sandwiched between them. Visually says: there
   is a chasm here, and the chasm IS the point. On mobile the connector
   rotates horizontal for the stacked layout. */
.sn-proof-band-vs {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  color: var(--sn-ink-muted);
}
.sn-proof-band-vs-line {
  display: block;
  width: 1px;
  height: 56px;
  background: linear-gradient(180deg, transparent 0%, var(--sn-line) 50%, transparent 100%);
}
.sn-proof-band-vs-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  white-space: nowrap;
}
@media (max-width: 720px) {
  .sn-proof-band-vs {
    flex-direction: row;
    gap: 12px;
  }
  .sn-proof-band-vs-line {
    width: 56px;
    height: 1px;
    background: linear-gradient(90deg, transparent 0%, var(--sn-line) 50%, transparent 100%);
  }
}
.sn-proof-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(32px, 5vw, 64px);
}
/* Three-stat variant — used when the proof band tells one tight story
   instead of stretching across four. Each tile gets more breathing room. */
.sn-proof-grid-3 {
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(40px, 6vw, 80px);
}
@media (max-width: 800px) {
  .sn-proof-grid { grid-template-columns: repeat(2, 1fr); gap: 40px; }
}
@media (max-width: 480px) {
  .sn-proof-grid { grid-template-columns: 1fr; gap: 36px; }
}
.sn-proof-tile {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.sn-proof-num {
  font-family: 'Inter', sans-serif;
  font-size: clamp(2.75rem, 6vw, 4.25rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 0.95;
  color: var(--sn-ink-dark);
  font-feature-settings: 'tnum' 1, 'lnum' 1;
  /* Range stats like "$50–$200" must never wrap mid-number — the en-dash
     would split the range across two lines and read like two unrelated
     numbers. Force the entire stat onto a single line. */
  white-space: nowrap;
}
.sn-proof-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  line-height: 1.4;
  max-width: 22ch;
}

/* Reduced-motion support */
@media (prefers-reduced-motion: reduce) {
  .sn-hero::before,
  .sn-gradient-text,
}

/* Dark variant — for the trust section */
.sn-trust .sn-promise {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.12);
}
.sn-trust .sn-promise:hover { border-color: rgba(255, 255, 255, 0.4); }
.sn-trust .sn-promise-mark { color: var(--sn-cream); }
.sn-trust .sn-promise-mark::before { background: var(--sn-cream); }
.sn-trust .sn-promise h3 { color: var(--sn-cream); }
.sn-trust .sn-promise p { color: rgba(255, 255, 255, 0.72); }

/* ═══════════════════════════════════════════════════════════════════
   EXPERIENCE MOCKUPS — sender + recipient visual sections
   Show, don't tell. CSS-only mockups (no images required).
   ═══════════════════════════════════════════════════════════════════ */

/* ─── iPhone frame mockup (for the RECIPIENT experience) ─── */
.sn-phone {
  position: relative;
  z-index: 1;
  width: 280px;
  height: 580px;
  background: #1a1a1a;
  border-radius: 42px;
  padding: 10px;
  box-shadow: 0 30px 60px -20px rgba(12, 27, 46, 0.32), 0 10px 24px -6px rgba(12, 27, 46, 0.18), inset 0 0 0 2px #2a2a2a;
}
.sn-phone-screen {
  width: 100%;
  height: 100%;
  /* Modern minimal preset is the May 2026 default — pure white surface.
     The previous warm-paper #FDFBF6 was the pre-flip editorial-warm
     default. Multi-brand variant (.sn-multibrand-phone) further down
     overrides via --brand-mock-paper for showing per-brand mockups. */
  background: #FFFFFF;
  border-radius: 32px;
  overflow: hidden;
  position: relative;
  display: flex;
  flex-direction: column;
}
.sn-phone-notch {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 92px;
  height: 24px;
  background: #1a1a1a;
  border-bottom-left-radius: 14px;
  border-bottom-right-radius: 14px;
  z-index: 2;
}
.sn-phone-status {
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
  font-family: 'Inter', sans-serif;
  font-size: 11px;
  font-weight: 600;
  color: var(--sn-ink-dark);
}
/* Mobile-browser address bar — the recipient opens the reveal in their
   browser at the brand's own subdomain, so showing acme.thesweetnote.com
   (brand bolded) makes the "brand-owned moment" concrete. Pure chrome;
   sits between the status bar and the reveal content. */
.sn-phone-urlbar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  margin: 2px 12px 6px;
  padding: 6px 11px;
  background: rgba(10, 37, 64, 0.06);
  border: 1px solid rgba(10, 37, 64, 0.08);
  border-radius: 999px;
  font-family: var(--sn-font-mono, 'JetBrains Mono', monospace);
  font-size: 9.5px;
  letter-spacing: 0.01em;
  color: var(--brand-mock-ink-muted, rgba(10, 37, 64, 0.72));
  white-space: nowrap;
  overflow: hidden;
  flex: none;
}
.sn-phone-urlbar b { font-weight: 700; color: var(--brand-mock-ink, #0A2540); }
.sn-phone-urlbar svg { flex: none; opacity: 0.7; }
/* The reveal-page content inside the phone */
.sn-reveal-mock {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 12px 22px 14px;
  gap: 9px;
}
.sn-reveal-mock-logo {
  font-family: 'Inter', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--sn-ink-dark);
  margin-top: 6px;
}
/* Mock header carries the ACTUAL demo-logo image (founder 2026-07-14 — every
   example reveal shows a logo, modeling what real brands set up), not a text
   wordmark. Height matches the old text line so mock proportions hold. */
.sn-reveal-mock-logo img {
  height: 15px;
  width: auto;
  display: inline-block;
  vertical-align: middle;
}
/* Dark reveal surface (the how-it-works background picker): the teal wordmark
   would sink into a dark paper — float the logo on a small white plate, the
   way real brands place light-surface logos on dark layouts. The is-dark-paper
   class is toggled by the same JS that flips the mock ink vars. */
.sn-multibrand-phone.is-dark-paper .sn-reveal-mock-logo img {
  background: #FFFFFF;
  border-radius: 5px;
  padding: 2px 6px;
}
.sn-reveal-mock-eyebrow {
  font-family: 'JetBrains Mono', monospace;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
}
.sn-reveal-mock-greeting {
  font-family: var(--sn-font-display);
  font-style: normal;
  font-size: 24px;
  font-weight: 400;
  color: var(--sn-ink-dark);
  line-height: 1.15;
}
.sn-reveal-mock-greeting span {
  color: var(--sn-ink-dark);
  font-weight: 500;
}
.sn-reveal-mock-hair {
  display: block;
  width: 24px;
  height: 1px;
  background: var(--sn-ink-dark);
  margin: 2px auto;
}
.sn-reveal-mock-from {
  font-family: 'Inter', sans-serif;
  font-size: 11px;
  font-weight: 500;
  color: var(--sn-ink-soft);
  letter-spacing: 0.04em;
}
.sn-reveal-mock-video {
  /* Height-driven 9:16 portrait (like the login reveal preview), NOT
     width:100% — a full-width portrait resolves to ~384px tall and
     overflows the fixed-height phone, clipping the CTA, reactions, and
     the "Powered by SweetNote" footer. A capped height keeps the whole
     reveal visible. */
  width: auto;
  height: 176px;
  aspect-ratio: 9 / 16;
  background: linear-gradient(135deg, #1F2D44 0%, #06101F 100%);
  border-radius: 12px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 4px;
  box-shadow: 0 8px 20px -8px rgba(12, 27, 46, 0.35);
}
.sn-reveal-mock-video::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 30% 30%, rgba(255, 255, 255, 0.08), transparent 50%),
    radial-gradient(circle at 70% 70%, rgba(255, 255, 255, 0.04), transparent 50%);
  border-radius: 12px;
}
.sn-reveal-mock-play {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.95);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  z-index: 1;
}
.sn-reveal-mock-play::after {
  content: '';
  width: 0;
  height: 0;
  border-left: 14px solid var(--sn-ink-dark);
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
  margin-left: 4px;
}
.sn-reveal-mock-reactions {
  display: flex;
  gap: 8px;
  width: 100%;
  margin-top: 6px;
}
.sn-reveal-mock-reaction {
  flex: 1;
  padding: 7px 4px 6px;
  background: var(--sn-white);
  border: 1px solid var(--sn-line);
  border-radius: 8px;
  font-size: 9.5px;
  font-weight: 500;
  color: var(--sn-ink-dark);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font-family: 'Inter', sans-serif;
}
.sn-reveal-mock-reaction-emoji {
  font-size: 16px;
  line-height: 1;
  color: var(--brand-mock-accent, #0891B2);
}
/* Canonical reaction icons are inline SVGs (matching the login reveal
   preview + scan.html), not emoji glyphs — size them to the icon slot. */
.sn-reveal-mock-reaction-emoji svg { width: 15px; height: 15px; display: block; }
.sn-multibrand-row .sn-reveal-mock-reaction-emoji svg { width: 12px; height: 12px; }
.sn-reveal-mock-footer {
  font-size: 8.5px;
  color: var(--sn-ink-soft);
  margin-top: auto;
  padding-top: 8px;
  border-top: 1px solid var(--sn-line);
  width: 100%;
  display: flex;
  justify-content: space-between;
  font-family: 'Inter', sans-serif;
}
/* Optional message (canonical reveal slot 5) + the REQUIRED Action CTA
   (slot 6). Both sit between the video and the 3-tap reaction, matching
   scan.html's order. The CTA uses a deep cyan (AA-safe with white text,
   mirroring the .scan-action-cta fix), not the bright accent. */
.sn-reveal-mock-msg {
  font-size: 10px;
  line-height: 1.45;
  color: var(--sn-ink-soft);
  font-family: 'Inter', sans-serif;
  text-align: center;
  margin-top: 3px;
}
/* Optional brand-about (canonical reveal slot 8) — a small subordinate
   "This is [brand]." chapter between the 3-tap reaction and the footer,
   matching scan.html's order. Optional: omit it and the reveal skips it. */
.sn-reveal-mock-about {
  width: 100%;
  margin-top: 10px;
  text-align: center;
  font-family: 'Inter', sans-serif;
}
.sn-reveal-mock-about .sn-reveal-mock-about-eyebrow {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 7.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  opacity: 0.7;
}
.sn-reveal-mock-about .sn-reveal-mock-about-body {
  font-size: 9.5px;
  line-height: 1.5;
  color: var(--sn-ink-soft);
  margin-top: 2px;
}
.sn-multibrand-phone .sn-reveal-mock-about .sn-reveal-mock-about-eyebrow,
.sn-multibrand-phone .sn-reveal-mock-about .sn-reveal-mock-about-body {
  color: var(--brand-mock-ink-muted, rgba(27, 42, 63, 0.6));
}
.sn-reveal-mock-cta {
  width: 100%;
  margin-top: 7px;
  padding: 8px 10px;
  border-radius: 999px;
  background: #075F73;
  color: #FFFFFF;
  font-size: 10px;
  font-weight: 600;
  font-family: 'Inter', sans-serif;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}

/* ═══════════════════════════════════════════════════════════════════
   MULTI-BRAND PHONE ROW — three phones, three brand looks
   Demonstrates per-tenant customization. Same template, different
   brand identity, all driven by tenant config (no per-brand engineering).
   ═══════════════════════════════════════════════════════════════════ */
.sn-multibrand-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(20px, 3vw, 36px);
  justify-items: center;
  margin: 32px 0;
}
@media (max-width: 880px) {
  .sn-multibrand-row { grid-template-columns: 1fr; gap: 32px; }
}
.sn-multibrand-row .sn-phone {
  width: 220px;
  height: 460px;
  padding: 8px;
  border-radius: 34px;
}
.sn-multibrand-row .sn-phone-screen { border-radius: 26px; }
.sn-multibrand-row .sn-phone-notch {
  width: 70px;
  height: 18px;
  border-bottom-left-radius: 10px;
  border-bottom-right-radius: 10px;
}
.sn-multibrand-row .sn-phone-status {
  height: 24px;
  font-size: 9px;
  padding: 0 18px;
}
.sn-multibrand-row .sn-reveal-mock {
  padding: 8px 16px 12px;
  gap: 8px;
}
.sn-multibrand-row .sn-reveal-mock-logo { font-size: 9px; letter-spacing: 0.22em; }
.sn-multibrand-row .sn-reveal-mock-greeting { font-size: 19px; }
.sn-multibrand-row .sn-reveal-mock-from { font-size: 9px; }
.sn-multibrand-row .sn-reveal-mock-eyebrow { font-size: 7.5px; }
.sn-multibrand-row .sn-reveal-mock-video { aspect-ratio: 9 / 16; border-radius: 8px; }
.sn-multibrand-row .sn-reveal-mock-play { width: 34px; height: 34px; }
.sn-multibrand-row .sn-reveal-mock-play::after {
  border-left: 11px solid var(--brand-mock-ink, var(--sn-ink-dark));
  border-top: 7px solid transparent;
  border-bottom: 7px solid transparent;
  margin-left: 3px;
}
.sn-multibrand-row .sn-reveal-mock-reactions { gap: 4px; margin-top: 2px; }
.sn-multibrand-row .sn-reveal-mock-reaction {
  font-size: 7.5px;
  padding: 4px 2px 4px;
}
.sn-multibrand-row .sn-reveal-mock-reaction-emoji { font-size: 12px; }
.sn-multibrand-row .sn-reveal-mock-footer { font-size: 6.5px; padding-top: 4px; }
.sn-multibrand-row .sn-reveal-mock-hair { width: 18px; }

/* Per-brand color variants — driven by inline CSS variables on the parent.
   Set --brand-mock-paper, --brand-mock-ink, --brand-mock-accent on the
   .sn-phone wrapper to retheme the entire reveal page mock. */
.sn-multibrand-phone .sn-phone-screen {
  background: var(--brand-mock-paper, #FFFFFF);
  color: var(--brand-mock-ink, #1B2A3F);
}
.sn-multibrand-phone .sn-reveal-mock-logo,
.sn-multibrand-phone .sn-reveal-mock-greeting,
.sn-multibrand-phone .sn-reveal-mock-greeting span,
.sn-multibrand-phone .sn-reveal-mock-reaction {
  color: var(--brand-mock-ink, #1B2A3F);
}
.sn-multibrand-phone .sn-reveal-mock-eyebrow,
.sn-multibrand-phone .sn-reveal-mock-from,
.sn-multibrand-phone .sn-reveal-mock-msg,
.sn-multibrand-phone .sn-reveal-mock-footer {
  color: var(--brand-mock-ink-muted, rgba(27, 42, 63, 0.6));
}
.sn-multibrand-phone .sn-reveal-mock-hair {
  background: var(--brand-mock-accent, var(--sn-ink-dark));
}
.sn-multibrand-phone .sn-reveal-mock-video {
  background: linear-gradient(135deg, var(--brand-mock-video-from, #1F2D44) 0%, var(--brand-mock-video-to, #06101F) 100%);
}
.sn-multibrand-phone .sn-reveal-mock-reaction {
  background: var(--brand-mock-card, #FFFFFF);
  border-color: var(--brand-mock-line, rgba(27, 42, 63, 0.12));
}
.sn-multibrand-phone .sn-phone-status { color: var(--brand-mock-ink, #1B2A3F); }
.sn-multibrand-caption {
  margin-top: 14px;
  text-align: center;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
}

/* ═══════════════════════════════════════════════════════════════════
   BRAND-CUSTOMIZATION STUDIO — form + live phone preview
   Shows what the self-service onboarding looks like.
   ═══════════════════════════════════════════════════════════════════ */
.sn-studio {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: clamp(28px, 4vw, 56px);
  align-items: center;
  background: var(--sn-paper-deep);
  border: 1px solid var(--sn-line);
  border-radius: 18px;
  padding: clamp(28px, 4vw, 48px);
  margin: 32px 0;
}
@media (max-width: 880px) {
  .sn-studio { grid-template-columns: 1fr; gap: 32px; }
}
.sn-studio-form {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.sn-studio-form-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sn-studio-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
}
.sn-studio-input,
.sn-studio-color-row,
.sn-studio-upload,
.sn-studio-fonts {
  background: var(--sn-white);
  border: 1px solid var(--sn-line);
  border-radius: 8px;
  padding: 12px 14px;
  font-family: 'Inter', sans-serif;
  font-size: 14px;
  color: var(--sn-ink-dark);
  display: flex;
  align-items: center;
  gap: 10px;
}
.sn-studio-color-row {
  justify-content: space-between;
  padding: 8px 12px 8px 8px;
}
.sn-studio-swatch {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
}
.sn-studio-swatch-chip {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  border: 1px solid var(--sn-line);
  flex-shrink: 0;
}
.sn-studio-hex {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  color: var(--sn-ink-soft);
}
.sn-studio-color-label {
  font-family: 'Inter', sans-serif;
  font-size: 13px;
  font-weight: 500;
  color: var(--sn-ink-dark);
}
.sn-studio-upload {
  background: var(--sn-white);
  border: 1.5px dashed var(--sn-ink-dark);
  justify-content: center;
  padding: 14px;
  font-size: 13px;
  color: var(--sn-ink-soft);
}
.sn-studio-upload-icon {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  background: var(--sn-ink-dark);
  color: var(--sn-cream);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: 'Inter', sans-serif;
  font-size: 13px;
  font-weight: 700;
  margin-right: 8px;
}
.sn-studio-fonts {
  justify-content: space-between;
}
.sn-studio-fonts-active {
  font-family: var(--sn-font-display);
  font-size: 18px;
  font-style: normal;
  color: var(--sn-ink-dark);
}
.sn-studio-cta {
  margin-top: 8px;
  padding: 12px 18px;
  background: var(--sn-ink-dark);
  color: var(--sn-cream);
  border-radius: 8px;
  font-family: 'Inter', sans-serif;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-align: center;
  align-self: flex-start;
}
.sn-studio-preview {
  position: relative;
}
.sn-studio-preview .sn-phone {
  width: 240px;
  height: 500px;
  margin: 0 auto;
}
.sn-studio-preview-tag {
  position: absolute;
  top: 14px;
  right: -12px;
  background: var(--sn-ink-dark);
  color: var(--sn-cream);
  padding: 6px 12px;
  border-radius: 999px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  z-index: 10;
  box-shadow: 0 4px 12px -4px rgba(12, 27, 46, 0.18);
}

/* ═══════════════════════════════════════════════════════════════════
   ONBOARDING STEPS — 5-step horizontal flow
   ═══════════════════════════════════════════════════════════════════ */
.sn-onboarding-flow {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 16px;
  margin: 32px 0 24px;
  position: relative;
}
.sn-onboarding-flow::before {
  content: '';
  position: absolute;
  top: 22px;
  left: 8%;
  right: 8%;
  height: 2px;
  background: linear-gradient(90deg, transparent 0%, var(--sn-ink-dark) 15%, var(--sn-ink-dark) 85%, transparent 100%);
  opacity: 0.18;
  z-index: 0;
}
@media (max-width: 800px) {
  .sn-onboarding-flow { grid-template-columns: 1fr; gap: 18px; }
  .sn-onboarding-flow::before { display: none; }
}
.sn-onboarding-step {
  position: relative;
  z-index: 1;
  background: var(--sn-white);
  border: 1px solid var(--sn-line);
  border-radius: 10px;
  padding: 18px 16px 14px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  transition: border-color 0.2s ease, transform 0.2s ease;
}
.sn-onboarding-step:hover {
  border-color: var(--sn-ink-dark);
  transform: translateY(-2px);
}
.sn-onboarding-step-num {
  width: 28px;
  height: 28px;
  background: var(--sn-ink-dark);
  color: var(--sn-cream);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Inter', sans-serif;
  font-size: 12px;
  font-weight: 700;
  font-feature-settings: 'tnum' 1;
}
.sn-onboarding-step-title {
  font-family: 'Inter', sans-serif;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--sn-ink-dark);
  letter-spacing: -0.005em;
  line-height: 1.25;
}
.sn-onboarding-step-time {
  font-family: 'JetBrains Mono', monospace;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
}

/* ───── TYPOGRAPHY ──────────────────────────────────────────────────
   April 28 v3: Inter for all headings (display + UI + body).
   Matches Stripe-circle convention (Stripe Söhne, Mercury Inter,
   Linear Inter, Vercel Geist — all functionally similar sans-serif).
   Fraunces was tried for "research authority via serif" but read as
   quirky/flouncy. Warmth now comes from cream surface + coral accent
   + writing voice — not typography.

   ─────────────────────────────────────────────────────────────────── */
h1 {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.05;
  font-size: clamp(2.5rem, 5vw, 4rem);
  color: var(--sn-ink-dark);
  text-wrap: balance;
}
h2 {
  font-family: 'Inter', system-ui, -apple-system, sans-serif;
  font-weight: 700;
  letter-spacing: -0.032em;
  line-height: 1.08;
  font-size: clamp(2.15rem, 4.3vw, 3.4rem);
  color: var(--sn-ink-dark);
  text-wrap: balance;
}
h3 {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.25;
  font-size: clamp(1.25rem, 2vw, 1.5rem);
  color: var(--sn-ink-dark);
  text-wrap: balance;
}
h4 {
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: 600;
  letter-spacing: -0.005em;
  line-height: 1.3;
  font-size: 1.0625rem;
  color: var(--sn-ink-dark);
  text-wrap: balance;
}
.sn-lede { text-wrap: pretty; }
p { text-wrap: pretty; }
/* Inline text link — cyan + underline so an in-copy link reads as a link
   (base `a` is color:inherit/no-underline, which hides links inside body copy). */
.sn-textlink {
  color: var(--sn-link, #0E7490);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  font-weight: 500;
}
.sn-textlink:hover { text-decoration-thickness: 2px; }
h1 em, h2 em {
  font-style: normal;
  color: var(--sn-spark-deep);
  font-weight: 600;
}
p { color: var(--sn-ink-soft); }
strong { color: var(--sn-ink-dark); font-weight: 600; }

.sn-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-accent);
  margin-bottom: 18px;
}
/* Narrative-spine section numeral — tiny mono "01–10" prefix that
   sits inside the eyebrow on each homepage section. Reads as a
   running argument index and gives the page one continuous through-
   line without adding a heavy decorator. */
.sn-eyebrow-num {
  display: inline-block;
  margin-right: 10px;
  padding-right: 10px;
  border-right: 1px solid currentColor;
  /* 0.55 blended navy on white is 3.68:1 — below AA for 11px text.
     0.72 lands ~5.5:1 and is visually indistinguishable at this size. */
  opacity: 0.72;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "lnum" 1;
}

/* ─── Progressive disclosure — shared <details>/<summary> system ───
   Used wherever we have content the buyer MIGHT want to read but
   shouldn't be force-fed: research source detail, about commitment
   explanations, hiw role split, etc.

   Native <details> gets keyboard a11y, screen-reader behavior, and
   "open by default" via the open attribute — for free. We just style
   the summary + add a subtle chevron rotation.

   Usage:
     <details class="sn-disclose">
       <summary><span class="sn-disclose-label">Read summary</span></summary>
       <div class="sn-disclose-body">…</div>
     </details>
*/
.sn-disclose {
  margin: 0;
}
.sn-disclose > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sn-spark-deep);
  padding: 6px 0;
  border-bottom: 1px solid rgba(8, 145, 178, 0.32);
  transition: color 0.15s ease, border-color 0.15s ease;
}
.sn-disclose > summary::-webkit-details-marker { display: none; }
.sn-disclose > summary::marker { content: ""; }
.sn-disclose > summary::after {
  content: "";
  width: 7px; height: 7px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  margin-top: -3px;
  margin-left: 2px;
  transition: transform 0.22s ease;
}
.sn-disclose[open] > summary {
  color: var(--sn-ink-dark);
  border-bottom-color: var(--sn-ink-dark);
}
.sn-disclose[open] > summary::after {
  transform: rotate(-135deg);
  margin-top: 1px;
}
.sn-disclose > summary:hover {
  color: var(--sn-spark-deep);
  border-bottom-color: var(--sn-spark-deep);
}
.sn-disclose > summary:focus-visible {
  outline: 2px solid var(--sn-spark);
  outline-offset: 3px;
  border-radius: 2px;
}
.sn-disclose-body {
  padding-top: 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* "Read X" + "Hide" toggle — show different summary text in open vs closed.
   The .sn-disclose-when-closed shows when not open; .sn-disclose-when-open
   shows when open. CSS handles both — no JS. */
.sn-disclose .sn-disclose-when-open { display: none; }
.sn-disclose[open] .sn-disclose-when-closed { display: none; }
.sn-disclose[open] .sn-disclose-when-open { display: inline; }

/* ─── "You'll have" outcome chip — shared utility ───
   The same pattern used per-phase on hiw and on the pricing
   calculator result. Generic so any page can drop one in to
   anchor the buyer in user-value (the ARTIFACT they walk away
   with) instead of just describing activity.

   Usage:
     <div class="sn-outcome">
       <span class="sn-outcome-key">You'll have</span>
       <span class="sn-outcome-val">A <strong>thing</strong>...</span>
     </div>
*/
.sn-outcome {
  margin-top: 4px;
  padding: 12px 14px 12px 16px;
  background: var(--sn-mist, #F6F9FC);
  border: 1px solid var(--sn-hairline, #E3E8EE);
  border-radius: 8px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.sn-outcome-key {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-spark-deep);
  flex-shrink: 0;
  padding-top: 1px;
  line-height: 1.4;
  white-space: nowrap;
}
.sn-outcome-val {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--sn-ink-dark);
  font-weight: 500;
}
.sn-outcome-val strong { font-weight: 700; color: var(--sn-ink-darkest, #0A2540); }

/* ─── Glossary term — inline tooltip system ───
   We name a research methodology (BBMR), and use research-jargon terms
   that buyers can't be expected to know cold (BIPA, aggregate-only,
   cohort, per-recipient, sample floor). Inline tooltips define them on
   the page so the reader doesn't have to leave to Google something.

   Usage:
     <span class="sn-term" tabindex="0">
       term<span class="sn-term-tip">definition shown on hover/focus/tap</span>
     </span>

   Behavior:
     - Subtle dotted underline tells the reader "more info available"
     - Hover (mouse) → shows tooltip
     - Focus (keyboard tab) → shows tooltip (a11y)
     - Tap (touch) → tabindex makes :focus-within fire on tap, shows tip
     - Tooltip max-width clamps to 280px, wraps, tabular-nums for any nums
     - Cyan-accent left border so the tip carries our brand identity */
.sn-term {
  position: relative;
  display: inline;
  cursor: help;
  border-bottom: 1px dashed currentColor;
  border-bottom-color: var(--sn-ink-muted);
  outline: none;
  /* Prevent accidental selection of the inner tip text on click */
  -webkit-tap-highlight-color: transparent;
}
.sn-term:hover,
.sn-term:focus-visible {
  border-bottom-color: var(--sn-spark-deep);
  border-bottom-style: solid;
}
.sn-term-tip {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  width: max-content;
  /* min() keeps the centered tip from poking past the right edge on
     narrow phones (<~380px); normal phones (>=390px) stay at 280px. */
  max-width: min(280px, calc(100vw - 100px));
  padding: 12px 14px;
  background: var(--sn-ink-darkest, #0A2540);
  color: rgba(255, 255, 255, 0.94);
  border-radius: 8px;
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: 0;
  text-transform: none;
  text-align: left;
  text-decoration: none;
  white-space: normal;
  box-shadow: 0 12px 32px -10px rgba(10, 37, 64, 0.40);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.22s ease;
  z-index: 100;
}
.sn-term-tip strong { color: #FFFFFF; font-weight: 600; }
/* Caret (small triangle pointing down to the term) */
.sn-term-tip::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: var(--sn-ink-darkest, #0A2540);
}
.sn-term:hover .sn-term-tip,
.sn-term:focus-visible .sn-term-tip,
.sn-term:focus-within .sn-term-tip {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
/* When the term is near the right edge of the viewport, anchor the
   tooltip to the right rather than centered (prevents it overflowing
   off-screen). Authors can opt in by adding .is-right. */
.sn-term-tip.is-right {
  left: auto;
  right: 0;
  transform: translateY(4px);
}
.sn-term-tip.is-right::after {
  left: auto;
  right: 14px;
  transform: none;
}
.sn-term:hover .sn-term-tip.is-right,
.sn-term:focus-within .sn-term-tip.is-right { transform: translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .sn-term-tip { transition: opacity 0.1s ease; transform: none; }
  .sn-term:hover .sn-term-tip,
  .sn-term:focus-within .sn-term-tip { transform: none; }
}
.sn-lede {
  font-size: clamp(1.0625rem, 1.5vw, 1.25rem);
  line-height: 1.55;
  color: var(--sn-ink-soft);
  max-width: 640px;
}
/* Section-level lede — sub-section paragraph that sits beneath an h2.
   Smaller than .sn-lede (which sits beneath an h1). */
.sn-lede-section {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--sn-ink-soft);
  max-width: 640px;
}
/* Card-internal paragraph — for tight grid cards. */
.sn-text-card {
  font-size: 0.84375rem;  /* 13.5px @ 16px root */
  line-height: 1.55;
  color: var(--sn-ink-soft);
}

/* ───── TOC STRIP (horizontal in-page nav for long pages) ─────
   Compact anchor row that sits below the hero on long pages
   (research, methods, how-it-works). MOBILE-ONLY: at <=980px the
   sticky right rail (rs-nav / hiw-nav) is hidden, so the strip is
   the only in-page navigation. At >=981px the right rail handles
   navigation and the strip becomes redundant — hidden via the
   media query below. Horizontally scrollable when items overflow
   the viewport so the row never wraps awkwardly.
   Markup:
     <nav class="sn-toc-strip" aria-label="On this page">
       <a class="sn-toc-strip-item" href="#section-1">
         <span class="sn-toc-strip-num">01</span>
         Section title
       </a>
       …
     </nav>
   Place after </header> of the page-specific hero, before the first
   content section. Wrap inside the page's container so it inherits
   horizontal padding from the parent. */
.sn-toc-strip {
  display: flex;
  align-items: stretch;
  gap: 6px;
  padding: 10px;
  margin: 24px auto 0;
  background: linear-gradient(180deg, #FFFFFF 0%, #FBFCFD 100%);
  border: 1px solid var(--sn-line);
  border-radius: 12px;
  box-shadow: 0 1px 2px rgba(10, 37, 64, 0.04), 0 8px 22px -14px rgba(10, 37, 64, 0.08);
  overflow-x: auto;
  scrollbar-width: thin;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.sn-toc-strip::-webkit-scrollbar { height: 4px; }
.sn-toc-strip::-webkit-scrollbar-thumb { background: var(--sn-line); border-radius: 2px; }
.sn-toc-strip-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--sn-ink-soft);
  white-space: nowrap;
  scroll-snap-align: start;
  flex-shrink: 0;
  transition: background 0.15s ease, color 0.15s ease;
}
.sn-toc-strip-item:hover,
.sn-toc-strip-item:focus-visible {
  background: var(--sn-paper-deep);
  color: var(--sn-ink-dark);
}
.sn-toc-strip-num {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--sn-spark-deep);
  background: rgba(6, 182, 212, 0.10);
  padding: 3px 6px;
  border-radius: 4px;
  line-height: 1;
}
.sn-toc-strip-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  padding: 9px 6px 9px 14px;
  flex-shrink: 0;
  align-self: center;
}
/* Hide on desktop where the right sticky rail handles the same job.
   Two parallel nav controls listing the same pillars / phases /
   sections felt cluttered at 1024px+; the rail is more elegant. */
@media (min-width: 981px) {
  .sn-toc-strip { display: none; }
}

/* ───── HEADER + NAV ──────────────────────────────────────────────── */
.sn-header {
  position: sticky;
  top: 0;
  z-index: 50;
  /* Solid white (May 2026 cohesion pass). The bar used to be
     translucent (rgba 0.85) + backdrop-blur, so each page's hero
     gradient bled through it by a different amount (cyan wash behind
     the logo on /methods; top-right tint on /index) — the identical nav
     markup read subtly different page-to-page. Making it opaque removes
     ALL gradient bleed, so the nav chrome renders pixel-identical on
     every page (the only intended per-page variance is the current-page
     link highlight). */
  background: #FFFFFF;
  border-bottom: 1px solid var(--sn-line-soft);
  /* Header bar spans the full viewport width — Stripe / Linear / Vercel
     pattern. Logo sits flush-left (against the 32px outer padding), nav
     items sit flush-right. This is intentionally separate from the
     content max-width below: chrome runs the full viewport, content
     stays inset to the 1240px container. The slight visual offset
     between the logo's left edge and the H1's left edge is the
     standard SaaS convention and reads as "the chrome is the chrome,
     the content is the content." */
  padding: 0 32px;
}
/* ═══════════════════════════════════════════════════════════════════
   ANIMATION PAUSE — WCAG 2.2.2 universal stop control.
   When the footer pause button is engaged (sets data-anim-paused="true"
   on <body> + persists to localStorage), every CSS keyframe animation
   pauses at its current frame. The hero video + JS-driven timer cycles
   are handled separately in site-anim.js + the index page setup IIFEs.
   ═══════════════════════════════════════════════════════════════════ */
body[data-anim-paused="true"] *,
body[data-anim-paused="true"] *::before,
body[data-anim-paused="true"] *::after {
  animation-play-state: paused !important;
}

/* Footer pause-animations chip — small text + icon control in the
   legal footer row. Discoverable but unobtrusive. Mirrors the link
   styling already in .sn-footer-legal so it reads as a peer of the
   copyright/email row, not a CTA. */
.sn-anim-toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 12px;
  margin-left: 10px;
  border: 1px solid var(--sn-line);
  border-radius: 999px;
  background: transparent;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--sn-ink-muted);
  cursor: pointer;
  transition: border-color .18s ease, color .18s ease, background .18s ease;
}
.sn-anim-toggle:hover,
.sn-anim-toggle:focus-visible {
  border-color: var(--sn-spark-deep);
  color: var(--sn-spark-deep);
  background: rgba(6, 182, 212, 0.04);
  outline: none;
}
.sn-anim-toggle svg {
  width: 11px;
  height: 11px;
  flex-shrink: 0;
}
/* Swap pause↔play icon via data-anim-paused state. The button's
   markup includes both icons; the inactive one is hidden. */
.sn-anim-toggle .sn-anim-toggle-icon-play { display: none; }
body[data-anim-paused="true"] .sn-anim-toggle .sn-anim-toggle-icon-pause { display: none; }
body[data-anim-paused="true"] .sn-anim-toggle .sn-anim-toggle-icon-play { display: inline-block; }

.sn-header-inner {
  padding: 14px 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  width: 100%;
  /* Lock min-height so the nav bar is the same vertical size on
     every page regardless of which elements sit inside it (the
     index used to carry a ⌘K chip that nudged the height; other
     pages didn't). The 64px floor matches the --sn-header-h
     token and guarantees uniform chrome across surfaces. */
  min-height: 64px;
}
.sn-logo {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--sn-ink-dark);
}
/* Logo mark — original ornate S+N monogram silhouette, rendered as a
   unified white silhouette on a navy disc. The original artwork uses
   rotational symmetry: one half of a heart-shape is rotated 180° to
   create the other half, and the resulting interlocking form reads as
   both an S+N monogram AND as two halves of a heart ("communication
   takes two"). Both readings depend on the mark being visually unified —
   splitting the halves into different colors exposes the rotational
   asymmetry and breaks the "one heart" reading.
   Markup: <span class="sn-logo-mark"><img src="assets/logo-sn-mark.svg" alt=""></span>
   The wrapping span paints the navy disc; the inner <img> is an SVG that
   embeds the original PNG and applies an feColorMatrix filter to recolor
   the silhouette to white. The SVG bakes its own color, so no CSS
   filter chain is needed at runtime. */
/* The brand mark ships as the navy rounded square + the white S+N
   baked into a single SVG/PNG asset, so the wrapping span doesn't
   paint its own background. Container is a sizing slot — let the
   mark's own art breathe. */
.sn-logo-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  box-sizing: border-box;
}
.sn-logo-mark img {
  width: 100%;
  height: 100%;
  display: block;
}

/* Variant retained for backward-compat. The new mark doesn't use it
   directly, but any legacy callers passing .sn-logo-mark--turquoise
   still get a turquoise tile (rendered as a CSS background, behind a
   transparent SVG, so opt-in only). */
.sn-logo-mark--turquoise {
  background-color: var(--sn-spark);
  border-radius: 8px;
}
.sn-nav {
  display: flex;
  align-items: center;
  gap: 4px;
}
.sn-nav-link {
  position: relative;
  font-size: 14px;
  font-weight: 500;
  color: var(--sn-ink-soft);
  padding: 8px 14px;
  border-radius: var(--sn-radius-sm);
  transition: color 0.18s ease;
}
/* Linear-style underline reveal — hairline cyan stroke grows from
   the left on hover. Cleaner than the prior background-pill hover
   for a tech-forward nav feel. */
.sn-nav-link::after {
  content: '';
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 4px;
  height: 1.5px;
  background: var(--sn-spark);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.26s cubic-bezier(0.2, 0.8, 0.2, 1);
  pointer-events: none;
}
.sn-nav-link:hover { color: var(--sn-ink-darkest); }
.sn-nav-link:hover::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  .sn-nav-link::after { transition: none; }
}
/* Sign-in link — small, secondary, separated from primary nav by a
   thin divider. Routes to /login.html (stub until first-partner
   onboarding ships the real customer portal). */
.sn-nav-signin {
  font-size: 13px;
  color: var(--sn-ink-muted);
  margin-left: 8px;
  padding-left: 14px;
  border-left: 1px solid var(--sn-line);
  border-radius: 0;
}
.sn-nav-signin:hover {
  background: transparent;
  color: var(--sn-spark-deep);
}
.sn-nav-cta {
  margin-left: 12px;
}

/* ─── HAMBURGER toggle (mobile nav button) ───
   Hidden at desktop. Shown at <=860px where the desktop nav goes
   off-screen. The button is a 3-bar icon that animates to an X
   when [data-mobile-open="true"] is on the page <body>.
   Markup:
     <button class="sn-nav-toggle" type="button"
             aria-label="Open menu"
             aria-expanded="false"
             aria-controls="sn-nav-primary">
       <span class="sn-nav-toggle-bar"></span>
       <span class="sn-nav-toggle-bar"></span>
       <span class="sn-nav-toggle-bar"></span>
     </button>
   Sits flush-right next to the logo. Touch target is 44×44 (a11y). */
.sn-nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  background: transparent;
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-sm);
  position: relative;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  padding: 0;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
  flex-shrink: 0;
  /* Force the toggle flush-right inside .sn-header-inner, regardless
     of how flex distributes the 3rd child (the fixed-position nav,
     which Chrome can still allocate flex space for in narrow layouts).  */
  margin-left: auto;
}
.sn-nav-toggle:hover { background: var(--sn-paper-deep); border-color: var(--sn-spark); }
.sn-nav-toggle-bar {
  width: 20px;
  height: 2px;
  background: var(--sn-ink-dark);
  border-radius: 1px;
  transition: transform 0.2s ease, opacity 0.15s ease;
}
[data-mobile-open="true"] .sn-nav-toggle-bar:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
[data-mobile-open="true"] .sn-nav-toggle-bar:nth-child(2) {
  opacity: 0;
}
[data-mobile-open="true"] .sn-nav-toggle-bar:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* ───── BUTTONS ───────────────────────────────────────────────────── */
.sn-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  padding: 11px 20px;
  border-radius: var(--sn-radius-sm);
  border: 1px solid transparent;
  transition: transform 0.15s ease, background 0.15s ease, border 0.15s ease, color 0.15s ease;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}
/* Keyboard focus ring for the primary CTA — the most-clicked control on the
   site. Larger offset than the global rule so the ring clears the button's
   fill + shadow and stays visible on both light and dark CTA variants. */
.sn-btn:focus-visible {
  outline: 2px solid var(--sn-spark-deep);
  outline-offset: 3px;
}
.sn-btn-primary {
  background: var(--sn-accent);
  color: #FFFFFF;
  box-shadow: 0 1px 2px rgba(10, 37, 64, 0.16), 0 0 0 1px rgba(10, 37, 64, 0.06);
}
.sn-btn-primary:hover {
  background: var(--sn-accent-soft);
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(10, 37, 64, 0.22), 0 0 0 1px rgba(10, 37, 64, 0.06);
}
.sn-btn-secondary {
  background: #FFFFFF;
  color: var(--sn-ink-dark);
  border-color: var(--sn-line);
  box-shadow: 0 1px 2px rgba(50, 50, 93, 0.04);
}
.sn-btn-secondary:hover {
  background: var(--sn-paper-deep);
  border-color: var(--sn-spark);
  color: var(--sn-accent);
}
.sn-btn-light {
  background: var(--sn-cream);
  color: var(--sn-ink-darkest);
}
.sn-btn-light:hover { background: var(--sn-white); transform: translateY(-1px); }
.sn-btn-dark-outline {
  background: transparent;
  color: var(--sn-cream);
  border-color: rgba(255, 255, 255, 0.30);
}
.sn-btn-dark-outline:hover {
  border-color: var(--sn-cream);
  background: rgba(255, 255, 255, 0.08);
}
.sn-btn-lg {
  padding: 14px 24px;
  font-size: 15px;
}
/* Arrow-slide micro on every CTA — Stripe/Vercel pattern. The
   arrow shifts right on hover with an eased curve (deliberate, not
   nervous). Applied broadly so any element with a `.arrow` child
   gets the same response — buttons, inline links, CTAs in cards. */
.arrow { display: inline-block; transition: transform 0.22s cubic-bezier(0.2, 0.8, 0.2, 1); }
.sn-btn:hover .arrow,
a:hover > .arrow,
.sn-dash-widget-cta:hover .arrow { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .arrow { transition: none; }
}

/* ───── SECTIONS / CONTAINER ──────────────────────────────────────── */
/* Section vertical rhythm — values match the Stripe-pattern defaults
   the rest of the design system is tuned to. Wider padding (e.g.,
   72–136px) overshoots and makes the page feel "zoomed in" on
   13–14" laptops. */
.sn-section {
  padding: clamp(56px, 8vw, 104px) 28px;
}
.sn-section-narrow { padding: clamp(44px, 6vw, 76px) 28px; }

/* Alternating section background — Stripe alternates pure white with
   #F6F9FC light blue-tinted off-white for visual rhythm. Apply to every
   other content section (or to specific ones that benefit from the
   contrast — usually the "audience grid" / "logo strip" / "pricing"
   sections, which feel grounded by a tinted bg). */
.sn-section-alt {
  background: var(--sn-paper-deep);
}

/* ═══════════════════════════════════════════════════════════════════
   ICONOGRAPHY + STEP NUMBERS
   Designed for "scroll-and-understand" scannability. Every card section
   gets a category icon or numbered step. Icons are 24×24 line-style
   SVGs at 1.75px stroke, picking up `currentColor` so they re-skin per
   surface (teal on light, white on dark). Step numbers are 40px circles
   with mono-font numerals — Stripe pattern for sequential commitments.
   ═══════════════════════════════════════════════════════════════════ */
.sn-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  display: inline-block;
}
.sn-icon-lg { width: 28px; height: 28px; }

/* Card icon container — sits at the top of a card, before the title.
   Icons take the bright turquoise spark color (the "interactive
   moment" register), against a soft turquoise tint background. On
   .sn-trust dark sections, icons brighten to spark-soft so they pop
   against navy bg. */
.sn-card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: var(--sn-spark-tint);
  color: var(--sn-spark-deep);
  margin-bottom: 4px;
}
.sn-trust .sn-card-icon {
  background: rgba(34, 211, 238, 0.10);
  color: var(--sn-spark-soft);
}

/* Numbered step badge — used for sequential commitment cards in the
   "Why independent" section. Bright turquoise border + text on white
   surface = "this is an interactive moment, scan top-to-bottom". */
.sn-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1.5px solid var(--sn-spark);
  color: var(--sn-spark-deep);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 4px;
  background: var(--sn-spark-tint);
}
.sn-trust .sn-step-num {
  border-color: var(--sn-spark-soft);
  color: var(--sn-spark-soft);
  background: rgba(34, 211, 238, 0.08);
}

/* Audience-card icon — smaller variant (36px) for the audience grid. */
.sn-audience-card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: var(--sn-spark-tint);
  color: var(--sn-spark-deep);
  margin-bottom: 14px;
}
.sn-audience-card-icon .sn-icon { width: 20px; height: 20px; }

/* Pricing-row dot — tiny turquoise dot beside each pricing-terms label.
   Bright spark color, calls the eye to each itemized commitment. */
.sn-pricing-terms li > span:first-child::before {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 12px;
  border-radius: 50%;
  background: var(--sn-spark);
  vertical-align: middle;
  margin-bottom: 1px;
}
.sn-container {
  max-width: var(--sn-container);
  margin: 0 auto;
}
.sn-container-narrow {
  max-width: var(--sn-container-narrow);
  margin: 0 auto;
}
/* Section header — eyebrow + h2 + lede. Current values are the
   design-system originals; they keep the head deliberate without
   crowding the page (680px / 64px / 18px would read as zoomed-in on
   13–14" laptops). */
.sn-section-head {
  max-width: 720px;
  margin: 0 auto 48px;
  text-align: center;
}
.sn-section-head h2, .sn-section-head h1 { margin-bottom: 14px; }
/* A page that leads with a section-head instead of a hero (e.g. contact.html)
   uses an <h1> here for correct document outline; keep it at section-heading
   scale, not the larger hero-h1 scale, so the layout is unchanged. */
.sn-section-head h1 {
  font-size: clamp(2.15rem, 4.3vw, 3.4rem);
  font-weight: 700;
  letter-spacing: -0.032em;
  line-height: 1.08;
}
.sn-section-head .sn-lede { margin: 0 auto; }
/* Variant for sections that read as a "letter" or "note" rather than
   a headline. Used by the About-page founder note and any future
   editorial-style sections. */
.sn-section-head-aligned-left {
  text-align: left;
  margin: 0 0 24px;
}
.sn-section-head-aligned-left .sn-lede { margin: 0; }
/* Use when stacking multiple section heads inside the same wrapper —
   adds top breathing room so subsequent rooms don't crash into the
   prior section's content. Paired with .sn-section-head-aligned-left
   on the FAQ page's three procurement rooms. */
.sn-section-head-spaced {
  margin-top: 64px;
}

/* Centered CTA row used by sections that close with a single button or
   a primary+secondary pair. Replaces ad-hoc inline-style hero-actions
   misuse from earlier IA passes. */
.sn-section-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 36px;
}

/* Small footnote sentence that sits beneath a section's main grid
   (e.g. the integration "Shopify app on the roadmap" line). */
.sn-section-footnote {
  text-align: center;
  margin-top: 28px;
  color: var(--sn-ink-muted);
  font-size: 13.5px;
  line-height: 1.55;
}
.sn-section-footnote strong { color: var(--sn-ink-dark); font-weight: 600; }
.sn-section-footnote a {
  color: var(--sn-ink-dark);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Pricing-section "what's negotiated" terms list. Two-column dl-style
   row layout — the term on the left, the value on the right. Stripe's
   pricing page uses a similar structure. */
.sn-pricing-terms {
  list-style: none;
  margin: 32px auto 0;
  padding: 8px 0;
  max-width: 520px;
  border-top: 1px solid var(--sn-line);
  border-bottom: 1px solid var(--sn-line);
}
.sn-pricing-terms li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 14px 4px;
  font-size: 14px;
}
.sn-pricing-terms li + li { border-top: 1px solid var(--sn-line); }
.sn-pricing-terms li > span:first-child {
  color: var(--sn-ink-muted);
}
.sn-pricing-terms li > span:last-child {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--sn-ink-dark);
  text-transform: uppercase;
}

/* Dark-surface variant of .sn-lede — used inside .sn-trust and other
   dark sections so the lede sits at the right contrast against navy. */
.sn-lede-on-dark { color: rgba(255, 255, 255, 0.72); }

/* Form disclaimer (small text under the contact form submit button) */
.sn-form-disclaimer {
  font-size: 12px;
  color: var(--sn-ink-muted);
  text-align: center;
  margin-top: 4px;
  line-height: 1.55;
}
.sn-form-disclaimer a {
  color: var(--sn-ink-soft);
  text-decoration: underline;
}

/* Email-aside under the contact form ("Prefer email?") */
.sn-form-aside {
  text-align: center;
  margin-top: 56px;
  padding-top: 32px;
  border-top: 1px solid var(--sn-line);
}
.sn-form-aside p {
  font-size: 13px;
  color: var(--sn-ink-muted);
  margin-bottom: 4px;
}
.sn-form-aside-email {
  font-family: 'JetBrains Mono', monospace;
  font-size: 14px;
  color: var(--sn-ink-dark);
  font-weight: 600;
}

/* Direct-booking shortcut card in the contact-form aside. Sits above
   the "What happens next" list as the fastest path for prospects who
   already know they want a kickoff slot. The Cal.com link short-
   circuits the email-tag loop entirely. */
.sn-aside-booking {
  display: flex;
  gap: 14px;
  padding: 16px 18px;
  background: linear-gradient(135deg, rgba(10, 37, 64, 0.05), rgba(10, 37, 64, 0.01));
  border: 1px solid rgba(10, 37, 64, 0.15);
  border-radius: 8px;
  align-items: flex-start;
}
.sn-aside-booking-icon {
  flex-shrink: 0;
  width: 36px; height: 36px;
  border-radius: 8px;
  background: rgba(10, 37, 64, 0.08);
  color: #0E7490;
  display: flex;
  align-items: center;
  justify-content: center;
}
.sn-aside-booking-h {
  margin: 0 0 4px;
  font-size: 14px;
  font-weight: 600;
  color: var(--sn-ink-dark);
  letter-spacing: -0.005em;
}
.sn-aside-booking-p {
  margin: 0 0 12px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--sn-ink-soft);
}
.sn-aside-booking .sn-btn {
  font-size: 12px;
  padding: 7px 12px;
}

/* Founder signature block — humanizes the wait without requiring a
   photo asset. Initials avatar in the brand palette, name + role
   beside it. Sits at the bottom of the contact aside and on the
   onboarding success state. */
.sn-founder-sig {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--sn-line);
}
.sn-founder-avatar {
  flex-shrink: 0;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: linear-gradient(135deg, #0A2540, #14325A);
  color: #FFF;
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  display: flex;
  align-items: center;
  justify-content: center;
}
.sn-founder-body { display: flex; flex-direction: column; gap: 1px; }
.sn-founder-name {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--sn-ink-dark);
  letter-spacing: -0.005em;
}
.sn-founder-role {
  font-size: 11.5px;
  color: var(--sn-ink-muted);
  font-style: italic;
}

/* ───── HERO LAYOUT ────────────────────────────────────────────────
   The hero now uses the Stripe-aligned light treatment defined earlier
   in this file (~line 386). Background = page (white), text = slate,
   subtle cool gradient on .sn-hero::before. The dark-hero override that
   used to live here was removed April 28 v9 — Stripe doesn't do dark
   marketing heros. Padding + h1/lede color now inherit from the
   light-hero block earlier in the file. */
.sn-hero {
  /* Compressed hero padding so the CTAs stay above the fold on
     13–14" laptops. The buyer's first paint should reveal the
     value-prop AND the call to action; the hero needs to fit in
     ~720–820px including the nav bar. 56+72 (128px) is the
     comfortable middle. */
  padding: 56px 28px 72px;
}
.sn-hero h1 {
  margin-bottom: 18px;
}
.sn-hero .sn-lede {
  max-width: 560px;
  margin-bottom: 28px;
}
.sn-hero-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 32px;
}

/* ───── Hero category note ─────
   Sits below .sn-hero-actions on the homepage. Small, muted "category"
   label + the BBMR term (with tooltip) + one-line definition. Reads
   as a quiet caption rather than competing with the lede or H1.
   Sits alongside the hero opening so the lede lands on the punchier
   "no surveys, no biometrics, no guessing" without a definitional
   clause running through it. */
.sn-hero-category-note {
  max-width: 560px;
  margin: 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--sn-ink-muted);
}
.sn-hero-category-note strong { color: var(--sn-ink-dark); font-weight: 600; }
.sn-hero-category-note-label {
  display: inline-block;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-spark-deep);
  margin-right: 8px;
  padding: 3px 8px;
  background: rgba(6, 182, 212, 0.08);
  border: 1px solid rgba(6, 182, 212, 0.20);
  border-radius: 4px;
  vertical-align: 1px;
}
.sn-hero-trust {
  display: flex;
  gap: 32px;
  flex-wrap: wrap;
  padding-top: 32px;
  border-top: 1px solid rgba(255, 255, 255, 0.10);
}
.sn-hero-trust-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sn-hero-trust-num {
  font-family: var(--sn-font-display);
  font-style: normal;
  font-size: 28px;
  font-weight: 500;
  color: var(--sn-cream);
  line-height: 1;
}
.sn-hero-trust-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.60);
}

/* HERO VISUAL — wrapper only (the dashboard-preview mockup it once
   contained was removed; .sn-hero-visual is still used as a layout
   container in index.html for the live hero column). */
.sn-hero-visual {
  position: relative;
}

/* Compact label above the hero phone. A prose caption here would
   duplicate the left-column lede and push the phone below the fold;
   this tag just names the view ("Recipient view · Live demo") in a
   small mono so the phone reads as the visual centerpiece. */
.sn-hero-visual-tag {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  text-align: center;
  margin: 0 auto 14px;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
}
.sn-hero-visual-tag-sep { color: var(--sn-spark-deep); }

/* ───── PROBLEM SECTION ───────────────────────────────────────────── */
.sn-problem {
  background: var(--sn-paper);
}
.sn-problem-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  margin-top: 56px;
}
.sn-problem-stat {
  text-align: center;
  padding: 32px 24px;
  background: var(--sn-cream);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-lg);
}
.sn-problem-stat-num {
  font-family: var(--sn-font-display);
  font-style: normal;
  font-size: clamp(2.5rem, 4vw, 3.5rem);
  font-weight: 500;
  color: var(--sn-ink-dark);
  line-height: 1;
  letter-spacing: -0.02em;
  margin-bottom: 12px;
}
.sn-problem-stat-label {
  font-size: 14px;
  color: var(--sn-ink-soft);
  line-height: 1.5;
}
.sn-problem-stat-label strong { color: var(--sn-ink-dark); }

/* ───── HOW IT WORKS — 3-step ─────────────────────────────────────── */
.sn-how-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
  margin-top: 56px;
}
.sn-how-step {
  position: relative;
  padding: 32px 28px;
  background: var(--sn-cream);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-lg);
}
.sn-how-step-num {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--sn-gold-deep);
  margin-bottom: 16px;
}
.sn-how-step h3 { margin-bottom: 12px; }

/* ───── PRODUCT TILES ─────────────────────────────────────────────── */
.sn-product-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  margin-top: 56px;
}
.sn-product-tile {
  padding: 36px 32px;
  background: var(--sn-white);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-lg);
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.sn-product-tile-icon {
  width: 48px; height: 48px;
  background: var(--sn-paper-deep);
  border-radius: var(--sn-radius-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--sn-gold-deep);
}
.sn-product-tile h3 { margin-bottom: 4px; }
.sn-product-tile-list {
  list-style: none;
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--sn-line);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sn-product-tile-list li {
  font-size: 13px;
  color: var(--sn-ink-soft);
  padding-left: 18px;
  position: relative;
}
.sn-product-tile-list li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.65em;
  width: 8px; height: 1px;
  background: var(--sn-gold);
}

/* In-tile action button — used at the bottom of .sn-product-tile cards
   to give the prospect a clear next step. Replaces an earlier pattern
   of <p style="margin-top:12px"><a class="sn-btn" style="padding:8px 18px">
   which orphaned the button visually and used inline styles for sizing.
   The action sits flush left at the tile's bottom, separated from the
   body copy by margin-top:auto so all three tiles in a row align even
   when their copy lengths differ. */
.sn-tile-action {
  margin-top: auto;
  padding-top: 18px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.sn-tile-action-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 16px;
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--sn-ink-dark);
  background: var(--sn-white);
  border: 1px solid var(--sn-ink-dark);
  border-radius: 6px;
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
}
.sn-tile-action-btn:hover {
  background: var(--sn-ink-dark);
  color: var(--sn-white);
  transform: translateY(-1px);
}
.sn-tile-action-btn .arrow {
  transition: transform 0.18s ease;
}
.sn-tile-action-btn:hover .arrow {
  transform: translateX(2px);
}

/* Founder-note section — the about-page "A note from Lauren" block.
   Replaces an earlier pattern of multiple <p style="font-size:17px;
   color:var(--sn-ink-soft); max-width:680px"> paragraphs that floated
   orphaned, plus a credits block in muted ink that was too faint.
   Now: a designed quote-style card with a left-edge accent, slightly
   warmer paper background, properly-weighted founder credits, and
   readable LinkedIn link. The whole thing reads as a deliberate
   founder-letter artifact rather than a raw text dump. */
/* Founder note — two-column layout at desktop: founder identity
   card on the left (avatar + name + role + bio + links), letter body
   on the right with an opening serif-quote glyph and a closing pull-
   quote. Continuity sub-block sits below the layout as a procurement-
   grade appendix on a quieter surface. Uses the index-page
   navy + cyan palette so the about page reads continuous with the
   rest of the site. */
.sn-founder-note {
  position: relative;
  max-width: 960px;
  margin: 0 auto;
  padding: 44px 48px;
  background: linear-gradient(180deg, rgba(6, 182, 212, 0.05) 0%, rgba(6, 182, 212, 0.015) 100%), #FFFFFF;
  border: 1px solid rgba(6, 182, 212, 0.22);
  border-radius: var(--sn-radius-lg);
  box-shadow:
    0 1px 2px rgba(10, 37, 64, 0.04),
    0 24px 48px -22px rgba(6, 182, 212, 0.20);
}
@media (max-width: 720px) {
  .sn-founder-note { padding: 28px 24px; }
}
.sn-founder-note-layout {
  display: grid;
  grid-template-columns: 220px minmax(0, 1fr);
  gap: 44px;
  align-items: start;
}
@media (max-width: 880px) {
  .sn-founder-note-layout {
    grid-template-columns: 1fr;
    gap: 28px;
  }
}

/* ── Founder identity card (left column) ───────────────────────── */
.sn-founder-note-id {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-right: 28px;
  border-right: 1px solid rgba(10, 37, 64, 0.08);
}
@media (max-width: 880px) {
  .sn-founder-note-id {
    padding-right: 0;
    padding-bottom: 22px;
    border-right: none;
    border-bottom: 1px solid rgba(10, 37, 64, 0.08);
    /* On tablet+ mobile, lay out the identity card as a horizontal
       row (avatar left, name/role/bio right) so it reads as a calling
       card above the letter, not a stacked column with too much air. */
    flex-direction: row;
    align-items: flex-start;
    gap: 18px;
  }
  .sn-founder-note-id > div { flex: 1; min-width: 0; }
  /* The flex:1 above is meant for the text block; it out-specifies the
     avatar's own flex:none and stretched it into an oval. Re-pin it. */
  .sn-founder-note-id > .sn-founder-note-id-avatar { flex: none; }
  .sn-founder-note-id-links {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 10px;
    padding-top: 0;
    border-top: none;
    width: 100%;
  }
}
@media (max-width: 540px) {
  .sn-founder-note { padding: 24px 20px; }
  .sn-founder-note-id-avatar {
    width: 56px;
    height: 56px;
    font-size: 22px;
  }
  .sn-founder-note-pullquote { padding: 18px 18px; }
}
.sn-founder-note-id-avatar {
  width: 72px;
  height: 72px;
  /* Hold the avatar square regardless of the parent layout (the id card
     switches between flex-row, flex-column, and grid across breakpoints,
     any of which can stretch a flex/grid child). aspect-ratio keeps it
     1:1, flex:none + align/justify-self:start stop the parent from
     stretching it into an oval on mobile. */
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--sn-ink-dark, #0A2540) 0%, var(--sn-spark-deep, #0891B2) 100%);
  color: #F0FBFC;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--sn-font-display, 'Fraunces', Georgia, serif);
  font-size: 26px;
  font-weight: 600;
  letter-spacing: 0.02em;
  flex: none;
  flex-shrink: 0;
  align-self: start;
  justify-self: start;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.10) inset,
    0 4px 12px -4px rgba(6, 182, 212, 0.45);
}
.sn-founder-note-id-name {
  font-family: 'Inter', sans-serif;
  font-size: 17px;
  font-weight: 600;
  color: var(--sn-ink-darkest, #0A2540);
  margin: 0;
  letter-spacing: -0.01em;
}
.sn-founder-note-id-role {
  font-family: 'Inter', sans-serif;
  font-size: 13px;
  color: var(--sn-ink-soft);
  margin: 2px 0 0;
}
.sn-founder-note-id-bio {
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--sn-ink-soft);
  margin: 4px 0 0;
}
.sn-founder-note-id-links {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
  padding-top: 14px;
  border-top: 1px solid rgba(10, 37, 64, 0.08);
}
.sn-founder-note-id-links a {
  font-size: 13px;
  color: var(--sn-accent);
  text-decoration: none;
  border-bottom: 1px solid rgba(14, 116, 144, 0.32);
  padding-bottom: 1px;
  width: fit-content;
  transition: border-bottom-color 0.15s ease, color 0.15s ease;
}
.sn-founder-note-id-links a:hover {
  color: var(--sn-spark-deep);
  border-bottom-color: var(--sn-spark-deep);
}

/* ── Letter column (right at desktop, below at mobile) ─────────── */
.sn-founder-note-letter {
  position: relative;
}
/* Large display-serif opening quote glyph — sets the editorial tone. */
.sn-founder-note-letter::before {
  content: "\201C";
  position: absolute;
  top: -36px;
  left: -16px;
  font-family: var(--sn-font-display, 'Fraunces', Georgia, serif);
  font-size: 110px;
  font-weight: 600;
  line-height: 1;
  color: var(--sn-spark-deep, #0891B2);
  opacity: 0.32;
  pointer-events: none;
  user-select: none;
}
@media (max-width: 880px) {
  .sn-founder-note-letter::before {
    top: -24px;
    left: -10px;
    font-size: 80px;
  }
}
.sn-founder-note-letter p {
  font-size: 16.5px;
  line-height: 1.7;
  color: var(--sn-ink-dark);
  margin: 0 0 18px;
  position: relative;
}
.sn-founder-note-letter p:first-of-type {
  /* Lift the first paragraph slightly so the quote glyph reads as
     a flourish over the start of the letter, not floating above it. */
  padding-top: 4px;
}
.sn-founder-note-letter p:last-of-type { margin-bottom: 0; }

/* Pull-quote — extracted closing line, sits as the editorial close
   to the letter. Echoes the page H1 ("Integrity is the product.
   Intentionality is how we get there.") on a deliberately italic,
   serif treatment. Cyan accent matches the index palette. */
.sn-founder-note-pullquote {
  margin: 28px 0 0;
  padding: 22px 26px;
  background: transparent;
  font-family: var(--sn-font-display, 'Fraunces', Georgia, serif);
  font-size: clamp(17px, 1.6vw, 19px);
  font-style: italic;
  font-weight: 500;
  line-height: 1.5;
  color: var(--sn-ink-darkest, #0A2540);
  letter-spacing: -0.005em;
}
.sn-founder-note-pullquote em { font-style: italic; color: var(--sn-spark-deep, #0891B2); }
/* Continuity sub-block — single-founder operations addressed head-on
   so procurement teams don't have to ask. Visually distinct from the
   letter above: cooler ink wash (instead of warm gold), separated by
   a clear gap, framed as the procurement appendix not part of the
   personal note. */
.sn-founder-note-continuity {
  margin-top: 32px;
  padding: 22px 26px;
  background: rgba(10, 37, 64, 0.025);
  border: 1px solid rgba(10, 37, 64, 0.08);
  border-radius: var(--sn-radius-md);
}
.sn-founder-note-continuity-eyebrow {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  margin: 0 0 10px;
}
.sn-founder-note-continuity-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 8px;
}
.sn-founder-note-continuity-list li {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--sn-ink-soft);
  padding-left: 18px;
  position: relative;
}
.sn-founder-note-continuity-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 9px;
  width: 8px;
  height: 1px;
  background: var(--sn-spark-deep, #0891B2);
}
.sn-founder-note-continuity-list strong {
  color: var(--sn-ink-dark);
  font-weight: 600;
}
@media (max-width: 720px) {
  .sn-founder-note { padding: 24px 22px 24px 26px; }
  .sn-founder-note p { font-size: 15px; }
}

/* ───── INSIGHTS DEEP DIVE ────────────────────────────────────────── */
.sn-insights-section {
  background: var(--sn-paper);
}
.sn-insights-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: center;
  margin-top: 32px;
}
.sn-insights-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.sn-insights-list li {
  padding-left: 56px;
  position: relative;
}
.sn-insights-list li h4 {
  margin-bottom: 6px;
  color: var(--sn-ink-dark);
}
.sn-insights-list li p {
  font-size: 14px;
  line-height: 1.55;
}
.sn-insights-list-num {
  position: absolute;
  left: 0; top: 0;
  width: 36px; height: 36px;
  background: var(--sn-ink-dark);
  color: var(--sn-cream);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  font-weight: 700;
}
.sn-insights-screenshot {
  background: var(--sn-cream);
  border-radius: var(--sn-radius-lg);
  box-shadow: var(--sn-shadow-md);
  padding: 20px;
  border: 1px solid var(--sn-line);
}
.sn-insights-screenshot-frame {
  background: var(--sn-paper);
  border-radius: var(--sn-radius-md);
  padding: 16px;
  border: 1px solid var(--sn-line-soft);
}
.sn-insights-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 24px;
  font-size: 14px;
  font-weight: 600;
  color: var(--sn-gold-deep);
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
}
.sn-insights-link:hover { color: var(--sn-ink-dark); }

/* ───── TRUST SECTION ─────────────────────────────────────────────── */
.sn-trust {
  background: var(--sn-ink-darkest);
  color: var(--sn-cream);
}
.sn-trust .sn-section-head h2 { color: var(--sn-cream); }
.sn-trust .sn-section-head .sn-lede { color: rgba(255, 255, 255, 0.72); }
.sn-trust-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
  margin-top: 32px;
}
.sn-trust-card {
  padding: 28px 28px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: var(--sn-radius-lg);
}
.sn-trust-card h3 {
  color: var(--sn-cream);
  margin-bottom: 10px;
  font-size: 1.0625rem;
}
.sn-trust-card p {
  color: rgba(255, 255, 255, 0.72);
  font-size: 14px;
  line-height: 1.6;
}
.sn-trust-card-icon {
  width: 36px; height: 36px;
  background: rgba(14, 116, 144, 0.16);
  color: var(--sn-spark-soft);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 16px;
  font-size: 16px;
}

/* ───── ANIMATED FUNNEL VIZ ──────────────────────────────────────────
   Six-stage horizontal funnel that animates on scroll-into-view.
   Bar widths pre-set via inline --funnel-pct custom property; on
   reveal each bar transitions from width:0 to its target width over
   ~700ms with a 120ms stagger between rows, while a count-up runs
   on the inline number. Reuses the IntersectionObserver pattern
   already present in the proof-band script. */
/* ─────────────────────────────────────────────────────────────────
   Signal section · 2-column layout
   Phone (the moment) on the left, three signal widgets stacked on
   the right. Pairs the physical-to-digital experience with the
   measurement that flows back from it.
   ───────────────────────────────────────────────────────────────── */
.sn-signal-grid {
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: 64px;
  align-items: start;
  max-width: 1080px;
  margin: 0 auto;
}
@media (max-width: 920px) {
  .sn-signal-grid {
    grid-template-columns: 1fr;
    gap: 48px;
    max-width: 560px;
  }
}

.sn-signal-col-tag {
  display: inline-block;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  margin-bottom: 18px;
  padding: 4px 10px;
  background: rgba(10, 37, 64, 0.05);
  border-radius: 4px;
}
.sn-signal-col-tag.is-spark {
  /* Was --sn-spark (#06B6D4 ≈ 2.8:1 on the cyan-tint bg, below WCAG
     AA). Bumped to --sn-spark-deep (#0891B2) for ~4.5:1 contrast on
     the same tinted background. Same visual register, AA-clean. */
  color: var(--sn-spark-deep);
  background: rgba(6, 182, 212, 0.10);
}

/* Phone column — phone centered horizontally. Caption below ties the
   visual to the story. */
.sn-signal-phone-col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.sn-signal-phone-wrap {
  position: relative;
  align-self: center;
}
@media (max-width: 920px) {
  .sn-signal-phone-col { align-items: center; }
}
.sn-signal-phone-cap {
  margin-top: 28px;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--sn-ink-muted);
  font-style: italic;
  text-align: center;
  align-self: center;
  max-width: 280px;
}
/* "Open the live preview" CTA under the phone in the engage section — opens the
   real scan.html reveal in a new tab. Centered under the caption. */
.sn-signal-phone-preview {
  margin-top: 16px;
  align-self: center;
}
.sn-signal-phone-preview .arrow {
  transition: transform 0.15s ease;
}
.sn-signal-phone-preview:hover .arrow {
  transform: translateX(2px);
}

/* Widgets column — the 3 signal cards stacked single-column. */
.sn-signal-widgets-col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.sn-funnel {
  /* Funnel is a single stacked column of group cards (Reach, Engagement,
     Affirmation, Action) inside the signal section's right column. The
     phone on the left provides "the moment"; this column shows the signal. */
  display: flex;
  flex-direction: column;
  gap: 18px;
  width: 100%;
  margin: 0;
}

/* Widget card — cyan-tinted wash, hairline border, soft shadow.
   Generous padding so the bars and numbers feel substantial. */
.sn-funnel-group {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 24px 28px 22px;
  background: linear-gradient(180deg, rgba(6, 182, 212, 0.06) 0%, rgba(6, 182, 212, 0.015) 100%), #FFFFFF;
  border: 1px solid rgba(6, 182, 212, 0.20);
  border-radius: var(--sn-radius-lg);
  box-shadow:
    0 1px 2px rgba(10, 37, 64, 0.04),
    0 16px 32px -16px rgba(6, 182, 212, 0.22);
}
@media (max-width: 720px) {
  .sn-funnel-group { padding: 20px 22px 18px; gap: 12px; }
}

/* Group header — bigger, more visible than the prior small mono row.
   Icon lifts to a 36px circular badge; title is sans-bold display
   size so a reader skimming this section gets Reach / Engagement /
   Action as the dominant read before the bar values. */
.sn-funnel-group-header {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-bottom: 14px;
  margin-bottom: 4px;
  border-bottom: 1px dashed rgba(6, 182, 212, 0.30);
}
.sn-funnel-group-icon {
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(6, 182, 212, 0.12);
  color: var(--sn-spark);
  flex-shrink: 0;
}
.sn-funnel-group-icon svg {
  width: 19px;
  height: 19px;
}
.sn-funnel-group-name {
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.012em;
  color: var(--sn-ink-darkest);
  line-height: 1.1;
}
/* New layout (April 2026): label OUTSIDE the bar on the left, bar
   track in the middle, number + percent OUTSIDE on the right. The
   prior layout had label + number inside the colored fill which
   collided when the bar was narrow ("CTA clicked1,080" overlap).
   Universal rule: labels and numbers always have space between them.
   Mirrors the dashboard.html funnel-stage pattern. */
.sn-funnel-bar {
  display: grid;
  grid-template-columns: minmax(120px, 160px) minmax(0, 1fr) 96px;
  gap: 16px;
  align-items: center;
}
.sn-funnel-bar-label {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--sn-ink-dark);
  line-height: 1.3;
}
.sn-funnel-bar-track {
  position: relative;
  height: 22px;
  background: rgba(10, 37, 64, 0.07);
  border-radius: 11px;
  overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(10, 37, 64, 0.04);
}
.sn-funnel-bar-fill {
  position: absolute;
  inset: 0;
  height: 100%;
  width: 0;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.18) 0%, rgba(255, 255, 255, 0) 60%),
    linear-gradient(90deg, var(--sn-spark) 0%, var(--sn-accent) 100%);
  border-radius: 11px;
  transition: width 700ms cubic-bezier(0.22, 1, 0.36, 1);
  box-shadow: 0 1px 3px rgba(6, 182, 212, 0.28);
}
.sn-funnel.is-visible .sn-funnel-bar-fill {
  width: var(--funnel-pct, 100%);
}
/* Stagger reveal — each subsequent bar waits a bit longer so the
   funnel "fills" top-to-bottom rather than all at once. Bars now
   live inside .sn-funnel-group wrappers; within each group the
   header is :nth-child(1) and the two bars are :nth-child(2) and
   :nth-child(3). */
.sn-funnel.is-visible .sn-funnel-group:nth-child(1) .sn-funnel-bar:nth-child(2) .sn-funnel-bar-fill { transition-delay: 0ms; }
.sn-funnel.is-visible .sn-funnel-group:nth-child(1) .sn-funnel-bar:nth-child(3) .sn-funnel-bar-fill { transition-delay: 120ms; }
.sn-funnel.is-visible .sn-funnel-group:nth-child(2) .sn-funnel-bar:nth-child(2) .sn-funnel-bar-fill { transition-delay: 240ms; }
.sn-funnel.is-visible .sn-funnel-group:nth-child(2) .sn-funnel-bar:nth-child(3) .sn-funnel-bar-fill { transition-delay: 360ms; }
.sn-funnel.is-visible .sn-funnel-group:nth-child(3) .sn-funnel-bar:nth-child(2) .sn-funnel-bar-fill { transition-delay: 480ms; }
.sn-funnel.is-visible .sn-funnel-group:nth-child(3) .sn-funnel-bar:nth-child(3) .sn-funnel-bar-fill { transition-delay: 600ms; }
.sn-funnel-bar-stat {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  text-align: right;
  white-space: nowrap;
}
.sn-funnel-bar-num {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--sn-ink-darkest);
  font-feature-settings: 'tnum' 1, 'lnum' 1;
}
.sn-funnel-bar-pct {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--sn-ink-muted);
  font-feature-settings: 'tnum' 1, 'lnum' 1;
}
.sn-funnel-caption {
  margin: 22px 0 0;
  max-width: 100%;
  font-size: 12px;
  line-height: 1.55;
  color: var(--sn-ink-muted);
  text-align: left;
  font-style: italic;
}
/* Fine-print disclosure (design review 2026-09-02): methodology notes keep
   their full text — nothing trimmed, claim language intact — but sit behind
   a one-line toggle so evidence sections don't end in a wall of italics. */
.sn-fine-note { margin: 18px 0 0; }
.sn-fine-note > summary {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  font-weight: 600;
  font-style: normal;
  color: var(--sn-ink-muted);
  -webkit-user-select: none;
  user-select: none;
}
.sn-fine-note > summary::-webkit-details-marker { display: none; }
.sn-fine-note > summary::before {
  content: '';
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 160ms ease;
}
.sn-fine-note[open] > summary::before { transform: rotate(45deg); }
.sn-fine-note > summary:hover { color: var(--sn-ink-soft); }
.sn-fine-note > p { margin-top: 10px; }
.sn-fine-note > .sn-funnel-caption { margin-top: 10px; }
/* Reduced-motion: skip the staggered reveal, render bars at full
   width immediately. Counts still increment on the number elements
   but without the visual sweep. */
@media (prefers-reduced-motion: reduce) {
  .sn-funnel .sn-funnel-bar-fill { transition: none; width: var(--funnel-pct, 100%) !important; }
}
@media (max-width: 600px) {
  /* On narrow viewports, stack: label on top, bar + stat row below
     within a horizontal pair. Avoids cramped 3-column grid. */
  .sn-funnel-bar {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "label stat" "track track";
    gap: 6px 10px;
    column-gap: 12px;
  }
  .sn-funnel-bar > .sn-funnel-bar-label { grid-area: label; font-size: 13px; }
  .sn-funnel-bar > .sn-funnel-bar-track { grid-area: track; }
  .sn-funnel-bar > .sn-funnel-bar-stat { grid-area: stat; }
  .sn-funnel-bar-num { font-size: 12.5px; }
  .sn-funnel-bar-pct { font-size: 10.5px; }
}

/* "Plays with" platform-strip — a categorized wordmark grid that
   replaces the earlier single-paragraph version. Grouped by category,
   each row shows the named partner platforms in a way that signals
   "we play with these" without claiming partnership relationships
   we don't have. Visual treatment is deliberately understated (uppercase
   letterspaced text, no brand colors) so it reads as a directory rather
   than a logo wall — keeps integrity intact while still giving the
   visual credibility signal procurement teams scan for. */
.sn-platforms-strip {
  margin: 36px auto 0;
  max-width: 920px;
  padding: 28px 32px;
  background: linear-gradient(180deg, rgba(10, 37, 64, 0.03), rgba(10, 37, 64, 0.005));
  border: 1px solid var(--sn-line);
  border-radius: 12px;
}
.sn-platforms-cap {
  text-align: center;
  margin-bottom: 22px;
  padding-bottom: 18px;
  border-bottom: 1px dashed rgba(10, 37, 64, 0.10);
}
.sn-platforms-eyebrow {
  display: block;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--sn-ink-dark);
  margin-bottom: 4px;
  letter-spacing: -0.005em;
}
.sn-platforms-sub {
  display: block;
  font-size: 12.5px;
  color: var(--sn-ink-muted);
  font-style: italic;
}
.sn-platforms-rows {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.sn-platforms-row {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 24px;
  align-items: center;
}
.sn-platforms-cat {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
}
.sn-platforms-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  align-items: center;
}
/* Each wordmark is rendered as understated text — Inter at a fixed
   weight + letter-spacing — and gains color on hover. The dot
   separator between items keeps the list readable without bullet
   marks or pills. */
.sn-platforms-list li {
  position: relative;
  padding: 4px 14px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--sn-ink-soft);
  transition: color 0.15s ease, transform 0.15s ease;
  cursor: default;
}
.sn-platforms-list li:hover {
  color: var(--sn-ink-dark);
  transform: translateY(-1px);
}
.sn-platforms-list li:not(:last-child)::after {
  content: "·";
  position: absolute;
  right: -2px;
  top: 50%;
  transform: translateY(-50%);
  color: rgba(110, 99, 88, 0.35);
  font-size: 14px;
}
.sn-platforms-list li:first-child { padding-left: 0; }
@media (max-width: 720px) {
  .sn-platforms-strip { padding: 22px 18px; }
  .sn-platforms-row { grid-template-columns: 1fr; gap: 6px; }
  .sn-platforms-cat { font-size: 9.5px; }
  .sn-platforms-list li { padding: 4px 10px; font-size: 13px; }
}

/* ───── PRICING TEASER ────────────────────────────────────────────── */
.sn-pricing-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  margin-top: 56px;
  max-width: 1080px;
  margin-left: auto;
  margin-right: auto;
}
.sn-pricing-note {
  max-width: 760px;
  margin: 32px auto 0;
  text-align: center;
  font-size: 12px;
  color: var(--sn-ink-muted);
  font-style: normal;
}
.sn-pricing-tier {
  padding: 28px 24px;
  background: var(--sn-cream);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-lg);
  display: flex;
  flex-direction: column;
}
.sn-pricing-tier.is-featured {
  background: var(--sn-ink-darkest);
  color: var(--sn-cream);
  border-color: var(--sn-ink-darkest);
}
.sn-pricing-tier-name {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sn-gold-deep);
  margin-bottom: 8px;
}
.sn-pricing-tier.is-featured .sn-pricing-tier-name { color: var(--sn-spark-soft); }
.sn-pricing-tier-price {
  font-family: var(--sn-font-display);
  font-style: normal;
  font-size: 32px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--sn-ink-dark);
  line-height: 1;
  margin-bottom: 4px;
}
.sn-pricing-tier.is-featured .sn-pricing-tier-price { color: var(--sn-cream); }
.sn-pricing-tier-cadence {
  font-size: 13px;
  color: var(--sn-ink-muted);
  margin-bottom: 20px;
}
.sn-pricing-tier.is-featured .sn-pricing-tier-cadence { color: rgba(255, 255, 255, 0.6); }
.sn-pricing-tier-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 13px;
  margin-bottom: 24px;
}
.sn-pricing-tier-list li {
  color: var(--sn-ink-soft);
  padding-left: 16px;
  position: relative;
  line-height: 1.5;
}
.sn-pricing-tier.is-featured .sn-pricing-tier-list li { color: rgba(255, 255, 255, 0.78); }
.sn-pricing-tier-list li::before {
  content: '✓';
  position: absolute;
  left: 0;
  color: var(--sn-success);
  font-weight: 700;
  font-size: 11px;
}
.sn-pricing-tier.is-featured .sn-pricing-tier-list li::before { color: var(--sn-spark-soft); }
.sn-pricing-tier-cta {
  margin-top: auto;
}

/* ───── FINAL CTA ─────────────────────────────────────────────────── */
.sn-final-cta {
  /* Clean dark close — dot pattern over solid base. The cyan blob
     that lived here previously had visible edges (same issue the
     proof band had). The light + dark-outline CTAs carry enough
     accent for this section to feel alive. */
  background:
    radial-gradient(rgba(255,255,255,0.05) 1.1px, transparent 1.4px) 0 0 / 27px 27px,
    var(--sn-ink-darkest);
  color: var(--sn-cream);
  text-align: center;
  padding: clamp(72px, 9vw, 112px) 28px;
  position: relative;
  overflow: hidden;
}
.sn-final-cta > h2,
.sn-final-cta > p,
.sn-final-cta > .sn-final-cta-actions { position: relative; z-index: 1; }

.sn-final-cta h2 {
  color: var(--sn-cream);
  margin-bottom: 16px;
  max-width: 760px;
  margin-left: auto;
  margin-right: auto;
}
.sn-final-cta h2 em {
  font-style: normal;
  color: var(--sn-spark-soft);
  font-weight: 500;
  font-family: var(--sn-font-display);
}
.sn-final-cta p {
  color: rgba(255, 255, 255, 0.78);
  max-width: 560px;
  margin: 0 auto 32px;
  font-size: 17px;
}
/* On the dark navy final-CTA background, <strong> needs to override
   the global "strong { color: var(--sn-ink-dark) }" rule (which would
   render dark navy on navy = invisible). White lifts emphasis. */
.sn-final-cta p strong { color: #FFFFFF; }
.sn-final-cta-actions {
  display: inline-flex;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
}

/* ───── FOOTER ────────────────────────────────────────────────────── */
.sn-footer {
  background: var(--sn-paper);
  border-top: 1px solid var(--sn-line);
  padding: 48px 28px 32px;
}
.sn-footer-inner {
  max-width: var(--sn-container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 32px;
  margin-bottom: 32px;
}
.sn-footer-brand p {
  font-size: 13px;
  margin-top: 12px;
  max-width: 360px;
  line-height: 1.55;
}
.sn-footer-brand p a {
  text-decoration: underline;
  text-underline-offset: 2px;
}
.sn-footer-col h3 {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  margin-bottom: 14px;
}
.sn-footer-col ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.sn-footer-col a {
  font-size: 13px;
  color: var(--sn-ink-soft);
  transition: color 0.15s ease;
}
.sn-footer-col a:hover { color: var(--sn-ink-dark); }
.sn-footer-legal {
  max-width: var(--sn-container);
  margin: 0 auto;
  padding-top: 24px;
  border-top: 1px solid var(--sn-line);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  font-size: 12px;
  color: var(--sn-ink-muted);
}
.sn-footer-legal a { color: inherit; }
.sn-footer-legal a:hover { color: var(--sn-ink-dark); }

/* ───── CONTACT FORM ──────────────────────────────────────────────── */
.sn-form {
  display: flex;
  flex-direction: column;
  gap: 18px;
  max-width: 560px;
  margin: 32px auto 0;
}
.sn-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
.sn-form-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.sn-form-field label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
}
.sn-form-field input,
.sn-form-field textarea,
.sn-form-field select {
  font-family: inherit;
  font-size: 15px;
  padding: 11px 14px;
  background: var(--sn-white);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-sm);
  color: var(--sn-ink-dark);
  transition: border-color 0.15s ease;
  width: 100%;
}
.sn-form-field input:focus,
.sn-form-field textarea:focus,
.sn-form-field select:focus {
  outline: none;
  border-color: var(--sn-spark-deep);
  box-shadow: 0 0 0 3px rgba(8, 145, 178, 0.16);
}
.sn-form-field textarea { min-height: 120px; resize: vertical; line-height: 1.55; }
.sn-form-submit { margin-top: 8px; }

/* ───── RESPONSIVE ────────────────────────────────────────────────── */
@media (max-width: 1080px) {
  .sn-hero-inner,
  .sn-insights-grid { grid-template-columns: 1fr; gap: 48px; }
  .sn-hero-visual { max-width: 480px; margin: 0 auto; }
  .sn-pricing-grid { grid-template-columns: repeat(2, 1fr); }
  .sn-footer-inner { grid-template-columns: 1fr 1fr; gap: 28px; }
}
/* ─── LAPTOP-WIDTH HEADER FIX (1024–1280px) ───
   At common laptop sizes the 9-item nav was wrapping items like
   "How it works" / "Case study" / "Sign in" to two lines. Tighter
   gap + reduced link padding keeps everything on a single row down
   to 1024. Below 1024 we drop the desktop nav entirely and the
   hamburger takes over (see <=1024 block below). */
@media (max-width: 1280px) {
  .sn-nav { gap: 0; }
  .sn-nav-link { padding: 8px 10px; font-size: 13.5px; }
  .sn-nav-signin { margin-left: 4px; padding-left: 10px; }
  .sn-nav-cta { margin-left: 8px; }
  .sn-header-inner { gap: 16px; }
}

/* ─── HAMBURGER BREAKPOINT (≤1024px) ───
   Earlier than the typical 768px because our nav has 9 items + a CTA;
   even at 900–1024px the items wrapped or felt cramped. Below this
   the desktop flexbox nav becomes a slide-down drawer triggered by
   the hamburger button next to the logo. */
@media (max-width: 1024px) {
  /* Fixed-position toggle — flexbox-cascade-proof. Some parent
     containers were briefly computing wider than the viewport during
     layout (hero-journey absolute children with right:-148px, etc.)
     and pushing the toggle off-screen at narrow widths. Anchoring to
     the viewport sidesteps it entirely. */
  .sn-nav-toggle {
    display: inline-flex;
    position: fixed;
    top: 10px;
    right: 18px;
    z-index: 51;
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
  }
  /* Drawer state — the .sn-nav element from the desktop layout becomes
     a positioned overlay panel below the header. Hidden by default,
     revealed when [data-mobile-open="true"] is set on <body> by JS. */
  .sn-nav {
    position: fixed;
    top: var(--sn-header-h);
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 49;
    background: rgba(255, 255, 255, 0.98);
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    padding: 24px 24px 32px;
    overflow-y: auto;
    max-height: calc(100vh - var(--sn-header-h));
    transform: translateY(-12px);
    opacity: 0;
    pointer-events: none;
    transition: transform 0.22s ease, opacity 0.22s ease;
    border-top: 1px solid var(--sn-line-soft);
  }
  body[data-mobile-open="true"] .sn-nav {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
  }
  /* Drawer link styling: full-width tappable rows, 16px font, generous
     padding so each row is a 48px+ touch target. */
  .sn-nav-link {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 14px 16px;
    font-size: 16px;
    color: var(--sn-ink-dark);
    border-radius: var(--sn-radius-md);
    border-left: none;
  }
  .sn-nav-link:hover,
  .sn-nav-link:focus-visible { background: var(--sn-paper-deep); }
  .sn-nav-signin {
    margin: 8px 0 0;
    padding-left: 16px;
    border-left: none;
    border-top: 1px solid var(--sn-line);
    padding-top: 16px;
    font-size: 15px;
    color: var(--sn-ink-soft);
  }
  .sn-nav-cta {
    margin: 12px 0 0;
    justify-content: center;
    width: 100%;
    padding: 14px 20px;
    font-size: 15px;
  }
  /* Lock body scroll while the drawer is open. */
  body[data-mobile-open="true"] {
    overflow: hidden;
  }
}

@media (max-width: 740px) {
  .sn-header { padding: 0 18px; }
  .sn-header-inner { padding: 12px 0; gap: 12px; }
  .sn-hero { padding: 64px 22px 56px; }
  .sn-hero-trust { gap: 18px; padding-top: 24px; }
  /* Hero CTA pairs stack full-width on phones so both buttons are the same
     length (uniform CTAs across the marketing site). Covers the canonical
     .sn-hero-actions plus the page-specific hero rows on how-it-works and
     methods/research; trust's .tc-hero-actions already handles itself. */
  .sn-hero-actions,
  .hiw-hero-actions,
  .rs-hero-actions { flex-direction: column; align-items: stretch; }
  .sn-hero-actions .sn-btn,
  .hiw-hero-actions .sn-btn,
  .rs-hero-actions .sn-btn { justify-content: center; width: 100%; max-width: 100%; }
  .sn-section { padding: 56px 22px; }
  /* Phone-tier h1 overrides — the desktop clamp's min (2.75rem ≈ 44px)
     was too wide for "Tell us what you need to learn." at 390px width;
     letter-spacing -0.035em + word "what" + "need" = ~350px line which
     blew past the 342px content area. At <=740 we drop the floor and
     enforce overflow-wrap so any unusually-long word breaks safely.
     Same fix applied to the page-specific hero variants on
     research / methods (rs-hero) and how-it-works (hiw-hero) so they
     inherit the same phone behavior. */
  .sn-hero h1,
  .sn-hero h1.sn-hero-headline,
  .rs-hero h1,
  .hiw-hero h1,
  .pr-hero-bottomup h1 {
    /* Bumped up (was clamp(2rem, 8.5vw, 2.625rem)) — bigger, more confident
       hero headlines on phones, uniform across every page. */
    font-size: clamp(2.25rem, 9.4vw, 3rem);
    overflow-wrap: anywhere;
  }
  /* Long-form pages (research/methods/how-it-works) use 48px outer
     padding by default; tighten to 22px at phone widths to recover
     the ~52px the H1 + cards desperately need on narrow viewports. */
  .rs-app,
  .hiw-app {
    padding-left: 22px !important;
    padding-right: 22px !important;
  }
  .sn-problem-stats,
  .sn-how-grid,
  .sn-product-grid,
  .sn-trust-grid { grid-template-columns: 1fr; gap: 16px; }
  .sn-pricing-grid { grid-template-columns: 1fr; }
  .sn-form-row { grid-template-columns: 1fr; }
  .sn-footer-inner { grid-template-columns: 1fr; }
  /* Final-CTA actions stack on phones. */
  .sn-final-cta-actions { flex-direction: column; align-items: stretch; }
  .sn-final-cta-actions .sn-btn { width: 100%; max-width: 100%; justify-content: center; }
}

/* ════════════════════════════════════════════════════════════════════
   STRIPE-STYLE SECTION VARIETY (April 30 v2)
   ────────────────────────────────────────────────────────────────────
   The marketing page was reading repetitive — same headline-grid-cards
   pattern in every section. These new components break the rhythm:
     · Dashboard widget — embedded product surface (proof, not slide)
     · Same-budget comparison — split visual showing the math
     · Webhook event preview — code-block credibility for engineering
     · Section tone variants — subtle background gradations for rhythm
   Each is a self-contained block; sections that use them keep the
   existing .sn-section / .sn-container scaffold for consistency.
   ════════════════════════════════════════════════════════════════════ */

/* ─── Card-tone surface system — 4 deliberate variants ───
     Stripe never lets you see five identical cards in a row. They
     vary surface tone (paper / outline / glass / ink) so the eye
     groups by intent, not by chrome. Apply ONE of these to any card
     instead of redefining background / border per page.

     paper    — default. White on hairline cool-grey line. Used for
                most content cards.
     outline  — chrome-light. Transparent bg, no shadow, just a line.
                Use for "lighter than the paper next to it" — e.g. a
                grid of tertiary items inside a section.
     glass    — paper-deep wash with subtle inner highlight. Use for
                "this is a different surface" — methodology callouts,
                helper modules.
     ink      — dark navy chrome. Reserved for hero/payoff moments
                (final CTA, dashboard preview, signature stat tiles).
                White text. Use sparingly — these draw the eye.

     Each carries the same radius + transition so they swap cleanly. */
.sn-surface-paper,
.sn-surface-outline,
.sn-surface-glass,
.sn-surface-ink {
  border-radius: var(--sn-radius-lg);
  transition: border-color 0.18s ease, transform 0.22s ease, box-shadow 0.22s ease;
}
.sn-surface-paper {
  background: #FFFFFF;
  border: 1px solid var(--sn-line);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.85) inset,
    0 1px 2px rgba(10, 37, 64, 0.04),
    0 12px 32px -18px rgba(10, 37, 64, 0.10);
}
.sn-surface-outline {
  background: transparent;
  border: 1px solid var(--sn-line);
  box-shadow: none;
}
.sn-surface-glass {
  background: linear-gradient(180deg, var(--sn-paper-deep) 0%, #FAFCFD 100%);
  border: 1px solid var(--sn-line);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.65) inset,
    0 1px 2px rgba(10, 37, 64, 0.03);
}
.sn-surface-ink {
  background: linear-gradient(135deg, var(--sn-ink-darkest) 0%, #061A33 100%);
  border: 1px solid rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.92);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.05) inset,
    0 24px 60px -28px rgba(10, 37, 64, 0.55);
}
.sn-surface-ink h1, .sn-surface-ink h2, .sn-surface-ink h3, .sn-surface-ink h4 {
  color: #FFFFFF;
}
.sn-surface-ink p, .sn-surface-ink li { color: rgba(255, 255, 255, 0.78); }

/* ─── Section tone variants — alternating cool backgrounds that
   give the page a real, readable rhythm. Deep enough that sections
   read as distinct bands (near-white would be "barely perceptible").
   Both cool — no warm paper on marketing surfaces. */
/* Flat tinted sections with hard, clean edges (Stripe pattern — no
   gradient fades; sections break cleanly). The dot grid carries a
   quiet data-field texture; a soft cyan glow sits in one corner. */
.sn-section-tone-paper {
  background-color: #EBF1F7;
  background-image:
    radial-gradient(rgba(10,37,64,0.045) 1px, transparent 1.4px),
    radial-gradient(120% 78% at 90% 0%, rgba(6, 182, 212, 0.12), transparent 60%);
  background-size: 26px 26px, 100% 100%;
  background-repeat: repeat, no-repeat;
}
.sn-section-tone-mist {
  background-color: #EBF1F7;
  background-image:
    radial-gradient(rgba(10,37,64,0.045) 1px, transparent 1.4px),
    radial-gradient(112% 78% at 10% 0%, rgba(6, 182, 212, 0.13), transparent 60%);
  background-size: 26px 26px, 100% 100%;
  background-repeat: repeat, no-repeat;
}

/* ─── Dashboard widget — condensed product surface embedded in the
   homepage. Visual proof of "this is the actual thing your team would
   log into" without making the visitor click through to /demo. The
   chrome (header bar, tabs, KPI tiles) mirrors the real dashboard so a
   prospect feels the product before they meet it.
   Layout: header bar with logo + tenant context, then 4 KPI tiles in
   a row, then a subtle footer link to the full demo. The whole widget
   sits inside a card with a soft shadow that lifts it off the page. */
.sn-dash-widget {
  margin-top: 48px;
  background: #FFFFFF;
  border: 1px solid var(--sn-line);
  border-radius: 14px;
  box-shadow:
    0 1px 2px rgba(10, 37, 64, 0.04),
    0 24px 48px -12px rgba(10, 37, 64, 0.10);
  overflow: hidden;
  max-width: 980px;
  margin-left: auto;
  margin-right: auto;
}
.sn-dash-widget-chrome {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  padding: 14px 20px;
  background: #FAFBFD;
  border-bottom: 1px solid var(--sn-line);
}
.sn-dash-widget-brand {
  display: flex;
  align-items: center;
  gap: 10px;
}
.sn-dash-widget-mark {
  width: 28px; height: 28px;
  border-radius: 6px;
  background: #0A2540;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  flex-shrink: 0;
}
.sn-dash-widget-mark img {
  width: 100%; height: 100%;
  display: block;
}
.sn-dash-widget-stack {
  display: flex;
  flex-direction: column;
  gap: 1px;
  line-height: 1.15;
}
.sn-dash-widget-product {
  font-size: 14px;
  font-weight: 600;
  color: #0A2540;
  letter-spacing: -0.01em;
}
.sn-dash-widget-tenant {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--sn-ink-muted);
  text-transform: uppercase;
}
.sn-dash-widget-tenant strong { color: #0A2540; font-weight: 700; }
.sn-dash-widget-tabs {
  display: flex;
  gap: 4px;
}
.sn-dash-widget-tab {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  padding: 6px 10px;
  border-radius: 5px;
}
.sn-dash-widget-tab.is-active {
  color: var(--sn-accent);
  background: rgba(10, 37, 64, 0.06);
}
.sn-dash-widget-kpis {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--sn-line);
}
.sn-dash-widget-kpi {
  background: #FFFFFF;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.sn-dash-widget-kpi-label {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
}
.sn-dash-widget-kpi-val {
  font-family: var(--sn-font-display);
  font-size: clamp(28px, 3.5vw, 36px);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: #0A2540;
  line-height: 1.05;
}
.sn-dash-widget-kpi-val span {
  font-size: 0.55em;
  font-weight: 500;
  color: var(--sn-ink-muted);
  margin-left: 1px;
}
.sn-dash-widget-kpi-bench {
  font-size: 11.5px;
  color: #2F6B48;
  font-weight: 500;
  font-style: italic;
}
.sn-dash-widget-kpi-bench.is-below { color: #B04A2A; }
/* Footnote superscript on the projected industry-benchmark line.
   Visually quiet but signals "see footnote below" — the dashboard
   widget footer caption explains the figures are a projection until
   n≥10 brands enroll. */
.sn-dash-widget-footnote {
  font-size: 0.85em;
  font-weight: 600;
  color: var(--sn-spark-deep);
  margin-left: 1px;
  font-style: normal;
}
.sn-dash-widget-footer {
  padding: 14px 20px;
  border-top: 1px solid var(--sn-line);
  background: #FAFBFD;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
}
.sn-dash-widget-footer-meta {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  letter-spacing: 0.06em;
  color: var(--sn-ink-muted);
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
/* Live pulse dot — small green dot that pulses to signal "real-time
   data" without claiming live numbers we don't have yet. */
@media (prefers-reduced-motion: reduce) {
}
/* Subtle KPI tick — when the JS micro-animation updates the number,
   add `is-ticking` briefly to flash the cyan-spark color. */
.sn-dash-widget-kpi-num {
  transition: color 0.35s ease;
}
.sn-dash-widget-kpi-val.is-ticking .sn-dash-widget-kpi-num {
  color: var(--sn-spark-deep);
}
.sn-dash-widget-cta {
  font-size: 13px;
  font-weight: 600;
  color: var(--sn-accent);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: gap 0.15s ease;
}
.sn-dash-widget-cta:hover { gap: 9px; }

/* ── Methodology + status pills (replaced the fake Results/Cohort/A/B/
   Benchmarks tab row — the real portal uses a .cl-page-header with a
   methodology pill + a three-state status pill, not tabs). ── */
.sn-dash-widget-pills { display: flex; gap: 6px; flex-wrap: wrap; }
.sn-dash-widget-pill {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
  padding: 4px 9px; border-radius: 999px; white-space: nowrap;
}
.sn-dash-widget-pill.is-method { color: var(--sn-accent); background: rgba(10, 37, 64, 0.06); border: 1px solid rgba(10, 37, 64, 0.12); }
.sn-dash-widget-pill.is-status { color: var(--sn-spark-deep); background: rgba(6, 182, 212, 0.08); border: 1px solid rgba(6, 182, 212, 0.22); }
.sn-dash-widget-illus {
  margin-left: auto; padding: 3px 9px; font-size: 10px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--sn-ink-muted);
  background: rgba(10, 37, 64, 0.06); border: 1px solid rgba(10, 37, 64, 0.14); border-radius: 999px;
}

/* ── Reach coverage hero — Reach is the universe the engagement strip
   measures (mirrors the real dashboard's renderReachHero). ── */
.sn-dash-widget-reach {
  display: flex; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap; gap: 8px 18px;
  padding: 16px 20px; background: #FFFFFF; border-bottom: 1px solid var(--sn-line);
}
.sn-dash-widget-reach-head { display: flex; flex-direction: column; gap: 3px; }
.sn-dash-widget-reach-stat { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.sn-dash-widget-reach-stat .sn-dash-widget-kpi-val { line-height: 1; }

/* ── Per-KPI question label (the most recognizable portal element),
   Wilson CI, and aggregate count denominator. ── */
.sn-dash-widget-kpi-q { font-size: 12px; font-weight: 500; color: var(--sn-ink-soft); line-height: 1.3; }
.sn-dash-widget-kpi-valrow { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.sn-dash-widget-kpi-ci {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px; font-weight: 600; color: var(--sn-ink-muted); letter-spacing: 0.02em;
}
.sn-dash-widget-kpi-denom {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px; color: var(--sn-ink-muted); letter-spacing: 0.03em;
}
/* "modeled" tag — KPIs estimated from a model until their event lands in v1.0. */
.sn-dash-widget-kpi-modeled {
  font-size: 8.5px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--sn-ink-muted); background: rgba(10, 37, 64, 0.06);
  border: 1px solid rgba(10, 37, 64, 0.14); border-radius: 999px;
  padding: 1px 5px; vertical-align: middle; white-space: nowrap;
}

@media (max-width: 720px) {
  .sn-dash-widget-kpis { grid-template-columns: repeat(2, 1fr); }
}

/* ═══════════════════════════════════════════════════════════════════
   REFRAME SPLIT-SCREEN
   A literal silent-vs-streaming visual: same gift moment shown twice.
   Left = silent (no QR, no event stream, "No signal" label). Right
   = live (QR on the package, three pulsing event rows in the stream).
   The visual carries the argument; the captions just name the outcome.
   ═══════════════════════════════════════════════════════════════════ */
.sn-reframe-split {
  margin: var(--sn-space-9) auto 0;
  max-width: 980px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sn-space-5);
}
@media (max-width: 720px) {
  .sn-reframe-split { grid-template-columns: 1fr; gap: var(--sn-space-3); }
}
.sn-reframe-side {
  background: var(--sn-paper);
  border: 1px solid var(--sn-line);
  border-radius: var(--sn-radius-2xl);
  padding: var(--sn-space-6) var(--sn-space-6) var(--sn-space-6);
  display: flex;
  flex-direction: column;
  gap: var(--sn-space-5);
  position: relative;
  overflow: hidden;
}
.sn-reframe-side-silent {
  background: var(--sn-paper-deep);
  border-color: rgba(105, 115, 134, 0.18);
}
.sn-reframe-side-live {
  background:
    linear-gradient(180deg, rgba(6, 182, 212, 0.05) 0%, var(--sn-paper) 60%);
  border-color: rgba(6, 182, 212, 0.32);
  box-shadow:
    0 0 0 4px rgba(6, 182, 212, 0.05),
    var(--sn-shadow-card-lift);
}
.sn-reframe-side-live::before {
  content: "";
  position: absolute;
  top: -1px;
  left: -1px;
  right: -1px;
  height: 3px;
  border-radius: var(--sn-radius-2xl) var(--sn-radius-2xl) 0 0;
  background: linear-gradient(90deg, var(--sn-spectrum-blue) 0%, var(--sn-spectrum-cyan) 100%);
}
.sn-reframe-side-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.sn-reframe-side-tag {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
}
.sn-reframe-side-live .sn-reframe-side-tag {
  color: var(--sn-spark-deep);
}
.sn-reframe-side-state {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: rgba(105, 115, 134, 0.65);
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(105, 115, 134, 0.10);
  border: 1px solid rgba(105, 115, 134, 0.18);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.sn-reframe-side-state.is-live {
  color: var(--sn-spark-deep);
  background: rgba(6, 182, 212, 0.10);
  border-color: rgba(6, 182, 212, 0.32);
}
@media (prefers-reduced-motion: reduce) {
}

/* The "stage" — package on top, event stream below. Uses a thin
   dashed connector between them so the eye reads them as the same
   shipment + its (absent or present) signal. */
.sn-reframe-side-stage {
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: stretch;
}
.sn-reframe-package {
  align-self: center;
  width: 96px;
  height: 64px;
  border-radius: 6px;
  background: #FFFFFF;
  border: 1.5px solid rgba(105, 115, 134, 0.32);
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  padding: 10px;
}
.sn-reframe-side-silent .sn-reframe-package {
  background: rgba(255, 255, 255, 0.6);
  border-color: rgba(105, 115, 134, 0.28);
}
.sn-reframe-package.is-live {
  border-color: rgba(6, 182, 212, 0.45);
  box-shadow: 0 6px 18px -10px rgba(6, 182, 212, 0.45);
}
.sn-reframe-package-line {
  height: 3px;
  background: rgba(105, 115, 134, 0.22);
  border-radius: 2px;
}
.sn-reframe-package-line:nth-child(1) { width: 70%; }
.sn-reframe-package-line:nth-child(2) { width: 50%; }
.sn-reframe-package-line:nth-child(3) { width: 60%; }
.sn-reframe-package.is-live .sn-reframe-package-line {
  background: rgba(10, 37, 64, 0.32);
}
/* QR code in the corner of the live package — 4-dot mini-grid that
   evokes a QR pattern without requiring a real SVG. */
.sn-reframe-package-qr {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 18px;
  height: 18px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: repeat(2, 1fr);
  gap: 2px;
}
.sn-reframe-package-qr-dot {
  background: var(--sn-spark-deep);
  border-radius: 1px;
}
.sn-reframe-package-qr-dot:nth-child(2),
.sn-reframe-package-qr-dot:nth-child(3) {
  background: rgba(6, 182, 212, 0.55);
}

/* Stream panel below the package. Silent variant has empty placeholder
   lines + "No signal" label; live variant has 3 event rows that
   stagger-fade in. */
.sn-reframe-side-stream {
  background: rgba(10, 37, 64, 0.04);
  border-radius: 8px;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 132px;
  position: relative;
}
.sn-reframe-side-silent .sn-reframe-side-stream {
  background: rgba(105, 115, 134, 0.05);
  border: 1px dashed rgba(105, 115, 134, 0.22);
  align-items: center;
  justify-content: center;
}
.sn-reframe-side-stream-line {
  width: 60%;
  height: 6px;
  border-radius: 3px;
  background: rgba(105, 115, 134, 0.14);
}
.sn-reframe-side-stream-line:nth-child(2) { width: 80%; }
.sn-reframe-side-stream-line:nth-child(3) { width: 50%; }
.sn-reframe-side-stream-empty-label {
  margin-top: 4px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(105, 115, 134, 0.6);
}

/* Live event rows — three lines, stagger fade-up on first reveal,
   reusing the parent .sn-reveal observer so the animation only fires
   when the section is in view. */
.sn-reframe-event {
  display: grid;
  grid-template-columns: 8px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  background: #FFFFFF;
  border: 1px solid rgba(6, 182, 212, 0.16);
  border-radius: 6px;
  font-size: 11.5px;
  opacity: 0;
  transform: translateY(6px);
  transition:
    opacity 500ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 500ms cubic-bezier(0.22, 1, 0.36, 1);
}
.sn-reveal-shown .sn-reframe-event {
  opacity: 1;
  transform: translateY(0);
}
.sn-reveal-shown .sn-reframe-event:nth-child(1) { transition-delay: 200ms; }
.sn-reveal-shown .sn-reframe-event:nth-child(2) { transition-delay: 400ms; }
.sn-reveal-shown .sn-reframe-event:nth-child(3) { transition-delay: 600ms; }
@media (prefers-reduced-motion: reduce) {
  .sn-reframe-event { opacity: 1; transform: none; transition: none; }
}
.sn-reframe-event-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--sn-spark-deep);
  justify-self: center;
}
.sn-reframe-event-name {
  font-weight: 500;
  color: var(--sn-ink-dark);
  letter-spacing: -0.005em;
}
.sn-reframe-event-time {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--sn-ink-muted);
}

.sn-reframe-side-caption {
  margin: 0;
  font-family: var(--sn-font-display);
  font-size: clamp(18px, 2vw, 22px);
  font-weight: 500;
  letter-spacing: -0.015em;
  line-height: 1.3;
  color: var(--sn-ink-dark);
  text-wrap: balance;
}
.sn-reframe-side-silent .sn-reframe-side-caption {
  color: var(--sn-ink-muted);
}
.sn-reframe-side-live .sn-reframe-side-caption {
  background: linear-gradient(95deg, var(--sn-spectrum-blue), var(--sn-spectrum-cyan));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  padding-bottom: 0.08em;
}

/* ─── Roadmap — stacked horizontal-row layout.
   Used on the case-study page to show what publishes when. Three
   event-triggered phases as full-width rows separated by hairline
   dividers. Each row has a meta column on the left (big gradient
   number + monospace event-trigger label) and a content column on
   the right (phase title + body copy).
   Editorial register: no diagram chrome (no rails, no nodes, no
   pill tags). Typography and layout do the work. Reads as a
   confident publishing schedule, not a corporate PowerPoint.
   Replaced an earlier rail-and-nodes treatment that competed
   visually with the rest of the case-study page. */
.sn-roadmap {
  list-style: none;
  margin: 56px 0 0;
  padding: 0;
  border-top: 1px solid var(--sn-line);
}
.sn-roadmap-row {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: clamp(32px, 5vw, 64px);
  padding: clamp(28px, 4vw, 40px) 0;
  border-bottom: 1px solid var(--sn-line);
  align-items: start;
}
.sn-roadmap-meta {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.sn-roadmap-num {
  font-family: 'Inter', sans-serif;
  font-size: clamp(56px, 6vw, 76px);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 0.9;
  font-feature-settings: 'tnum' 1, 'lnum' 1;
  background: linear-gradient(135deg, var(--sn-ink-dark) 0%, var(--sn-spark-deep) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  padding-bottom: 0.05em;
}
.sn-roadmap-date {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-spark-deep);
}
.sn-roadmap-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 6px;
}
.sn-roadmap-body h3 {
  font-size: clamp(20px, 2.2vw, 24px);
  font-weight: 600;
  color: var(--sn-ink-dark);
  letter-spacing: -0.01em;
  margin: 0;
  line-height: 1.2;
}
.sn-roadmap-body p {
  font-size: 15px;
  line-height: 1.6;
  color: var(--sn-ink-soft);
  margin: 0;
  max-width: 600px;
}
@media (max-width: 720px) {
  .sn-roadmap-row {
    grid-template-columns: 1fr;
    gap: 14px;
    padding: 28px 0;
  }
  .sn-roadmap-num { font-size: 48px; }
}


/* ─── IP-status pill (.sn-patent-pill)
   Small status pill paired next to a section eyebrow on surfaces where
   we want the IP-protection signal (provisional being filed) visible
   without making it the lead message. Cyan-spark accent so it ties to the same architectural-
   commitment color treatment used elsewhere on the trust + methodology
   sections. The dot is purely decorative — animates a subtle pulse
   when a user has not enabled prefers-reduced-motion. */
.sn-eyebrow-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.sn-eyebrow-row .sn-eyebrow {
  margin: 0;
}
.sn-patent-pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-spark-deep);
  background: rgba(6, 182, 212, 0.08);
  border: 1px solid rgba(6, 182, 212, 0.26);
  padding: 4px 10px 4px 8px;
  border-radius: 999px;
  white-space: nowrap;
}
.sn-patent-pill-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--sn-spark);
  box-shadow: 0 0 8px rgba(6, 182, 212, 0.5);
  animation: sn-patent-pill-pulse 2.4s ease-in-out infinite;
}
@keyframes sn-patent-pill-pulse {
  0%, 100% { opacity: 0.6; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.18); }
}
@media (prefers-reduced-motion: reduce) {
  .sn-patent-pill-dot { animation: none; opacity: 0.85; }
}

/* ─── Stack cards — yours / ours / yours.
   Three-card visual that sits below the "we layer in, never replace"
   headline. The middle card ("Ours") gets the cyan-spark highlight
   treatment so the eye reads "two yours, one ours" — reinforcing
   that SweetNote is a thin layer between the recipient experience
   and the brand's existing stack, not a replacement for either.
   The two flanking "Yours" cards stay in white so the asymmetry
   itself communicates the architectural commitment. */
.sn-stack-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
  margin: 32px 0 36px;
}
.sn-stack-card {
  padding: 24px 24px 22px;
  background: #FFFFFF;
  border: 1px solid var(--sn-line);
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
}
.sn-stack-card.is-ours {
  background: linear-gradient(180deg, rgba(6, 182, 212, 0.07), rgba(34, 211, 238, 0.02));
  border-color: rgba(6, 182, 212, 0.32);
  box-shadow: 0 0 0 4px rgba(6, 182, 212, 0.06);
}
.sn-stack-card-tag {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
  align-self: flex-start;
  padding: 3px 10px;
  background: rgba(105, 115, 134, 0.10);
  border-radius: 999px;
}
.sn-stack-card.is-ours .sn-stack-card-tag {
  color: var(--sn-spark-deep);
  background: rgba(6, 182, 212, 0.12);
  border: 1px solid rgba(6, 182, 212, 0.22);
}
.sn-stack-card-name {
  font-size: 17px;
  font-weight: 600;
  color: var(--sn-ink-dark);
  letter-spacing: -0.005em;
  margin: 0;
}
.sn-stack-card-detail {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--sn-ink-soft);
  margin: 0;
}
@media (max-width: 880px) {
  .sn-stack-cards { grid-template-columns: 1fr; gap: 10px; }
}

/* ─── Section split-layout with sticky left column — Stripe Atlas
   pattern: a left column that pins while a longer right column scrolls
   past. Used on Independence + Architecture sections so the headline
   stays anchored while the supporting cards reveal one by one. */
.sn-split-sticky {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: clamp(36px, 6vw, 80px);
  align-items: start;
}
.sn-split-sticky-headline {
  position: sticky;
  top: 100px;
  align-self: start;
}
.sn-split-sticky-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
@media (max-width: 880px) {
  .sn-split-sticky { grid-template-columns: 1fr; gap: 24px; }
  .sn-split-sticky-headline { position: static; }
}

/* ─── Methodology comparison — three-card contrast between
   survey-based measurement, biometric measurement, and behavioral
   measurement (SweetNote). The behavioral column gets a cyan-spark
   highlight border + tinted background to anchor "this is the
   right one." Each card carries an icon, a category label, a
   one-line headline, a paragraph explaining the trade-off, and a
   footer with a numeric stat and its interpretation. */
/* Asymmetric layout — 2 small "not recommended" cards on top row,
   1 large "this is what we do" card on bottom row spanning both
   columns. Visual weight is intentionally lopsided so the eye reads
   "these two are alternatives we considered and dismissed; this
   third one is the one to pay attention to." */
.sn-method-compare {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 48px;
}
.sn-method-card {
  background: #FFFFFF;
  border: 1px solid var(--sn-line);
  border-radius: 12px;
  padding: 22px 22px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  position: relative;
}
/* Dimmed treatment for the alternatives we DON'T recommend.
   Smaller padding, muted tones, grayscale icon, struck-through label
   above the headline. Reads at a glance as "this is what other
   measurement tools do, and we don't." */
.sn-method-card.is-dimmed {
  background: #F8F9FB;
  border-color: rgba(105, 115, 134, 0.18);
  opacity: 0.92;
}
.sn-method-card.is-dimmed::before {
  content: "What we don't do";
  position: absolute;
  top: 14px;
  right: 14px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(176, 74, 42, 0.85);
  background: rgba(176, 74, 42, 0.08);
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid rgba(176, 74, 42, 0.20);
}
.sn-method-card.is-dimmed .sn-method-icon {
  background: rgba(105, 115, 134, 0.10);
  color: rgba(105, 115, 134, 0.65);
}
.sn-method-card.is-dimmed .sn-method-label,
.sn-method-card.is-dimmed .sn-method-h,
.sn-method-card.is-dimmed .sn-method-cap {
  color: var(--sn-ink-muted);
}
.sn-method-card.is-dimmed .sn-method-h {
  text-decoration: line-through;
  text-decoration-color: rgba(105, 115, 134, 0.35);
  text-decoration-thickness: 1px;
}
.sn-method-card.is-dimmed .sn-method-stat {
  color: rgba(105, 115, 134, 0.75);
}

/* Collapsible methodology card (the two "what we don't do" rows on
   the homepage). Same dimmed treatment as before, but rendered as a
   <details> accordion so first paint shows just label + struck-through
   headline + toggle. The "What we don't do" badge that used to live
   absolutely-positioned in the corner is suppressed here — the
   struck-through headline already conveys the rejection, and the
   absolute badge collides with the toggle. */
details.sn-method-card-collapsible {
  display: block;
  padding: 0;
  gap: 0;
}
details.sn-method-card-collapsible::before { display: none; }
details.sn-method-card-collapsible > summary {
  list-style: none;
  cursor: pointer;
  padding: 18px 20px;
  display: grid;
  grid-template-columns: 42px 1fr 22px;
  align-items: center;
  gap: 14px;
}
details.sn-method-card-collapsible > summary::-webkit-details-marker { display: none; }
.sn-method-card-summary-text {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.sn-method-card-summary-text .sn-method-h {
  font-size: 15px;
  line-height: 1.3;
}
.sn-method-card-toggle {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(105, 115, 134, 0.55);
  position: relative;
  flex-shrink: 0;
}
.sn-method-card-toggle::before,
.sn-method-card-toggle::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background: #FFFFFF;
  border-radius: 1px;
  transform: translate(-50%, -50%);
}
.sn-method-card-toggle::before { width: 10px; height: 1.5px; }
.sn-method-card-toggle::after { width: 1.5px; height: 10px; transition: transform 0.18s ease; }
details.sn-method-card-collapsible[open] .sn-method-card-toggle::after { transform: translate(-50%, -50%) scaleY(0); }
.sn-method-card-body {
  padding: 0 20px 20px 76px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
@media (max-width: 720px) {
  .sn-method-card-body { padding-left: 20px; }
}
/* Feature treatment — the behavioral card. Spans both columns of
   the grid (full row width), gets larger padding, bigger headline,
   full-color icon, cyan accent border + glow shadow. */
.sn-method-card.is-highlight {
  background: linear-gradient(180deg, rgba(6, 182, 212, 0.06), rgba(34, 211, 238, 0.02));
  border-color: rgba(6, 182, 212, 0.32);
  box-shadow: 0 0 0 4px rgba(6, 182, 212, 0.06);
}
.sn-method-card.is-feature {
  grid-column: 1 / -1;
  padding: 36px 36px 32px;
  flex-direction: row;
  gap: 28px;
  align-items: stretch;
}
.sn-method-card.is-feature .sn-method-icon {
  width: 56px; height: 56px;
  flex-shrink: 0;
}
.sn-method-card.is-feature .sn-method-icon svg { width: 28px; height: 28px; }
.sn-method-feature-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
  min-width: 0;
}
.sn-method-card.is-feature .sn-method-h {
  font-size: clamp(20px, 2vw, 26px);
  letter-spacing: -0.015em;
  line-height: 1.25;
}
.sn-method-card.is-feature .sn-method-cap {
  font-size: 15px;
  line-height: 1.6;
  max-width: 720px;
}
.sn-method-card.is-feature .sn-method-foot {
  flex-direction: row;
  align-items: baseline;
  gap: 14px;
  padding-top: 14px;
  border-top: 1px solid rgba(6, 182, 212, 0.18);
}
.sn-method-card.is-feature .sn-method-stat {
  font-size: clamp(28px, 3vw, 36px);
}
.sn-method-card.is-feature .sn-method-stat-label {
  font-size: 13px;
}
.sn-method-icon {
  width: 42px; height: 42px;
  background: var(--sn-paper-deep);
  border-radius: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--sn-ink-soft);
}
.sn-method-icon svg { width: 22px; height: 22px; }
.sn-method-card.is-highlight .sn-method-icon {
  background: rgba(6, 182, 212, 0.10);
  color: var(--sn-spark-deep);
}
.sn-method-label {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--sn-ink-muted);
}
.sn-method-card.is-highlight .sn-method-label { color: var(--sn-spark-deep); }
.sn-method-h {
  font-size: 17px;
  margin: 0;
  color: var(--sn-ink-dark);
  letter-spacing: -0.005em;
  line-height: 1.3;
  font-weight: 600;
}
.sn-method-cap {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--sn-ink-soft);
  margin: 0;
  flex: 1;
}
.sn-method-foot {
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--sn-line-soft);
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.sn-method-stat {
  font-family: var(--sn-font-display);
  font-size: clamp(22px, 2.2vw, 28px);
  font-weight: 500;
  color: var(--sn-ink-dark);
  letter-spacing: -0.02em;
  line-height: 1.05;
}
.sn-method-card.is-highlight .sn-method-stat {
  background: linear-gradient(95deg, var(--sn-spectrum-blue), var(--sn-spectrum-cyan));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  padding-bottom: 0.08em;
}
.sn-method-stat-label {
  font-size: 12px;
  color: var(--sn-ink-muted);
  line-height: 1.4;
}

@media (max-width: 720px) {
  .sn-method-compare { grid-template-columns: 1fr; gap: 12px; }
  .sn-method-card.is-feature { flex-direction: column; padding: 28px 24px; gap: 14px; }
  .sn-method-card.is-feature .sn-method-foot { flex-direction: column; align-items: flex-start; gap: 4px; }
}

/* The "moment" callout — closing argument about why the physical-gift
   moment is itself a unique measurement window. Sits below the 3-card
   compare. Strong display-font typography, cyan-spark left edge, soft
   gradient background — reads as a quote/aphorism rather than another
   card. Anchored visually with a small eyebrow above. */
.sn-method-moment {
  margin: 56px auto 0;
  max-width: 820px;
  padding: 36px clamp(24px, 4vw, 44px);
  background: var(--sn-mist, #F6F9FC);
  border: 1px solid var(--sn-hairline, #E3E8EE);
  border-radius: 12px;
}
.sn-method-moment-eyebrow {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sn-spark-deep);
  margin-bottom: 14px;
  display: block;
}
.sn-method-moment-quote {
  font-family: var(--sn-font-display);
  font-size: clamp(20px, 2vw, 26px);
  line-height: 1.45;
  color: var(--sn-ink-dark);
  letter-spacing: -0.01em;
  font-weight: 500;
  margin: 0;
}
.sn-method-moment-quote em {
  font-style: normal;
  background: linear-gradient(95deg, var(--sn-spectrum-blue), var(--sn-spectrum-cyan));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
  font-weight: 600;
  padding-bottom: 0.05em;
}
/* Small "see the research" footer link inside the moment callout.
   Quietly invites a curious visitor to deep-dive without competing
   visually with the quote above it. */
.sn-method-moment-cite {
  margin: 16px 0 0;
  font-size: 13px;
  line-height: 1.4;
}
.sn-method-moment-cite a {
  color: var(--sn-spark-deep);
  text-decoration: none;
  font-weight: 600;
  border-bottom: 1px solid rgba(8, 145, 178, 0.32);
  padding-bottom: 1px;
  transition: border-color 0.15s ease;
}
.sn-method-moment-cite a:hover {
  border-bottom-color: var(--sn-spark-deep);
}

/* ════════════════════════════════════════════════════════════════════
   SPARK-COLOR DISCIPLINE — Stripe-style restraint pass
   ────────────────────────────────────────────────────────────────────
   Cyan (--sn-spark / --sn-spark-deep) was creeping into too many
   roles: every uppercase eyebrow, every tag chip, every fact-key,
   every body <em>. When the brand color is everywhere, nothing pops.

   Locked roles for cyan from this point forward:
     ✓ Gradient text (.sn-gradient-text — hero h1 highlight)
     ✓ Primary CTA background
     ✓ Single hover/focus accent border (one moment per card)
     ✓ Active sidebar nav
     ✓ Inline links inside body copy
     ✓ Decorative icon backgrounds (one chip per card)

   Demoted from cyan to muted ink (or ink-dark for emphasis):
     ✗ Mono uppercase eyebrows
     ✗ Tag chips
     ✗ Fact-keys / method-keys (column headers inside cards)
     ✗ Body <em> and <strong> (use weight 600, not color)

   The `body` prefix is a specificity bump that lets these rules
   beat per-page <style> block declarations without !important.
   ════════════════════════════════════════════════════════════════════ */

/* Eyebrows + tag chips — quiet mono labels, not loud accents.
   These ride above headlines and on cards as scannable category
   markers; they should NEVER outshout the headline below them. */
body .rs-hero-eyebrow,
body .rs-section-eyebrow,
body .rs-signal-eyebrow,
body .rs-source-eyebrow,
body .rs-pillar-tag,
body .rs-signal-tag,
body .rs-study-tag,
body .hiw-hero-eyebrow,
body .hiw-int-tag,
body .hiw-mock-phone-eyebrow,
body .pr-breath-eyebrow,
body .pr-compare-eyebrow,
body .pr-result-eyebrow,
body .sec-meta-tag,
body .sn-method-moment-eyebrow,
body .sn-proof-band-eyebrow,
body .sn-platforms-eyebrow,
body .sn-founder-note-continuity-eyebrow,
body .sn-reveal-mock-eyebrow,
body .sn-personalize-tag,
body .sn-stack-card-tag,
body .sn-studio-preview-tag,
body .sn-faq-answer-tag {
  color: var(--sn-ink-muted);
}

/* Fact-keys / method-keys — column headers inside cards. Same
   restraint: mono mute, not cyan. */
body .rs-study-fact-key,
body .rs-study-method-key,
body .rs-signal-foot-key {
  color: var(--sn-ink-muted);
}

/* Bullet dots that preceded fact-keys: drop the cyan bullet too. */
body .rs-study-fact-key::before {
  background: var(--sn-ink-faint);
}

/* Body <em> + <strong> — emphasis via WEIGHT (600), not color.
   Stripe never colors body text; emphasis is purely typographic. */
body .rs-study-fact-val em,
body .rs-study-method em {
  color: var(--sn-ink-dark);
  font-style: normal;
  font-weight: 600;
}
body .rs-study-fact-val strong,
body .rs-signal-foot strong,
body .rs-source-relevance strong,
body .rs-study-method strong {
  color: var(--sn-ink-dark);
  font-weight: 600;
}

/* ─── Pass-A hover-lift sweep: opt the major static card families
   into a subtle lift on hover. Same micro-interaction the index
   home-campaign cards have, applied to signal cards / pillar cards
   / source cards / signature-signal cards across methods + research.
   transition + non-hover state are inherited from the per-page
   declarations; we add only the :hover delta. */
body .rs-signal,
body .rs-pillar,
body .rs-source,
body .hiw-int-card {
  transition: border-color 0.18s ease, transform 0.22s ease, box-shadow 0.22s ease;
}
body .rs-signal:hover,
body .rs-pillar:hover,
body .rs-source:hover,
body .hiw-int-card:hover {
  border-color: rgba(10, 37, 64, 0.20);
  transform: translateY(-2px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.85) inset,
    0 4px 8px rgba(10, 37, 64, 0.04),
    0 24px 48px -18px rgba(10, 37, 64, 0.18);
}
@media (prefers-reduced-motion: reduce) {
  body .rs-signal:hover,
  body .rs-pillar:hover,
  body .rs-source:hover,
  body .hiw-int-card:hover { transform: none; }
}

/* ─── Pass-A scroll-reveal — the [data-reveal] elements get this
   transform/opacity until the IntersectionObserver in site-anim.js
   adds .is-reveal-shown. Subtle: 8px lift, 280ms ease-out.
   Gated under html.sn-js (set synchronously in each page <head>) so the
   hidden state applies ONLY when JS is present to reveal them — no-JS
   browsers get fully-visible content with no noscript override needed. */
.sn-js [data-reveal] {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.4s ease-out, transform 0.5s cubic-bezier(0.32, 0.72, 0.24, 1.0);
  will-change: opacity, transform;
}
.sn-js [data-reveal].is-reveal-shown {
  opacity: 1;
  transform: translateY(0);
}
/* Above-the-fold on load: revealed instantly by site-anim.js with NO
   transition, so the page opens already settled instead of playing a
   fade/slide-in on every navigation (the "double load" jitter). */
.sn-js [data-reveal].is-reveal-instant {
  transition: none;
}
@media (prefers-reduced-motion: reduce) {
  .sn-js [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ─── Pass-A animated counters — visual hint that numbers are
   "calculating" while they tick. Use tabular-nums so digits don't
   reflow as values cycle through. */
[data-count-up] {
  font-feature-settings: 'tnum' 1, 'lnum' 1;
  font-variant-numeric: tabular-nums lining-nums;
}

/* ─── Mobile-only progressive disclosure ──────────────────────────────
   Lets phone visitors scroll a clean spine and tap to reveal supporting
   detail. The wiring lives in scripts/site-anim.js and runs ONLY at
   <=767px; on desktop the script no-ops and these rules don't apply, so
   the desktop layout is byte-for-byte unchanged. A `.sn-mc-sum` element
   becomes the tap target for the `.sn-mc-body` sibling that follows it.
   If JS fails, nothing is marked [aria-expanded] and all content simply
   shows — graceful degradation, never a dead end. */
/* Make the `hidden` attribute win even when a body element sets its own
   `display` (e.g. flex/grid lists) — the classic [hidden]-override trap.
   Only the mobile script ever sets [hidden] on these, so desktop is
   unaffected. */
.sn-mc-body[hidden] { display: none !important; }
@media (max-width: 767px) {
  .sn-mc-sum[aria-expanded] {
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    display: flex;
    align-items: center;
    min-height: 44px;
    position: relative;
    padding-right: 28px;
  }
  /* The cue is a single quiet chevron pinned to the right of the row — no
     words. It rotates 180° on open. This is the one disclosure signifier
     used everywhere (NN/g: the caret is the affordance users recognize). */
  .sn-mc-sum[aria-expanded]::after {
    content: "";
    position: absolute;
    right: 7px;
    top: 50%;
    margin-top: -4px;
    width: 8px;
    height: 8px;
    border-right: 2px solid var(--sn-spark-deep, #0891B2);
    border-bottom: 2px solid var(--sn-spark-deep, #0891B2);
    border-radius: 0 0 2px 0;
    transform: rotate(45deg);
    transform-origin: 55% 55%;
    transition: transform 0.2s ease;
  }
  .sn-mc-sum[aria-expanded="true"]::after { transform: rotate(-135deg); }
  .sn-mc-sum[aria-expanded]:focus-visible {
    outline: 2px solid var(--sn-spark-deep, #0891B2);
    outline-offset: 3px;
    border-radius: 4px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .sn-mc-sum[aria-expanded]::after { transition: none; }
}

/* ─── Mobile-only swipe carousel ──────────────────────────────────────
   Turns a desktop grid/row of 3+ peer cards into a horizontal, snap-to
   swipe carousel on phones — so a comparison set reads as "swipe through"
   instead of a long vertical scroll. Add `.sn-hscroll` to the container
   (its desktop grid/flex layout is left intact; these rules apply ONLY at
   <=767px). Each direct child becomes a snap card; the next one peeks so
   the swipe affordance is obvious. Desktop is untouched. */
@media (max-width: 767px) {
  .sn-hscroll {
    display: flex !important;
    flex-wrap: nowrap !important;
    grid-template-columns: none !important;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    gap: 12px;
    scroll-padding-left: 2px;
    /* full-bleed to the screen edges so cards can swipe past the frame */
    margin-inline: calc(-1 * var(--sn-hscroll-bleed, 0px));
    padding-inline: var(--sn-hscroll-bleed, 0px);
  }
  .sn-hscroll::-webkit-scrollbar { display: none; }
  .sn-hscroll > * {
    flex: 0 0 86% !important;
    scroll-snap-align: start;
    min-width: 0;
  }
  /* trailing breathing room so the last card snaps cleanly */
  .sn-hscroll::after {
    content: "";
    flex: 0 0 1px;
    align-self: stretch;
  }
  /* swipe hint — a small mono cue above the rail, opt in with .sn-hscroll-hint */
  .sn-hscroll-hint { display: block; }
}
.sn-hscroll-hint { display: none; }

/* ─── Sticky mobile CTA ───────────────────────────────────────────────
   A slim bar that slides up once the hero scrolls off, so converting is
   always one thumb-tap away on a phone. Created + driven by site-anim.js
   on mobile only; it never exists in the DOM on desktop, so desktop is
   untouched. */
.sn-mobile-cta {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 9px 16px;
  padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  background: rgba(255, 255, 255, 0.94);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  backdrop-filter: saturate(1.4) blur(12px);
  border-top: 1px solid var(--sn-line, #E3E8EE);
  box-shadow: 0 -8px 24px -14px rgba(10, 37, 64, 0.28);
  transform: translateY(125%);
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.sn-mobile-cta.is-visible { transform: translateY(0); }
/* flex-wrap so the bar stacks instead of overflowing on very narrow phones.
   The primary is flex:1 but min-width:auto floors it at its label's min-content
   (~180px), and the demo button is flex:0 0 auto + nowrap, so at a 320px viewport
   the pair exceeded the row and pushed past the screen edge. Wrapping never fires
   at 360px and above, where both still fit on one line. Measured, not assumed. */
.sn-mobile-cta-row { display: flex; gap: 8px; flex-wrap: wrap; }
.sn-mobile-cta-row .sn-btn { justify-content: center; min-height: 46px; }
.sn-mobile-cta-row .sn-btn-primary { flex: 1; }
.sn-mobile-cta-demo { flex: 0 0 auto; white-space: nowrap; }
/* a quiet "ask a human" line for the buyer who'd rather talk first */
.sn-mobile-cta-ask {
  display: block;
  text-align: center;
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--sn-ink-muted);
  text-decoration: none;
}
.sn-mobile-cta-ask strong { color: var(--sn-link, #0E7490); font-weight: 600; }
.sn-mobile-cta-ask:active { opacity: 0.7; }
@media (min-width: 768px) { .sn-mobile-cta { display: none !important; } }
@media (prefers-reduced-motion: reduce) { .sn-mobile-cta { transition: none; } }

/* ─── Scroll dots for .sn-hscroll carousels ───────────────────────────
   site-anim.js auto-generates one dot per card beneath each swipe rail on
   mobile and syncs the active dot to scroll position (tap a dot to jump).
   The element is only created on mobile, so desktop never has it. */
.sn-hscroll-dots { display: none; }
@media (max-width: 767px) {
  .sn-hscroll-dots {
    display: flex;
    justify-content: center;
    gap: 3px;
    margin-top: 14px;
  }
  .sn-hscroll-dot {
    width: 30px; height: 40px;          /* >=40px tap target; 7px visual via ::before */
    padding: 0; border: 0; background: transparent;
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
  }
  .sn-hscroll-dot::before {
    content: "";
    width: 7px; height: 7px; border-radius: 999px;
    background: var(--sn-line, #E3E8EE);
    transition: background 0.22s ease, width 0.22s ease;
  }
  .sn-hscroll-dot.is-active::before {
    background: var(--sn-spark-deep, #0891B2);
    width: 20px;
  }
}

/* ─── FAQ accordion (mobile only) ─────────────────────────────────────
   The FAQ ships answers fully expanded — fine on desktop, a wall of text
   on a phone. site-anim.js (FAQ page only) collapses each answer behind
   its question on mobile; these rules give the question a tap affordance.
   Desktop never gets the .sn-faq-q class, so it stays fully expanded. */
@media (max-width: 767px) {
  .sn-faq-q {
    cursor: pointer;
    position: relative;
    padding-right: 26px;
    -webkit-tap-highlight-color: transparent;
  }
  .sn-faq-q::after {
    content: "+";
    position: absolute;
    right: 2px;
    top: 50%;
    transform: translateY(-50%);
    font-weight: 400;
    font-size: 1.5em;
    line-height: 1;
    color: var(--sn-spark-deep, #0891B2);
  }
  .sn-faq-q[aria-expanded="true"]::after { content: "\2013"; }
  .sn-faq-a[hidden] { display: none !important; }
}

/* ─── Tactile press feedback (mobile) ─────────────────────────────────
   A subtle scale-down on tap so buttons feel physical on a phone. Mobile
   only — desktop (hover/click) is untouched. */
@media (max-width: 767px) {
  .sn-btn { transition: transform 0.12s cubic-bezier(0.22, 1, 0.36, 1); }
  .sn-btn:active { transform: scale(0.97); }
  .sn-mobile-cta .sn-btn:active { transform: scale(0.98); }
  /* Snappier scroll-reveals on mobile — 700ms feels great scrolling
     slowly but lags a fast flick; 520ms settles before you arrive.
     Desktop keeps the slower, more cinematic 700ms. */
  .sn-reveal { transition-duration: 520ms; }
}

/* ─── Smooth page-to-page transitions ─────────────────────────────────
   Cross-document view transitions: a quick cross-fade between same-origin
   pages instead of a hard white-flash reload, so the site feels like one
   continuous product when flipping between pages. Progressive enhancement
   — browsers without support just navigate normally. Applies site-wide
   (it's a navigation transition, not a layout change). */
@view-transition { navigation: auto; }
::view-transition-old(root),
::view-transition-new(root) { animation-duration: 0.22s; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none; }
}

/* ── iOS form-control zoom floor (A6 mobile pass, 2026-08-30; REWRITTEN same day) ──
   iOS Safari zooms the whole page when a focused text control renders under 16px.
   styles/site.css has no `pointer: coarse` block, so MARKETING forms genuinely lack
   the protection that clients/styles/client.css:5025 has always given the portal
   (16px + min-height 44px + padding 12px 14px). /login.html at 14.5px is a brand's
   first touch of the product; /contact.html is 15px across six fields.

   ⚠ THE FIRST VERSION OF THIS RULE WAS A BLANKET `font-size: 16px !important` ON
   EVERY input/select/textarea AT max-width 767px, AND IT SHIPPED BROKEN. Three
   things were wrong with it and each one matters:

   1. `font-size: 16px` is an ASSIGNMENT, not a floor. Four controls in this repo are
      display typography that happens to be an <input>, and it CRUSHED all of them:
      .pr-slider-value-num (the pricing calculator's hero recipient count, clamp
      32-44px, in a font-relative box that collapsed 176px -> 128px, leaving the
      headline number SMALLER than its own 10.5px "Recipients" caption — on the
      pricing page), .pr-arms-num-input (28px in a fixed 80px box),
      .cl-wizard-name-input (28px — that input IS the wizard's H1 and the locked
      .cl-page-header spec), and #lg-code-input (an inline 19px letter-spaced OTP
      field, which a stylesheet !important beats).
   2. It was scoped to `max-width: 767px`, which is a proxy for "phone" and gets it
      wrong in both directions: it fires on a narrowed DESKTOP window (where there is
      no zoom bug to fix and no compensating min-height) and it says nothing about
      pointer type, which is what the bug actually tracks.
   3. Its stated justification was false. client.css does not "win by coming later"
      on phones — it already sets these to 16px under `pointer: coarse`, correctly
      paired with min-height and padding. The rule was solving, for the portal, a
      problem that only existed in the emulator used to find it: CDP touch emulation
      did NOT make `(pointer: coarse)` match, so every portal control measured at its
      desktop size. The marketing half of the finding was real; the portal half was
      an artifact of the harness.

   So: `pointer: coarse` (the condition the bug actually has), NOT `!important` (so an
   inline font-size on a display input still wins), and an explicit exclusion list for
   the class-styled display inputs. If you add a form control that is display type,
   add it here. */
@media (pointer: coarse) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="button"]):not([type="image"]):not([type="file"]):not(.pr-slider-value-num):not(.pr-arms-num-input):not(.cl-wizard-name-input),
  select,
  textarea {
    font-size: max(16px, 1rem);
  }
  /* .sn-form-field input/select/textarea is 0,1,1 and would beat a bare `select`
     at 0,0,1 — /contact.html's three selects stayed at 15px until this line.
     Matched specificity, still no !important, so an inline display size wins. */
  .sn-form-field input,
  .sn-form-field select,
  .sn-form-field textarea {
    font-size: max(16px, 1rem);
  }
}
