
    /* ---------------------------------------------------------------
       reference/results-loading.html
       ESA-letter results-loading reference, adapted from the reference per
       the Waggy pivot (skills/results-loading.md, ESA-letter rebrand).

       Four screens, all on the teal page surface
       (--wag-component-surface-page-teal-*). The same chrome
       (Waggy wordmark, headline-with-stat-pill,
       coral-diamond divider, coral progress bar) carries across
       every calculating stage; the stage-visual slot is what
       differs.

         Stage 1 — Scoring symptoms (animated checklist)
           Loader visual: a vertical list of system tasks resolving
           one-by-one (Connecting database → Extracting symptoms →
           Cross-referencing DSM-5 → Verifying housing protections).
           Each row replaces a mint pulse-dot with a green check as
           it completes. Coral progress bar at ~28%.

         Stage 2 — Your protections preview (2x2 benefit grid)
           Reuses the included-feature-card token from plan-select.
           Four mint cards: No-pet-rent waiver, Travel cabin access,
           Apartment approval, Public housing protection. Coral
           progress bar at ~62%.

         Stage 3 — Clinician match (stacked sub-progress bars)
           Three thin sub-bars filling at different rates, each with
           an eyebrow label and a percentage. Reads as "we are
           finalizing several things in parallel." Coral progress bar
           at ~88%.

         Stage 4 — Score reveal
           Teal upper half: headline + coral speech bubble with
           downward tail ("YOUR QUALIFICATION SCORE / High match")
           + stylized ESA-letter preview with a coral ELIGIBLE stamp
           overlay. White-card lower half: subhead, hero photo
           placeholder, body, three coral-icon ESA-rows, coral
           Continue CTA, escape stack, safety-disclosure link.
           Warm-tan footnote band at the very bottom.
    --------------------------------------------------------------- */

    *, *::before, *::after { box-sizing: border-box; }

    html, body {
      margin: 0;
      padding: 0;
      /* Teal at the html/body level so the loader stages and the score
         reveal both bleed edge-to-edge to the viewport — no cream gutter
         on the left/right of the card on desktop, no cream peek above
         the headline on a tall mobile screen. The reveal page repaints
         its lower regions (.reveal-content-card = white, .reveal-footnote
         = warm-tan) on top of this teal canvas, but the upper hero stays
         continuous with the body background, so there's no visible seam
         where the card meets the surrounding chrome. */
      background: var(--wag-component-surface-page-teal-background-color);
      color: var(--wag-component-surface-page-teal-text-color);
      font-family: var(--wag-typography-body-md-font-family);
      font-size: var(--wag-typography-body-md-font-size);
      line-height: var(--wag-typography-body-md-line-height);
      -webkit-font-smoothing: antialiased;
      text-rendering: optimizeLegibility;
    }

    .reference-frame {
      display: grid;
      grid-template-columns: 1fr;
      gap: var(--wag-spacing-xxl);
      max-width: 1080px;
      margin: 0 auto;
      padding: var(--wag-spacing-xl) var(--wag-spacing-gutter);
    }

    .variant-label {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: var(--wag-spacing-md);
      margin: 0 0 var(--wag-spacing-gutter);
      font-family: var(--wag-typography-eyebrow-font-family);
      font-size: var(--wag-typography-eyebrow-font-size);
      font-weight: var(--wag-typography-eyebrow-font-weight);
      letter-spacing: var(--wag-typography-eyebrow-letter-spacing);
      line-height: var(--wag-typography-eyebrow-line-height);
      color: var(--wag-color-outline-strong);
      text-transform: uppercase;
    }

    .replay-button {
      cursor: pointer;
      border: 1px solid var(--wag-color-outline);
      background: transparent;
      color: var(--wag-color-ink);
      border-radius: var(--wag-rounded-full);
      padding: 6px 14px;
      font-family: var(--wag-typography-label-md-font-family);
      font-size: var(--wag-typography-label-md-font-size);
      font-weight: var(--wag-typography-label-md-font-weight);
      letter-spacing: 0.04em;
    }
    .replay-button:hover { background: var(--wag-color-surface-pill-deselected); }

    /* ---------- Page surface (teal for the three calculating stages) ----------

       The three calculating stages share a fixed canvas height so the
       page never reflows when one stage hands off to the next: the
       logo stays pinned at the top, the coral-fill bar stays pinned
       at the bottom, and the stage-visual region in the middle
       expands/centers inside the leftover space. This matches the
       Reference evidence (Mobile/01-calculating-progress-1.png and
       …-progress-2.png are pixel-identical canvas heights).

       The score-reveal page is its own composition (.reveal-page);
       it does not inherit this fixed height. */

    /* Scoped to #flow-host (unique to the matching/loader step) rather
       than the bare .wag-page class. quiz-question.css, interstitial.css,
       checkout.css, and plan-select.css each define their OWN .wag-page
       for their own step type, on the assumption that only one of these
       "recipe" stylesheets is loaded per page. The combined funnel loads
       all of them on one document, so an unscoped .wag-page here would
       both leak this stage's flex/teal/min-height rules onto every other
       step AND get its own margin/max-width clobbered by whichever of
       those other rules happens to win the cascade (in practice: this
       rule's `margin: 0` survives but quiz-question.css's leaked
       `max-width: 500px` does too, since nothing here overrides it —
       producing a flush-left, off-center loader instead of the centered
       column the demo shows). #flow-host scoping fixes both: it can't
       leak out, and `max-width: none` below explicitly cancels the
       inherited 500px cap so the percentage-padding centering trick
       actually runs full-width as designed. */
    #flow-host .wag-page {
      /* Full-bleed teal canvas. The teal background is painted on
         html/body (above) so it extends to the viewport edges on
         every screen size; .wag-page itself is now a transparent
         flex container that just lays out the headline / stage-visual /
         divider / coral-bar stack on top of that canvas.

         The horizontal padding uses a max(gutter, …) trick so the
         INNER CONTENT stays at most 500px wide and centered — even
         though the surrounding teal bleeds full-width. On a narrow
         phone the formula collapses to the plain gutter; on a wide
         desktop it expands to push the content into a centered
         column. This matches the reference's calculating screens where
         the teal fills the whole viewport but the headline + chart +
         coral bar all sit inside a phone-shaped column in the middle.

         LAYOUT NOTE: Children pack to the TOP with their natural
         spacing (justify-content: flex-start). On Reference's reference
         screenshots the logo / headline / visual / divider / status /
         coral bar sit as a compact cluster in the top ~60-70% of the
         viewport, and the bottom is just empty teal breathing room.
         We do NOT use flex: 1 1 auto on the visual to spread content
         vertically — that produces giant gaps on tall desktops. */
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      min-height: 100vh;
      height: 100%;
      margin: 0;
      max-width: none;
      padding:
        var(--wag-spacing-md)
        max(var(--wag-spacing-gutter), calc((100% - 500px) / 2))
        var(--wag-spacing-xl);
      background: transparent;
      color: var(--wag-component-surface-page-teal-text-color);
    }

    /* The stage-visual flows naturally between the headline and the
       coral-diamond divider with its intrinsic height. We don't expand
       it as a flex-spacer because that pushed the chrome to the
       viewport floor on tall desktop screens, producing huge empty
       gaps between the headline and the visual and between the visual
       and the bar. Reference's reference packs everything tight near the
       top, with empty teal below — this matches that. */
    .stage-visual {
      flex: 0 0 auto;
      display: flex;
      flex-direction: column;
      margin-bottom: var(--wag-spacing-lg);
    }
    /* Children of .stage-visual should not double-pad the divider. */
    .stage-visual > *:last-child { margin-bottom: 0; }

    /* ---------- wag-photo-placeholder primitive ---------- */

    .wag-photo-placeholder {
      background: var(--wag-component-photo-placeholder-background-color);
      color: var(--wag-component-photo-placeholder-text-color);
      border: 1px dashed var(--wag-color-outline);
      border-radius: var(--wag-component-photo-placeholder-rounded);
      display: grid;
      place-items: center;
      padding: var(--wag-spacing-md);
      text-align: center;
      overflow: hidden;
    }
    .wag-photo-placeholder__label {
      font-family: var(--wag-component-photo-placeholder-font-family);
      font-size: var(--wag-component-photo-placeholder-font-size);
      font-weight: var(--wag-component-photo-placeholder-font-weight);
      line-height: var(--wag-component-photo-placeholder-line-height);
      letter-spacing: 0.02em;
      max-width: 28ch;
    }
    .wag-photo-placeholder[data-aspect="16/9"] { aspect-ratio: 16 / 9; }
    .wag-photo-placeholder[data-aspect="4/3"]  { aspect-ratio: 4 / 3; }
    .wag-photo-placeholder[data-aspect="1/1"]  { aspect-ratio: 1 / 1; }

    /* ---------- Shared chrome: Waggy wordmark ---------- */

    .wag-loading-logo {
      display: flex;
      align-items: center;
      justify-content: center;
      margin: 0 0 var(--wag-spacing-lg);
      color: var(--wag-color-on-dark);
    }
    /* Waggy brand lockup at the top of each loader stage.
       Uses the same on-dark PNG that ships on the competitor-compare
       interstitial (coral heart mark + white "Waggy"
       wordmark). The native asset is 989×356 (~2.78:1). Rendered at
       110px wide (~40px tall) so the lockup reads as a small brand
       stamp at the top of the page without competing with the
       headline below — same role as Reference's "Reference MED" header in
       the calculating-stage reference. Replaces the old uppercase
       text wordmark. */
    .wag-loading-logo .logo-wag-img {
      display: block;
      width: 110px;
      height: auto;
    }
    /* Legacy text fallback. The new templates use <img class="logo-wag-img">
       but if any older snapshot still uses the text span, hide it cleanly
       rather than letting it shout in two competing styles. */
    .wag-loading-logo .logo-reference {
      font-family: var(--wag-typography-label-md-font-family);
      font-size: var(--wag-typography-label-md-font-size);
      font-weight: var(--wag-typography-label-md-font-weight);
      letter-spacing: 0.08em;
      line-height: var(--wag-typography-label-md-line-height);
      text-transform: uppercase;
    }

    /* ---------- Headline + inline stat-pill ---------- */

    .loading-headline {
      margin: 0 auto var(--wag-spacing-xl);
      max-width: 26ch;
      text-align: center;
      font-family: var(--wag-typography-display-md-font-family);
      font-size: var(--wag-typography-display-md-font-size);
      font-weight: var(--wag-typography-display-md-font-weight);
      line-height: var(--wag-typography-display-md-line-height);
      letter-spacing: var(--wag-typography-display-md-letter-spacing);
      color: var(--wag-color-on-dark);
    }

    /* Stage 3 headline swap. Two <h1.loading-headline> elements live
       in the headline slot — the "searching" copy is visible at the
       start, the "found" copy is hidden, and the JS cross-fades them
       around the halfway point of Stage 3 (see results-loading.js,
       swapStage3Headline). We stack them so the layout doesn't jump
       during the swap. */
    .loading-headline[data-state] {
      transition: opacity 280ms ease-out;
    }
    .loading-headline[data-state="enter"] { opacity: 1; }
    .loading-headline[data-state="leave"] { opacity: 0; }
    .loading-headline[data-state="idle"]  { opacity: 0; }
    .loading-headline[hidden] { display: none; }
    @media (prefers-reduced-motion: reduce) {
      .loading-headline[data-state] { transition: none; }
    }
    .wag-stat-pill {
      /* Originally a mint-filled pill highlighting key nouns in the
         loader headlines ("eligibility", "protections", "state-licensed").
         Per design feedback the pill read as visual noise on the teal
         canvas, so we strip the background + ink color and let the
         <mark> tag's emphasized words simply inherit the white headline
         color. The element stays in the DOM (a) so production HTML can
         keep its <mark> markup unchanged, and (b) so we can reintroduce
         a different highlight treatment later without touching templates. */
      background: transparent;
      color: inherit;
      padding: 0;
      border-radius: 0;
      font-style: normal;
    }

    /* ---------- Stage-visual: scoring checklist (Stage 1) ---------- */

    .scoring-checklist {
      list-style: none;
      margin: 0 0 var(--wag-spacing-lg);
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--wag-spacing-sm);
    }
    .scoring-checklist li {
      display: grid;
      /* The status column is fixed-width (not auto) so the label
         column doesn't reflow as the status text swaps between
         QUEUED / WORKING / DONE. Without this, "Scoring symptom
         responses" (a 25-char label that's borderline two-line on
         mobile) wraps to one line only when its status is the
         shorter "DONE", making that row visibly shorter than the
         other three rows whose labels always wrap. Pinning the
         status width keeps the label column constant, so all four
         rows wrap identically and stay the same height across
         every state transition. */
      grid-template-columns: 28px 1fr 56px;
      align-items: center;
      gap: var(--wag-spacing-md);
      padding: var(--wag-spacing-sm) var(--wag-spacing-md);
      /* Floor every row to the natural two-line label height so
         "Scoring symptom responses" doesn't visually collapse to a
         single-line row on narrow viewports where the other three
         labels still wrap. The number matches the rendered height
         of a two-line body-md label at the current padding. */
      min-height: 56px;
      background: rgba(246, 244, 238, 0.06);
      border: 1px solid rgba(246, 244, 238, 0.12);
      border-radius: var(--wag-rounded-md);
      transition: background 240ms ease-out, border-color 240ms ease-out;
    }
    .scoring-checklist li[data-state="complete"] {
      background: rgba(108, 193, 182, 0.12);
      border-color: rgba(108, 193, 182, 0.32);
    }
    .scoring-checklist .indicator {
      position: relative;
      width: 24px;
      height: 24px;
      border-radius: var(--wag-rounded-full);
      display: grid;
      place-items: center;
      background: var(--wag-color-primary-soft);
      color: var(--wag-color-primary-deep);
      flex-shrink: 0;
    }
    .scoring-checklist li[data-state="active"] .indicator {
      background: var(--wag-color-surface-mint-pale);
      animation: indicator-pulse 1200ms ease-in-out infinite;
    }
    .scoring-checklist li[data-state="complete"] .indicator {
      background: var(--wag-color-success-green);
      color: var(--wag-color-on-dark);
    }
    .scoring-checklist li[data-state="pending"] .indicator {
      background: rgba(246, 244, 238, 0.18);
      color: rgba(246, 244, 238, 0.5);
    }
    .scoring-checklist .indicator svg {
      width: 14px;
      height: 14px;
      opacity: 0;
      transition: opacity 200ms ease-out;
    }
    .scoring-checklist li[data-state="complete"] .indicator svg { opacity: 1; }
    .scoring-checklist li[data-state="active"] .indicator::after {
      content: "";
      position: absolute;
      inset: 6px;
      border-radius: var(--wag-rounded-full);
      background: var(--wag-color-primary-deep);
    }
    .scoring-checklist .label {
      font-family: var(--wag-typography-body-md-font-family);
      font-size: var(--wag-typography-body-md-font-size);
      font-weight: 600;
      line-height: 1.3;
      color: var(--wag-color-on-dark);
    }
    .scoring-checklist li[data-state="pending"] .label { opacity: 0.55; }
    .scoring-checklist .status {
      font-family: var(--wag-typography-eyebrow-font-family);
      font-size: 10px;
      font-weight: var(--wag-typography-eyebrow-font-weight);
      letter-spacing: var(--wag-typography-eyebrow-letter-spacing);
      line-height: var(--wag-typography-eyebrow-line-height);
      text-transform: uppercase;
      color: var(--wag-color-on-dark);
      opacity: 0.7;
      /* Right-aligned inside its fixed 56px column so shorter status
         words (DONE) don't float to the left and leave a visible gap
         before the row's right edge. */
      text-align: right;
    }
    .scoring-checklist li[data-state="complete"] .status {
      color: var(--wag-color-surface-mint-pale);
      opacity: 1;
    }
    .scoring-checklist li[data-state="pending"] .status { opacity: 0.4; }

    @keyframes indicator-pulse {
      0%, 100% { transform: scale(1); opacity: 1; }
      50%      { transform: scale(0.85); opacity: 0.7; }
    }

    /* ---------- Stage-visual: protections grid (Stage 2) ----------

       A3 layout — horizontal cards. Each card is a 2-column grid:
       a circular icon chip on the left, the protection label on the
       right. The 2x2 outer grid is preserved on desktop + tablet so
       the visual envelope still matches stage 1 / stage 3 (four units
       of content, packed into the same shell-body cell), but on
       narrow phones it collapses to a single column so the labels
       get full width and the cards no longer have to fit a 1:1
       square (which previously left half of every card empty on
       small screens). */

    .protection-grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: var(--wag-spacing-sm);
      margin: 0 0 var(--wag-spacing-md);
    }
    .protection-card {
      display: grid;
      grid-template-columns: 44px 1fr;
      gap: var(--wag-spacing-sm);
      align-items: center;
      background: var(--wag-component-included-feature-card-background-color);
      color: var(--wag-component-included-feature-card-text-color);
      border-radius: var(--wag-component-included-feature-card-rounded);
      padding: 12px var(--wag-spacing-md);
    }
    .protection-card .icon {
      width: 44px;
      height: 44px;
      border-radius: var(--wag-rounded-full);
      background: var(--wag-color-primary);
      color: var(--wag-color-on-dark);
      display: grid;
      place-items: center;
    }
    .protection-card .icon svg { width: 22px; height: 22px; }
    /* Stagger-entrance hook. Cards start hidden + slightly translated,
       JS adds [data-state="enter"] one-by-one with an 80ms stagger to
       match the option-pill stagger documented in skills/motion.md. */
    .protection-card {
      opacity: 0;
      transform: translateY(8px);
      transition: opacity 320ms cubic-bezier(0.16, 1, 0.3, 1),
                  transform 320ms cubic-bezier(0.16, 1, 0.3, 1);
    }
    .protection-card[data-state="enter"] {
      opacity: 1;
      transform: translateY(0);
    }
    .protection-card p {
      margin: 0;
      font-family: var(--wag-typography-body-sm-font-family);
      font-size: var(--wag-typography-body-sm-font-size);
      font-weight: 600;
      line-height: 1.3;
      color: var(--wag-color-ink);
    }
    .protection-grid-footnote {
      margin: 0 auto var(--wag-spacing-lg);
      text-align: center;
      font-family: var(--wag-typography-body-sm-font-family);
      font-size: var(--wag-typography-body-sm-font-size);
      color: var(--wag-color-on-dark);
      opacity: 0.7;
      max-width: 32ch;
    }

    /* ---------- Stage-visual: clinician-match sub-progress (Stage 3) ---------- */

    .match-bars {
      list-style: none;
      /* Bumped the inter-row gap up one step so the three sub-bars
         occupy more of Stage 3's visual envelope. Stage 1 (4 tall
         checklist rows) and Stage 2 (two stacked benefit-card rows)
         naturally fill the same envelope; Stage 3 used to read as
         "too small" by comparison because the sub-bars were short
         and tightly packed. */
      margin: 0 0 var(--wag-spacing-lg);
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--wag-spacing-lg);
    }
    .match-bars li {
      display: grid;
      grid-template-columns: 1fr auto;
      grid-template-areas:
        "label  pct"
        "track  track";
      column-gap: var(--wag-spacing-md);
      /* Extra space between the label/percent row and the track
         below so the label reads as its own line rather than
         crowding the bar. */
      row-gap: var(--wag-spacing-sm);
      align-items: center;
    }
    .match-bars .match-label {
      grid-area: label;
      /* Promoted from the tiny eyebrow style to label-md so the
         label has the same optical weight as the percent value on
         its right. Casing kept uppercase + letterspaced so it still
         reads as a structural label, just larger. */
      font-family: var(--wag-typography-label-md-font-family);
      font-size: var(--wag-typography-label-md-font-size);
      font-weight: var(--wag-typography-label-md-font-weight);
      letter-spacing: 0.06em;
      line-height: var(--wag-typography-label-md-line-height);
      text-transform: uppercase;
      color: var(--wag-color-on-dark);
    }
    .match-bars .match-pct {
      grid-area: pct;
      /* Larger percent value — display-sm-equivalent — so the number
         carries more weight in the row and balances the wider track
         beneath it. tabular-nums keeps the digits aligned as the
         counter animates. */
      font-family: var(--wag-typography-label-md-font-family);
      font-size: 22px;
      font-weight: 700;
      line-height: 1.1;
      color: var(--wag-color-on-dark);
      font-variant-numeric: tabular-nums;
    }
    .match-bars .match-track {
      grid-area: track;
      position: relative;
      width: 100%;
      /* Bumped track height 8px → 14px. The original 8px read as
         "afterthought" alongside Stage 1's tall checklist rows and
         Stage 2's chunky benefit cards. 14px gives the bars enough
         vertical mass to feel like the primary content of the
         stage. */
      height: 14px;
      background: rgba(246, 244, 238, 0.15);
      border-radius: var(--wag-rounded-full);
      overflow: hidden;
    }
    .match-bars .match-fill {
      position: absolute;
      inset: 0;
      width: 0%;
      background: var(--wag-color-primary-soft);
      border-radius: inherit;
      transition: width 600ms cubic-bezier(0.16, 1, 0.3, 1),
                  background-color 240ms ease-out;
    }
    /* On complete we previously swapped the fill to success-green,
       which read as a darker muted color against the teal canvas —
       the bars visually "emptied" the moment they hit 100%. Per
       design feedback we keep the mint primary-soft fill across all
       states so a completed bar stays clearly filled. The shimmer
       overlay (active state) still goes away on complete, which is
       the cue that the bar has finished animating. */
    .match-bars li[data-state="complete"] .match-fill {
      background: var(--wag-color-primary-soft);
    }
    /* The active sub-bar communicates "still working" with a soft
       traveling shimmer overlay — never on the complete bars. */
    .match-bars li[data-state="active"] .match-fill::after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(
        90deg,
        rgba(246, 244, 238, 0) 0%,
        rgba(246, 244, 238, 0.35) 50%,
        rgba(246, 244, 238, 0) 100%
      );
      animation: match-shimmer 1600ms ease-in-out infinite;
    }
    /* ============================================================
       Loader: small-phone fit (≤ 480px)

       The loader stack shares one persistent shell whose visual
       envelope is sized to its tallest stage (Stage 1: a 4-row
       scoring checklist with body-md labels). When the global
       mobile body-md override kicks in (18px / 26px on phones),
       those four labels grow tall enough to push the shell past
       the iPhone SE viewport, *and* Stage 2's 2x2 protection grid
       gets stretched into tall narrow cards because the parent
       envelope's height is now huge.

       This block:
         1. Drops the headline a tier (display-md → ~22px) so
            "Performing pet eligibility screening" stays on 2 lines
            at 320px instead of 3.
         2. Pulls .scoring-checklist .label back to a label tier
            (15px / 1.3) so labels wrap to at most 2 lines per row.
         3. Pins .protection-card to a 1/1 aspect-ratio so the 2x2
            grid renders as four equal-sized cards instead of
            stretching to fill whatever vertical space the shell
            envelope claims. Body text inside the card drops to
            13px / 1.3 to fit comfortably in the smaller square.
         4. Trims .match-bars row gap and label size proportionally
            so Stage 3 stays balanced against the now-shorter
            Stage 1 envelope.
       ============================================================ */
    @media (max-width: 480px) {
      .loading-headline {
        margin-bottom: var(--wag-spacing-lg);
        font-size: 22px;
        line-height: 28px;
      }
      .scoring-checklist {
        gap: 6px;
      }
      .scoring-checklist li {
        padding-top: 8px;
        padding-bottom: 8px;
        grid-template-columns: 22px 1fr 48px;
      }
      .scoring-checklist .indicator {
        width: 22px;
        height: 22px;
      }
      .scoring-checklist .indicator svg {
        width: 12px;
        height: 12px;
      }
      .scoring-checklist .label {
        font-size: 15px;
        line-height: 1.3;
      }
      .scoring-checklist .status {
        font-size: 9px;
      }

      .protection-grid {
        /* On phones the 2x2 collapses to a single column so each
           horizontal card gets the full row width. The icon stays at
           44px and the label gets the rest — no more squashed labels
           wrapping into 3+ lines inside a square. */
        grid-template-columns: 1fr;
        gap: 8px;
      }
      .protection-card {
        /* Tighter padding on mobile and slightly smaller icon column
           so all four rows fit within stage 1's checklist envelope
           without stretching the shell-body cell. */
        grid-template-columns: 40px 1fr;
        padding: 10px 12px;
        gap: 10px;
      }
      .protection-card .icon {
        width: 40px;
        height: 40px;
      }
      .protection-card .icon svg {
        width: 20px;
        height: 20px;
      }
      .protection-card p {
        font-size: 13px;
        line-height: 1.3;
      }

      .match-bars {
        gap: var(--wag-spacing-md);
      }
      .match-bars li {
        row-gap: 6px;
      }
      .match-bars .match-label {
        font-size: 12px;
      }
      .match-bars .match-pct {
        font-size: 18px;
      }
      .match-bars .match-track {
        height: 10px;
      }
    }

    /* Extra-narrow phones (≤ 360px) — iPhone SE 1st gen. Take the
       headline + checklist one step further so the whole loader
       still fits in a 568px-tall viewport without scroll. */
    @media (max-width: 360px) {
      .loading-headline {
        font-size: 20px;
        line-height: 26px;
        margin-bottom: var(--wag-spacing-md);
      }
      .scoring-checklist .label {
        font-size: 14px;
      }
      .protection-card p {
        font-size: 12px;
      }
    }

    @keyframes match-shimmer {
      0%   { transform: translateX(-100%); }
      100% { transform: translateX(100%); }
    }

    /* ---------- Coral-diamond divider ---------- */

    .coral-diamond-divider {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: var(--wag-spacing-sm);
      margin: var(--wag-spacing-md) 0 var(--wag-spacing-lg);
      color: var(--wag-color-on-dark);
      opacity: 0.6;
    }
    .coral-diamond-divider::before,
    .coral-diamond-divider::after {
      content: "";
      display: inline-block;
      width: 60px;
      height: 1px;
      background: currentColor;
    }
    .coral-diamond-divider svg {
      width: 14px;
      height: 14px;
      color: var(--wag-color-accent-coral);
      opacity: 1;
    }

    /* ---------- Coral progress bar ---------- */

    .progress-eyebrow {
      margin: 0 0 var(--wag-spacing-sm);
      text-align: center;
      font-family: var(--wag-typography-eyebrow-font-family);
      font-size: var(--wag-typography-eyebrow-font-size);
      font-weight: var(--wag-typography-eyebrow-font-weight);
      letter-spacing: var(--wag-typography-eyebrow-letter-spacing);
      line-height: var(--wag-typography-eyebrow-line-height);
      color: var(--wag-color-on-dark);
      text-transform: uppercase;
    }
    .wag-progress-bar {
      position: relative;
      width: 100%;
      max-width: 360px;
      margin: 0 auto;
      height: var(--wag-component-progress-bar-fill-height);
      border-radius: var(--wag-component-progress-bar-fill-rounded);
      background: var(--wag-color-surface);
      overflow: hidden;
    }
    .wag-progress-bar-fill {
      position: absolute;
      inset: 0;
      width: 0%;
      background: var(--wag-component-progress-bar-fill-background-color);
      border-radius: inherit;
    }
    .wag-progress-bar-label {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      color: var(--wag-component-progress-bar-fill-text-color);
      font-family: var(--wag-typography-label-lg-font-family);
      font-size: var(--wag-typography-label-lg-font-size);
      font-weight: 700;
      line-height: 1;
      font-variant-numeric: tabular-nums;
    }

    /* ---------- Score reveal ---------- */

    .reveal-page {
      /* Full-bleed results surface. Each child region
         (.reveal-page__teal, .reveal-content-card, .reveal-footnote)
         repaints its own full-width background band, and uses a
         max(gutter, …) padding to keep its inner content centered
         inside a 500px column. The outer .reveal-page no longer
         clamps width or radius — it's just the vertical stack. */
      padding-bottom: 0;
      background: transparent;
      margin: 0;
    }
    .reveal-page__teal {
      /* The teal band continues from html/body's teal canvas; we still
         paint it explicitly so the band keeps reading as the teal hero
         region even if the body background is ever overridden. The
         padding-inline uses max(gutter, …) to constrain the inner
         content to a 500px column centered in the viewport. */
      background: var(--wag-component-surface-page-teal-background-color);
      padding:
        var(--wag-spacing-md)
        max(var(--wag-spacing-gutter), calc((100% - 500px) / 2))
        var(--wag-spacing-lg);
      color: var(--wag-color-on-dark);
    }

    .reveal-headline {
      margin: var(--wag-spacing-md) auto var(--wag-spacing-md);
      max-width: 22ch;
      text-align: center;
      font-family: var(--wag-typography-display-lg-font-family);
      font-size: var(--wag-typography-display-lg-font-size);
      font-weight: var(--wag-typography-display-lg-font-weight);
      line-height: var(--wag-typography-display-lg-line-height);
      letter-spacing: var(--wag-typography-display-lg-letter-spacing);
      color: var(--wag-color-on-dark);
    }
    .reveal-headline em {
      font-style: normal;
      color: var(--wag-color-primary-soft);
    }

    /* Score-reveal speech bubble (WITH downward tail) */
    .score-bubble {
      position: relative;
      display: inline-flex;
      flex-direction: column;
      align-items: center;
      gap: 2px;
      margin: 0 auto var(--wag-spacing-lg);
      background: var(--wag-color-accent-coral);
      color: var(--wag-component-button-primary-text-color);
      border-radius: var(--wag-rounded-md);
      padding: 8px 16px;
      box-shadow: 0 2px 8px rgba(25, 23, 23, 0.18);
      animation: bubble-pop 320ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
      animation-delay: 240ms;
    }
    .score-bubble__eyebrow {
      font-family: var(--wag-typography-eyebrow-font-family);
      font-size: 10px;
      font-weight: var(--wag-typography-eyebrow-font-weight);
      letter-spacing: var(--wag-typography-eyebrow-letter-spacing);
      line-height: var(--wag-typography-eyebrow-line-height);
      text-transform: uppercase;
    }
    .score-bubble__value {
      font-family: var(--wag-typography-label-lg-font-family);
      font-size: 18px;
      font-weight: 700;
      line-height: 1.1;
    }
    .score-bubble__tail {
      position: absolute;
      bottom: -10px;
      left: 50%;
      transform: translateX(-50%);
      width: 0;
      height: 0;
      border-left: 8px solid transparent;
      border-right: 8px solid transparent;
      border-top: 10px solid var(--wag-color-accent-coral);
    }
    .reveal-bubble-wrap { display: flex; justify-content: center; }

    @keyframes bubble-pop {
      from { transform: scale(0.6); opacity: 0; }
      to   { transform: scale(1);   opacity: 1; }
    }

    /* ---------- Letter-preview hero (replaces Reference's projected chart) ---------- */

    .letter-preview {
      position: relative;
      width: 100%;
      max-width: 170px;
      margin: 0 auto;
      aspect-ratio: 5 / 6;
      background: var(--wag-color-surface);
      color: var(--wag-color-ink);
      border-radius: var(--wag-rounded-md);
      padding: 14px 16px;
      box-shadow: 0 12px 24px rgba(13, 23, 30, 0.22);
      transform: rotate(-1.5deg);
      overflow: hidden;
    }
    .letter-preview__seal {
      width: 22px;
      height: 22px;
      border-radius: var(--wag-rounded-full);
      background: var(--wag-color-primary);
      color: var(--wag-color-on-dark);
      display: grid;
      place-items: center;
      margin: 0 0 8px;
    }
    .letter-preview__seal svg { width: 12px; height: 12px; }
    .letter-preview__title {
      margin: 0 0 2px;
      font-family: var(--wag-typography-display-md-font-family);
      font-size: 11px;
      font-weight: 600;
      line-height: 1.2;
      color: var(--wag-color-ink);
    }
    .letter-preview__subtitle {
      margin: 0 0 10px;
      font-family: var(--wag-typography-caption-font-family);
      font-size: 8px;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      color: var(--wag-color-ink-slate);
    }
    .letter-preview__lines {
      display: flex;
      flex-direction: column;
      gap: 4px;
    }
    .letter-preview__line {
      height: 4px;
      border-radius: var(--wag-rounded-full);
      background: var(--wag-color-outline);
    }
    .letter-preview__line--short { width: 38%; }
    .letter-preview__line--medium { width: 72%; }
    .letter-preview__line--long  { width: 100%; }
    .letter-preview__line--mint  { background: var(--wag-color-primary-soft); }
    .letter-preview__sig {
      margin-top: 10px;
      padding-top: 8px;
      border-top: 1px dashed var(--wag-color-outline);
    }
    .letter-preview__sig-label {
      font-family: var(--wag-typography-caption-font-family);
      font-size: 7px;
      letter-spacing: 0.08em;
      text-transform: uppercase;
      color: var(--wag-color-ink-slate);
    }
    .letter-preview__sig-line {
      margin-top: 3px;
      width: 60%;
      height: 4px;
      border-radius: var(--wag-rounded-full);
      background: var(--wag-color-ink);
    }

    .letter-stamp {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%) rotate(-12deg);
      padding: 3px 8px;
      border: 2px solid var(--wag-color-accent-coral);
      border-radius: var(--wag-rounded-sm);
      background: rgba(255, 92, 57, 0.08);
      font-family: var(--wag-typography-eyebrow-font-family);
      font-size: 9px;
      font-weight: 800;
      letter-spacing: 0.14em;
      color: var(--wag-color-accent-coral);
      text-transform: uppercase;
      animation: stamp-down 320ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
      animation-delay: 760ms;
    }

    @keyframes stamp-down {
      from { transform: translate(-50%, -50%) rotate(-12deg) scale(2.4); opacity: 0; }
      to   { transform: translate(-50%, -50%) rotate(-12deg) scale(1);   opacity: 1; }
    }

    /* ---------- White-card content block (score reveal lower half) ---------- */

    .reveal-content-card {
      /* On Reference's reveal screen the white card floats centered on top
         of the teal bleed (it does NOT extend to the viewport edges).
         max-width clamps it to a 500px column; the teal continues to
         show on the left and right of the card on desktop, which is
         what gives it the "card on top of a colored hero" look. The
         rounded TOP corners are visible because the teal sits behind
         them; the bottom corners are squared because the warm-tan
         footnote band sits flush below. */
      background: var(--wag-color-surface-card-white);
      color: var(--wag-color-ink);
      border-radius: var(--wag-rounded-md) var(--wag-rounded-md) 0 0;
      max-width: 500px;
      margin: 0 auto;
      padding: var(--wag-spacing-lg) var(--wag-spacing-gutter);
      /* No entrance animation. We used to slide this card in with a
         1100ms delay so it would "reveal" after the teal hero settled,
         but that meant for the first ~1.4s of page load the card was
         opacity: 0 / translated, leaving an empty cream gap below the
         teal hero. That gap read as a layout flicker — the teal hero
         appeared to stretch the whole viewport and then "snap" smaller
         as the card faded in. On the production hand-off (loader →
         results), the user has already seen the loader complete, so
         this destination page should just render in its final state
         from frame one. The card-slide-in keyframes have been
         removed accordingly. */
    }

    .reveal-content-card h2 {
      margin: 0 0 var(--wag-spacing-md);
      font-family: var(--wag-typography-display-md-font-family);
      font-size: var(--wag-typography-display-md-font-size);
      font-weight: var(--wag-typography-display-md-font-weight);
      line-height: var(--wag-typography-display-md-line-height);
      letter-spacing: var(--wag-typography-display-md-letter-spacing);
    }

    /* ---------- Card variant: hero image bled to top edge ----------
       Mirrors the .wag-card--with-portrait pattern from the
       16-int-quiz-intro card. The portrait <img> sits at the top
       of the card with its left/right edges flush to the card's
       inner edges (so it visually breaks out of the gutter), while
       the body copy + bullet list + CTA below keep their normal
       gutter padding.

       Sizing math:
         - .reveal-content-card padding is `32px 24px` (i.e.
           --wag-spacing-lg / --wag-spacing-gutter). The image
           negative-margin must therefore be -32px on top and
           -24px on the sides — and the image's width must add
           48px (2 × 24) to claim those reclaimed gutters.
         - aspect-ratio: 16/9 keeps the woman + dog in frame on
           every viewport without awkward cropping. */
    .reveal-content-card--with-portrait {
      padding-top: 0;
      overflow: hidden;
    }
    .reveal-card-portrait {
      display: block;
      width: calc(100% + 48px);
      /* 'height: auto' is required so aspect-ratio actually
         controls the rendered height — without it, the <img> tag's
         intrinsic height attribute would win and the aspect-ratio
         declaration becomes a no-op. */
      height: auto;
      margin: -32px -24px var(--wag-spacing-md);
      aspect-ratio: 16 / 9;
      object-fit: cover;
      object-position: center 35%;
    }

    .reveal-hero-photo {
      position: relative;
      margin: 0 0 var(--wag-spacing-md);
      border-radius: var(--wag-rounded-md);
      overflow: hidden;
    }
    .reveal-hero-photo .wag-photo-placeholder {
      background: var(--wag-color-surface-mint-pale);
      border-color: var(--wag-color-primary-soft);
    }
    /* When the placeholder is replaced with a real product photo, the
       <img> should fill the 4:3 slot, preserve the same rounded corners,
       and sit below the .clinician-pill overlay. The aspect-ratio lock
       prevents layout shift before the image decodes. */
    .reveal-hero-photo__img {
      display: block;
      width: 100%;
      height: auto;
      aspect-ratio: 4 / 3;
      object-fit: cover;
      object-position: center;
      border-radius: var(--wag-rounded-md);
    }
    .reveal-hero-photo .clinician-pill {
      position: absolute;
      top: var(--wag-spacing-sm);
      right: var(--wag-spacing-sm);
      background: var(--wag-color-surface-card-white);
      color: var(--wag-color-primary-deep);
      border: 1px solid var(--wag-color-primary-soft);
      border-radius: var(--wag-rounded-full);
      padding: 4px 10px;
      font-family: var(--wag-typography-label-md-font-family);
      font-size: var(--wag-typography-label-md-font-size);
      font-weight: var(--wag-typography-label-md-font-weight);
      line-height: var(--wag-typography-label-md-line-height);
    }

    .reveal-body {
      margin: 0 0 var(--wag-spacing-md);
      font-family: var(--wag-typography-body-md-font-family);
      font-size: var(--wag-typography-body-md-font-size);
      line-height: var(--wag-typography-body-md-line-height);
      color: var(--wag-color-ink);
    }

    .clinical-rows {
      list-style: none;
      margin: 0 0 var(--wag-spacing-lg);
      padding: 0;
      display: flex;
      flex-direction: column;
      gap: var(--wag-spacing-md);
    }
    .clinical-rows li {
      display: grid;
      grid-template-columns: 24px 1fr;
      gap: var(--wag-spacing-md);
      align-items: flex-start;
    }
    .clinical-rows .icon {
      width: 24px;
      height: 24px;
      color: var(--wag-color-accent-coral);
      flex-shrink: 0;
    }
    .clinical-rows .icon svg { width: 100%; height: 100%; }
    .clinical-rows p {
      margin: 0;
      font-family: var(--wag-typography-body-md-font-family);
      font-size: var(--wag-typography-body-md-font-size);
      line-height: var(--wag-typography-body-md-line-height);
      color: var(--wag-color-ink);
    }
    .clinical-rows p strong { font-weight: 700; }

    .reveal-cta {
      cursor: pointer;
      width: 100%;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      border: 0;
      background: var(--wag-component-button-primary-background-color);
      color: var(--wag-component-button-primary-text-color);
      border-radius: var(--wag-component-button-primary-rounded);
      padding: var(--wag-component-button-primary-padding);
      font-family: var(--wag-component-button-primary-font-family);
      font-size: var(--wag-component-button-primary-font-size);
      font-weight: var(--wag-component-button-primary-font-weight);
      line-height: var(--wag-component-button-primary-line-height);
      transition: background-color 120ms ease-out, transform 60ms ease-out;
    }
    .reveal-cta:hover,
    .reveal-cta:focus-visible {
      background: var(--wag-component-button-primary-hover-background-color);
      outline: none;
    }
    .reveal-cta:active { transform: translateY(1px); }

    /* The .escape-stack ("Not ready for an ESA letter? Browse other
       resources") and .safety-link ("See full eligibility disclosure")
       blocks were removed from score-reveal because they cluttered the
       outcome page without driving any decision the warm-tan footnote
       below doesn't already cover. If we ever need a "not interested"
       off-ramp here, prefer adding it to the page comment first so we
       can review the surrounding hierarchy before reintroducing the
       link stack. */

    /* Footnote on warm-tan at the very bottom. The warm-tan band itself
       bleeds full-width (no max-width on the section), but the text
       inside is clamped to the same 500px column the rest of the page
       uses, so the copy aligns vertically with the headline / white
       card column on desktop. */
    .reveal-footnote {
      /* Match the disclaimer treatment from the encouragement recipe
         (reference/recipes/encouragement.html → .recipe-a .wag-footnote):
           - Cream surface, NOT warm-tan, so it reads as the same
             page-bottom band the rest of the funnel uses.
           - Same 500px column width as the white .reveal-content-card
             above, centered, so the footnote sits visually flush
             beneath the card instead of bleeding edge-to-edge to
             the viewport. The teal hero behind continues to show on
             the left and right of this stack on desktop, just like
             the card above. */
      max-width: 500px;
      margin: 0 auto;
      padding: var(--wag-spacing-md) var(--wag-spacing-gutter);
      background: var(--wag-color-surface);
    }
    .reveal-footnote p {
      margin: 0 0 var(--wag-spacing-sm);
      font-family: var(--wag-typography-caption-font-family);
      font-size: var(--wag-typography-caption-font-size);
      font-weight: var(--wag-typography-caption-font-weight);
      line-height: var(--wag-typography-caption-line-height);
      color: var(--wag-color-ink);
    }
    .reveal-footnote p:last-child { margin-bottom: 0; }

    @media (prefers-reduced-motion: reduce) {
      .score-bubble,
      .letter-stamp,
      .reveal-content-card,
      .scoring-checklist li[data-state="active"] .indicator,
      .match-bars li[data-state="active"] .match-fill::after {
        animation: none !important;
        opacity: 1;
        transform: none;
      }
      .letter-stamp {
        transform: translate(-50%, -50%) rotate(-12deg);
      }
      .protection-card,
      .protection-card[data-state="enter"] {
        opacity: 1;
        transform: none;
        transition: none;
      }
      .match-bars .match-fill {
        transition: none;
      }
    }
  