/* Page-level CSS for the WPR ported pages.
 *
 * Merged from the <style> blocks of Eligibility Report.dc.html and Eligibility
 * Funnel.dc.html -- the client-approved artifacts. Only rules inline styles
 * cannot express live here: media queries, pseudo-elements, icon masks.
 *
 * Merge rules, in case this needs regenerating:
 *   - Ordinary selectors are deduped; every shared one was verified
 *     byte-identical between the two files.
 *   - @media blocks are NOT deduped by condition. Both files scope different
 *     selectors under the same breakpoint, and their inner selectors were
 *     checked for conflicts (there are none). Deduping them by condition is
 *     what dropped .flow-main, .wpr-choice, .consent-box, .action-row,
 *     .hero-rail and .name-grid on the first attempt.
 *
 * Load-bearing rules -- do not "tidy" any of these (CLAUDE.md S14):
 *
 *   .ico           SVG data URIs must stay in this stylesheet and must omit the
 *                  ";utf8" parameter. In an inline style attribute the
 *                  semicolon terminates the declaration and truncates the
 *                  payload. A mask that fails to load renders as a SOLID FILLED
 *                  BLOCK, not as nothing.
 *   .band-scale    minmax(0, 1fr), not 1fr. A bare 1fr floors at min-content,
 *                  pushing the middle band label off the gauge axis.
 *   .preview-body  The max-height crop, with .preview-veil over it, is what
 *                  makes the landing preview read as a glimpse of the real
 *                  report rather than a stack of cards.
 *
 * Paths are rewritten for the worker: assets/ -> /assets/.
 */

body { margin: 0; background: var(--bg-canvas); }

a { color: var(--fg-accent); }

a:hover { color: var(--wpr-green-800); }

dd { margin: 0; }

.grain { position: relative; }

.grain::after {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background-image: url("/assets/grain.png"); background-size: 192px 192px;
    opacity: 0.035; mix-blend-mode: overlay;
  }

.grain > * { position: relative; z-index: 1; }

.ico {
    display: inline-block; width: 1.125rem; height: 1.125rem; flex: none;
    background: currentColor;
    -webkit-mask-position: center; mask-position: center;
    -webkit-mask-size: contain; mask-size: contain;
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  }

@media (max-width: 60rem) { .two-up { grid-template-columns: 1fr !important; gap: 2rem !important; } .eq-head { min-height: 0; } }

.site-footer { background: var(--wpr-green-800); padding: 3.5rem 0 2rem; margin-top: 1rem; }

.footer-top { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 2fr); gap: 3rem; padding-bottom: 2.5rem; border-bottom: 1px solid color-mix(in srgb, var(--fg-primary) 20%, transparent); }

.footer-brand { display: flex; flex-direction: column; gap: 1.25rem; }

.footer-blurb { margin: 0; font: var(--text-body-sm); max-width: 40ch; color: color-mix(in srgb, var(--fg-primary) 72%, transparent); text-wrap: pretty; }

.footer-contact { display: flex; flex-direction: column; gap: 0.375rem; }

.footer-phone { font-family: var(--wpr-font-sans); font-size: 1.5rem; font-weight: 600; letter-spacing: -0.015em; font-variant-numeric: tabular-nums lining-nums; color: var(--fg-primary); text-decoration: none; }

.footer-phone:hover { color: var(--fg-primary); text-decoration: underline; text-underline-offset: 3px; }

.footer-address { margin: 0; font: var(--text-body-sm); line-height: 1.55; color: color-mix(in srgb, var(--fg-primary) 74%, transparent); }

.footer-cols { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 2rem; }

.footer-col { display: flex; flex-direction: column; gap: 0.75rem; }

.footer-col a { font: var(--text-body-sm); color: color-mix(in srgb, var(--fg-primary) 74%, transparent); text-decoration: none; min-height: 1.5rem; transition: color var(--wpr-duration-fast) var(--wpr-ease-standard); }

.footer-col a:hover { color: var(--fg-primary); text-decoration: underline; text-underline-offset: 3px; }

.footer-legal { padding-top: 2rem; display: flex; flex-direction: column; gap: 1rem; }

.footer-legal p { margin: 0; font-size: 0.75rem; line-height: 1.6; max-width: 88ch; color: color-mix(in srgb, var(--fg-primary) 56%, transparent); }

.footer-legal strong { font-weight: 600; color: color-mix(in srgb, var(--fg-primary) 74%, transparent); }

.footer-base { display: flex; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; margin-top: 0.75rem; padding-top: 1.25rem; border-top: 1px solid color-mix(in srgb, var(--fg-primary) 14%, transparent); }

@media (max-width: 60rem) {
    .site-footer { padding: 2.5rem 0 1.5rem; }
    .footer-top { grid-template-columns: 1fr; gap: 2rem; }
    .footer-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.75rem; }
  }

/* Legal and compliance text. This class was referenced by the contact step, the
 * footer and the desk record but never defined, so all three printed it at full
 * body size — louder than the copy it qualifies. */
.wpr-disclosure { font: var(--text-caption); color: var(--fg-muted); }

.row-basis { display: block; margin-top: 0.1875rem; font: var(--text-caption); color: var(--fg-muted); font-variant-numeric: tabular-nums lining-nums; }

.eq-head { min-height: 2.34em; }

/* minmax(0,1fr) so the side tracks can be equal — a bare 1fr floors at
     min-content, which made the middle chip drift off the gauge's axis. */
  .band-scale {
    display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center; gap: 0.5rem;
    width: 100%; max-width: 23rem; margin: 1.25rem auto 0;
  }

@media (max-width: 30rem) {
    .band-scale { display: flex; justify-content: center; }
    .band-off { display: none; }
  }

/* ══ Tables sit on a white card; their headings stay on the canvas ══
 *
 * The report alternates two surfaces on purpose: prose reads directly on the
 * sage canvas, and anything tabular sits on a raised surface so the eye can
 * tell a written claim from a measured one at a glance. The card is the
 * scroller itself rather than a wrapper, so a table that has to scroll
 * sideways on a phone scrolls *inside* its card instead of dragging the card.
 *
 * `min-width: 0` is load-bearing, not tidying. A flex or grid child defaults to
 * `min-width: auto`, which resolves to min-content — so `overflow-x: auto` on
 * the scroller could not contain the 28rem table below, and every ancestor grew
 * to fit it instead. At 375px that pushed the page to 472px wide and the score
 * card off the right edge of the phone. Remove these and the report drifts
 * outside the viewport again.
 */
.wpr-container > *, .two-up > *, .body-section .wpr-container > * { min-width: 0; }

.t-scroll {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  min-width: 0; max-width: 100%;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--wpr-radius-lg);
}
/* The card's own edge is the last rule; a trailing cell border doubles it. */
.t-scroll .wpr-table tr:last-child td { border-bottom: 0; }
/* A card inside a card would be two edges saying the same thing. */
.wpr-card .t-scroll { background: none; border: 0; border-radius: 0; }

@media (max-width: 40rem) {
    .t-scroll .wpr-table { min-width: 20rem; }
    .hero { padding: 2.5rem 0 2.25rem !important; }
    .body-section { padding: 2.5rem 0 3rem !important; }
    .wpr-stat { padding: 1rem 1.25rem; }
  }

.ico--check {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M20%206%209%2017l-5-5%22%2F%3E%3C%2Fsvg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M20%206%209%2017l-5-5%22%2F%3E%3C%2Fsvg%3E");
  }

.ico--help {
    -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%2210%22%2F%3E%3Cpath%20d%3D%22M9.09%209a3%203%200%200%201%205.83%201c0%202-3%203-3%203%22%2F%3E%3Cpath%20d%3D%22M12%2017h.01%22%2F%3E%3C%2Fsvg%3E");
    mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%2210%22%2F%3E%3Cpath%20d%3D%22M9.09%209a3%203%200%200%201%205.83%201c0%202-3%203-3%203%22%2F%3E%3Cpath%20d%3D%22M12%2017h.01%22%2F%3E%3C%2Fsvg%3E");
  }


/* ══ From Eligibility Funnel.dc.html ══ */


@keyframes wpr-rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* Report preview: the real report page, cropped. The veil fades the lower
     edge so the CTA sits on solid canvas rather than mid-table. */
  .preview-frame {
    position: relative; border: 1px solid var(--border-subtle); border-radius: 10px;
    background: var(--bg-surface); overflow: hidden;
  }

/* Capped so the preview reads as a glimpse of the real page, not a scroller. */
  .preview-body { padding: 0; max-height: 40rem; overflow: hidden; }

.preview-grid {
    display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;
    padding: 1.5rem; align-items: stretch;
  }

.preview-veil {
    position: absolute; left: 0; right: 0; bottom: 0; height: 55%;
    background: linear-gradient(to bottom, transparent 0%, var(--bg-canvas) 68%);
    pointer-events: none;
  }

.preview-cta {
    position: absolute; left: 0; right: 0; bottom: 0;
    display: flex; flex-direction: column; align-items: center; gap: 0.75rem;
    padding: 0 1.5rem 2rem; text-align: center;
  }

@media (max-width: 60rem) {
    .site-footer { padding: 2.5rem 0 1.5rem; }
    .footer-top { grid-template-columns: 1fr; gap: 2rem; }
    .footer-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.75rem; }
  }

.rail-wide { display: block; }

.rail-narrow { display: none; }

@media (max-width: 60rem) {
    .rail-wide { display: none; }
    .rail-narrow { display: flex; }
    .flow-main { padding: 1.75rem 1.25rem 3rem !important; }
    .flow-aside { padding: 1.125rem 1.25rem !important; border-right: 0 !important; border-bottom: 1px solid var(--border-subtle); position: sticky; top: 0; z-index: 5; }
    .two-up { grid-template-columns: 1fr !important; gap: 2rem !important; }
    .preview-grid { grid-template-columns: 1fr; padding: 1.25rem; }
    .preview-veil { height: 70%; }
    .hero { padding: 2.5rem 0 2.25rem !important; }
    .hero-rail { padding-top: 0 !important; }
    .hero-ornament { display: none !important; }
    .body-section { padding: 2.5rem 0 3rem !important; }
  }

@media (max-width: 40rem) {
    .name-grid { grid-template-columns: 1fr !important; }
    .wpr-choice { flex-wrap: wrap; row-gap: 0.25rem; }
    .wpr-choice__hint { white-space: normal; flex-basis: 100%; }
    .consent-box { flex-wrap: nowrap; }
    .action-row { flex-direction: column; align-items: stretch; gap: 1rem; }
    .action-row .wpr-btn--primary { width: 100%; justify-content: center; }
    .action-row .wpr-btn--link { align-self: center; min-height: 2.75rem; }
    .wpr-stat { padding: 1rem 1.25rem; }
  }

/* ───────────────────────────────────────────────────────────────────────────
 * Questionnaire chrome. Added during the port, not lifted from the artifacts.
 *
 * .flow-topbar holds the step label and the progress bar together. On wide
 * screens it sits statically above the question, with the rail alongside naming
 * all eight steps. On mobile the rail, the logo and the split layout are gone
 * and this bar is the entire navigation, so it sticks to the top.
 *
 * It is deliberately short: label, bar, minimal padding. It sits above every
 * question, and every pixel of it is taken from the thing being read. The
 * design collapsed the rail into a sticky strip of dots here (CLAUDE.md S5.2);
 * this replaces the dots with the bar, which says the same thing in less space
 * and matches the gauge the report ends with.
 * ─────────────────────────────────────────────────────────────────────────── */
.flow-topbar { display: flex; flex-direction: column; gap: 0.5rem; }
.flow-meter { width: 100%; max-width: 20rem; }

@media (max-width: 60rem) {
  /* No rail, no logo, no split. */
  .flow-aside { display: none !important; }

  .flow-topbar {
    position: sticky;
    top: 0;
    z-index: 5;
    gap: 0.375rem;
    /* Bleed past .flow-main's inline padding so the bar spans the viewport. */
    margin: -1.25rem -1.25rem 1.25rem;
    padding: 0.75rem 1.25rem 0.625rem;

    /* Surface, not canvas: the bar sits above the page rather than on it, and
     * the system's canvas is *darker* than its surfaces, so lifting it reads
     * correctly rather than inverted.
     *
     * §4 allows a shadow only for things that truly float. A sticky bar with
     * content scrolling under it is exactly that, so it gets one instead of the
     * hairline — kept very low so it reads as a lift, not a card. */
    background: var(--bg-surface);
    box-shadow:
      0 1px 2px color-mix(in srgb, var(--fg-primary) 5%, transparent),
      0 4px 12px color-mix(in srgb, var(--fg-primary) 4%, transparent);
  }
  .flow-meter { max-width: none; }
  .flow-main { padding: 1.25rem 1.25rem 3rem !important; }
}


/* ══ From Member Portal.dc.html ══ */

.ico--report { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M15%202H6a2%202%200%200%200-2%202v16a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2V7Z%22%2F%3E%3Cpath%20d%3D%22M14%202v5h6%22%2F%3E%3Cpath%20d%3D%22M8%2013h8%22%2F%3E%3Cpath%20d%3D%22M8%2017h5%22%2F%3E%3C%2Fsvg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M15%202H6a2%202%200%200%200-2%202v16a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2V7Z%22%2F%3E%3Cpath%20d%3D%22M14%202v5h6%22%2F%3E%3Cpath%20d%3D%22M8%2013h8%22%2F%3E%3Cpath%20d%3D%22M8%2017h5%22%2F%3E%3C%2Fsvg%3E"); }

.ico--settings { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223%22%2F%3E%3Cpath%20d%3D%22M19.4%2015a1.65%201.65%200%200%200%20.33%201.82l.06.06a2%202%200%201%201-2.83%202.83l-.06-.06a1.65%201.65%200%200%200-1.82-.33%201.65%201.65%200%200%200-1%201.51V21a2%202%200%201%201-4%200v-.09A1.65%201.65%200%200%200%209%2019.4a1.65%201.65%200%200%200-1.82.33l-.06.06a2%202%200%201%201-2.83-2.83l.06-.06a1.65%201.65%200%200%200%20.33-1.82%201.65%201.65%200%200%200-1.51-1H3a2%202%200%201%201%200-4h.09A1.65%201.65%200%200%200%204.6%209a1.65%201.65%200%200%200-.33-1.82l-.06-.06a2%202%200%201%201%202.83-2.83l.06.06a1.65%201.65%200%200%200%201.82.33H9a1.65%201.65%200%200%200%201-1.51V3a2%202%200%201%201%204%200v.09a1.65%201.65%200%200%200%201%201.51%201.65%201.65%200%200%200%201.82-.33l.06-.06a2%202%200%201%201%202.83%202.83l-.06.06a1.65%201.65%200%200%200-.33%201.82V9a1.65%201.65%200%200%200%201.51%201H21a2%202%200%201%201%200%204h-.09a1.65%201.65%200%200%200-1.51%201Z%22%2F%3E%3C%2Fsvg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%223%22%2F%3E%3Cpath%20d%3D%22M19.4%2015a1.65%201.65%200%200%200%20.33%201.82l.06.06a2%202%200%201%201-2.83%202.83l-.06-.06a1.65%201.65%200%200%200-1.82-.33%201.65%201.65%200%200%200-1%201.51V21a2%202%200%201%201-4%200v-.09A1.65%201.65%200%200%200%209%2019.4a1.65%201.65%200%200%200-1.82.33l-.06.06a2%202%200%201%201-2.83-2.83l.06-.06a1.65%201.65%200%200%200%20.33-1.82%201.65%201.65%200%200%200-1.51-1H3a2%202%200%201%201%200-4h.09A1.65%201.65%200%200%200%204.6%209a1.65%201.65%200%200%200-.33-1.82l-.06-.06a2%202%200%201%201%202.83-2.83l.06.06a1.65%201.65%200%200%200%201.82.33H9a1.65%201.65%200%200%200%201-1.51V3a2%202%200%201%201%204%200v.09a1.65%201.65%200%200%200%201%201.51%201.65%201.65%200%200%200%201.82-.33l.06-.06a2%202%200%201%201%202.83%202.83l-.06.06a1.65%201.65%200%200%200-.33%201.82V9a1.65%201.65%200%200%200%201.51%201H21a2%202%200%201%201%200%204h-.09a1.65%201.65%200%200%200-1.51%201Z%22%2F%3E%3C%2Fsvg%3E"); }

.ico--out { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9%2021H5a2%202%200%200%201-2-2V5a2%202%200%200%201%202-2h4%22%2F%3E%3Cpath%20d%3D%22m16%2017%205-5-5-5%22%2F%3E%3Cpath%20d%3D%22M21%2012H9%22%2F%3E%3C%2Fsvg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M9%2021H5a2%202%200%200%201-2-2V5a2%202%200%200%201%202-2h4%22%2F%3E%3Cpath%20d%3D%22m16%2017%205-5-5-5%22%2F%3E%3Cpath%20d%3D%22M21%2012H9%22%2F%3E%3C%2Fsvg%3E"); }

.ico--phone { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M22%2016.92v3a2%202%200%200%201-2.18%202%2019.79%2019.79%200%200%201-8.63-3.07%2019.5%2019.5%200%200%201-6-6%2019.79%2019.79%200%200%201-3.07-8.67A2%202%200%200%201%204.11%202h3a2%202%200%200%201%202%201.72%2012.84%2012.84%200%200%200%20.7%202.81%202%202%200%200%201-.45%202.11L8.09%209.91a16%2016%200%200%200%206%206l1.27-1.27a2%202%200%200%201%202.11-.45%2012.84%2012.84%200%200%200%202.81.7A2%202%200%200%201%2022%2016.92Z%22%2F%3E%3C%2Fsvg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22black%22%20stroke-width%3D%221.5%22%20stroke-linecap%3D%22round%22%20stroke-linejoin%3D%22round%22%3E%3Cpath%20d%3D%22M22%2016.92v3a2%202%200%200%201-2.18%202%2019.79%2019.79%200%200%201-8.63-3.07%2019.5%2019.5%200%200%201-6-6%2019.79%2019.79%200%200%201-3.07-8.67A2%202%200%200%201%204.11%202h3a2%202%200%200%201%202%201.72%2012.84%2012.84%200%200%200%20.7%202.81%202%202%200%200%201-.45%202.11L8.09%209.91a16%2016%200%200%200%206%206l1.27-1.27a2%202%200%200%201%202.11-.45%2012.84%2012.84%200%200%200%202.81.7A2%202%200%200%201%2022%2016.92Z%22%2F%3E%3C%2Fsvg%3E"); }

.doc-links { display: flex; flex-direction: column; gap: 0.25rem; align-items: flex-start; }

.doc-links a { font: var(--text-body-sm); min-height: 2.75rem; display: flex; align-items: center; }

.portal { display: grid; grid-template-columns: minmax(15rem, 17rem) 1fr; min-height: 100vh; }

.portal-nav { background: var(--bg-canvas); border-right: 1px solid var(--border-subtle); padding: 1.75rem 1.25rem; }

.nav-item {
    display: flex; align-items: center; gap: 0.75rem; width: 100%;
    min-height: 2.75rem; padding: 0.5rem 0.75rem; border-radius: 6px;
    border: 1px solid transparent; background: transparent; cursor: pointer;
    font: var(--text-body-sm); text-align: left;
    color: color-mix(in srgb, var(--fg-primary) 72%, transparent);
    transition: background-color var(--wpr-duration-fast) var(--wpr-ease-standard), border-color var(--wpr-duration-fast) var(--wpr-ease-standard), color var(--wpr-duration-fast) var(--wpr-ease-standard);
  }

.nav-item:hover { color: var(--fg-primary); border-color: color-mix(in srgb, var(--fg-primary) 22%, transparent); }

.nav-item[data-on="true"] { color: var(--fg-primary); border-color: color-mix(in srgb, var(--fg-primary) 42%, transparent); font-weight: 600; }

.sub-nav { display: flex; flex-direction: column; gap: 0.25rem; }

.sub-item {
    display: flex; align-items: center; width: 100%; min-height: 2.75rem;
    padding: 0.5rem 0.875rem; border-radius: 6px; border: 1px solid transparent;
    background: transparent; cursor: pointer; font: var(--text-body-sm);
    text-align: left; color: var(--fg-secondary);
    transition: background-color var(--wpr-duration-fast) var(--wpr-ease-standard), border-color var(--wpr-duration-fast) var(--wpr-ease-standard);
  }

.sub-item:hover { border-color: var(--border-strong); }

.sub-item[data-on="true"] { border-color: var(--border-brand); color: var(--fg-primary); font-weight: 600; }

@media (max-width: 60rem) {
    .portal { grid-template-columns: 1fr; }
    .portal-nav { border-right: 0; border-bottom: 1px solid var(--border-subtle); padding: 1.25rem; }
    .nav-list { flex-direction: row !important; flex-wrap: wrap; gap: 0.5rem !important; }
    .nav-item { width: auto; }
    .rail-foot { margin-top: 1.25rem !important; }
    .portal-main { padding: 2rem 1.25rem 3rem !important; }
    .settings-split { grid-template-columns: 1fr !important; }
    .sub-nav { flex-direction: row; flex-wrap: wrap; }
    .two-up { grid-template-columns: 1fr !important; }
  }


/* ══ From Desk Record.dc.html ══ */

.desk-split { display: grid; grid-template-columns: minmax(16rem, 21rem) 1fr; min-height: 100vh; }

/* ── The rail is a dark ground and has to say so ────────────────────────────
 *
 * `[data-theme="deep"]` swaps the token values but never sets `color` on the
 * element itself, so anything inside that does not name its own colour keeps
 * inheriting the paper ink from `body`. In the queue that was the client's
 * name — 26,37,36 on a dark green ground, which is to say invisible.
 *
 * It has been that way since the desk was built: every row showed its band,
 * score and date under a blank line where the name should be. The one thing
 * the rail exists for is picking a person out by name.
 */
.desk-queue { color: var(--fg-primary); }

.queue-item {
    display: flex; flex-direction: column; gap: 0.25rem; width: 100%;
    min-height: 2.75rem; padding: 0.75rem 0.875rem; border-radius: 6px;
    border: 1px solid color-mix(in srgb, var(--fg-primary) 16%, transparent);
    background: transparent; cursor: pointer; text-align: left;
    transition: border-color var(--wpr-duration-fast) var(--wpr-ease-standard);
  }

.queue-item:hover { border-color: color-mix(in srgb, var(--fg-primary) 40%, transparent); }

.queue-item[data-on="true"] { border-color: var(--fg-primary); border-width: 2px; padding: calc(0.75rem - 1px) calc(0.875rem - 1px); }

@media (max-width: 64rem) {
    .desk-split { grid-template-columns: 1fr; }
    .desk-queue { border-right: 0 !important; border-bottom: 1px solid var(--border-subtle); }
    .desk-main { padding: 2rem 1.25rem 3rem !important; }
    /* Scoped to the desk. Unscoped and last in the file, this rule set the
       stacked gap on the report and the funnel too — 1.5rem, where those pages
       intend 2.75rem — and ran their sections together on a phone. */
    .desk-main .two-up { grid-template-columns: 1fr !important; gap: 1.5rem !important; }
    .eq-head { min-height: 0; }
  }

/* ══ Stacked sections need room to read as separate sections ══
 * Last in the file on purpose: it has to beat the three earlier `.two-up`
 * overrides, which is also why the gap is a single deliberate value rather
 * than one more competing !important. */
@media (max-width: 60rem) {
  .body-section .two-up { gap: 2.75rem !important; }
}

/* On a phone a table scrolls inside its card, but a header clipped mid-word
 * reads as broken rather than as scrollable. Tighter cells and a lower floor
 * let the narrow numeric tables fit outright. */
@media (max-width: 40rem) {
  .t-scroll .wpr-table th, .t-scroll .wpr-table td { padding: 0.75rem 0.875rem; }
  .wpr-disclosure { text-align: center; }
}

/* ══ The score card holds both halves ══
 * The gauge and the point table share one surface. Stacked on a phone they need
 * a rule between them, or the arithmetic reads as a continuation of the band
 * note rather than as its own half of the card.
 */
.score-card { padding: var(--wpr-space-6); }
@media (max-width: 60rem) {
  .score-card .score-build {
    border-top: 1px solid var(--border-subtle);
    padding-top: 1.75rem;
  }
  .score-card .two-up { gap: 1.75rem !important; }
}
@media (max-width: 40rem) {
  /* Inside a card the table loses the card's padding on both sides, so the
     20rem floor that fits on the canvas overflows here and clips the last
     column. These columns are short — let them size to their own content. */
  .score-card { padding: 1.25rem; }
  .wpr-card .t-scroll .wpr-table { min-width: 0; }
}

/* A break that only holds while there is room for two lines. Without it the
 * headline wraps on width alone and lands mid-phrase — "Find / out your
 * protection score" — rather than at the full stop. Below 40rem the line is
 * too narrow for two lines anyway, so the break is removed and the text wraps
 * naturally. */
.sentence-break { display: inline; }
@media (max-width: 40rem) { .sentence-break { display: none; } }

/* ══ The specialist bar on the report ══
 *
 * Sticky at the top of the report, carrying the number a client would ring
 * while the document is still in front of them. It is the one persistent
 * call-to-action on a page that is otherwise deliberately unhurried, so it is
 * kept slim and quiet — no urgency copy, no colour that reads as an alert.
 *
 * Deep ground rather than paper: it has to stay legible over the deep hero it
 * starts on *and* over the sage body it travels down, and only the dark
 * treatment works against both. The brass number ties it to the rest of the
 * accent rather than introducing a third voice.
 */
.specialist-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--wpr-green-900);
  border-bottom: 1px solid color-mix(in srgb, var(--wpr-brass-300) 28%, transparent);
  box-shadow: 0 1px 12px color-mix(in srgb, #000 22%, transparent);
}
.specialist-bar__inner {
  display: flex;
  align-items: baseline;
  gap: 0.875rem;
  padding-top: 0.625rem;
  padding-bottom: 0.625rem;
}
.specialist-bar__label {
  font: var(--text-body-sm);
  color: color-mix(in srgb, var(--wpr-sage-100) 76%, transparent);
}
.specialist-bar__tel {
  font: var(--text-heading-sm);
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--wpr-brass-300);
  text-decoration: none;
  white-space: nowrap;
}
.specialist-bar__tel:hover { color: var(--wpr-brass-100); }
.specialist-bar__note {
  font: var(--text-caption);
  color: color-mix(in srgb, var(--wpr-sage-100) 55%, transparent);
  margin-left: auto;
}

/* On a phone the bar moves to the bottom.
 *
 * Three reasons, in order of how much they matter: the bottom third is where a
 * thumb rests, so the one thing we want tapped is the easiest thing to reach;
 * the top of a phone viewport is already competing with the browser's own
 * chrome, and stacking a second bar under it costs real reading height; and a
 * bottom bar cannot push the page's own header out of view.
 *
 * `fixed` rather than `sticky` — sticky bottom would only pin once the page had
 * scrolled far enough to reach it, which on a long report is never.
 *
 * The safe-area inset keeps it clear of the iPhone home indicator, and the body
 * gets matching bottom padding so the footer's last line is never underneath it.
 */
@media (max-width: 40rem) {
  .specialist-bar {
    position: fixed;
    top: auto;
    bottom: 0;
    left: 0;
    right: 0;
    border-bottom: 0;
    border-top: 1px solid color-mix(in srgb, var(--wpr-brass-300) 28%, transparent);
    box-shadow: 0 -2px 16px color-mix(in srgb, #000 26%, transparent);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  .specialist-bar__inner {
    flex-direction: column;
    align-items: center;
    gap: 0.125rem;
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
  }
  .specialist-bar__label { font: var(--text-caption); }
  .specialist-bar__tel { font: var(--text-heading-md); }
  /* Two lines is the budget: the label and the number. The reassurance is on
     the closing card further down and does not need repeating here. */
  .specialist-bar__note { display: none; }

  /* The whole bar dials, not just the twelve characters of the number.
   *
   * The link's own box is 24px tall, well under §2's 44x44 floor, and on a
   * phone held one-handed by someone in their sixties that is the difference
   * between a call and a mis-tap. The bar is already a positioned element, so
   * stretching the anchor's ::after over it makes the entire strip the target —
   * 63px tall and the full width — without changing the markup or the layout.
   */
  .specialist-bar__tel::after { content: ""; position: absolute; inset: 0; }
  .specialist-bar__label { position: relative; z-index: 1; pointer-events: none; }

  /* Clear the fixed bar so the footer's last line is readable. */
  body { padding-bottom: calc(5rem + env(safe-area-inset-bottom, 0px)); }
}

/* ══ Report tables: room to breathe, and matched heights ══
 *
 * The cells were on the design system's compact padding, which is right for a
 * dense internal table and wrong for a document someone reads once, slowly, on
 * their own money. The extra inset also stops the first and last columns
 * sitting hard against the card's edge.
 */
.body-section .t-scroll .wpr-table th,
.body-section .t-scroll .wpr-table td {
  padding: 1.125rem 1.5rem;
}

/* The mix and the stress test sit side by side and had different row counts, so
 * their cards ended at different depths and the row read as broken rather than
 * as two halves of one thought. The columns stretch to match, and the tables
 * fill the space they are given — rows distributing evenly rather than the
 * shorter table leaving a pocket of blank card under it. `.eq-head` already
 * matches the two headings above them.
 */
.equal-tables > * { height: 100%; }
.equal-tables .t-scroll { flex: 1; }
.equal-tables .t-scroll > .wpr-table { height: 100%; }

@media (max-width: 60rem) {
  /* Stacked, there is nothing to match — and forcing a height would stretch the
     rows of whichever table happens to be shorter for no reason at all. */
  .equal-tables > * { height: auto; }
  .equal-tables .t-scroll { flex: 0 1 auto; }
  .equal-tables .t-scroll > .wpr-table { height: auto; }
  .body-section .t-scroll .wpr-table th,
  .body-section .t-scroll .wpr-table td { padding: 0.875rem 1rem; }
}

/* ══ Brass — the one distinction mark on a screen ══
 *
 * The palette has carried brass since the design system was written and
 * nothing had ever used it. Its documented job is narrow: "earned distinction
 * only: seals, credentials, audited figures. Budget: one brass element per
 * screen. Two is a jewelry store."
 *
 * The crisis stress test is the only thing in this report that qualifies. Every
 * other figure is computed from the visitor's own answers; these three rows are
 * measured, and the client checked each one against source (§13) — which is
 * also why two of them were corrected rather than left flattering. Marking that
 * section, and only that section, says "this part is checked" without a word.
 *
 * Deliberately not the protection score. The score is the product, so it is
 * the tempting place to put gold on a page about gold — and it is computed,
 * not audited. Brass there would be decoration claiming to be a credential.
 */
.eyebrow-distinction { color: var(--fg-distinction); }

/* ── Brass as the accent on eyebrows, on paper only ─────────────────────────
 *
 * Tried on both grounds and kept on one. Light brass on the deep canvas read as
 * decoration — on a dark ground the warm tone stops being an accent and becomes
 * the section's character, which is not what the eyebrow is for. On paper it
 * does the job: warm enough to mark the section, quiet enough to stay a label.
 * The deep sections keep the design system's own muted eyebrow.
 *
 * The hero CTA stays brass. A button is meant to be the warm thing on a dark
 * ground; a row of labels is not.
 *
 * Extended to the questionnaire and the portal on 25 August so the whole
 * client-facing journey matches — a visitor clicked a brass CTA and landed on a
 * green one, which is a visible seam at the point of highest intent. The
 * portal's deep nav rail and the specialist desk are deliberately excluded: the
 * nav is a dark ground, and the desk is an internal tool that should not change
 * appearance because a marketing page did.
 *
 * ⚠ On paper, brass-700 on the sage canvas measures about 3.9:1. The palette
 * calls it "text-safe on paper", and for body copy it is; an eyebrow is 12px at
 * 600 weight, which WCAG counts as small text and holds to 4.5:1. For an
 * audience in its fifties to seventies (§2) that is not a rounding error, so it
 * is mixed a step darker toward ink to clear AA — 4.64:1, measured.
 */
.body-section .wpr-eyebrow,
.preview-frame .wpr-eyebrow,
.portal-main .wpr-eyebrow {
  color: color-mix(in srgb, var(--wpr-brass-700) 86%, var(--wpr-sage-950));
}

/* The questionnaire keeps brand green on its eyebrows.
 *
 * Brass reads as a mark of distinction, which is right on a page selling the
 * report and right on the report itself. Inside the questionnaire the eyebrow
 * is doing plain work — it says which question this is — and a distinction
 * colour on a counter makes the step feel like a claim. Green is the brand at
 * its quietest, which is what a wayfinding label wants to be.
 *
 * 9:1 on the sage canvas, so it also reads harder than the brass did. */
.flow-main .wpr-eyebrow,
.flow-aside .wpr-eyebrow {
  color: var(--fg-brand);
}


.distinction-rule {
  border-top: 2px solid var(--wpr-brass-500);
  padding-top: 1rem;
}

/* ── Brass on the paper CTA, and only there ────────────────────────────────
 *
 * The deep hero's button stays white. It is the loudest thing on that screen
 * precisely because nothing around it competes, and a gold button on a page
 * about gold is the fastest way to read as a sales page rather than research
 * (§2 — restraint is the conversion strategy, not an aesthetic preference).
 *
 * On paper the button was brand green against a sage canvas, which is quiet.
 * Brass lifts it and ties it to the eyebrows without introducing a hue that
 * is not already in the palette.
 *
 * brass-700, not brass-500: the button label is 16px at 600 weight, which WCAG
 * still counts as small text, and white on brass-500 measures about 3.8. On
 * brass-700 it is 5.2. The hover darkens rather than lightens for the same
 * reason — a lighter hover would drop the label below AA at the moment someone
 * is about to click it.
 */
/* The hero button takes the light end of the same ramp, so the two CTAs on the
 * page are one colour read against two grounds rather than two colours. Dark
 * green label on light brass — the inverse of the paper button, which is light
 * label on dark brass. Scoped to the hero so the desk's sign-in, which is also
 * a deep-theme primary button, stays as it was. */
.hero[data-theme="deep"] .wpr-btn--primary {
  background: var(--wpr-brass-300);
  border-color: var(--wpr-brass-300);
  color: var(--wpr-green-900);
}
.hero[data-theme="deep"] .wpr-btn--primary:hover:not([disabled]) {
  background: var(--wpr-brass-100);
  border-color: var(--wpr-brass-100);
}

.body-section .wpr-btn--primary,
.flow-main .wpr-btn--primary,
.portal-main .wpr-btn--primary {
  background: var(--wpr-brass-700);
  border-color: var(--wpr-brass-700);
  color: var(--wpr-sage-50);
}
.body-section .wpr-btn--primary:hover:not([disabled]),
.flow-main .wpr-btn--primary:hover:not([disabled]),
.portal-main .wpr-btn--primary:hover:not([disabled]) {
  background: color-mix(in srgb, var(--wpr-brass-700) 84%, var(--wpr-sage-950));
  border-color: color-mix(in srgb, var(--wpr-brass-700) 84%, var(--wpr-sage-950));
}

/* ══ Depth in the deep hero ══
 *
 * One flat radial over a flat canvas read as a solid block. Three layers give
 * the section a direction to travel in: a tight lift behind the headline where
 * the eye lands first, the original broad wash, and a deepening toward the
 * bottom-right so the block falls away instead of stopping.
 *
 * Every value is a palette token (§4: never invent a colour) — the lift is
 * green-600, the wash green-700, the falloff green-950, all mixed down against
 * the green-900 canvas rather than blended into new hues.
 *
 * The grain lifts from 3.5% to 5% here and only here. §4 approved the texture
 * at 3.5% against paper; on the deep canvas it was effectively invisible, which
 * is what made the section feel like a fill rather than a printed surface.
 */
.hero-deep {
  background-color: var(--bg-canvas);
  background-image:
    /* A cool emerald bloom on the right, behind the rail. The brand's signal
       colour at 12% does not read as green — it reads as the light coming from
       somewhere, which is what stops a single-hue block looking painted on. */
    radial-gradient(
      58% 62% at 88% 16%,
      color-mix(in srgb, var(--wpr-green-500) 12%, transparent) 0%,
      transparent 70%
    ),
    /* The lift behind the headline, where the eye lands first. */
    radial-gradient(
      64% 56% at 4% 2%,
      color-mix(in srgb, var(--wpr-green-600) 34%, transparent) 0%,
      transparent 66%
    ),
    /* The original broad wash, widened. */
    radial-gradient(
      124% 96% at 16% 0%,
      color-mix(in srgb, var(--wpr-green-700) 66%, transparent) 0%,
      transparent 68%
    ),
    /* Falloff into the bottom-right. Pushed past the corner so the darkening
       runs off the edge instead of banding inside it. */
    radial-gradient(
      104% 96% at 112% 116%,
      color-mix(in srgb, var(--wpr-green-950) 86%, transparent) 0%,
      transparent 66%
    );
}

.hero-deep.grain::after { opacity: 0.06; }

/* ══ The hero rail walks itself through the eight steps ══
 *
 * A deliberate deviation from §4's "wpr-rise and wpr-fade only". It is the one
 * animated element on the site, it is decorative rather than a state anyone
 * acts on, and it is scoped to `.rail-cycle` — the questionnaire's rail shows
 * real progress and must never move on its own.
 *
 * CSS only, because the landing page ships no JavaScript and this is not worth
 * breaking that for. Each step runs the same keyframes over the full loop and
 * starts `--i` slots late, so the highlight walks down the list.
 *
 * The resting state is deliberately quieter and further apart than the static
 * rail was: the label scales up 12% when it activates, and without the extra
 * room that read as cramped rather than as emphasis. Scaling by transform
 * rather than font-size keeps every row at a fixed height, so nothing below
 * shifts as the highlight passes — a list that nudges its own neighbours while
 * someone is reading it is worse than no animation at all.
 */
.rail-cycle { --rail-step: 1.5s; --rail-loop: 12s; }

.rail-cycle .wpr-rail__step { padding-bottom: 2rem; }
.rail-cycle .wpr-rail__step:last-child { padding-bottom: 0; }

.rail-cycle .wpr-rail__label,
.rail-cycle .wpr-rail__meta {
  transform-origin: left center;
  will-change: transform, color;
}
.rail-cycle .wpr-rail__label {
  font-size: 0.9375rem;
  animation: rail-label var(--rail-loop) ease-in-out infinite;
  animation-delay: calc(var(--i) * var(--rail-step));
}
.rail-cycle .wpr-rail__meta {
  animation: rail-meta var(--rail-loop) ease-in-out infinite;
  animation-delay: calc(var(--i) * var(--rail-step));
}
.rail-cycle .wpr-rail__step::after {
  animation: rail-node var(--rail-loop) ease-in-out infinite;
  animation-delay: calc(var(--i) * var(--rail-step));
}

/* One eighth of the loop is 12.5%. The highlight ramps in over the first
   quarter of its slot, holds, then releases — so two neighbours are never both
   at full size, and the walk reads as one moving point of attention. */
@keyframes rail-label {
  0%, 12.5%, 100% { transform: scale(1); color: var(--fg-secondary); }
  3%, 9.5% { transform: scale(1.12); color: var(--fg-primary); }
}
@keyframes rail-meta {
  0%, 12.5%, 100% { color: var(--fg-muted); }
  3%, 9.5% { color: var(--fg-secondary); }
}
@keyframes rail-node {
  0%, 12.5%, 100% {
    transform: scale(1);
    background: var(--rail-node-idle);
    border-color: var(--rail-line);
  }
  3%, 9.5% {
    transform: scale(1.45);
    background: var(--rail-node-done);
    border-color: var(--rail-node-done);
  }
}

/* The node is positioned from its top-left, so it grows down and right unless
   told otherwise. */
.rail-cycle .wpr-rail__step::after { transform-origin: center; }

/* Someone who has asked their system for less motion gets the rail as it was:
   the highlight still lands on the first step, and nothing moves. */
@media (prefers-reduced-motion: reduce) {
  .rail-cycle .wpr-rail__label,
  .rail-cycle .wpr-rail__meta,
  .rail-cycle .wpr-rail__step::after { animation: none; }
}

/* ══ The call block ══
 * The card matches the height of the prose beside it rather than floating at
 * the top of a tall column, and the two columns are held further apart — at
 * 2.5rem the body copy was running into the card's edge.
 * On a phone the row stacks, so the card sizes to its own content again.
 */
@media (max-width: 60rem) {
  .call-row { gap: 2.5rem !important; }
  .call-card { height: auto !important; padding: 1.75rem !important; }
}

/* ══ The consent checkbox ══
 *
 * Deliberately NOT a `.wpr-choice`. That class hides its own input
 * (`position: absolute; opacity: 0`) and shows selection as a 2px border on the
 * whole row, which is right for an answer option — §4 keeps fills off choices
 * because a fill implies the system prefers that answer.
 *
 * Consent is not an answer option. It is an attestation a person has to be able
 * to see the state of, and "did I tick that?" must be answerable at a glance by
 * someone in their sixties holding a phone. So this one gets a real box that
 * visibly fills when checked. The deviation from §4 is intentional and scoped
 * to this control.
 *
 * The whole label is the hit target, so it clears 44×44 by a wide margin (§2);
 * the box itself is 28px, and 32px on a phone.
 */
.consent-box {
  display: flex; align-items: flex-start; gap: 0.875rem;
  padding: 1rem; cursor: pointer;
  background: var(--bg-surface);
  border: 1px solid var(--border-subtle); border-radius: var(--wpr-radius-lg);
}
.consent-box:hover { border-color: var(--border-strong); }
.consent-box:has(input:checked) { border-color: var(--border-brand); }
.consent-box:has(input:focus-visible) { outline: 2px solid var(--ring); outline-offset: 2px; }
.consent-box input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  flex: none; width: 1.75rem; height: 1.75rem; margin: 0.0625rem 0 0;
  display: grid; place-content: center;
  background: var(--bg-canvas);
  border: 2px solid var(--border-strong); border-radius: var(--wpr-radius-md);
  cursor: pointer;
}
.consent-box input[type="checkbox"]:checked {
  background: var(--bg-brand); border-color: var(--bg-brand);
}
.consent-box input[type="checkbox"]:checked::after {
  content: ""; width: 0.5rem; height: 0.875rem;
  border: solid var(--fg-on-brand); border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg) translate(-0.5px, -1.5px);
}
.consent-text { font: var(--text-caption); color: var(--fg-secondary); }

@media (max-width: 40rem) {
  .consent-box input[type="checkbox"] { width: 2rem; height: 2rem; }
  .consent-box { padding: 1rem 0.875rem; }
}

/* ══ Prose tables stack into labelled rows on a phone ══
 *
 * Three columns of sentences inside 325px gives every cell a four-word measure
 * and five wrapped lines — technically inside the viewport and unreadable.
 * Numeric tables keep their grid, because columns of figures are what a table
 * is for; only the ones carrying prose stack, each cell captioned with the
 * header it lost.
 *
 * `data-numeric` reverts to left-aligned here: right alignment exists to line
 * decimal points up under each other, and stacked there is nothing above to
 * line up with — it just strands the value against the far edge.
 */
@media (max-width: 40rem) {
  .wpr-table--stack { min-width: 0 !important; }
  .wpr-table--stack thead { display: none; }
  .wpr-table--stack, .wpr-table--stack tbody, .wpr-table--stack tr, .wpr-table--stack td {
    display: block; width: 100%;
  }
  .wpr-table--stack tr { padding: 0.875rem 0; border-bottom: 1px solid var(--border-subtle); }
  .wpr-table--stack tr:last-child { border-bottom: 0; }
  .wpr-table--stack td { border-bottom: 0; padding: 0.375rem 1rem; }
  .wpr-table--stack td[data-numeric] { text-align: left; }
  .wpr-table--stack td::before {
    content: attr(data-label);
    display: block;
    font: var(--text-eyebrow); letter-spacing: var(--tracking-eyebrow);
    text-transform: uppercase; color: var(--fg-muted);
    margin-bottom: 0.125rem;
  }
  .wpr-table--stack td:first-child { font-weight: 600; color: var(--fg-primary); }
}
