/* =========================================================================
   Design system v3.2 — see Website/DESIGN_SYSTEM.md for the documented
   rationale. Premium refinement pass, 2026-08-17; deepened same day
   (focused refinement #2); recolored same day again per founder's exact
   reference spec (v3.2) — a strong, saturated #5C28F4 Revealta purple used
   *selectively* (CTA, accents, active/evidence states) plus a softer
   derived violet for repeated structural chrome, diffusing into an
   atmospheric lavender/plum background system. System font stack retained
   after evaluation — no external font requests, offline-safe. Still white
   first, purple noticed on a second look — the strong color is a signal,
   not a wash.
   ========================================================================= */

:root {
  /* Palette — near-black navy for text/headings (unchanged, already
     premium). Two-tier violet system per founder's exact spec: --violet-
     strong is the concentrated brand color (used selectively: CTAs,
     accents, active states, evidence highlights); --violet is a softer
     derivative of the same hue (used for repeated chrome -- labels, icons,
     links -- that would read as "purple everywhere" at full strength).
     --plum is atmospheric-only, never text/buttons/borders. See
     Website/DESIGN_SYSTEM.md for full rationale. */
  --navy: #0B0F19;
  --violet-strong: #5C28F4;
  --violet: #6247A6;
  --violet-dark: #4A1FC7;
  --plum: #7A3F5C;
  --lavender-bg: #F6F3FA;
  --bg: #F7F6F2;
  --bg-white: #FFFFFF;
  --text: #14151A;
  --text-muted: #57564F;
  --text-faint: #8B897E;
  --green: #1E7A46;
  --green-bg: #EEF6F0;
  --amber: #A15A17;
  --amber-bg: #FBF1E6;
  --red: #A23B33;
  --red-bg: #FAEEEC;
  --border: #E7E4DC;
  --border-strong: #D6D2C6;

  /* Shadows — tokenized (were scattered rgba() one-offs in v2). Card shadow
     stays neutral; hover shadow carries a soft violet-strong tint at low
     opacity, per the founder's "subtle interaction states" use case --
     reads as soft light on hover, not a solid fill. */
  --shadow-card: 0 1px 2px rgba(11,15,25,.04), 0 8px 24px rgba(11,15,25,.05);
  --shadow-hover: 0 14px 34px rgba(92,40,244,.20);
  --focus-ring: 0 0 0 3px rgba(92,40,244,.22);

  /* Type scale — larger, more confident hero size; same restrained scale
     elsewhere. */
  --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --fs-xs: 0.8125rem;   /* 13px */
  --fs-sm: 0.9375rem;   /* 15px */
  --fs-base: 1.0625rem; /* 17px */
  --fs-lg: 1.25rem;     /* 20px */
  --fs-xl: 1.5rem;      /* 24px */
  --fs-2xl: 2rem;       /* 32px */
  --fs-3xl: 2.75rem;    /* 44px */
  --fs-4xl: 3.5rem;     /* 56px — cleaner, more restrained hero size (was 72px) */

  /* Spacing (8px base unit) */
  --sp-1: 0.5rem;
  --sp-2: 1rem;
  --sp-3: 1.5rem;
  --sp-4: 2rem;
  --sp-5: 2.5rem;
  --sp-6: 3rem;
  --sp-8: 4rem;
  --sp-12: 6rem;
  --sp-16: 8rem;
  --sp-20: 10rem;

  --radius: 10px;
  --radius-sm: 6px;
  --max-width: 1120px;

  /* Motion */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-fast: 150ms;
  --dur: 400ms;
  --dur-slow: 700ms;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--text);
  background: var(--bg-white);
  line-height: 1.55;
  font-size: var(--fs-base);
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }

a { color: inherit; }

.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--sp-3);
}

/* ---------- Header / Nav ---------- */
.site-header {
  border-bottom: 1px solid transparent;
  background: var(--bg-white);
  position: sticky;
  top: 0;
  z-index: 40;
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.site-header.scrolled { border-bottom-color: var(--border); box-shadow: var(--shadow-card); }
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 72px;
}
.brand-mark {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  font-size: var(--fs-lg);
  letter-spacing: -0.01em;
  text-decoration: none;
  color: var(--navy);
}
.brand-icon {
  height: 26px;
  width: 26px;
  object-fit: contain;
  display: block;
}
.brand-group {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-width: 0;
}
.brand-tagline {
  font-size: var(--fs-xs);
  color: var(--text-faint);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-left: var(--sp-2);
  border-left: 1px solid var(--border-strong);
}
@media (max-width: 860px) {
  .brand-tagline { display: none; }
}
.nav-links {
  display: flex;
  gap: var(--sp-4);
  align-items: center;
  flex-wrap: nowrap;
}
/* "What we do" and "How it works" were breaking onto two lines, which makes the
   whole header look accidental. Labels never wrap; if the row genuinely runs out
   of room the links collapse at a breakpoint instead (see below), which is the
   founder's stated preference over shrinking the type. */
.nav-links a { white-space: nowrap; }
.nav-links a {
  text-decoration: none;
  color: var(--text-muted);
  font-size: var(--fs-sm);
  font-weight: 500;
}
.nav-links a:hover { color: var(--navy); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  border-radius: var(--radius-sm);
  font-weight: 600;
  font-size: var(--fs-sm);
  padding: 0.9rem 1.6rem;
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
  min-height: 44px;
}
.btn:active { transform: translateY(1px); }
.btn.btn-primary {
  background: var(--violet-strong);
  color: #fff;
  box-shadow: var(--shadow-card);
}
.btn.btn-primary:hover { background: var(--violet-dark); transform: translateY(-1px); box-shadow: var(--shadow-hover); }
.btn-secondary {
  background: transparent;
  color: var(--navy);
  border-color: var(--border-strong);
}
.btn-secondary:hover { border-color: var(--navy); background: var(--bg); }
.btn-text {
  background: none;
  border: none;
  color: var(--violet);
  font-weight: 600;
  font-size: var(--fs-sm);
  text-decoration: none;
  padding: 0;
  cursor: pointer;
}
.btn-text:hover { color: var(--navy); }
.btn-block { width: 100%; }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* ---------- Sections ---------- */
section { padding: var(--sp-12) 0; }
/* Homepage rhythm, tightened 2026-08-31.
   `--sp-12` top and bottom means 192px between two adjacent sections, which
   reads as a gap rather than as breathing room once the page is viewed whole
   rather than section by section. These four run consecutively and carry the
   argument, so the joins between them were the ones that felt slack.
   4.75rem is a ~21% reduction and keeps the restraint; it is scoped to `.home`
   so /check, /work-with-us and the Snapshot pages keep their own rhythm. */
.home .discovery,
.home #example,
.home #what-we-do,
.home #what-we-improve { padding: 4.75rem 0; }
section.tight { padding: var(--sp-8) 0; }
/* Dense data pages (Snapshot) use <section> purely as a scroll-reveal
   wrapper, not a marketing-page block -- the default 96px rhythm above is
   much too loose here and was creating awkward gaps. */
.snapshot-header ~ section,
.at-a-glance ~ section { padding: var(--sp-4) 0; }
.section-label {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--violet);
  margin: 0 0 var(--sp-2);
}
h1, h2, h3 { color: var(--navy); letter-spacing: -0.02em; margin: 0; }
h1 { font-size: var(--fs-4xl); line-height: 1.12; font-weight: 700; }
.accent { color: var(--violet-strong); }
h2 { font-size: var(--fs-2xl); line-height: 1.15; font-weight: 700; letter-spacing: -0.015em; }
h3 { font-size: var(--fs-lg); font-weight: 600; letter-spacing: -0.005em; }
.subhead {
  font-size: var(--fs-lg);
  color: var(--text-muted);
  line-height: 1.55;
  max-width: 620px;
  font-weight: 400;
}
.eyebrow {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--violet);
  margin-bottom: var(--sp-2);
}

.bg-navy { background: var(--navy); color: #fff; }
.bg-light { background: var(--bg); }

/* ---------- Hero ---------- */
.hero {
  position: relative;
  overflow: hidden;
  padding: var(--sp-16) 0 var(--sp-12);
  text-align: center;
  background: linear-gradient(180deg, #FFFFFF 0%, var(--bg) 100%);
}
.hero .container { max-width: 800px; position: relative; z-index: 1; }
.hero h1 { margin-bottom: var(--sp-3); max-width: 660px; margin-left: auto; margin-right: auto; text-wrap: balance; }
.hero .subhead { margin: 0 auto var(--sp-4); }
.hero-ctas {
  display: flex;
  gap: var(--sp-3);
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  margin-top: var(--sp-4);
}

/* Atmospheric light system -- large, extremely soft violet/plum fields
   whose centers sit OUTSIDE the section bounds (large negative offsets),
   so only a diffused edge of light ever enters the white canvas -- never
   a visible circle or blob boundary. Purely decorative (aria-hidden where
   applicable), never covers text (z-index below .container), frozen by the
   global reduced-motion rule. The governing test: someone should register
   the page as white first, and only notice the light on a second look --
   if it reads as "a gradient background," it's too strong.

   Deliberately asymmetric and varied per placement, not the same field
   repeated -- .atmosphere's custom properties are overridden per modifier
   class so each placement gets its own position/size/hue rather than one
   reusable blob. Every hue traces back to the same brand purple
   (--violet-strong, #5C28F4) diffusing toward transparent/plum, per the
   founder's "one coherent purple system" direction -- this is not a
   separate, unrelated background palette. */
.hero-bg,
.atmosphere { position: relative; overflow: hidden; }
.hero-bg { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.hero-bg::before,
.hero-bg::after,
.atmosphere::before {
  content: "";
  position: absolute;
  z-index: 0;
  pointer-events: none;
  width: var(--atmo-size, 900px);
  height: var(--atmo-size, 900px);
  border-radius: 50%;
  filter: blur(var(--atmo-blur, 130px));
  background: radial-gradient(circle, var(--atmo-color, rgba(92,40,244,.13)), transparent 65%);
  top: var(--atmo-top, auto);
  right: var(--atmo-right, auto);
  bottom: var(--atmo-bottom, auto);
  left: var(--atmo-left, auto);
}

/* Hero -- the strongest moment. A large field entering from the upper
   left, a much fainter warm-plum field low on the right, both centered
   well outside the viewport. */
.hero-bg::before {
  --atmo-size: 1040px;
  --atmo-blur: 140px;
  --atmo-color: rgba(92,40,244,.18);
  --atmo-top: -420px;
  --atmo-left: -340px;
  animation: heroDriftA 24s ease-in-out infinite alternate;
}
.hero-bg::after {
  --atmo-size: 760px;
  --atmo-blur: 125px;
  --atmo-color: rgba(122,63,92,.08);
  --atmo-top: -60px;
  --atmo-right: -300px;
  animation: heroDriftB 28s ease-in-out infinite alternate;
}
.hero .container { position: relative; z-index: 1; }

/* Base .atmosphere placement (discovery-demo): soft violet entering from
   the right, quieter than the hero. */
.atmosphere::before {
  --atmo-size: 860px;
  --atmo-color: rgba(92,40,244,.12);
  --atmo-top: -320px;
  --atmo-right: -280px;
}

/* Snapshot section: faint, from the left, shifted toward the plum
   undertone rather than repeating the hero's pure violet. */
.atmosphere--left::before {
  --atmo-color: rgba(122,63,92,.10);
  --atmo-top: -300px;
  --atmo-left: -300px;
  --atmo-right: auto;
}

/* One quiet transition deeper in the page -- mainly to keep a long white
   stretch from feeling completely flat, not a focal moment. */
.atmosphere--quiet::before {
  --atmo-size: 700px;
  --atmo-color: rgba(92,40,244,.07);
  --atmo-top: -260px;
  --atmo-right: -240px;
}

/* Final CTA -- allowed to be a little more noticeable again at the close,
   entering from below rather than above, plum-leaning. */
.atmosphere--plum::before {
  --atmo-size: 1000px;
  --atmo-blur: 140px;
  --atmo-color: rgba(122,63,92,.15);
  --atmo-bottom: -420px;
  --atmo-left: -220px;
  --atmo-top: auto;
  --atmo-right: auto;
}

.atmosphere > .container { position: relative; z-index: 1; }

@media (max-width: 520px) {
  /* Mobile isn't a naive shrink: single light source per section (drop the
     hero's second field), reduced size/intensity so nothing dominates a
     narrow viewport or muddies text contrast. */
  .hero-bg::after { display: none; }
  .hero-bg::before,
  .atmosphere::before {
    --atmo-size: 520px;
    --atmo-blur: 90px;
  }
}

/* ---------- Snapshot -> paid-service bridge strip ---------- */
/* Deliberately lighter than a card grid (no borders, no shadows, no
   .proof-card/.step-card reuse) -- this is a thin connective moment
   answering "why do I need Revealta after the gap is found," not another
   feature section. */
/* ---------- What We Do -- the core Revealta model (FIND/INVESTIGATE/
   IMPROVE/RE-TEST), promoted to a primary, early homepage section per the
   founder's 2026-08-18 hierarchy correction: this is the actual product,
   not the free Snapshot, and needs to read as one, not as a small
   process footnote. Large mono step index + bold word label, generous
   spacing, a real connecting line rather than a tight card grid --
   deliberately not another .steps-grid/.proof-grid instance. The IMPROVE
   step alone carries the strong violet, the one semantic-purple moment
   in this section, matching the standing "purple = the positive outcome"
   rule. */
.method-flow {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  /* One row or none. At five steps the old 200px column plus wrap left
     "Measure" stranded alone on a second line, which reads as a broken layout
     rather than as a fifth step. Below the breakpoint it becomes a clean
     vertical column instead of wrapping into an uneven grid. */
  flex-wrap: nowrap;
  gap: var(--sp-4) var(--sp-2);
  margin-top: var(--sp-6);
}
.method-step {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  max-width: 170px;
  flex: 1 1 0;
  min-width: 0;
}
/* --- the process deepens as it progresses -----------------------------------
   Discover -> Measure moves from a lighter violet to the full brand colour, so
   the eye is pulled along the sequence and Measure reads as the culmination.

   **Widened 2026-08-31 after looking at the rendered page.** The first attempt
   ran #9482E9 -> #5C28F4, a total contrast range of only x2.16, and on screen the
   last three steps read as one purple while Discover looked merely faded. The
   range is now x3.07 across five even 7.4-point lightness steps, so the
   progression is legible as a sequence rather than as a slight drift.

   **Discover is light but not weak, and that distinction is the whole trick.**
   Lightness is high (74%) while saturation stays at 92%, which is what separates
   "the pale end of a deliberate ramp" from "disabled text". It is never given
   reduced opacity. It sits at exactly 3.00:1 -- the floor for large text, and as
   light as it can go while still looking chosen.

   **Measure is `--violet-dark`, not `--violet-strong`.** Ending on the darker
   brand token buys the depth the previous version lacked: the old ramp topped out
   at 6.85:1 and this one reaches 9.08:1, which is what finally separates 03, 04
   and 05 from each other.

   One custom property per step drives the label, the number and the arrow that
   follows, so the progression is defined once. `nth-of-type` is safe here
   because the arrows between steps are spans and every div in the flow is a
   step. */
.method-step:nth-of-type(1) { --step-violet: #9F81FA; }  /* L 74%  3.00:1 */
.method-step:nth-of-type(2) { --step-violet: #835CF8; }  /* L 67%  4.33:1 */
.method-step:nth-of-type(3) { --step-violet: #6839F6; }  /* L 59%  5.99:1 */
.method-step:nth-of-type(4) { --step-violet: #4E16F3; }  /* L 52%  7.68:1 */
.method-step:nth-of-type(5) { --step-violet: var(--violet-dark); }  /* L 45%  9.08:1 */

.method-step-index {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-sm);
  font-weight: 600;
  /* The numbers take the same progression at low opacity: present enough to
     reinforce the movement, faint enough that they stay chrome rather than
     competing with the labels. */
  color: color-mix(in srgb, var(--step-violet, var(--violet-strong)) 62%, transparent);
  letter-spacing: .04em;
  margin-bottom: var(--sp-1);
}
.method-step-label {
  font-size: var(--fs-xl);
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--step-violet, var(--violet-strong));
  margin-bottom: 0.5rem;
}
.method-step-desc { font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.5; }
/* `--accent` no longer changes anything and is kept only so the existing markup
   stays valid. Singling one step out made it look like the step you were
   currently on, and the gradient now carries the emphasis instead. */
.method-step--accent .method-step-label { color: var(--step-violet, var(--violet-strong)); }

/* Arrows strengthen with the steps, at a much lower weight. They are connective
   tissue: enough tint to carry the eye forward, not enough to become marks in
   their own right. Each arrow takes the colour of the step *before* it, so the
   run reads as leaving one step rather than arriving at the next. */
.method-arrow { color: var(--border-strong); font-size: var(--fs-2xl); flex-shrink: 0; margin-top: 2.6rem; }
.method-step:nth-of-type(1) ~ .method-arrow { color: color-mix(in srgb, #9F81FA 55%, var(--border-strong)); }
.method-step:nth-of-type(2) ~ .method-arrow { color: color-mix(in srgb, #835CF8 65%, var(--border-strong)); }
.method-step:nth-of-type(3) ~ .method-arrow { color: color-mix(in srgb, #6839F6 75%, var(--border-strong)); }
.method-step:nth-of-type(4) ~ .method-arrow { color: color-mix(in srgb, #4E16F3 85%, var(--border-strong)); }
@media (max-width: 900px) {
  .method-flow { flex-direction: column; align-items: center; gap: var(--sp-3); }
  .method-step { max-width: 320px; flex: none; }
  .method-arrow { transform: rotate(90deg); margin-top: 0; }
}
@keyframes heroDriftA { from { transform: translate(0, 0); } to { transform: translate(34px, 44px); } }
@keyframes heroDriftB { from { transform: translate(0, 0); } to { transform: translate(-28px, 32px); } }

/* Hero load-in — staggered fade + rise on page load (not scroll-triggered,
   since this content starts in view). Same easing/restraint as .reveal. */
.hero-anim { opacity: 0; transform: translateY(14px); animation: heroIn var(--dur-slow) var(--ease) forwards; }
.hero .eyebrow.hero-anim { animation-delay: 0ms; }
.hero h1.hero-anim { animation-delay: 90ms; }
.hero .subhead.hero-anim { animation-delay: 180ms; }
.hero .hero-ctas.hero-anim { animation-delay: 270ms; }
.hero .footnote.hero-anim { animation-delay: 350ms; }
@keyframes heroIn { to { opacity: 1; transform: translateY(0); } }

/* ---------- Real example card ---------- */
.example-wrap { max-width: 760px; margin: 0 auto; }
.example-body { padding: var(--sp-4); }
.example-title { font-weight: 700; font-size: var(--fs-lg); margin-bottom: 0.25rem; }
.example-meta { color: var(--text-faint); font-size: var(--fs-sm); margin-bottom: var(--sp-3); }
.pill {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: var(--fs-xs);
  font-weight: 700;
  margin-top: 0.5rem;
}
.pill-weak { background: var(--red-bg); color: var(--red); }
.pill-mixed { background: var(--amber-bg); color: var(--amber); }
.pill-strong { background: var(--green-bg); color: var(--green); }

.finding-callout {
  border-left: 3px solid var(--violet-strong);
  background: var(--lavender-bg);
  padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-4);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: var(--fs-sm);
  color: var(--text);
  margin-top: var(--sp-3);
}
.finding-callout .finding-label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--violet-strong);
  margin-bottom: 0.5rem;
}
.disclosure {
  font-size: var(--fs-xs);
  color: var(--text-faint);
  margin-top: var(--sp-2);
}
.disclosure a { color: var(--violet); text-decoration: none; }

/* ---------- Problem / plain sections ---------- */
.centered-copy { max-width: 640px; margin: 0 auto; text-align: center; }
.centered-copy p { font-size: var(--fs-lg); color: var(--text-muted); margin: var(--sp-2) 0; }

/* ---------- Surface row ---------- */
.surface-row {
  display: flex;
  justify-content: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-top: var(--sp-4);
}
.surface-chip {
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.6rem 1.25rem;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  background: var(--bg-white);
}

/* ---------- How it works ---------- */
.steps-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}
.steps-grid.cols-5 { grid-template-columns: repeat(5, 1fr); }
@media (max-width: 1180px) {
  .steps-grid.cols-5 { grid-template-columns: repeat(3, 1fr); }
}
.step-card {
  padding: var(--sp-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  transition: border-color var(--dur-fast) var(--ease);
}
.step-card:hover { border-color: var(--border-strong); transform: translateY(-2px); box-shadow: var(--shadow-hover); }
.step-num {
  width: 32px; height: 32px;
  border-radius: 999px;
  background: var(--navy);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: var(--fs-sm);
  margin-bottom: var(--sp-2);
  transition: background-color var(--dur-fast) var(--ease);
}
.step-card:hover .step-num { background: var(--violet-strong); }

/* Small on-brand line icons (mask technique, matches .check-list) — used
   sparingly for visual interest without resorting to stock photography,
   which would clash with the evidence-only trust positioning. */
.step-icon {
  width: 20px; height: 20px;
  display: inline-block;
  background: var(--violet);
  margin-left: 0.5rem;
  vertical-align: -4px;
}
.icon-search { -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M15.5 14h-.79l-.28-.27a6.5 6.5 0 1 0-.7.7l.27.28v.79l5 4.99L20.49 19zm-6 0A4.5 4.5 0 1 1 14 9.5 4.5 4.5 0 0 1 9.5 14'/%3E%3C/svg%3E") center/contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M15.5 14h-.79l-.28-.27a6.5 6.5 0 1 0-.7.7l.27.28v.79l5 4.99L20.49 19zm-6 0A4.5 4.5 0 1 1 14 9.5 4.5 4.5 0 0 1 9.5 14'/%3E%3C/svg%3E") center/contain no-repeat; }
.icon-sparkle { -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M12 2l1.8 5.2L19 9l-5.2 1.8L12 16l-1.8-5.2L5 9l5.2-1.8zM19 15l.9 2.6L22.5 18.5l-2.6.9L19 22l-.9-2.6L15.5 18.5l2.6-.9z'/%3E%3C/svg%3E") center/contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M12 2l1.8 5.2L19 9l-5.2 1.8L12 16l-1.8-5.2L5 9l5.2-1.8zM19 15l.9 2.6L22.5 18.5l-2.6.9L19 22l-.9-2.6L15.5 18.5l2.6-.9z'/%3E%3C/svg%3E") center/contain no-repeat; }
.icon-compare { -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M9 3v18l-6-6h6zm6 18V3l6 6h-6z'/%3E%3C/svg%3E") center/contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M9 3v18l-6-6h6zm6 18V3l6 6h-6z'/%3E%3C/svg%3E") center/contain no-repeat; }
.icon-mail { -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M20 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2m0 4-8 5-8-5V6l8 5 8-5z'/%3E%3C/svg%3E") center/contain no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M20 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2m0 4-8 5-8-5V6l8 5 8-5z'/%3E%3C/svg%3E") center/contain no-repeat; }
.step-card h3 { margin-bottom: 0.4rem; font-size: var(--fs-base); }
.step-card p { font-size: var(--fs-sm); color: var(--text-muted); margin: 0; }

/* ---------- Proof cards ---------- */
.proof-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}
.proof-card {
  background: var(--bg-white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-3);
  transition: border-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.proof-card:hover { border-color: var(--border-strong); transform: translateY(-2px); box-shadow: var(--shadow-hover); }
.proof-card .proof-index {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--text-faint);
  font-weight: 600;
  margin-bottom: var(--sp-1);
}
.proof-card .quote {
  font-weight: 600;
  font-size: var(--fs-base);
  color: var(--navy);
  margin-bottom: var(--sp-1);
}
.proof-card p { font-size: var(--fs-sm); color: var(--text-muted); margin: 0 0 var(--sp-2); }

/* ---------- Two column explainer (.cols-3 modifier for a 3-up layout, e.g.
   Google Search / Google Maps / AI Recommendations) ---------- */
.explainer-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-4);
  margin-top: var(--sp-4);
}
.explainer-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.explainer-card {
  background: var(--bg-white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-4);
  transition: border-color var(--dur-fast) var(--ease);
}
.explainer-card:hover { border-color: var(--border-strong); }
.explainer-card h3 { margin-bottom: var(--sp-2); }
.explainer-card p { color: var(--text-muted); font-size: var(--fs-base); margin: 0; }

/* ---------- Lists ---------- */
.check-list { list-style: none; padding: 0; margin: var(--sp-3) 0; }
.check-list li {
  padding-left: 1.75rem;
  position: relative;
  margin-bottom: var(--sp-2);
  font-size: var(--fs-base);
  color: var(--text);
}
.check-list li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.35rem;
  width: 18px; height: 18px;
  border-radius: 4px;
  background: var(--violet);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M9 16.2l-3.5-3.5-1.4 1.4L9 19 20 8l-1.4-1.4z'/%3E%3C/svg%3E") center/contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='black' d='M9 16.2l-3.5-3.5-1.4 1.4L9 19 20 8l-1.4-1.4z'/%3E%3C/svg%3E") center/contain no-repeat;
}
.footnote { font-size: var(--fs-xs); color: var(--text-faint); margin-top: var(--sp-2); }

/* ---------- CTA band ---------- */
.cta-band { text-align: center; }
.cta-band .container { max-width: 620px; }
.cta-band p { color: var(--text-muted); margin: var(--sp-2) 0 var(--sp-4); }

/* ---------- FAQ ---------- */
.faq-item { border-bottom: 1px solid var(--border); }
.faq-q {
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: var(--sp-3) 0;
  font-size: var(--fs-base);
  font-weight: 600;
  color: var(--navy);
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  min-height: 44px;
}
.faq-q .chev { transition: transform 150ms ease; color: var(--text-faint); font-size: var(--fs-lg); }
.faq-item.open .faq-q .chev { transform: rotate(45deg); }
.faq-a {
  max-height: 0;
  overflow: hidden;
  transition: max-height 200ms ease;
  color: var(--text-muted);
  font-size: var(--fs-sm);
}
.faq-item.open .faq-a { max-height: 240px; }
.faq-a p { margin: 0 0 var(--sp-3); }

/* ---------- Footer ---------- */
.site-footer {
  border-top: 1px solid var(--border);
  padding: var(--sp-6) 0;
  color: var(--text-faint);
  font-size: var(--fs-xs);
}
.site-footer .container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

/* ---------- Tap targets and focus, measured rather than assumed ---------- */

/* Measured on the running preview at 375 CSS pixels, 2026-09-12. Twelve links
   per page rendered between 17 and 31 pixels tall. WCAG 2.5.8 asks for 24 by 24
   and touch guidance asks for roughly 44, and the two most expensive misses were
   both conversion links rather than footer furniture: "Request a consultation"
   at 17 pixels and "Prefer to speak first?" at 25.

   This changes hit area only. No font size, no colour, no copy, no layout that a
   sighted visitor would notice: the page looks the same and a thumb stops
   missing it. */
@media (max-width: 767px) {
  .site-footer nav a,
  .site-footer .container > a,
  .brand-mark,
  .offer-alt a,
  .wwu-alt a,
  a.cta-quiet {
    display: inline-block;
    min-height: 44px;
    padding-block: 0.75rem;
    line-height: 1.25;
  }
  /* The footer separators are text nodes between these links. Tightening the
     row keeps the middots beside their links instead of stranding them. */
  .site-footer nav { line-height: 1.1; }

  /* **Links inside a sentence are deliberately left alone.** WCAG 2.5.8 exempts
     targets in a block of text, and it is right to: "You can run a free
     Visibility Snapshot first, or tell us about your business" reads as one
     sentence offering two paths, and giving each link a 44 pixel box would break
     the sentence apart to satisfy a rule that does not apply to it. The links
     enlarged above are the ones that stand alone and act as buttons. */
}

/* An explicit focus ring for links and buttons.

   The form controls already had one (`--focus-ring`). Links and buttons did not,
   so they fell back to whatever ring the browser draws, which is a different
   shape and colour in every browser and is close to invisible against the violet
   buttons. `:focus-visible` rather than `:focus`, so a mouse click does not leave
   a ring behind and a keyboard user never loses their place. */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
[role="button"]:focus-visible {
  outline: 2px solid var(--violet-strong);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- Checker flow ---------- */
.checker-shell {
  max-width: 560px;
  margin: 0 auto;
  padding: var(--sp-8) 0 var(--sp-16);
}
.checker-progress {
  display: flex;
  gap: 0.4rem;
  margin-bottom: var(--sp-4);
}
.checker-progress .dot {
  height: 4px;
  flex: 1;
  border-radius: 999px;
  background: var(--border);
}
.checker-progress .dot.active { background: var(--violet-strong); }
.checker-progress .dot.done { background: var(--navy); }

.checker-card {
  background: var(--bg-white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-4);
}
.checker-step { display: none; }
.checker-step.active { display: block; animation: fadeIn 220ms ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }

.field { margin-bottom: var(--sp-3); }
.field label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  margin-bottom: 0.4rem;
}
.field input, .field select {
  width: 100%;
  font-size: var(--fs-base);
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-white);
  color: var(--text);
  font-family: inherit;
  min-height: 44px;
}
.field input:focus, .field select:focus {
  outline: none;
  border-color: var(--violet-strong);
  box-shadow: var(--focus-ring);
}
.field .hint { font-size: var(--fs-xs); color: var(--text-faint); margin-top: 0.3rem; }
.field .error { font-size: var(--fs-xs); color: var(--red); margin-top: 0.3rem; display: none; }
.field.invalid input { border-color: var(--red); }
.field.invalid .error { display: block; }

.step-actions { display: flex; justify-content: space-between; align-items: center; margin-top: var(--sp-4); gap: var(--sp-2); }
.step-actions .btn-text { order: -1; }

.query-preview-intro { font-size: var(--fs-sm); color: var(--text-muted); margin-bottom: var(--sp-3); }
.query-list { list-style: none; padding: 0; margin: 0 0 var(--sp-2); }
.query-list li {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.7rem 1rem;
  margin-bottom: 0.6rem;
  font-size: var(--fs-sm);
  font-family: var(--font-mono);
  color: var(--navy);
  opacity: 0;
  transform: translateY(6px);
  animation: queryIn 320ms ease forwards;
}
@keyframes queryIn { to { opacity: 1; transform: translateY(0); } }
.query-list li.ai-style { font-family: inherit; font-style: italic; color: var(--text-muted); }
.query-note { font-size: var(--fs-xs); color: var(--text-faint); margin-top: var(--sp-2); }

.confirmation { text-align: center; padding: var(--sp-6) 0; }
.confirmation .icon {
  width: 56px; height: 56px; border-radius: 999px;
  background: var(--green-bg); color: var(--green);
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto var(--sp-3);
  font-size: var(--fs-xl);
}
.confirmation h2 { margin-bottom: var(--sp-2); }
.confirmation p { color: var(--text-muted); max-width: 420px; margin: 0 auto var(--sp-2); }

/* ---------- Results / Snapshot page ---------- */
.demo-banner {
  background: var(--amber-bg);
  border-bottom: 1px solid var(--border-strong);
  color: var(--amber);
  text-align: center;
  padding: 0.75rem var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: 600;
}
.demo-banner strong { text-transform: uppercase; letter-spacing: .04em; margin-right: 0.4rem; }

.snapshot-header { padding: var(--sp-6) 0 var(--sp-3); }
.snapshot-header .prepared-for { font-size: var(--fs-sm); color: var(--text-faint); margin-bottom: var(--sp-1); }
.snapshot-header h1 { font-size: var(--fs-2xl); margin-bottom: var(--sp-1); }
.snapshot-meta { font-size: var(--fs-sm); color: var(--text-faint); }
.snapshot-headline {
  font-size: var(--fs-xl);
  font-weight: 600;
  color: var(--navy);
  line-height: 1.4;
  max-width: 760px;
  margin: var(--sp-3) 0;
}

/* Revealta report system -- the one shared "intelligence report" card
   pattern used identically on the homepage's real example and on every
   actual customer Snapshot page. A visitor's own Snapshot literally looks
   like this, not a marketing mockup of it. */
.at-a-glance { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-3); margin: var(--sp-3) 0 var(--sp-4); }
.glance-card {
  border: 1px solid var(--border);
  border-top: 2px solid var(--violet-strong);
  border-radius: var(--radius);
  padding: var(--sp-3);
  background: var(--bg-white);
  transition: box-shadow var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.glance-card:hover { box-shadow: var(--shadow-hover); transform: translateY(-2px); }
.glance-card .label { font-family: var(--font-mono); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .04em; color: var(--text-faint); font-weight: 600; margin-bottom: .5rem; }
.glance-card .value { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--fs-3xl); font-weight: 700; color: var(--navy); line-height: 1; margin-bottom: .35rem; }
.glance-card .desc { font-size: var(--fs-sm); color: var(--text-muted); }

table.compare-table { width: 100%; border-collapse: collapse; margin: var(--sp-2) 0 var(--sp-4); font-size: var(--fs-sm); }
table.compare-table th {
  text-align: left; padding: 0.6rem 0.75rem; border-bottom: 2px solid var(--border-strong);
  color: var(--text-faint); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .03em;
}
table.compare-table td { padding: 0.65rem 0.75rem; border-bottom: 1px solid var(--border); vertical-align: top; }
table.compare-table tr:last-child td { border-bottom: none; }
.badge-yes { color: var(--green); font-weight: 700; }
.badge-no { color: var(--red); font-weight: 700; }

.overflow-x { overflow-x: auto; }

.snapshot-footer-cta {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--sp-4);
  text-align: center;
  margin: var(--sp-4) 0;
}
.snapshot-footer-cta p { color: var(--text-muted); margin: 0 0 var(--sp-3); }

.methodology-note {
  font-size: var(--fs-xs);
  color: var(--text-faint);
  border-top: 1px solid var(--border);
  padding-top: var(--sp-3);
  margin-top: var(--sp-4);
}

/* ---------- Scroll reveal (js/motion.js toggles .is-visible) ---------- */
.reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}
.reveal.is-visible { opacity: 1; transform: translateY(0); }

/* ---------- Ratio bar (data visualization for Snapshot metrics) ---------- */
.ratio-bar-track {
  height: 6px;
  background: var(--border);
  border-radius: 999px;
  overflow: hidden;
  margin-top: 0.6rem;
}
.ratio-bar-fill {
  height: 100%;
  background: var(--navy);
  border-radius: 999px;
  width: 0;
  transition: width 900ms var(--ease);
}
.ratio-bar-fill.positive { background: var(--green); }
.ratio-bar-fill.caution { background: var(--amber); }

/* Data/metadata typeface -- applied to Snapshot metric values, labels,
   dates, and query text sitewide, paired with the system sans everywhere
   else. Numbers become part of the visual identity rather than just large
   bold sans text. */
.data-mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ---------- Query result rows (replaces plain table styling) ---------- */
table.compare-table.query-rows { border: none; }
table.compare-table.query-rows td { border-bottom: 1px solid var(--border); padding: 0.85rem 0.25rem; transition: background-color var(--dur-fast) var(--ease); }
table.compare-table.query-rows tr:last-child td { border-bottom: none; }
table.compare-table.query-rows tr:hover td { background-color: var(--bg); }
.result-badge { display: inline-flex; align-items: center; gap: 0.45rem; font-size: var(--fs-xs); font-weight: 600; white-space: nowrap; transition: color var(--dur-fast) var(--ease); }
.result-badge .dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease); }
.result-badge.yes { color: var(--green); }
.result-badge.yes .dot { background: var(--green); }
.result-badge.no { color: var(--text-faint); font-weight: 500; }
.result-badge.no .dot { background: transparent; border: 1.5px solid var(--border-strong); }
/* On row hover, a missed search draws slightly more attention -- an honest
   emphasis of data that's already there (this search was missed), not a
   fabricated "here's who captured it" claim per query, since that
   attribution isn't data the audit actually captures per-query today. */
tr:hover .result-badge.no { color: var(--red); }
tr:hover .result-badge.no .dot { background: var(--red); border-color: var(--red); }

/* ---------- Product-visual mockup frame (homepage) ---------- */
.product-visual {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-white);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.product-visual .pv-bar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.7rem var(--sp-3);
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.product-visual .pv-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--border-strong); }

/* ---------- Discovery demonstration -- the homepage's signature moment.
   Deliberately NOT a fake Google/ChatGPT screenshot -- a restrained,
   Revealta-native interpretation of "one search, two discovery
   environments." Reveal timing reuses the existing motion.js .reveal /
   .is-visible observer -- no new JS, just CSS keyed off the class it
   already toggles, staggering each row so the story unfolds in order:
   query -> results appear -> competitors visible -> your business missing
   -> Revealta names the gap. ---------- */
.demo-query {
  max-width: 480px;
  margin: 0 auto var(--sp-4);
  text-align: center;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--bg-white);
  box-shadow: var(--shadow-card);
}
.demo-query-label {
  display: block;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--text-faint);
  font-weight: 600;
  margin-bottom: 0.2rem;
}
.demo-query-text { font-family: var(--font-mono); font-size: var(--fs-base); color: var(--navy); }

.demo-panels {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
  max-width: 880px;
  margin: 0 auto;
}
.demo-panel {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-white);
  padding: var(--sp-3);
}
.demo-panel-label {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--violet);
  font-weight: 600;
  margin-bottom: var(--sp-2);
}
.demo-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-2);
  padding: 0.65rem 0.75rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  margin-bottom: 0.5rem;
  opacity: 0;
  transform: translateY(8px);
}
.demo-panels.is-visible .demo-row { animation: demoRowIn 500ms var(--ease) forwards; }
.demo-panels.is-visible .demo-row:nth-child(1) { animation-delay: 100ms; }
.demo-panels.is-visible .demo-row:nth-child(2) { animation-delay: 250ms; }
.demo-panels.is-visible .demo-row:nth-child(3) { animation-delay: 450ms; }
@keyframes demoRowIn { to { opacity: 1; transform: translateY(0); } }
.demo-row-name { font-size: var(--fs-sm); font-weight: 600; color: var(--text); }
.demo-row-tag { font-family: var(--font-mono); font-size: var(--fs-xs); font-weight: 600; text-transform: uppercase; letter-spacing: .03em; }
.demo-row--present { background: var(--bg); }
.demo-row--present .demo-row-tag { color: var(--green); }
.demo-row--missing { border-style: dashed; border-color: var(--border-strong); }
.demo-row--missing .demo-row-name { color: var(--text-faint); }
.demo-row--missing .demo-row-tag { color: var(--red); }
.demo-ai-answer {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  background: var(--bg);
  border-radius: var(--radius-sm);
  padding: var(--sp-2) 0.75rem;
  margin-bottom: var(--sp-2);
}
.demo-ai-answer strong { color: var(--text); }

.demo-reveal {
  max-width: 640px;
  margin: var(--sp-4) auto 0;
  text-align: center;
  border-top: 1px solid var(--border);
  padding-top: var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.demo-reveal .finding-label { justify-content: center; display: flex; }

/* ---------- Responsive: desktop (default) / laptop / tablet / mobile ---------- */

/* Laptop — slightly reduce the hero's desktop-scale grandeur before it needs to wrap */
@media (max-width: 1180px) {
  :root { --fs-4xl: 3.75rem; }
}

/* Tablet */
@media (max-width: 860px) {
  :root { --fs-4xl: 3rem; }
  .steps-grid, .proof-grid, .explainer-grid, .at-a-glance, .demo-panels, .steps-grid.cols-5, .explainer-grid.cols-3 { grid-template-columns: 1fr; }
  .hero { padding: var(--sp-8) 0 var(--sp-6); }
  section { padding: var(--sp-8) 0; }
  .nav-links { gap: var(--sp-2); }
  .nav-links .btn { padding: 0.6rem 0.9rem; font-size: var(--fs-xs); }
}

/* Mobile */
/* Collapse the text links before they can crowd, not after they have wrapped. */
@media (max-width: 700px) {
  .nav-links a:not(.btn) { display: none; }
}

@media (max-width: 520px) {
  :root { --fs-4xl: 2.5rem; --fs-2xl: 1.6rem; }
  .site-footer .container { flex-direction: column; align-items: flex-start; }
  .hero-ctas { flex-direction: column; align-items: stretch; }
  .hero-ctas .btn { width: 100%; }
  .product-visual .example-body { padding: var(--sp-3); }
}

/* Available to screen readers and crawlers, invisible on screen. Added 2026-08-21
   for check.html, which had four h2 headings and no h1 at all: a page whose subject
   no machine can state. The visible design is deliberately unchanged -- the form's
   step headings are the right visual hierarchy, they just were not anchored to
   anything. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   PARTNERS PAGE
   Added 2026-08-23. Uses only existing tokens -- no new colours,
   no new type scale -- so the page reads as the same product.
   ============================================================ */

.calc-shell {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: var(--sp-4);
  align-items: start;
  margin-top: var(--sp-4);
  padding: var(--sp-4);
  background: var(--bg-white);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
}

.calc-field { margin-bottom: var(--sp-3); }
.calc-field:last-child { margin-bottom: 0; }

.calc-field label {
  display: block;
  font-size: var(--fs-sm);
  color: var(--text-muted);
  margin-bottom: var(--sp-1);
}

.calc-field input[type="range"] {
  width: 100%;
  accent-color: var(--violet-strong);
  height: 1.5rem;
}

.calc-field input[type="range"]:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: 6px;
}

/* The slider is the one thing on this page a visitor actually manipulates, and on
   a phone it measured 24px tall against the ~44px a thumb needs. Grown on coarse
   pointers only, so the desktop proportions are untouched: the track keeps its
   height, the hit area around it does not. */
@media (pointer: coarse) {
  .calc-field input[type="range"] {
    height: 2.75rem;
  }
}

.calc-output {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-lg);
  color: var(--text);
  font-weight: 600;
}

.calc-results {
  border-left: 1px solid var(--border);
  padding-left: var(--sp-4);
}

.calc-line {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-2);
  padding: var(--sp-1) 0;
}

.calc-line--total {
  border-top: 1px solid var(--border-strong);
  margin-top: var(--sp-1);
  padding-top: var(--sp-2);
}

.calc-label { font-size: var(--fs-sm); color: var(--text-muted); }

.calc-amount {
  font-family: var(--font-mono);
  font-size: var(--fs-lg);
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.calc-line--total .calc-amount {
  font-size: var(--fs-2xl);
  color: var(--violet-strong);
}

.calc-note {
  font-size: var(--fs-xs);
  color: var(--text-faint);
  margin-top: var(--sp-2);
  min-height: 2.4em;
}

.partner-form {
  max-width: 34rem;
  margin: var(--sp-4) auto 0;
  padding: var(--sp-4);
  background: var(--bg-white);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-card);
}

.partner-form .field { margin-bottom: var(--sp-3); }

.partner-form label {
  display: block;
  font-size: var(--fs-sm);
  color: var(--text-muted);
  margin-bottom: var(--sp-1);
}

.partner-form input,
.partner-form select,
.partner-form textarea {
  width: 100%;
  padding: 0.7rem 0.85rem;
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--text);
  background: var(--bg-white);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
}

.partner-form textarea { resize: vertical; }

.partner-form input:focus-visible,
.partner-form select:focus-visible,
.partner-form textarea:focus-visible {
  outline: none;
  border-color: var(--violet-strong);
  box-shadow: var(--focus-ring);
}

@media (max-width: 760px) {
  .calc-shell { grid-template-columns: 1fr; }
  .calc-results {
    border-left: none;
    border-top: 1px solid var(--border);
    padding-left: 0;
    padding-top: var(--sp-3);
  }
}

/* ==========================================================================
   /partners refinements, 2026-08-25
   ========================================================================== */

/* Three partner paths, three equal columns. The default `explainer-grid` is two
   across, which left Service Partner alone on a second row and made it read as an
   afterthought when the three are meant to be equally intentional. */
.explainer-grid--three { grid-template-columns: repeat(3, 1fr); }

@media (max-width: 980px) {
  .explainer-grid--three { grid-template-columns: 1fr; }
}

/* The Sales Partner progression. It is the strongest thing we can say to a good
   independent seller and it was a clause at the end of a paragraph. Set apart,
   but quietly: a coloured box would read as a promise, and access is earned. */
.path-progression {
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  /* --border, not --line: --line is not a token, and an unresolvable
     custom property voids the entire declaration, so this separator
     simply did not render. */
  border-top: 1px solid var(--border);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.path-progression strong { color: var(--text); display: block; margin-bottom: .35rem; }

/* The residual card carries the one number a partner will do arithmetic on. */
.step-card--residual { border-color: rgba(92, 40, 244, .22); }

/* Secondary calculator line: residual over the capped 12 months. Visually
   subordinate to "that month", because it is a projection and the month is not. */
.calc-line--secondary {
  /* --border, not --line: --line is not a token, and an unresolvable
     custom property voids the entire declaration, so this separator
     simply did not render. */
  border-top: 1px dashed var(--border);
  margin-top: var(--sp-2);
  padding-top: var(--sp-2);
}
.calc-amount--secondary { color: var(--violet); font-weight: 600; }
.calc-note--quiet { color: var(--text-muted); font-size: var(--fs-xs, .8rem); }

/* Trust: six protections that must all stay, in less vertical space. Tightened
   by reducing the card padding and copy size rather than by cutting protections,
   which is the one thing this section cannot afford to lose. */
#trust .explainer-grid { grid-template-columns: repeat(3, 1fr); gap: var(--sp-3); }
#trust .explainer-card { padding: var(--sp-3); }
#trust .explainer-card h3 { font-size: var(--fs-base); margin-bottom: .4rem; }
#trust .explainer-card p { font-size: var(--fs-sm); color: var(--text-muted); }

/* Six cards divide evenly by two, so a tablet gets three tidy rows rather than
   six full-width blocks. The three partner paths deliberately do NOT do this:
   two columns would leave one alone on a second row, which is the orphan the
   three-column layout exists to avoid. */
@media (max-width: 980px) {
  #trust .explainer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 640px) {
  #trust .explainer-grid { grid-template-columns: 1fr; }
}

/* Referral: one intentional callout instead of a full section of whitespace for
   four lines of information. */
.referral-callout {
  position: relative;
  overflow: hidden;
  border-radius: 20px;
  border: 1px solid rgba(92, 40, 244, .16);
  background: linear-gradient(180deg, #FFFFFF 0%, var(--lavender-bg) 100%);
  /* --sp-5 does not exist in the token set. It was used here, which made the
     whole declaration invalid and dropped, so this callout rendered with no
     padding at all and the text sat against the border. */
  padding: var(--sp-6) var(--sp-4);
  text-align: center;
}
.referral-callout__glow {
  position: absolute;
  width: 620px; height: 620px;
  top: -380px; right: -220px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(122, 63, 92, .16) 0%, rgba(122, 63, 92, 0) 70%);
  filter: blur(90px);
  pointer-events: none;
}
.referral-callout__body { position: relative; z-index: 1; }
.referral-callout h2 { margin-bottom: var(--sp-2); }
/* The proposition itself, lifted out of the paragraph that used to bury it at
   the end of a sentence. Sits below the heading and above the explanation, so
   the order a reader takes it in is: what is this, what do I get, how does it
   work, what are the rules. */
.referral-offer {
  font-size: var(--fs-xl);
  font-weight: 600;
  color: var(--text);
  margin: 0 auto var(--sp-1);
  letter-spacing: -.01em;
}
/* Explanation, not proposition. Stepped down from fs-lg once the euro figures
   moved above it: two consecutive large lines would have flattened the order
   they are meant to be read in. The rules line below supplies its own top
   margin, so this one ends at zero. */
.referral-lead {
  font-size: var(--fs-base);
  color: var(--text-muted);
  max-width: 32rem;
  margin: 0 auto;
}
/* The referral rules are policy, not proposition.
   They were four pills, which gave secondary information the visual weight of a
   feature list and made it compete with "You get EUR 150. They get EUR 150."
   Now one hairline-separated line, subordinate by size, weight and colour, with
   no background, border or badge of its own. */
.referral-rules {
  list-style: none;
  padding: 0;
  margin: var(--sp-3) auto 0;
  max-width: 56rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  column-gap: 1.5rem;
  row-gap: .5rem;
  font-size: var(--fs-xs);
  line-height: 1.55;
  color: var(--text-faint);
  letter-spacing: .012em;
}
.referral-rules li { position: relative; }

/* Separators live inside the column gap, so they never crowd the text and need
   no box of their own. Violet rather than plum: --plum is atmospheric-only in
   this system and never a border.

   They are suppressed below the width where the line wraps. A separator
   orphaned at the start of a wrapped row reads as a mistake, and no CSS rule
   can tell that an item begins a row -- so below that width each rule takes its
   own centred line instead, which needs no separator to stay unambiguous. */
@media (min-width: 981px) {
  .referral-rules li + li::before {
    content: "";
    position: absolute;
    left: -.75rem;
    top: .22em;
    bottom: .1em;
    width: 1px;
    background: rgba(92, 40, 244, .22);
  }
}
@media (max-width: 980px) {
  .referral-rules {
    flex-direction: column;
    column-gap: 0;
    row-gap: .45rem;
  }
}

/* Help text under the adaptive application questions. */
.field-help {
  margin-top: .4rem;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

/* One quiet sentence under the trust heading. It is the only place on the page
   that says a partner has actually agreed to anything, so it belongs here
   rather than in a card -- a card would make it a feature, and it is a fact. */
.trust-standards-note {
  text-align: center;
  max-width: 34rem;
  margin: var(--sp-2) auto 0;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

/* =========================================================================
   Compression + second conversion path, 2026-08-27.

   Two additions, and the first is a constraint rather than a feature: the
   homepage had 13 sections and three of them stated the problem in different
   wording. `.discovery` is one sticky stage that moves through those three
   ideas instead of stacking them, so the page gets shorter while the
   explanation gets stronger.

   `.nav-cta` is the high-intent action. Deliberately NOT a second button --
   two equally loud CTAs in one header is the thing the brief rules out.
   ========================================================================= */

/* ---------- Nav: the restrained high-intent action ---------- */
.nav-cta {
  color: var(--navy) !important;
  font-weight: 600 !important;
  white-space: nowrap;
}
.nav-cta span {
  color: var(--violet-strong);
  transition: transform var(--dur-fast) var(--ease);
  display: inline-block;
}
.nav-cta:hover span { transform: translateX(3px); }

/* ---------- Work with Revealta ---------- */
.wwu-shell { padding: var(--sp-8) 0 var(--sp-12); }
.wwu-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: var(--sp-8); align-items: start;
}
.wwu-intro h1 { font-size: var(--fs-3xl); line-height: 1.1; margin: .4rem 0 var(--sp-2); }
.wwu-intro .subhead { margin-bottom: var(--sp-4); }
.wwu-points { list-style: none; padding: 0; margin: 0 0 var(--sp-4); }
.wwu-points li {
  font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.6;
  padding-left: var(--sp-3); border-left: 1px solid var(--border-strong);
  margin-bottom: var(--sp-3);
}
.wwu-point-title { display: block; color: var(--text); font-weight: 600; margin-bottom: .2rem; }
.wwu-alt { margin: 0; }
.wwu-alt a { color: var(--violet-strong); font-weight: 600; }

.wwu-form-card {
  background: var(--bg-white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: var(--sp-4);
}
.wwu-form-card textarea {
  width: 100%; padding: .8rem 1rem; font: inherit; font-size: var(--fs-sm);
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--bg-white); color: var(--text); resize: vertical;
}
.wwu-form-card textarea:focus {
  outline: none; border-color: var(--violet-strong); box-shadow: var(--focus-ring);
}
.field-optional {
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--text-faint);
  font-weight: 400; text-transform: none; letter-spacing: 0; margin-left: .35rem;
}
.wwu-submit { width: 100%; margin-top: var(--sp-1); }
.wwu-privacy { text-align: center; margin: var(--sp-2) 0 0; }
.form-error {
  font-size: var(--fs-sm); color: var(--red); background: var(--red-bg);
  border: 1px solid rgba(162,59,51,.25); border-radius: var(--radius-sm);
  padding: .7rem 1rem; margin: 0 0 var(--sp-2);
}
/* Honeypot: off-screen rather than display:none, which some bots skip. */
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.wwu-success { text-align: center; padding: var(--sp-4) var(--sp-2); }
.wwu-success h2 { font-size: var(--fs-xl); margin-bottom: var(--sp-2); }
.wwu-success p { color: var(--text-muted); font-size: var(--fs-sm); line-height: 1.65; }
.wwu-success-mark {
  width: 46px; height: 46px; border-radius: 50%; margin: 0 auto var(--sp-3);
  border: 1.5px solid var(--violet-strong); position: relative;
}
.wwu-success-mark::after {
  content: ""; position: absolute; left: 15px; top: 11px;
  width: 11px; height: 19px; border: solid var(--violet-strong);
  border-width: 0 1.5px 1.5px 0; transform: rotate(45deg);
}

@media (max-width: 860px) {
  .wwu-grid { grid-template-columns: 1fr; gap: var(--sp-6); }
  .wwu-intro h1 { font-size: var(--fs-2xl); }
}

/* ---------- Final conversion band: two paths, one clearly primary ---------- */
.cta-choice {
  display: flex; gap: var(--sp-3); justify-content: center;
  align-items: center; flex-wrap: wrap; margin-top: var(--sp-3);
}
.cta-quiet {
  color: inherit; text-decoration: none; font-size: var(--fs-sm);
  font-weight: 500; opacity: .82; border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
}
.cta-quiet:hover { opacity: 1; }

/* ---------- Free vs paid, as a progression --------------------------------
   Two cards of deliberately unequal weight, with a transition between them.

   **The asymmetry is the argument.** The previous version was a symmetrical
   two-column grid, which made the paid engagement read as a longer version of
   the free Snapshot rather than a different kind of thing. The free card is
   therefore lighter than the surrounding page and the paid card is heavier:
   no shadow versus a shadow, muted background versus white, smaller type versus
   larger, a flat list versus a numbered sequence.

   The four scope areas survive as chips. They are what we look at, not what a
   customer buys, and leading with them was what made the engagement look like an
   audit. */
.offer-flow {
  display: grid;
  grid-template-columns: 1fr auto 1.15fr;   /* the paid card is wider on purpose */
  gap: var(--sp-4);
  /* **Top-aligned, not centred.** Centring floated the shorter free card 161px
     down the page against an 831px paid card, which read as a rendering gap
     rather than as a deliberate difference. Aligned at the top the two eyebrows
     line up, the comparison is legible immediately, and the paid card simply
     extends further down -- which is the asymmetry saying what it is meant to
     say without any dead space above the free card. */
  align-items: start;
  max-width: 1000px;
  margin: 0 auto;
}

.offer-card { border-radius: var(--radius); padding: var(--sp-4); }

/* Entry product: quiet. It should look like the start of something rather than
   a lesser version of the thing beside it. */
.offer-card--free {
  background: var(--lavender-bg);
  border: 1px solid var(--border);
}

/* The engagement: the page's normal card treatment, which next to the muted
   free card reads as elevated without needing decoration. */
.offer-card--paid {
  background: var(--bg-white);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-card);
  padding: var(--sp-5);
}

.offer-eyebrow {
  font-family: var(--font-mono); font-size: var(--fs-xs);
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--text-faint); margin-bottom: .5rem;
}
.offer-eyebrow--paid { color: var(--violet-strong); }

.offer-title {
  font-size: var(--fs-lg); font-weight: 700; letter-spacing: -0.015em;
  margin: 0 0 var(--sp-3); color: var(--text);
}
.offer-title--paid { font-size: var(--fs-xl); }

.offer-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.offer-list li {
  position: relative; padding-left: 1.25rem;
  font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.55;
}
.offer-list li::before {
  content: "\2713"; position: absolute; left: 0; top: 0;
  color: var(--violet); font-weight: 700;
}

/* The sequence is numbered because the order is the product: you cannot improve
   before investigating, and you cannot claim a result before re-measuring. */
.offer-steps { list-style: none; margin: 0 0 var(--sp-4); padding: 0; counter-reset: step; }
.offer-steps li {
  counter-increment: step; position: relative;
  padding-left: 2.1rem; padding-bottom: var(--sp-3);
}
.offer-steps li:last-child { padding-bottom: 0; }
.offer-steps li::before {
  content: counter(step); position: absolute; left: 0; top: -1px;
  width: 1.45rem; height: 1.45rem; border-radius: 50%;
  background: var(--violet-strong); color: #fff;
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}
/* A hairline joining the steps, so it reads as a sequence rather than four
   separate claims. */
.offer-steps li:not(:last-child)::after {
  content: ""; position: absolute; left: .7rem; top: 1.6rem; bottom: .35rem;
  width: 1px; background: var(--border-strong);
}
.offer-step-name {
  display: block; font-size: var(--fs-base); font-weight: 700;
  color: var(--text); margin-bottom: .1rem;
}
.offer-step-desc {
  display: block; font-size: var(--fs-sm); color: var(--text-muted); line-height: 1.55;
}

.offer-chips-label {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--text-faint); margin: 0 0 .5rem;
}
.offer-chips { list-style: none; display: flex; flex-wrap: wrap; gap: .4rem; margin: 0 0 var(--sp-4); padding: 0; }
.offer-chips li {
  font-size: var(--fs-xs); color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 999px; padding: .25rem .6rem;
  background: var(--bg-white);
}

.offer-foot { margin-top: var(--sp-4); display: flex; flex-direction: column; gap: .7rem; align-items: flex-start; }
.offer-price {
  font-size: var(--fs-xl); font-weight: 700; letter-spacing: -0.02em;
  color: var(--violet-dark); margin: 0;
}
.offer-price span {
  display: block; font-size: var(--fs-sm); font-weight: 400;
  color: var(--text-muted); letter-spacing: 0;
}
.offer-price--free { color: var(--text-muted); font-size: var(--fs-lg); }
.offer-cta { align-self: stretch; text-align: center; }

.offer-bridge {
  display: flex; flex-direction: column; align-items: center; gap: .3rem;
  color: var(--violet-strong); padding: 0 var(--sp-1);
  /* The bridge now sits in the upper-middle of the composition rather than at
     the midpoint of the taller card. It has to connect the two cards where both
     of them actually are: level with the free card's body, not level with the
     bottom half of the engagement card that the free card never reaches. */
  margin-top: 7.5rem;
}
.offer-bridge-text {
  font-family: var(--font-mono); font-size: var(--fs-xs);
  letter-spacing: .06em; text-transform: uppercase; white-space: nowrap;
}
.offer-bridge-arrow { font-size: var(--fs-2xl); line-height: 1; }

.offer-summary {
  max-width: 620px; margin: var(--sp-5) auto 0; text-align: center;
  font-size: var(--fs-base); color: var(--text); line-height: 1.6;
}

@media (max-width: 860px) {
  /* Stacked, and the bridge arrow turns to point down the page so the
     progression still reads in the direction the visitor is travelling. */
  .offer-flow { grid-template-columns: 1fr; gap: var(--sp-3); }
  .offer-bridge { flex-direction: row; gap: .5rem; justify-content: center;
                  padding: var(--sp-1) 0; margin-top: 0; }
  .offer-bridge-arrow { transform: rotate(90deg); font-size: var(--fs-xl); }
  .offer-card--paid { padding: var(--sp-4); }
  .offer-title--paid { font-size: var(--fs-lg); }
}

/* Per-panel label. The sticky stage bar names the current state on desktop, so
   this is redundant there; on mobile every panel is shown at once and each one
   needs to say what it is. */
.stage-panel-label {
  display: none;
  font-family: var(--font-mono); font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: .05em;
  color: var(--violet); margin: 0 0 .7rem; text-align: center;
}
@media (max-width: 900px) {
  .stage-panel-label { display: block; }
  .stage-panel + .stage-panel { margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--border); }
}

/* An extra anchor target on a section that owns more than one old id, so a
   link into either still lands in the right place under the sticky header. */
.anchor-offset {
  display: block; position: relative; top: -90px; visibility: hidden;
}

/* =========================================================================
   PAGE-LEVEL ATMOSPHERE, 2026-08-27.

   The problem it fixes: the homepage read as a stack of separate blocks
   because the background changed per section -- white hero fading to warm,
   warm, white, warm `.bg-light`, white, warm again. Every boundary was a
   visible horizontal seam, and seams make a page feel both modular and
   longer than it is.

   The old `.atmosphere` system is good and stays for the other pages, but it
   cannot solve this: it paints INSIDE a section and sets `overflow: hidden`,
   so by construction every glow stops exactly at a section edge. That is the
   thing being removed.

   So: one white canvas, and one atmosphere layer spanning the whole document
   underneath all of it. The glows are positioned as a percentage of page
   height, which means they cross section boundaries by default rather than by
   exception -- a field can begin behind the discovery stage and fade out
   halfway through the Snapshot, and nothing about the markup has to know.

   Cost: four absolutely-positioned divs painting radial gradients, no blur
   filter and no raster images. Blur on elements this large is genuinely
   expensive and buys nothing here, because a radial-gradient fading to
   transparent is already perfectly smooth.
   ========================================================================= */

body { position: relative; }

.page-atmo {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 100%;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}
/* Everything real sits above the atmosphere. */
.site-header, main, .site-footer { position: relative; z-index: 1; }

.page-atmo span {
  position: absolute;
  display: block;
  border-radius: 50%;
}

/* 1. Hero. The strongest moment, entering from the upper left, centred well
      outside the page so only a diffused edge ever lands on the canvas. */
.page-atmo .a1 {
  top: -18vh; left: -22vw;
  width: 78vw; height: 78vw;
  max-width: 1150px; max-height: 1150px;
  background: radial-gradient(circle, rgba(92,40,244,.15), rgba(92,40,244,0) 68%);
}

/* 2. Enters behind the hero's lower edge and fades out through the discovery
      stage -- deliberately spanning that boundary. */
.page-atmo .a2 {
  top: 6%; right: -26vw;
  width: 70vw; height: 70vw;
  max-width: 1000px; max-height: 1000px;
  background: radial-gradient(circle, rgba(122,63,92,.085), rgba(122,63,92,0) 66%);
}

/* 3. Behind the Snapshot, from the left. The quietest of the four: this is a
      long reading stretch and the content is dense. */
.page-atmo .a3 {
  top: 36%; left: -24vw;
  width: 66vw; height: 66vw;
  max-width: 950px; max-height: 950px;
  background: radial-gradient(circle, rgba(92,40,244,.075), rgba(92,40,244,0) 66%);
}

/* 4. A gentle rise toward the close, so the final CTA carries more Revealta
      atmosphere without becoming a separate purple box bolted onto a white
      page. It starts well before the CTA and continues past it into the FAQ. */
.page-atmo .a4 {
  /* Measured rather than eyeballed. At -14% this sat from 7255px on a 7285px
     page: entirely below the fold of the document, so the final CTA and the FAQ
     -- the two places that should carry the most atmosphere -- got none at all.
     At 2% it spans roughly 5840-7140px, which begins inside the scope section
     and rises through both, so the increase is gradual rather than a box. */
  bottom: 2%; left: 50%;
  transform: translateX(-50%);
  width: 118vw; height: 100vw;
  max-width: 1500px; max-height: 1300px;
  background: radial-gradient(ellipse at center, rgba(122,63,92,.14), rgba(122,63,92,0) 62%);
}

/* 5. The long middle. Measured: without this there is a ~2,000px stretch of
      completely flat white across the process and scope sections, which is
      nearly three screens. Deliberately the faintest field of the five -- the
      job is to stop a long reading stretch feeling empty, not to be noticed. */
.page-atmo .a5 {
  top: 56%; right: -20vw;
  width: 60vw; height: 60vw;
  max-width: 880px; max-height: 880px;
  background: radial-gradient(circle, rgba(92,40,244,.05), rgba(92,40,244,0) 66%);
}

@media (max-width: 900px) {
  /* On a narrow screen a 78vw circle is small in absolute terms and lands as a
     visible blob rather than as atmosphere, so each field is widened relative
     to the viewport and softened. */
  /* Heights switch from vw to vh here. A phone is narrow and the page is much
     taller, so a vw-sized circle that looked generous on desktop becomes a
     small dot floating in a very long page -- measured at 563px tall against a
     10,000px document. Sizing the height against the viewport keeps each field
     proportional to what the reader can actually see at once. */
  .page-atmo .a1 { width: 150vw; height: 95vh; top: -10vh; left: -40vw; }
  .page-atmo .a2 { width: 140vw; height: 85vh; right: -55vw; background: radial-gradient(ellipse at center, rgba(122,63,92,.06), rgba(122,63,92,0) 66%); }
  .page-atmo .a3 { width: 140vw; height: 85vh; left: -55vw; background: radial-gradient(ellipse at center, rgba(92,40,244,.055), rgba(92,40,244,0) 66%); }
  .page-atmo .a5 { width: 130vw; height: 80vh; right: -50vw; max-height: none; }
  .page-atmo .a4 { width: 190vw; height: 120vh; max-height: none; background: radial-gradient(ellipse at center, rgba(122,63,92,.10), rgba(122,63,92,0) 62%); }
}

/* The hero no longer fades into the warm page colour, because there is no warm
   page colour any more. Other pages keep a plain white hero. */
.hero { background: var(--bg-white); }

/* On the homepage the hero must be TRANSPARENT, not white.
   An opaque hero sits above the atmosphere layer and hides the strongest glow
   on the page, which is the one behind it. And `.hero`'s own internal
   `.hero-bg` fields are clipped by its `overflow: hidden`, so they stop dead at
   the hero's bottom edge -- reintroducing the exact seam this system removes.
   The page-level fields cross that boundary instead. */
.home .hero { background: transparent; }
.home .hero-bg { display: none; }

/* `.bg-light` still exists for the other pages. On the continuous canvas it is
   exactly the horizontal band being removed, so the homepage opts out. */
.home .bg-light { background: transparent; }

/* Cards need to hold their own against a continuously white canvas now that no
   section tint separates them. A hairline and a soft shadow do it without
   boxing everything in. */
.home .proof-card,
.home .glance-card,
.home .step-caption,
.home .stage-card,
.home .product-visual {
  background: var(--bg-white);
}
.home .proof-card { border: 1px solid var(--border); box-shadow: var(--shadow-card); }


/* --- discovery stage: no sticky, no spacers, no scroll capture --------------
   The previous version pinned the card and gave the section 130vh of invisible
   spacers, so scrolling felt like resistance. Whatever it was called, that is
   scroll hijacking, and it was the worst interaction on the site.

   The section is now ordinary page flow at its natural height. The three beats
   play on a timer once the card enters the viewport, and the scroll position is
   never read or written. */
.discovery { padding: var(--sp-8) 0; position: relative; }
.discovery-head { text-align: center; max-width: 640px; margin: 0 auto var(--sp-4); }

.stage-card {
  background: var(--bg-white);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  max-width: 820px;
  margin: 0 auto;
}

.stage-bar {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.65rem var(--sp-3);
  border-bottom: 1px solid var(--border);
  background: var(--lavender-bg);
  font-size: var(--fs-xs); color: var(--text-faint);
  font-family: var(--font-mono); letter-spacing: .03em;
}
.stage-bar strong { color: var(--violet); font-weight: 600; letter-spacing: .05em; }
.stage-progress { display: inline-flex; gap: .3rem; margin-left: .4rem; }
.stage-progress i {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--border-strong);
  transition: background-color var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}
.stage-progress i.is-on { background: var(--violet-strong); transform: scale(1.25); }
.stage-bar .stage-live { margin-left: auto; display: inline-flex; align-items: center; gap: .4rem; }
.stage-bar .stage-live i { width: 5px; height: 5px; border-radius: 50%; background: var(--violet-strong); display: inline-block; }

.stage-body { padding: var(--sp-4) var(--sp-4) var(--sp-3); }

/* One sentence, the largest type in the card. The point should land before the
   diagram is read, not after a paragraph. */
.stage-narrative {
  font-size: var(--fs-xl); font-weight: 700; letter-spacing: -0.015em;
  color: var(--text); text-align: center;
  margin: 0 auto var(--sp-3); max-width: 520px; min-height: 2.4em;
  transition: opacity var(--dur-slow) var(--ease);
}

.stage-query {
  display: flex; align-items: center; gap: .6rem;
  border: 1px solid var(--border-strong); border-radius: 999px;
  padding: .55rem 1rem; max-width: 460px; margin: 0 auto var(--sp-4);
  background: var(--bg-white); font-size: var(--fs-sm);
}
.stage-query .q-icon { color: var(--violet); flex: none; line-height: 0; }
.stage-query .q-text { color: var(--text-muted); }
/* The query types itself in once, on the first beat only. A caret that blinks
   forever is a gimmick; one that finishes and stops is a demonstration. */
.viz.is-s1 ~ .stage-query .q-text::after,
.discovery.is-typing .stage-query .q-text::after {
  content: ""; display: inline-block; width: 1px; height: 1em;
  background: var(--violet-strong); margin-left: 2px;
  vertical-align: -0.15em; animation: caret 900ms steps(2) 3;
}
@keyframes caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

/* --- the field ------------------------------------------------------------- */
.viz { position: relative; height: 244px; margin: 0 auto; max-width: 640px; }

.viz-axis {
  position: absolute; left: 0; right: 0; top: 50%;
  height: 1px; background: var(--border-strong);
}
.viz-zone {
  position: absolute; right: 0; text-align: right;
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: .08em; text-transform: uppercase; color: var(--text-faint);
  opacity: 0; transition: opacity var(--dur-slow) var(--ease);
}
.viz-zone--up { top: calc(50% - 1.5rem); }
.viz-zone--down { top: calc(50% + 0.7rem); }
.viz.is-s2 .viz-zone, .viz.is-s3 .viz-zone { opacity: 1; }

/* One sweep, on the beat where Revealta starts looking. Never a loop. */
.viz-scan {
  position: absolute; top: 8%; bottom: 8%; width: 1px; left: 0; opacity: 0;
  background: linear-gradient(180deg, transparent, rgba(92,40,244,.55), transparent);
}
.viz.is-scanning .viz-scan { animation: vizScan 900ms var(--ease) 1; }
@keyframes vizScan {
  0% { opacity: 0; transform: translateX(0); }
  15%, 85% { opacity: 1; }
  100% { opacity: 0; transform: translateX(640px); }
}

.viz-pill {
  position: absolute; transform: translate(-50%, -50%);
  padding: .4rem .8rem; border-radius: 999px;
  font-size: var(--fs-xs); white-space: nowrap; background: var(--bg-white);
  opacity: 0;
  transition: opacity 420ms var(--ease), top 420ms var(--ease);
}
.viz-pill b { color: var(--green); font-weight: 700; margin-left: .25rem; }
.viz-pill--rival {
  border: 1px solid var(--border-strong); color: var(--text-muted);
  top: calc(50% - 42px);
}
/* Rivals surface onto the line rather than appearing on it: they start below and
   rise, which is the whole metaphor in one transition. */
.viz.is-s0 .viz-pill--rival { top: 50%; opacity: 0; }
.viz.is-s1 .viz-pill--rival,
.viz.is-s2 .viz-pill--rival,
.viz.is-s3 .viz-pill--rival { opacity: 1; }
.v-r1 { left: 18%; }
.v-r2 { left: 47%; }
.v-r3 { left: 78%; }
/* Staggered, so three things do not arrive as one block. */
.viz.is-s1 .v-r1 { transition-delay: 0ms; }
.viz.is-s1 .v-r2 { transition-delay: 160ms; }
.viz.is-s1 .v-r3 { transition-delay: 320ms; }

.viz-pill--you {
  border: 1px dashed var(--violet-strong); color: var(--violet-strong);
  font-weight: 600; top: calc(50% + 44px); left: 46%;
  background: rgba(92,40,244,.04);
}
.viz-pill--you em {
  font-style: normal; font-weight: 500; opacity: .8;
  margin-left: .35rem; font-size: 11px;
}
.viz.is-s2 .viz-pill--you, .viz.is-s3 .viz-pill--you { opacity: 1; }

.viz-gap, .viz-gap-mark { opacity: 0; transition: opacity var(--dur-slow) var(--ease); }
.viz.is-s2 .viz-gap, .viz.is-s3 .viz-gap,
.viz.is-s2 .viz-gap-mark, .viz.is-s3 .viz-gap-mark { opacity: 1; }
.viz-gap {
  position: absolute; left: 46%; top: calc(50% + 5px);
  height: 42px; width: 0; border-left: 1px dashed var(--violet-strong);
}
/* Where the business would sit if it surfaced. The distance between this and the
   pill below is the thing an owner cannot normally see. */
.viz-gap-mark {
  position: absolute; left: 46%; top: 50%;
  width: 11px; height: 11px; border-radius: 50%;
  transform: translate(-50%, -50%);
  border: 1.5px dashed var(--violet-strong); background: var(--bg-white);
}

/* Beat three: what Revealta looks at once the gap is found. Signals, not another
   search result. */
.viz-signals {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; justify-content: center; gap: var(--sp-2);
  opacity: 0; transform: translateY(6px);
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease);
}
.viz.is-s3 .viz-signals { opacity: 1; transform: translateY(0); }
.viz-signals span {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .04em;
  color: var(--violet); border: 1px solid rgba(92,40,244,.28);
  background: rgba(92,40,244,.04); border-radius: 999px; padding: .3rem .7rem;
}

.stage-finding {
  text-align: center; font-size: var(--fs-sm); color: var(--text-muted);
  margin: var(--sp-3) auto 0; max-width: 520px; min-height: 2.6em;
  transition: opacity var(--dur-slow) var(--ease);
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

@media (max-width: 900px) {
  .stage-body { padding: var(--sp-3) var(--sp-2); }
  .stage-narrative { font-size: var(--fs-lg); min-height: 3.2em; }
  .viz { height: 236px; }
  .viz-pill { font-size: 11px; padding: .3rem .6rem; }
  .viz-pill--you em { display: none; }
  .v-r1 { left: 22%; } .v-r2 { left: 50%; } .v-r3 { left: 78%; }
  .viz-signals { gap: .35rem; }
  .viz-signals span { font-size: 9px; padding: .25rem .5rem; }
  .stage-query { max-width: none; }
}

@media (prefers-reduced-motion: reduce) {
  /* No animation at all: the card renders on the beat that carries the point,
     and the three beats are still in the DOM as text. */
  .viz-pill, .viz-zone, .viz-gap, .viz-gap-mark, .viz-signals,
  .stage-narrative, .stage-finding { transition: none; }
  .viz.is-scanning .viz-scan { animation: none; }
  .stage-query .q-text::after { animation: none; content: none; }
}


/* --- instant visibility check ----------------------------------------------
   The first thing on /check. Where we already hold fresh evidence this returns a
   real result in seconds; otherwise it hands over to the Snapshot request below,
   which is a different answer rather than a failure. */
.instant { max-width: 620px; margin: 0 auto var(--sp-5); text-align: center; }
.instant-form { display: flex; gap: .5rem; justify-content: center; flex-wrap: wrap; }
.instant-form input {
  flex: 1 1 260px; min-width: 0; padding: .75rem 1rem;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  font-size: var(--fs-base); background: var(--bg-white); color: var(--text);
}
.instant-form input:focus-visible { outline: 2px solid var(--violet-strong); outline-offset: 1px; }

/* Steps appear as they actually complete. There is no timed sequence here and
   there must never be one: a progress indicator driven by a clock is a
   fabricated observation, which on this site would be self-refuting. */
.instant-steps { list-style: none; margin: var(--sp-3) 0 0; padding: 0;
                 font-size: var(--fs-sm); color: var(--text-faint); }
.instant-steps li { padding: .18rem 0; transition: color var(--dur-fast) var(--ease); }
.instant-steps li::before { content: "· "; }
.instant-steps li.is-done { color: var(--violet-dark); }
.instant-steps li.is-done::before { content: "✓ "; }

.instant-out { margin-top: var(--sp-3); text-align: left; }
.instant-msg { margin: 0 0 .3rem; }
.instant-msg-sub { color: var(--text-muted); font-size: var(--fs-sm); margin: 0; }

.instant-picks { list-style: none; margin: var(--sp-2) 0 0; padding: 0;
                 display: grid; gap: .5rem; }
.instant-pick {
  width: 100%; text-align: left; cursor: pointer;
  background: var(--bg-white); border: 1px solid var(--border);
  border-radius: var(--radius); padding: .7rem .9rem;
  display: flex; flex-direction: column; gap: .15rem;
  transition: border-color var(--dur-fast) var(--ease);
}
.instant-pick:hover, .instant-pick:focus-visible { border-color: var(--violet-strong); }
.ip-name { font-weight: 600; color: var(--text); }
/* The domain is the disambiguator, so it is never the small print people skip. */
.ip-meta { font-size: var(--fs-sm); color: var(--text-muted); font-family: var(--font-mono); }

@media (max-width: 640px) {
  .instant-form { flex-direction: column; }
  .instant-form input, .instant-form .btn { width: 100%; }
}
@media (prefers-reduced-motion: reduce) {
  .instant-steps li, .instant-pick { transition: none; }
}

/* Two buyer paths, added 2026-09-11 after the founder's website review.
   A ready buyer gets a primary action that buys; "speak first" stays available
   and deliberately quieter, rather than being the only way through. */
.offer-alt {
  margin-top: .6rem;
  font-size: var(--fs-xs);
  color: var(--text-faint);
}
.offer-alt a { color: var(--text-muted); text-decoration: underline; }
.offer-alt a:hover { color: var(--violet-strong); }

.wwu-ready {
  margin: var(--sp-2) 0 var(--sp-3);
  padding: .7rem .9rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  font-size: var(--fs-sm);
}
.wwu-ready a { color: var(--violet-strong); }
