/* === RankPanda V2 Design System — A/B premium overlay ===
   Loaded ONLY on /landing-v2 (V2_CSS_LINK). Never imported by design-system.css.
   Additive + A/B-safe: every surface override is scoped under `.lp-v2` (the
   class on <main>). Utility-class overrides use `main.lp-v2 .util` so they win
   the specificity/order tie against tailwind.css (which loads later). V1 (/)
   never loads this file, so V1 stays pixel-identical.

   Register: brand landing, premium restraint (Linear-like). Near-mono OKLCH
   surface, hairline borders, grain + soft glow depth, one disciplined indigo
   accent, framed product mocks, confident type. */

/* ───────────────────────────── 1. Token layer ───────────────────────────── */
.lp-v2 {
  /* Near-black tinted neutrals (never #000). Faint indigo hue = 275. */
  --v2-bg:           oklch(15% 0.012 275);
  --v2-surface-1:    oklch(18.5% 0.014 275);
  --v2-surface-2:    oklch(22% 0.016 275);

  /* Hairlines — low-opacity white, the Linear/Mobbin edge treatment. */
  --v2-line:         oklch(100% 0 0 / 0.08);
  --v2-line-strong:  oklch(100% 0 0 / 0.14);

  /* Text — tinted neutrals, no pure gray. */
  --v2-fg:           oklch(96% 0.005 275);
  --v2-fg-muted:     oklch(74% 0.01 275);
  --v2-fg-subtle:    oklch(60% 0.012 275);

  /* Single accent — indigo, demoted to accent-only duty. */
  --v2-accent:       oklch(64% 0.17 275);
  --v2-accent-soft:  oklch(64% 0.17 275 / 0.16);

  /* One soft elevation shadow, reused everywhere. */
  --v2-shadow: 0 1px 2px oklch(0% 0 0 / 0.4), 0 12px 32px -12px oklch(0% 0 0 / 0.55);
  --v2-ease:  cubic-bezier(0.22, 1, 0.36, 1);

  background: var(--v2-bg);
  color: var(--v2-fg);
}

/* ──────────────────────── 2. Depth: glow + grain ────────────────────────── */
/* Soft radial glow behind the hero fold. Large, low-chroma, blurred: replaces
   the busy dual-orb look with one confident light source. */
.lp-v2-glow {
  position: absolute;
  inset: 0 0 auto 0;
  height: 900px;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 60% 50% at 72% 8%, oklch(64% 0.17 275 / 0.16), transparent 60%),
    radial-gradient(ellipse 50% 40% at 12% 4%, oklch(60% 0.10 260 / 0.10), transparent 65%);
}

/* Barely-there film grain — the tactile "expensive" signal. Fixed, cheap,
   non-interactive. feTurbulence baked into a data URI so it needs no asset. */
.lp-v2-grain {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Keep page content above the depth layers. */
.lp-v2 > .uk-container,
.lp-v2 > .container {
  position: relative;
  z-index: 1;
}

/* Tone the shared V1 atmosphere DOWN on V2: quieter dots, desaturated softer
   orbs so they read as ambient light, not decoration. (design-system.css owns
   the base rules; these scoped overrides only apply on V2.) */
main.lp-v2 .atf-bg-dots {
  background-image: radial-gradient(circle, oklch(100% 0 0 / 0.05) 1px, transparent 1px);
}
main.lp-v2 .atf-orb-1 {
  background: radial-gradient(ellipse, oklch(64% 0.12 275 / 0.10) 0%, transparent 68%);
}
main.lp-v2 .atf-orb-2 {
  background: radial-gradient(ellipse, oklch(60% 0.08 265 / 0.08) 0%, transparent 70%);
}

/* ───────────────────────────── 3. Typography ─────────────────────────────── */
/* Schibsted Grotesk — characterful premium grotesque, off the reflex-reject
   list (was Plus Jakarta Sans). Tight tracking + strong weight contrast. */
.v2-heading {
  font-family: 'Schibsted Grotesk', 'Open Sans', sans-serif;
  letter-spacing: -0.021em;
  font-feature-settings: 'ss01' 1;
}

/* Fluid, committed scale (≥1.25 between steps). Overrides the hero H1 size. */
main.lp-v2 h1.v2-heading {
  font-size: clamp(2.5rem, 1.4rem + 3.6vw, 4.25rem);
  line-height: 1.04;
  font-weight: 800;
}
main.lp-v2 h2.v2-heading {
  font-size: clamp(1.9rem, 1.3rem + 1.9vw, 2.9rem);
  line-height: 1.1;
  font-weight: 700;
  letter-spacing: -0.024em;
}
/* Muted body/subheads tinted, capped measure for premium calm. */
main.lp-v2 p {
  color: var(--v2-fg-muted);
}
main.lp-v2 section > p,
main.lp-v2 .v2-measure {
  max-width: 68ch;
}

/* ──────────────────── 4. Surfaces: hairline, no boxiness ─────────────────── */
/* Shared V1 cards (SixCardGrid, Example, PricingSection, TestimonialsV2) carry
   only tailwind utilities. Retarget those utilities under scope: layered
   surface bg + hairline border + one soft shadow. Structure untouched. */
main.lp-v2 .bg-white,
main.lp-v2 .dark\:bg-gray-900,
main.lp-v2 .uk-card,
main.lp-v2 .uk-card-default {
  background-color: var(--v2-surface-1) !important;
  background-image: none;
}
main.lp-v2 .dark\:bg-gray-800 {
  background-color: var(--v2-surface-2) !important;
}

main.lp-v2 .border-gray-100,
main.lp-v2 .border-gray-200,
main.lp-v2 .dark\:border-gray-700,
main.lp-v2 .dark\:border-gray-700\/60,
main.lp-v2 .dark\:border-gray-800,
main.lp-v2 .dark\:border-gray-800\/60,
main.lp-v2 .uk-card {
  border-color: var(--v2-line) !important;
}

/* Collapse the assorted tailwind shadows to a single refined elevation. */
main.lp-v2 .shadow-sm,
main.lp-v2 .shadow-md,
main.lp-v2 .shadow-lg {
  box-shadow: var(--v2-shadow) !important;
}

/* Hover lift stays subtle; add a hairline-brighten for tactility. */
main.lp-v2 .uk-card:hover,
main.lp-v2 .border-gray-200:hover {
  border-color: var(--v2-line-strong) !important;
}

/* ───────────────────── 5. Framed product-mock panels ─────────────────────── */
/* The single biggest premium lever: present UI mocks like framed screenshots —
   hairline frame, soft shadow, and a glow backdrop behind them. */
.v2-frame {
  position: relative;
  border: 1px solid var(--v2-line);
  border-radius: 0.9rem;
  background: var(--v2-surface-1);
  box-shadow: var(--v2-shadow);
}
.v2-frame::before {
  /* Glow backdrop bleeding out from behind the frame. */
  content: '';
  position: absolute;
  inset: -14% -8% -20% -8%;
  z-index: -1;
  border-radius: 1.4rem;
  background: radial-gradient(ellipse at 50% 0%, var(--v2-accent-soft), transparent 62%);
  filter: blur(24px);
  pointer-events: none;
}

/* Upgrade the hero workflow panel to the framed treatment. */
main.lp-v2 #v2-workflow-panel {
  border-color: var(--v2-line) !important;
  background: var(--v2-surface-1) !important;
  box-shadow: var(--v2-shadow) !important;
}

/* Glow backdrop bleeding from behind the hero panel. On the OUTER wrapper so
   it isn't clipped by the panel's own overflow-hidden. */
.v2-hero-frame {
  position: relative;
}
.v2-hero-frame::before {
  content: '';
  position: absolute;
  inset: -18% -12% -24% -12%;
  z-index: -1;
  border-radius: 1.6rem;
  background: radial-gradient(ellipse at 60% 0%, var(--v2-accent-soft), transparent 60%);
  filter: blur(28px);
  pointer-events: none;
}

/* ────────────────────────── 6. Rhythm & restraint ────────────────────────── */
/* Break spacing monotony: larger, less uniform vertical rhythm than V1's flat
   section-gap. Folds breathe. */
main.lp-v2 .section-gap {
  padding-top: clamp(5rem, 3rem + 6vw, 9rem);
  padding-bottom: clamp(5rem, 3rem + 6vw, 9rem);
}

/* Centered heading blocks: tighten the heading→subhead pairing. */
main.lp-v2 .v2-heading + p {
  color: var(--v2-fg-subtle);
}

/* Contrast: bare .text-slate-500 (#64748b) fails WCAG AA on the near-black
   surface (4.2:1 measured). The `main.lp-v2 p` muted rule loses the
   specificity tie to the later-loading tailwind utility, so retarget the
   utility itself under scope. */
main.lp-v2 .text-slate-500 {
  color: var(--v2-fg-muted);
}

/* SmolCTA — ONE loud primary; the repeats become quiet hairline bands.
   `.v2-smol-cta` is the loud dark indigo (kept for the single primary).
   `.v2-cta-quiet` (new variant) is a restrained bordered band. */
.v2-smol-cta {
  background:
    radial-gradient(ellipse 80% 120% at 50% 0%, oklch(30% 0.09 275), oklch(16% 0.03 275));
  border: 1px solid var(--v2-line-strong);
}
.dark .v2-smol-cta { background:
    radial-gradient(ellipse 80% 120% at 50% 0%, oklch(30% 0.09 275), oklch(16% 0.03 275)); }

.v2-cta-quiet {
  background: var(--v2-surface-1);
  border: 1px solid var(--v2-line);
}
main.lp-v2 .v2-cta-quiet .v2-heading { color: var(--v2-fg); }

/* Loud CTA keeps a crisp near-white button (the single primary signal).
   Higher specificity than the .bg-white surface override above. */
main.lp-v2 a.v2-cta-loud-btn {
  background: oklch(98% 0.006 275) !important;
  color: var(--v2-accent) !important;
}
main.lp-v2 a.v2-cta-loud-btn:hover {
  background: oklch(100% 0 0) !important;
}

/* ───────────────────────── 7. Scroll reveal (JS-driven) ──────────────────── */
/* Panels/headings fade-up once on first intersect. `.is-in` toggled by JS. */
.v2-reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.7s var(--v2-ease), transform 0.7s var(--v2-ease);
  will-change: opacity, transform;
}
.v2-reveal.is-in {
  opacity: 1;
  transform: translateY(0);
}

/* ═══════════════════ Existing workflow + entrance animation ═══════════════ */
/* --- V2 feature list — background numeral positioning fix --- */
.v2-feature-number { overflow: hidden; }

/* Ghosted neutral numeral — near-mono, indigo stays the single accent. */
.v2-feature-num { color: oklch(100% 0 0 / 0.07); }

/* --- V2 workflow panel — subtle pulse on the active step --- */
@keyframes v2-step-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.65; }
}
.v2-step-active { animation: v2-step-pulse 2.6s ease-in-out infinite; }

/* Active step dot — radiating "ping" ring signals a live run */
.v2-wf-dot { position: relative; }
.v2-wf-row.is-active .v2-wf-dot::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--v2-accent);
  animation: v2-dot-ping 2.6s ease-out infinite;
  pointer-events: none;
}
@keyframes v2-dot-ping {
  0%   { transform: scale(1); opacity: 0.55; }
  100% { transform: scale(2.4); opacity: 0; }
}

/* --- V2 workflow panel — animated step rows --- */
.v2-wf-row { transition: background-color 0.4s ease; }
.v2-wf-row.is-active { background-color: oklch(64% 0.17 275 / 0.06); }
.dark .v2-wf-row.is-active { background-color: oklch(64% 0.17 275 / 0.12); }

/* Status glyphs — one visible per row state */
.v2-wf-row .v2-wf-check,
.v2-wf-row .v2-wf-dot { display: none; }
.v2-wf-row.is-done .v2-wf-check {
  display: inline;
  animation: v2-check-in 0.3s ease-out;
}
.v2-wf-row.is-done .v2-wf-dash,
.v2-wf-row.is-active .v2-wf-dash { display: none; }
.v2-wf-row.is-active .v2-wf-dot { display: block; }
@keyframes v2-check-in {
  from { opacity: 0; transform: scale(0.5); }
  to   { opacity: 1; transform: scale(1); }
}

/* Status bar text fade on swap */
.v2-wf-status { transition: opacity 0.25s ease; }

/* --- V2 hero entrance — staggered fade-up choreography --- */
@keyframes v2-rise {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: translateY(0); }
}
.v2-rise { animation: v2-rise 0.6s cubic-bezier(0.22, 1, 0.36, 1) both; }
.v2-rise-1 { animation-delay: 0ms; }
.v2-rise-2 { animation-delay: 90ms; }
.v2-rise-3 { animation-delay: 180ms; }
.v2-rise-4 { animation-delay: 270ms; }
.v2-rise-5 { animation-delay: 360ms; }

/* Shimmer CTA: cap at 3 sweeps on V2 (V1 loops forever). */
.atf-shimmer.atf-shimmer::after { animation-iteration-count: 3; }

/* --- Teaser fill: the ghost fades out, the real result rises in its place --- */
#teaser-result.htmx-swapping { opacity: 0; transition: opacity 0.12s var(--v2-ease); }
@keyframes teaser-fill {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
.teaser-fill { animation: teaser-fill 0.4s var(--v2-ease) both; }

/* Loading line collapses when idle so it doesn't reserve a dead gap under the
   form; it expands only while the teaser request is in flight (htmx-request). */
#teaser-loading { max-height: 0; overflow: hidden; margin-top: 0 !important;
  transition: max-height 0.2s var(--v2-ease), opacity 0.2s var(--v2-ease); }
#teaser-loading.htmx-request { max-height: 4rem; margin-top: 1rem !important; }

/* --- Teaser panel state machine (V4 hero) ------------------------------- */
/* Skeleton/status pulse. Tailwind's animate-pulse keyframes are purged from
   the compiled build (class survives, @keyframes don't), so the panel's
   loading affordances were silently static. Own the animation here. */
@keyframes v2-skel-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}
.v2-skel { animation: v2-skel-pulse 1.8s ease-in-out infinite; }

/* The analyzing panel sits as a SIBLING before #teaser-result (not inside the
   swap target), so it survives result/error swaps and can carry feedback on
   every retry. htmx toggles .htmx-request on it via hx-indicator. */
.teaser-analyzing { display: none; }
.teaser-analyzing.htmx-request { display: block; }
.teaser-analyzing.htmx-request ~ #teaser-result { display: none; }

/* Staged fill: six pipeline steps brighten and check off in sequence, roughly
   pacing the real 15-30s analysis. Delays live in --stg-delay per step; late
   steps keep dimming/pulsing until the swap lands. Used only by the V4 hero
   (the .v2-stage markup exists only in components/landing_v4.py). */
.v2-stage { opacity: 0.35; }
.v2-stage-1 { --stg-delay: 0.2s; }
.v2-stage-2 { --stg-delay: 4s; }
.v2-stage-3 { --stg-delay: 8s; }
.v2-stage-4 { --stg-delay: 12s; }
.v2-stage-5 { --stg-delay: 16s; }
.v2-stage-6 { --stg-delay: 20s; }
.teaser-analyzing.htmx-request .v2-stage {
  animation: v2-stage-on 0.5s var(--v2-ease) var(--stg-delay, 0.2s) forwards;
}
@keyframes v2-stage-on { to { opacity: 1; } }

/* Step marker: a pulsing indigo dot (::before) flips to an emerald check
   (::after) at the same --stg-delay as its row. Both live on one span so the
   flip is pure CSS — no JS, and it restarts cleanly on every retry (htmx
   re-adds .htmx-request, which restarts the delayed animations). */
.v2-stg-marker { position: relative; width: 1rem; height: 1.25rem; flex: none; }
.v2-stg-marker::before {
  content: ''; position: absolute; left: 50%; top: 50%;
  width: 0.5rem; height: 0.5rem; margin: -0.25rem 0 0 -0.25rem;
  border-radius: 9999px; background: rgb(99 102 241);
}
.v2-stg-marker::after {
  content: '\2713'; position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.8rem; font-weight: 700; line-height: 1;
  color: rgb(52 211 153); opacity: 0;
}
.teaser-analyzing.htmx-request .v2-stage .v2-stg-marker::before {
  /* pulse until this step's delay elapses, then v2-dot-off (listed last, so
     it wins the opacity conflict once active) fades the dot out for good */
  animation: v2-skel-pulse 1.8s ease-in-out infinite,
             v2-dot-off 0.3s var(--v2-ease) var(--stg-delay, 0.2s) forwards;
}
.teaser-analyzing.htmx-request .v2-stage .v2-stg-marker::after {
  animation: v2-check-on 0.3s var(--v2-ease) var(--stg-delay, 0.2s) forwards;
}
@keyframes v2-dot-off  { to { opacity: 0; } }
@keyframes v2-check-on { to { opacity: 1; } }

/* ───────────────────────────── Reduced motion ────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .v2-step-active { animation: none; }
  .v2-wf-row.is-active .v2-wf-dot::after { animation: none; display: none; }
  .v2-wf-row,
  .v2-wf-status { transition: none; }
  .v2-wf-row.is-done .v2-wf-check { animation: none; }
  .v2-rise { animation: none; }
  .teaser-fill { animation: none; }
  #teaser-result.htmx-swapping { opacity: 1; transition: none; }
  #teaser-loading { transition: none; }
  .v2-skel { animation: none; }
  .v2-stage { opacity: 1; animation: none !important; }
  /* Static all-checked list: no pulse, checks visible (panel is aria-hidden;
     the aria-live line under the form carries the status). */
  .v2-stg-marker::before { animation: none !important; opacity: 0; }
  .v2-stg-marker::after  { animation: none !important; opacity: 1; }
  .v2-reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ─────────────────────────── V4 fold ownership ───────────────────────────── */
/* The hero owns the first viewport on desktop: the next section must not
   intrude at the fold edge and dilute the single decision (paste a URL). */
@media (min-width: 1024px) {
  main.lp-v4 #top-teaser {
    min-height: calc(100svh - 8rem);
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
}

/* V4's 7-word headline ("Rank on Google, ChatGPT, Claude and Perplexity.")
   can run larger than the old 14-word cap but still below the shared lp-v2
   4.25rem clamp so it wraps at 2 lines in the split hero column. Extra
   .lp-v4 class outranks the main.lp-v2 h1.v2-heading rule. */
main.lp-v2.lp-v4 h1.v2-heading {
  font-size: clamp(2.2rem, 1.2rem + 2.8vw, 3.4rem);
  line-height: 1.1;
}

/* ──────────────── Workflow comparison (V3: WorkflowCompareV2) ────────────── */
/* One hairline surface, asymmetric ~60/40 split. Product side dominant with a
   numbered 01-06 spine; the old way is a recessed ghost column. Stacks on
   mobile, steps first (V1's RPHalfGrid was hidden below lg entirely). */
.v2-compare {
  display: grid;
  grid-template-columns: 1fr;
  border: 1px solid var(--v2-line);
  border-radius: 16px;
  background: var(--v2-surface-1);
  box-shadow: var(--v2-shadow);
  overflow: hidden;
}
@media (min-width: 1024px) {
  .v2-compare { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); }
}

.v2-compare-main { padding: clamp(1.75rem, 4vw, 3.25rem); }

.v2-compare-ghost {
  padding: clamp(1.75rem, 4vw, 2.75rem);
  background: oklch(0% 0 0 / 0.22);
  border-top: 1px solid var(--v2-line);
}
@media (min-width: 1024px) {
  .v2-compare-ghost { border-top: 0; border-left: 1px solid var(--v2-line); }
}
.v2-compare-ghost-title {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--v2-fg-muted);
}

.v2-compare-sub {
  color: var(--v2-fg-muted);
  font-size: 0.95rem;
  margin-top: 0.35rem;
}

/* Numbered spine: hairline runs through the numeral column; numerals sit on
   the surface color so the line breaks behind them. */
.v2-compare-steps {
  list-style: none;
  margin: 1.75rem 0 0;
  padding: 0;
  position: relative;
}
.v2-compare-steps::before {
  content: '';
  position: absolute;
  left: 0.95rem;
  top: 1.5rem;
  bottom: 1.5rem;
  width: 1px;
  background: var(--v2-line);
}
.v2-compare-steps li {
  display: grid;
  grid-template-columns: 2.6rem 1fr;
  column-gap: 0.9rem;
  padding: 0.95rem 0;
}
.v2-compare-num {
  position: relative;
  z-index: 1;
  align-self: start;
  justify-self: start;
  padding: 0.15rem 0.2rem;
  background: var(--v2-surface-1);
  color: var(--v2-accent);
  font-weight: 700;
  font-size: 0.95rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}
.v2-compare-step-title {
  color: var(--v2-fg);
  font-size: 1.02rem;
  font-weight: 600;
  margin: 0;
}
.v2-compare-step-desc {
  color: var(--v2-fg-muted);
  font-size: 0.925rem;
  line-height: 1.55;
  margin: 0.2rem 0 0;
  max-width: 46ch;
}

.v2-compare-cons {
  list-style: none;
  margin: 1.75rem 0 0;
  padding: 0;
}
.v2-compare-cons li {
  display: flex;
  gap: 0.75rem;
  padding: 0.85rem 0;
  color: var(--v2-fg-muted);
  font-size: 0.95rem;
  line-height: 1.5;
  border-top: 1px solid oklch(100% 0 0 / 0.05);
}
.v2-compare-cons li:first-child { border-top: 0; }
.v2-compare-x {
  color: var(--v2-fg-subtle);
  font-size: 0.85rem;
  padding-top: 0.1rem;
}

/* ───────────────────────── V5: skyline spectacle hero ────────────────────── */
/* Full-bleed fold owned by the WebGL canvas (static/js/hero-skyline.js).
   Layers: .atf-* fallback backdrop → canvas (fades in on .is-live) → two
   radial scrims (text contrast with or without WebGL) → bottom-left copy. */
.lp-v5-hero {
  position: relative;
  z-index: 1;              /* above .lp-v2-glow, like the .uk-container rule */
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  padding: 6rem 6vw 10vh;
}
@media (min-width: 1024px) {
  .lp-v5-hero { padding-bottom: 14vh; }
}

.lp-v5-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity 0.7s var(--v2-ease);
  /* Fade the terrain out at the hero's bottom edge so the scene dissolves
     into the next section instead of ending on a hard clip line. */
  -webkit-mask-image: linear-gradient(to bottom, black 84%, transparent 100%);
  mask-image: linear-gradient(to bottom, black 84%, transparent 100%);
}
.lp-v5-canvas.is-live { opacity: 1; }

.lp-v5-scrim-a,
.lp-v5-scrim-b {
  position: absolute;
  inset: -10% -12%;
  pointer-events: none;
}
.lp-v5-scrim-a { background: radial-gradient(42% 42% at 24% 62%, oklch(0% 0 0 / 0.55), transparent 66%); }
.lp-v5-scrim-b { background: radial-gradient(36% 32% at 74% 66%, oklch(0% 0 0 / 0.45), transparent 68%); }

.lp-v5-hero-copy {
  position: relative;
  max-width: 46rem;
}

/* 3-word headline earns a bigger clamp than the shared lp-v2 cap; the extra
   .lp-v5 class outranks main.lp-v2 h1.v2-heading (same trick as .lp-v4). */
main.lp-v2.lp-v5 h1.v2-heading {
  font-size: clamp(2.8rem, 1.6rem + 4.2vw, 5rem);
  line-height: 1.03;
}

/* Quiet secondary hero CTA — own class so the tailwind purge can't eat it. */
.lp-v5-ghost-btn {
  border: 1px solid var(--v2-line-strong);
  color: var(--v2-fg-muted);
  transition: border-color 0.2s var(--v2-ease), color 0.2s var(--v2-ease);
}
.lp-v5-ghost-btn:hover {
  border-color: oklch(100% 0 0 / 0.3);
  color: var(--v2-fg);
}

/* Smooth-scroll for the hero anchor CTAs (#teaser / #features). */
@media (prefers-reduced-motion: no-preference) {
  html:has(main.lp-v5) { scroll-behavior: smooth; }
}
@media (prefers-reduced-motion: reduce) {
  .lp-v5-canvas { transition: none; }
}

/* ═══════════════ Proof-data section (.lp-proof-*) ═══════════════
   /landing-proof demo route + future landing embed (components/landing_proof.py).
   Cards reveal via .is-in from ProofDataScript's IntersectionObserver:
   line draws in (pathLength=1 dash trick), area fades, bars scale,
   numbers count up in JS. Server renders final numbers, so no-JS /
   reduced-motion users see a complete static card. */

.lp-proof-card {
  position: relative;
  border: 1px solid var(--v2-line);
  border-radius: 1rem;
  background: var(--v2-surface-1);
  box-shadow: var(--v2-shadow);
  padding: 1.75rem 1.75rem 1.5rem;
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.7s var(--v2-ease), transform 0.7s var(--v2-ease);
}
.lp-proof-card:nth-child(2) { transition-delay: 0.12s; }
.lp-proof-card:nth-child(3) { transition-delay: 0.24s; }
.lp-proof-card.is-in { opacity: 1; transform: translateY(0); }

/* Giant count-up hook */
.lp-proof-num-row {
  display: flex;
  align-items: baseline;
  gap: 0.15rem;
  font-size: clamp(2.6rem, 4.5vw, 3.4rem);
  font-weight: 700;
  line-height: 1;
  color: var(--v2-fg);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.lp-proof-num-suffix { color: var(--v2-accent); font-size: 0.65em; }

/* Source + placeholder chips */
.lp-proof-gsc-chip {
  display: inline-flex;
  align-items: center;
  padding: 0.2rem 0.6rem;
  border-radius: 9999px;
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--v2-fg-muted);
  border: 1px solid var(--v2-line-strong);
  background: oklch(100% 0 0 / 0.03);
  white-space: nowrap;
}
.lp-proof-pending-chip {
  position: absolute;
  top: -0.7rem;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.2rem 0.7rem;
  border-radius: 9999px;
  font-size: 0.65rem;
  font-weight: 600;
  white-space: nowrap;
  color: oklch(84% 0.12 85);
  background: oklch(30% 0.06 85 / 0.9);
  border: 1px solid oklch(70% 0.12 85 / 0.4);
}

/* Chart — line draws in (heat-gradient stroke set as SVG attribute; no
   stroke property here or it would override the gradient), area fades after,
   dots/chip pop last. Dots, chip and pulse ring are HTML overlays inside
   .lp-proof-spark-wrap — SVG circles/text would stretch under
   preserveAspectRatio="none". */
.lp-proof-spark { width: 100%; height: 84px; display: block; }
.lp-proof-spark-wrap { position: relative; }
.lp-proof-line {
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 1.6s var(--v2-ease) 0.25s;
}
.lp-proof-card.is-in .lp-proof-line { stroke-dashoffset: 0; }
.lp-proof-area { opacity: 0; transition: opacity 0.9s var(--v2-ease) 1.1s; }
.lp-proof-card.is-in .lp-proof-area { opacity: 1; }
.lp-proof-grid-line {
  stroke: oklch(100% 0 0 / 0.06);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.lp-proof-baseline {
  stroke: oklch(100% 0 0 / 0.14);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.lp-proof-dot {
  position: absolute;
  transform: translate(-50%, -50%);
  border-radius: 9999px;
  opacity: 0;
  transition: opacity 0.4s var(--v2-ease) 1.6s;
}
.lp-proof-dot-start {
  width: 8px;
  height: 8px;
  border: 2px solid var(--v2-accent);
  background: var(--v2-surface-1);
  transition-delay: 0.35s;
}
.lp-proof-dot-peak {
  width: 7px;
  height: 7px;
  background: oklch(76% 0.16 162);
}
.lp-proof-peak-chip {
  position: absolute;
  padding: 0.15rem 0.5rem;
  border-radius: 9999px;
  font-size: 0.65rem;
  font-weight: 600;
  white-space: nowrap;
  color: oklch(84% 0.14 162);
  background: oklch(28% 0.05 162 / 0.9);
  border: 1px solid oklch(70% 0.13 162 / 0.4);
  opacity: 0;
  transition: opacity 0.4s var(--v2-ease) 1.6s;
}
.lp-proof-peak-ring {
  position: absolute;
  width: 7px;
  height: 7px;
  border: 2px solid oklch(76% 0.16 162);
  border-radius: 9999px;
  transform: translate(-50%, -50%);
  opacity: 0;
}
@keyframes lp-proof-pulse {
  from { transform: translate(-50%, -50%) scale(1); opacity: 0.7; }
  to   { transform: translate(-50%, -50%) scale(2.8); opacity: 0; }
}
.lp-proof-card.is-in .lp-proof-dot,
.lp-proof-card.is-in .lp-proof-peak-chip { opacity: 1; }
.lp-proof-card.is-in .lp-proof-peak-ring {
  animation: lp-proof-pulse 0.9s var(--v2-ease) 1.75s forwards;
}

/* Before/after bars — width is set inline (honest ratio), scaleX animates */
.lp-proof-bar-track {
  height: 8px;
  border-radius: 9999px;
  background: oklch(100% 0 0 / 0.06);
  overflow: hidden;
}
.lp-proof-bar-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, oklch(58% 0.17 275), oklch(70% 0.15 275));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 1.1s var(--v2-ease) 0.4s;
}
.lp-proof-bar-fill.lp-proof-bar-base {
  background: oklch(100% 0 0 / 0.28);
  transition-delay: 0.3s;
}
.lp-proof-card.is-in .lp-proof-bar-fill { transform: scaleX(1); }

/* Absolute-numbers footer */
.lp-proof-stat-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
  border-top: 1px solid var(--v2-line);
}

@media (prefers-reduced-motion: reduce) {
  .lp-proof-card,
  .lp-proof-line,
  .lp-proof-area,
  .lp-proof-dot,
  .lp-proof-peak-chip,
  .lp-proof-bar-fill { transition: none; }
  .lp-proof-card { opacity: 1; transform: none; }
  .lp-proof-line { stroke-dashoffset: 0; }
  .lp-proof-area,
  .lp-proof-dot,
  .lp-proof-peak-chip { opacity: 1; }
  .lp-proof-card.is-in .lp-proof-peak-ring { animation: none; opacity: 0; }
  .lp-proof-bar-fill { transform: scaleX(1); }
}

/* Grid + micro-type for the proof cards — own classes because the prebuilt
   tailwind.css purged lg:max-w-none / text-[11px] / tabular-nums. */
.lp-proof-grid {
  display: grid;
  gap: 1.5rem;
  max-width: 28rem;
  margin-inline: auto;
}
@media (min-width: 1024px) {
  .lp-proof-grid { grid-template-columns: repeat(3, 1fr); max-width: none; }
}
.lp-proof-micro { font-size: 0.6875rem; line-height: 1.4; }
.lp-proof-card { font-variant-numeric: tabular-nums; }
