#hero-search-listbox[data-astro-cid-gp6napx3]{transition:opacity 150ms ease-out,transform 150ms ease-out;opacity:0;transform:translateY(8px);pointer-events:none}@media (min-width: 640px){#hero-search-listbox[data-astro-cid-gp6napx3]{transform:translateY(-8px)}}#hero-search-listbox[data-astro-cid-gp6napx3].is-open{opacity:1;transform:translateY(0);pointer-events:auto}#hero-search-listbox[data-astro-cid-gp6napx3].is-closing{pointer-events:none}@media (prefers-reduced-motion: reduce){#hero-search-listbox[data-astro-cid-gp6napx3]{transition:opacity 1ms;transform:none!important}}#home-search-compact[data-astro-cid-gp6napx3]{max-height:0;opacity:0;transition:max-height 200ms ease-out,opacity 150ms ease-out;pointer-events:none}#home-search-compact[data-astro-cid-gp6napx3].is-open{max-height:400px;opacity:1;pointer-events:auto}#home-search-compact[data-astro-cid-gp6napx3].is-closing{pointer-events:none}@media (prefers-reduced-motion: reduce){#home-search-compact[data-astro-cid-gp6napx3]{transition:opacity 1ms}}.hero-search-progress[data-astro-cid-gp6napx3].hsp-indeterminate .hsp-fill[data-astro-cid-gp6napx3]{width:40%!important;transition:none;animation:hsp-sweep 1.1s ease-in-out infinite}@keyframes hsp-sweep{0%{transform:translateX(-110%)}100%{transform:translateX(275%)}}@media (prefers-reduced-motion: reduce){.hero-search-progress[data-astro-cid-gp6napx3],.hero-search-progress[data-astro-cid-gp6napx3] .hsp-fill[data-astro-cid-gp6napx3]{transition:opacity 1ms,width 1ms}.hero-search-progress[data-astro-cid-gp6napx3].hsp-indeterminate .hsp-fill[data-astro-cid-gp6napx3]{width:100%!important;transform:none;opacity:0.45;animation:none}}/* is:global so the client-created ledger pins (built via document.createElement
     in home-preview.ts, which lack the Astro data-astro-cid scope attribute) receive
     the .hp-pin/.hp-lab/.ambient rules — same pattern the FearCard component uses.
     NOTE: NO apostrophes in comments in this block — Lightning CSS (which processes
     is:global) tokenizes a bare apostrophe as a string start and fails the build.
     Safe: every selector below is .hp-dash or .home-preview-root scoped (unique to
     this page), so nothing leaks to other routes. (Do NOT write a star-slash pair
     in this comment — it closes the block early and drops the next rule.)
     ── Warm-editorial palette (phase 5) ──────────────────────────────────────
     The fusion-B7 paper/navy/teal/amber palette, applied by OVERRIDING the
     shared --color-* tokens ONLY within .home-preview-root. This recolours both
     the hp-* structural styles AND the canonical FearCard/RegretPairCard search
     results + chapter cards (which read the same tokens) so the whole preview
     reads as one warm-editorial surface — without leaking to any other page.
     Applied in LIGHT MODE ONLY — gated on html:not([data-theme="dark"]) so a
     dark-mode user keeps the site dark tokens (a light cream block inside the
     dark Base chrome would clash). The override sets custom properties on the
     subtree, recolouring both hp-* styles and the canonical cards. */
  /* Match the risks/decisions contained column (item 6): same 64rem (max-w-5xl)
     width on desktop so home reads as the same "boxed" column, and NO own
     horizontal padding — the global body padding (1rem) is the single inset, so
     home is no longer double-padded on mobile (it was body-1rem + clamp). */
  .home-preview-root {
    max-width: 64rem; margin: 0 auto; padding: 0;
  }
  html:not([data-theme="dark"]) .home-preview-root {
    --color-bg: #f4f0e8;
    --color-bg-card: #fcf9f3;
    --color-surface-raised: #fffdf8;
    --color-ink: #1d2630;
    --color-ink-muted: #46555f;
    --color-line: #d8cfbe;
    --color-accent: #1c6f67;     /* teal — reality / under-rated */
    --color-accent-dim: #d4e7e3; /* teal-soft — balanced badge bg */
    --color-warm: #b0631f;       /* amber — fear / over-rated */
  }
  /* Full-bleed page background. The warm gradient used to sit on the 1180px
     content column, so it ended mid-page and read as a mismatched box. Put a
     soft top glow over flat cream on the WHOLE page instead — full width, no
     box edge. Light mode only; scoped to home-preview pages via :has. */
  html:not([data-theme="dark"]):has(.home-preview-root) body {
    background:
      radial-gradient(1200px 600px at 50% -120px, #fbf7ef 0%, rgba(251, 247, 239, 0) 72%),
      #f4f0e8 !important;
  }
  .home-preview-root .compare-select-btn { display: none !important; }

  /* B7 parity for the shared HeroSearch (#28 gradient progress) — preview-only
     overrides of HeroSearch's classes; HeroSearch.astro itself is never touched,
     so the live homepage is unaffected. The Ask AI CTA is unified to the
     site-wide teal --color-accent (its own class), so no background override
     here — only a teal-tinted lift to match the old CTA's depth. */
  .home-preview-root #hero-search-calibrate-link {
    box-shadow: 0 8px 22px -8px color-mix(in srgb, var(--color-accent) 80%, transparent);
  }
  .home-preview-root .hsp-fill {
    background: linear-gradient(90deg, var(--color-accent), var(--color-warm)) !important;
  }

  /* ── Animated search ring (homepage-only) ────────────────────────────────
     Replaces the thin under-bar progress with a gradient border that sweeps
     around the search input while a query resolves. hero-search.ts toggles
     `.hs-ring-active` on the `.home-search-section` wrapper off the SAME
     lifecycle as the old bar (armed on keystroke → settles on results). The
     ring is a masked conic-gradient on the input `.relative` wrapper::after,
     rotated via a registered custom property so only the coloured arc travels
     the perimeter (the mask + radius stay put — clean on a rounded rect).
     Overlay-only (position:absolute, inset:0) → zero layout shift. */
  .home-preview-root #hero-search-progress { display: none; }

  /* Registered so the conic `from` angle is animatable (a plain custom property
     is a computed string and will not interpolate in @keyframes). */
  @property --hs-ring-angle {
    syntax: "<angle>";
    inherits: false;
    initial-value: 0deg;
  }

  /* Child combinator (`> .relative`), NOT descendant: `.relative` is a Tailwind
     positional utility, and the search section may later gain nested `.relative`
     wrappers (dropdown, tooltip). Scoping to the DIRECT input wrapper keeps the
     ring from painting a stray masked pseudo-element on the wrong element. */
  .home-preview-root .home-search-section > .relative::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 0.5rem; /* matches the rounded-lg input */
    padding: 2.5px;        /* ring thickness (carved out by the mask) */
    /* A dim accent floor around the whole perimeter + a bright accent→warm
       "comet" head, so the sweep reads as a glowing ring with a travelling
       highlight rather than a lone faint arc lost against the focus border. */
    background: conic-gradient(
      from var(--hs-ring-angle, 0deg),
      color-mix(in srgb, var(--color-accent) 14%, transparent) 0deg,
      color-mix(in srgb, var(--color-accent) 14%, transparent) 190deg,
      color-mix(in srgb, var(--color-accent) 50%, transparent) 258deg,
      var(--color-accent) 318deg,
      var(--color-warm) 348deg,
      color-mix(in srgb, var(--color-warm) 30%, transparent) 358deg,
      color-mix(in srgb, var(--color-accent) 14%, transparent) 360deg
    );
    -webkit-mask:
      linear-gradient(#000 0 0) content-box,
      linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask:
      linear-gradient(#000 0 0) content-box,
      linear-gradient(#000 0 0);
    mask-composite: exclude;
    opacity: 0;
    transition: opacity 220ms ease-out;
    pointer-events: none;
    z-index: 1;
  }
  .home-preview-root .home-search-section.hs-ring-active > .relative::after {
    opacity: 1;
    animation: hs-ring-spin 1.1s linear infinite;
    filter: drop-shadow(0 0 3px color-mix(in srgb, var(--color-accent) 45%, transparent));
  }
  /* While the ring owns the border, calm the input own teal focus outline so
     the two do not fight (the sweep would otherwise vanish against an already
     teal border). Higher specificity than Tailwind focus:border utility → no
     !important needed; `transition-colors` on the input eases it back on settle. */
  .home-preview-root .home-search-section.hs-ring-active #hero-search-input {
    border-color: var(--color-line);
  }
  @keyframes hs-ring-spin {
    to { --hs-ring-angle: 360deg; }
  }

  /* Reduced motion / no @property support → a calm static accent ring instead
     of a spinning arc (still reads as "search is working"). */
  @media (prefers-reduced-motion: reduce) {
    .home-preview-root .home-search-section.hs-ring-active > .relative::after {
      animation: none;
      background: color-mix(in srgb, var(--color-accent) 55%, transparent);
      opacity: 0.7;
      filter: none;
    }
  }
  /* NOTE: this probes conic-gradient support, NOT @property (there is no reliable
     @supports test for a registered custom property). The real gap case — conic
     supported but @property not — is pre-Safari 16.4 / pre-Firefox 128, i.e. no
     current browser. In that historical gap the ring simply renders static at the
     @property `initial-value: 0deg` (a dim arc), which is an acceptable degrade;
     this block is a belt-and-suspenders solid ring for genuinely conic-less UAs. */
  @supports not (background: conic-gradient(from var(--hs-ring-angle, 0deg), #000, #fff)) {
    .home-preview-root .home-search-section.hs-ring-active > .relative::after {
      animation: none;
      background: color-mix(in srgb, var(--color-accent) 55%, transparent);
    }
  }
  /* SEARCH RESULTS region — now lives below the ledger + tidbit, with the Ask AI
     CTA as its last child. Match the ledger column width so it reads as the same
     boxed surface. */
  .hp-results { max-width: 64rem; margin: 14px auto 0; }

  /* Decisions render as a single full-width column (grouped Decisions section).
     Drop the big 2:1 hero image IN THE STACK so each card collapses to a compact
     "regret bar" row — question + the two-sided bar (which now gets the full width)
     + the dominance badge — scannable one-after-the-other. The card still links to
     the full detail page (with its image). The image block is the only aspect-ratio
     box in the canonical RegretPairCard, so this targets exactly it. */
  .hp-decisions-stack [class*="aspect-"] { display: none !important; }

  /* Compact typeahead panel animation — relocated here from HeroSearch's scoped
     <style> because externalResults moves #home-search-compact into THIS body, so
     the component-scoped selector no longer matches it. */
  #home-search-compact {
    max-height: 0;
    opacity: 0;
    transition: max-height 200ms ease-out, opacity 150ms ease-out;
    pointer-events: none;
  }
  /* Tall enough for the inline stacked decision cards (variant B). The compact
     preview shows up to 5 risk rows + DECISION_PREVIEW_QUOTA (3) full regret-bar
     cards (hero-search.ts), plus the "See all" header and two group headers — the
     worst realistic set is ~1100px, more in verbose locales. The old 1000px ceiling
     CLIPPED the last decision card. 1800px clears it with headroom; the panel
     doesn't scroll internally (overflow:hidden is just for the slide) — the PAGE
     scrolls past it, so a high ceiling only makes the reveal complete a touch
     sooner, never a scroll trap. */
  #home-search-compact.is-open { max-height: 1800px; opacity: 1; pointer-events: auto; }
  #home-search-compact.is-closing { pointer-events: none; }

  /* Search-active condensations (.hp-searching is toggled by home-preview.ts when
     a query is live): strip what is orientation-at-rest but noise once you have
     searched — the "Try:" chips, the ambient ticker, and the static scroll chapters
     (Decisions / gap / receipts) so they cannot be mistaken for search results when
     you scroll past the list. NB: the under-ledger scope-honesty note (.hp-scopenote
     — "Scopes vary … see methodology") is deliberately KEPT visible during search:
     it is the axis-level comparability disclosure, and it matters most exactly when
     mixed-scope result pins land on the ledger. It sits inside the already-on-screen
     ledger block, so keeping it does NOT reintroduce the off-screen push this fixed.
     No plot-height change → the SVG scale stays in sync (no buildScale needed). */
  .home-preview-root.hp-searching .hp-promptline,
  .home-preview-root.hp-searching .hp-ticker,
  .home-preview-root.hp-searching .hp-content { display: none; }

  /* Mobile keyboard-up collapse (:focus-within): the instant the search field is
     focused, drop the resting-orientation chrome — the "Try:" chips and the 3 stat
     numbers — so the ledger + results rise directly under the input instead of
     below the on-screen keyboard. This fires on FOCUS (before the 650ms debounce
     sets .hp-searching); once a query is live, .hp-searching (chips) and the strip
     .single live-summary keep things collapsed, so it survives the #7 auto-blur.
     The .single summary is exempt (:not(.single)) so the live "showing N" still
     shows once results land. Desktop is untouched — no keyboard, space is ample. */
  @media (max-width: 640px) {
    .hp-searchwrap:focus-within .hp-promptline { display: none; }
    .hp-searchwrap:focus-within .hp-strip:not(.single) { display: none; }
  }

  /* Result pins: the top few matches carry a visible label (proximity-tiered so
     they never overlap — see home-preview.ts plotSearchPins); the overflow gets
     .dot-only — label/odds/scope hidden visually but kept in the DOM for the hover
     tooltip + screen readers — so clustered matches stop piling up. */
  .hp-pin.dot-only .hp-lab,
  .hp-pin.dot-only .hp-odds,
  .hp-pin.dot-only .hp-scopetick { display: none; }
  /* .label-only: a labeled result sharing the ledger with other labels drops its
     odds + scope tick so each stacked row stays a single line (odds still live in
     the hover tooltip). A lone labeled result keeps its odds (showOdds path). */
  .hp-pin.label-only .hp-odds,
  .hp-pin.label-only .hp-scopetick { display: none; }

  /* Tidbit: clamp to 3 lines at rest; tap / Enter / Space toggles .expanded for
     the full insight (the full text is always in the DOM, so screen readers are
     unaffected — the clamp is purely visual). The chevron rotates when open. */
  .hp-tidbit-txt {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
  }
  .hp-tidbit.expanded .hp-tidbit-txt { -webkit-line-clamp: unset; overflow: visible; }
  /* The chevron + pointer affordance only appear when the text actually overflows
     the clamp — home-preview.ts adds .clampable after measuring. */
  .hp-tidbit-chev { display: none; }
  .hp-tidbit.clampable { cursor: pointer; }
  .hp-tidbit.clampable .hp-tidbit-chev {
    display: inline-flex; flex: none; align-self: flex-start; margin-top: 2px;
    color: var(--color-accent); transition: transform .25s ease; opacity: .7;
  }
  .hp-tidbit.clampable.expanded .hp-tidbit-chev { transform: rotate(180deg); }
  @media (prefers-reduced-motion: reduce) {
    #home-search-compact { transition: opacity 1ms; }
    .hp-tidbit-chev { transition: none; }
  }

  .hp-eyebrow {
    font-size: 11.5px; letter-spacing: .15em; text-transform: uppercase;
    color: var(--color-ink-muted); font-weight: 700; margin: 12px 0 8px;
    display: flex; align-items: center; gap: 9px;
  }
  .hp-eyebrow-ln { height: 1px; width: 26px; background: var(--color-line); }
  .hp-head {
    font-family: var(--font-serif, Georgia, serif); font-weight: 700;
    font-size: clamp(29px, 5.6vw, 50px); line-height: 1.04; letter-spacing: -.02em;
    margin: 0 0 10px; max-width: 17ch;
  }
  .hp-em { color: var(--color-warm); font-style: italic; }
  .hp-subhead { font-size: clamp(14.5px, 2vw, 17px); color: var(--color-ink-muted); margin: 0; max-width: 48ch; line-height: 1.5; }
  .hp-searchwrap { position: relative; margin: 22px auto 0; max-width: 760px; }

  /* Seek pulse — one-shot teal→amber underline cue when results land. */
  .hp-seekline {
    position: relative; height: 2.5px; margin: 0 16px 2px; border-radius: 3px;
    background: transparent; opacity: 0; overflow: hidden;
  }
  .hp-seekline .hp-seekbar {
    position: absolute; left: 50%; top: 0; bottom: 0; width: 0; border-radius: 3px;
    transform: translateX(-50%); opacity: 0;
    background: linear-gradient(90deg, var(--color-accent), var(--color-warm));
  }
  .hp-seekline.pulse { opacity: 1; }
  .hp-seekline.pulse .hp-seekbar { animation: hp-seekpulse .52s cubic-bezier(0.16,1,0.30,1) 1; }
  @keyframes hp-seekpulse {
    0% { width: 0; opacity: 0; }
    35% { width: 92%; opacity: 1; }
    100% { width: 92%; opacity: 0; }
  }
  @media (prefers-reduced-motion: reduce) {
    .hp-seekline, .hp-seekline.pulse .hp-seekbar { animation: none !important; opacity: 0 !important; }
  }

  .hp-strip {
    display: grid; grid-template-columns: 1fr 1fr 1fr;
    margin: 4px 16px 2px; border-top: 1px solid var(--color-line);
  }
  /* Live-typing accent: numbers turn teal (amber for over-rated myth cells) to
     signal the strip is showing live result counts — matches B7 .strip.live. */
  .hp-strip.live .hp-num { color: var(--color-accent); }
  .hp-strip.live .hp-cell.amber .hp-num { color: var(--color-warm); }
  .hp-cell {
    position: relative; padding: 9px 6px 8px; text-align: center;
    display: flex; flex-direction: column; align-items: center; gap: 2px;
    min-height: 46px; justify-content: center;
  }
  .hp-cell + .hp-cell::before {
    content: ""; position: absolute; left: 0; top: 22%; bottom: 22%;
    width: 1px; background: var(--color-line);
  }
  .hp-num { font-family: var(--font-serif, Georgia, serif); font-weight: 700; font-size: 17px; color: var(--color-ink); line-height: 1; font-variant-numeric: tabular-nums; }
  .hp-cap { font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase; color: var(--color-ink-muted); font-weight: 700; line-height: 1.1; }
  /* On results: collapse 3 cells → one centered localized summary line. */
  .hp-strip.single { display: flex; align-items: center; justify-content: center; padding: 9px 6px 8px; min-height: 46px; }
  .hp-strip.single .hp-cell { display: none; }
  .hp-strip.single #hp-cellA { display: flex; padding: 0; min-height: 0; }
  .hp-strip.single #hp-cellA::before { display: none; }
  .hp-strip.single .hp-num, .hp-strip.single .hp-cap { display: none; }
  .hp-strip.single .hp-summary { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; letter-spacing: .03em; color: var(--color-accent); font-weight: 700; line-height: 1.3; text-align: center; }

  /* Labeled Clear pill — a calm, discoverable exit from search mode, shown beside
     the live result summary (home-preview.ts toggles its [hidden]). Complements the
     in-input x; hidden at rest so it never occupies a stat-strip grid cell. */
  .hp-clearbtn {
    display: inline-flex; align-items: center; gap: 5px; margin-left: 12px;
    font-size: 11.5px; font-weight: 600; letter-spacing: .02em;
    color: var(--color-ink-muted); background: transparent;
    border: 1px solid var(--color-line); border-radius: 999px;
    padding: 5px 11px; min-height: 32px; cursor: pointer;
    transition: color .2s, border-color .2s, background .2s;
  }
  .hp-clearbtn[hidden] { display: none; }
  .hp-clearbtn:hover { color: var(--color-ink); border-color: var(--color-accent); background: color-mix(in srgb, var(--color-accent-dim) 30%, transparent); }
  .hp-clearbtn svg { width: 12px; height: 12px; flex: none; }

  .hp-promptline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 10px 0 12px; }
  .hp-lead { font-size: 12px; color: var(--color-ink-muted); }
  .hp-lead em { font-style: italic; font-weight: 600; }
  .hp-chiprotator { display: inline-flex; flex-wrap: wrap; gap: 8px; align-items: center; }
  .hp-chip {
    font-size: 12.5px; color: var(--color-ink-muted); background: var(--color-bg-card);
    border: 1px solid var(--color-line); border-radius: 999px; padding: 7px 13px;
    cursor: pointer; min-height: 44px; display: inline-flex; align-items: center; gap: 6px;
    transition: transform .2s cubic-bezier(0.34,1.56,0.64,1), border-color .2s, color .2s, opacity .32s cubic-bezier(0.16,1,0.30,1);
  }
  .hp-chip:hover { transform: translateY(-2px); border-color: var(--color-accent); color: var(--color-accent); }
  /* Mobile: one-line horizontal scroll carousel instead of wrapping to 3 lines.
     The "Try:" lead stays pinned; the chip row takes the remaining width and
     scrolls. Chips never shrink/wrap; a right-edge fade hints there's more. */
  @media (max-width: 600px) {
    .hp-promptline { flex-wrap: nowrap; }
    .hp-chiprotator {
      flex: 1; min-width: 0; flex-wrap: nowrap; overflow-x: auto;
      scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch;
      scrollbar-width: none;
      -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
      mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent);
    }
    .hp-chiprotator::-webkit-scrollbar { display: none; }
    .hp-chip { flex: none; white-space: nowrap; scroll-snap-align: start; }
  }

  .hp-resmeta { display: flex; gap: 8px; align-items: center; font-size: 11.5px; color: var(--color-ink-muted); letter-spacing: .04em; min-height: 18px; margin: 10px 0 0; }
  /* Collapse the reserved meta line when the controller leaves it empty — its
     min-height + margins otherwise wedge ~30px of dead space between the scale
     and the tidbit, holding the cited insight further from the ledger than it
     needs to be. Shows (and re-reserves height) the moment text lands. */
  .hp-resmeta:empty { display: none; }

  /* Contextual tidbit (B7 .tidbit) — teal-edged cited insight for the top match.
     Fades in via .in (the [hidden] attribute is toggled by home-preview.ts). */
  .hp-tidbit {
    display: flex; align-items: flex-start; gap: 10px;
    max-width: 64rem; margin: 8px auto 0;
    background: color-mix(in srgb, var(--color-accent-dim) 50%, var(--color-bg-card));
    border: 1px solid color-mix(in srgb, var(--color-accent) 26%, var(--color-line));
    border-left: 3px solid var(--color-accent);
    border-radius: 12px; padding: 11px 15px;
    font-size: 13px; line-height: 1.5; color: var(--color-ink);
    opacity: 0; transform: translateY(6px);
    transition: opacity .42s cubic-bezier(0.16,1,0.30,1), transform .42s cubic-bezier(0.16,1,0.30,1);
  }
  .hp-tidbit[hidden] { display: none; }
  .hp-tidbit.in { opacity: 1; transform: none; }
  .hp-tidbit-badge { flex: none; display: inline-flex; color: var(--color-accent); margin-top: 1px; }
  .hp-tidbit-badge svg { width: 15px; height: 15px; }
  .hp-tidbit-txt { flex: 1; }
  @media (prefers-reduced-motion: reduce) {
    .hp-tidbit { transition: none !important; transform: none !important; }
  }

  /* ── Ledger (phase 3) ── */
  .hp-ledgerwrap {
    max-width: 64rem; margin: 14px auto 0; position: relative;
    background: var(--color-bg-card); border: 1px solid var(--color-line);
    border-radius: 18px; padding: 12px clamp(16px, 3vw, 26px) 10px; overflow: hidden;
  }
  .hp-ledgerhead { display: flex; align-items: flex-end; justify-content: space-between; gap: 10px; margin-bottom: 4px; }
  .hp-ledgert { font-size: 11.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--color-ink-muted); font-weight: 700; }
  .hp-ledgerlive { font-size: 10px; color: var(--color-accent); display: flex; align-items: center; gap: 6px; letter-spacing: .1em; }
  .hp-ledgerlive .hp-d { width: 6px; height: 6px; border-radius: 50%; background: var(--color-accent); }
  /* Reserve the plot height so client pins never cause CLS. */
  /* Height gives the bottom-anchored pin labels room to clear the top region
     labels. At the wide full-odds desktop form the anchor label ("Chronic back
     pain" / "Phone at gas pump") sat ~4px into the region label above it; the
     taller plot opens a comfortable gap. Mobile's compact odds already cleared,
     and 172px keeps it clear there too — so one height serves both. */
  .hp-plot { position: relative; height: 172px; margin-top: 6px; }
  .hp-regionlab { position: absolute; top: 2px; font-style: italic; font-size: 12.5px; color: var(--color-ink-muted); pointer-events: none; transition: opacity .3s cubic-bezier(0.16,1,0.30,1); }
  .hp-regionlab.left { left: 0; } .hp-regionlab.right { right: 0; text-align: right; }
  .hp-scale { position: absolute; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; overflow: visible; }
  .hp-scaleticks { position: absolute; left: 0; right: 0; bottom: 6px; height: 22px; pointer-events: none; }
  .hp-tk { position: absolute; transform: translateX(-50%); font-size: 9.5px; color: var(--color-ink-muted); white-space: nowrap; text-align: center; }

  .hp-pin {
    position: absolute; bottom: 34px; transform: translateX(-50%);
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    transition: left .62s cubic-bezier(0.22,1,0.36,1), opacity .4s cubic-bezier(0.16,1,0.30,1), filter .3s;
    cursor: pointer; will-change: left, opacity;
  }
  .hp-pin .hp-lab { font-size: 10.5px; line-height: 1.15; color: var(--color-ink-muted); text-align: center; max-width: 96px; background: color-mix(in srgb, var(--color-bg-card) 86%, transparent); padding: 1px 4px; border-radius: 4px; }
  .hp-pin .hp-odds { font-size: 12.5px; color: var(--color-ink); font-weight: 700; white-space: nowrap; }
  .hp-pin .hp-scopetick { font-size: 8.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--color-ink-muted); font-weight: 700; line-height: 1; margin-top: 1px; opacity: .85; }
  .hp-pin .hp-stem { width: 1.5px; height: 18px; background: currentColor; opacity: .5; }
  .hp-pin .hp-head { width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--color-bg-card); box-shadow: 0 1px 3px rgba(0,0,0,.3); position: relative; }
  .hp-pin.amber { color: var(--color-warm); } .hp-pin.amber .hp-head { background: var(--color-warm); }
  .hp-pin.teal  { color: var(--color-accent); } .hp-pin.teal .hp-head { background: var(--color-accent); }
  .hp-pin.myth  { color: var(--color-warm); } .hp-pin.myth .hp-head { background: var(--color-warm); }
  /* Calibrated / unclassified — neutral gray so the legend's colour→meaning map
     is honest (amber is over-rated only). currentColor drives the stem + the
     hollow recent-pin ring, so a gray recent pin reads as a gray ring. */
  .hp-pin.gray  { color: var(--color-ink-muted); } .hp-pin.gray .hp-head { background: var(--color-ink-muted); }
  /* Display-only showcase pins → pointer-transparent. The big odds pill has an
     opaque padded box; with pointer-events it intercepted hover/click across a
     wide area, blocking the ambient/recent/result pins beneath it (and, since it
     has no handler, the "click did nothing but stole focus" jitter). Anchors carry
     no JS listeners, so dropping pointer-events is safe and lets clicks fall
     through to the real pins. */
  .hp-pin.anchor { z-index: 3; pointer-events: none; }
  .hp-pin.anchor .hp-odds { font-size: 18px; line-height: 1.05; letter-spacing: -.015em; padding: 2px 7px; border-radius: 6px; background: color-mix(in srgb, var(--color-bg-card) 92%, transparent); box-shadow: 0 1px 3px rgba(33,58,82,.10); }
  .hp-pin.anchor .hp-lab { font-size: 11px; max-width: 96px; font-weight: 500; }
  .hp-pin.anchor .hp-head { width: 11px; height: 11px; }
  /* B7 dual odds form: full ("1 in 1,000,000,000") on desktop, abbreviated
     ("~1 in 1.0B" / "~4 in 5") swapped in at mobile so the rightmost anchor
     never overflows the ledger at 375px (fusion-B7 lines 830-831, 838). */
  .hp-pin.anchor .hp-od-comp { display: none; }
  @media (max-width: 600px) {
    .hp-pin.anchor .hp-odds { font-size: 14px; padding: 1px 5px; }
    .hp-pin.anchor .hp-od-full { display: none; }
    .hp-pin.anchor .hp-od-comp { display: inline; }
  }
  /* Expanding-ring pseudo-element so the anchor pulse fires a ring (B7 parity). */
  .hp-pin.anchor .hp-head::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; border: 1.5px solid currentColor; opacity: 0; }
  .hp-pin.ambient { opacity: .72; } .hp-pin.ambient .hp-head { width: 10px; height: 10px; }
  .hp-pin.ambient .hp-lab, .hp-pin.ambient .hp-odds { display: none; }
  .hp-pin.ambient .hp-scopetick { display: none; }
  .hp-pin.ambient .hp-stem { height: 13px; opacity: .35; }
  .hp-pin.ambient.fade { opacity: 0; }
  .hp-pin.enter { animation: hp-pin-drop .6s cubic-bezier(0.34,1.56,0.64,1) both; }
  /* Staggered entry: on a NEW query the incoming pins wait ~.34s (the outgoing
     pins fade over .4s / are removed at .32s) so the swap reads as "old leaves,
     then new arrives" rather than the two overlapping. `both` holds the from-state
     (opacity:0) through the delay so the pin is invisible until it drops in. */
  .hp-pin.enter-late { animation: hp-pin-drop .6s cubic-bezier(0.34,1.56,0.64,1) .34s both; }
  @keyframes hp-pin-drop { from { opacity: 0; transform: translateX(-50%) translateY(-12px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }
  .hp-pin.hot .hp-head { transform: scale(1.35); }
  /* Rank number — the result-list position, rendered CENTRED INSIDE the pin-head
     dot (not an offset side chip). The rank is a CHILD of the head, filling it
     (inset:0) and flex-centring the cream digit — so it's dead-centre on the dot
     and rides the head's .hot/.linked scale transforms automatically (a child of a
     transformed element scales with it). Direction-agnostic → correct under RTL too
     (the old `left: calc(50% + 7px)` side chip was physical-left, wrong on /ar). */
  .hp-pin .hp-head .hp-rank {
    position: absolute; inset: 0;
    display: none; align-items: center; justify-content: center;
    color: var(--color-bg-card);
    font: 700 9px/1 ui-monospace, "SFMono-Regular", Menlo, monospace;
    text-shadow: 0 0.5px 0.5px rgba(0,0,0,.35);
    pointer-events: none;
  }
  .hp-pin.ranked .hp-head .hp-rank { display: flex; }
  /* Two-digit ranks (10+): shrink the digits so they stay inside the 14px head. */
  .hp-pin.rank-2d .hp-head .hp-rank { font-size: 7px; letter-spacing: -0.5px; }
  .hp-pin.anchor.pulse .hp-head { animation: hp-anchor-pop .62s cubic-bezier(0.34,1.56,0.64,1); }
  @keyframes hp-anchor-pop { 0% { transform: scale(1); } 38% { transform: scale(1.5); } 100% { transform: scale(1); } }
  .hp-pin.anchor.pulse .hp-head::after { opacity: .85; animation: hp-ring 1s cubic-bezier(0.16,1,0.30,1) 1; }
  @keyframes hp-ring { 0% { transform: scale(1); opacity: .85; } 70% { transform: scale(2); opacity: 0; } 100% { opacity: 0; } }

  /* During search the two exemplar anchors HIDE entirely (fade out) so the ledger
     shows only the result pins — the anchors are resting-state orientation, noise
     once you have your own matches. EXCEPTIONS stay visible: an anchor the query
     itself matched (.hp-hit — it's deduped to a pulse, not a result pin, so without
     this it would vanish), and a hovered card's linked anchor (.linked). The live
     count follows suit (home-preview.ts setLedgerLive counts .hp-hit) so "showing
     N" stays honest. */
  .home-preview-root.hp-searching .hp-pin.anchor:not(.linked):not(.hp-hit) { opacity: 0; pointer-events: none; }
  /* Edge anchor labels: an exemplar sitting at the axis end (e.g. "Chronic back
     pain" at the certain end) has its centred label overhang the plot and an
     overflow-clip ancestor truncates it ("…ck pain"). Shift ONLY the label + odds
     (each by its own %, so width-robust) to hang inward — the dot stays truthful.
     Same trick as RiskLens rl-edge. Rest-only (anchors hide during search). */
  .hp-pin.anchor.hp-edge-l .hp-lab,
  .hp-pin.anchor.hp-edge-l .hp-odds { transform: translateX(calc(50% + 4px)); }
  .hp-pin.anchor.hp-edge-r .hp-lab,
  .hp-pin.anchor.hp-edge-r .hp-odds { transform: translateX(calc(-50% - 4px)); }
  /* Card ↔ ledger hover link (home-preview.ts highlightPin). The pin for the hovered
     result card pops (.linked); the others recede (.dimmed). */
  .hp-pin.dimmed { opacity: .28; }
  .hp-pin.linked { opacity: 1; z-index: 6; }
  .hp-pin.linked .hp-head { transform: scale(1.4); box-shadow: 0 0 0 4px color-mix(in srgb, currentColor 28%, transparent); }

  /* Card-side rank badge — the other half of the ledger's map-legend. Injected by
     home-preview.ts annotateCards with the SAME digit + framing colour as the pin
     head, so dot↔card pairing reads statically (no hover needed → works on touch).
     Chip mirrors the .hp-head look: filled circle, cream digit, card-colour ring. */
  .hp-cardrank {
    display: inline-flex; align-items: center; justify-content: center;
    width: 18px; height: 18px; border-radius: 50%; flex: none;
    color: var(--color-bg-card);
    font: 700 10px/1 ui-monospace, "SFMono-Regular", Menlo, monospace;
    border: 2px solid var(--color-bg-card);
    box-shadow: 0 1px 3px rgba(0,0,0,.3);
    pointer-events: none;
  }
  .hp-cardrank.teal  { background: var(--color-accent); }
  .hp-cardrank.amber { background: var(--color-warm); }
  .hp-cardrank.gray  { background: var(--color-ink-muted); }
  .hp-cardrank.rank-2d { font-size: 8px; letter-spacing: -.25px; }
  /* Canonical grid cards are position:relative — float the chip over the image
     corner. Logical inset → mirrors correctly under RTL (/ar, /fa). Compact
     typeahead rows are flex — the chip just leads the row as an inline item. */
  .card > .hp-cardrank { position: absolute; top: 8px; inset-inline-start: 8px; z-index: 2; }
  /* Pin-hover/-focus → ring the matching card (reverse of the card-hover pin
     emphasis). Neutral ink ring — teal/amber stay reserved for framing meaning.
     Keyed off a data-attribute, NOT a class: the search panels' MutationObserver
     filters on class mutations, and a hover must not re-fire the ledger sync. */
  [data-hp-cardlink] { outline: 2px solid color-mix(in srgb, var(--color-ink) 55%, transparent); outline-offset: 2px; border-radius: 8px; }

  /* Recently-viewed risks — a quiet, navigable history layer (home-preview.ts
     plotRecentPins). Hollow ring head + label-only so they read as visited and
     stay subordinate to the two labeled anchors. At rest only; hidden in search. */
  .hp-pin.recent { z-index: 2; opacity: .92; }  /* underline opt-out via .no-underline class */
  .hp-pin.recent .hp-odds { display: none; }
  .hp-pin.recent .hp-head {
    width: 11px; height: 11px;
    background: var(--color-bg-card);
    border: 2px solid currentColor;
    box-shadow: 0 1px 2px rgba(0,0,0,.18);
  }
  .hp-pin.recent .hp-stem { opacity: .4; }
  /* Alternate tier — a taller stem lifts the label to a second row so adjacent
     recent pins never collide their labels (home-preview.ts assigns tier-a/tier-b
     by axis order). 48px clears a two-line tier-a label (~26px) with a small gap
     while still keeping tier-b under the top region labels in the 172px plot
     (measured 0-overlap + 14px region clearance at 375px and 1280px). A third
     clustered recent overflows to a dot-only pin rather than a colliding tier-c. */
  .hp-pin.recent.tier-b .hp-stem { height: 48px; }
  .hp-pin.recent .hp-lab { font-weight: 600; max-width: 84px; }
  /* Same multi-row lift for the search-result label layer (home-preview.ts
     plotSearchPins proximity-tiers the top matches). tier-a is the default stem;
     tier-b/c raise the label onto higher rows so up to three clustered result
     labels never overprint. 74px (tier-c) still clears the top region labels —
     which dim to .3 during search — in the 172px plot. */
  .hp-pin.tier-b .hp-stem { height: 48px; }
  .hp-pin.tier-c .hp-stem { height: 74px; }
  .hp-pin.recent:hover, .hp-pin.recent:focus-visible { opacity: 1; outline: none; }
  .hp-pin.recent:focus-visible .hp-head { box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 40%, transparent); }
  .home-preview-root.hp-searching .hp-pin.recent { display: none; }

  /* Ledger key — three always-on colour swatches (framing) + a recently-viewed
     ring that reveals on demand. Centred, wraps on a narrow phone. */
  .hp-legend {
    list-style: none; padding: 0;
    display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
    gap: 6px 14px; margin: 10px 0 0;
    font-size: 10.5px; letter-spacing: .03em; color: var(--color-ink-muted);
  }
  .hp-lgi { display: inline-flex; align-items: center; gap: 5px; }
  .hp-lgmark {
    width: 10px; height: 10px; border-radius: 50%; flex: none;
    border: 2px solid var(--color-bg-card);
    box-shadow: 0 1px 2px rgba(0,0,0,.22);
  }
  .hp-lgmark.teal  { background: var(--color-accent); }
  .hp-lgmark.amber { background: var(--color-warm); }
  /* Recently-viewed = hollow ring, mirroring the recent pin's .hp-head. */
  .hp-lgmark.ring {
    background: var(--color-bg-card);
    border-color: var(--color-ink-muted);
  }
  /* The recent key stays out of layout until ≥1 recent pin lands (home-preview.ts
     adds .show), and hides again during search (recent pins are hidden then). The
     colour keys remain — result pins are still colour-coded while searching. */
  .hp-lg-recent { display: none; }
  .hp-lg-recent.show { display: inline-flex; }
  .home-preview-root.hp-searching .hp-lg-recent { display: none; }

  .hp-pintip { position: absolute; z-index: 12; pointer-events: none; transform: translate(-50%, -100%); background: var(--color-ink); color: var(--color-bg-card); border-radius: 8px; padding: 6px 10px; max-width: 200px; opacity: 0; transition: opacity .16s ease; font-size: 11.5px; line-height: 1.3; text-align: center; }
  .hp-pintip.on { opacity: 1; }
  /* Rank chip in the tooltip — same digit as the pin head + card badge, so the
     tooltip reinforces the pairing key. Empty (anchor/recent/ambient) → hidden;
     .nm is inline so the chip shares the name's line, .od still breaks below. */
  .hp-pintip .rk { display: none; }
  .hp-pintip .rk:not(:empty) { display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; border-radius: 50%; border: 1px solid currentColor; margin-inline-end: 5px; font: 700 9px/1 ui-monospace, "SFMono-Regular", Menlo, monospace; vertical-align: -2px; }
  .hp-pintip .nm { font-weight: 600; display: inline; }
  .hp-pintip .od { font-weight: 700; margin-top: 2px; display: block; }

  .hp-scopenote { margin: 10px 0 0; font-size: 10.5px; line-height: 1.4; color: var(--color-ink-muted); text-align: center; letter-spacing: .01em; }
  .hp-scopenote .hp-more { color: var(--color-accent); text-decoration: none; font-weight: 600; white-space: nowrap; }
  .hp-scopenote .hp-more:hover { text-decoration: underline; }
  /* Reserve ticker height so the client-populated line never shifts layout. */
  .hp-ticker { margin: 8px 0 0; min-height: 16px; text-align: center; font-size: 11px; color: var(--color-ink-muted); transition: opacity .35s cubic-bezier(0.16,1,0.30,1); }
  .hp-ticker .lead { font-weight: 700; letter-spacing: .06em; text-transform: uppercase; font-size: 9.5px; color: var(--color-ink-muted); margin-right: 6px; }
  .hp-ticker .nm { color: var(--color-ink); font-weight: 600; }
  .hp-ticker .od { font-family: var(--font-serif, Georgia, serif); color: var(--color-ink); font-weight: 700; }
  .hp-ticker.swap, .hp-ticker:empty { opacity: 0; }

  /* ── Scroll chapters (phase 3) ── */
  .hp-sec { padding: 46px 0 30px; }
  .hp-sec--decisions, .hp-sec--gap, .hp-sec--close { border-top: 1px solid color-mix(in srgb, var(--color-line) 60%, transparent); }
  .hp-sec--close { padding-bottom: 64px; }
  .hp-chaptertitle { font-family: var(--font-serif, Georgia, serif); font-weight: 700; font-size: clamp(22px, 3.6vw, 32px); letter-spacing: -.02em; margin: 0 0 6px; }
  .hp-chaptersub { font-size: clamp(13.5px, 1.7vw, 15.5px); color: var(--color-ink-muted); margin: 0 0 18px; max-width: 56ch; line-height: 1.5; }
  .hp-staticgrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
  @media (max-width: 899px) { .hp-staticgrid { grid-template-columns: repeat(2, 1fr); } }
  @media (max-width: 439px) { .hp-staticgrid { grid-template-columns: 1fr; } }

  .hp-reveal { opacity: 0; transform: translateY(26px); transition: opacity .7s cubic-bezier(0.16,1,0.30,1), transform .8s cubic-bezier(0.22,1,0.36,1); will-change: opacity, transform; }
  .hp-reveal.in { opacity: 1; transform: none; }
  .hp-reveal.hp-d1 { transition-delay: .06s; } .hp-reveal.hp-d2 { transition-delay: .14s; } .hp-reveal.hp-d3 { transition-delay: .22s; }

  /* ── Receipts (phase 3) ── */
  .hp-closing { text-align: center; max-width: 720px; margin: 0 auto; }
  .hp-big { font-family: var(--font-serif, Georgia, serif); font-size: clamp(20px, 3vw, 28px); line-height: 1.3; color: var(--color-ink); margin: 0 0 14px; }
  .hp-big em { color: var(--color-warm); font-style: italic; }
  .hp-authorities { margin: 0 0 22px; font-size: 13px; color: var(--color-ink-muted); line-height: 1.7; }
  .hp-authlead { display: block; margin-bottom: 9px; font-size: 12px; letter-spacing: .02em; }
  .hp-wordmarks { display: inline-flex; flex-wrap: wrap; gap: 7px; justify-content: center; }
  .hp-wm { font-size: 12px; font-weight: 700; letter-spacing: .03em; color: var(--color-ink); background: var(--color-bg-card); border: 1px solid var(--color-line); border-radius: 7px; padding: 5px 10px; }
  .hp-wm.jrnl { font-weight: 600; font-style: italic; color: var(--color-ink-muted); }

  .hp-receipt { text-align: left; max-width: 520px; margin: 0 auto 20px; background: var(--color-bg-card); border: 1px solid var(--color-line); border-radius: 13px; padding: 15px 17px 14px; box-shadow: 0 1px 2px rgba(33,58,82,.06), 0 4px 14px -6px rgba(33,58,82,.16); }
  .hp-rhead { display: flex; align-items: center; gap: 8px; margin-bottom: 9px; font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--color-ink-muted); font-weight: 700; }
  .hp-tag { display: inline-flex; align-items: center; gap: 5px; color: var(--color-accent); background: var(--color-accent-dim); border: 1px solid color-mix(in srgb, var(--color-accent) 35%, transparent); border-radius: 999px; padding: 2px 9px; letter-spacing: .04em; }
  .hp-tag svg { width: 12px; height: 12px; }
  .hp-claim { font-family: var(--font-serif, Georgia, serif); font-size: 16px; font-weight: 700; color: var(--color-ink); margin: 0 0 4px; letter-spacing: -.01em; }
  .hp-receipt .hp-odds { font-family: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace; font-size: 12.5px; color: var(--color-ink-muted); margin: 0 0 11px; }
  .hp-framing { color: var(--color-warm); }
  .hp-source { font-size: 12px; color: var(--color-ink-muted); margin: 0 0 7px; }
  .hp-source b { color: var(--color-ink); font-weight: 600; }
  .hp-excerpt { font-size: 13px; line-height: 1.55; color: var(--color-ink); margin: 0 0 13px; border-left: 3px solid var(--color-accent); padding: 4px 0 4px 12px; background: color-mix(in srgb, var(--color-accent-dim) 30%, transparent); border-radius: 0 6px 6px 0; font-style: italic; }
  .hp-links { display: flex; flex-wrap: wrap; gap: 8px; }
  .hp-srclink { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 14px; border-radius: 9px; text-decoration: none; font-size: 12.5px; font-weight: 600; color: var(--color-accent); background: var(--color-bg-card); border: 1px solid var(--color-line); transition: background .2s, border-color .2s, transform .18s cubic-bezier(0.34,1.56,0.64,1); }
  .hp-srclink:hover { border-color: var(--color-accent); transform: translateY(-1px); }
  .hp-takeaway { font-size: 12.5px; color: var(--color-ink-muted); line-height: 1.55; max-width: 560px; margin: 0 auto; }
  .hp-takeaway b { color: var(--color-ink); font-weight: 600; }
  .hp-honesty { font-size: 13px; color: var(--color-ink-muted); line-height: 1.55; max-width: 560px; margin: 14px auto 0; padding-top: 12px; border-top: 1px solid var(--color-line); }
  .hp-honesty b { color: var(--color-ink); font-weight: 700; font-variant-numeric: tabular-nums; }
  @media (max-width: 520px) { .hp-links { flex-direction: column; } .hp-srclink { width: 100%; justify-content: center; } }

  @media (prefers-reduced-motion: reduce) {
    .hp-reveal { opacity: 1 !important; transform: none !important; }
    .hp-pin { transition: none !important; }
  }