/* ============================================================
   FOMC-SIM · YC Demo · Design System
   Unified to the daytime ivory palette, mirroring sapiensq.com.
   The time-of-day switcher is disabled, so data-theme stays "ivory";
   the dark variant below is kept commented out for future revival.
   ============================================================ */

:root,
:root[data-theme="ivory"] {
  /* Surfaces */
  --bg-0: #f6f1e4;
  --bg-1: #f0e9d7;
  --bg-2: #e8decc;
  --surface: #fbf6e9;
  --surface-raised: #fffcf0;
  --surface-translucent: rgba(251, 246, 233, 0.82);
  --border: #d9c9a5;
  --border-soft: #e8dcc0;

  /* Brand */
  --gold: #8b6e2e;
  --gold-soft: #6b5423;
  --gold-glow: rgba(139, 110, 46, 0.14);
  /* Peak of the committee-cta pulse. Separate from --gold-glow, which at 0.14
     is a resting lift and invisible as motion. This needs 0.75 to register at
     all, because --gold is a dark olive ink (#8b6e2e) on a near-white canvas:
     the halo can only ever be DARKER than the page, so it lands as a shadow
     rather than a glow, and a shadow has to be heavy before the eye catches it
     moving. See the note on .committee-cta::before. */
  --gold-pulse: rgba(139, 110, 46, 0.75);
  --teal: #1f6f63;

  /* Verdict / direction */
  --hawk: #a8302a;
  --dove: #2c5b99;
  --neutral: #5d459a;
  /* Derived from --neutral (the preview app's signature indigo). Used only by the
     committee -> preview card, which borrows the demo's colour so it reads as the
     door into it — the one indigo element on an otherwise gold page. --neutral-soft
     is the darker gradient stop for its filled CTA; the rest are its shadows and the
     imminent-halo pulse, mirroring the --gold-* set. */
  --neutral-soft: #45327a;
  --neutral-glow: rgba(93, 69, 154, 0.16);
  --neutral-card-shadow: rgba(93, 69, 154, 0.26);
  --neutral-pulse: rgba(93, 69, 154, 0.70);
  --miss: #a8302a;
  --hit: #1f6f63;
  --hit-bg: rgba(31, 111, 99, 0.12);
  --hit-bg-strong: rgba(31, 111, 99, 0.22);
  --miss-bg: rgba(168, 48, 42, 0.10);

  /* Text */
  --text: #2a241c;
  --text-muted: #6c6254;
  --text-dim: #9e9180;

  /* Decorative — page glow, card shadows, pending haze */
  --page-glow-1: rgba(139, 110, 46, 0.06);
  --page-glow-2: rgba(31, 111, 99, 0.04);
  --cta-shadow: rgba(139, 110, 46, 0.25);
  --cta-shadow-hover: rgba(139, 110, 46, 0.32);
  --card-shadow: rgba(139, 110, 46, 0.20);
  --shipping-shadow: rgba(31, 111, 99, 0.20);
  --pending-grad-end: rgba(217, 201, 165, 0.32);
  --pending-haze-radial: rgba(139, 110, 46, 0.06);
  --pending-haze-stripe: rgba(139, 110, 46, 0.03);

  /* Chart gridlines — needs higher contrast than UI borders so the
     dashed splitLine reads inside .live-card. */
  --chart-grid: #d9c9a5;

  /* Three cores accents (persona = teal, deliberation = orchid) */
  --persona: #7fb8aa;
  --persona-strong: #3f7a70;
  --persona-bd: #b5d2cc;
  --persona-bg: rgba(127, 184, 170, 0.08);
  --delib: #c79ed6;
  --delib-strong: #7e5a90;
  --delib-bd: #d4c2dc;
  --delib-bg: rgba(199, 158, 214, 0.08);

  /* Stub banner / data-load error fallback */
  --warn-bg: #fff4c9;
  --warn-border: #e6d27a;
  --warn-text: #5a4600;

  /* Type / layout */
  --font-display: "Cormorant Garamond", "Times New Roman", serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", "Fira Code", Consolas, monospace;
  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 16px;
  /* 1024 − 32×2 gutters = 960px of content, matching /refill and /survey. */
  --max-w: 1024px;
}

/* Dark palette — DISABLED for the day-theme unification.
   Canvas / surfaces lean blue-black; gold lifts to a warmer
   parchment so brand identity survives the swap. Kept here
   (commented) for future revival.

:root[data-theme="dark"] {
  --bg-0: #02040a;
  --bg-1: #0a0f2c;
  --bg-2: #11183a;
  --surface: #0f1c3a;
  --surface-raised: #162142;
  --surface-translucent: rgba(15, 28, 58, 0.82);
  --border: #283356;
  --border-soft: #1c2748;

  --gold: #d4b260;
  --gold-soft: #b89860;
  --gold-glow: rgba(212, 178, 96, 0.16);
  --gold-pulse: rgba(212, 178, 96, 0.36);
  --teal: #3da899;

  --hawk: #ff6f61;
  --dove: #5b9dd9;
  --neutral: #b39ce0;
  --miss: #ff6f61;
  --hit: #3da899;
  --hit-bg: rgba(61, 168, 153, 0.14);
  --hit-bg-strong: rgba(61, 168, 153, 0.26);
  --miss-bg: rgba(255, 111, 97, 0.12);

  --text: #f2e6c9;
  --text-muted: #b8b0a0;
  --text-dim: #807868;

  --page-glow-1: rgba(212, 178, 96, 0.05);
  --page-glow-2: rgba(61, 168, 153, 0.04);
  --cta-shadow: rgba(0, 0, 0, 0.45);
  --cta-shadow-hover: rgba(0, 0, 0, 0.55);
  --card-shadow: rgba(0, 0, 0, 0.40);
  --shipping-shadow: rgba(61, 168, 153, 0.22);
  --pending-grad-end: rgba(22, 33, 66, 0.60);
  --pending-haze-radial: rgba(212, 178, 96, 0.05);
  --pending-haze-stripe: rgba(212, 178, 96, 0.03);

  --chart-grid: #3c4b6e;

  --persona: #5d9d8e;
  --persona-strong: #7fb8aa;
  --persona-bd: #2d4a43;
  --persona-bg: rgba(127, 184, 170, 0.10);
  --delib: #b58dc5;
  --delib-strong: #c79ed6;
  --delib-bd: #4a3858;
  --delib-bg: rgba(199, 158, 214, 0.10);

  --warn-bg: #3d3214;
  --warn-border: #6b5423;
  --warn-text: #f2e6c9;
}
*/

/* Smooth crossfade retained from the cross-theme transition. */
html[data-theme] body,
html[data-theme] body * {
  transition: background-color 320ms ease, border-color 320ms ease, color 320ms ease;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background:
    radial-gradient(ellipse 90% 60% at 50% -10%, var(--page-glow-1), transparent 60%),
    radial-gradient(ellipse 70% 50% at 20% 20%, var(--page-glow-2), transparent 60%),
    var(--bg-0);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  scroll-behavior: smooth;
}

/* Scoped to .fomc-page. This stylesheet is injected globally while the /fomc
   routes are mounted, and a bare `a { color: inherit }` is UNLAYERED — so it beat
   the shared footer/navbar's Tailwind `text-*` utilities (which live in a cascade
   layer, and layer < no-layer regardless of specificity), dragging every footer
   social icon to the inherited dark colour = all black. :where() keeps the
   original zero-ish specificity so the page's own link classes still win. */
:where(.fomc-page) a { color: inherit; text-decoration: none; }
.fomc-page code { font-family: var(--font-mono); font-size: 0.92em; background: var(--bg-1); padding: 1px 6px; border-radius: 4px; }

/* Disable text selection and image dragging site-wide — matches sapiensq.com */
html, body {
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

img, svg, a {
  -webkit-user-drag: none;
  -khtml-user-drag: none;
  -moz-user-drag: none;
  -o-user-drag: none;
  user-drag: none;
}

/* ===== stub banner ===== */
.stub-banner {
  position: sticky; top: 0; z-index: 100;
  background: var(--warn-bg);
  border-bottom: 1px solid var(--warn-border);
  color: var(--warn-text);
  text-align: center;
  padding: 8px 16px;
  font-size: 13px;
  font-family: var(--font-mono);
}

/* ===== top nav ===== */
.topbar {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 32px;
  background: var(--surface-translucent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border-soft);
}
.stub-banner:not([hidden]) ~ .topbar { top: 36px; }

.brand { display: flex; align-items: center; gap: 12px; }
.brand-seal {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, var(--gold), var(--gold-soft));
  box-shadow: 0 0 14px var(--gold-glow), inset 0 0 6px rgba(0,0,0,0.2);
  display: grid; place-items: center;
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--surface-raised);
  font-size: 17px;
}
.brand-text { display: flex; flex-direction: column; line-height: 1.1; }
.brand-title { font-family: var(--font-display); font-size: 18px; font-weight: 600; letter-spacing: 0.4px; }
.brand-sub { font-size: 10px; color: var(--text-dim); letter-spacing: 2px; text-transform: uppercase; margin-top: 2px; }

.topnav { display: flex; gap: 22px; align-items: center; }
.topnav a {
  font-size: 13.5px;
  color: var(--text-muted);
  transition: color 0.15s ease;
}
.topnav a:hover { color: var(--text); }
.topnav a.ghost {
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--gold);
}
.topnav a.ghost:hover { background: var(--gold-glow); }

/* minimal subpage topbar — wordmark only, links to company root */
.brand-link {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.4px;
  color: var(--text);
  transition: color 0.15s ease;
}
.brand-link:hover { color: var(--gold); }

/* ===== sections ===== */
/* Scoped to .fomc-page. Unscoped, this element selector also matched the app
   shell's own <main> (SapiensQWireframe_v1), which wraps this page — so the
   max-width and both gutters applied twice and the content rendered 64px
   narrower than --max-w intends. A port artifact: the original standalone page
   had exactly one <main>.

   --max-w is 1024 so the content box lands on 960px, matching /refill
   (1008 − 24×2) and /survey. Gutters differ per page, so the outer widths
   differ; the content width is what is held equal. */
.fomc-page main { max-width: var(--max-w); margin: 0 auto; padding: 0 32px; }

.section { padding: 96px 0; border-top: 1px solid var(--border-soft); }
.section.alt { background: linear-gradient(180deg, transparent, var(--bg-1) 30%, var(--bg-1) 70%, transparent); padding-left: 32px; padding-right: 32px; margin-left: -32px; margin-right: -32px; padding-top: 96px; padding-bottom: 96px; }

.section-eyebrow {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 18px;
}
.section h2 {
  font-family: var(--font-display);
  font-size: 44px;
  font-weight: 600;
  line-height: 1.15;
  margin: 0 0 18px 0;
  max-width: 100%;
}
.section-lede {
  font-size: 17px;
  color: var(--text-muted);
  /* Same as .hero .lede: the content box, and wrapping, so these end on the
     page's right edge instead of overflowing past it. */
  max-width: 100%;
  margin: 0 0 44px 0;
}

/* ===== page language toggle (EN / KR) =====
   PageLangToggle is shared across /fomc, /refill and /survey, so it ships with
   the main site's Tailwind tokens (bg-primary / border-line / text-meta) — the
   wrong palette on this gold page, where the pressed pill came out in the site's
   blue. These rules re-skin it in the FOMC theme while it sits inside .fomc-page,
   without the shared component needing to know this theme exists. Scoped tightly
   to the toggle's role="group"+aria-pressed buttons so nothing else is caught. */
.fomc-page [role="group"] {
  border-color: var(--border);
  background: var(--surface-translucent);
}
.fomc-page [role="group"] button {
  font-family: var(--font-mono);
}
.fomc-page [role="group"] button[aria-pressed="true"] {
  background: var(--gold);
  color: var(--surface-raised);
}
.fomc-page [role="group"] button[aria-pressed="false"] {
  background: transparent;
  color: var(--text-muted);
}
.fomc-page [role="group"] button[aria-pressed="false"]:hover {
  color: var(--gold);
}

/* ===== hero ===== */
.hero {
  padding: 56px 0 48px 0;
  /* No max-width: the hero shares main's 960px content box with every section
     below it, so the committee card, the h1 and the lede all end on the same
     right edge as the live cards and the rate path. It used to cap at 820 while
     the nowrap lines below escaped past even 960, which left three different
     right edges stacked on top of each other. */
}
.hero .kicker {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 22px 0;
}
.hero h1 {
  font-family: var(--font-display);
  font-size: clamp(32px, 4.4vw, 50px);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.3px;
  margin: 0 0 22px 0;
  color: var(--text);
  /* Both <br/>-separated halves sit on their own single line at desktop. */
  white-space: nowrap;
}
.hero h1 .accent {
  color: var(--gold);
  font-style: italic;
}
/* Keep "We simulate the committee that decide them." on one line at
   desktop. Mobile media query below relaxes this so the line wraps
   when the viewport is too narrow to fit. */
.hero .lede {
  font-size: 16.5px;
  color: var(--text-muted);
  /* Full content box, and wrapping. The <br/>-separated sentences still get a
     row each — they fit — but the longest one now folds inside 960px instead of
     running past it. It used to be pinned to one line by white-space: nowrap and
     allowed to overflow a 640px max-width into the hero's whitespace, which put
     its right edge ~124px past everything else on the page and, below ~1225px,
     past the viewport itself (clipping the end of the sentence rather than
     scrolling). Wrapping needs no breakpoint and no assumption about how wide
     the fallback font renders. */
  max-width: 100%;
  margin: 0 0 34px 0;
  line-height: 1.6;
}

.hero-cta-row { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 56px; }
.cta-primary {
  display: inline-block;
  padding: 14px 26px;
  background: linear-gradient(135deg, var(--gold), var(--gold-soft));
  color: var(--surface-raised);
  border-radius: var(--radius);
  font-weight: 600;
  font-size: 15px;
  box-shadow: 0 6px 20px var(--cta-shadow);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.cta-primary:hover { transform: translateY(-1px); box-shadow: 0 10px 24px var(--cta-shadow-hover); }

.cta-ghost {
  display: inline-block;
  padding: 14px 22px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--text-muted);
  font-size: 14.5px;
  transition: all 0.15s ease;
}
.cta-ghost:hover { border-color: var(--gold); color: var(--gold); }

/* ===== preview handoff ===== */
.preview-ribbon {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin: -8px 0 28px 0;
  padding: 14px 18px;
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--gold);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-muted);
  font-size: 13.5px;
}
.preview-ribbon-eyebrow {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 2.2px;
  text-transform: uppercase;
  color: var(--gold);
  font-weight: 700;
  white-space: nowrap;
}
.preview-ribbon-text {
  flex: 1;
  min-width: 240px;
  line-height: 1.55;
}
.preview-ribbon-link {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--gold);
  white-space: nowrap;
  letter-spacing: 0.5px;
  border-bottom: 1px dashed var(--border);
  padding-bottom: 1px;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.preview-ribbon-link:hover {
  color: var(--gold-soft);
  border-bottom-color: var(--gold);
}

/* ===== proof strip ===== */
.proof-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 20px;
  padding: 24px 28px;
  background: var(--surface);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
}
.proof-item { display: flex; flex-direction: column; gap: 6px; }
.proof-item .num {
  font-family: var(--font-display);
  font-size: 34px;
  font-weight: 600;
  line-height: 1;
  color: var(--gold);
  letter-spacing: -0.5px;
}
.proof-item .label {
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-dim);
  font-family: var(--font-mono);
}
.proof-item .sub {
  font-size: 12.5px;
  color: var(--text-muted);
}

/* ===== live-bet ribbon (hero, above the fold) ===== */
.live-ribbon {
  margin-top: 18px;
  padding: 14px 22px;
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--gold);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: 13.5px;
  color: var(--text-muted);
}
.live-ribbon:empty { display: none; }
.live-ribbon .ribbon-eyebrow {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: var(--gold);
  font-weight: 700;
  white-space: nowrap;
}
.live-ribbon .ribbon-text {
  flex: 1;
  min-width: 240px;
  line-height: 1.55;
}
.live-ribbon .ribbon-text b { color: var(--text); }
.live-ribbon .ribbon-cta {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--gold);
  white-space: nowrap;
  letter-spacing: 0.5px;
  border-bottom: 1px dashed var(--border);
  padding-bottom: 1px;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.live-ribbon .ribbon-cta:hover {
  color: var(--gold-soft);
  border-bottom-color: var(--gold);
}
@media (max-width: 700px) {
  .live-ribbon { padding: 12px 16px; gap: 12px; font-size: 13px; }
}

/* ===== live card ===== */
.live-card {
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  /* Tighter at the foot than the head: both cards end in a bottom-anchored
     action row, and the link's own dashed bottom rule already reads as an edge,
     so a full 28px under it left the pair looking bottom-heavy. */
  padding: 28px 32px 18px;
  box-shadow: 0 20px 40px -24px var(--card-shadow);
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.live-card::before {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(135deg, var(--gold-glow), transparent 40%);
  pointer-events: none;
}
.live-card > * { position: relative; }
/* Pin the bottom action link to the card's bottom regardless of how
   tall the body content above grows — this is what aligns the left
   card's action row with the right card's "Read the full FOMC
   statement" on the same baseline. */
.live-card > .deliberation-link { margin-top: auto; }

/* The left card's bottom row is the .pred-actions-block, which sits two levels
   down (.prediction-box > .pred-decision) rather than being a direct flex child
   like the right card's link — so `margin-top: auto` alone could not reach it
   and the two rows drifted apart by whatever the difference in body height
   happened to be. Carrying the stretch down the chain re-anchors it to the same
   card bottom the link uses, which is the only shared reference the two cards
   have: .live-pair stretches them to equal height, so bottom is the one edge
   that is guaranteed to line up whatever each card contains. */
/* padding-bottom goes to 0 with it: .prediction-box's 24px foot is what the
   action row was bottom-anchoring against, while the right card's link anchors
   to the card itself — so that padding alone was the offset that kept the two
   rows off the same line. The card's own padding-bottom still spaces the row
   from the edge. */
#live-card > .prediction-box {
  flex: 1 1 auto;
  padding-bottom: 0;
}
#live-card .pred-decision {
  display: flex;
  flex-direction: column;
  height: 100%;
}
/* The gap above the row has to be padding, not the base rule's margin: an auto
   margin wins the push but collapses to 0 exactly when the body already fills
   the column, which is the common case here — and that left the row sitting
   flush against the last bloc name. */
#live-card .pred-decision > .pred-actions-block {
  margin-top: auto;
  padding-top: 18px;
}

.live-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; margin-bottom: 22px; flex-wrap: wrap; }
.live-date {
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 600;
  line-height: 1.1;
}
.live-subtitle {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 6px;
  font-family: var(--font-body);
  letter-spacing: 0;
  text-transform: none;
}
.live-status {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px;
  background: var(--gold);
  color: var(--surface-raised);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  font-weight: 600;
}
.live-status .pulse {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--surface-raised);
  animation: pulse 1.8s ease-in-out infinite;
}
.live-status-group {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}
.live-committed-at {
  display: inline-flex;
  align-items: center;
  padding: 5px 12px;
  border: 1px solid var(--border-soft);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}
@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.5; transform: scale(0.85); }
}

.countdown {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-bottom: 28px;
}
.countdown-unit {
  background: var(--bg-1);
  border-radius: var(--radius);
  padding: 16px 12px;
  text-align: center;
}
.countdown-unit .v {
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 600;
  line-height: 1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.countdown-unit .u {
  font-size: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-dim);
  font-family: var(--font-mono);
  margin-top: 6px;
}

.prediction-box {
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  gap: 32px;
  padding: 24px 0;
  border-top: 1px solid var(--border-soft);
}
.pred-decision { }
.pred-decision .lbl {
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-dim);
  font-family: var(--font-mono);
  margin-bottom: 10px;
}
.pred-decision .direction {
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.5px;
}
.pred-decision .delta {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 3px;
}
.pred-decision .range {
  font-size: 12.5px;
  color: var(--text-muted);
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border-soft);
  /* Reserve two lines in both cards. The right card fills the second with its
     roll-call summary; the left card's is empty now that the provenance line is
     gone. Without this the two blocks differ by exactly one line, and that
     offset carries straight down to the rule and the label beneath it — which
     is what has to line up across the pair.
     line-height is pinned rather than left at `normal` so that `lh` is a real
     line: under `normal` the unit resolves from font metrics (~1.2) while the
     rendered line box is taller, and 2lh then reserves too little. */
  line-height: 1.64;
  /* border-box is global (see the reset above), so the reserve has to carry the
     padding too — otherwise it eats into the two lines it is meant to hold. */
  min-height: calc(2lh + 10px);
}
.pred-decision .range b { color: var(--text); }

/* Core-bloc box — the members who wanted this call in every repeat run. Sits
   between the target range and the action row so the card reads top-down as
   call → range → who was behind it → why. Deliberately mirrors .votes-box on
   the right card (same mono label, same tinted rows with a coloured left rule)
   so the two cards scan as one comparison rather than two designs; the rows
   here carry no second column because the count is constant across the bloc and
   belongs in the label, not repeated five times. */
/* Accent tracks the bloc's own direction, like the headline above it, so a
   future HOLD or CUT bloc is not stuck wearing the hawkish red. */
.bloc-box {
  --bloc-accent: var(--gold);
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
}
.bloc-box.dir-hike { --bloc-accent: var(--hawk); }
.bloc-box.dir-hold { --bloc-accent: var(--neutral); }
.bloc-box.dir-cut { --bloc-accent: var(--dove); }
.bloc-box .lbl {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 10px;
}
.bloc-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.bloc-row {
  padding: 6px 10px;
  border-left: 2px solid var(--bloc-accent);
  background: color-mix(in oklab, var(--bloc-accent) 6%, transparent);
  border-radius: 2px;
  font-size: 12px;
  line-height: 1.4;
}
.bloc-row .bloc-name {
  font-weight: 600;
  color: var(--text);
  font-family: var(--font-body);
}

/* Action row under the target range: a quiet disclosure that opens the
   reasoning behind the locked call, and the filled report download beside it.
   Deliberately unequal weight — the toggle is an outline so it reads as part of
   the card's own text, the download is the one filled control in the card and
   carries the gold. The panel is a sibling of the row rather than a child of
   the toggle, so the prose spans the full card width instead of the button's
   column. Both children are optional (see renderPredActions), so the row may
   hold either one alone; flex-start keeps a lone button from stretching. */
/* A container, not just a wrapper. The row has to stack when the CARD is
   narrow, and card width does not track viewport width here: .live-pair drops
   to one column at 900px, so a 901px viewport gives a ~340px card while an
   880px one gives a ~860px card. A viewport media query gets that band exactly
   backwards (measured: the row overflowed the card by 5px at 901px). Sizing
   containment also zeroes this subtree's min-content contribution, so the
   nowrap row can no longer widen the 1fr grid track it sits in. */
.pred-actions-block {
  margin-top: 18px;
  container-type: inline-size;
}
/* nowrap, not wrap: the card's content box is ~400px and the two labels do not
   both fit at the card's usual mono-uppercase size, so a wrapping row silently
   stacks them at every width. The toggle takes the slack (flex: 1) and the
   download hugs the right edge, which is the intended reading order; the sizes
   below are tuned so neither has to shrink at the real card width. */
.pred-actions {
  display: flex;
  flex-wrap: nowrap;
  justify-content: flex-start;
  align-items: stretch;
  gap: 8px;
}

/* The one control on this page in sentence case, not mono uppercase: it is a
   question the card just raised, and at 29 characters the uppercase mono
   treatment costs ~40px the row does not have. */
.pred-why-toggle {
  flex: 1 1 auto;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 7px;
  padding: 10px 13px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--text-muted);
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.1px;
  text-align: left;
  white-space: nowrap;
  /* Also zeroes this flex item's automatic minimum size, so a long label
     shrinks the pill instead of shoving the download past the card edge. */
  overflow: hidden;
  cursor: pointer;
  transition: color 160ms ease, border-color 160ms ease, background-color 160ms ease;
}
/* Guards the nowrap above: if a future label really is too long for the row,
   it ellipsizes inside its own pill instead of forcing the download off-card. */
.pred-why-toggle > span:last-child {
  overflow: hidden;
  text-overflow: ellipsis;
}
.pred-why-toggle:hover {
  color: var(--gold);
  border-color: var(--gold);
  background: var(--gold-glow);
}
.pred-why-toggle:focus-visible,
.pred-report:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* Drawn rather than typed: a "▸" glyph is missing from several of the mono
   fallbacks, and a border triangle inherits currentColor so it picks up the
   hover state for free. */
.pred-why-caret {
  flex: none;
  width: 0;
  height: 0;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform 160ms ease;
}
.pred-why-toggle[aria-expanded="true"] { color: var(--gold); border-color: var(--gold); }
.pred-why-toggle[aria-expanded="true"] .pred-why-caret { transform: rotate(90deg); }

.pred-report {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 10px 14px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--gold), var(--gold-soft));
  color: var(--surface-raised);
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 6px 18px var(--gold-glow);
  transition: transform 160ms ease, box-shadow 160ms ease;
}
.pred-report:hover {
  transform: translateY(-1px);
  box-shadow: 0 9px 22px var(--cta-shadow);
}
.pred-report-arrow { transition: transform 160ms ease; }
.pred-report:hover .pred-report-arrow { transform: translateX(3px); }

.pred-why-panel {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px dashed var(--border-soft);
}
.pred-why-panel p {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.75;
  color: var(--text-muted);
}
.pred-why-panel p + p { margin-top: 12px; }

/* Below this the two pills no longer fit side by side, and a shrunken toggle
   with an ellipsised question reads as debris — so they stack full width
   instead. 372px = the measured side-by-side requirement of the longest label
   pair (English, 356px) plus a 16px cushion for font fallback. Korean needs
   only ~296px, so it stacks a little earlier than it strictly must; one
   threshold for both beats a locale-specific rule, and a ~350px card is
   narrow enough that stacking is the better layout either way. */
@container (max-width: 372px) {
  .pred-actions { flex-direction: column; align-items: stretch; }
  .pred-why-toggle,
  .pred-report { justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  .pred-why-caret,
  .pred-report,
  .pred-report-arrow { transition: none; }
  .pred-report:hover { transform: none; }
  .pred-report:hover .pred-report-arrow { transform: none; }
}

.dotplot-box { }
.dotplot-box .lbl {
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-dim);
  font-family: var(--font-mono);
  margin-bottom: 10px;
  white-space: nowrap;
}
.dotplot { width: 100%; height: 180px; }

/* Constrain only the chart canvas — the label inside .dotplot-box keeps
   the full card width so "Year-end rate projections · 12 voters" stays
   on one line and lines up vertically with the right card's "Voting
   record · 12 voters" label. A small margin-top gives the chart a
   touch of breathing room below the label without opening a wide gap. */
#live-card .dotplot {
  max-width: 180px;
  margin-left: 0;
  margin-right: auto;
  margin-top: 20px;
}

/* ===== committee -> preview CTA (hero handoff) =====
   Replaces the old thin .preview-ribbon: the 12 current voters' faces make
   the hand-off to the live sandbox feel like "meet the room, then step in."
   The whole block is one <a>, so the lineup + copy are a single click target. */
.committee-cta {
  display: flex;
  align-items: center;
  gap: 28px;
  flex-wrap: wrap;
  margin: -4px 0 32px 0;
  padding: 22px 24px;
  border: 1px solid var(--border-soft);
  border-left: 3px solid var(--neutral);
  border-radius: var(--radius);
  background: linear-gradient(135deg, var(--surface), var(--surface-raised));
  box-shadow: 0 4px 16px var(--neutral-glow);
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
  cursor: pointer;
  position: relative;
}
/* The halo pulse lives on a pseudo-element and animates OPACITY, not the card's
   own box-shadow. Animating box-shadow directly repaints the card and its
   subtree every frame for the life of the page; a pre-rendered shadow on a
   throwaway layer only composites. The shadow is an outer one on a zero-content
   box at inset:0, so it can only ever draw outside the card's border box —
   nothing tints the copy, and no z-index is needed (which matters, because
   :hover's transform creates a stacking context and would reshuffle one). */
@keyframes committee-cta-pulse {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}
.committee-cta::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: 0 0 26px 8px var(--neutral-pulse);
  opacity: 0;
}
/* Added in Fomc.tsx only when the next meeting is <= 3 days out, so the halo
   is a deadline signal rather than a permanent plea for attention. Most of the
   year this class is absent and the card sits still. */
.committee-cta-imminent::before {
  animation: committee-cta-pulse 3.2s ease-in-out infinite;
}
/* Once the pointer is on the card, the card has better feedback of its own —
   the lift, the fan-out, the pill filling. Leaving the pulse running underneath
   just fights them. */
.committee-cta:hover::before {
  animation: none;
  opacity: 0;
}
/* This card is the only way into the live demo, so it has to read as a door,
   not a banner. On hover the whole border lights gold (not just the left rule),
   the lift and glow go further, and the committee row fans open — see
   .committee-face below. */
.committee-cta:hover {
  transform: translateY(-4px);
  box-shadow: 0 20px 44px var(--neutral-card-shadow);
  border-color: var(--neutral);
  border-left-color: var(--neutral-soft);
}
.committee-cta-lineup { display: flex; flex-direction: column; gap: 9px; }
/* Replaces the old "CURRENT COMMITTEE" eyebrow that sat above the faces. That
   label competed with the gold kicker in the copy column — two mono caps lines at
   nearly the same size, so the card had two heads and no focal point. The
   surnames say the same thing with more force and leave one head. */
.committee-cta-names {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.6px;
  color: var(--text-dim);
  white-space: nowrap;
  padding-left: 2px;
  transition: color 0.18s ease;
}
.committee-cta-more { color: var(--text-muted); }
.committee-cta:hover .committee-cta-names { color: var(--text-muted); }
.committee-faces { display: flex; padding-left: 2px; }
.committee-face {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  overflow: hidden;
  margin-left: -11px;
  border: 2px solid var(--surface-raised);
  background: var(--bg-1);
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.18);
  position: relative;
  /* --i (set per face in Fomc.tsx) staggers both the shift and its timing, so
     the row opens left-to-right like a hand of cards rather than snapping. */
  transition: transform 0.22s cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: calc(var(--i, 0) * 14ms);
}
.committee-face:first-child { margin-left: 0; }
/* Fan out on hover of the CARD, not the individual face — the faces are the
   thing that says "a room of people", and previously they only reacted if you
   landed on one exactly, so the card's best signal never fired. translateX
   rather than margin: margins would reflow the copy sitting next to it.

   The fan is anchored on the middle of the row (hence the -5.5 on a 12-face
   lineup) so it opens both ways from its centre. Spreading rightward from the
   first face pushed the last one 44px into the 31px gap before the copy column,
   and it landed on top of the "Open the live preview" pill. Centred, each end
   travels ~17px and both stay clear. */
.committee-cta:hover .committee-face {
  transform: translateX(calc((var(--i, 0) - 5.5) * 3px));
}
/* The hovered face still lifts out of the row, and wins over the fan. */
.committee-cta:hover .committee-face:hover {
  transform: translateX(calc((var(--i, 0) - 5.5) * 3px)) translateY(-5px) scale(1.1);
  transition-delay: 0s;
  z-index: 3;
}
.committee-face img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The source headshots are tall portraits (~120×275, head-and-shoulders), so a
     square avatar with object-fit:cover only shows a ~44% vertical band. `top`
     showed the crown but cut the chin; 13% down slides that band onto the face so
     the whole head — hairline to chin — lands inside the circle for all 12 members
     (only a sliver of hair above the crown is trimmed). */
  object-position: 50% 13%;
  user-select: none;
}
/* (The lone .committee-face:hover rule that used to sit here is folded into
   .committee-cta:hover .committee-face:hover above — kept separate it would win
   on source order and cancel the fan-out's translateX.) */
.committee-cta-copy {
  flex: 1;
  min-width: 250px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.committee-cta-kicker {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 2.2px;
  text-transform: uppercase;
  color: var(--neutral);
  font-weight: 700;
}
/* The serif headline that carries the demo's hero into the card. Same face as
   the page h1 so the two rhyme; smaller, because the card is a door, not the
   masthead. The accent word is the demo's indigo (not the page's gold) — the
   colour is the tell that this block belongs to the preview it opens. */
.committee-cta-headline {
  font-family: var(--font-display);
  font-size: clamp(21px, 2.3vw, 26px);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.3px;
  color: var(--text);
  margin: 1px 0;
}
.committee-cta-headline .accent {
  color: var(--neutral);
  font-style: italic;
}
/* Was an outlined pill that only committed to being a button on hover. This is
   the door to the live demo, so it now reads as the demo's own primary CTA at
   rest — filled indigo, the "START THE SIMULATION" affordance from the preview
   app — and the whole card lifts it on hover. Uppercase mono to match the
   button language on the meeting chooser it opens ("ENTER THE ROOM"). */
.committee-cta-link {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  color: var(--surface-raised);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  padding: 11px 22px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--neutral), var(--neutral-soft));
  box-shadow: 0 6px 18px var(--neutral-glow);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.committee-cta:hover .committee-cta-link {
  transform: translateY(-1px);
  box-shadow: 0 12px 26px var(--neutral-card-shadow);
}

/* Row holding the filled CTA pill and the gated-access cue on one baseline. The
   margin that used to sit on .committee-cta-link lives here now, so the two stay
   vertically centred together; it wraps to a second line on narrow cards. */
.committee-cta-action {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 14px;
  margin-top: 6px;
}
/* "Invite-only" — deliberately quieter than the pill: small mono, muted, so it
   reads as metadata on the button, not a second action. The gold accent (not
   the demo's indigo) marks it as a status note belonging to the page. */
.committee-cta-access {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--text-muted);
  white-space: nowrap;
}
/* Static, not pulsing — the live-status .pulse means "a call is locked/live";
   a pulse here would read as the same signal. Gold = by-invitation, not blocked
   (which a red dot would imply). Decorative: meaning is carried by the label. */
.committee-cta-access-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--gold);
  box-shadow: 0 0 0 3px var(--gold-glow);
  flex: none;
}

/* ===== rate-path section — dot plot promoted to its own full-width section ===== */
.ratepath-frame {
  margin-top: 30px;
  padding: 26px 24px 22px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  background: var(--surface);
}
.ratepath-plot {
  width: 100%;
  height: 360px;
  max-width: 780px;
  margin: 0 auto;
}
.ratepath-caption {
  max-width: 720px;
  margin: 16px auto 0;
  text-align: center;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-muted);
  font-family: var(--font-mono);
}
.ratepath-caption b { color: var(--text); font-weight: 700; }

/* Side-by-side prediction vs. actual dot plots (the actual column is revealed
   only once the meeting resolves). One visible column centers; two share the row. */
.ratepath-compare {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  justify-content: center;
  align-items: flex-start;
  margin-top: 30px;
}
.ratepath-col {
  /* Basis 440 (was 500) so the prediction + actual columns sit side by side
     inside the 960px content box — two 500px columns plus the 24px gap needed
     ~1024px and always stacked. At 440 the pair fits (2×440 + 24 = 904 ≤ 960)
     and only stacks once the viewport itself is narrower than that. The trade
     for fitting is that the "Median path:" caption may wrap to a second line in
     the ~468px columns this yields (see .ratepath-median below) — that keeps the
     layout correct for every visitor regardless of which mono font their system
     falls back to, rather than betting the one-line caption on a fixed width. */
  flex: 1 1 440px;
  min-width: 0;
  max-width: 780px;
}
.ratepath-col .ratepath-frame { margin-top: 10px; }
.ratepath-col-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-dim);
  text-align: center;
}
.ratepath-col .ratepath-caption { font-size: 11px; line-height: 1.55; margin-top: 12px; }
/* Wraps (was nowrap). In the side-by-side layout each column is ~468px, too
   narrow to hold the whole "Median path: …" line on one row for a 0.6em mono
   fallback — so let it wrap at the "·" separators instead of overflowing the
   frame. It breaks between horizons cleanly and stays readable as two lines. */
.ratepath-median { white-space: normal; }

@media (max-width: 768px) {
  .committee-cta { gap: 18px; padding: 16px 18px; }
  /* The 12-avatar lineup is fixed-width on desktop, which overflowed the card
     on phones (12 × 36px − overlap ≈ 322px > the ~260px card inner width).
     Make it fluid: the row fills the card and each face shrinks equally to fit,
     so all 12 stay visible and inside the border at any phone width.
     aspect-ratio keeps each face circular as its width shrinks; max-width caps
     them at the desktop size on wider screens. */
  .committee-cta-lineup { width: 100%; }
  .committee-faces { width: 100%; align-items: center; }
  .committee-face {
    flex: 1 1 0;
    width: auto;
    height: auto;
    aspect-ratio: 1 / 1;
    min-width: 0;
    max-width: 40px;
    margin-left: -9px;
  }
  .committee-face:first-child { margin-left: 0; }
  .ratepath-frame { padding: 18px 14px; }
  .ratepath-plot { height: 300px; }
}

.live-foot {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--border-soft);
  font-size: 13.5px;
  color: var(--text-muted);
}
.live-foot b { color: var(--text); }

/* ===== past grid ===== */
.past-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 28px;
}

.past-card {
  background: var(--surface-raised);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: 28px 28px 22px 28px;
  /* Flex column so the "open detail" footer pins to the bottom regardless of how
     tall each card's stats block is — keeps the footers aligned across the row
     (cards already stretch to equal height in the grid). */
  display: flex;
  flex-direction: column;
  /* The whole card is now the link to /fomc/<date>. */
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  transition: transform 160ms ease, box-shadow 160ms ease, border-color 160ms ease;
}
.past-card > .past-card-more { margin-top: auto; }
.past-card.hit { border-color: var(--hit); box-shadow: 0 0 0 1px var(--hit) inset; }
.past-card.miss { border-color: var(--border); }
.past-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 30px var(--neutral-card-shadow, rgba(0, 0, 0, 0.12));
  border-color: var(--gold);
}
.past-card:focus-visible {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 2px var(--gold);
}
/* Footer affordance — quiet at rest, the arrow slides on hover to signal the
   card opens somewhere. */
.past-card-more {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px dashed var(--border-soft);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.4px;
  color: var(--text-muted);
  transition: color 160ms ease, border-color 160ms ease;
}
.past-card-more-chevron { color: var(--gold); transition: transform 160ms ease; }
.past-card:hover .past-card-more { color: var(--text); border-top-color: var(--gold); }
.past-card:hover .past-card-more-chevron { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) {
  .past-card, .past-card-more-chevron { transition: none; }
  .past-card:hover { transform: none; }
  .past-card:hover .past-card-more-chevron { transform: none; }
}

.past-card-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  margin-bottom: 22px;
}
.past-card-date {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 600;
  line-height: 1.1;
}
.past-card-date small {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
  font-weight: 400;
  letter-spacing: 1px;
  margin-top: 2px;
}
.verdict {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 2px;
  font-weight: 700;
  padding: 5px 10px;
  border-radius: 4px;
}
.verdict.hit { background: var(--hit-bg); color: var(--hit); }
.verdict.miss { background: var(--miss-bg); color: var(--miss); }

.compare-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin-bottom: 20px;
}
.compare-col { }
.compare-col .side {
  font-size: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-dim);
  font-family: var(--font-mono);
  margin-bottom: 8px;
}
.compare-col .big {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 600;
  line-height: 1;
}
.compare-col .small {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 6px;
}

.diff-row {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
  padding-top: 18px;
  border-top: 1px solid var(--border-soft);
}
.diff-stat { text-align: left; }
.diff-stat .v {
  font-family: var(--font-mono);
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
}
.diff-stat .l {
  font-size: 10px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-dim);
  font-family: var(--font-mono);
  margin-top: 4px;
}

.statement-diff {
  margin-top: 20px;
  padding: 14px 16px;
  background: var(--bg-1);
  border-radius: var(--radius-sm);
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.55;
}
.statement-diff b { color: var(--text); }

/* Analysis note — label + bulleted list (replaces "Analyst note · ..." prose). */
.statement-diff .note-label {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 8px;
}
.statement-diff .note-bullets {
  margin: 0;
  padding-left: 18px;
  list-style: disc;
}
.statement-diff .note-bullets li {
  margin-bottom: 4px;
}
.statement-diff .note-bullets li:last-child { margin-bottom: 0; }
.statement-diff .note-bullets li::marker { color: var(--text-dim); }

/* ===== three cores (Persona · Memory · Deliberation) ===== */
.cores-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}
.core-card {
  background: var(--surface-raised);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: 28px 26px 24px 26px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  position: relative;
  overflow: hidden;
}
.core-card::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--gold), transparent 120%);
}
.core-card[data-core="persona"]::before { background: linear-gradient(90deg, var(--persona), transparent 120%); }
.core-card[data-core="memory"]::before { background: linear-gradient(90deg, var(--gold), transparent 120%); }
.core-card[data-core="deliberation"]::before { background: linear-gradient(90deg, var(--delib), transparent 120%); }

.core-head { display: flex; flex-direction: column; gap: 10px; }
.core-badge {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--gold);
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  align-self: flex-start;
  background: var(--bg-1);
}
.core-card[data-core="persona"] .core-badge { color: var(--persona-strong); border-color: var(--persona-bd); background: var(--persona-bg); }
.core-card[data-core="deliberation"] .core-badge { color: var(--delib-strong); border-color: var(--delib-bd); background: var(--delib-bg); }

.core-head h3 {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 600;
  line-height: 1.15;
  margin: 0;
  color: var(--text);
}
.core-mech {
  font-size: 14.5px;
  color: var(--text-muted);
  margin: 0;
  line-height: 1.6;
}
.core-mech code {
  font-size: 0.92em;
  color: var(--gold-soft);
  background: var(--bg-1);
}
.core-proof {
  padding: 14px 16px;
  background: var(--bg-1);
  border-radius: var(--radius-sm);
  display: flex; flex-direction: column; gap: 10px;
}
.core-proof-line {
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.55;
}
.core-proof-line b { color: var(--text); }
.core-link {
  margin-top: auto;
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--gold);
  padding-top: 14px;
  border-top: 1px dashed var(--border-soft);
  transition: color 0.15s ease;
  display: inline-block;
}
.core-link:hover { color: var(--gold-soft); }

/* ===== roadmap (Mirror Real Ones line) ===== */
.roadmap-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
.roadmap-card {
  background: var(--surface-raised);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: 28px 26px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  position: relative;
}
.roadmap-card.shipping {
  border-color: var(--hit);
  box-shadow: 0 0 0 1px var(--hit) inset, 0 20px 40px -24px var(--shipping-shadow);
}
.roadmap-card.next { opacity: 0.92; }

.roadmap-stage {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 999px;
  align-self: flex-start;
}
.roadmap-card.shipping .roadmap-stage {
  color: var(--hit);
  background: var(--hit-bg);
  border: 1px solid var(--hit-bg-strong);
}
.roadmap-card.next .roadmap-stage {
  color: var(--text-dim);
  background: var(--bg-2);
  border: 1px solid var(--border-soft);
}

.roadmap-product {
  font-family: var(--font-display);
  font-size: 40px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.5px;
  color: var(--text);
}
.roadmap-tagline {
  font-family: var(--font-display);
  font-size: 17px;
  font-style: italic;
  color: var(--gold);
  line-height: 1.3;
}
.roadmap-card p {
  font-size: 13.5px;
  color: var(--text-muted);
  margin: 8px 0 0 0;
  line-height: 1.6;
}

.regime-note {
  margin-top: 24px;
  padding: 22px 26px;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-left: 3px solid var(--miss);
  border-radius: var(--radius);
  color: var(--text-muted);
  font-size: 14.5px;
  line-height: 1.6;
}
.regime-note b { color: var(--text); }
.regime-note .num {
  font-family: var(--font-mono);
  color: var(--miss);
  font-weight: 600;
}

/* ===== N=3 reruns · metric cards (3×2 desktop, 2×3 tablet, 1×6 mobile) ===== */
.metric-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
.metric-card {
  background: var(--surface-raised);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: 24px 24px 22px 24px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.metric-num {
  font-family: var(--font-display);
  font-size: 38px;
  font-weight: 600;
  line-height: 1;
  color: var(--gold);
  letter-spacing: -0.5px;
  font-variant-numeric: tabular-nums;
}
.metric-label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--text);
  font-weight: 600;
  margin-top: 4px;
}
.metric-desc {
  font-size: 12.5px;
  color: var(--text-muted);
  line-height: 1.5;
}

@media (max-width: 900px) {
  .metric-grid { grid-template-columns: repeat(2, 1fr); gap: 14px; }
  .metric-num { font-size: 32px; }
}
@media (max-width: 540px) {
  .metric-grid { grid-template-columns: 1fr; }
}

/* ===== deliberation transcript (expandable) ===== */
.deliberation {
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px dashed var(--border-soft);
}
.deliberation-summary {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 12px;
  margin-left: -12px;
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--text-muted);
  transition: background 0.15s ease, color 0.15s ease;
  user-select: none;
}
.deliberation-summary::-webkit-details-marker { display: none; }
.deliberation-summary:hover { background: var(--gold-glow); color: var(--text); }
.deliberation-summary .chevron {
  display: inline-block;
  transition: transform 0.18s ease;
  color: var(--gold);
}
.deliberation[open] > .deliberation-summary .chevron { transform: rotate(90deg); }
.deliberation-label { color: var(--text); font-weight: 600; letter-spacing: 0.3px; }
.deliberation-meta { color: var(--text-dim); }

.deliberation-body {
  margin-top: 14px;
  padding: 18px 20px;
  background: #1c1812;
  color: #dcd2bf;
  border: 1px solid #2e2619;
  border-radius: var(--radius);
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.55;
  max-height: 520px;
  overflow-y: auto;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.02);
}
.deliberation-body::-webkit-scrollbar { width: 8px; }
.deliberation-body::-webkit-scrollbar-track { background: transparent; }
.deliberation-body::-webkit-scrollbar-thumb { background: #3a3021; border-radius: 4px; }

.deliberation-phase {
  margin: 14px 0 12px 0;
  padding: 4px 10px;
  display: inline-block;
  border-radius: 3px;
  background: linear-gradient(90deg, #3a3021 0%, transparent 100%);
  color: #d4b260;
  font-size: 11px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  font-weight: 600;
}
.deliberation-phase:first-child { margin-top: 0; }

.deliberation-turn { margin: 10px 0 14px 0; }
.deliberation-speaker {
  display: flex; align-items: baseline; gap: 8px;
  margin-bottom: 4px;
}
.phase-badge {
  display: inline-block;
  padding: 1px 6px;
  background: #2c2418;
  border: 1px solid #4a3a24;
  border-radius: 3px;
  color: #b89860;
  font-size: 10px;
  letter-spacing: 1px;
  font-weight: 600;
}
.deliberation-turn.p1 .phase-badge { color: #7fb8aa; border-color: #2d4a43; }
.deliberation-turn.p2 .phase-badge { color: #8ab0d8; border-color: #2d3f55; }
.deliberation-turn.p3 .phase-badge { color: #e0b968; border-color: #5a4520; }
.deliberation-turn.p4 .phase-badge { color: #c79ed6; border-color: #4a3858; }

.speaker-name {
  color: #f2e6c9;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.3px;
}
.deliberation-message {
  padding-left: 2px;
  color: #c4b89f;
  word-wrap: break-word;
}
.deliberation-message strong { color: #f2e6c9; }

mark.citation {
  background: rgba(212, 178, 96, 0.14);
  color: #d4b260;
  padding: 0 4px;
  border-radius: 3px;
  font-size: 11px;
  letter-spacing: 0.2px;
  white-space: normal;
}

/* ===== footer ===== */
.site-footer {
  margin-top: 64px;
  padding: 40px 0 48px 0;
  border-top: 1px solid var(--border-soft);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
  color: var(--text-muted);
  font-size: 13px;
  line-height: 1.65;
}
.footer-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 6px;
}
.footer-voice {
  font-family: var(--font-display);
  font-size: 14.5px;
  color: var(--gold);
  display: inline-block;
}

/* The committee card's hover is motion-heavy (lift + a 12-face fan). Honour a
   reduced-motion request by keeping the colour cues — indigo border, filled pill —
   and dropping the movement, so the affordance survives without the animation. */
@media (prefers-reduced-motion: reduce) {
  .committee-cta,
  .committee-face,
  .committee-cta-link {
    transition: none;
  }
  .committee-cta:hover {
    transform: none;
  }
  .committee-cta:hover .committee-face {
    transform: none;
  }
  /* The filled button is filled at rest, so the affordance survives without the
     lift — drop only the movement. */
  .committee-cta:hover .committee-cta-link {
    transform: none;
  }
  /* A pulse is the one thing here nobody can wait out. */
  .committee-cta::before,
  .committee-cta-imminent::before {
    animation: none;
    opacity: 0;
  }
}

/* ===== responsive ===== */
@media (max-width: 900px) {
  .topbar { padding: 12px 20px; }
  .topnav { gap: 14px; }
  .topnav a { font-size: 12.5px; }
  .brand-sub { display: none; }

  /* Scoped for the same reason as the base rule above — unscoped, this hit the
     app shell's <main> too and mobile got 40px of gutter instead of 20. */
  .fomc-page main { padding: 0 20px; }
  .section.alt { margin-left: -20px; margin-right: -20px; padding-left: 20px; padding-right: 20px; }

  /* The white-space: normal overrides that used to live here are gone with the
     nowrap they undid — the headline and ledes now wrap at every width. */
  .section { padding: 64px 0; }
  .section h2 { font-size: 32px; }

  .hero { padding: 40px 0 32px 0; }
  .hero h1 { font-size: clamp(26px, 6.6vw, 38px); }
  .hero .lede { font-size: 15.5px; }
  .preview-ribbon { margin-top: -2px; }

  .prediction-box { grid-template-columns: 1fr; gap: 24px; }
  .past-grid { grid-template-columns: 1fr; gap: 20px; }
  .cores-grid { grid-template-columns: 1fr; gap: 20px; }
  .roadmap-row { grid-template-columns: 1fr; gap: 16px; }
  .site-footer { grid-template-columns: 1fr; gap: 20px; }

  .countdown-unit .v { font-size: 30px; }
  .pred-decision .direction { font-size: 26px; }

  /* Tighter side padding so the card's body text has room to breathe
     once the live-pair stacks into one column. */
  .live-card { padding: 24px 20px; }
  /* Allow the dotplot label to wrap on narrow screens — otherwise the
     nowrap min-content forces the grid track wider than the viewport
     and overflow: hidden clips both this label and the "Source-traced…"
     line that sits in the same prediction-box. */
  .dotplot-box .lbl { white-space: normal; }
}

@media (max-width: 540px) {
  .countdown { grid-template-columns: repeat(4, 1fr); gap: 6px; }
  .countdown-unit { padding: 12px 6px; }
  .countdown-unit .v { font-size: 24px; }
  .countdown-unit .u { font-size: 9px; letter-spacing: 1px; }
  .compare-row { grid-template-columns: 1fr; }
  .diff-row { grid-template-columns: 1fr 1fr; }
}

/* ===== company-page additions: two-card live layout + contact-gated deliberation ===== */

/* Live row — two cards side by side */
.live-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  align-items: stretch;
}

/* Left (locked prediction) card — stack HOLD over dotplot vertically.
   Same rule applies to the post-release right card so its prediction-box
   matches the locked card's layout.

   gap is 0 because the two cards hang their list off different levels: the left
   card's .bloc-box is inside .pred-decision, the right card's .votes-box is a
   sibling of it and so picks up a grid gap the left one never sees. That gap was
   the last 20px keeping the two labels off the same line. Spacing above each
   list is now owned entirely by .bloc-box / .votes-box margin-top, which are
   equal — the left grid has a single child, so it loses nothing here. */
#live-card .prediction-box,
.live-card-actual .prediction-box {
  grid-template-columns: 1fr;
  gap: 0;
}

/* Right (pending) card — dim, hazy backdrop with one centered message */
.live-card-pending {
  display: flex;
  align-items: center;
  justify-content: center;
  border-style: dashed;
  border-color: var(--border);
  background: linear-gradient(180deg, var(--surface) 0%, var(--pending-grad-end) 100%);
  position: relative;
  overflow: hidden;
}
.live-card-pending::before { display: none; }

.pending-haze {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 30% 30%, var(--pending-haze-radial), transparent 60%),
    repeating-linear-gradient(
      45deg,
      transparent 0,
      transparent 18px,
      var(--pending-haze-stripe) 18px,
      var(--pending-haze-stripe) 22px
    );
  filter: blur(1.6px);
  pointer-events: none;
}

.pending-only-message {
  position: relative;
  z-index: 1;
  font-family: var(--font-display);
  font-size: clamp(30px, 4.4vw, 44px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.5px;
  color: var(--text-muted);
  text-align: center;
  padding: 72px 32px;
}

/* Right card · post-release verdict view. The base .live-card class
   provides chrome (background, border, padding) so it matches the left
   card visually for a clean left-vs-right comparison. */

/* Voting record block — parallels the .bloc-box on the left card, and carries
   the same rule above it so both cards separate their range block from the
   list below it the same way. Keep these three values in sync with .bloc-box:
   they are what puts the two labels on one line. */
.live-card-actual .votes-box {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
}
.live-card-actual .votes-box .lbl {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 10px;
}
.vote-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.vote-row {
  display: grid;
  grid-template-columns: minmax(140px, max-content) 1fr;
  gap: 12px;
  padding: 6px 10px;
  border-left: 2px solid var(--hawk, var(--gold));
  background: color-mix(in oklab, var(--hawk, var(--gold)) 6%, transparent);
  border-radius: 2px;
  font-size: 12px;
  line-height: 1.4;
}
.vote-row .vote-name {
  font-weight: 600;
  color: var(--text);
  font-family: var(--font-body);
}
.vote-row .vote-reason {
  color: var(--text-muted);
}

/* The verdict strip that used to sit under .live-pair — hit/miss badge, diff
   stats, analysis note — was removed along with its renderer. Its classes
   (.verdict-strip/-row/-badge/-stats, .v-stat) had no other user; the record
   grid's own verdict uses .verdict / .diff-row / .diff-stat, below. */

/* Engine-match indicator on the right card's dissenter list. The strong
   variant highlights our most impactful match (Miran's 25bp cut called
   six days early); the soft variant marks the partial-credit row where
   we flagged the dissent but missed the reasoning. */
.vote-row.has-match {
  border-left-color: var(--neutral, var(--gold));
  background: color-mix(in oklab, var(--neutral, var(--gold)) 6%, transparent);
}
.vote-row.strong-match {
  border-left-color: var(--gold);
  background: var(--gold-glow);
}
.engine-tag {
  grid-column: 1 / -1;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.6px;
  margin-top: 2px;
  padding: 2px 0 0 0;
}
.engine-tag.strong {
  color: var(--gold);
  font-weight: 600;
  letter-spacing: 0.8px;
}
.engine-tag.soft {
  color: var(--text-muted);
}

/* deliberation request link · full-width strip with dashed top/bottom */
.deliberation-link {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 22px;
  padding: 14px 4px;
  border-top: 1px dashed var(--border-soft);
  border-bottom: 1px dashed var(--border-soft);
  background: transparent;
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text-muted);
  text-decoration: none;
  letter-spacing: 0.3px;
  transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
}
.deliberation-link:hover {
  background: var(--gold-glow);
  color: var(--text);
  border-top-color: var(--gold);
  border-bottom-color: var(--gold);
}
.deliberation-link .chevron { color: var(--gold); }
.deliberation-link .deliberation-label { color: var(--text); font-weight: 600; letter-spacing: 0.3px; }
.deliberation-link .deliberation-meta { color: var(--text-muted); }

/* Three parts — let .core-mech absorb extra vertical space so .core-proof
   sits flush at the bottom of every card (uniform card baselines) */
.cores-grid .core-card .core-mech { flex: 1 0 auto; }

/* Mini footer — Observatory-style single line */
.site-footer-mini {
  padding: 32px 0 48px;
  border-top: 1px solid var(--border-soft);
  margin-top: 24px;
}
.footer-mini-row {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text-dim);
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.footer-mini-row .dot { color: var(--border); }
.footer-mini-row a {
  color: var(--text-muted);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 150ms ease, border-color 150ms ease;
}
.footer-mini-row a:hover {
  color: var(--gold);
  border-bottom-color: var(--gold);
}

@media (max-width: 900px) {
  .live-pair { grid-template-columns: 1fr; gap: 16px; }
}

/* ===== utility: direction colors + load-error banner =====
   Replaces inline style="" attributes that app.js used to set.
   Theme tokens drive the color, so a sunrise/sunset flip
   recolors them automatically. */
.pred-decision .direction.dir-cut  { color: var(--dove); }
.pred-decision .direction.dir-hike { color: var(--hawk); }
.pred-decision .direction.dir-hold { color: var(--neutral); }

.error-banner {
  padding: 20px;
  background: var(--warn-bg);
  border: 1px solid var(--warn-border);
  color: var(--warn-text);
  font-family: var(--font-mono);
  font-size: 13px;
}

/* ===== per-meeting detail page (/fomc/<date>) ===== */
.fomc-detail-main { padding-bottom: 96px; }

.detail-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 8px 0 28px;
}
.detail-back {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.6px;
  color: var(--text-muted);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 150ms ease, border-color 150ms ease;
}
.detail-back:hover { color: var(--gold); border-bottom-color: var(--gold); }

.detail-head { padding: 8px 0 12px; }
.detail-title {
  font-family: var(--font-display);
  font-size: clamp(30px, 5vw, 46px);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.5px;
  margin: 6px 0 12px;
}
.detail-meta {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.detail-id {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 1px;
  color: var(--text-dim);
}
.verdict.pending {
  background: var(--gold-glow);
  color: var(--gold);
}

.detail-section {
  padding: 34px 0 6px;
  border-top: 1px solid var(--border-soft);
  margin-top: 30px;
}
.detail-section:first-of-type { border-top: none; margin-top: 8px; }
.detail-h2 {
  font-family: var(--font-display);
  font-size: clamp(20px, 2.6vw, 26px);
  font-weight: 600;
  letter-spacing: -0.2px;
  margin: 0 0 18px;
}
.detail-section-lede {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text-muted);
  margin: -8px 0 20px;
}
.detail-pending-note {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--text-muted);
  font-style: italic;
  padding-top: 16px;
  border-top: 1px solid var(--border-soft);
}
/* Direction colour on the detail summary (the index cards leave these neutral;
   the deep view can afford the cue). */
.detail-section .compare-col .big.dir-cut  { color: var(--dove); }
.detail-section .compare-col .big.dir-hike { color: var(--hawk); }
.detail-section .compare-col .big.dir-hold { color: var(--neutral); }

/* --- statements, side by side --- */
.statement-compare {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
}
.statement-col {
  display: flex;
  flex-direction: column;
  background: var(--surface-raised);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: 22px 24px;
}
.statement-col-label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 12px;
}
.statement-body { font-family: var(--font-body); font-size: 14.5px; line-height: 1.7; color: var(--text-muted); }
.statement-body p { margin: 0 0 12px; }
.statement-body p:last-child { margin-bottom: 0; }

/* Teaser marker — a vertical ellipsis (three stacked dots) capping a truncated
   block on the detail page. In the statement columns it is pinned to the foot so
   the two grid-stretched columns end their ellipsis on the same line. */
.trunc-more {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 16px 0 4px;
}
.trunc-more span {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text-dim);
}
.statement-col .trunc-more { margin-top: auto; }

/* --- deliberation transcript: one collapsible <details> per phase; opening a
   phase reveals a teaser (first substantive turn's opening block) + ellipsis --- */
.transcript { display: flex; flex-direction: column; gap: 10px; }
.tr-phase-block {
  background: var(--surface-raised);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
/* The phase header is the toggle. Mono + gold, with a chevron that rotates open
   and a turn-count chip on the right. */
.tr-phase {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  padding: 16px 20px;
  list-style: none;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--gold);
  transition: background 150ms ease;
}
.tr-phase::-webkit-details-marker { display: none; }
.tr-phase::before {
  content: '▸';
  font-size: 11px;
  transition: transform 150ms ease;
}
.tr-phase-block[open] > .tr-phase::before { transform: rotate(90deg); }
.tr-phase:hover { background: var(--gold-glow); }
.tr-phase-block[open] > .tr-phase { border-bottom: 1px solid var(--border-soft); }
.tr-phase-label { flex: 1; }
.tr-phase-count {
  font-size: 10px;
  letter-spacing: 1px;
  color: var(--text-dim);
  background: var(--gold-glow);
  border-radius: 999px;
  padding: 2px 9px;
}
.tr-phase-body { padding: 6px 20px 16px; }
.tr-turn { padding: 14px 0 2px; }
.tr-speaker {
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.8px;
  color: var(--text);
  margin-bottom: 10px;
}
.tr-body {
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.68;
  color: var(--text-muted);
}
.tr-body p { margin: 0 0 10px; }
.tr-body p:last-child { margin-bottom: 0; }
.tr-body .tr-h {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 14px 0 6px;
}
.tr-body .tr-li { position: relative; padding-left: 16px; margin: 4px 0; }
.tr-body .tr-li::before { content: '·'; position: absolute; left: 4px; color: var(--gold); }
/* Inline source citation collapsed from the verbatim quote — the quote survives
   in the title tooltip. */
.tr-cite {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--gold);
  background: var(--gold-glow);
  border-radius: 4px;
  padding: 1px 6px;
  white-space: nowrap;
  cursor: help;
}

@media (max-width: 700px) {
  .statement-compare { grid-template-columns: 1fr; }
  .tr-turn { padding: 8px 0 2px; }
}
.error-banner a { color: var(--warn-text); text-decoration: underline; }
