/*
 * Vantage v2 stylesheet.
 * Ported faithfully from the two approved v2 mockups:
 *   - docs/mockups/2026-07-06-vantage-v2-workspace.html (the base: shell,
 *     rail, report sections, scoreboard, claims, SWOT, frameworks, verify,
 *     chat, motion, and the review-gate fixes already present there).
 *   - docs/mockups/2026-07-06-vantage-v2-journey.html (append-only: the
 *     dev scene switcher and the brand/intake/research journey scenes not
 *     present in the workspace mockup).
 *
 * The journey mockup's `.orb` / `.mark-*` living-mark rules are deliberately
 * NOT ported here: that signature already lives in public/vantage/app.css
 * (ported there in an earlier task) and must not be duplicated.
 *
 * Only one `:root` block exists in this file (the workspace mockup's token
 * set). One extra alias, `--eo`, is added inside that same root: the journey
 * mockup's ported rules (`.log-line` in particular) reference `var(--eo)`,
 * which is the exact same cubic-bezier value as the workspace's `--ease-out`.
 * Adding the alias avoids duplicating the root while keeping the ported
 * rules working unmodified, so this is a value-identical alias, not an
 * invented value.
 */

:root {
  /* Locked tokens (spec section 3.1) */
  --base: #0a0c11;
  --panel: #10141c;
  --raise: #1b2130;
  --line: #2a3242;
  --fg: #edeff4;
  --sub: #bcc4d4;
  --dim: #8791a5;
  --slate: #6f7b96;
  --slate-rgb: 111, 123, 150;
  --gold: #e3b34e;
  --gold-rgb: 227, 179, 78;
  --gold-hi: #f2ca6d;
  --gold-hi-rgb: 242, 202, 109;
  --gold-deep: #a97e26;
  --verified: #5fd6a2;
  --verified-rgb: 95, 214, 162;
  --inferred: #e8974a;
  --inferred-rgb: 232, 151, 74;
  --threat: #e26559;
  --threat-rgb: 226, 101, 89;

  --r-input: 6px;
  --r-card: 10px;
  --r-answer: 14px;
  --r-btn: 8px;

  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  /* alias for the journey mockup's ported rules (same value as --ease-out) */
  --eo: cubic-bezier(0.23, 1, 0.32, 1);
  --shadow-card: 0 1px 2px rgba(0,0,0,0.4), 0 8px 24px rgba(0,0,0,0.35);

  --font-ui: 'Space Grotesk', system-ui, -apple-system, sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
  background: var(--base);
  color: var(--fg);
  font-family: var(--font-ui);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
a { color: inherit; }

/* ---------- Shell ---------- */
.shell {
  display: grid;
  grid-template-columns: 260px minmax(0, 1.5fr) 380px;
  height: 100vh;
  width: 100vw;
}
.shell.chat-collapsed { grid-template-columns: 260px minmax(0, 1fr) 52px; }

.panel-scroll { overflow-y: auto; height: 100vh; }
.panel-scroll::-webkit-scrollbar { width: 10px; }
.panel-scroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: 8px; border: 2px solid var(--base); }

/* ---------- Session rail ---------- */
.rail {
  background: var(--panel);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  height: 100vh;
  position: relative;
}
.rail-head { padding: 20px 18px 14px; }
.brand { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; }
.mark-sm { width: 26px; height: 26px; flex: none; }
.wordmark { font-weight: 700; font-size: 17px; letter-spacing: -0.02em; color: var(--gold); }
.wordmark span { color: var(--fg); font-weight: 500; }

.btn {
  font-family: var(--font-ui); font-size: 13.5px; font-weight: 600;
  border-radius: var(--r-btn); border: 1px solid transparent;
  padding: 9px 14px; cursor: pointer; color: var(--base);
  background: var(--gold); width: 100%;
  transition: filter 150ms ease, transform 160ms var(--ease-out), background 150ms ease;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.btn:hover { filter: brightness(1.06); }
.btn:active { transform: scale(0.97); }
.btn-ghost {
  background: transparent; color: var(--fg); border: 1px solid var(--line);
  width: auto; font-weight: 500;
}
.btn-ghost:hover { filter: none; background: var(--raise); }

.rail-scroll { flex: 1; overflow-y: auto; padding: 6px 10px 18px; }
.day-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--dim); padding: 16px 8px 6px; font-weight: 600;
}
.session {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: var(--r-input);
  cursor: pointer; color: var(--sub); font-size: 13px;
  transition: background 120ms ease;
}
.session:hover { background: var(--raise); }
.session.active { background: var(--raise); color: var(--fg); font-weight: 500; }
.session .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.dot.ready { background: var(--verified); }
.dot.err { background: var(--inferred); }
.dot.run { background: var(--gold); animation: pulse 1.6s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.3; } }


/* ---------- Report panel ---------- */
.report { background: var(--base); position: relative; }
.report-inner { max-width: 980px; margin: 0 auto; padding: 26px 40px 120px; }

.report-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; padding-bottom: 22px; border-bottom: 1px solid var(--line); }
.report-title { font-size: 20px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.3; }
.report-title b { color: var(--gold); font-weight: 600; }
.report-meta { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 10px; color: var(--sub); font-size: 12.5px; }
.report-meta .mono { color: var(--fg); }
.meta-sep { color: var(--line); }

section.block { padding: 30px 0; border-bottom: 1px solid var(--line); }
.kicker { /* used ONLY as a real section title, action sentence */ }
.sec-title { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; margin-bottom: 4px; }
.sec-sub { color: var(--sub); font-size: 13px; margin-bottom: 18px; max-width: 68ch; }
.badge-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }

/* Hero: headline + the call */
.hero { position: relative; padding: 34px 0 30px; border-bottom: 1px solid var(--line); }
.verdict-glow {
  position: absolute; top: 24px; left: -70px; width: 520px; height: 230px; pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(var(--gold-rgb),0.18), transparent 66%);
  animation: breathe 7s ease-in-out infinite; z-index: 0;
}
@keyframes breathe { 0%,100% { opacity: 0.6; transform: scale(1); } 50% { opacity: 1; transform: scale(1.05); } }
.hero > *:not(.verdict-glow) { position: relative; z-index: 1; }

.conf-chip {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600;
  padding: 4px 9px; border-radius: 999px; border: 1px solid;
}
.conf-medium { color: var(--inferred); border-color: rgba(var(--inferred-rgb),0.4); background: rgba(var(--inferred-rgb),0.08); }
.conf-high { color: var(--verified); border-color: rgba(var(--verified-rgb),0.4); background: rgba(var(--verified-rgb),0.08); }

.headline {
  font-size: 26px; line-height: 1.28; font-weight: 600; letter-spacing: -0.02em;
  margin: 14px 0 4px; text-wrap: balance; max-width: 24ch;
}
.headline .accent { color: var(--gold); }

.the-call { margin-top: 24px; }
.call-row { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.mode-chip {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600;
  padding: 4px 10px; border-radius: 999px;
  background: rgba(var(--gold-rgb),0.12); color: var(--gold); border: 1px solid rgba(var(--gold-rgb),0.3);
}
.call-verdict { font-size: 15px; color: var(--fg); max-width: 74ch; margin-bottom: 20px; }
.call-verdict b { font-weight: 600; }
.moves { display: flex; flex-direction: column; }
.move { display: grid; grid-template-columns: 30px 1fr; gap: 14px; padding: 16px 0; border-top: 1px solid var(--line); }
.move:first-child { border-top: none; }
.move-num { font-family: var(--font-mono); font-size: 15px; font-weight: 600; color: var(--gold); padding-top: 1px; }
.move-text { font-size: 14.5px; font-weight: 500; margin-bottom: 5px; line-height: 1.45; }
.move-why { font-size: 13px; color: var(--sub); line-height: 1.5; max-width: 76ch; }

/* ---------- Scoreboard (the moat) ---------- */
.scoreboard { }
.sov { margin-bottom: 28px; }
.sov-row { display: grid; grid-template-columns: 150px 1fr 56px; align-items: center; gap: 14px; padding: 7px 0; }
.sov-name { font-size: 13px; color: var(--sub); display: flex; align-items: center; gap: 8px; }
.sov-row.you .sov-name { color: var(--fg); font-weight: 600; }
.you-tag { font-size: 9.5px; font-weight: 700; letter-spacing: 0.05em; color: var(--base); background: var(--gold); padding: 1px 5px; border-radius: 4px; }
.sov-track { height: 12px; background: var(--raise); border-radius: 3px; overflow: hidden; }
.sov-fill { height: 100%; border-radius: 3px; background: linear-gradient(90deg, #55617d, var(--slate)); transition: width 600ms var(--ease-out); }
.sov-row.you .sov-fill { background: linear-gradient(90deg, var(--gold-deep), var(--gold)); box-shadow: 0 0 12px rgba(var(--gold-rgb),0.4); }
.sov-val { font-family: var(--font-mono); font-size: 13px; text-align: right; color: var(--fg); }

.matrix { width: 100%; border-collapse: collapse; margin-top: 4px; table-layout: fixed; }
.matrix th, .matrix td { text-align: right; padding: 12px 14px; border-bottom: 1px solid var(--line); }
.matrix thead th { font-size: 12px; font-weight: 600; color: var(--sub); border-bottom: 1px solid var(--line); }
.matrix th.axis, .matrix td.axis { text-align: left; width: 30%; }
.matrix td.axis { color: var(--fg); font-size: 13px; }
.matrix td.axis small { display: block; color: var(--dim); font-size: 11px; font-weight: 400; }
.col-you { background: rgba(var(--gold-rgb),0.05); }
th.col-you .colname { color: var(--gold); }
.colname { display: inline-flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 6px; }
.cell { position: relative; }
.cell-val { font-family: var(--font-mono); font-size: 13.5px; color: var(--fg); }
.cell.loss .cell-val { color: var(--sub); }
.cell-bar { height: 4px; border-radius: 2px; background: var(--slate); margin-top: 6px; margin-left: auto; }
.col-you .cell-bar { background: var(--gold); }
.cell.win .cell-val { color: var(--gold); font-weight: 600; }
.win-flag { font-size: 9px; color: var(--gold); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; display: block; margin-top: 3px; }

/* claim rows / proof */
.claims { display: flex; flex-direction: column; }
.claim { display: grid; grid-template-columns: 92px 1fr; gap: 14px; padding: 13px 0; border-top: 1px solid var(--line); align-items: start; }
.claim:first-child { border-top: none; }
.claim-text { font-size: 13.5px; line-height: 1.5; }
.claim-text .mono { color: var(--gold); font-size: 12.5px; }
.claim-src { font-size: 11.5px; color: var(--dim); margin-top: 5px; }
.claim-src a { color: var(--sub); text-decoration: underline; text-underline-offset: 2px; }
.stat {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 8px; border-radius: 999px;
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.03em; border: 1px solid; height: fit-content; white-space: nowrap;
}
.stat::before { content: ""; width: 6px; height: 6px; border-radius: 50%; }
.stat.verified { color: var(--verified); border-color: rgba(var(--verified-rgb),0.35); background: rgba(var(--verified-rgb),0.07); }
.stat.verified::before { background: var(--verified); }
.stat.inferred { color: var(--inferred); border-color: rgba(var(--inferred-rgb),0.35); background: rgba(var(--inferred-rgb),0.07); }
.stat.inferred::before { background: var(--inferred); }

.hypothesis {
  background: var(--raise); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 14px 16px; margin-bottom: 18px; font-size: 13.5px; color: var(--sub); line-height: 1.5;
}
.hypothesis b { color: var(--inferred); font-weight: 600; text-transform: uppercase; font-size: 11px; letter-spacing: 0.05em; margin-right: 8px; }

/* Fact-Impact-Act */
.fia { display: flex; flex-direction: column; }
.fia-item { padding: 16px 0; border-top: 1px solid var(--line); }
.fia-item:first-child { border-top: none; }
.fia-fact { font-size: 14px; font-weight: 500; line-height: 1.45; margin-bottom: 10px; display: flex; gap: 10px; align-items: baseline; }
.impact-chip { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; padding: 2px 7px; border-radius: 4px; flex: none; }
.impact-high { background: rgba(var(--threat-rgb),0.14); color: var(--threat); }
.impact-medium { background: rgba(var(--inferred-rgb),0.14); color: var(--inferred); }
.fia-line { display: grid; grid-template-columns: 60px 1fr; gap: 12px; font-size: 13px; color: var(--sub); padding: 3px 0; line-height: 1.5; }
.fia-line .lbl { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--dim); font-weight: 600; padding-top: 2px; }
.fia-line.act .lbl { color: var(--gold); }
.fia-line.act { color: var(--fg); }

/* status quo */
.sq-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; margin-bottom: 22px; }
.sq-h { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--fg); font-weight: 600; margin-bottom: 10px; }
.sq-list { list-style: none; display: flex; flex-direction: column; gap: 8px; }
.sq-list li { font-size: 13px; color: var(--sub); line-height: 1.45; padding-left: 16px; position: relative; }
.sq-list li::before { content: ""; position: absolute; left: 0; top: 8px; width: 5px; height: 5px; border-radius: 50%; background: var(--slate); }
.cost-inaction { background: rgba(var(--threat-rgb),0.06); border: 1px solid rgba(var(--threat-rgb),0.22); border-radius: var(--r-card); padding: 14px 16px; font-size: 13.5px; color: var(--fg); line-height: 1.5; }
.cost-inaction .badge-label { color: var(--threat); display: block; margin-bottom: 6px; }

/* SWOT tabs */
.tabs { display: flex; gap: 4px; margin-bottom: 20px; border-bottom: 1px solid var(--line); }
.tab {
  padding: 9px 15px; font-size: 13px; font-weight: 500; color: var(--sub); cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px; display: flex; align-items: center; gap: 8px;
  background: none; border-top: none; border-left: none; border-right: none; font-family: var(--font-ui);
  transition: color 180ms var(--ease-out), border-color 180ms var(--ease-out);
}
.tab .role { font-size: 9.5px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--dim); }
.tab.active { color: var(--fg); border-bottom-color: var(--gold); }
.tab.active .role { color: var(--gold); }
.swot-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; }
.swot-col-h { font-size: 12px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; margin-bottom: 8px; display: flex; align-items: center; gap: 8px; }
.swot-col-h.s { color: var(--verified); }
.swot-col-h.w { color: var(--threat); }

/* 90-day */
.play-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 30px; }
.play-h { font-size: 12.5px; font-weight: 600; margin-bottom: 12px; color: var(--gold); letter-spacing: 0.02em; }

/* frameworks */
.fw-strength { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 8px; }
.fw-brand { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-card); padding: 16px; }
.fw-brand.you { border-color: rgba(var(--gold-rgb),0.35); }
.fw-brand-name { font-size: 12.5px; font-weight: 600; margin-bottom: 2px; display: flex; align-items: center; gap: 7px; }
.fw-brand.you .fw-brand-name { color: var(--gold); }
.fw-overall { font-family: var(--font-mono); font-size: 26px; font-weight: 600; margin: 6px 0 12px; }
.fw-overall small { font-size: 13px; color: var(--dim); }
.fw-lens { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 11.5px; color: var(--sub); padding: 3px 0; }
.fw-meter { width: 54px; height: 4px; background: var(--raise); border-radius: 2px; overflow: hidden; }
.fw-meter i { display: block; height: 100%; background: var(--slate); border-radius: 2px; }
.fw-brand.you .fw-meter i { background: var(--gold); }
.fw-other { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
.fw-chip-row { display: flex; gap: 10px; flex-wrap: wrap; }
.fw-pill { font-size: 12px; color: var(--sub); border: 1px solid var(--line); border-radius: 999px; padding: 6px 13px; background: var(--panel); }
.fw-pill b { color: var(--fg); font-weight: 600; }
.fw-lens-r { display: flex; align-items: center; gap: 8px; }
.fw-lens-r b { font-family: var(--font-mono); font-size: 11px; color: var(--fg); width: 15px; text-align: right; font-weight: 600; }

/* info affordance (click to expand a definition) */
.info-i {
  display: inline-grid; place-items: center; width: 17px; height: 17px; border-radius: 50%;
  border: 1px solid rgba(var(--gold-rgb),0.5); color: var(--gold); background: rgba(var(--gold-rgb),0.1);
  font-size: 10px; font-style: normal; font-weight: 700; font-family: var(--font-ui); line-height: 1; padding: 0;
  cursor: pointer; margin-left: 8px; vertical-align: middle; user-select: none; transition: border-color 120ms ease, background 120ms ease; flex: none;
}
.info-i:hover { border-color: var(--gold); background: rgba(var(--gold-rgb),0.2); }
.def { display: none; background: var(--raise); border: 1px solid var(--line); border-radius: 8px; padding: 11px 13px; margin: 10px 0 0; font-size: 12.5px; color: var(--sub); line-height: 1.55; }
.def.open { display: block; }
.def b { color: var(--fg); font-weight: 600; }
.def dt { color: var(--fg); font-weight: 600; margin-top: 7px; }
.def dt:first-child { margin-top: 0; }
.def dd { margin: 0 0 4px; }
.so-what { font-size: 13px; color: var(--fg); background: rgba(var(--gold-rgb),0.06); border: 1px solid rgba(var(--gold-rgb),0.18); border-radius: 8px; padding: 12px 14px; margin-top: 16px; line-height: 1.5; }
.so-what b { color: var(--gold); text-transform: uppercase; font-size: 10.5px; letter-spacing: 0.05em; margin-right: 8px; }

/* framework sub-block */
.fw-section { margin-top: 30px; padding-top: 24px; border-top: 1px solid var(--line); }
.fw-h { font-size: 13.5px; font-weight: 600; margin-bottom: 4px; display: flex; align-items: center; }
.fw-desc { font-size: 12.5px; color: var(--sub); margin-bottom: 16px; max-width: 72ch; }

/* preference ladder */
.ladder { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; margin: 8px 0 2px; }
.rung { text-align: center; padding: 10px 6px 12px; border-radius: 8px; background: var(--panel); border: 1px solid var(--line); transition: border-color 200ms ease; }
.rung:not(:has(.pill-b)) .rung-label { color: var(--dim); }
.rung:has(.pill-b.you) { border-color: rgba(var(--gold-rgb),0.4); }
.rung-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--sub); font-weight: 600; }
.rung:has(.pill-b) .rung-label { color: var(--fg); }
.rung .brands { display: flex; flex-direction: column; gap: 5px; margin-top: 10px; min-height: 22px; }
.pill-b { font-size: 11.5px; padding: 4px 7px; border-radius: 5px; background: var(--raise); color: var(--fg); border: 1px solid var(--line); }
.pill-b.you { background: linear-gradient(180deg, var(--gold), var(--gold-deep)); color: var(--base); font-weight: 700; border: none; box-shadow: 0 0 12px rgba(var(--gold-rgb),0.4); }
.ladder-arrow { display: flex; justify-content: space-between; font-size: 10.5px; color: var(--dim); margin-top: 8px; padding: 0 2px; }

/* funnel + leak map */
.funnel { display: flex; flex-direction: column; }
.fstage { display: grid; grid-template-columns: 130px 1fr; gap: 16px; align-items: baseline; padding: 11px 0; border-top: 1px solid var(--line); }
.fstage:first-child { border-top: none; }
.fstage-name { font-size: 12.5px; font-weight: 600; display: flex; align-items: center; gap: 8px; color: var(--fg); }
.fstage.leak .fstage-name { color: var(--threat); }
.leak-flag { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--threat); background: rgba(var(--threat-rgb),0.14); padding: 2px 6px; border-radius: 4px; }
.fstage-note { font-size: 12.5px; color: var(--sub); line-height: 1.45; }

/* positioning teardown */
.pt-grid { display: grid; grid-template-columns: 175px 1fr; gap: 14px 16px; align-items: start; }
.pt-k {
  justify-self: start; align-self: start; font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--fg); font-weight: 600; background: var(--raise); border: 1px solid var(--line);
  border-radius: 6px; padding: 5px 10px; white-space: nowrap;
}
.pt-v { font-size: 13px; color: var(--fg); line-height: 1.5; padding-top: 3px; }

/* competitor positioning summaries (short, sit under the client's full teardown) */
.pos-rivals { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.pos-rival { display: grid; grid-template-columns: 130px 1fr; gap: 12px; align-items: baseline; padding: 10px 0; border-top: 1px solid var(--line); }
.pos-rival:first-of-type { border-top: 1px solid var(--line); }
.pos-rival-name { font-size: 12px; font-weight: 600; color: var(--fg); }
.pos-rival-sum { font-size: 12.5px; color: var(--sub); line-height: 1.5; }

/* verify-before-you-cite advisory */
.verify-lead { font-size: 13.5px; color: var(--fg); margin-bottom: 16px; }
.verify-lead b { color: var(--verified); font-weight: 600; }
.verify-item { display: grid; grid-template-columns: 150px 1fr; gap: 16px; padding: 13px 0; border-top: 1px solid var(--line); align-items: baseline; }
.verify-item:first-of-type { border-top: 1px solid var(--line); }
.verify-brand { font-size: 12.5px; font-weight: 600; color: var(--fg); }
.verify-brand .you-tag { margin-left: 6px; }
.verify-what { font-size: 13px; color: var(--sub); line-height: 1.5; }
.verify-what .tag { color: var(--inferred); font-weight: 600; }

/* trust grades */
.trust-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
.trust-card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-card); padding: 15px; display: flex; gap: 13px; align-items: flex-start; }
.grade-badge {
  width: 40px; height: 40px; border-radius: 9px; flex: none; display: grid; place-items: center;
  font-family: var(--font-mono); font-size: 20px; font-weight: 700; border: 1.5px solid;
}
.grade-B { color: var(--verified); border-color: rgba(var(--verified-rgb),0.5); background: rgba(var(--verified-rgb),0.08); }
.grade-C { color: var(--inferred); border-color: rgba(var(--inferred-rgb),0.5); background: rgba(var(--inferred-rgb),0.08); }
.grade-F { color: var(--threat); border-color: rgba(var(--threat-rgb),0.5); background: rgba(var(--threat-rgb),0.08); }
.trust-brand { font-size: 12.5px; font-weight: 600; margin-bottom: 3px; }
.trust-brand .you-tag { margin-left: 6px; }
.trust-sum { font-size: 11.5px; color: var(--sub); line-height: 1.4; }

/* notes */
.notes-list { display: flex; flex-direction: column; gap: 12px; }
.note-brand { font-size: 12.5px; font-weight: 600; margin-bottom: 5px; color: var(--sub); }
.note-line { font-size: 12.5px; color: var(--dim); font-family: var(--font-mono); padding: 2px 0; }
.note-line::before { content: "\203A "; color: var(--dim); }

/* export bar */
.pdf-note { font-size: 11.5px; color: var(--dim); margin-top: 6px; }

/* ---------- Chat panel ---------- */
.chat { background: var(--panel); border-left: 1px solid var(--line); display: flex; flex-direction: column; height: 100vh; }
.chat-head { padding: 16px 18px; border-bottom: 1px solid var(--line); display: flex; align-items: center; justify-content: space-between; }
.chat-title { font-size: 13.5px; font-weight: 600; }
.chat-title small { display: block; color: var(--dim); font-size: 11px; font-weight: 400; margin-top: 1px; }
.pin-btn { background: none; border: 1px solid var(--line); color: var(--sub); width: 28px; height: 28px; border-radius: 6px; cursor: pointer; font-size: 14px; display: grid; place-items: center; transition: background 150ms ease, color 150ms ease; }
.pin-btn:hover { background: var(--raise); color: var(--fg); }

.chat-scroll { flex: 1; overflow-y: auto; padding: 18px; display: flex; flex-direction: column; gap: 18px; }
.msg { max-width: 92%; }
.msg.user { align-self: flex-end; }
.msg.user .bubble { background: var(--raise); border-radius: 12px 12px 4px 12px; padding: 10px 13px; font-size: 13.5px; }
.msg.bot .bubble { background: transparent; font-size: 13.5px; line-height: 1.55; }
.msg-claims { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.msg-claim { display: flex; gap: 8px; align-items: flex-start; font-size: 12px; color: var(--sub); }
.stat.model { border-style: dashed; opacity: 0.95; }
.not-established { font-size: 11px; color: var(--dim); border: 1px dashed var(--line); border-radius: 6px; padding: 8px 10px; margin-top: 8px; }
.honesty-foot { font-size: 10.5px; color: var(--dim); margin-top: 8px; font-style: italic; }

.chips { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 18px 12px; }
.chip { font-size: 12px; color: var(--sub); border: 1px solid var(--line); border-radius: 999px; padding: 6px 12px; cursor: pointer; background: var(--base); transition: background 150ms ease, color 150ms ease; }
.chip:hover { background: var(--raise); color: var(--fg); }

.composer { border-top: 1px solid var(--line); padding: 14px; }
.composer-box { background: var(--raise); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; display: flex; gap: 10px; align-items: flex-end; transition: border-color 130ms ease, box-shadow 130ms ease; }
.composer-box:focus-within { border-color: rgba(var(--gold-rgb),0.6); box-shadow: 0 0 0 2px rgba(var(--gold-rgb),0.15); }
.composer-error { color: var(--inferred); font-size: 12px; margin-top: 8px; padding: 0 2px; }
.composer textarea { flex: 1; background: none; border: none; resize: none; color: var(--fg); font-family: var(--font-ui); font-size: 13.5px; line-height: 1.5; outline: none; max-height: 120px; }
.composer textarea::placeholder { color: var(--dim); }
.send-btn { width: 32px; height: 32px; border-radius: 7px; background: var(--gold); border: none; color: var(--base); cursor: pointer; flex: none; display: grid; place-items: center; font-size: 15px; transition: transform 160ms var(--ease-out), filter 150ms ease; }
.send-btn:hover { filter: brightness(1.06); }
.send-btn:active { transform: scale(0.94); }

.chat-collapsed-strip { display: none; }
.shell.chat-collapsed .chat { align-items: center; }
.shell.chat-collapsed .chat-head, .shell.chat-collapsed .chat-scroll, .shell.chat-collapsed .chips, .shell.chat-collapsed .composer { display: none; }
.shell.chat-collapsed .chat-collapsed-strip { display: flex; flex-direction: column; align-items: center; gap: 14px; padding-top: 16px; }
.collapsed-label { writing-mode: vertical-rl; font-size: 12px; color: var(--sub); letter-spacing: 0.04em; margin-top: 8px; }

/* --- review-gate fixes (already present in the workspace mockup) --- */
:focus-visible { outline: 2px solid rgba(var(--gold-rgb),0.75); outline-offset: 2px; border-radius: 4px; }
.claim-text, .pt-v, .fstage-note, .trust-sum, .verify-what, .move-why, .fia-line span:last-child, .sq-list li { max-width: 66ch; }

@media (prefers-reduced-motion: reduce) {
  .verdict-glow, .dot.run { animation: none; }
  * { transition: none !important; }
}

/*
 * ==========================================================================
 * Journey scenes, ported from docs/mockups/2026-07-06-vantage-v2-journey.html
 * append-only: only rules not already present above are included. The
 * `.orb` / `.mark-*` living-mark rules and the journey's own `.btn` and
 * `:focus-visible` (identical selectors already covered above) are
 * deliberately NOT repeated here.
 * ==========================================================================
 */

/* ---------- dev scene switcher ---------- */
.switcher {
  position: fixed; top: 16px; right: 16px; z-index: 100; display: flex; gap: 4px;
  background: rgba(16,20,28,0.9); border: 1px solid var(--line); border-radius: 10px; padding: 4px; backdrop-filter: blur(8px);
}
.switcher button {
  font-family: var(--font-ui); font-size: 12px; font-weight: 500; color: var(--sub);
  background: none; border: none; border-radius: 7px; padding: 7px 12px; cursor: pointer;
  transition: color 150ms ease, background 150ms ease;
}
.switcher button:hover { color: var(--fg); background: var(--raise); }
.switcher button.active { color: var(--base); background: var(--gold); font-weight: 600; }
.switcher .lbl { font-size: 10px; color: var(--dim); align-self: center; padding: 0 8px 0 6px; text-transform: uppercase; letter-spacing: 0.05em; }

.scene { position: fixed; inset: 0; display: none; z-index: 2; }
.scene.active { display: flex; }

/* ---------- Scene 1: brand entry ---------- */
#s-brand { flex-direction: column; align-items: center; justify-content: center; text-align: center; }
.wordmark-xl {
  font-size: 90px; font-weight: 700; letter-spacing: -.035em; line-height: .95;
  background: linear-gradient(180deg, #fff 30%, var(--gold-hi) 125%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; color: transparent;
  margin-top: 8vh;
}
.brand-kicker { font-size: 12px; text-transform: uppercase; letter-spacing: 0.28em; color: var(--sub); margin-top: 18px; }
.tagline { font-size: 22px; color: var(--fg); margin-top: 22px; font-weight: 500; }
.tagline .q { color: var(--gold); }
.subline { font-size: 15px; color: var(--sub); margin-top: 16px; max-width: 52ch; line-height: 1.55; }
.brand-cta { margin-top: 34px; }
.brand-foot { position: absolute; bottom: 26px; font-size: 12px; color: var(--dim); }

/* ---------- Scene 2: intake ---------- */
#s-intake { flex-direction: column; align-items: center; justify-content: flex-start; overflow-y: auto; padding: 15vh 24px 40px; }
.intake-head { text-align: center; margin-bottom: 34px; }
.intake-title { font-size: 26px; font-weight: 600; letter-spacing: -0.02em; }
.intake-sub { font-size: 14px; color: var(--sub); margin-top: 8px; }
.form { width: 560px; max-width: 100%; }
.field { margin-bottom: 20px; }
.field label { display: block; font-size: 12px; font-weight: 600; margin-bottom: 7px; color: var(--fg); }
.field label .req { color: var(--gold); margin-left: 2px; }
.field .help { font-size: 11.5px; color: var(--dim); margin-top: 6px; }
.input {
  width: 100%; background: var(--raise); border: 1px solid var(--line); border-radius: 8px;
  padding: 11px 13px; color: var(--fg); font-family: var(--font-ui); font-size: 14px; outline: none;
  transition: border-color 130ms ease, box-shadow 130ms ease;
}
.input.mono { font-family: var(--font-mono); }
.input::placeholder { color: var(--dim); }
.input:focus { border-color: rgba(var(--gold-rgb),0.7); box-shadow: 0 0 0 2px rgba(var(--gold-rgb),0.16); }
textarea.input { resize: vertical; min-height: 74px; line-height: 1.5; }
.row2 { display: grid; grid-template-columns: 1fr 160px; gap: 14px; }
.comp-row { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; }
.comp-row .idx { font-family: var(--font-mono); font-size: 12px; color: var(--dim); width: 16px; flex: none; }
.comp-row .input { flex: 1; }
.add-comp { font-size: 12.5px; color: var(--gold); background: none; border: none; cursor: pointer; padding: 4px 0; font-family: var(--font-ui); font-weight: 500; }
.run-block { margin-top: 30px; padding-top: 24px; border-top: 1px solid var(--line); text-align: center; }
.spend { font-size: 12.5px; color: var(--sub); margin-top: 12px; }
.spend b { color: var(--fg); font-weight: 600; }

/* ---------- Scene 3: research running ---------- */
#s-research { flex-direction: column; align-items: center; justify-content: center; text-align: center; padding-top: 14vh; }
.gerund { font-family: var(--font-mono); font-size: 22px; font-weight: 500; color: var(--gold); margin-top: 10px; height: 30px; letter-spacing: 0.01em; }
.gerund::after { content: "..."; color: var(--gold-deep); }
.run-status { font-size: 13px; color: var(--sub); margin-top: 6px; }
.run-status .mono { color: var(--fg); }
.log {
  margin-top: 30px; width: 620px; max-width: 100%; text-align: left;
  background: rgba(16,20,28,0.5); border: 1px solid var(--line); border-radius: 12px; padding: 16px 18px;
  height: 210px; overflow: hidden; position: relative;
}
.log-line {
  font-family: var(--font-mono); font-size: 12.5px; color: var(--sub); line-height: 1.7;
  display: flex; gap: 10px; align-items: baseline; opacity: 0; transform: translateY(6px);
  animation: logIn 400ms var(--eo) forwards;
}
.log-line .tick { color: var(--verified); flex: none; }
.log-line .run-i { color: var(--gold); flex: none; animation: spin 1s linear infinite; display: inline-block; }
@keyframes logIn { to { opacity: 1; transform: translateY(0); } }
@keyframes spin { to { transform: rotate(360deg); } }
.research-foot { font-size: 12px; color: var(--dim); margin-top: 22px; }

/* journey-only reduced-motion additions (the .orb/.mark-*/.log-line-run-i
   animation cut and the .orb transition cut already live in app.css's own
   reduced-motion block; only the .log-line entrance state is new here) */
@media (prefers-reduced-motion: reduce) {
  .log-line .run-i { animation: none; }
  .log-line { opacity: 1; transform: none; animation: none; }
}

/*
 * ==========================================================================
 * Responsive breakpoints (added 2026-07-07 after the v2 render-check smoke).
 * The desktop shell (260px rail / report / 380px chat) squeezed the report
 * column on narrower or display-scaled desktops: a 150%-scaled 1080p panel
 * reports a ~1008px CSS viewport, which truncated report content. These rules
 * are append-only. One rule (the framework-grid reflow) is global and fixes a
 * wide-screen bug; the rest are inside breakpoints and only adapt below the
 * wide layout. The side-by-side report+chat signature is preserved at every
 * width. All values follow the existing spacing scale.
 * ==========================================================================
 */

/* Reflow the fixed four-up framework grids with auto-fit so the actual number
   of brands fits exactly, with no phantom empty column that overflows (the
   confirmed .fw-strength 26px overflow at 1280px with 3 brands), and so they
   drop to fewer columns as the report narrows. The 150px floor keeps the full
   four-brand set four-across on common laptop widths (down to ~1366px), the
   same as the original repeat(4, 1fr); auto-fit never emits more tracks than
   there are cards, so the empty-phantom overflow is gone regardless. */
.fw-strength,
.trust-row { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

@media (max-width: 1200px) {
  /* Trim the rail and chat so the report keeps a workable width. Chat stays
     visible (the side-by-side signature); the manual pin still collapses it.
     The collapsed grid gets the same trimmed rail, so collapsing the chat at a
     narrow width never widens the rail. */
  .shell:not(.chat-collapsed) { grid-template-columns: 224px minmax(0, 1fr) 312px; }
  .shell.chat-collapsed { grid-template-columns: 224px minmax(0, 1fr) 52px; }
  /* Contain the decorative verdict glow (position:absolute, 520px wide, bleeds
     left by design) to the hero box once the hero narrows, so its soft edge
     can never trigger a horizontal scrollbar. The wide-screen bleed is
     untouched above this breakpoint. */
  .hero { overflow-x: clip; }
}

@media (max-width: 1120px) {
  /* Stack the two-up sections so their fixed-label sub-grids never truncate. */
  .sq-grid,
  .swot-grid,
  .play-grid { grid-template-columns: 1fr; }
  /* Let the SWOT brand tabs scroll horizontally instead of overflowing. Scroll
     (not wrap) keeps them on one row so the active tab's gold underline stays
     on the shared bottom-border baseline. */
  .tabs { overflow-x: auto; }
  .tabs::-webkit-scrollbar { height: 0; }
  /* Keep the preference ladder's five rungs left-to-right (the curve metaphor)
     but let each rung shrink rather than overflow; trim the rung padding and
     label size a touch so the single-word stage labels still fit. */
  .ladder { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .rung { padding-left: 3px; padding-right: 3px; }
  .rung-label { font-size: 9.5px; letter-spacing: 0.02em; }
}

/*
 * ==========================================================================
 * Chat provenance tiers (added for the v2 chat rebuild, chatV2.js). Ported
 * from docs/mockups/2026-07-07-vantage-v2-chat-bubble.html. Append-only: none
 * of the rules below touch the existing .stat / .stat.model / .honesty-foot
 * block (line ~234 and ~409) or the report's own .claim-src / .research-foot
 * rules (line ~232 and ~534), which are unrelated components that happen to
 * reuse these class names. Every new rule here is scoped under .msg-claim or
 * .msg.bot so it only ever applies inside a chat bubble.
 * ==========================================================================
 */
/* report reuses the existing outlined .stat.model look in slate; researched
   is verified-green; reasoning is inferred-amber. Sizing/shape come from the
   shared .stat rule above; only the colour is new here. */
.stat.report { color: var(--slate); border-color: rgba(var(--slate-rgb),0.45); }
.stat.report::before { background: var(--slate); }
.stat.researched { color: var(--verified); border-color: rgba(var(--verified-rgb),0.40); background: rgba(var(--verified-rgb),0.06); }
.stat.researched::before { background: var(--verified); }
.stat.reasoning { color: var(--inferred); border-color: rgba(var(--inferred-rgb),0.40); background: rgba(var(--inferred-rgb),0.06); }
.stat.reasoning::before { background: var(--inferred); }

/* The live source link on a researched claim, scoped to the chat so it never
   touches the report's own (unrelated) .claim-src div/anchor styling. */
.msg-claim a.claim-src { color: var(--gold); text-decoration: none; border-bottom: 1px solid rgba(var(--gold-rgb),0.35); margin-left: 5px; white-space: nowrap; font-size: 12px; margin-top: 0; }
.msg-claim a.claim-src:hover { border-bottom-color: var(--gold); }
.msg-claim a.claim-src .host { color: var(--dim); font-family: var(--font-mono); font-size: 11px; margin-left: 4px; }

/* The per-turn research footnotes, scoped to a chat bubble so they never
   touch the unrelated .research-foot rule used on the running scene. */
.msg.bot .research-foot { font-size: 11px; color: var(--verified); margin-top: 8px; }
.msg.bot .research-foot.empty { color: var(--dim); }

/*
 * ==========================================================================
 * Task 8 review-fix wave (chat only). Append-only: every rule below is a
 * later same-specificity or more-specific override of an existing chat rule
 * above, nothing here is edited or deleted from the original block.
 * ==========================================================================
 */
/* A long researched-claim link must wrap inside the narrow chat column
   instead of forcing horizontal scroll. */
.msg-claim { flex-wrap: wrap; }
.msg-claim > span { min-width: 0; overflow-wrap: anywhere; }
.msg-claim a.claim-src { overflow-wrap: anywhere; white-space: normal; }
.chat-scroll { overflow-x: hidden; }
/* AA contrast fix for the "from the report" badge text; the slate dot and
   border stay as they were. */
.stat.report { color: var(--sub); }
/* A claim badge must never get squeezed by a long wrapping link next to it. */
.msg-claim .stat { flex: none; }
/* A touch more readable than the italic 10.5px base note. */
.msg.bot .honesty-foot { font-size: 11px; }

/* Live ad creatives link-outs (2026-07-13 paid-ads signal build). Append-only. */
.adlib-rows { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.adlib-row { display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap; }
.adlib-brand { min-width: 200px; font-weight: 600; }
.adlib-links { display: flex; gap: 18px; flex-wrap: wrap; }
.adlib-note { margin-top: 12px; font-size: 12px; color: var(--dim); }

.adlib-links a { color: var(--sub); text-decoration: none; border-bottom: 1px solid var(--line); }
.adlib-links a:hover { color: var(--gold); border-bottom-color: var(--gold); }

/* Verified-advertiser presence label (2026-07-23 paid-ads reframe). A muted
   sibling of the brand name; deliberately carries no number, ever. */
.adlib-advertiser { font-size: 12px; color: var(--dim); }

/* Ad creatives is a utility strip, not an analytic section: step its title down
   from the 15px/600 analytic-section weight to a quieter, muted label. */
.sec-title-utility { font-size: 13px; font-weight: 500; color: var(--sub); }

/* Rail nav (2026-07-13): the wordmark is now a real <button> (goes home); reset
   button chrome so it renders exactly like the old plain <div> did. app.css's
   .wm rule already sets the flex layout, gap, weight, size and color. */
.wm {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
}

/* Sign-out link pinned to the bottom of the rail (.rail is a flex column,
   see the .rail rule above), muted until hovered. */
.rail-signout {
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--dim);
  font-size: 12px;
  font-family: inherit;
  text-align: left;
  margin-top: auto;
  padding: 10px 2px 2px;
  transition: color 150ms ease;
}
.rail-signout:hover {
  color: var(--sub);
}

/* ---------- Intake: market country select (append-only, task: intake country dropdown) ----------
   select.input needs a couple of rules .input alone does not cover: killing the
   native OS chrome so it matches the text inputs, room for a custom arrow, and a
   muted color for the disabled placeholder option. */
select.input {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238791a5' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 13px center;
  padding-right: 34px;
  cursor: pointer;
}
select.input option {
  background: var(--raise);
  color: var(--fg);
}
select.input option:disabled {
  color: var(--dim);
}

/* Your question, answered (queryAnswers.js) */
.qa-item { margin-top: 18px; }
.qa-q { font-family: "JetBrains Mono", monospace; font-weight: 600; font-size: 13px; color: var(--gold); margin-bottom: 6px; }
.qa-a { margin: 0 0 10px; }

/* Print actions (workspaceV2.js task 7): Download PDF sits above the report
   hero as its own thin bar, and Export chat sits in the chat head next to
   the collapse pin; both a quiet gold-outline treatment, values copied from
   the existing .info-i affordance rather than invented. */
.report-actions { display: flex; justify-content: flex-end; padding: 14px 40px 0; }
.print-btn, .export-chat-btn {
  font-family: var(--font-ui); font-size: 12px; font-weight: 600;
  border-radius: 6px; border: 1px solid rgba(var(--gold-rgb),0.5); color: var(--gold);
  background: rgba(var(--gold-rgb),0.1); padding: 7px 13px; cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease;
}
.print-btn:hover, .export-chat-btn:hover { border-color: var(--gold); background: rgba(var(--gold-rgb),0.2); }

/* ================================================================
 * Public intake page (/vantage/start), Task 11. Ported from
 * docs/mockups/2026-07-18-vantage-pricing-surfaces.html SCREEN 1 (the
 * approved public intake + gate design). New selectors are scoped under
 * .start-scene / .gate-modal where the class name (e.g. .intake-card,
 * .intake-title, .intake-sub) already exists at top level elsewhere in this
 * file for the signed-in app's own intake form (Scene 2 above): scoping
 * keeps this page's rules from leaking onto that one. .honest-line,
 * .sample-link, .gate-modal, .modal, .modal-h, .modal-sub, .consent, and
 * .sent-state are new names with no existing collision, so they stay
 * top-level like the rest of this file's component idioms.
 * ================================================================ */
.start-scene {
  min-height: 100vh; display: flex; flex-direction: column;
  position: relative; overflow-y: auto; padding: 26px 0 0;
}
.start-glow {
  position: absolute; top: 110px; left: 50%; width: 620px; height: 300px;
  transform: translateX(-50%); pointer-events: none; z-index: 0;
  background: radial-gradient(ellipse at center, rgba(var(--gold-rgb),0.13), transparent 68%);
  animation: breathe 7s ease-in-out infinite;
}
.start-top { padding: 0 40px; position: relative; z-index: 1; }
.start-body {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  justify-content: center; padding: 40px 24px 60px; position: relative; z-index: 1;
}
.start-scene .intake-card {
  position: relative; width: 560px; max-width: 100%;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-answer);
  box-shadow: var(--shadow-card); padding: 32px 34px 28px;
}
.start-scene .intake-title {
  font-size: 26px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.25;
  text-wrap: balance; margin-bottom: 8px; margin-top: 0;
}
.start-scene .intake-sub { font-size: 13.5px; color: var(--sub); margin-top: 0; margin-bottom: 26px; max-width: 46ch; }
.start-scene .run-block { margin-top: 24px; padding-top: 22px; border-top: 1px solid var(--line); text-align: center; }
.honest-line { font-size: 12.5px; color: var(--sub); text-align: center; margin-top: 12px; }
.sample-link {
  display: inline-block; position: relative; z-index: 1; margin-top: 22px; font-size: 13px; color: var(--dim);
  text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line);
  transition: color 140ms ease;
}
.sample-link:hover { color: var(--gold); text-decoration-color: rgba(var(--gold-rgb),0.5); }

/* the resumed / started / error states after the round trip (start.js's boot(), not under test) */
.started-body {
  flex: 1; display: flex; align-items: center; justify-content: center;
  padding: 40px 24px; position: relative; z-index: 1;
}
.started-body .btn {
  width: auto; padding: 11px 22px; margin-top: 18px; display: inline-flex; text-decoration: none;
}
.resuming-line { font-size: 14px; color: var(--sub); text-align: center; }

/* ---------- the email gate modal ---------- */
.gate-modal {
  position: fixed; inset: 0; z-index: 20;
  display: flex; align-items: center; justify-content: center;
  background: rgba(5,7,10,0.72); padding: 24px;
}
.gate-modal .modal {
  position: relative; width: 400px; max-width: 100%;
  background: var(--base); border: 1px solid var(--line); border-radius: var(--r-answer);
  box-shadow: var(--shadow-card); padding: 24px 24px 22px;
}
.modal-h { font-size: 17px; font-weight: 600; letter-spacing: -0.015em; margin-bottom: 6px; }
.modal-sub { font-size: 12.5px; color: var(--sub); margin-bottom: 20px; line-height: 1.5; }
.consent { font-size: 11.5px; color: var(--dim); margin-top: 12px; line-height: 1.5; text-align: center; }
.consent a { color: var(--sub); text-decoration: underline; text-underline-offset: 2px; }
.sent-state {
  display: flex; gap: 12px; align-items: flex-start;
  background: rgba(var(--verified-rgb),0.06); border: 1px solid rgba(var(--verified-rgb),0.24);
  border-radius: var(--r-card); padding: 14px 15px;
}
.sent-state .tick { color: var(--verified); font-size: 15px; line-height: 1.3; flex: none; }
.sent-state .txt { font-size: 13px; color: var(--fg); line-height: 1.5; }
.sent-state .txt small { display: block; color: var(--sub); font-size: 12px; margin-top: 4px; }

@media (prefers-reduced-motion: reduce) {
  .start-glow { animation: none; }
}
.export-chat-btn { font-size: 11px; padding: 5px 10px; flex: none; }

/* ================================================================
 * Task 11 fix wave 1. APPEND-ONLY, per this file's convention: nothing
 * above is edited, these later rules win by cascade order and specificity.
 * ================================================================ */

/* The glow was drawn 310px off centre. .start-glow sets
 * transform: translateX(-50%), but @keyframes breathe (line 164) animates
 * transform: scale(...) only, so for the whole animation the centring is
 * overwritten. breathe is shared with .verdict-glow and must not change, so
 * this is its own keyframe that carries the offset through every step. The
 * reduced-motion rule is repeated after it because the original one sits
 * ABOVE this block and would otherwise be re-enabled by it. */
@keyframes startGlowBreathe {
  0%, 100% { opacity: 0.6; transform: translateX(-50%) scale(1); }
  50% { opacity: 1; transform: translateX(-50%) scale(1.05); }
}
.start-glow { animation: startGlowBreathe 7s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .start-glow { animation: none; }
}

/* The header logo lockup had no rules at all, so app.css's global
 * .mark { width: 54px; height: 54px } won and the wordmark hung off the
 * mark's bottom-right. Ported from the approved mockup (lines 110 to 111)
 * and scoped to .start-scene so no other surface moves. */
.start-scene .wordmark-lock { display: inline-flex; align-items: center; gap: 10px; }
.start-scene .wordmark-lock .mark { width: 26px; height: 26px; }

/* The confirmation line above Run, shown only when the form was prefilled
 * from a carried intake: what this click is about to cost. */
.start-scene .run-cost-note {
  font-size: 12.5px; color: var(--fg); text-align: center; margin: 0 0 14px;
  padding: 9px 12px; border-radius: var(--r-card);
  background: rgba(var(--gold-rgb), 0.08);
  border: 1px solid rgba(var(--gold-rgb), 0.24);
}

/* ================================================================
 * Task 11 fix wave 3 (real-browser UX audit). APPEND-ONLY, same convention
 * as wave 1: nothing above is edited, and every rule is SCOPED so no other
 * surface moves. Three shipped bugs on this page have all come from cascade
 * collisions, so each rule below names the rule it is correcting.
 *
 * The gate modal lives inside #gate-host, which is inside .start-scene, so
 * .start-scene reaches the modal too even though .gate-modal is position:fixed.
 * ================================================================ */

/* The primary CTA was 10 percent short. The approved mockup's page-local .btn
 * is padding: 11px 16px (41px tall); the live page inherits v2.css:103 .btn at
 * 9px 14px (37px). On a page whose whole job is one click, the approved
 * proportion wins. Scoped, so every other .btn in the app is untouched. */
/* Targeted by id, not by `.start-scene .btn`: that class-scoped form also won
 * over `.started-body .btn` (v2.css:784, same specificity but earlier), which
 * silently reshaped the "Go to Vantage" and "Try again" buttons on the started
 * and error screens. Ids hit exactly the two buttons this rule is about. */
#s-run, #gate-send { padding: 11px 16px; }

/* Four fields, two different shapes. app.css:112 `.field input, .field textarea`
 * (specificity 0-0-1-1) beats v2.css:496 `.input` (0-0-1-0) and forces 6px
 * radius / 12px 14px padding on the three text inputs, but it does not match
 * <select>, so #s-country kept .input's 8px / 11px 13px. The mockup is a
 * uniform 8px / 11px 13px. This rule matches app.css's specificity and wins on
 * order, restoring the approved shape without editing anything shared. */
.start-scene .field input,
.start-scene .field textarea {
  border-radius: 8px;
  padding: 11px 13px;
}

/* Two focus treatments inside one form: app.css:125 gives the inputs a 3px
 * @0.22 ring with a solid gold border, v2.css:503 gives the select 2px @0.16
 * with rgba(gold,.7). The mockup uses the softer one throughout. */
.start-scene .field input:focus,
.start-scene .field textarea:focus {
  border-color: rgba(var(--gold-rgb), 0.7);
  box-shadow: 0 0 0 2px rgba(var(--gold-rgb), 0.16);
}

/* v2.css:492 .field is 20px, the approved mockup is 18px, which made the card
 * 14px taller than approved across the four fields. */
.start-scene .field { margin-bottom: 18px; }

/* v2.css:504 textarea.input is min-height 74px, the mockup's natural box is
 * 66px for the same two rows. */
.start-scene textarea.input { min-height: 66px; }

/* The sent state's "Done" button: a real keyboard exit from the gate (it had
 * none, a WCAG 2.1.2 trap). Utility weight, so it never competes with the
 * primary action the person has already taken. */
.gate-actions { margin-top: 16px; text-align: center; }
.gate-actions .btn { width: auto; padding: 8px 20px; }

/* Height, the last part of the same inconsistency. With radius and padding
 * corrected the four fields still stood at three different heights, because
 * their content boxes were sized by "normal" line-height and the two URL
 * fields are JetBrains Mono (v2.css:501 .input.mono, deliberate for URLs)
 * while the select and textarea are Space Grotesk. Mono is 2.7px shorter at
 * 14px, so the typeface was silently setting the field height.
 *
 * The approved mockup shows a uniform 42px. It reaches that by accident (its
 * .mono rule at line 79 is overridden by its own .input at line 138, so its
 * URL fields are not actually mono), which is not a behaviour to copy: mono
 * URLs are a real convention of this app. Pinning line-height instead makes
 * the height independent of the typeface, so all three single-line controls
 * measure 42px (11 + 11 padding, 1 + 1 border, 18 line) and keep their fonts.
 * The textarea is excluded: its 1.5 line-height sets the spacing of real
 * wrapped text, not a box height. */
.start-scene .field input,
.start-scene .field select {
  line-height: 18px;
}

/* ================================================================
 * THE PAYWALL (Task 12), ported from the approved mockup
 * docs/mockups/2026-07-18-vantage-pricing-surfaces.html screen 2.
 *
 * APPEND-ONLY, like every block above it. Two deliberate departures from the
 * mockup, both because the mockup draws a standalone full-page screen while
 * the real paywall lives in the rail shell's main column (.answer-col):
 *   1. The mockup's .pay-bar (wordmark plus back link) is dropped. The rail
 *      already carries the wordmark and the navigation, so repeating them
 *      would put two Vantage marks on one screen. Only the back control
 *      survives, as .pay-topline.
 *   2. .pay-body is a flex column with min-height 100%, which is what lets
 *      the mockup's `.honest { margin-top: auto }` still push the honest
 *      lines to the foot of a tall screen inside a scrolling column.
 *
 * Every class name below was grepped against tokens.css, app.css and v2.css
 * first; all were unused. Two shared rules DO reach this markup and are
 * corrected here rather than edited at source (the Task 11 lesson):
 *   - v2.css .btn-ghost sets width:auto, which the mockup's .btn-ghost does
 *     not. Left alone, the Solo card's ghost Buy button renders as a small
 *     auto-width button beside Full's full-width one, breaking the symmetry
 *     of the two cards.
 *   - v2.css .rail-signout has margin-top:auto to pin it to the foot of the
 *     rail. A second auto margin above it would split the free space between
 *     the two controls instead of keeping them together.
 * ================================================================ */

.pay-body {
  display: flex; flex-direction: column; min-height: 100%;
  padding: 24px 44px 28px;
}
.pay-topline { display: flex; justify-content: flex-end; margin-bottom: 10px; }
.pay-back {
  background: none; border: 0; cursor: pointer; font-family: inherit;
  font-size: 12.5px; color: var(--dim); padding: 4px 2px;
  transition: color 150ms ease;
}
.pay-back:hover { color: var(--sub); }

.pay-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 30px; }
.pay-title { font-size: 26px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.25; margin: 0; }
.pay-sub { font-size: 13.5px; color: var(--sub); margin-top: 8px; max-width: 60ch; }
/* Quiet by design: the refused-free-run line and the balance-unavailable line
   are facts, not warnings, and neither is the customer's doing. */
.pay-note { font-size: 12.5px; color: var(--dim); margin-top: 10px; max-width: 62ch; line-height: 1.5; }
.pay-error { font-size: 12.5px; color: var(--threat); margin-top: 16px; }
.pay-right { display: flex; flex-direction: column; align-items: flex-end; gap: 12px; flex: none; }

.wallet {
  display: inline-flex; align-items: baseline; gap: 9px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 999px; padding: 8px 16px;
}
.wallet .lbl { font-size: 11.5px; color: var(--sub); }
.wallet .val { font-family: var(--font-mono); font-size: 15px; font-weight: 600; color: var(--gold); }

.cur-toggle { display: inline-flex; background: var(--raise); border: 1px solid var(--line); border-radius: 999px; padding: 3px; }
.cur-toggle button {
  font-family: var(--font-ui); font-size: 12px; font-weight: 600; color: var(--sub);
  background: none; border: none; border-radius: 999px; padding: 5px 15px; cursor: pointer;
  transition: color 150ms ease, background 150ms ease;
}
.cur-toggle button.on { color: var(--base); background: var(--gold); }

/* A quiet factual note, not a warning. Amber means "inferred" in this design
   system, so it must never be used for checkout availability. */
.intl-note { font-size: 11.5px; color: var(--dim); text-align: right; max-width: 34ch; line-height: 1.5; }

/* run sizes: the primary decision, given real weight */
.runs { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; margin-top: 22px; }
.run-card {
  position: relative; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 24px 24px 22px;
  transition: border-color 180ms var(--ease-out);
}
.run-card:hover { border-color: rgba(var(--gold-rgb),0.32); }
.run-card.lead { border-color: rgba(var(--gold-rgb),0.38); background: linear-gradient(180deg, rgba(var(--gold-rgb),0.05), var(--panel) 62%); }
.run-flag {
  position: absolute; top: -1px; right: 20px;
  font-size: 9.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--base); background: var(--gold); padding: 3px 9px; border-radius: 0 0 5px 5px;
}
.run-name { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.run-what { font-size: 12.5px; color: var(--sub); margin-top: 4px; min-height: 19px; }
.price-row { display: flex; align-items: baseline; gap: 10px; margin: 18px 0 4px; }
.price { font-family: var(--font-mono); font-size: 30px; font-weight: 600; letter-spacing: -0.02em; }
.run-card.lead .price { color: var(--gold); }
.credits { font-size: 12.5px; color: var(--dim); }
.run-list { list-style: none; display: flex; flex-direction: column; gap: 7px; margin: 16px 0 20px; padding: 0; }
.run-list li { font-size: 12.5px; color: var(--sub); padding-left: 17px; position: relative; line-height: 1.45; }
.run-list li::before {
  content: ""; position: absolute; left: 0; top: 7px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--slate);
}
.run-card.lead .run-list li::before { background: var(--gold-deep); }

/* The correction named in the block comment: the mockup's buy buttons are all
   full width. v2.css:113 .btn-ghost narrows them to auto. Scoped to the
   paywall, so no other ghost button in the app moves. */
.pay-body .run-card .btn,
.pay-body .pack .btn { width: 100%; }

/* packs: a quieter strip, deliberately NOT a second identical card grid */
.packs { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line); }
.packs-h { font-size: 12px; font-weight: 600; color: var(--fg); letter-spacing: 0.01em; margin-bottom: 4px; }
.packs-sub { font-size: 12.5px; color: var(--dim); margin-bottom: 16px; }
.pack-rows { display: flex; flex-direction: column; }
.pack {
  display: grid; grid-template-columns: 210px 1fr 140px 108px;
  align-items: center; gap: 20px; padding: 13px 0; border-top: 1px solid var(--line);
}
.pack:first-child { border-top: none; }
.pack-n { font-family: var(--font-mono); font-size: 15px; font-weight: 600; color: var(--fg); }
.pack-n small { display: block; font-family: var(--font-ui); font-size: 11.5px; font-weight: 400; color: var(--dim); }
.pack-save { font-size: 12.5px; color: var(--verified); }
.pack-price { font-family: var(--font-mono); font-size: 17px; font-weight: 600; text-align: right; }
.pack .btn { padding: 8px 14px; font-size: 12.5px; }

/* the honest lines */
.honest {
  margin-top: auto; padding-top: 24px;
  display: flex; align-items: flex-end; justify-content: space-between; gap: 30px;
}
.honest-list { list-style: none; display: flex; gap: 28px; margin: 0; padding: 0; flex-wrap: wrap; }
.honest-list li { font-size: 12.5px; color: var(--sub); padding-left: 17px; position: relative; }
.honest-list li::before {
  content: ""; position: absolute; left: 0; top: 7px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--verified);
}
.tax-line { font-size: 11.5px; color: var(--dim); flex: none; }

/* the wait between "paid" and "credited" (the webhook gap) */
.pay-waiting { align-items: center; justify-content: center; }
.pay-waiting-card { text-align: center; max-width: 46ch; }
.pay-waiting-card .pay-sub { margin-left: auto; margin-right: auto; }
.pay-body .pay-refresh { width: auto; margin-top: 18px; padding: 9px 20px; }

/* The rail's way into the paywall, pinned above Sign out. .rail-signout keeps
   its own margin-top:auto for every surface that has no Buy control; this
   zeroes it only when the two sit together, so the pair stays at the foot of
   the rail instead of splitting the free space between them. */
.rail-buy {
  background: none; border: 0; cursor: pointer; color: var(--dim);
  font-size: 12px; font-family: inherit; text-align: left;
  margin-top: auto; padding: 10px 2px 2px;
  transition: color 150ms ease;
}
.rail-buy:hover { color: var(--gold); }
.rail-buy + .rail-signout { margin-top: 0; }

/* Below laptop widths the two run cards and the four-column pack rows stop
   fitting side by side, the same reflow the framework grids above already do. */
@media (max-width: 1240px) {
  .pay-body { padding: 20px 28px 24px; }
  .runs { grid-template-columns: 1fr; }
  .pack { grid-template-columns: 1fr 120px 100px; }
  .pack-save { display: none; }
  .pay-head { flex-direction: column; gap: 16px; }
  .pay-right { align-items: flex-start; }
  .intl-note { text-align: left; }
  .honest { flex-direction: column; align-items: flex-start; gap: 12px; }
  .honest-list { flex-direction: column; gap: 8px; }
}

/* Task 12 fix wave. The paid-and-still-here confirmation, and the paid-then-walked-away toast. */
.pay-ok { font-size: 12.5px; color: var(--verified); margin-top: 10px; max-width: 62ch; line-height: 1.5; }
/*
 * Task 12 fix wave 5. The toasts used to pin themselves to the bottom right of
 * the viewport, which is exactly where the chat composer sits on the only screen
 * a toast can ever appear on. The browser audit measured a toast covering the
 * whole send button, so a person trying to send a chat message hit Dismiss
 * instead, and two real payments landed on identical pixels so one of them was
 * invisible. The toasts now live in this stack at the bottom LEFT of the
 * workspace column, and stack upwards visibly.
 *
 * The left offset tracks the rail rather than being a single hardcoded number,
 * because the rail is 260px on the workspace shell, 248px on the two-column
 * rail shell, and 224px on the shell below 1200px. --rail-w carries the widest
 * rail in play at each width, so the stack always begins clear of every one of
 * them. The width is capped well short of the chat column (380px, or 312px
 * below 1200px) so the stack cannot reach it either.
 *
 * pointer-events on the container is none, with auto restored on each toast, so
 * the empty stack can never sit invisibly over anything clickable.
 */
:root { --rail-w: 260px; }
/* Below 1200px the workspace rail trims to 224px but the two-column rail shell
   stays at 248px, so 248px is the widest rail in play here and the one the
   stack has to clear. */
@media (max-width: 1200px) { :root { --rail-w: 248px; } }
.pay-toast-stack {
  position: fixed; left: calc(var(--rail-w) + 24px); bottom: 24px; z-index: 60;
  display: flex; flex-direction: column; gap: 10px;
  max-width: min(420px, 32vw);
  pointer-events: none;
}
.pay-toast {
  pointer-events: auto;
  display: flex; align-items: center; gap: 14px;
  padding: 13px 16px;
  background: var(--panel); border: 1px solid rgba(var(--verified-rgb),0.34); border-radius: 10px;
  box-shadow: 0 14px 34px rgba(0,0,0,0.44);
  font-size: 12.5px; color: var(--fg); line-height: 1.5;
}
.pay-toast button {
  flex: none; background: none; border: none; cursor: pointer;
  font-family: inherit; font-size: 12.5px; color: var(--gold);
  padding: 0; text-decoration: underline; text-underline-offset: 3px;
}
.pay-toast button:hover { color: var(--fg); }
.pay-toast .pay-toast-x { color: var(--dim); text-decoration: none; }
.pay-toast .pay-toast-x:hover { color: var(--sub); }

/*
 * Task 12 fix wave 5, the honest disabled state. .btn carries no :disabled rule
 * of its own, so a genuinely dead Buy button rendered at full opacity with a
 * pointer cursor and a full gold fill, pixel-identical to a working one. Scoped
 * to the paywall's own buy controls rather than every .btn in the app, because
 * the other disabled buttons on other screens are not this wave's business.
 */
.pay-body [data-sku] button:disabled {
  opacity: 0.42;
  cursor: not-allowed;
  filter: none;
  transform: none;
}
.pay-body [data-sku] button:disabled:hover { filter: none; }
.pay-body [data-sku] .btn-ghost:disabled:hover { background: transparent; }
/* The reason, next to the control it applies to. The corner note explains the currency, but someone looking at a dead button needs the answer where they are looking. */
.pay-why { font-size: 11.5px; color: var(--dim); margin-top: 9px; line-height: 1.5; }

/*
 * The balance on the waiting screen is the most actionable fact there (it is
 * the one thing that can contradict a wrong "still not in"), so it is boxed and
 * carries slightly more weight than the reassurance lines around it, which are
 * all --dim body copy at 12.5px.
 */
.pay-balance {
  display: flex; flex-direction: column; gap: 3px;
  margin-top: 14px; padding: 11px 14px; max-width: 62ch;
  background: var(--raise); border: 1px solid var(--line); border-radius: 8px;
}
.pay-balance-num { font-size: 14px; font-weight: 600; color: var(--fg); }

/*
 * Task 13: the free-lane PDF upgrade bar. Sits in the same .report-actions
 * slot the Download PDF button would otherwise take (v2.css:726), so it
 * inherits that bar's flex/justify-end/padding; this just lays out its own
 * note-plus-button pair. Deliberately quiet, matching the gold-outline
 * weight already used for .print-btn/.export-chat-btn rather than a loud
 * paywall interrupting someone reading their free report.
 */
.pdf-upgrade { display: flex; align-items: center; gap: 12px; }
.pdf-upgrade-note { font-size: 12px; color: var(--sub); }
.pdf-upgrade-btn { font-size: 12px; padding: 7px 13px; }

/*
 * Task 13: the free-lane chat research cap footnote. A fixed, always-visible
 * note (not a toggle like .def above it), same quiet box treatment.
 */
.cap-foot {
  background: var(--raise); border: 1px solid var(--line); border-radius: 8px;
  padding: 9px 13px; margin: 10px 18px 0; font-size: 12px; color: var(--sub); line-height: 1.5;
}
/* .cap-foot did not exist when the collapsed-chat hide-list (v2.css:432) was
   written, so it is added here as its own rule (append-only) rather than
   editing that list: left visible, a full-width note would not fit the thin
   collapsed strip and would look broken rather than quiet. */
.shell.chat-collapsed .cap-foot { display: none; }
.pay-balance-note { font-size: 12px; color: var(--dim); line-height: 1.5; }

/* ================================================================
 * Public sample report (/vantage/sample), Task 14, spec 5.5. Ported from the
 * approved mockup (docs/mockups/2026-07-18-vantage-pricing-surfaces.html,
 * screen 3 "SCREEN 3: frost-gated sample", roughly lines 331 to 402): .frost,
 * .frost-veil, .frost-copy, .frost-lead, and the CSS-drawn placeholder bars
 * (.ph-field, .ph, .ph-cards, .ph-card).
 *
 * ONE DELIBERATE ADAPTATION from the mockup, worth stating plainly: the
 * mockup is a fixed-height showcase frame, so it pins .frost with
 * position:absolute at the bottom of a clipped, overflow:hidden .samp-scroll,
 * overlapping the tail of the real content to make it look continuous. This
 * page is a real, unbounded document, and there is nothing to clip: the
 * anonymous payload is server-side truncated (sampleVisible,
 * src/services/sampleReport.ts), so nothing real exists below the hero and
 * scoreboard to hide. .frost is therefore an ordinary block that follows them
 * in normal document flow, at a fixed height, with the same three visual
 * layers (blurred placeholder bars, then the dark gradient veil, then the
 * centred CTA copy) achieved with position:absolute INSIDE .frost itself. The
 * rule the brief cares about, "the frost band sits over decorative
 * placeholder bars only, never over real content", holds either way: here it
 * holds trivially, because there is no real content in the DOM to sit over.
 *
 * .wordmark, .wordmark span, .btn, .btn-ghost, .field, .input, .field-error
 * and .consent are pre-existing top-level rules elsewhere in this file and
 * are reused unscoped and unmodified.
 * ================================================================ */
.sample-scene { min-height: 100vh; display: flex; flex-direction: column; background: var(--base); }
.samp-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 44px; border-bottom: 1px solid var(--line); flex: none;
}
.samp-head-r { display: flex; align-items: center; gap: 14px; }
/* .wordmark-lock itself carries no unscoped rule elsewhere in this file (the
   only existing one is scoped to .start-scene), so it is scoped here the same
   way, rather than left bare: an unscoped .mark elsewhere in app.css defaults
   to 54px, which is exactly the oversized-logo bug the 2026-07-19 handoff
   already paid for once. */
.samp-head .wordmark-lock { display: inline-flex; align-items: center; gap: 10px; }
.samp-head .wordmark-lock .mark { width: 26px; height: 26px; }
.samp-head .btn-ghost { width: auto; padding: 8px 16px; font-size: 12.5px; }
.samp-tag {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.07em; font-weight: 600;
  color: var(--gold); background: rgba(var(--gold-rgb),0.1);
  border: 1px solid rgba(var(--gold-rgb),0.3); border-radius: 999px; padding: 4px 11px;
}
.samp-scroll { flex: 1; padding-bottom: 40px; }
.samp-inner { max-width: 900px; margin: 0 auto; padding: 26px 44px 0; }

/* --- the gate. Placeholder geometry only, never real content. --- */
.frost { position: relative; height: 348px; max-width: 900px; margin: 10px auto 0; overflow: hidden; }
.ph-field {
  position: absolute; inset: 0; padding: 30px 44px 0;
  display: flex; flex-direction: column; gap: 11px;
  filter: blur(5px); opacity: 0.5;
}
.ph { height: 11px; border-radius: 3px; background: var(--raise); }
.ph.t { height: 15px; background: #263042; width: 34%; margin-bottom: 6px; }
.ph.w90 { width: 90%; } .ph.w76 { width: 76%; } .ph.w84 { width: 84%; }
.ph.w62 { width: 62%; } .ph.w70 { width: 70%; } .ph.w48 { width: 48%; }
.ph-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-top: 8px; }
.ph-card { height: 76px; border-radius: var(--r-card); background: var(--panel); border: 1px solid var(--line); }

.frost-veil {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(10,12,17,0) 0%, rgba(10,12,17,0.42) 20%, rgba(10,12,17,0.86) 42%, rgba(10,12,17,0.98) 60%, var(--base) 74%);
}
.frost-copy {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 0 40px 24px;
}
.frost-lead { font-size: 15.5px; color: var(--fg); max-width: 62ch; line-height: 1.6; margin: 0 0 18px; text-wrap: balance; }
.frost-lead b { color: var(--gold); font-weight: 600; }
.frost-field { width: 320px; max-width: 100%; margin: 0 0 12px; }
.frost-cta { width: auto; padding: 12px 26px; font-size: 14px; }
.frost-sub { font-size: 12.5px; color: var(--sub); margin-top: 12px; }

/* ================================================================
 * Task 15: the signup consent line under the login send button
 * (public/vantage/login.js). Quiet legal microcopy, matching the same
 * treatment already approved for the intake gate modal in the mockup.
 * ================================================================ */
.consent-line { font-size: 11.5px; color: var(--dim); margin-top: 14px; line-height: 1.5; text-align: center; }
.consent-line a { color: var(--sub); text-decoration: underline; text-underline-offset: 2px; }

/* ================================================================
 * Task 15: the "How to read this report" link inside .report-actions
 * (public/vantage/workspaceV2.js). It sits beside whichever real action is
 * already there (Download PDF when entitled, the upgrade bar otherwise),
 * so it only needs its own left margin; .report-actions itself is an
 * existing rule (display:flex, no gap) and stays untouched.
 * ================================================================ */
.report-actions .guide-link {
  font-size: 12px; padding: 7px 13px; margin-left: 12px;
  display: inline-flex; align-items: center; text-decoration: none;
}

/* ================================================================
 * The public "how to read this report" guide (/vantage/guide, Task 15,
 * spec 5.8). Static, anonymous, one-screen layout ported from the approved
 * mockup's screen 4 (docs/mockups/2026-07-18-vantage-pricing-surfaces.html),
 * using this file's own tokens rather than the mockup's self-contained
 * copies of them.
 * ================================================================ */
.guide-scene { min-height: 100vh; background: var(--base); padding: 40px 56px 60px; }
.guide-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 30px;
  max-width: 1100px; margin: 0 auto; padding-bottom: 22px; border-bottom: 1px solid var(--line);
}
.guide-head .wordmark-lock { display: inline-flex; align-items: center; gap: 10px; flex: none; }
.guide-head .wordmark-lock .mark { width: 26px; height: 26px; }
.guide-title { font-size: 26px; font-weight: 600; letter-spacing: -0.02em; }
.guide-sub { font-size: 14px; color: var(--sub); margin-top: 8px; max-width: 62ch; line-height: 1.55; }

.guide-grid {
  max-width: 1100px; margin: 0 auto; display: grid; grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--line); border-top: none;
}
.guide-block { border-right: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 24px 26px; }
.guide-block:nth-child(3n) { border-right: none; }
.guide-block:nth-child(n+4) { border-bottom: none; }
.guide-block-n { font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--gold); margin-bottom: 10px; }
.guide-block-p { font-size: 13px; color: var(--sub); line-height: 1.6; }
.guide-block-p strong { color: var(--fg); font-weight: 600; }

.guide-foot { max-width: 1100px; margin: 30px auto 0; text-align: center; }
.guide-close { font-size: 14px; color: var(--sub); }
.guide-close a { color: var(--gold); text-decoration: underline; text-underline-offset: 2px; }

/* ---------- Sample page scroll + matchup line (2026-07-21, append-only) ----------
   v2.css locks body overflow for the app shell (three columns, each with its
   own internal scroll), and /vantage/sample inherits that lock. The
   placeholder sample fit one viewport so the Task 14 render check never saw
   it; the real GIVA report does not fit, so the page must scroll INSIDE
   .samp-scroll, with the top bar staying put. */
.sample-scene { height: 100vh; }
.samp-scroll { overflow-y: auto; }
.samp-scroll::-webkit-scrollbar { width: 10px; }
.samp-scroll::-webkit-scrollbar-thumb { background: var(--line); border-radius: 8px; border: 2px solid var(--base); }

/* Which websites this report analysed: shown to both anonymous and signed-in
   visitors, above the executive summary. */
.samp-matchup {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--sub);
  margin: 18px 0 6px;
  line-height: 1.7;
}
.samp-matchup .samp-vs { color: var(--gold); font-weight: 600; }
.samp-matchup .samp-domain { color: var(--dim); }
.samp-matchup-wrap { padding-bottom: 0; }

/* ================================================================
 * 2026-07-22, the measure system (presentation wave, spec section 3.6)
 *
 * The problem this fixes, measured on the live sample at 1440px inside an
 * 812px column: .samp-matchup rendered at 812px, .headline at 403px,
 * .call-verdict at 712px, .move-why at 550px and .sec-title at 812px. Five
 * different right edges stacked vertically. Every one of those caps is
 * reasonable typography on its own. Together they read as unfinished.
 *
 * One measure for all running prose. The hero headline is deliberately exempt,
 * because a display line is MEANT to be short and reads as intentional rather
 * than ragged. Tables, the scoreboard and structural elements keep the full
 * column, because they are not prose.
 *
 * Append-only: nothing above this banner is edited.
 * ================================================================ */

:root { --measure: 72ch; }

/* BOTH wrappers, deliberately. The signed-in report renders inside
   .report-inner, and the public sample renders inside .samp-inner. The
   measurements that motivated this whole rule (812 / 403 / 712 / 550 / 812)
   were taken on the LOCKED SAMPLE, which never enters .report-inner at all, so
   scoping this to .report-inner alone would leave the exact page the evidence
   came from unfixed. */
.report-inner .call-verdict, .samp-inner .call-verdict,
.report-inner .move-why, .samp-inner .move-why,
.report-inner .sec-sub, .samp-inner .sec-sub,
.report-inner .fw-desc,
.report-inner .claim-text,
.report-inner .pt-v,
.report-inner .fstage-note,
.report-inner .trust-sum,
.report-inner .verify-what,
.report-inner .verify-lead,
.report-inner .sq-list li,
.report-inner .fia-line span:last-child,
.report-inner .dec-list li, .samp-inner .dec-list li,
.report-inner .dec-sb-head, .samp-inner .dec-sb-head,
.report-inner .acc-body p,
.report-inner .acc-body li,
.samp-matchup {
  max-width: var(--measure);
}

/* The display line keeps its short, deliberate measure. */
.report-inner .headline, .samp-inner .headline { max-width: 24ch; }

/* Structural surfaces are not prose and keep the column. */
.report-inner .matrix, .samp-inner .matrix,
.report-inner .sov, .samp-inner .sov,
.report-inner .adlib-rows { max-width: none; }

/* ================================================================
 * 2026-07-22, the decision page and the accordion (spec sections 3.1, 3.2)
 * Append-only.
 * ================================================================ */

.decision-page { padding-bottom: 8px; }

.dec-sb-head {
  font-size: 14px; color: var(--sub); line-height: 1.6;
  margin: 22px 0 0; max-width: var(--measure);
}

.decision-cols {
  display: grid; grid-template-columns: 1fr 1fr; gap: 28px; margin-top: 26px;
}

.dec-block { min-width: 0; }

.dec-h {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.07em;
  font-weight: 600; color: var(--sub); margin-bottom: 10px;
}

.dec-list { margin: 0; padding-left: 18px; }
.dec-list li { font-size: 13.5px; color: var(--fg); line-height: 1.6; margin-bottom: 7px; }
.dec-wins .dec-list li::marker { color: var(--verified); }
.dec-risks .dec-list li::marker { color: var(--threat); }
.dec-actions { margin-top: 26px; }
.dec-actions .dec-list li::marker { color: var(--gold); }

/* --- the accordion --- */

.acc { border-top: 1px solid var(--line); }
.acc:last-child { border-bottom: 1px solid var(--line); }
.acc-h { margin: 0; font-size: inherit; font-weight: inherit; }

.acc-toggle {
  width: 100%; display: flex; align-items: center; gap: 16px;
  background: none; border: none; padding: 18px 2px; cursor: pointer;
  text-align: left; color: var(--fg); font-family: var(--font-ui);
}
.acc-toggle:hover .acc-title { color: var(--gold); }

.acc-title { font-size: 15px; font-weight: 600; letter-spacing: -0.01em; flex: none; }

.acc-summary {
  font-family: var(--font-mono); font-size: 12.5px; color: var(--sub);
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.acc-chevron {
  flex: none; width: 8px; height: 8px; border-right: 1.5px solid var(--dim);
  border-bottom: 1.5px solid var(--dim); transform: rotate(-45deg);
  transition: transform 140ms ease; margin-right: 4px;
}
.acc.open .acc-chevron { transform: rotate(45deg); }

.acc-body { padding-bottom: 8px; }
.acc-body > div > section.block:last-child,
.acc-body > section.block:last-child { border-bottom: none; }

@media (prefers-reduced-motion: reduce) {
  .acc-chevron { transition: none; }
}

/* --- the share-of-voice caveat --- */

.sov-caveat {
  font-size: 12.5px; color: var(--dim); line-height: 1.55;
  margin: 14px 0 0; max-width: var(--measure);
}

/* The ChatGPT United States coverage note, same treatment as the caveat. */
.ai-note {
  font-size: 12.5px; color: var(--dim); line-height: 1.55;
  margin: 14px 0 0; max-width: var(--measure);
}

/* ================================================================
 * 2026-07-22, mobile for the public pages only (spec section 3.7)
 *
 * Scope: /vantage/sample, /vantage/start, /vantage/guide. These are the three
 * pages a stranger meets from a shared link, and the sample link is about to be
 * shared widely. The signed-in workspace stays desktop-only by design.
 *
 * Structural first: the page must scroll NATIVELY. The desktop layout locks the
 * body and scrolls inside .samp-scroll, which on a phone fights the browser's
 * own scrolling, momentum and address bar, and 100vh is unreliable on mobile
 * Safari because the bar collapses.
 *
 * Append-only.
 * ================================================================ */

@media (max-width: 768px) {
  /* 1. Native scrolling. */
  body:has(#app[data-page="sample"]),
  body:has(#app[data-page="start"]),
  body:has(#app[data-page="guide"]) { overflow: auto; }

  .sample-scene { height: auto; min-height: 100svh; }
  .samp-scroll { overflow-y: visible; }

  /* 2. The header stops wrapping. */
  .samp-head { flex-wrap: wrap; gap: 10px; padding: 14px 18px; }
  .samp-head-r { gap: 10px; }
  .samp-tag { font-size: 9.5px; padding: 3px 9px; }
  .samp-head .btn-ghost { padding: 7px 12px; font-size: 12px; white-space: nowrap; }

  /* 3. Column padding suited to a phone. */
  .samp-inner { padding: 20px 18px 0; }
  .report-inner { padding: 20px 18px 80px; }

  /* 4. The share-of-voice bar keeps usable width. The desktop grid gives the
     track 58px at this size, which stops the bar communicating anything. */
  .sov-row { grid-template-columns: minmax(0, 1fr) 56px; grid-template-areas: "name val" "track track"; row-gap: 6px; }
  .sov-name { grid-area: name; min-width: 0; }
  .sov-val { grid-area: val; }
  .sov-track { grid-area: track; }

  /* 5. The frost gate sizes to its content instead of a locked 348px. */
  .frost { height: auto; min-height: 300px; }
  .ph-field { position: relative; padding: 24px 18px 0; }
  .ph-cards { grid-template-columns: repeat(2, 1fr); }
  .frost-copy { position: relative; padding: 18px 18px 24px; }

  /* 6. Prose measure is the column at this width. */
  :root { --measure: 100%; }

  /* 7. The accordion row stacks its summary under its title rather than
     truncating it to nothing. */
  .acc-toggle { flex-wrap: wrap; gap: 4px 12px; padding: 15px 2px; }
  .acc-title { flex: 1 1 auto; }
  .acc-summary { flex: 1 0 100%; white-space: normal; }

  /* 8. The decision page columns stack. */
  .decision-cols { grid-template-columns: 1fr; gap: 22px; }

  /* 9. Tables scroll inside their own box rather than pushing the page wide. */
  .matrix { display: block; overflow-x: auto; }

  /* 10. The guide page's own rigid 3-column grid (found by the real-browser
     check this task requires, not in the brief's list): at 56px of scene
     padding and 3 fixed columns, the page produced genuine horizontal
     overflow with each column only around 92px wide, unreadable. One column
     and phone-sized padding, matching the treatment already given to the
     sample page's own columns above. */
  .guide-scene { padding: 32px 18px 40px; }
  .guide-grid { grid-template-columns: 1fr; }
  .guide-block { border-right: none; border-bottom: 1px solid var(--line); padding: 20px 18px; }
  .guide-block:last-child { border-bottom: none; }
}

/* ================================================================
 * 2026-07-22 (part 2), narrowing the block directly above to the three
 * pages it was written for. Independent review of commit c543d5f.
 *
 * The block above this banner fires at max-width: 768px and was scoped by
 * the task to /vantage/sample, /vantage/start and /vantage/guide only (the
 * three pages a stranger meets from a shared link); the signed-in workspace
 * (data-page="app") is binding scope to stay desktop-only and unchanged.
 * Rule 1 in that block is correctly gated on body:has(#app[data-page="..."]),
 * and rules 2, 3 (its .samp-inner half) and 5 are safe because .samp-*,
 * .sample-scene, .frost* and .ph-* are authored only by sample.js. But five
 * of its rules are BARE, so they also apply to the workspace, whose shell
 * has no min-width lockout stopping a window narrowing below 768px:
 *   - the share-of-voice bar (.sov-row/.sov-name/.sov-val/.sov-track, also
 *     authored by scoreboard.js)
 *   - the global prose measure (:root { --measure: 100%; }), which reaches
 *     every surface, not only the public pages
 *   - the accordion row (.acc-toggle/.acc-title/.acc-summary, also authored
 *     by accordion.js)
 *   - the decision-page columns (.decision-cols, also authored by
 *     execSummary.js)
 *   - the matrix table (.matrix, also authored by aiVisibility.js and
 *     scoreboard.js)
 * A sixth, .report-inner (rule 3's other half, "column padding suited to a
 * phone"), was found the same way and is the same class of bug: it is not
 * sample.js's own class, it is authored by deepReport.js and reused by the
 * signed-in workspace (workspaceV2.js's report zone renders
 * renderDeepReport, confirmed by reading both files), so it is included in
 * this fix even though it is not one of the five named above.
 *
 * v2.css is append-only, so none of those bare rules can be edited or
 * removed. This block instead does two things, both still inside
 * max-width: 768px so nothing here reaches desktop:
 *   1. Repeats each affected property gated behind the same three-page
 *      selector rule 1 above already uses, so the public pages keep the
 *      exact mobile behaviour that already shipped, unchanged.
 *   2. Adds a fourth gated selector, body:has(#app[data-page="app"]), that
 *      restores each property to its desktop value. Every desktop value below
 *      was read from this file, not guessed; the exact line is named beside
 *      it. The gated selectors are more specific than the bare rules above
 *      regardless of source order, so they win on their own merit; the
 *      workspace selectors additionally do not depend on winning a
 *      specificity fight with :root at all, because :root only ever matches
 *      the html element, and body:has(#app[data-page="app"]) sets --measure
 *      on the body element directly, which the whole app subtree inherits
 *      from.
 *
 * Append-only: nothing above this banner is edited.
 * ================================================================ */

@media (max-width: 768px) {
  /* Share-of-voice bar. Public pages: identical repeat of rule 4 above.
     Workspace: restored to the desktop grid (v2.css:200, 200-207). */
  body:has(#app[data-page="sample"]) .sov-row,
  body:has(#app[data-page="start"]) .sov-row,
  body:has(#app[data-page="guide"]) .sov-row {
    grid-template-columns: minmax(0, 1fr) 56px;
    grid-template-areas: "name val" "track track";
    row-gap: 6px;
  }
  body:has(#app[data-page="sample"]) .sov-name,
  body:has(#app[data-page="start"]) .sov-name,
  body:has(#app[data-page="guide"]) .sov-name { grid-area: name; min-width: 0; }
  body:has(#app[data-page="sample"]) .sov-val,
  body:has(#app[data-page="start"]) .sov-val,
  body:has(#app[data-page="guide"]) .sov-val { grid-area: val; }
  body:has(#app[data-page="sample"]) .sov-track,
  body:has(#app[data-page="start"]) .sov-track,
  body:has(#app[data-page="guide"]) .sov-track { grid-area: track; }

  body:has(#app[data-page="app"]) .sov-row {
    grid-template-columns: 150px 1fr 56px;
    grid-template-areas: none;
    row-gap: 14px;
  }
  body:has(#app[data-page="app"]) .sov-name,
  body:has(#app[data-page="app"]) .sov-val,
  body:has(#app[data-page="app"]) .sov-track { grid-area: auto; }

  /* Item 4, final review: the block above restores grid-area on .sov-name
     but was missing min-width, the one other property the mobile rule (4,
     v2.css:1523) sets on that same selector. A signed-in window narrowing
     below 768px kept the mobile min-width: 0 instead of the initial auto.
     Appended as its own rule rather than edited into the one above, since
     v2.css is append-only. */
  body:has(#app[data-page="app"]) .sov-name { min-width: auto; }

  /* Global prose measure. Public pages: identical repeat of rule 6 above.
     Workspace: held at its desktop 72ch (v2.css:1372). */
  body:has(#app[data-page="sample"]),
  body:has(#app[data-page="start"]),
  body:has(#app[data-page="guide"]) { --measure: 100%; }

  body:has(#app[data-page="app"]) { --measure: 72ch; }

  /* .report-inner column padding: the sixth rule this fix adds, see the
     banner above. Public pages: identical repeat of rule 3's second
     declaration above. Workspace: restored to its desktop padding
     (v2.css:142). */
  body:has(#app[data-page="sample"]) .report-inner,
  body:has(#app[data-page="start"]) .report-inner,
  body:has(#app[data-page="guide"]) .report-inner { padding: 20px 18px 80px; }

  body:has(#app[data-page="app"]) .report-inner { padding: 26px 40px 120px; }

  /* Accordion row. Public pages: identical repeat of rule 7 above.
     Workspace: restored to its desktop row shape (v2.css:1444-1455). */
  body:has(#app[data-page="sample"]) .acc-toggle,
  body:has(#app[data-page="start"]) .acc-toggle,
  body:has(#app[data-page="guide"]) .acc-toggle { flex-wrap: wrap; gap: 4px 12px; padding: 15px 2px; }
  body:has(#app[data-page="sample"]) .acc-title,
  body:has(#app[data-page="start"]) .acc-title,
  body:has(#app[data-page="guide"]) .acc-title { flex: 1 1 auto; }
  body:has(#app[data-page="sample"]) .acc-summary,
  body:has(#app[data-page="start"]) .acc-summary,
  body:has(#app[data-page="guide"]) .acc-summary { flex: 1 0 100%; white-space: normal; }

  body:has(#app[data-page="app"]) .acc-toggle { flex-wrap: nowrap; gap: 16px; padding: 18px 2px; }
  body:has(#app[data-page="app"]) .acc-title { flex: none; }
  body:has(#app[data-page="app"]) .acc-summary { flex: 1; white-space: nowrap; }

  /* Decision-page columns. Public pages: identical repeat of rule 8 above.
     Workspace: restored to its desktop two-up grid (v2.css:1420-1422). */
  body:has(#app[data-page="sample"]) .decision-cols,
  body:has(#app[data-page="start"]) .decision-cols,
  body:has(#app[data-page="guide"]) .decision-cols { grid-template-columns: 1fr; gap: 22px; }

  body:has(#app[data-page="app"]) .decision-cols { grid-template-columns: 1fr 1fr; gap: 28px; }

  /* Matrix table. Public pages: identical repeat of rule 9 above.
     Workspace: restored to its desktop table display (v2.css:209). */
  body:has(#app[data-page="sample"]) .matrix,
  body:has(#app[data-page="start"]) .matrix,
  body:has(#app[data-page="guide"]) .matrix { display: block; overflow-x: auto; }

  body:has(#app[data-page="app"]) .matrix { display: table; overflow-x: visible; }
}

/* Task B3: who-else-shows-up chip lists (whoElse.js). Subtle, matching the
   existing .fw-pill / .chip look: rounded, --panel background, --sub text. */
.whoelse-group { margin-bottom: 16px; }
.whoelse-group:last-child { margin-bottom: 0; }
.whoelse-h { font-size: 12px; font-weight: 600; color: var(--sub); margin-bottom: 8px; }
.whoelse-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.whoelse-chip { font-size: 12px; color: var(--sub); background: var(--panel); border: 1px solid var(--line); border-radius: 999px; padding: 6px 13px; }

/* Comparative SWOT (2026-07-23, C1/C2): ONE client-centric SWOT, four quadrant
   columns, no brand tabs. Reuses the .swot-col-h.s (green) / .w accents and
   adds .o (gold, opportunities) and .t (amber, threats) to match the semantic
   palette. Append-only: none of the rules above are touched. */
.swot-quadrants { display: grid; grid-template-columns: 1fr 1fr; gap: 30px 40px; }
.swot-quadrant { min-width: 0; }
.swot-col-h.o { color: var(--gold); }
.swot-col-h.t { color: var(--inferred); }
.swot-sub { font-size: 10px; font-weight: 500; text-transform: none; letter-spacing: 0.01em; color: var(--dim); }

@media (max-width: 1120px) {
  /* Reflow the four quadrants to one column below the two-up breakpoint. */
  .swot-quadrants { grid-template-columns: 1fr; }
}

/* Fix 3 (2026-07-23): a scoreboard cell with no measured value reads as an
   explicit absence, never a blank cell that could be mistaken for a zero.
   Muted, smaller and italic so "no coverage" is visibly not a value. */
.cell-empty { color: var(--sub); font-size: 12px; font-style: italic; }

/* Sample disclaimer (2026-07-23): the public sample is an illustrative report
   built from public data, not a client engagement. This line makes that
   explicit and carries the AI disclosure, so the page is safe to share. */
.samp-disclaimer {
  max-width: 72ch;
  margin: 8px auto 0;
  padding: 0 20px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--dim);
  text-align: center;
}

/* Task F2 (2026-07-25): the decision memo (decisionMemo.js) and the
   one-clear-move section (oneClearMove.js). The memo table reuses .matrix
   (class="matrix memo-table" on the <table>) for its borders and rhythm,
   overriding only the text alignment, since move text reads left, not
   right like a scoreboard number. .hypothesis, .badge-label, .fia-line,
   .lbl, .act, .dec-h, .dec-list, .block, .sec-title, .sec-sub and .headline
   are all reused as-is, deliberately: new sections inherit the approved
   look rather than inventing a second visual language. */
.memo { padding: 34px 0 30px; border-bottom: 1px solid var(--line); }
.memo-head { margin-bottom: 22px; }
.memo-head .headline { margin: 6px 0 0; max-width: 34ch; }

.memo-adv {
  background: var(--raise); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 16px 18px; margin-bottom: 22px;
}
.memo-adv-sub { font-size: 12.5px; color: var(--sub); margin: 0 0 10px; }
.memo-adv-head { font-size: 14.5px; font-weight: 600; color: var(--gold); margin: 0 0 6px; }

.memo-market { font-size: 13.5px; color: var(--sub); line-height: 1.6; max-width: 78ch; margin-bottom: 24px; }
.memo-market b { color: var(--fg); font-weight: 600; }

.memo-table td, .memo-table th { text-align: left; }
.memo-table th:first-child, .memo-table td:first-child { width: 34px; }
.memo-table th:nth-child(3), .memo-table td:nth-child(3),
.memo-table th:nth-child(4), .memo-table td:nth-child(4) { width: 76px; }
.memo-table th:last-child, .memo-table td:last-child { width: 150px; }
.memo-rank { font-family: var(--font-mono); font-size: 14px; font-weight: 600; color: var(--gold); }

/* Three bands that read without colour: solid / dashed / dotted border plus
   the band's own word in the DOM (HIGH / MEDIUM / LOW), so a colour-blind
   reader and a greyscale print both still tell them apart. */
.memo-band {
  display: inline-flex; align-items: center; font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em; padding: 3px 10px; border-radius: 999px;
  border: 1.5px solid;
}
.memo-band-high { color: var(--verified); border-color: rgba(var(--verified-rgb),0.5); background: rgba(var(--verified-rgb),0.1); }
.memo-band-medium { color: var(--inferred); border-style: dashed; border-color: rgba(var(--inferred-rgb),0.5); background: rgba(var(--inferred-rgb),0.1); }
.memo-band-low { color: var(--threat); border-style: dotted; border-color: rgba(var(--threat-rgb),0.5); background: rgba(var(--threat-rgb),0.08); }

.memo-drivers-row { margin-top: 8px; }
.memo-drivers { margin: 0; padding-left: 16px; }
.memo-drivers li { font-size: 12px; color: var(--dim); line-height: 1.5; margin-bottom: 3px; }
.memo-band-note { font-size: 11.5px; color: var(--dim); margin-top: 10px; max-width: 68ch; }

.memo-not { margin-top: 26px; }
.memo-not .dec-list li b { color: var(--fg); font-weight: 600; }

.memo-cost {
  margin-top: 26px; background: rgba(var(--threat-rgb),0.06); border: 1px solid rgba(var(--threat-rgb),0.22);
  border-radius: var(--r-card); padding: 14px 16px; font-size: 13.5px; color: var(--fg); line-height: 1.5;
}
.memo-cost .badge-label { color: var(--threat); display: block; margin-bottom: 6px; }
.memo-cost p { margin-top: 4px; }

.move-full .move-assume,
.move-full .move-contra { margin-top: 16px; }
.move-assume, .move-contra {
  background: var(--raise); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 14px 16px; font-size: 13.5px; color: var(--fg); line-height: 1.5;
}
.move-contra { border-color: rgba(var(--threat-rgb),0.3); background: rgba(var(--threat-rgb),0.06); }
.move-assume .badge-label, .move-contra .badge-label { display: block; margin-bottom: 6px; }
.move-contra .badge-label { color: var(--threat); }
.move-test { margin-top: 20px; }
/* The rationale is the one bare <p> oneClearMove.js emits directly under
   .move-full (the site-wide * { margin: 0 } reset otherwise leaves it
   flush against .move-assume above it). */
.move-full > p { margin: 16px 0; font-size: 13.5px; color: var(--sub); line-height: 1.6; max-width: 76ch; }

/* Task F2 fix wave (2026-07-25). Nothing above this banner is edited; these
   rules only override specific properties the block above already sets. */

/* Fix 5: `.move-full > p` above also captures oneClearMove.js's own
   `<p class="sec-sub">` subtitle (a direct child of .move-full), knocking it
   from 13px/18px-bottom/no-top-margin down to 13.5px with a phantom 16px top
   margin. This more specific rule (two classes plus the element beats one
   class plus the element) restores .sec-sub's own approved size and spacing
   inside .move-full. `.move-full > p` keeps governing the rationale
   paragraph beneath it, which carries no .sec-sub class. */
.move-full > p.sec-sub { font-size: 13px; margin: 0 0 18px; }

/* Fix 7: join the report's single prose measure (--measure, v2.css:1383)
   instead of standing as new ragged ones. Same-selector re-declaration:
   equal specificity to the rule above, later in the file, so this wins on
   max-width only and leaves that rule's other properties untouched.
   .memo-band-note keeps its own narrower 68ch (committed above): it is a
   small caption under the table, matching .sec-sub's own base 68ch caption
   measure (v2.css:154), not a body-prose paragraph the 2026-07-22 wave's
   72ch measure was written for. */
.memo-market { max-width: var(--measure); }
.move-full > p { max-width: var(--measure); }

/* Memo table proportions, corrected after a real-browser render check at 1440px.
   The confidence column carries the band pill AND the service-authored drivers
   beneath it, but it was committed at a fixed 150px, so those drivers wrapped
   into a tall narrow ribbon (four to five lines each) and pushed every row to
   roughly 200px high, while the move column sat half empty beside them. jsdom
   does no layout, so no test in the suite can see this. Widening the confidence
   column lets a driver sit on one or two lines and returns the table to
   something a reader can scan. Cells align to the top so the move text starts
   level with its band rather than floating in the middle of a tall row. */
.memo-table th:last-child, .memo-table td:last-child { width: 34%; }
.memo-table td { vertical-align: top; }
.memo-table thead th { vertical-align: bottom; }

/* Task F3 (2026-07-25): the intent split (intentSplit.js), the competitor simulation
   (simulation.js) and what-we-do-not-know (unknowns.js). Reuses .block, .sec-title, .sec-sub,
   .dec-h, .dec-list, .sov-track, .sov-fill, .sov-val, .badge-label and .you-tag as already styled
   above; nothing above this banner is edited. */

.intent-brand { margin-top: 26px; }
.intent-brand:first-of-type { margin-top: 0; }
.intent-coverage { font-size: 12.5px; color: var(--dim); line-height: 1.5; max-width: var(--measure); margin-bottom: 14px; }

.intent-bars { display: flex; flex-direction: column; gap: 3px; }
/* A wider first column than .sov-row's 150px: "Transaction intent (40 keywords)" runs longer than
   a brand name. Track and value columns keep .sov-row's proportions so the two bar families read
   as one visual language. */
.intent-row { display: grid; grid-template-columns: 230px 1fr 90px; align-items: center; gap: 14px; padding: 6px 0; }
.intent-name { font-size: 13px; color: var(--sub); }
/* A caption under its row rather than a grid cell inside it, so a long example list never fights
   the row's fixed columns. */
.intent-examples { font-size: 12px; color: var(--dim); font-style: italic; margin: 2px 0 10px; }
/* Shared "no number here" treatment: the total-loss explainer paragraph and the inline
   "not measured" label both use it, so an absent share always reads the same way. */
.intent-unit { color: var(--dim); font-style: italic; }
.intent-hook {
  margin-top: 22px; background: var(--raise); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 14px 16px; font-size: 13px; color: var(--sub); line-height: 1.5; max-width: var(--measure);
}

.sim-item { margin-top: 20px; padding-top: 20px; border-top: 1px solid var(--line); }
.sim-item:first-of-type { margin-top: 0; padding-top: 0; border-top: none; }
.sim-move { font-size: 13.5px; color: var(--fg); line-height: 1.6; max-width: var(--measure); margin: 4px 0 12px; }
.sim-warn {
  background: rgba(var(--inferred-rgb),0.08); border: 1px solid rgba(var(--inferred-rgb),0.28);
  border-radius: var(--r-card); padding: 12px 14px; font-size: 13px; color: var(--fg); line-height: 1.5;
}
.sim-warn .badge-label { color: var(--inferred); display: block; margin-bottom: 5px; }

.unknowns-hook {
  margin-top: 16px; background: var(--raise); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 14px 16px; font-size: 13px; color: var(--sub); line-height: 1.5; max-width: var(--measure);
}

/* ================================================================
 * Task F3 fix wave (2026-07-25), Fix 1 (CRITICAL): the intent rows reused .sov-track and
 * .sov-val, and those two classes carry grid-area rules scoped to the public-page markers
 * (v2.css:1634-1648) and written for the SCOREBOARD's own responsive layout. .intent-row above
 * made its own parent a grid, which is the one thing that had kept the reuse safe (the pre-flight
 * correction that called the reuse "probably safe" was wrong about that, and said so should a
 * browser check prove it). Measured in real Chromium at 768px with #app[data-page="sample"]:
 * grid-area: track / val landed live, the bar and its value drew on top of each other on all
 * three rows, and the track's width was driven by the VALUE TEXT's implicit column instead of by
 * the share, so the never-measured "not measured" bucket drew the longest rail of the three.
 *
 * Fix: stop reusing the scoreboard bar classes inside .intent-row. .intent-track and .intent-val
 * below carry their own rules, copied from .sov-track (v2.css:204) and .sov-val (v2.css:207), so
 * the two bar families still look identical but the scoreboard's page-marker rules can never
 * reach them again. .sov-fill is kept as-is inside .intent-track: verified (grep) that
 * .sov-fill/.sov-row.you .sov-fill (v2.css:205-206) carry no grid-area or page-marker rule of
 * their own, so nesting it inside .intent-track is safe.
 * ================================================================ */
.intent-track { height: 12px; background: var(--raise); border-radius: 3px; overflow: hidden; }
.intent-val { font-family: var(--font-mono); font-size: 13px; text-align: right; color: var(--fg); }

/* Also Fix 1: .intent-row had NO phone reflow at all. Even with the grid-area collision above
 * fixed, 230px 1fr 90px inside a ~324px column at 375px drives the track to 0px width and the
 * document scrolls horizontally (measured: scrollWidth 451 vs clientWidth 360 before this rule).
 * Gated to the three public pages only, mirroring the established .sov-row pattern at
 * v2.css:1621-1648: the signed-in workspace stays desktop-only by design (2026-07-22), and because
 * .intent-row's own base rule above is not itself inside any media query, leaving
 * data-page="app" out of this selector list means the workspace is never touched at any width,
 * with no separate "restore" rule needed (unlike .sov-row, which needed one because a BARE,
 * ungated mobile rule already existed for it before this fix was written).
 */
@media (max-width: 768px) {
  body:has(#app[data-page="sample"]) .intent-row,
  body:has(#app[data-page="start"]) .intent-row,
  body:has(#app[data-page="guide"]) .intent-row {
    grid-template-columns: minmax(0, 1fr) 90px;
    grid-template-areas: "name val" "track track";
    row-gap: 6px;
  }
  body:has(#app[data-page="sample"]) .intent-name,
  body:has(#app[data-page="start"]) .intent-name,
  body:has(#app[data-page="guide"]) .intent-name { grid-area: name; min-width: 0; }
  body:has(#app[data-page="sample"]) .intent-track,
  body:has(#app[data-page="start"]) .intent-track,
  body:has(#app[data-page="guide"]) .intent-track { grid-area: track; }
  body:has(#app[data-page="sample"]) .intent-val,
  body:has(#app[data-page="start"]) .intent-val,
  body:has(#app[data-page="guide"]) .intent-val { grid-area: val; }
}

/* Fix wave 2026-07-25, Fix 6 (Minor "`.unknown-item` has no rule by that name"): it already
 * inherits `.dec-list li` (v2.css:1443) correctly, so this adds nothing visually; it exists so the
 * class has a real declared rule of its own, and guards long "what we do not know" lines from
 * overflowing their column. */
.unknown-item { overflow-wrap: break-word; }

/* Task G2 (2026-07-25): the credibility strip (credibility.js), an engine-counted utility strip
   mounted immediately before the verify section (deepReport.js, printReport.js). Reuses .block,
   .sec-title and .sec-title-utility as already styled above (v2.css:153, 675); these four classes
   are new and brand-specific, deliberately not reused from .sov-track/.sov-val or any other class
   already carrying a page-marker or grid-area rule, the exact reuse bug an earlier task in this
   wave shipped (F3's .intent-row Critical). */
.cred-strip { display: flex; flex-wrap: wrap; gap: 6px 20px; margin-top: 2px; }
.cred-item { font-size: 12.5px; color: var(--sub); }
.cred-recheck { margin-top: 14px; font-size: 13px; color: var(--fg); line-height: 1.5; max-width: var(--measure); }
.cred-note { margin-top: 10px; font-size: 11.5px; color: var(--dim); font-style: italic; }

/* Task G3 (2026-07-25): sources.js, the app's per-brand source list, collapsed behind a labelled
   expander mounted as the THIRD sibling in the verify accordion row (after credibility.js and
   verify.js, C2). C1 found that ".sources" and ".source-row" are ORPHAN v1 rules already live in
   app.css on every Vantage page (nothing in public/ or src/ still emits either), so this task never
   emits those two exact bare tokens: every class below is a distinct token that cannot collide with
   them (CSS class selectors match a whole token, so "sources-toggle" etc. do not match "sources"),
   grepped against tokens.css, app.css and v2.css first (C9) and given its own rule here. Reuses
   .block, .sec-title and .sec-title-utility as already styled above (v2.css:153, 675) for the
   section heading, and .sec-sub (v2.css:154, also measured at v2.css:1393) for the reconciliation
   sub-line's base prose treatment; .sources-sub carries no rule of its own beyond that reuse. */
.sources-toggle {
  display: inline-flex;
  align-items: center;
  margin-top: 8px;
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--raise);
  color: var(--fg);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
}
.sources-toggle:hover { border-color: var(--gold); }
.sources-list { display: none; margin-top: 16px; flex-direction: column; gap: 20px; }
.sources-list.open { display: flex; }
.sources-brand { display: flex; flex-direction: column; gap: 8px; }
.sources-brand-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--fg);
  border-bottom: 1px solid var(--line);
  padding-bottom: 4px;
}
.sources-row { font-size: 12.5px; color: var(--sub); display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline; }
.sources-row b { color: var(--fg); font-weight: 600; }
.sources-row a { color: var(--fg); text-decoration: none; border-bottom: 1px solid var(--line); word-break: break-all; }
.sources-row a:hover { color: var(--gold); }
.sources-date { color: var(--dim); font-size: 12px; white-space: nowrap; }

/* Task G4 fix wave (2026-07-26), Fix 1. G2 and G3 mounted renderCredibility, renderVerify and
   renderSources each into its OWN host div inside the verify accordion row (deepReport.js's
   host()), so each section is the only child of its own div and ALL THREE match the :last-child
   selector at v2.css:1477-1478, stripping the divider between every pair of them (measured in a
   real browser: all three reported border-bottom: 0px none, leaving 60px of unexplained space
   with no rule anywhere). This restores the divider on every section whose host div is NOT the
   last one, leaving the final section in a row borderless as intended; the scoreboard row and
   every other single-section row are untouched, since a lone div there already matches
   :last-child on its own. Specificity ties the rule at v2.css:1477-1478 at (0,3,2), so this one
   wins on source order only: it MUST stay appended after that rule, never inserted above it. */
.acc-body > div:not(:last-child) > section.block { border-bottom: 1px solid var(--line); }

/* Task G4 fix wave (2026-07-26), Fix 4. credibility.js's second line, .cred-method, states the
   design rule the .cred-recheck sentence above it rests on ("the re-check can only lower a
   claim's standing, never raise it"): a quiet method note, not a boast, so it sits at roughly
   .cred-note's weight (11.5px, --dim, italic) rather than competing with .cred-recheck (13px,
   --fg). Landing a touch above .cred-note's weight, at --sub and 12px, non-italic: it is read
   before the italic aside, not mistaken for one. */
.cred-method { margin-top: 6px; font-size: 12px; color: var(--sub); line-height: 1.5; max-width: var(--measure); }

/* Task G4 fix wave 1 (2026-07-26), Fix 2. The rule above this comment (v2.css:2015,
   `.acc-body > div:not(:last-child) > section.block`) keys the divider on the host div's ORDINAL
   position among .acc-body's own children, not on whether a section actually follows it.
   renderCredibility and renderSources can each legitimately render NOTHING into a host div that
   stays in the DOM (the committed fixture
   `src/services/__fixtures__/fixture-synthetic-no-leak-funnel.json` has 0 source rows on all four
   brands, so this shape is reached by a real run, not a hypothetical), so a trailing EMPTY host div
   was enough to make that rule draw a divider under the true last VISIBLE section with nothing
   under it (measured live: 0.666667px solid rgb(42,50,66) under "verify" with 8px of dead space
   above .acc-body's bottom edge and nothing under it).

   These two rules replace the ordinal test with a structural one, for both shapes v2.css already
   pairs together at line 1477-1478 (a section wrapped in its own host div, the provenance row's
   shape; a bare section direct child of .acc-body, the scoreboard row's shape): the divider draws
   only when a LATER sibling actually holds a section, never merely because a later div exists in
   the DOM. `:has()` necessarily imports the specificity of its own argument (the div and section
   elements inside the parentheses), so both rules below already outrank the ordinal rule above and
   win wherever they match without depending on being appended after it; the ordinal rule is kept
   (append-only) but is superseded everywhere it used to matter. Only two rows on this page ever
   hold more than one item (the provenance row: credibility, verify, sources; the scoreboard row:
   scoreboard, ad libraries; checked by hand against every entry in deepReport.js's `bodies` map), so
   neither selector can match, let alone change anything, on any of the other 13 solo-item rows: the
   full fixture renders the identical 2-of-18 section change this pair's predecessor made (both in
   the provenance row), nothing else moves. As a bonus, not a regression, the bare-shape half of
   this pair also fixes the same dangle in the scoreboard row for the day `renderAdLibraries` renders
   nothing (unreachable by any fixture today, but reachable the same way the provenance row's dangle
   was: a host div that stays in the DOM empty). Keep border-bottom; do not change this to
   border-top, that would move every divider in the report for a defect this narrow. */
.acc-body > div:has(~ div > section.block) > section.block,
.acc-body > section.block:has(~ div > section.block) { border-bottom: 1px solid var(--line); }

.acc-body > div:not(:has(~ div > section.block)) > section.block,
.acc-body > section.block:not(:has(~ div > section.block)) { border-bottom: none; }

/* Task G4 fix wave 2 (Minor, corrects the comment above without changing the rules). That comment
   says the divider draws "only when a LATER sibling actually holds a section, never merely because
   a later div exists in the DOM." The predicate the two rules above actually use is
   `~ div > section.block`, and only that: a later BARE section (not wrapped in a div) does not
   satisfy it, and neither does a section nested a level deeper than a direct child. So a trailing
   later sibling of either of those two shapes would not keep the divider either, which the comment
   above overstates. The mechanism is deliberately left as-is: every one of those shapes is
   unreachable against the current composition (15 rows, 18 sections, every host div holding exactly
   one direct `section.block`), so this is a correction to the comment's claim, not a change to
   behaviour. */

/* Task H1 fix wave 2 (2026-07-26), F7. The "no coverage" label for an unmeasured brand renders in
   the NAME cell, beside the brand name, because the value cell is a fixed 56px track that an
   11-character label does not fit (measured: it wrapped to two lines and overhung its column).
   .sov-name is a flex row (v2.css:201) with the default flex-wrap: nowrap, and on the CLIENT's own
   row it now holds THREE items: the brand name, the YOU tag, and this label. A long brand name then
   exceeds the fixed 150px column, and because data-page="app" sets min-width: auto (v2.css:1656)
   the cell cannot shrink, so it overflowed by 11.2px on screen and by 17.7px in print, where the
   label physically overlapped the bar track by 7.7px. Measured with "Malabar Gold and Diamonds", a
   real shipped client name.

   Scoped with :has() to rows that actually carry the label, and that scoping is load-bearing, not
   tidiness: an unscoped .sov-name flex-wrap also wraps MEASURED rows, which pushed the YOU tag onto
   its own line and grew the client's measured row from 44px to 65px in print, changing a surface
   that was never broken. Measured both ways before choosing. With the scope, absent rows sit 38.5px
   clear of the bar and measured rows keep today's exact heights.

   Specificity 0,2,0 beats v2.css:201's 0,1,0, so this wins regardless of source order, but keep it
   appended anyway and never edit line 201 in place. The page-marker rules for .sov-name set only
   grid-area and min-width, so none of them conflict. */
.sov-name:has(.cell-empty) { flex-wrap: wrap; }

/* =========================================================================================
   2026-07-27. Two appends, both APPEND-ONLY: nothing above this line is edited.

   (1) THE SCOREBOARD AXIS NOTE.
   scoreboard.js now prints a direction line under every axis name, plus a basis line on the two
   USD axes. It has to be styled here because the pre-existing `.matrix td.axis small` rule
   (v2.css:214) has NEVER applied to anything: every .axis cell in the matrix is a <th>
   (scoreboard.js and aiVisibility.js both emit `<th scope="row" class="axis">`), and grepping the
   whole of public/vantage finds no module that emits a td.axis at all. So that rule and the
   `.matrix td.axis` colour rule above it are both dead. These target the real markup.

   (2) THE SMALL-TEXT LEGIBILITY FIX.
   Measured in a real browser at both 1x and 1.5x, then validated against Vineeth's own screenshot
   (the harness reproduced it to within 3%), NOT eyeballed:

     report body prose  14px/400/--fg    nominal 17.00:1   EFFECTIVE 5.74:1
     .intent-name       13px/400/--sub   nominal 11.16:1   EFFECTIVE 3.81:1   <- reads fine
     these classes      12.5px/400/--dim nominal  6.17:1   EFFECTIVE 2.15:1   <- reported illegible

   "Effective" is the mean luminance of every ink pixel including antialiasing, against the
   background. WCAG scores the token pair at 6.17:1 and PASSES it, because WCAG measures a colour
   pair and not a rendered glyph. That assumption holds for thick strokes on white and breaks for
   12px light-on-dark, where most of every stroke is antialiasing far below the nominal colour.
   So this is not a WCAG failure being corrected; it is a legibility failure WCAG cannot see.

   Target is .intent-name's 3.81:1, the quietest text nobody has complained about, NOT 4.5:1:
   body prose itself only reaches 5.74:1 on this theme, so 4.5 as an absolute would flatten the
   whole hierarchy. The chosen treatment (13.5px / 500 / --sub) measures 4.47:1 at 1x and 5.52:1
   at 1.5x, which is clearly above the labels that read fine and still clearly below body prose.

   Lever sizes, isolated by measurement, because the intuition was wrong: colour +77%, weight
   +17%, size +4%. Weight alone was expected to carry this and does almost nothing on its own.

   SCOPE. Only text that carries EVIDENCE (what we measured, where it came from, what we could not
   establish) or MONEY AND LEGAL copy. Chrome that is genuinely incidental (.brand-foot,
   .ladder-arrow, .switcher .lbl, .swot-sub) is deliberately left on --dim: it is decoration, and
   lifting it too would remove the contrast step that makes the evidence readable as evidence.
   ========================================================================================= */

/* (1) axis note.
   The direction is stated ONCE above the table (.matrix-dir) and per row only where a row
   disagrees with it (.axis-dir). The first build printed it on every row, and measuring the real
   render killed that: 11.5px on --slate came out at 1.76:1 EFFECTIVE, worse than the 2.18:1 this
   whole change exists to fix, and raising it to a legible value made every row double-weighted
   because the hint then shouted as loud as the metric name, ten times over. Small repeated text
   on a near-black theme cannot be both quiet and legible. Stated once, it can afford to be read. */
.matrix-dir { font-size: 13px; font-weight: 500; color: var(--sub); margin: 0 0 10px; }
.matrix th.axis .axis-dir,
.matrix th.axis .axis-basis { display: block; font-weight: 500; letter-spacing: 0; text-transform: none; }
/* Rare by construction (only an axis that bucks the stated default), so it is sized to be read
   rather than sized to disappear, and it carries the gold accent because it is an exception. */
.matrix th.axis .axis-dir { font-size: 12.5px; color: var(--gold); margin-top: 4px; }
.matrix th.axis .axis-basis { font-size: 12.5px; color: var(--sub); margin-top: 3px; line-height: 1.4; }

/* (2) evidence text */
.intent-coverage,
.claim-src,
.not-established,
.research-foot,
.adlib-note,
.adlib-advertiser,
.cred-note,
.memo-band-note,
.sources-date,
.pdf-note { font-size: 13.5px; font-weight: 500; color: var(--sub); }
/* The example keywords are SUBORDINATE to the intent row they illustrate (.intent-name, 13px/400
   /--sub). Giving them the 13.5px/500 treatment above inverted that: rendered side by side, the
   examples visibly outweighed the label they belong under, which the real browser comparison
   showed immediately and no assertion could. They sit at the row label's own weight instead:
   legible (the --sub step is what carries this, not the weight) without shouting over it.
   The italic goes: at this size on a near-black field it costs legibility and the "For example:"
   opener already marks the line as subordinate without it. */
.intent-examples { font-size: 13px; font-weight: 400; color: var(--sub); font-style: normal; }
.honesty-foot { font-size: 12.5px; font-weight: 500; color: var(--sub); }

/* (2) money and legal copy. Same treatment and the same reason: a consent line or a tax line that
   cannot be read comfortably is a worse problem than a report line that cannot, not a smaller one. */
.consent,
.consent-line,
.pay-note,
.pay-why,
.pay-balance-note,
.tax-line,
.credits,
.packs-sub,
.intl-note { font-size: 13.5px; font-weight: 500; color: var(--sub); }

/* 2026-07-27. The same .fia-line overflow on screen: "CONDITION" at 11px/600/0.06em measures
   62.03px against a 60px track, so it overflows by 2.03px into the value column. Smaller than the
   PDF's 10.63px because the app's column was already wider, but the same defect. 68px clears it.
   Appended, never edited in place: specificity 0,1,0 matches v2.css:258 and this relies on order. */
.fia-line { grid-template-columns: 68px 1fr; }

/* =========================================================================================
   2026-07-28. APPEND-ONLY: nothing above this line is edited.

   THE SCOREBOARD PROVENANCE LINE (.matrix-source), app side.

   Sits BELOW the table, deliberately, not in the header cells. The axis definitions added the
   same day already cost 2 lines of height inside every metric cell, and a real-browser
   measurement at print geometry showed the block reaching 1004px against 986px of printable
   height before the copy was trimmed. One line under the table adds its height once, not once
   per axis, so this cannot re-open that overflow however many axes a future run carries.

   Quieter than .matrix-dir above the table (12px against 13px, weight 400 against 500): the
   direction note changes how you READ every row, while this states where the numbers came from.
   Both are secondary to the data, but they are not equally load-bearing.
   ========================================================================================= */
.matrix-source { font-size: 12px; font-weight: 400; color: var(--sub); margin: 14px 0 0; line-height: 1.5; }

/* App twin of print.css's .src-measured: the collapsed connector-source line, a statement rather
   than a citation, so it reads italic and stays in the muted ink. No link and no hostname by
   design (see brandSourceRows in printSources.js). */
.sources-row.sources-measured { font-style: italic; color: var(--sub); }

/* App twins of the 2026-07-28 print fixes.
   .fstage-name wraps for the same reason it does in print: "Consideration" plus the "Biggest leak"
   badge do not fit the fixed 130px track, and the badge overflowed onto the note column.
   .lens-key is the Brand Strength lens key, now shown rather than hidden behind the info button. */
.fstage-name { flex-wrap: wrap; }
.lens-key { display: grid; grid-template-columns: auto 1fr; gap: 3px 10px; margin: 10px 0 0; font-size: 12px; line-height: 1.45; }
.lens-key dt { font-weight: 600; color: var(--fg); }
.lens-key dd { margin: 0; color: var(--sub); }

/* The Preference Curve ladder is FOUR rungs, not five (public/vantage/frameworks.js RUNGS). The
   engine has only ever placed a brand at overlooked / considered / preferred / default, so the
   original five-column grid drew two rungs nothing could ever land on. Appended rather than edited
   at .ladder above, because this stylesheet is append-only.

   THE COUNT IS A CUSTOM PROPERTY so it is stated exactly ONCE. A first attempt wrote the literal 4
   into both the base rule and the 1120px breakpoint, and the drift test that guards it reads the
   LAST matching declaration, so changing only the base rule slipped past it. Two numbers meant two
   chances to disagree, which is the same defect this whole change exists to remove. */
.ladder { --rung-count: 4; grid-template-columns: repeat(var(--rung-count), 1fr); }
@media (max-width: 1120px) {
  /* Restated so the appended base rule above cannot win at narrow widths and quietly drop the
     minmax(0, 1fr) that stops a long brand name overflowing its column. */
  .ladder { grid-template-columns: repeat(var(--rung-count), minmax(0, 1fr)); }
}

/* Design wave 1, fix 5 (2026-08-11): the "Vantage" wordmark text beside the brand mark on
   /vantage/start, /vantage/sample, the workspace rail header and the login screen moves to the
   violet brand treatment the marketing nav uses, LOGO ONLY, per design-wave-1-brief.md. No new
   class names (grepped .start-scene, .wordmark-lock, .wordmark, .samp-head, .wm and
   .login-wordmark all pre-exist above in this file or in app.css); these are overrides by source
   order, appended here because this stylesheet is append-only. The matching mark-colour edit
   (the inline SVGs) lives in start.js, sample.js, rail.js and login.js themselves.

   .wordmark's own base rule (color: var(--gold), line 100 above) stays untouched: it still serves
   /vantage/guide (guide.js), which is OUT of this wave's named scope and keeps its gold mark and
   wordmark unchanged. .wm's base colour comes from app.css (color: var(--fg), neutral); this
   override is additive there too, deliberate so all four surfaces read one consistent violet
   accent rather than three violet and one neutral. Hardcoded to the exact violet
   marketing/src/assets/vantage-logo-violet.svg uses (#A78BFA), never through --gold-hi: the full
   gold-to-violet app re-theme is a separate later job and is not started here. */
.start-scene .wordmark-lock .wordmark,
.samp-head .wordmark-lock .wordmark,
.wm {
  color: #A78BFA;
}

.login-wordmark {
  background: linear-gradient(180deg, #fff 30%, #A78BFA 125%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Design wave 1, fix 5 follow-up (2026-08-11): guide.js's own wordmark text, scoped under
   .guide-head (tokens.css/v2.css line ~1318), was NOT covered by the wave 1 override above
   (that block lists only .start-scene, .samp-head and the bare .wm; .guide-head was out of
   scope at the time and .wordmark's base rule, color: var(--gold) near the top of this file,
   still applied there). The controller has now ruled guide.js in scope for the same violet
   swap the other four surfaces got, so the text needs its own selector too, appended here
   rather than edited into the block above (CSS is append-only). Same hardcoded #A78BFA as
   the rest, for the same reason: the full gold-to-violet re-theme is not started yet. */
.guide-head .wordmark-lock .wordmark {
  color: #A78BFA;
}
