/*
 * Public scan-funnel styles (COD-235), ported from the
 * dsa-onboarding-revised.html mockup onto design-tokens.css.
 *
 * The wizard is server-rendered: selection controls are native
 * checkboxes/radios hidden inside styled <label> rows, so every step
 * works without JavaScript.
 */

/* ── Page shell ── */
*,
*::before,
*::after { box-sizing: border-box; margin: 0; padding: 0; }

.funnel-body {
  min-height: 100vh;
  font-family: var(--sans);
  color: var(--dark);
  background: var(--white);
  --funnel-grad: linear-gradient(135deg, #0b1a4f 0%, #1a3aad 50%, var(--blue) 100%);
}

.funnel-shell { display: flex; min-height: 100vh; }

.funnel-left {
  width: 55%;
  display: flex;
  flex-direction: column;
  padding: 2.5rem 3.5rem 1.75rem;
}

.funnel-logo {
  font-family: var(--mono);
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--blue);
  letter-spacing: -0.01em;
  margin-bottom: 2.5rem;
}
.funnel-logo a { color: inherit; text-decoration: none; }

.funnel-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  /* Centre the content column in the left pane (the design centres each step
     horizontally; left-aligning made it read as small and off-centre). */
  max-width: 480px;
  width: 100%;
  margin-left: auto;
  margin-right: auto;
  animation: funnel-step-in 0.28s ease both;
}
@keyframes funnel-step-in {
  from { opacity: 0; transform: translateX(22px); }
  to   { opacity: 1; transform: translateX(0); }
}

/* ── Step header: dots + eyebrow ── */
.step-header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 2.5rem;
}
.step-dots { display: flex; align-items: center; gap: 0.45rem; }
.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--blue-light);
}
.dot.active { width: 22px; border-radius: 4px; background: var(--blue); }
.dot.done { background: var(--blue); opacity: 0.3; }

.eyebrow {
  font-family: var(--mono);
  font-size: 0.65rem;
  font-weight: 600;
  color: var(--blue);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}

/* ── Typography ── */
.step-h {
  font-size: 1.85rem;
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -0.025em;
  margin-bottom: 0.6rem;
}
.step-sub {
  font-size: 1rem;
  color: var(--text-muted);
  line-height: 1.5;
  margin-bottom: 1.75rem;
}
.step-lead {
  font-size: 1rem;
  font-weight: 600;
  color: var(--dark);
  margin-bottom: 1.5rem;
  line-height: 1.5;
}

/* ── URL / email input rows ── */
.url-box {
  display: flex;
  align-items: center;
  border: 1px solid var(--blue);
  border-radius: 50px;
  max-width: 420px;
  margin-bottom: 0.75rem;
  background: var(--white);
  transition: box-shadow 0.15s;
  padding: 4px 4px 4px 0;
}
.url-box:focus-within { box-shadow: 0 0 0 3px rgba(11, 69, 255, 0.12); }
.url-prefix {
  padding: 0 0.5rem 0 1.25rem;
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--text-muted);
  white-space: nowrap;
}
.url-input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--dark);
  padding: 0.7rem 0.25rem;
  background: transparent;
  font-family: var(--sans);
}
.url-input::placeholder { color: var(--text-sub); font-weight: 400; }
.url-box > .url-input:first-child { padding-left: 1.25rem; }
.btn-scan {
  background: var(--blue);
  color: var(--white);
  border: none;
  padding: 0.7rem 1.25rem;
  font-family: var(--sans);
  font-size: 0.88rem;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  border-radius: 50px;
  transition: background 0.15s;
}
.btn-scan:hover { background: var(--blue-dark); }
/* Loading state for the step-4 email submit, which acknowledges the click at once
   while the lead is captured (see scope_confirmed.html). */
.btn-spinner {
  display: inline-block;
  width: 13px;
  height: 13px;
  margin-right: 0.45rem;
  border: 2px solid rgba(255, 255, 255, 0.45);
  border-top-color: var(--white);
  border-radius: 50%;
  animation: funnel-spin 0.7s linear infinite;
  vertical-align: -1px;
}

/* ── Step 1 "what we check" box ── */
.proof-box {
  max-width: 480px;
  width: 100%;
  padding: 1rem 1.15rem;
  border: 1.5px solid var(--blue);
  border-radius: 10px;
  margin-top: auto;
}
.proof-box-intro {
  font-size: 0.78rem;
  color: var(--blue);
  line-height: 1.65;
  margin-bottom: 0.85rem;
}
.proof-box-label {
  font-size: 0.7rem;
  font-weight: 700;
  color: var(--blue);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  margin-bottom: 0.5rem;
}
.proof-list {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.proof-list li {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  font-size: 0.78rem;
  color: var(--blue);
}
.proof-art {
  font-family: var(--mono);
  font-size: 0.65rem;
  font-weight: 700;
  flex-shrink: 0;
}

/* ── Choice rows (platform categories, step 2) ── */
.choice-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  width: 100%;
}
.choice-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.95rem 1.15rem;
  background: var(--white);
  border: 1.5px solid var(--border-solid);
  border-radius: 12px;
  cursor: pointer;
  transition: border-color 0.18s, background 0.18s;
}
.choice-row:hover { border-color: var(--blue-light); }
.choice-row:has(input:checked) { border-color: var(--blue); background: var(--blue-pale); }
.choice-row input { position: absolute; opacity: 0; pointer-events: none; }
.choice-icon {
  width: 38px;
  height: 38px;
  border-radius: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--gray-bg);
  color: var(--text-muted);
  flex-shrink: 0;
  transition: background 0.18s, color 0.18s;
}
.choice-row:has(input:checked) .choice-icon { background: var(--blue); color: var(--white); }
.choice-text { flex: 1; min-width: 0; }
.choice-label {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--dark);
  line-height: 1.2;
}
.choice-sub {
  display: block;
  font-size: 0.72rem;
  color: var(--text-muted);
  margin-top: 0.18rem;
}
.choice-row:has(input:checked) .choice-sub { color: var(--blue); }
.choice-toggle {
  width: 40px;
  height: 22px;
  border-radius: 50px;
  background: #cbd5e1;
  position: relative;
  flex-shrink: 0;
  transition: background 0.2s;
}
.choice-toggle::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  background: var(--white);
  border-radius: 50%;
  transition: transform 0.2s;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}
.choice-row:has(input:checked) .choice-toggle { background: var(--blue); }
.choice-row:has(input:checked) .choice-toggle::after { transform: translateX(18px); }

/* ── Pill options (company size, VLOP yes/no) ── */
.pill-options { display: flex; gap: 1.1rem; flex-wrap: wrap; }
.pill-option { display: flex; flex-direction: column; flex: 1; min-width: 110px; }
.pill-option input { position: absolute; opacity: 0; pointer-events: none; }
.pill-btn {
  display: block;
  padding: 0.65rem 1.5rem;
  border-radius: 50px;
  border: 1.5px solid var(--border-solid);
  background: var(--white);
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--dark);
  text-align: center;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
}
.pill-option:hover .pill-btn { border-color: var(--blue); color: var(--blue); }
.pill-option:has(input:checked) .pill-btn {
  background: var(--blue);
  border-color: var(--blue);
  color: var(--white);
}
.pill-desc {
  font-size: 0.65rem;
  color: var(--text-muted);
  margin-top: 0.55rem;
  line-height: 1.4;
}

.q-big {
  font-size: 1.4rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: -0.02em;
  color: var(--dark);
  margin-bottom: 0.6rem;
}
.q-note {
  font-size: 0.72rem;
  color: var(--text-muted);
  margin-bottom: 1.25rem;
  line-height: 1.5;
}
/* Separates the two questions on the combined scope-questions step. */
.q-block { margin-bottom: 2.25rem; }
/* Inline per-question validation message (step 3), shown by the page's script in
   place of the browser's default bubble when a group is unanswered (COD-263). */
.q-error {
  margin-top: 0.75rem;
  font-size: 0.8rem;
  font-weight: 500;
  color: #dc2626;
}
.q-error[hidden] { display: none; }

/* Respectful informational note on the platform-type step when detection judges the
   domain isn't a DSA-relevant service (COD-263) — muted, not an error. */
.scope-note {
  margin: 0 0 1.5rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--blue);
  border-radius: 8px;
  background: var(--blue-pale, #eef2ff);
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--text-muted);
}
.scope-note strong { color: var(--dark); }

/* ── Confirm page (step 4) ──
 *
 * Einat's batch-5 mock (s7) replaced the old dark key/value scope card with a
 * prose recap + an email "hero" card. The card is the step's whole call to
 * action, so it carries the mark, the ask, and the submit together. */
.scope-h { margin-bottom: 0.5rem; }
/* Wider than the mock's 360px: its sample classification is short, ours can carry
   three category labels. At the mock's airy 1.9 line-height a wrapped sentence
   reads as two unrelated lines, so give each one room to stay whole. */
.scope-line {
  font-size: 1rem;
  color: var(--dark);
  line-height: 1.9;
  margin-bottom: 2rem;
  width: 100%;
}
.scope-line-domain { font-weight: 700; color: var(--blue); }
.scope-line-count { color: var(--blue); }

.email-card {
  width: 100%;
  max-width: 360px;
  background: var(--white);
  border: 1.5px solid var(--border);
  border-radius: 18px;
  padding: 2rem 1.75rem 1.75rem;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
  text-align: center;
}
.email-card-h {
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--dark);
  line-height: 1.3;
  letter-spacing: -0.02em;
  margin-bottom: 0.6rem;
}
.email-card-p {
  font-size: 0.82rem;
  color: var(--text-muted);
  line-height: 1.6;
  margin-bottom: 1.4rem;
}
.email-card-input {
  width: 100%;
  border: 2px solid var(--border);
  border-radius: 50px;
  padding: 0.7rem 1.1rem;
  font-family: var(--sans);
  font-size: 0.88rem;
  color: var(--dark);
  outline: none;
  margin-bottom: 0.65rem;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.email-card-input:focus {
  border-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(11, 69, 255, 0.1);
}
.email-card-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  background: var(--blue);
  color: var(--white);
  border: none;
  border-radius: 50px;
  padding: 0.75rem 1rem;
  font-family: var(--sans);
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s;
  box-shadow: 0 4px 14px -4px rgba(11, 69, 255, 0.5);
}
.email-card-btn:hover { background: var(--blue-dark); }
.email-card-btn:disabled { opacity: 0.8; cursor: default; }
.email-card-note {
  font-size: 0.7rem;
  color: var(--text-sub);
  margin-top: 1rem;
  line-height: 1.5;
  max-width: 360px;
}

/* Document-with-tick mark: CSS boxes, as the mock builds it. */
.email-card-illo { position: relative; display: inline-block; margin-bottom: 1.5rem; }
.email-card-illo-shadow {
  position: absolute;
  top: 5px;
  left: 5px;
  width: 58px;
  height: 68px;
  background: var(--blue-light);
  border-radius: 8px;
}
.email-card-illo-doc {
  position: relative;
  width: 58px;
  height: 68px;
  background: var(--white);
  border: 1.5px solid var(--border-solid);
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 10px 10px 12px;
  gap: 5px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}
.email-card-illo-fold,
.email-card-illo-fold-inner {
  position: absolute;
  width: 0;
  height: 0;
  border-style: solid;
}
.email-card-illo-fold {
  top: 0;
  right: 0;
  border-width: 0 14px 14px 0;
  border-color: transparent var(--border-solid) transparent transparent;
}
.email-card-illo-fold-inner {
  top: 1.5px;
  right: 1.5px;
  border-width: 0 12px 12px 0;
  border-color: transparent var(--gray-bg) transparent transparent;
}
.email-card-illo-line { height: 3.5px; background: var(--blue-light); border-radius: 2px; }
.email-card-illo-line:nth-child(3) { width: 80%; }
.email-card-illo-line:nth-child(4) { width: 65%; }
.email-card-illo-line:nth-child(5) { width: 75%; }
.email-card-illo-badge {
  position: absolute;
  bottom: -8px;
  right: -8px;
  width: 24px;
  height: 24px;
  background: var(--blue);
  border-radius: 50%;
  border: 2.5px solid var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 6px rgba(11, 69, 255, 0.35);
}

/* ── Errors ── */
.form-errors {
  max-width: 420px;
  background: var(--amber-bg);
  border: 1px solid var(--amber-border);
  border-radius: 10px;
  color: var(--amber-text);
  font-size: 0.78rem;
  line-height: 1.5;
  padding: 0.6rem 0.9rem;
  margin-bottom: 0.9rem;
}
.form-errors ul { list-style: none; }

/* ── Nav row ── */
.nav-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 1.5rem;
  margin-top: auto;
  max-width: 480px;
  width: 100%;
}
.btn-back {
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--text-muted);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0.75rem;
  border-radius: 8px;
  transition: color 0.15s, background 0.15s;
}
.btn-back:hover { color: var(--dark); background: var(--gray-bg); }
/* Pull the back link flush to the content column's left edge so it sits in the
   lower-left corner (per the design), without losing its symmetric hover padding. */
.nav-row .btn-back { margin-left: -0.75rem; }

.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--blue);
  color: var(--white);
  border: none;
  border-radius: 50px;
  padding: 0.9rem 2rem;
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s, transform 0.1s, box-shadow 0.15s;
  box-shadow: 0 6px 18px -6px rgba(11, 69, 255, 0.45), 0 2px 4px rgba(11, 69, 255, 0.15);
}
.btn-primary:hover {
  background: var(--blue-dark);
  box-shadow: 0 10px 24px -6px rgba(11, 69, 255, 0.55), 0 3px 6px rgba(11, 69, 255, 0.2);
}
.btn-primary:active { transform: scale(0.97); }

/* ── Right panel ── */
.funnel-right {
  width: 45%;
  background: var(--funnel-grad);
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  pointer-events: none;
}
.glow-1 { width: 320px; height: 320px; background: rgba(11, 69, 255, 0.35); top: -80px; right: -80px; }
.glow-2 { width: 200px; height: 200px; background: rgba(221, 231, 254, 0.1); bottom: 30px; left: 10px; }
.glow-3 { width: 140px; height: 140px; background: rgba(245, 232, 74, 0.07); top: 50%; left: 40%; transform: translate(-50%, -50%); }

.doc-frame { position: relative; width: 260px; z-index: 2; }
.doc-card {
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 16px;
  padding: 1.5rem 1.75rem;
  backdrop-filter: blur(8px);
}
.doc-label {
  font-family: var(--mono);
  font-size: 0.62rem;
  color: rgba(255, 255, 255, 0.45);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 1rem;
}
.doc-line {
  height: 6px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.1);
  margin-bottom: 0.5rem;
}
.doc-line.acc { background: rgba(11, 69, 255, 0.55); }
.doc-line.w60 { width: 60%; }
.doc-line.w45 { width: 45%; }
.doc-line.w75 { width: 75%; }
.doc-line.w50 { width: 50%; }
.doc-logo {
  font-family: var(--mono);
  font-size: 0.8rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.85);
  margin-top: 1.2rem;
  letter-spacing: -0.01em;
}
.float-pill {
  position: absolute;
  /* nowrap is load-bearing: the side pills are positioned past the 260px card via
     calc(100% + gap), which collapses an auto-width box to near-zero (forcing the
     label to wrap) unless it's kept on one line. */
  white-space: nowrap;
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 600;
  color: var(--white);
  background: rgba(11, 69, 255, 0.65);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 50px;
  padding: 0.22rem 0.6rem;
  animation: float-y 3s ease-in-out infinite;
}
/* Badges scattered clear of the card (its backdrop-filter stacking context would
   otherwise paint over an overlapping pill): Art. 16 floats above; Art. 20 flanks
   the left at ~1/3 of the card height; Art. 25 flanks the right at ~2/3. The two
   side pills sit fully outside the card via left/right: calc(100% + gap) — measured
   from the card's own edges — and their % tops track the card height. */
.float-pill:nth-child(1) { top: -32px; left: 60px; animation-delay: 0s; }              /* Art. 16 — above, nudged right of the corner */
.float-pill:nth-child(2) { top: 60%; left: calc(100% + 8px); animation-delay: 0.7s; }  /* Art. 25 — right of the card, ~2/3 down */
.float-pill:nth-child(3) { top: 28%; right: calc(100% + 8px); animation-delay: 1.4s; } /* Art. 20 — left of the card, ~1/3 down */
@keyframes float-y {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

/* ── Submitted page ── */
.submitted-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  max-width: 480px;
}
.submitted-icon {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--blue-pale);
  color: var(--blue);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1.5rem;
}
.submitted-email { font-weight: 700; color: var(--dark); }

/* ── Live scan progress (token report page, pending state) ── */
/* This page shares the wizard's column width so every block on it centres on one
   axis. It previously widened to 620px to keep each step row ("<label> – Art. NN(N)")
   on one line (Einat, COD-263), but the widened column left the narrower prose blocks
   pinned to its left edge with ~160px of dead space on the right — the page read as
   off-centre rather than roomy. The step rows still fit on one line at the shared
   width (they need ~400px of the ~480px available). Everything that reads as a block
   shares the full column; the prose blocks keep their own narrower measure but are
   centred within it (margin-inline: auto) so no edge goes ragged. On narrow screens
   the column falls back to 100% and rows may wrap, which is fine. */
.funnel-content--scan { max-width: 480px; }
.funnel-content--scan .scan-progress-card,
.funnel-content--scan .scan-tally,
.funnel-content--scan .scan-offer { max-width: 100%; }

/* The card is unpadded and clips (batch-5 mock, s6) so the header rule and each
   row's separator run edge to edge; padding lives on the header and the rows. */
.scan-progress-card {
  border: 1.5px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  margin: 0.5rem 0 1.25rem;
  max-width: 460px;
}
.scan-progress-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.6rem 1rem;
  border-bottom: 1px solid var(--border);
}
.scan-progress-title {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.scan-progress-count { font-size: 0.72rem; color: var(--text-muted); }
.scan-steps { display: flex; flex-direction: column; }
.scan-step {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 1rem;
  font-size: 0.82rem;
  color: var(--dark);
  border-bottom: 1px solid var(--border);
}
.scan-step:last-child { border-bottom: none; }
.scan-step.queued .scan-step-label { color: var(--text-muted); }
/* Status chip: a tinted circle behind the icon (batch-5 mock, s6), tinted by the
   row's state. The mock's own palette is inlined raw hexes; we use the shared
   status tokens so the chip agrees with the verdict pill beside it. */
.scan-step-icon {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--gray-bg);
  transition: background 0.2s;
}
.scan-step.active             .scan-step-icon { background: var(--blue-pale); }
.scan-step.done               .scan-step-icon,
.scan-step.verdict-pass       .scan-step-icon { background: var(--green-bg); }
.scan-step.verdict-needs-attention .scan-step-icon { background: var(--amber-bg); }
.scan-step.failed             .scan-step-icon { background: var(--red-bg); }
/* The glyphs sit inside the 22px chip, so they render smaller than their
   intrinsic size. */
.scan-step-icon svg { width: 13px; height: 13px; }
/* The queued ring and the running spinner are the same circle in two states, so
   they must render identically. The spinner is a <span>, so the svg rule above
   never reached it: the queued circle rendered 9.75px wide with a 1.08px stroke
   against the spinner's 12px/2px, and the icon jumped +23% in size and +85% in
   weight the moment a row started running. Size this one to the spinner instead;
   its viewBox geometry is tuned to match (see report_progress.html). */
.scan-step-icon .ic-queued { width: 12px; height: 12px; }
/* Each row carries all icon variants; the row's status (or, for a resolved
   scenario, its verdict) class reveals exactly one. */
.scan-step-icon > * { display: none; }
.scan-step.done   .ic-done   { display: inline-flex; }
.scan-step.failed .ic-failed { display: inline-flex; }
.scan-step.queued .ic-queued { display: inline-flex; }
.scan-step.active .ic-active { display: inline-block; }
.scan-step.verdict-pass            .ic-done         { display: inline-flex; }
.scan-step.verdict-needs-attention .ic-warn         { display: inline-flex; }
.scan-step.verdict-inconclusive    .ic-inconclusive { display: inline-flex; }

/* Verdict pill — pre-rendered per row, revealed by the row's verdict class as
   each obligation lands (COD-263). */
.scan-step-verdict { margin-left: auto; }
.scan-step-verdict .sv {
  display: none;
  align-items: center;
  font-size: 0.6rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 0.22rem 0.6rem;
  border-radius: 50px;
}
.scan-step.verdict-pass            .sv-pass            { display: inline-flex; background: var(--green-bg); color: var(--green); }
.scan-step.verdict-needs-attention .sv-needs-attention { display: inline-flex; background: var(--amber-bg); color: var(--amber); }
.scan-step.verdict-inconclusive    .sv-inconclusive    { display: inline-flex; background: var(--gray-bg); color: var(--text-muted); }
.scan-step.verdict-needs-attention .scan-step-label { font-weight: 600; }
/* Muted DSA-article tag after each step label (Einat, COD-263), e.g. "(Art. 16(1))". */
.scan-step-art { color: var(--text-muted); font-weight: 400; white-space: nowrap; }
.scan-spinner {
  width: 12px;
  height: 12px;
  border: 2px solid var(--blue-light);
  border-top-color: var(--blue);
  border-radius: 50%;
  animation: funnel-spin 0.7s linear infinite;
}
@keyframes funnel-spin { to { transform: rotate(360deg); } }
/* Full contrast, not muted: this is the page's most important text (it carries the
   prospect's actual next action — wait here, or close the tab and use the email),
   and it is the "you get your report either way" path standing against the sign-up
   card below it. Whispered in grey it left the upsell reading as the only way
   forward (Yoni + Einat, COD-263). */
.scan-note { font-size: 0.85rem; color: var(--dark); line-height: 1.6; max-width: 460px; margin-inline: auto; }
.scan-note strong { font-weight: 600; }

/* ── Dead-end recovery (failed scan: mistyped / content-less domain, COD-263) ── */
.scan-recovery { margin-top: 0.5rem; max-width: 460px; margin-inline: auto; }
.scan-recovery-note { font-size: 0.82rem; color: var(--text-muted); line-height: 1.55; margin-bottom: 1rem; }
.scan-recovery-actions { display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center; }
.btn-outline {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--white);
  color: var(--dark);
  border: 1px solid var(--border);
  border-radius: 50px;
  padding: 0.9rem 2rem;
  font-family: var(--sans);
  font-size: 0.95rem;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.btn-outline:hover { background: var(--gray-bg); border-color: var(--text-muted); }

/* ── Running tally (live verdict counts above the progress card, COD-263) ── */
.scan-tally {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
  max-width: 460px;
  margin: 1rem 0 1.25rem;
}
.scan-stat {
  background: var(--blue-pale);
  border-radius: 10px;
  padding: 0.55rem 0.5rem 0.6rem;
  text-align: center;
}
.scan-stat-num {
  font-family: var(--mono);
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1;
  color: var(--blue);
}
.scan-stat-num.green { color: var(--green); }
.scan-stat-num.amber { color: var(--amber); }
.scan-stat-lbl { font-size: 0.62rem; color: var(--text-muted); margin-top: 0.25rem; }

/* ── Conversion offer (present throughout the wait, COD-263) ── */
.scan-offer {
  display: flex;
  align-items: center;
  gap: 1rem;
  border: 1.5px solid var(--blue);
  border-radius: 16px;
  background: var(--blue-pale);
  padding: 1.1rem 1.25rem;
  max-width: 460px;
  margin: 1.25rem 0 0;
}
/* A flex display would otherwise win over the [hidden] UA rule, so the failure
   state (which sets hidden) could still show the offer — keep it withheld. */
.scan-offer[hidden] { display: none; }
.scan-offer-body { flex: 1; }
.scan-offer-h { font-size: 1rem; font-weight: 800; color: var(--dark); line-height: 1.3; margin-bottom: 0.3rem; }
.scan-offer-p { font-size: 0.8rem; color: var(--text-muted); line-height: 1.5; }
.scan-offer-p strong { color: var(--dark); }

/* Card variant — the live-progress closing CTA (batch-5 mock, s6): a centred
   card with the platform mark, rather than the inline strip the access-block
   panel still uses. Quieter chrome than the strip's blue fill, so the mark and
   the CTA carry it. */
.scan-offer--card {
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0;
  background: var(--white);
  border-color: var(--border);
  border-radius: 16px;
  padding: 1.5rem 1.25rem 1.4rem;
  transition: box-shadow 0.2s;
}
.scan-offer--card:hover { box-shadow: 0 6px 24px rgba(11, 69, 255, 0.1); }
.scan-offer--card .scan-offer-illo { margin-bottom: 1rem; line-height: 0; }
.scan-offer--card .scan-offer-h { font-size: 1rem; font-weight: 700; line-height: 1.35; margin-bottom: 0.6rem; }
.scan-offer--card .scan-offer-p { font-size: 0.75rem; line-height: 1.55; margin-bottom: 1.1rem; }
/* The CTA is an inline <a>, so it needs a block box before width applies. */
.scan-offer--card .scan-offer-cta { display: block; width: 100%; border-radius: 50px; text-align: center; }
.scan-offer-cta {
  flex-shrink: 0;
  background: var(--blue);
  color: var(--white);
  border-radius: 8px;
  padding: 0.7rem 1.1rem;
  font-size: 0.88rem;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition: background 0.15s;
}
.scan-offer-cta:hover { background: var(--blue-dark); }

/* The strip stacks on narrow screens; the card variant is already a centred
   column, so it opts out rather than being stretched flat. */
@media (max-width: 560px) {
  .scan-offer:not(.scan-offer--card) { flex-direction: column; align-items: stretch; }
  .scan-offer:not(.scan-offer--card) .scan-offer-cta { text-align: center; }
}

/* ── Right-panel scan scene (interstitial / analyzing) ──
   Ported from the dsa-onboarding-revised.html mockup's RP2 "abstract scan"
   illustration: a platform frame swept by a scan beam, with two findings
   filling in and ambient tree/dot motion. Replaces the default doc-frame on
   the analyzing page so the right panel reads as a live scan. */
.scan-svg { width: 100%; max-width: 420px; height: auto; display: block; overflow: visible; position: relative; z-index: 2; }
@keyframes scan-beam-sweep {
  0%   { transform: translateY(0); opacity: 0; }
  15%  { opacity: 0.85; }
  85%  { opacity: 0.85; }
  100% { transform: translateY(180px); opacity: 0; }
}
@keyframes scan-block-fill {
  0%, 100% { stroke-dashoffset: 240; }
  50%      { stroke-dashoffset: 0; }
}
@keyframes scan-tree-sway {
  0%, 100% { transform: rotate(-3deg) translateY(0); }
  50%      { transform: rotate(3deg) translateY(-6px); }
}
@keyframes scan-dot-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50%      { transform: scale(1.18); opacity: 0.8; }
}
.scan-beam    { animation: scan-beam-sweep 4.5s ease-in-out infinite; }
.scan-block   { stroke-dasharray: 240; animation: scan-block-fill 6s ease-in-out infinite; }
.scan-block-2 { animation-delay: 1.2s; }
.scan-tree    { transform-origin: bottom center; transform-box: fill-box; animation: scan-tree-sway 4.5s ease-in-out infinite; }
.scan-dot     { transform-origin: center; transform-box: fill-box; animation: scan-dot-pulse 1.8s ease-in-out infinite; }

/* ── Per-step right-panel scenes (ported from the mockup, RP1/RP3/RP5/RP6) ──
   Each wizard step renders one scene in `{% block right %}`; .funnel-right
   centers it. Class names keep the mockup's rp1-/rp3-/rp5-/rp6- prefixes
   (self-contained, no collision with the funnel- / doc- / scan- families). */
.funnel-scene { position: relative; z-index: 2; }
/* TODO(COD-154): Einat's mockup had an RP4 "rings" scene whose centre showed a
   live "N ARTICLES APPLY" count that updated as the user picked platform
   categories — answers→obligation-count feedback. We removed it (it was orphaned,
   and we don't yet compute the applicable-article count). When COD-154 lands,
   revive the *count* version (git history / the mockup's #rp4), not the inert
   port, as the classification-step scene. */

/* RP1 — journey illustration */
.rp1-card { width: 100%; max-width: 420px; }
.rp1-svg { width: 100%; height: auto; display: block; overflow: visible; }
@keyframes rp1-float-big    { 0%,100% { transform: translateY(0) translateX(0); } 50% { transform: translateY(-16px) translateX(4px); } }
@keyframes rp1-float-y-soft { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
@keyframes rp1-rock         { 0%,100% { transform: translateY(0) rotate(-6deg); } 50% { transform: translateY(-6px) rotate(6deg); } }
@keyframes rp1-pulse        { 0%,100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.18); opacity: 0.8; } }
@keyframes rp1-birds        { 0% { transform: translate(0,0); } 50% { transform: translate(-22px,-10px); } 100% { transform: translate(0,0); } }
@keyframes rp1-sway         { 0%,100% { transform: rotate(-3deg) translateY(0); } 50% { transform: rotate(3deg) translateY(-6px); } }
@keyframes rp1-dash-flow    { to { stroke-dashoffset: -40; } }
@keyframes rp1-x-pulse      { 0%,100% { transform: scale(1) rotate(0deg); } 50% { transform: scale(1.25) rotate(8deg); } }
.rp1-mountains { transform-origin: center; transform-box: fill-box; animation: rp1-float-big 5s ease-in-out infinite; }
.rp1-sun       { transform-origin: center; transform-box: fill-box; animation: rp1-pulse 3s ease-in-out infinite; }
.rp1-birds     { transform-origin: center; transform-box: fill-box; animation: rp1-birds 6s ease-in-out infinite; }
.rp1-boat      { transform-origin: center bottom; transform-box: fill-box; animation: rp1-rock 2.6s ease-in-out infinite; }
.rp1-tree      { transform-origin: bottom center; transform-box: fill-box; animation: rp1-sway 4.5s ease-in-out infinite; }
.rp1-dot       { transform-origin: center; transform-box: fill-box; animation: rp1-pulse 1.8s ease-in-out infinite; }
.rp1-x         { transform-origin: center; transform-box: fill-box; animation: rp1-x-pulse 2.4s ease-in-out infinite; }
.rp1-baretrees { transform-origin: center; transform-box: fill-box; animation: rp1-float-y-soft 4s ease-in-out infinite; }
.rp1-dashed    { stroke-dasharray: 5 4; animation: rp1-dash-flow 2.5s linear infinite; }

/* RP3 — platform / checkpoint scene */
.rp3-svg { width: 100%; max-width: 420px; height: auto; display: block; overflow: visible; }
@keyframes rp3-bob       { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
@keyframes rp3-twinkle   { 0%,100% { opacity: 0.5; } 50% { opacity: 0.95; } }
@keyframes rp3-sway-soft { 0%,100% { transform: rotate(-0.8deg); } 50% { transform: rotate(0.8deg); } }
@keyframes rp3-slide-knob { 0%,100% { transform: translateX(0); } 50% { transform: translateX(10px); } }
@keyframes rp3-leaf-sway  { 0%,100% { transform: rotate(-1.2deg); } 50% { transform: rotate(1.2deg); } }
@keyframes rp3-square-bob { 0%,100% { transform: translateY(0) rotate(0deg); } 50% { transform: translateY(-2px) rotate(3deg); } }
.rp3-twinkle  { transform-origin: center; transform-box: fill-box; animation: rp3-twinkle 5s ease-in-out infinite; }
.rp3-twinkle-2 { animation-delay: 1s; }
.rp3-twinkle-3 { animation-delay: 2s; }
.rp3-twinkle-4 { animation-delay: 3s; }
.rp3-twinkle-5 { animation-delay: 0.7s; }
.rp3-bob      { transform-origin: center; transform-box: fill-box; animation: rp3-bob 8s ease-in-out infinite; }
.rp3-tree     { transform-origin: bottom center; transform-box: fill-box; animation: rp3-sway-soft 10s ease-in-out infinite; }
.rp3-knob-1    { animation: rp3-slide-knob 9s ease-in-out infinite; }
.rp3-knob-2    { animation: rp3-slide-knob 10s ease-in-out infinite reverse; animation-delay: 0.8s; }
.rp3-knob-3    { animation: rp3-slide-knob 8.5s ease-in-out infinite; animation-delay: 1.6s; }
.rp3-leaves    { transform-origin: bottom center; transform-box: fill-box; animation: rp3-leaf-sway 8s ease-in-out infinite; }
.rp3-leaves-2  { animation-delay: 2s; }
.rp3-square    { transform-origin: center; transform-box: fill-box; animation: rp3-square-bob 6s ease-in-out infinite; }
.rp3-square-2  { animation-delay: 1.5s; }

/* RP5 — drifting article pills over an ambient backdrop */
/* Hold the backdrop's own 480:520 aspect. Without it the wrap collapses to the
   pills' height, and since the bg SVG is `meet`-fitted it scales down and centres
   its artwork — landing the tree on top of the pills instead of down in the
   corner. Pills stay vertically centred in the resulting box. */
.rp5-wrap {
  width: 100%;
  max-width: 420px;
  aspect-ratio: 480 / 520;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.rp5-ambient {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  align-items: flex-start;
  position: relative;
  z-index: 2;
}
.rp5-bg-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
  overflow: visible;
}
.rp5-amb-pill {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 50px;
  padding: 0.45rem 0.9rem;
  font-family: var(--mono);
  font-size: 0.62rem;
  font-weight: 500;
  color: rgba(255,255,255,0.55);
  white-space: nowrap;
  animation: rp5-pill-float 6s ease-in-out infinite;
}
.rp5-amb-pill:nth-child(2) { animation-delay: 0.8s; margin-left: 1rem; }
.rp5-amb-pill:nth-child(3) { animation-delay: 1.6s; margin-left: 0.4rem; }
.rp5-amb-pill:nth-child(4) { animation-delay: 2.4s; margin-left: 1.5rem; }
.rp5-amb-pill:nth-child(5) { animation-delay: 3.2s; margin-left: 0.2rem; }
.rp5-amb-pill:nth-child(6) { animation-delay: 4s;   margin-left: 1.2rem; }
.rp5-amb-dim  { opacity: 0.45; }
@keyframes rp5-pill-float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }

/* RP6 — stopwatch / notify scene */
.rp6-svg { width: 100%; max-width: 360px; height: auto; display: block; overflow: visible; }
.rp6-hl   { font-family: var(--sans); font-size: 13px; font-weight: 700; fill: white; }
.rp6-mono { font-family: var(--mono); font-size: 8px; font-weight: 700; fill: rgba(255,255,255,0.5); letter-spacing: 0.16em; }
@keyframes rp6-ring-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes rp6-arc-sweep { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes rp6-tick      { 0%,49%,100% { opacity: 0.6; } 50%,99% { opacity: 1; } }
.rp6-ring     { transform-origin: 180px 150px; animation: rp6-ring-spin 14s linear infinite; }
.rp6-arc      { transform-origin: 180px 150px; animation: rp6-arc-sweep 5s linear infinite; }
.rp6-tick-dot { animation: rp6-tick 1s steps(2, end) infinite; }

/* ── Mobile fallback (desktop-first; polish out of scope) ── */
@media (max-width: 900px) {
  .funnel-shell { flex-direction: column; }
  .funnel-left { width: 100%; padding: 1.5rem 1.25rem; }
  .funnel-right { display: none; }
}
