/* ====================================================
   VOTER CHOICE · 2026 redesign — overrides
   ====================================================
   ONLY the new surfaces. Everything else (cards, workspace grid,
   ballot pane, print sheet, responsive breakpoints) comes from the
   shipped prototype.css / prototype-c.css untouched.
   ==================================================== */

/* ---- app-wide Bold Flag / Keystone default (body.bf-app, set in
   src/app/layout.tsx — every route shares one class, including the static
   content pages that render outside App2's own #root; the legacy ballot
   app under NEXT_PUBLIC_BALLOT_ENABLED keeps the civic default instead).
   Same white/navy/red palette .hp-hero (prototype.css) and .ori-body
   (below) already scope locally, promoted to the whole app so every
   shared component that reads --paper/--ink/etc. picks it up for free.
   --civic is left untouched — it doubles as the alignment "keep" green
   elsewhere in the app; --bf-brand/--bf-brand-2 are new tokens for
   anything that needs the Keystone navy specifically. ---- */
.bf-app {
  --paper: oklch(1 0 0);
  --paper-2: oklch(0.985 0.003 258);
  --ink: oklch(0.2 0.035 260);
  --ink-2: oklch(0.37 0.032 260);
  --ink-3: oklch(0.54 0.026 260);
  --rule: oklch(0.88 0.006 260);
  --rule-2: oklch(0.93 0.005 260);
  --tag-bg: oklch(0.95 0.006 260);
  --bf-brand: oklch(0.4 0.155 262);
  --bf-brand-2: oklch(0.31 0.145 262);
  /* Same hue-262 soft tint .rep-card already uses for --civic-soft under
     its own local navy remap — reused here as the app-wide navy "soft"
     token (canvas's --brand-soft) for anything outside .rep-card that
     needs a light navy tint (e.g. the user chat bubble below). */
  --bf-brand-soft: oklch(0.94 0.04 262);
  /* Inheritable navy alias (canvas's own token names) — a new redesign
     surface that reads var(--brand)/var(--brand-2)/var(--brand-soft) now
     gets Bold Flag navy for free without needing its own local remap
     block. Existing per-scope remaps (.rep-card, .delegation, .pe-screen,
     .cmp, .polisstand2, .standing2) stay authoritative where they
     redefine --brand themselves; this only fills the gap for anything
     that has no local remap at all. Safety-checked: every existing
     var(--brand) read in redesign2.css/candidates.css already resolves
     inside one of those local-remap scopes, so this alias changes nothing
     that already renders — it only covers future/unscoped reads. */
  --brand: var(--bf-brand);
  --brand-2: var(--bf-brand-2);
  --brand-soft: var(--bf-brand-soft);
  background: var(--paper);
  /* Short-content stages (e.g. the honest error states in App2.tsx) don't
     fill the viewport on their own — without this, body's own un-scoped
     civic/cream background (declared on body itself, outside .bf-app's
     scope) shows through below the fold. */
  min-height: 100vh;
}

/* ---- provenance badge (roll-call vs researched) — canvas's ProvBadge
   unifier, ported from HeadToHead.tsx's .cmp .prov / DelegationOverview.tsx's
   DgProv onto RepCard's own civic-palette scope (no --brand remap needed;
   --civic/--vote-red/--paper-2 already resolve correctly here). ---- */
.cv2-prov-row {
  padding: 0 18px;
  margin-top: -2px;
}
.rep-card .prov {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  padding: 3px 8px 3px 7px;
  border-radius: 5px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
  line-height: 1.4;
}
.rep-card .prov::before {
  font-size: 9px;
}
.rep-card .prov.rollcall {
  background: var(--civic);
  color: var(--paper-2);
  border: 1.5px solid var(--civic);
}
.rep-card .prov.rollcall::before {
  content: "\25C6"; /* filled diamond */
}
.rep-card .prov.researched {
  background: var(--paper-2);
  color: var(--civic-2);
  border: 1.5px dashed var(--civic);
}
.rep-card .prov.researched::before {
  content: "\25C7"; /* hollow diamond */
}

/* ---- seat strip (top of RepCard) ---- */
.seat-strip {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 18px;
  border-bottom: 1px solid var(--rule-2);
  background: var(--paper);
}
.seat-office {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--tag-bg);
  color: var(--ink-2);
  padding: 3px 8px;
  border-radius: 5px;
}
.seat-district {
  font-size: 12.5px;
  color: var(--ink-3);
}
.seat-next {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
  letter-spacing: 0.03em;
}
.seat-next.up {
  color: var(--civic-2);
  font-weight: 600;
}

/* ---- non-2026 reps: de-emphasized + labeled, excluded from print ---- */
/* "Not up for election in 2026" badge up front on the rep card seat strip. */
.seat-not-up {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--tag-bg);
  /* --ink-3 on --tag-bg is ~4.4:1, just under AA's 4.5:1 (same gap as
     .cv2-sub.blind .cv2-tag below) — scoped darkened override. */
  color: oklch(0.5 0.026 260);
  padding: 3px 8px;
  border-radius: 5px;
}
/* A challenger whose party nomination is still pending a primary runoff —
   unlike .seat-not-up (de-emphasized, settled), this is an active CTA: the
   reader can still influence who ends up on their November ballot. */
.runoff-pending-tag {
  margin-left: 6px;
  background: var(--gold);
  color: var(--ink);
}
.runoff-pending-note {
  color: var(--ink-2);
  font-style: italic;
}

/* Open seat (v3 §6) — a neutral fact, not a warning; navy tint distinguishes
   it from the de-emphasized grey .seat-not-up pill it's always paired with. */
.seat-not-seeking-reelection {
  background: var(--civic-soft);
  color: var(--civic);
}

/* ---- open-seat verdict slot (replaces keep/replace when
   cand.seekingReelection2026 === false) ---- */
.rep-card .open-band {
  margin: 20px 18px 0;
  padding: 13px 16px 14px;
  border: 1px solid oklch(0.86 0.045 262);
  background: var(--civic-soft);
  border-radius: 12px;
}
.rep-card .open-band .ob-kick {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--civic);
  margin-bottom: 5px;
}
.rep-card .open-band p {
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink-2);
  margin: 0;
}
.rep-card .open-band .src {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
  margin-top: 7px;
}
.rep-card .btn-open {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  width: calc(100% - 36px);
  padding: 16px 14px;
  margin: 12px 18px 0;
  border-radius: 12px;
  border: 1.5px solid transparent;
  background: var(--civic);
  color: #fff;
  cursor: pointer;
  font-family: var(--sans);
  min-height: 44px;
}
.rep-card .btn-open:hover {
  background: var(--civic-2);
}
.rep-card .btn-open:focus-visible {
  outline: 2px solid var(--civic);
  outline-offset: 2px;
}
.rep-card .btn-open b {
  font-size: 15.5px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}
.rep-card .btn-open small {
  font-size: 11.5px;
  opacity: 0.85;
  font-weight: 400;
}
.rep-card .open-picked {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 20px 18px 0;
  padding: 14px 16px;
  border: 1.5px solid var(--rc-keep);
  background: var(--rc-keep-soft);
  border-radius: 12px;
  font-size: 14px;
  color: var(--ink);
}
.rep-card .open-picked .ck {
  width: 17px;
  height: 17px;
  border-radius: 5px;
  border: 2px solid var(--rc-keep);
  color: var(--rc-keep);
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 700;
  flex: 0 0 auto;
}
.rep-card .open-picked b {
  font-family: var(--serif);
  font-weight: 600;
}
.rep-card .open-picked .chg {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--civic);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  white-space: nowrap;
  background: none;
  border: none;
  padding: 6px 2px;
  min-height: 44px;
}
.rep-card .open-picked .chg:focus-visible {
  outline: 2px solid var(--civic);
  outline-offset: 2px;
}

/* Grey the whole rep card + its seat strip for a seat not on the 2026 ballot. */
.rep-card.not-up-2026 {
  background: var(--tag-bg);
}
.rep-card.not-up-2026 .seat-strip {
  background: var(--tag-bg);
}

/* RepCard's verdict block is replaced by this info band for a seat that
   isn't on the 2026 ballot — same slot/padding as .cv2-actions so it drops
   in without a layout shift. */
.cv2-notup-band {
  padding: 14px 20px 18px;
  background: var(--paper);
}
.cv2-notup-eyebrow {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 6px;
}
.cv2-notup-text {
  font-size: 13px;
  color: var(--ink-2);
  margin: 0;
}
/* ---- attendance band [Δ] ---- */
.att-band {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 12px 18px 0;
  padding: 10px 13px;
  border-radius: 9px;
  background: var(--paper);
  border: 1px solid var(--rule-2);
  font-size: 13px;
}
.att-band .txt {
  color: var(--ink-2);
}
.att-band .txt b {
  color: var(--ink);
}
.att-band.na .txt {
  font-style: italic;
  color: var(--ink-3);
  font-size: 12.5px;
}
.att-chip {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 999px;
  white-space: nowrap;
}
.att-chip.good {
  background: oklch(0.9 0.025 170);
  color: var(--civic-2);
}
.att-chip.mid {
  background: oklch(0.93 0.045 80);
  color: oklch(0.5 0.09 70);
}
.att-chip.bad {
  background: oklch(0.93 0.04 28);
  color: var(--vote-red);
}
.att-src {
  font-family: var(--mono);
  font-size: 11.5px;
}

/* ---- committees [Part 3] — own wrapper class (not .att-band): the
   redesign-core e2e suite locates the attendance box with a bare
   `.att-band` selector expecting exactly one match per card, so the
   committees box (same paper/border/na chrome, deliberately) must not
   share that class. ---- */
.cmt-outer {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 12px 18px 0;
  padding: 10px 13px;
  border-radius: 9px;
  background: var(--paper);
  border: 1px solid var(--rule-2);
  font-size: 13px;
}
.cmt-outer .txt {
  color: var(--ink-2);
}
.cmt-outer.na .txt {
  font-style: italic;
  color: var(--ink-3);
  font-size: 12.5px;
}
.cmt-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 6px;
  width: 100%;
}
.cmt-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.cmt-name {
  color: var(--ink-2);
  font-size: 13px;
}
.cmt-title-chip {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 999px;
  background: oklch(0.9 0.025 170);
  color: var(--civic-2);
  white-space: nowrap;
}

/* ---- collaborators (cosponsorship network) ---- */
.collab-band {
  align-items: stretch;
  flex-direction: column;
}
.collab-groups {
  display: grid;
  gap: 12px;
  width: 100%;
}
.collab-group-label {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 5px;
}
.collab-party {
  color: var(--ink-3);
  font-size: 12px;
}
.collab-count-chip {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--paper-2);
  color: var(--ink-2);
  white-space: nowrap;
}
.collab-cite {
  margin: 4px 0 0;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--ink-3);
}

/* ---- researched positions (executive) ---- */
.rp-row .cv2-iss-head {
  cursor: default;
}
.rp-row .meta {
  display: grid;
  gap: 4px;
  margin-top: 6px;
}
.rp-src-note {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
  letter-spacing: 0.04em;
}
.cv2-iss-head .cv2-ws-col {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  flex-shrink: 0;
}

/* ---- eligibility note [Δ] (evolved PartyGate) ---- */
.elig {
  margin: 14px 18px;
  border-radius: 10px;
  padding: 12px 14px;
  border: 1px solid var(--rule);
  background: var(--paper);
}
.elig.warn {
  background: oklch(0.93 0.045 80 / 0.5);
  border-color: oklch(0.84 0.07 80);
}
.elig-when {
  display: flex;
  align-items: baseline;
  gap: 9px;
  flex-wrap: wrap;
}
.elig-when .lab {
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
}
.elig-when .date {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-2);
  white-space: nowrap;
}
.elig-rule {
  font-size: 13px;
  color: var(--ink-2);
  margin-top: 4px;
  line-height: 1.5;
}
.elig-rule b {
  color: var(--ink);
}
.elig-todo {
  font-size: 12.5px;
  margin-top: 7px;
}
.elig-todo a {
  color: var(--civic);
  font-weight: 600;
  cursor: pointer;
}

/* ---- verdict chips (scorecard + print) ---- */
.verdict-chip {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  padding: 2px 7px;
  border-radius: 999px;
  vertical-align: 1px;
}
/* Keep = green check, Replace = red swap-arrow. Distinct icon + color + label
   so the voter can tell at a glance (the glyph rides in the JSX label). */
.verdict-chip.keep {
  background: oklch(0.9 0.025 170);
  color: var(--civic-2);
  border: 1px solid var(--civic);
}
.verdict-chip.replace {
  background: oklch(0.93 0.04 28);
  color: var(--vote-red);
  border: 1px solid var(--vote-red);
}
/* Print sheet: tinted chip so keep/replace read as distinct even in grayscale;
   the verdict-row class also tints the checkbox glyph (see prototype.css). */
.verdict-print {
  font-family: var(--mono);
  font-weight: 700;
  letter-spacing: 0.05em;
  padding: 1px 7px;
  border-radius: 999px;
  border: 1.2px solid currentColor;
}
.verdict-print.keep {
  color: var(--civic-2);
  background: oklch(0.95 0.02 170);
}
.verdict-print.replace {
  color: var(--vote-red);
  background: oklch(0.96 0.025 28);
}

.delegation .standing-cta h4 {
  font-size: 22px;
}

/* the successor chosen in the head-to-head duel, shown next to a "replace"
   verdict on the scorecard + print sheet */
.pick-successor {
  font-family: var(--serif);
  font-weight: 600;
  color: var(--ink);
}

/* ============================================================
   SCORECARD PRINT — Bold Flag / Keystone parity (04-scorecard)
   ScorecardPrintView.tsx keeps its own print-sheet/ballot-list/
   verdict-row vocabulary (see parity-gate.ts STRUCTURAL_WAIVERS —
   HANDOFF-EXACT-MATCH.md §4 only asks for behavioral/structural
   parity, not a literal class port). This block is palette + the
   missing grayscale-safe score callout, scoped to .print-wrap so
   no other surface (workspace scorecard pane, .verdict-chip) is
   touched. Tokens ported from design-handoff/keystone-canvas
   src/screens.css .screen[data-palette="white"] SCORECARD block.
   ============================================================ */
.print-wrap {
  --scp-brand: oklch(0.4 0.155 262);
  --scp-keep: oklch(0.44 0.115 159);
  --scp-keep-ink: oklch(0.32 0.1 159);
  --scp-keep-line: oklch(0.62 0.1 159);
  --scp-replace: oklch(0.53 0.205 27);
  --scp-replace-ink: oklch(0.47 0.18 27);
}
/* Frames 10+11 fix 2 (whiteboard line 589) — no whiteboard original exists
   for this note (unstyled there), so it matches the tone of the existing
   .vm-note below: small, muted meta text under the print header. */
.print-wrap .print-why-note {
  font-size: 12px;
  color: var(--ink-2);
  line-height: 1.45;
  margin: 4px 0 0;
}
/* .pflag — the flag-stripe accent canvas puts on the sheet card itself
   (screens-scorecard.jsx / screens-home.jsx .sheet .pflag), never ported to
   the print route. Same --scp-brand/--scp-replace tokens as the rest of
   this block, so it's the identical blue/red pair used for keep/replace. */
.print-wrap .print-sheet {
  position: relative;
}
.print-wrap .pflag {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 6px;
  display: flex;
}
.print-wrap .pflag span {
  flex: 1;
}
.print-wrap .pflag span:nth-child(1) {
  background: var(--scp-brand);
}
.print-wrap .pflag span:nth-child(2) {
  background: var(--scp-replace);
}
/* Umbrella "My decisions" heading (canvas .sheet-section-lab) above the
   ballot groups — names the sheet's top-level content hierarchy with a
   real seats-up-for-election count before the per-race groups start.
   .ballot-list already carries the 24px top margin, so this sits flush
   under it rather than doubling the gap. */
.print-wrap .sheet-section-lab {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--scp-brand);
  font-weight: 700;
  margin: 0 0 14px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.print-wrap .sheet-section-lab::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}
.print-wrap .ballot-group .gtitle {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--scp-brand);
  border-bottom: 0;
  padding-bottom: 0;
}
.print-wrap .ballot-group .gtitle::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}
.print-wrap .br {
  display: flex;
  align-items: flex-start;
}
.print-wrap .br-main {
  flex: 1;
  min-width: 0;
}
/* Candidate name size (canvas screens.css .dec-name: font-size 19px,
   line-height 1.3). Two other rules compete for .pick-name's font-size
   here: prototype.css's shared `.br .pick-name` (21px, the legacy
   workspace ballot pane's size — left alone, not print-specific) and
   src/styles/print.css's `.print-sheet .ballot-list .pick-name` (18pt =
   24px — an older "Phase 7" print stylesheet, still imported globally in
   layout.tsx, whose selectors happen to reuse ScorecardPrintView's own
   print-sheet/ballot-list/pick-name wrapper class names even though it
   predates this component and doesn't match its other markup). That 24px
   rule is the actual worst offender behind "the text is way too big" — a
   3-class selector, so it silently won over both the 21px base AND an
   equal-specificity 2-class override here. This selector's 4 classes are
   the deliberate fix: unambiguously higher specificity than both, so it
   wins regardless of stylesheet load order. */
.print-wrap .print-sheet .ballot-list .pick-name {
  font-size: 19px;
  line-height: 1.3;
}
/* Race label above the candidate name (canvas .dec-office: mono 9.5px,
   letter-spacing 0.08em) — prototype.css's shared `.br .race-name` (used
   by the legacy workspace ballot pane too) is 10.5px/0.12em. */
.print-wrap .br .race-name {
  font-size: 11.5px;
  letter-spacing: 0.08em;
}
/* "My Scorecard" masthead (canvas .sheet-mast h1: serif 34px) —
   src/styles/print.css's `.print-sheet .ph-head .l` (3-class selector) is
   22pt (~29px); 4 classes here to unambiguously outrank it, same pattern
   as the .pick-name fix above. */
.print-wrap .print-sheet .ph-head .l {
  font-size: 34px;
}
.print-wrap .br .bx {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  border-width: 2px;
  /* Centering [Δ]: the base .bx::after glyphs (prototype.css) are
     positioned with left/top magic numbers sized for the 18px workspace
     checkbox. The print sheet blows .bx up to 30px without rescaling those
     offsets, so the keep check and replace swap-arrow both sit
     top/left-of-center. Flex centers whatever the pseudo-element's own box
     turns out to be, independent of that size bump. */
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Checkbox glyph truly centered (Frame 10+11 fix 1) — inline-SVG check
   instead of the pseudo-element glyphs above, verbatim from the whiteboard
   (`.sheet-mock .bx.bx-svg`, scoped here to `.print-wrap` like every other
   rule in this block). The open-seat `→` box (rendered as literal JSX text,
   see the .br.verdict-row.open-seat comment below) is unaffected. */
.print-wrap .bx.bx-svg {
  display: flex;
  align-items: center;
  justify-content: center;
}
.print-wrap .bx.bx-svg::before,
.print-wrap .bx.bx-svg::after {
  content: none;
}
.print-wrap .br.verdict-row.keep .bx {
  border-color: var(--scp-keep-ink);
  background: var(--scp-keep);
}
.print-wrap .br.verdict-row.keep .bx::after {
  position: static;
  width: 16px;
  height: 8px;
  border-left-color: #fff;
  border-bottom-color: #fff;
}
.print-wrap .br.verdict-row.replace .bx {
  border-color: var(--scp-replace);
  background: #fff;
  /* canvas .dec-badge.replace: border 2.5px (vs .dec-badge.keep's plain
     2px, from the shared base .dec-badge rule) — the outline-vs-filled
     grayscale-safety distinction gets a slightly heavier stroke too. */
  border-width: 2.5px;
}
.print-wrap .br.verdict-row.replace .bx::after {
  position: static;
  color: var(--scp-replace);
  line-height: 1;
}
.print-wrap .verdict-print.keep {
  color: var(--scp-keep-ink);
  background: oklch(0.93 0.045 159);
  border-color: var(--scp-keep-line);
}
.print-wrap .verdict-print.replace {
  color: var(--scp-replace-ink);
  background: #fff;
  border-color: var(--scp-replace);
}
/* Verdict pill size (canvas screens.css .dec-verdict: font-size 10px,
   padding 3px 9px, letter-spacing 0.06em) — .verdict-print never carried
   its own font-size, so the two rows that also carry the `.party` class
   (keep/replace) picked up .party's 11px almost by accident, and the
   "Not up until 2028" tag — `.verdict-print notup` alone, no `.party` — had
   no font-size override at all and inherited .pick-name's 19px/21px serif,
   rendering as a giant pill. This selector's specificity matches
   `.br .pick-name .party` so it wins for every verdict-print use. */
.print-wrap .br .pick-name .verdict-print {
  font-size: 11.5px;
  padding: 3px 9px;
  letter-spacing: 0.06em;
}
/* the big match-% readout beside each decision (canvas .dec-score) — was
   missing entirely; the % previously only existed folded into .my-note's
   prose. Grayscale-safe: leading glyph + color, not color alone. */
.print-wrap .br-score {
  flex-shrink: 0;
  text-align: right;
  margin-left: 14px;
}
.print-wrap .br-score-pct {
  font-family: var(--serif);
  font-weight: 600;
  /* canvas .dec-score .ds-pct: font-size 30px (was 24px here). */
  font-size: 30px;
  line-height: 1;
}
.print-wrap .br-score.good .br-score-pct {
  color: var(--scp-keep);
}
.print-wrap .br-score.good .br-score-pct::before {
  content: "\2713  ";
  font-size: 0.55em;
  vertical-align: 0.2em;
}
.print-wrap .br-score.bad .br-score-pct {
  color: var(--scp-replace);
}
.print-wrap .br-score.bad .br-score-pct::before {
  content: "\26A0  ";
  font-size: 0.5em;
  vertical-align: 0.25em;
}
.print-wrap .br-score-lab {
  font-family: var(--mono);
  /* Was 8.5px — too small to read even in print; 10px matches this same
     sheet's other mono uppercase captions (.sheet-section-lab above). */
  font-size: 11.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 3px;
  white-space: nowrap;
}
/* "Not on your ballot this year" context row (canvas .dec.notup) — a seat
   excluded from the scored decisions above, shown de-emphasized with a dash
   in place of a checkbox/verdict icon and a neutral (not keep/replace) pill. */
/* No opacity on .br.notup (was 0.62): it uniformly diluted every child's
   contrast against the page — same failure mode as .dg-excluded above,
   worse (0.62 vs 0.85) since it also covered .race-name/.pick-name/.my-note
   real candidate/office text, not just a badge. De-emphasis is already
   carried by the dash glyph, the "Not on your ballot" group heading, and
   the .verdict-print.notup pill below. */
.print-wrap .br.notup .bx {
  border-color: var(--rule);
  display: grid;
  place-items: center;
  color: var(--ink-3);
  font-size: 12px;
}
.print-wrap .br.notup .bx::before {
  content: "\2014";
}
.print-wrap .verdict-print.notup {
  /* --ink-3 on --tag-bg is ~4.4:1, just under AA's 4.5:1 — same fix as
     .cv2-sub.blind .cv2-tag. */
  color: oklch(0.5 0.026 260);
  background: var(--tag-bg);
  border-color: var(--rule);
}
/* Open-seat print row (v3 §6b.4, frame 10) — a decided open-seat pick is
   neither a ✓ keep nor a ⇄ replace, so it gets its own → glyph (a literal
   character in the JSX, not a pseudo-element — ScorecardPrintView.tsx
   renders `<div className="bx">→</div>`) and a navy pill, never the
   green/red keep/replace treatment. The base `.br.checked .bx::after` rule
   (prototype.css) still matches this row (it carries `.checked` too) and
   would draw its check-shape UNDER the literal → character, so it's
   suppressed here. --scp-brand is this file's existing brand-blue token
   (declared above in the .print-wrap custom-property block) — same one
   the .pflag/.sheet-section-lab accents already use. */
.print-wrap .br.verdict-row.open-seat .bx::before,
.print-wrap .br.verdict-row.open-seat .bx::after {
  content: none;
}
.print-wrap .br.verdict-row.open-seat .bx {
  border-color: var(--scp-brand);
  background: oklch(0.93 0.045 262);
  color: var(--scp-brand);
  font-weight: 700;
}
.print-wrap .verdict-print.open-seat {
  color: var(--scp-brand);
  background: oklch(0.93 0.045 262);
  border-color: var(--scp-brand);
}
/* logistics info — Fix 3 (v3 §3c): stacked label/value rows (canvas's
   .vm-rows/.vm-row) replace the old 4-cell grid, which squeezed a
   7-item Texas ID list into one skinny cell. --rule-2/--ink-3/--mono/
   --serif already exist app-wide (prototype-c.css :root); --bf-brand from
   the canvas source doesn't exist in this repo, so link color reuses
   --scp-brand (this block's own brand-blue token) instead. */
.print-wrap .vm-rows {
  border-top: 1.5px solid var(--ink);
  margin-top: 6px;
}
.print-wrap .vm-row {
  display: grid;
  grid-template-columns: 150px 1fr;
  gap: 4px 18px;
  padding: 13px 0;
  border-bottom: 1px solid var(--rule-2);
  align-items: start;
}
.print-wrap .vm-row .k {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding-top: 3px;
}
.print-wrap .vm-row .v {
  font-family: var(--serif);
  font-size: 13.5px;
  color: var(--ink);
  line-height: 1.45;
  min-width: 0;
}
.print-wrap .vm-row .v b {
  font-weight: 600;
}
.print-wrap .vm-note {
  font-size: 12px;
  color: var(--ink-2);
  line-height: 1.45;
  margin-top: 5px;
}
.print-wrap .vm-note a,
.print-wrap .vm-row .v a {
  color: var(--scp-brand);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}
/* Bring-any-one ID list — 2 columns so a long list (e.g. Texas's 7 accepted
   IDs) wraps wide instead of stretching one narrow cell tall. */
.print-wrap .print-id-cols {
  margin: 0;
  padding: 0;
  list-style: none;
  columns: 2;
  column-gap: 26px;
}
.print-wrap .print-id-cols li {
  font-family: var(--serif);
  font-size: 12.5px;
  line-height: 1.4;
  padding: 2px 0 2px 12px;
  position: relative;
  break-inside: avoid;
}
.print-wrap .print-id-cols li::before {
  content: "·";
  position: absolute;
  left: 0;
  color: var(--ink-3);
}
/* "Judged against your issues" — canvas screens-scorecard.jsx's live
   .sheet-issues > .si-row > (.pill + .si-juris + .si-quote) markup
   (2026-07-11 Design edit; supersedes the Round-3 .sheet-issue/.lvl/
   .quote-line vocabulary this repo built from a prose description before
   the live canvas source was available — renamed to match exactly). Pill
   text is "N · {short label}"; the jurisdiction tag sits beside it, not
   nested inside; the quote wraps to its own line (flex-basis: 100%) and
   is OMITTED entirely when the issue carries no quote — no fallback text,
   per honest-data (a printed sheet can't expand/collapse, so this is the
   full progressive-disclosure story: pill reads first, the voter's own
   words follow when there are any). */
.print-wrap .sheet-issues {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin-top: 8px;
}
.print-wrap .sheet-issues .si-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
}
.print-wrap .sheet-issues .pill {
  display: inline-block;
  background: var(--tag-bg);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 3px 11px;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-2);
}
.print-wrap .sheet-issues .si-juris {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  align-self: center;
}
.print-wrap .sheet-issues .si-quote {
  flex-basis: 100%;
  font-family: var(--serif);
  font-style: italic;
  font-size: 12px;
  color: var(--ink-3);
  margin-left: 2px;
}

/* ---- rail done-check centering (shipped tick is pinned low-left) ---- */
.ws-rail .race-list li.done .ind::after {
  left: 50%;
  top: 46%;
  width: 5.5px;
  height: 2.5px;
  transform: translate(-50%, -50%) rotate(-45deg);
}

/* ---- per-card source transparency footer ---- */
.card-sources {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  align-items: baseline;
  padding: 11px 20px 16px;
  border-top: 1px solid var(--rule-2);
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
  letter-spacing: 0.02em;
}
.card-sources .lab {
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 600;
}
.card-sources a {
  color: var(--ink-2);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: var(--rule);
}
.card-sources a:hover {
  color: var(--civic);
}
.card-sources .sep {
  color: var(--rule);
}
.elig-src {
  font-family: var(--mono);
  font-size: 11.5px;
  margin-top: 8px;
  display: inline-block;
}

/* ---- single-panel results layout ----
   The right scorecard rail is gone entirely (product decision: "one focus
   per page" — the seat page is just the RepCard + all-done panel). With no
   second pane, .ws-wrap collapses to a single centered column instead of
   the shipped grid, at every breakpoint (unlike the old rail-era override,
   which only touched ≥1024px because the rail itself handled smaller
   widths). .rep-center keeps the ~720px measure the money-redesign card
   was designed to, rather than stretching into the freed rail space. */
.delegation .ws-wrap {
  display: flex;
  justify-content: center;
}
.delegation .ws-chat.rep-center {
  width: 100%;
  max-width: 720px;
}

/* ---- tier intro (center column, above card) ----
   .ws-chat is a flex column with overflow:hidden (built for the chat
   thread). The redesign center is a document, not a chat — let it flow
   and let the page scroll.
   Scoped to desktop only here; the mobile equivalent (.delegation
   .ws-chat.rep-center) lives in the max-width:767px block below.
   overflow-y:auto here was the wide-screen scroll bug (part 1): it made
   this pane its own height-capped internal scroll region instead of a
   normal flowing block. Dropped in favor of the shell-level fix below,
   which lets this pane size to its own content and scroll with the page. */
@media (min-width: 768px) {
  .ws-chat.rep-center {
    display: block;
    padding: 22px 28px 60px;
  }
  /* Wide-screen scroll bug (part 2, the actual root cause): prototype-c.css's
     "sticky-sidebar workspace" pattern (search .ws-shell above) clips the
     WHOLE shell to height:100vh/overflow:hidden and gives .ws-wrap/.ws-chat
     their own overflow:hidden too, on the assumption that .ws-chat .body
     (a nested sub-div) is the one designated scroll region. The redesign's
     DelegationWorkspace has no such .body wrapper — the card's content sits
     directly in .ws-chat.rep-center — so that assumption doesn't hold here,
     and the result was a page clipped to exactly one viewport tall with no
     scrollbar: content past the fold was simply invisible, not scrollable.
     Undo the clip for .delegation only (the legacy ballot workspace keeps
     its intentional fixed-viewport behavior); let the shell flow as a
     document instead. */
  .ws-shell.delegation {
    height: auto;
    overflow: visible;
  }
  .ws-shell.delegation .ws-wrap {
    flex: none;
    overflow: visible;
    align-items: start;
    min-height: 0;
  }
  .ws-shell.delegation .ws-chat {
    overflow: visible;
  }
}
/* center-pane head: back control is mobile-only (shipped class hides it
   on desktop); the label gives the overlay a title bar on phones */
.rep-center-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 0 10px;
}
.rep-center-head-lab {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
}
@media (min-width: 768px) {
  .ws-chat .rep-center-head,
  .rep-center-head {
    display: none;
  }
}
/* The seat page has no mobile-overlay toggle anymore (the Overview is the
   hub at every breakpoint; "back" is the ordinary back-to-overview link) —
   so the redesign center just needs to render as a normal scrolling
   document on phones too, overriding prototype.css's shipped
   .ws-chat{display:none} (built for the old tap-to-open overlay pattern).
   The header (with the seat label) is a normal child of this scrolling
   section, not a separate fixed bar the way the legacy .ws-chat .head/.body
   split has one — so it scrolls away with the card content within a screen
   or two and the label goes out of reach. Pin it; its background already
   matches the parent's, so it reads as one seamless bar rather than content
   peeking out from underneath. */
@media (max-width: 767px) {
  .delegation .ws-chat.rep-center {
    display: block;
    overflow-y: auto;
    background: var(--paper);
    padding: 14px 16px 80px;
  }
  .delegation .ws-chat.rep-center .rep-center-head {
    position: sticky;
    top: 0;
    background: var(--paper);
    z-index: 5;
  }
}
.tier-intro {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 0 2px 16px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--rule);
}
.ti-place {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  font-weight: 700;
  /* .ti-place has no other call site (confirmed by grep across src/) —
     it only ever renders inside DelegationWorkspace's .delegation scope,
     so the base rule can read --brand directly rather than needing a
     .delegation .ti-place override. */
  color: var(--brand);
  padding-top: 6px;
  white-space: nowrap;
}
.ti-copy h2 {
  font-family: var(--serif);
  font-size: 23px;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin: 0 0 4px;
}
/* the single seat-tier jurisdiction badge (canvas res-tier's .lvl —
   screens-results.jsx/screens-delegation.jsx) — the one tag DECISIONS.md
   keeps after dropping the noisier per-issue Fed/Both/State tags. */
.lvl-tag {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--brand-soft);
  color: var(--brand-2);
  margin-left: 8px;
  vertical-align: 2px;
}
.ti-copy p {
  font-size: 14px;
  color: var(--ink-2);
  margin: 0;
  max-width: 560px;
  line-height: 1.5;
}
.all-done {
  margin-top: 18px;
  padding: 18px 20px 20px;
  border-radius: 12px;
  background: oklch(0.95 0.018 170);
  border: 1px solid oklch(0.84 0.05 170);
  box-shadow: 0 1px 3px oklch(0.7 0.05 170 / 0.18);
  font-size: 14px;
  color: var(--ink-2);
}
.all-done-kick {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--civic-2);
  font-weight: 700;
  margin-bottom: 6px;
}
.all-done b {
  display: block;
  font-family: var(--serif);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.all-done-sub {
  font-size: 13px;
  color: var(--ink-2);
  margin: 5px 0 13px;
  line-height: 1.45;
  max-width: 460px;
}
.all-done-print {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  background: var(--ink);
  color: var(--paper);
  border: 1px solid var(--ink);
  border-radius: 9px;
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  padding: 13px 16px;
  min-height: 48px;
  cursor: pointer;
}
.all-done-print:hover {
  background: var(--civic);
  border-color: var(--civic);
}
.all-done-print .arrow {
  color: var(--paper);
}
.all-done-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 14px;
}
.all-done-actions .all-done-print {
  margin-top: 0;
  flex: 1;
  min-width: 240px;
}
.all-done-handoff {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 46px;
  padding: 0 20px;
  border-radius: 11px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 13.5px;
  border: 1.5px solid var(--rule, oklch(0.88 0.006 258));
  background: var(--paper, #fff);
  color: var(--bf-brand, oklch(0.4 0.155 262));
  cursor: pointer;
  white-space: nowrap;
}
.all-done-handoff:hover {
  border-color: var(--bf-brand, oklch(0.4 0.155 262));
  background: var(--bf-brand-soft, oklch(0.94 0.04 262));
}
.all-done-handoff:focus-visible {
  outline: 2px solid var(--bf-brand, oklch(0.4 0.155 262));
  outline-offset: 2px;
}
.all-done-handoff .ic {
  color: var(--ink-3, oklch(0.54 0.026 260));
  font-size: 12.5px;
}
@media (max-width: 560px) {
  .all-done-actions {
    flex-direction: column;
  }
  .all-done-actions .all-done-print {
    min-width: 0;
  }
}
.all-done-deadline {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--rule-2, oklch(0.93 0.005 258));
  font-size: 12.5px;
  color: var(--ink-2, oklch(0.37 0.032 260));
  line-height: 1.5;
}
.all-done-deadline b {
  display: inline;
  font-family: var(--sans);
  font-size: inherit;
  font-weight: 600;
  letter-spacing: 0;
  margin: 0;
}
.all-done-deadline a {
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
  color: var(--bf-brand, oklch(0.4 0.155 262));
}
.all-done-deadline .src {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3, oklch(0.54 0.026 260));
  margin-top: 5px;
}
.linklike {
  background: none;
  border: none;
  color: var(--civic);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  padding: 0 0 0 6px;
}
/* Bold Flag / Keystone: .linklike is a shared secondary-action control
   (DelegationWorkspace's "See where you stand", IntakeLocked's "Keep
   talking", IssueDeltaBanner's "dismiss", SeatChat/RepCard/HeadToHead's
   budget-options reveal). Its base rule above reads --civic, which .bf-app
   deliberately leaves as legacy green (see the .bf-app block's own
   comment) — so it already rendered correctly navy wherever it happened to
   sit inside a locally-remapped-navy scope (.rep-card, .cmp, .amend-modal)
   but stayed green everywhere else, an inconsistency confirmed by reading
   every .linklike call site. This harmonizes all of them to the Keystone
   navy brand color. */
.bf-app .linklike {
  color: var(--bf-brand);
}

/* ---- polis-invite panel (NEW, Frame 8+9 item 1) — replaces the buried
   .all-done-also + .linklike text link with the mounted <PolisEntry/>
   component, as the whiteboard's .polis-invite/.pi-* panel inside
   `.all-done`. NOTE: PolisEntry.tsx today renders its own established
   markup (.pe-invite/.pe-map/.pe-invite-body/.pe-cta/.go/.no/.meta,
   .pm-wrap/.pm/.pm-blob/.pm-dot/.pm-you) from the earlier Polis-viz build —
   this block stages the whiteboard's verbatim polis-invite/pi-* selectors
   for the mount described above; wiring PolisEntry's JSX to this markup (or
   translating it) is the pending TSX card, out of scope here. */
.all-done .polis-invite {
  margin-top: 16px;
  border: 1px solid var(--rule);
  border-radius: 12px;
  padding: 14px;
  display: flex;
  gap: 14px;
  align-items: stretch;
  background: var(--paper-2);
}
.all-done .pi-map {
  position: relative;
  flex: 0 0 132px;
  border-radius: 9px;
  background: #fff;
  border: 1px solid var(--rule-2);
  overflow: hidden;
  min-height: 112px;
}
.all-done .pi-map .blob {
  position: absolute;
  border-radius: 50%;
  opacity: 0.13;
}
.all-done .pi-map .blob.c0 {
  background: var(--bf-brand, oklch(0.4 0.155 262));
  left: 8%;
  top: 14%;
  width: 44%;
  height: 44%;
}
.all-done .pi-map .blob.c1 {
  background: var(--keep, oklch(0.44 0.115 159));
  left: 54%;
  top: 10%;
  width: 40%;
  height: 42%;
}
.all-done .pi-map .blob.c2 {
  background: oklch(0.55 0.12 76);
  left: 32%;
  top: 54%;
  width: 40%;
  height: 38%;
}
.all-done .pi-map .dot {
  position: absolute;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  opacity: 0.75;
}
.all-done .pi-map .dot.c0 {
  background: var(--bf-brand, oklch(0.4 0.155 262));
}
.all-done .pi-map .dot.c1 {
  background: var(--keep, oklch(0.44 0.115 159));
}
.all-done .pi-map .dot.c2 {
  background: oklch(0.55 0.12 76);
}
.all-done .pi-map .you {
  position: absolute;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--ink);
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px var(--ink);
  transform: translate(-50%, -50%);
}
.all-done .pi-map .you-lab {
  position: absolute;
  transform: translate(-50%, 7px);
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
}
.all-done .pi-body {
  flex: 1;
  min-width: 0;
}
.all-done .pi-kick {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.all-done .pi-h {
  font-family: var(--serif);
  font-size: 18px;
  font-weight: 600;
  display: block;
  margin-top: 3px;
}
.all-done .pi-body p {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-2);
  margin: 5px 0 10px;
}
.all-done .pi-cta {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
}
.all-done .pi-cta .go {
  background: var(--bf-brand, oklch(0.4 0.155 262));
  color: #fff;
  border: none;
  border-radius: 8px;
  padding: 9px 14px;
  font-weight: 600;
  font-size: 14.5px;
  cursor: pointer;
  font-family: inherit;
}
.all-done .pi-cta .no {
  background: none;
  border: none;
  color: var(--ink-3);
  font-size: 12.5px;
  text-decoration: underline;
  cursor: pointer;
  padding: 0;
  font-family: inherit;
}
.all-done .pi-cta .meta {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
}
/* Frame 8+9 item 4 — the whiteboard's .mv class convention becomes a real
   breakpoint: stack the map above the body under ~480px (this file's
   .all-done-actions stack is a separate, pre-existing 560px breakpoint —
   left as-is, out of this port's scope). */
@media (max-width: 480px) {
  .all-done .polis-invite {
    flex-direction: column;
  }
  .all-done .pi-map {
    flex-basis: auto;
    height: 92px;
  }
}

/* ---- .be-eyebrow (BudgetModal, EditIssuesModal, HandoffModal) — same
   leak as .linklike above: the shared kicker-label rule reads --civic with
   no remap covering these three modals, so it rendered legacy green
   instead of navy everywhere inside .bf-app. ---- */
.bf-app .be-eyebrow {
  color: var(--bf-brand);
}

/* ---- palette-audit sweep (card: Bold Flag teal leaks) — three more
   surfaces read --civic/--civic-2/--civic-soft with no local remap at
   all, unlike .rep-card/.delegation/.pe-screen/.cmp/.polisstand2/
   .standing2 (which redefine the tokens they need at their own root).
   Individually-scoped overrides here, NOT a blanket local remap on
   .coldopen/.amend-modal/.be-modal — IntakeLocked's .issue-locked-confirm
   (rendered inside .coldopen) derives its "worth keeping" green banner
   from --keep: var(--civic), so remapping --civic itself at a shared
   ancestor would silently turn that confirmation banner navy too. Scoping
   per-selector avoids that collision entirely. ---- */

/* IntakeView → IssueConversation (shared by IntakeLocked's continued
   convo and EditIssuesModal's re-run) — the "send" CTA and the small
   context-line dot both read --civic. */
.bf-app .co-input .send {
  background: var(--brand);
}
.bf-app .co-context::before {
  background: var(--brand);
}

/* IssueConversation's "your priorities" card (IssueReviewCard) — border
   accent, rank numerals, inline-rename input, quote rail, and the
   "Lock in priorities" CTA. */
.bf-app .themes-card {
  border-color: var(--brand-soft);
  border-top-color: var(--brand);
}
.bf-app .theme-row .rank {
  color: var(--brand);
}
.bf-app .theme-row .nm input.name-edit {
  border-color: var(--brand);
}
.bf-app .theme-row .quote {
  border-left-color: var(--brand-soft);
}
.bf-app .themes-card .th-foot .lock {
  background: var(--brand);
}
.bf-app .themes-card .th-foot .lock:hover:not(:disabled) {
  background: var(--brand-2);
}

/* EditIssuesModal's own "amend" chrome (its outer shell — the
   IssueConversation it hosts is already covered above). */
.bf-app .amend-eyebrow {
  color: var(--brand);
}
.bf-app .amend-rank {
  color: var(--brand);
}
.bf-app .amend-name:focus {
  border-color: var(--brand);
}
.bf-app .amend-add-btn {
  background: var(--brand);
}
.bf-app .amend-apply {
  background: var(--brand);
}

/* ByokCard (BudgetModal + HandoffModal's inline API-key form). */
.bf-app .be-byok-getkey {
  color: var(--brand);
}
.bf-app .be-byok-getkey:hover {
  color: var(--brand-2);
}
.bf-app .be-byok-input-wrap input {
  border-color: var(--brand);
}
.bf-app .be-byok-input-wrap input:focus {
  border-color: var(--brand-2);
}
.bf-app .be-byok-save {
  background: var(--brand);
}
.bf-app .be-byok-save:hover {
  background: var(--brand-2);
}
.bf-app .be-tipjar a {
  color: var(--brand);
}

/* ============================================================
   POLISSTAND — KEYSTONE blind agree/disagree/pass step (card fb77d0bb)
   Literal port of design-handoff/keystone-canvas/src/screens-polis.jsx's
   PolisStand artboard (polis.css `.ps-*` vocabulary) — class names, copy,
   and layout ported as-is, NOT re-expressed like PolisClose's `.pr-*`
   below, because this screen carries no party data to begin with (just
   agree/disagree/pass reactions) — there's no party-free conflict forcing
   a rewrite. Two intentional layout deltas from the canvas: (1) the canvas
   uses a fixed-viewport single-"screen" flex shell (.ps { height:100% });
   this app renders every stage as a normal scrolling document like every
   other stage, so `.ps-foot` is a normal in-flow footer bar, not pinned;
   (2) canvas's shared `.kick`/`.star` kicker classes live in its global
   screens.css, which this app doesn't import — scoped copies below.
   ============================================================ */
.polisstand2 {
  /* Same local Bold Flag token redefinition as .standing2 below, and for
     the same reason (redesign2.css is served verbatim from public/, so
     these survive the minifier's unused-custom-property pruning). */
  --paper: oklch(1 0 0);
  --paper-2: oklch(0.985 0.003 258);
  --ink: oklch(0.2 0.035 260);
  --ink-2: oklch(0.37 0.032 260);
  --ink-3: oklch(0.54 0.026 260);
  --rule: oklch(0.88 0.006 260);
  --rule-2: oklch(0.93 0.005 260);
  --brand: oklch(0.4 0.155 262);
  --brand-2: oklch(0.31 0.145 262);
  --brand-soft: oklch(0.94 0.04 262);
  --keep: oklch(0.44 0.115 159); /* agreement green */
  --replace: oklch(0.53 0.205 27); /* flag red — also the disagree accent */
  background: var(--paper);
  min-height: 100vh;
}
.ps-wrap {
  max-width: 720px;
  margin: 0 auto;
  padding: 30px 40px 40px;
}
.polisstand2 .kick {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--brand);
  white-space: nowrap;
}
@media (max-width: 480px) {
  /* The kicker copy ("Your scorecard's ready · this part's optional") is
     wider than a narrow phone's content column; nowrap let it bleed past
     the viewport (ink overflow, invisible to the span's own layout box)
     instead of wrapping onto a second line. .ps-k is already display:block
     with its own margin-bottom, so a wrap here is a plain 2-line kicker,
     not a layout break. */
  .polisstand2 .kick {
    white-space: normal;
  }
}
.polisstand2 .kick .star {
  color: var(--replace);
  margin-right: 4px;
}
.ps-k {
  display: block;
  margin-bottom: 14px;
}
.ps-h1 {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 38px;
  line-height: 1.06;
  letter-spacing: -0.022em;
  margin: 0 0 12px;
  color: var(--ink);
  text-wrap: balance;
}
.ps-h1 em {
  font-style: italic;
  color: var(--brand);
}
.ps-lede {
  font-family: var(--serif);
  font-size: 17.5px;
  line-height: 1.5;
  color: var(--ink-2);
  margin: 0 0 24px;
  max-width: 600px;
}
.ps-cards {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.ps-stmt {
  border: 1px solid var(--rule);
  border-radius: 14px;
  background: var(--paper-2);
  box-shadow: 0 1px 3px rgba(20, 20, 30, 0.06);
  padding: 18px 20px;
}
.ps-stmt.voted {
  border-color: var(--brand);
  box-shadow: 0 0 0 2px var(--brand-soft);
}
.ps-stmt .q {
  font-family: var(--serif);
  font-size: 19px;
  font-weight: 500;
  line-height: 1.32;
  color: var(--ink);
  margin: 0 0 14px;
}
.ps-react {
  display: flex;
  gap: 9px;
}
.ps-btn {
  flex: 1;
  min-height: 46px;
  border-radius: 10px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  border: 1.5px solid var(--rule);
  background: var(--paper);
  color: var(--ink-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.ps-btn:disabled {
  cursor: default;
}
.ps-btn.agree:hover:not(:disabled) {
  border-color: var(--keep);
  color: var(--keep);
}
.ps-btn.disagree:hover:not(:disabled) {
  border-color: var(--replace);
  color: var(--replace);
}
.ps-btn.pass {
  flex: 0 0 auto;
  padding: 0 16px;
  color: var(--ink-3);
}
.ps-btn.chosen {
  background: var(--keep);
  border-color: var(--keep);
  color: var(--paper-2);
}
.ps-btn.chosen-no {
  background: var(--paper);
  border-color: var(--replace);
  color: var(--replace);
}
/* Pass has no canvas-specified "chosen" treatment (the artboard never shows
   a passed statement) — styled neutral/ink rather than keep-green or
   replace-red so it doesn't read as a third directional verdict. */
.ps-btn.chosen-pass {
  background: var(--ink-3);
  border-color: var(--ink-3);
  color: var(--paper-2);
}
.ps-recorded {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--rule-2);
  font-size: 12.5px;
  color: var(--ink-3);
  line-height: 1.5;
}
.ps-recorded .rk {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--keep);
  margin-right: 7px;
}
.ps-foot {
  border-top: 1px solid var(--rule-2);
  background: var(--paper-2);
  padding: 16px 30px;
}
.ps-foot-inner {
  max-width: 720px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
/* Primary CTA — same --brand/--paper-2 convention as .pr-share (PolisClose),
   the sibling primary button on this same white Bold Flag surface. */
.ps-foot .btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: var(--brand);
  color: var(--paper-2);
  border: none;
  border-radius: 10px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 14px;
  padding: 13px 20px;
  min-height: 50px;
  cursor: pointer;
}
.ps-foot .btn-primary:hover {
  background: var(--brand-2);
}
.ps-foot .later {
  margin-left: auto;
  font-size: 13.5px;
  color: var(--ink-3);
  background: none;
  border: none;
  cursor: pointer;
}
.ps-foot .prog {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
}

/* ============================================================
   STANDING (polis) stage — KEYSTONE "Where you stand" report
   Ported from design-handoff/design_handoff_voter_choice_redesign/
   polis.css (the `.pr-*`, `.pm-*`, `.conv-*` vocabulary), migrated
   onto the Bold Flag palette and made PARTY-FREE (DECISION #116):
   one population overlap cloud, single-track agreement bars, an
   honest agree-vs-disagree split — no D/R/I dots, chips, or clusters.

   The whole surface flips to the Bold Flag WHITE ground here (scoped
   to .standing2 so the rest of the app keeps its warm `--civic`
   base). The named accent tokens (--brand/--keep/--replace…) are
   defined globally in globals.css.
   ============================================================ */
.standing2 {
  /* White ballot ground + Bold Flag (Palette B) accents, ported from the
     Keystone design-handoff and scoped to this surface so the rest of the app
     keeps its warm `--civic` base. Defined HERE (not globals.css) on purpose:
     redesign2.css is served verbatim from public/, so these survive the CSS
     minifier's unused-custom-property pruning that drops them from globals. */
  --paper: oklch(1 0 0);
  --paper-2: oklch(0.985 0.003 258);
  --ink: oklch(0.2 0.035 260);
  --ink-2: oklch(0.37 0.032 260);
  --ink-3: oklch(0.54 0.026 260);
  --rule: oklch(0.88 0.006 260);
  --rule-2: oklch(0.93 0.005 260);
  --gold: oklch(0.72 0.125 76);
  --brand: oklch(0.4 0.155 262); /* bold navy-royal — primary action */
  --brand-2: oklch(0.31 0.145 262);
  --brand-soft: oklch(0.94 0.04 262);
  --keep: oklch(0.44 0.115 159); /* agreement green */
  --keep-soft: oklch(0.93 0.045 159);
  --replace: oklch(0.53 0.205 27); /* flag red */
  --replace-soft: oklch(0.94 0.05 27);
  /* Opinion-map cluster hues — NEUTRAL, party-free (DECISION #116). Three
     distinct Bold-Flag-family tones (indigo / teal / violet) assigned to
     Group A/B/C by SIZE, never to any party. Deliberately NOT the canvas's
     red-vs-blue pairing so the map can never be misread as D-vs-R. */
  --cluster-a: oklch(0.52 0.16 264); /* indigo */
  --cluster-b: oklch(0.58 0.11 195); /* teal */
  --cluster-c: oklch(0.55 0.16 320); /* violet */
  background: var(--paper);
}
/* ---- Polis entry (invite/preview) stage ----
   PORT of design-handoff/keystone-canvas/src/screens-polis.jsx +
   polis.css → PolisEntry/PolisMap. Classes are the canvas's, verbatim.
   Design tokens (--brand/--keep/--replace) the canvas authored for the
   Bold Flag white ground.
   --brand/--brand-2 point at the app-wide --bf-brand/--bf-brand-2 tokens
   (.bf-app above) rather than --civic: this screen only ever renders
   inside App2, always under body.bf-app, so --bf-brand is
   already in scope. --civic was the pre-foundation choice (PR #237
   predates .bf-app, built on the same "remap --civic locally" pattern
   candidates.css's HeadToHead uses) but .bf-app's own comment is explicit
   that --civic is LEFT UNTOUCHED app-wide — it doubles as the "keep"
   green elsewhere — so reading it here resolved to the global green civic
   default, not navy: brand accents (flagbar, buttons, invite-card rail)
   rendered civic-green instead of the canvas's navy. --keep/--replace are
   unaffected (already independent of --civic). */
.pe-screen {
  --brand: var(--bf-brand);
  --brand-2: var(--bf-brand-2);
  --keep: oklch(0.44 0.115 159);
  --replace: var(--vote-red);
  /* Cluster hues for the decorative map teaser — same party-free values as
     .standing2's real map (DECISION #116); duplicated because .standing2's
     tokens don't reach this surface. */
  --cluster-a: oklch(0.52 0.16 264);
  --cluster-b: oklch(0.58 0.11 195);
  --cluster-c: oklch(0.55 0.16 320);
}
.pe-screen .ps {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
}
.pe-screen .flagbar {
  height: 4px;
  display: flex;
  flex: 0 0 auto;
}
.pe-screen .flagbar i {
  flex: 1;
}
.pe-screen .flagbar i:nth-child(1) {
  background: var(--brand);
}
.pe-screen .flagbar i:nth-child(2) {
  background: var(--paper);
}
.pe-screen .flagbar i:nth-child(3) {
  background: var(--replace);
}
.pe-screen .ps-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 30px 30px 60px;
}
.pe-screen .ps-inner {
  width: 100%;
  max-width: 720px;
}
.pe-screen .btn-primary {
  background: var(--brand);
  color: var(--paper-2);
  border: none;
  border-radius: 10px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 15px;
  padding: 14px 22px;
  min-height: 50px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  box-shadow: var(--shadow-soft);
  white-space: nowrap;
}
.pe-screen .btn-primary:hover {
  background: var(--brand-2);
}

.pe-done {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 18px;
}
.pe-check {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--keep);
  color: var(--paper-2);
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: 18px;
  flex-shrink: 0;
}
.pe-done h1 {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 34px;
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0;
  color: var(--ink);
}
.pe-done p {
  font-size: 15px;
  color: var(--ink-2);
  margin: 6px 0 0;
}
.pe-actions {
  display: flex;
  gap: 11px;
  margin-bottom: 28px;
  flex-wrap: wrap;
}
.pe-pdf {
  min-height: 50px;
  padding: 0 20px;
  border-radius: 10px;
  border: 1.5px solid var(--rule);
  background: var(--paper-2);
  color: var(--ink-2);
  font-family: var(--sans);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
}

.pe-invite {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 26px;
  align-items: center;
  border: 1px solid var(--rule);
  border-radius: 16px;
  background: var(--paper-2);
  box-shadow: var(--shadow-soft);
  padding: 22px;
  position: relative;
  overflow: hidden;
}
.pe-invite::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 5px;
  background: linear-gradient(var(--brand), var(--replace));
}
@media (max-width: 700px) {
  .pe-invite {
    grid-template-columns: 1fr;
  }
}
.pe-map .pm {
  height: 168px;
  border-radius: 12px;
}
.pe-map .pm-glab {
  display: none;
}
.pe-invite-body {
  min-width: 0;
}
.pe-invite-body .k {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--brand);
}
.pe-invite-body h3 {
  font-family: var(--serif);
  font-size: 25px;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin: 7px 0 8px;
  color: var(--ink);
}
.pe-invite-body p {
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ink-2);
  margin: 0 0 16px;
  max-width: 540px;
}
.pe-cta {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.pe-cta .go {
  min-height: 48px;
  padding: 0 20px;
  border-radius: 10px;
  border: none;
  background: var(--brand);
  color: var(--paper-2);
  font-family: var(--sans);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  box-shadow: var(--shadow-soft);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.pe-cta .no {
  font-size: 13.5px;
  color: var(--ink-3);
  background: none;
  border: none;
  cursor: pointer;
}
.pe-cta .meta {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
}

/* ---- opinion-map preview (shared shape: PolisEntry's decorative teaser
   today; PolisReport's real map is a separate, not-yet-built surface) ---- */
.pm-wrap {
  width: 100%;
}
.pm {
  position: relative;
  width: 100%;
  height: 320px;
  border-radius: 14px;
  background: linear-gradient(135deg, var(--paper-2) 0%, var(--paper) 100%);
  border: 1px solid var(--rule);
  overflow: hidden;
}
.pm-wrap.compact .pm {
  height: 220px;
}
.pm-blob {
  position: absolute;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  opacity: 0.12;
  filter: blur(2px);
}
.pm-dot {
  position: absolute;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  opacity: 0.62;
  box-shadow: 0 1px 2px oklch(0.2 0.03 255 / 0.25);
}
.pm-you {
  position: absolute;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: var(--ink);
  border: 3px solid var(--paper-2);
  box-shadow:
    0 0 0 3px var(--ink),
    0 3px 8px oklch(0.2 0.03 255 / 0.4);
  z-index: 3;
}
.pm-you-lab {
  position: absolute;
  transform: translate(14px, -50%);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--ink);
  background: var(--paper-2);
  border: 1px solid var(--ink);
  padding: 2px 8px;
  border-radius: 999px;
  z-index: 3;
  white-space: nowrap;
}

/* ============================================================
   STANDING (polis) stage — KEYSTONE "Where you stand" report
   Ported from design-handoff/design_handoff_voter_choice_redesign/
   polis.css (the `.pr-*`, `.pm-*`, `.conv-*` vocabulary), migrated
   onto the Bold Flag palette and made PARTY-FREE (DECISION #116):
   one population overlap cloud, single-track agreement bars, an
   honest agree-vs-disagree split — no D/R/I dots, chips, or clusters.

   The whole surface flips to the Bold Flag WHITE ground here (scoped
   to .standing2 so the rest of the app keeps its warm `--civic`
   base). The named accent tokens (--brand/--keep/--replace…) are
   defined globally in globals.css.
   ============================================================ */
.standing2 {
  /* White ballot ground + Bold Flag (Palette B) accents, ported from the
     Keystone design-handoff and scoped to this surface so the rest of the app
     keeps its warm `--civic` base. Defined HERE (not globals.css) on purpose:
     redesign2.css is served verbatim from public/, so these survive the CSS
     minifier's unused-custom-property pruning that drops them from globals. */
  --paper: oklch(1 0 0);
  --paper-2: oklch(0.985 0.003 258);
  --ink: oklch(0.2 0.035 260);
  --ink-2: oklch(0.37 0.032 260);
  --ink-3: oklch(0.54 0.026 260);
  --rule: oklch(0.88 0.006 260);
  --rule-2: oklch(0.93 0.005 260);
  --gold: oklch(0.72 0.125 76);
  --brand: oklch(0.4 0.155 262); /* bold navy-royal — primary action */
  --brand-2: oklch(0.31 0.145 262);
  --brand-soft: oklch(0.94 0.04 262);
  --keep: oklch(0.44 0.115 159); /* agreement green */
  --keep-soft: oklch(0.93 0.045 159);
  --replace: oklch(0.53 0.205 27); /* flag red */
  --replace-soft: oklch(0.94 0.05 27);
  /* Opinion-map cluster hues — NEUTRAL, party-free (DECISION #116). Three
     distinct Bold-Flag-family tones (indigo / teal / violet) assigned to
     Group A/B/C by SIZE, never to any party. Deliberately NOT the canvas's
     red-vs-blue pairing so the map can never be misread as D-vs-R. */
  --cluster-a: oklch(0.52 0.16 264); /* indigo */
  --cluster-b: oklch(0.58 0.11 195); /* teal */
  --cluster-c: oklch(0.55 0.16 320); /* violet */
  background: var(--paper);
}
.standing2-wrap {
  max-width: 860px;
  margin: 0 auto;
  padding: 20px 40px 100px;
}
.back2 {
  background: none;
  border: none;
  color: var(--brand);
  font-weight: 600;
  font-size: 13.5px;
  cursor: pointer;
  padding: 6px 0;
  font-family: var(--sans);
}

/* the report is a plain editorial article, not a card */
.standing2 .polis.pr {
  border-top: none;
  margin-top: 4px;
}
.pr-wrap {
  width: 100%;
}

/* ---- masthead ---- */
.pr-mast {
  padding: 24px 0 26px;
  border-bottom: 2px solid var(--ink);
  margin-bottom: 30px;
}
.pr-kicker {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--replace);
  margin-bottom: 14px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.pr-kicker::before {
  content: "";
  width: 26px;
  height: 2px;
  background: var(--replace);
}
.pr-mast h1 {
  font-family: var(--serif);
  font-weight: 600;
  font-size: clamp(38px, 5.5vw, 52px);
  line-height: 1;
  letter-spacing: -0.03em;
  margin: 0;
  color: var(--ink);
  text-wrap: balance;
}
.pr-mast h1 em {
  font-style: italic;
  color: var(--brand);
}
.pr-lede {
  font-family: var(--serif);
  font-size: 19px;
  line-height: 1.5;
  color: var(--ink-2);
  margin: 16px 0 0;
  max-width: 660px;
}

/* ---- scope switcher (kept functional, restyled onto the white ground) ---- */
.polis-scope {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 4px;
  flex-wrap: wrap;
}
.polis-scope .scope-lab {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 700;
}
.polis-scope .scope-n {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
}
.polis-scope .seg {
  display: flex;
  gap: 4px;
  background: var(--paper-2);
  border: 1px solid var(--rule);
  padding: 3px;
  border-radius: 8px;
  width: 300px;
}
.polis-scope .seg button {
  flex: 1;
  border: none;
  background: none;
  border-radius: 6px;
  padding: 7px 8px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-3);
  cursor: pointer;
}
.polis-scope .seg button.on {
  background: var(--brand);
  color: var(--paper-2);
}

/* ---- section heads ---- */
.pr-mapsec {
  margin: 30px 0 8px;
}
.pr-maphead,
.pr-bridgehead {
  margin: 26px 0 14px;
}
.pr-maphead .k,
.pr-bridgehead .k {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--replace);
}
.pr-maphead h2,
.pr-bridgehead h2 {
  font-family: var(--serif);
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 6px 0 0;
  color: var(--ink);
}
.pr-bridgehead {
  margin-top: 34px;
  padding-top: 28px;
  border-top: 1px solid var(--rule-2);
}
.pr-threshold {
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.55;
  color: var(--ink-3);
  margin: 8px 0 0;
  max-width: 640px;
}
.pr-threshold b {
  color: var(--ink-2);
}

/* ---- opinion map (party-free .pm card) ---- */
.pm-wrap {
  width: 100%;
}
.pm {
  position: relative;
  width: 100%;
  aspect-ratio: 200 / 100;
  border: 1px solid var(--rule);
  border-radius: 16px;
  background:
    linear-gradient(var(--rule-2) 1px, transparent 1px) 0 0 / 100% 40px,
    linear-gradient(90deg, var(--rule-2) 1px, transparent 1px) 0 0 / 40px 100%,
    var(--paper-2);
  overflow: hidden;
}
.pm-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.pm-field {
  fill: var(--brand);
  opacity: 0.07;
}
.pm-dot {
  fill: var(--brand);
  opacity: 0.55;
}
.pm-rlab {
  font-family: var(--mono);
  font-size: 3.4px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  fill: var(--ink-3);
  opacity: 0.72;
}
.pm-you-mark {
  fill: var(--gold);
  stroke: var(--ink);
  stroke-width: 1.4;
}
.pm-you-lab {
  position: absolute;
  transform: translate(10px, -50%);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--ink);
  padding: 2px 8px;
  border-radius: 999px;
  z-index: 3;
  white-space: nowrap;
  pointer-events: none;
}

/* ---- real pol.is cluster map (.pm.cluster): PCA + k-means opinion groups ----
   Soft group fields + per-cluster dots, positioned in container percentages
   (left/top). Party-free: colours are the neutral --cluster-* tokens above,
   assigned to Group A/B/C by size — never a party. Scoped to `.pm.cluster` so
   the single-cloud SVG `.pm-dot`/`.pm-field` styling above is untouched. */
.pm.cluster .pm-blob {
  position: absolute;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  opacity: 0.14;
  filter: blur(3px);
  pointer-events: none;
}
.pm.cluster .pm-blob.c0 {
  background: var(--cluster-a);
}
.pm.cluster .pm-blob.c1 {
  background: var(--cluster-b);
}
.pm.cluster .pm-blob.c2 {
  background: var(--cluster-c);
}
.pm.cluster .pm-dot {
  position: absolute;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  opacity: 0.66;
  box-shadow: 0 1px 2px oklch(0.2 0.03 255 / 0.25);
}
.pm.cluster .pm-dot.c0 {
  background: var(--cluster-a);
}
.pm.cluster .pm-dot.c1 {
  background: var(--cluster-b);
}
.pm.cluster .pm-dot.c2 {
  background: var(--cluster-c);
}
.pm.cluster .pm-glab {
  position: absolute;
  transform: translate(-50%, -100%);
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: oklch(1 0 0 / 0.8);
  padding: 2px 7px;
  border-radius: 999px;
  white-space: nowrap;
  z-index: 2;
  pointer-events: none;
}
.pm.cluster .pm-you {
  position: absolute;
  width: 16px;
  height: 16px;
  border-radius: 3px;
  transform: translate(-50%, -50%);
  background: var(--gold);
  border: 2.5px solid var(--paper);
  box-shadow:
    0 0 0 2.5px var(--ink),
    0 3px 8px oklch(0.2 0.03 255 / 0.4);
  z-index: 3;
  pointer-events: none;
}

/* legend swatches for the cluster key */
.pm-key i.c0 {
  background: var(--cluster-a);
}
.pm-key i.c1 {
  background: var(--cluster-b);
}
.pm-key i.c2 {
  background: var(--cluster-c);
}

.pm-cap {
  margin-top: 14px;
}
.pm-key {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.pm-key span {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-2);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.pm-key i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  display: inline-block;
  background: var(--brand);
}
.pm-key .you i {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  background: var(--gold);
  outline: 1.5px solid var(--ink);
  outline-offset: -1px;
}
.pm-cap p {
  font-family: var(--serif);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink-2);
  margin: 0;
  max-width: 660px;
}
.pm-cap p b {
  color: var(--ink);
  font-weight: 600;
}
.pm-cap .pm-disc {
  font-family: var(--sans);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-3);
  margin-top: 10px;
}

/* ---- common-ground list ---- */
.pr-list {
  display: flex;
  flex-direction: column;
}
.pr-row {
  padding: 24px 0;
  border-bottom: 1px solid var(--rule-2);
  display: grid;
  grid-template-columns: 1fr 300px;
  gap: 36px;
  align-items: center;
}
.pr-q {
  font-family: var(--serif);
  font-size: 22px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--ink);
}
.pr-q .src {
  display: block;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 8px;
}
.pr-stat {
  text-align: left;
}
.pr-pct {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 44px;
  line-height: 1;
  color: var(--keep);
  letter-spacing: -0.02em;
}
.pr-pct .ag {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-left: 8px;
}
.pr-conv {
  margin-top: 14px;
}

/* ---- party-free agreement / split bars ---- */
.conv {
  position: relative;
  height: 26px;
  margin: 4px 0 0;
}
.conv-track {
  position: absolute;
  top: 11px;
  left: 0;
  right: 0;
  height: 4px;
  border-radius: 999px;
  background: var(--rule-2);
}
.conv-fill {
  position: absolute;
  top: 11px;
  left: 0;
  height: 4px;
  border-radius: 999px;
  background: var(--keep-soft);
}
.conv-fill.gap {
  background: var(--rule);
}
.conv-dot {
  position: absolute;
  top: 4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2.5px solid var(--paper);
  transform: translateX(-50%);
  box-shadow: 0 2px 6px -1px oklch(0.2 0.03 255 / 0.35);
}
.conv-dot.agree {
  background: var(--keep);
}
.conv-dot.disagree {
  background: var(--replace);
}

/* ---- per-opinion-group convergence bar + chips ----
   One dot per opinion group (Group A/B/C) on a shared track, coloured with the
   SAME neutral cluster tokens the opinion map uses (--cluster-a/b/c) so a Group
   A dot/chip here matches the Group A dots on the map above. Party-free
   (DECISION #116): these are opinion clusters by answer similarity, never
   D/R/I. Dots CONVERGE on bridges, SPREAD on divided statements. */
.conv.groups {
  margin-top: 10px;
}
.conv-fill.neutral {
  background: var(--rule);
}
.conv-dot.c0 {
  background: var(--cluster-a);
}
.conv-dot.c1 {
  background: var(--cluster-b);
}
.conv-dot.c2 {
  background: var(--cluster-c);
}
.pr-split {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}
.pr-split .chip {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  padding: 4px 9px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.pr-split .chip i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
}
.pr-split .chip.c0 {
  background: color-mix(in oklch, var(--cluster-a) 12%, var(--paper));
  color: color-mix(in oklch, var(--cluster-a) 78%, var(--ink));
}
.pr-split .chip.c0 i {
  background: var(--cluster-a);
}
.pr-split .chip.c1 {
  background: color-mix(in oklch, var(--cluster-b) 14%, var(--paper));
  color: color-mix(in oklch, var(--cluster-b) 82%, var(--ink));
}
.pr-split .chip.c1 i {
  background: var(--cluster-b);
}
.pr-split .chip.c2 {
  background: color-mix(in oklch, var(--cluster-c) 12%, var(--paper));
  color: color-mix(in oklch, var(--cluster-c) 78%, var(--ink));
}
.pr-split .chip.c2 i {
  background: var(--cluster-c);
}

/* ---- where it split ---- */
.pr-fault {
  margin-top: 34px;
  padding: 24px 26px;
  border: 1px solid var(--rule);
  border-radius: 16px;
  background: var(--paper-2);
}
.pr-fault > .k {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ink-3);
}
.pr-fault h3 {
  font-family: var(--serif);
  font-size: 23px;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin: 7px 0 9px;
  color: var(--ink);
}
.pr-fault > p {
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0;
  max-width: 660px;
}
.pr-fault .pr-row.split {
  border-bottom: none;
  margin-top: 8px;
  padding-bottom: 0;
}
.pr-fault .pr-row.split + .pr-row.split {
  border-top: 1px solid var(--rule-2);
  margin-top: 0;
  padding-top: 20px;
}
.pr-pct.split {
  color: var(--ink-3);
}
.pr-pct.split .ag {
  color: var(--ink-3);
}

/* ---- provenance footer ---- */
.pr-foot {
  padding: 30px 0 12px;
  margin-top: 8px;
  border-top: 1px solid var(--rule-2);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
}
.pr-foot .meta {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
  line-height: 1.6;
}
.pr-foot .meta b {
  color: var(--ink-2);
}
.pr-share {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: var(--brand);
  color: var(--paper-2);
  border: none;
  border-radius: 10px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 14px;
  padding: 13px 20px;
  min-height: 48px;
  cursor: pointer;
  box-shadow: var(--shadow-soft);
}
.pr-share:hover {
  background: var(--brand-2);
}
.pr-note {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
  margin-top: 14px;
}

@media (max-width: 720px) {
  .standing2-wrap {
    padding: 16px 22px 80px;
  }
  .pr-row {
    grid-template-columns: 1fr;
    gap: 12px;
  }
}

/* ====================================================
   RAISED VS. THE MEDIAN — the money-gap scale [Δ]
   Ported from claude-code-handoff/design-session/funding.css.
   Design tokens (--brand/--keep/--replace, [data-palette="white"]) are mapped
   onto the redesign's shipped warm-palette tokens so this rides on the existing
   prototype.css system (no new palette). Neutral by design: gold = "above the
   median", muted navy = "raised". Keep/replace red/green mean alignment, not
   money. ==================================================== */

/* local scale colors — muted navy "money", gold "above the typical" */
.mgap,
.median-chip {
  --mg-base: oklch(0.46 0.075 240); /* money raised, up to the median */
  /* Darkened from oklch(0.74 0.04 240): that value was only ~2.2:1 against
     .mgap-track's --paper-2 fill, under AA's 3:1 for a graphical object.
     Never renders next to --mg-base (mutually exclusive .is-below swap), so
     no boundary conflict from darkening it. */
  --mg-lean: oklch(0.62 0.04 240); /* below-median bar — reads as "less" */
  --mg-over: var(--gold); /* the excess above the median */
  --mg-overink: oklch(0.5 0.115 74); /* darker gold for readable text */
  --mg-line: var(--ink); /* the median reference line */
}

/* party pip — the design's bare .pip (prototype.css scopes it to .cand-card) */
.mgap .pip,
.median-chip .pip {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
}
.mgap .pip.dem,
.median-chip .pip.dem {
  background: oklch(0.45 0.16 262);
}
.mgap .pip.rep,
.median-chip .pip.rep {
  background: var(--vote-red);
}
.mgap .pip.ind,
.median-chip .pip.ind {
  background: var(--gold);
}

/* =========================================================
   THE SCALE (inside the funder disclosure)
   ========================================================= */
.mgap {
  padding: 4px 0 22px;
}

/* axis header carries the median flag + the $0 / max ticks */
.mgap-axis {
  position: relative;
  height: 48px;
  margin-left: 154px;
  margin-right: 90px;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 14px;
}
.mgap-zero,
.mgap-max {
  position: absolute;
  bottom: 6px;
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ink-3);
}
.mgap-zero {
  left: 0;
}
.mgap-max {
  right: 0;
}
.mgap-medflag {
  position: absolute;
  bottom: 0;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.1;
  white-space: nowrap;
}
.mgap-medflag::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  width: 1.5px;
  height: 9px;
  background: var(--mg-line);
  transform: translateX(-50%);
}
.mgap-medflag .mf-lab {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--ink-3);
}
.mgap-medflag .mf-amt {
  font-family: var(--serif);
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  margin-top: 1px;
}
.mgap-medflag .mf-sub {
  font-size: 11.5px;
  color: var(--ink-3);
  margin-top: 1px;
}

/* one candidate row: label · track · readout */
.mgap-plot {
  display: flex;
  flex-direction: column;
  gap: 13px;
}
.mgap-row {
  display: grid;
  grid-template-columns: 140px 1fr 84px;
  align-items: center;
  gap: 14px;
}
.mgap-lab {
  min-width: 0;
}
.mgap-nm {
  font-family: var(--serif);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 7px;
  line-height: 1.15;
}
.mgap-nm .you {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 999px;
  background: var(--civic-soft);
  color: var(--civic-2);
}
.mgap-tag {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
  margin-top: 3px;
  letter-spacing: 0.02em;
}

.mgap-track {
  position: relative;
  height: 26px;
  border-radius: 6px;
  background: var(--paper-2);
  border: 1px solid var(--rule-2);
  overflow: hidden;
}
.mgap-bar {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  background: var(--mg-base);
  border-radius: 0 5px 5px 0;
  z-index: 1;
}
.mgap-bar.is-below {
  background: var(--mg-lean);
}
.mgap-over {
  position: absolute;
  top: 0;
  bottom: 0;
  background: var(--mg-over);
  border-radius: 0 5px 5px 0;
  z-index: 2;
  /* Boundary divider (1.4.11): .mgap-over stacks directly against
     .mgap-bar (--mg-base) when over-median, and raw gold vs. that navy is
     only ~2.8:1. Best achievable near-black divider gets to ~3.0:1 — same
     palette-L-spacing gap as the funding-mix bar above, flagged for
     design rather than darkening the shared --gold fill token. */
  border-left: 1.5px solid oklch(0.08 0 0);
}
.mgap-rem {
  position: absolute;
  top: 50%;
  height: 0;
  border-top: 1.5px dotted var(--ink-3);
  z-index: 1;
  opacity: 0.7;
}
.mgap-medline {
  position: absolute;
  top: -1px;
  bottom: -1px;
  width: 1.5px;
  background: var(--mg-line);
  z-index: 3;
}

.mgap-read {
  text-align: right;
}
.mgap-read b {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 22px;
  line-height: 1;
  display: block;
}
.mgap-read span {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
  display: block;
  margin-top: 3px;
}
.mgap-read.is-above b {
  color: var(--mg-overink);
}
.mgap-read.is-at b {
  color: var(--ink-2);
}
.mgap-read.is-below b {
  color: var(--ink-3);
}

/* legend chips + source under the scale */
.mgap-key {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--rule-2);
}
.mgap-key span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 11.5px;
  color: var(--ink-3);
}
.mgap-key i {
  width: 16px;
  height: 10px;
  border-radius: 3px;
  flex-shrink: 0;
}
.mgap-key i.base {
  background: var(--mg-base);
}
.mgap-key i.over {
  background: var(--mg-over);
}
.mgap-key i.line {
  width: 2px;
  height: 14px;
  border-radius: 0;
  background: var(--mg-line);
}
.mgap-src {
  margin-top: 12px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-3);
  letter-spacing: 0.02em;
}

/* the inline chip (collapsed glance on a money line) */
.median-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 11px 4px 9px;
  border-radius: 999px;
  border: 1px solid var(--rule);
  background: var(--paper-2);
  font-size: 12px;
  color: var(--ink-2);
  white-space: nowrap;
}
.median-chip b {
  font-family: var(--mono);
  font-weight: 700;
  font-size: 12.5px;
}
.median-chip.above b {
  color: var(--mg-overink);
}
.median-chip.below b,
.median-chip.at b {
  color: var(--ink);
}
.median-chip.none,
.median-chip.dollar-only {
  color: var(--ink-3);
}
.median-chip.none {
  font-style: italic;
}
.median-chip.dollar-only b {
  color: var(--ink);
}
.mc-bar {
  position: relative;
  width: 42px;
  height: 8px;
  border-radius: 999px;
  background: var(--rule-2);
  overflow: hidden;
  flex-shrink: 0;
}
.mc-bar i {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  border-radius: 999px;
}
.median-chip.above .mc-bar i {
  background: var(--mg-over);
}
.median-chip.at .mc-bar i {
  background: var(--mg-base);
}
.median-chip.below .mc-bar i {
  background: var(--mg-lean);
}
.mc-tick {
  position: absolute;
  top: -1px;
  bottom: -1px;
  left: 33%;
  width: 1.5px;
  background: var(--mg-line);
}

/* stacked / compact form < ~560px (the responsive P0 in the spec §2a) */
@media (max-width: 560px) {
  .mgap-axis {
    margin-left: 0;
    margin-right: 0;
  }
  .mgap-row {
    grid-template-columns: 1fr;
    gap: 6px;
  }
  .mgap-read {
    text-align: left;
  }
  .mgap-read b {
    display: inline;
    font-size: 18px;
  }
  .mgap-read span {
    display: inline;
    margin-left: 8px;
  }
}

/* ---- intake pre-lock confirm banner (IntakeLocked, artboard iq-locked) ----
   Ported verbatim from design-handoff/keystone-canvas/src/intake.css's
   .iq-locked block. Its --keep/--keep-soft tokens aren't in the global
   palette yet (rollout pending), so — same precedent as candidates.css's
   .cmp and this file's .mgap — they're mapped onto the shipped warm-palette
   tokens, scoped to this screen only. */
.issue-locked-confirm {
  --keep: var(--civic);
  --keep-soft: var(--civic-soft);
}
.iq-locked {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 14px 16px;
  border-radius: 13px;
  background: var(--keep-soft);
  border: 1px solid var(--keep);
  /* Round-3.1 correction: this was 16px 0 0 — the live canvas source
     (2026-07-11 edits) confirms 2px 0 14px, a much smaller top gap off
     the issues card and 14px of breathing room before the footer below. */
  margin: 2px 0 14px;
}
.iq-locked .tick {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--keep);
  color: var(--paper-2);
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: 14px;
  flex-shrink: 0;
}
.iq-locked .lt {
  font-family: var(--serif);
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
}
.iq-locked .ls {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-2);
  margin-top: 1px;
}

/* ---- shared intake control accents — Bold Flag / Keystone chrome pass ----
   prototype.css's .co-input .send / .themes-card .th-foot .lock and
   .theme-row .rank all predate the .bf-app foundation and read --civic
   directly (green app-wide, per .bf-app's own comment above), so the
   intake composer's send/lock CTA and the issue-review card's numbered
   rank chips rendered civic-green instead of matching the canvas source.
   Verified against design-handoff/keystone-canvas/src/intake.css directly:
   .iq-send { background: var(--brand) } confirms the CTA is brand-navy;
   .iq-rank { color: var(--ink-3) } confirms the rank number is neutral
   grey, NOT brand — a genuine second, different bug (not just a
   --civic-vs-bf-brand swap). Scoped under .bf-app since prototype.css is shared
   with the legacy ballot app, which must keep its own civic-green intact. */
.bf-app .co-input .send {
  background: var(--bf-brand);
}
.bf-app .themes-card .th-foot .lock {
  background: var(--bf-brand);
}
.bf-app .themes-card .th-foot .lock:hover:not(:disabled) {
  background: var(--bf-brand-2);
}
.bf-app .theme-row .rank {
  color: var(--ink-3);
}

/* ---- intake context-bar step indicator (canvas: .iq-ctx .step) ----
   screens-intake.jsx's IqShell always renders a right-aligned "Step 1 of 3
   · ..." label next to the address/jurisdiction line; the repo's
   .co-context had no equivalent element at all. .co-context is already
   `display:flex` (prototype.css), so margin-left:auto right-aligns this
   new child the same way canvas does. Scoped under .bf-app for the same
   shared-stylesheet reason as the block above — IntakeView (App2-only) is
   the only caller that renders a .step child today. */
.bf-app .co-context .step {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--bf-brand);
}

/* ---- chat "YOU" bubble — Bold Flag / Keystone parity ----
   prototype.css's .msg.user .bubble uses `background: var(--ink); color:
   var(--paper)` (near-black on white) everywhere, civic and Keystone
   alike. Canvas's own intake.css renders the user bubble light-blue on
   dark-navy text instead: `.iq-msg.user .iq-bubble { background:
   var(--brand-soft); border: 1px solid oklch(0.84 0.05 262); color:
   var(--brand-2); }` and `.iq-msg.user .iq-who { color: var(--brand); }`.
   Scoped under .bf-app so the legacy ballot app's own near-black bubble
   (never part of the Keystone canvas) is untouched. */
.bf-app .msg.user .bubble {
  background: var(--bf-brand-soft);
  border: 1px solid oklch(0.84 0.05 262);
  color: var(--bf-brand-2);
}
.bf-app .msg.user .who {
  color: var(--bf-brand);
}

/* ---------- Orientation interstitial — Bold Flag / Keystone parity ----------
   (after lock-issues, before first rep). Structure + classes ported
   verbatim from design-handoff/keystone-canvas/src/screens-orientation.jsx's
   OrientationActivated + screens.css's .ori/.flagbar/.ori-card rules, per
   HANDOFF-EXACT-MATCH.md §1. The white/navy/red palette is locally scoped
   to .ori-body (--ori-* tokens) so it doesn't bleed into AppNav's shared
   civic styling — AppNav is a sibling, not a descendant, of .ori-body. */
.ori {
  display: flex;
  flex-direction: column;
}
.flagbar {
  height: 4px;
  display: flex;
  flex: 0 0 auto;
}
.flagbar i {
  flex: 1;
}
.flagbar i:nth-child(1) {
  background: oklch(0.4 0.155 262);
}
.flagbar i:nth-child(2) {
  background: oklch(1 0 0);
}
.flagbar i:nth-child(3) {
  background: oklch(0.53 0.205 27);
}
.ori-body {
  --ori-paper: oklch(1 0 0);
  --ori-paper-2: oklch(0.985 0.003 258);
  --ori-ink: oklch(0.2 0.035 260);
  --ori-ink-2: oklch(0.37 0.032 260);
  --ori-ink-3: oklch(0.54 0.026 260);
  --ori-brand: oklch(0.4 0.155 262);
  --ori-brand-2: oklch(0.31 0.145 262);
  --ori-replace: oklch(0.53 0.205 27);
  --ori-rule: oklch(0.88 0.006 260);
  --ori-rule-2: oklch(0.93 0.005 260);
  flex: 1;
  display: grid;
  place-items: center;
  padding: 40px 32px;
  min-height: calc(100vh - 90px);
  background: var(--ori-paper);
}
.ori-card {
  width: 100%;
  max-width: 640px;
  background: var(--ori-paper-2);
  border: 1px solid var(--ori-rule);
  border-radius: 16px;
  box-shadow:
    0 1px 0 var(--ori-rule),
    0 30px 60px -34px oklch(0.2 0.03 255 / 0.3);
  padding: 40px 44px 36px;
  position: relative;
  overflow: hidden;
}
.ori-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 5px;
  background: linear-gradient(
    90deg,
    var(--ori-brand) 0 38%,
    transparent 38% 62%,
    var(--ori-replace) 62% 100%
  );
}
.ori-card.activated::before {
  height: 6px;
}
.ori-ey {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 18px;
}
.ori-ey .kick {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ori-brand);
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.ori-ey .star {
  color: var(--ori-replace);
}
.ori-card h1 {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 40px;
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin: 0 0 14px;
  color: var(--ori-ink);
  text-wrap: balance;
}
.ori-card h1 em {
  font-style: italic;
  color: var(--ori-brand);
}
.ori-lede {
  font-family: var(--serif);
  font-size: 18.5px;
  line-height: 1.5;
  color: var(--ori-ink-2);
  margin: 0 0 28px;
  max-width: 520px;
}
.ori-steps {
  display: grid;
  gap: 2px;
  margin: 0 0 30px;
  border: 1px solid var(--ori-rule-2);
  border-radius: 12px;
  overflow: hidden;
}
.ori-step {
  display: grid;
  grid-template-columns: 34px 1fr;
  gap: 14px;
  padding: 15px 18px;
  background: var(--ori-paper);
  align-items: start;
}
.ori-step + .ori-step {
  border-top: 1px solid var(--ori-rule-2);
}
.ori-step .n {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  color: var(--ori-paper-2);
  background: var(--ori-brand);
  width: 26px;
  height: 26px;
  border-radius: 7px;
  display: grid;
  place-items: center;
}
.ori-step:last-child .n {
  background: var(--ori-replace);
}
.ori-step .st-t {
  font-weight: 600;
  font-size: 14.5px;
  color: var(--ori-ink);
}
.ori-step .st-d {
  font-size: 13px;
  color: var(--ori-ink-3);
  line-height: 1.45;
  margin-top: 2px;
}
.ori-cta {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.ori-cta .btn-primary {
  background: var(--ori-brand);
  color: var(--ori-paper-2);
  border: none;
  border-radius: 10px;
  font-family: var(--sans);
  font-weight: 700;
  font-size: 15px;
  padding: 14px 22px;
  min-height: 50px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  box-shadow:
    0 1px 0 var(--ori-rule-2),
    0 12px 30px -22px oklch(0.2 0.03 255 / 0.18);
  white-space: nowrap;
}
.ori-cta .btn-primary:hover {
  background: var(--ori-brand-2);
}
.ori-meta {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ori-ink-3);
  letter-spacing: 0.02em;
}

/* ====================================================
   RepCard — Bold Flag / Keystone pass [Δ] (05a-candidates-parity, round 2)
   ----------------------------------------------------
   Ports the canvas's "one card, every seat" system (design-handoff/
   keystone-canvas/src/candidates.css .cd-card / .cd-align / .cd-money) onto
   RepCard's existing cv2-* markup. Locally-scoped white/navy/red palette,
   same pattern as the .sp-wrap.sp-tipjar / .sp-wrap.sp-about / .sp-wrap.
   sp-methodology fixes (PRs #252/#253/#254) — remaps the existing --civic/
   --paper/--ink tokens under .rep-card only, no global mood/palette system
   touched, no other page affected. New --rc-keep-* tokens because canvas's
   "worth keeping" green is a distinct hue from its brand navy, but the
   shipped --civic today serves both roles (roll-call badge AND the keep
   verdict button) — decoupling them is what actually lets the provenance
   badge read navy and the keep button read green, matching canvas.
   ==================================================== */
.rep-card {
  --paper: oklch(1 0 0);
  --paper-2: oklch(0.985 0.003 258);
  --paper-3: oklch(0.972 0.004 258);
  --ink: oklch(0.2 0.035 260);
  --ink-2: oklch(0.37 0.032 260);
  --ink-3: oklch(0.54 0.026 260);
  --civic: oklch(0.4 0.155 262); /* canvas --brand: bold navy-royal */
  --civic-2: oklch(0.31 0.145 262);
  --civic-soft: oklch(0.94 0.04 262);
  --vote-red: oklch(0.53 0.205 27); /* canvas --replace: flag red */
  --vote-red-soft: oklch(0.955 0.03 27);
  --gold: oklch(0.72 0.125 76);
  /* Gold as TEXT fails contrast at the design's raw --gold (≈2.2:1 on
     white) — darkened text-only variant (§5b). Raw --gold stays reserved
     for bar fills, which get a separate ≥3:1 edge check instead. */
  --gold-text: oklch(0.5 0.125 76);
  --amber: oklch(0.72 0.13 66);
  --amber-soft: oklch(0.96 0.04 76);
  --tag-bg: oklch(0.95 0.006 260);
  --rule: oklch(0.88 0.006 260);
  --rule-2: oklch(0.93 0.005 260);
  /* keep-green — canvas --keep, decoupled from --civic (brand navy above) */
  --rc-keep: oklch(0.44 0.115 159);
  --rc-keep-2: oklch(0.36 0.11 159);
  --rc-keep-soft: oklch(0.93 0.045 159);
}

/* ====================================================
   Money redesign v2/v3 — numbered step chrome, alignment×money tracks,
   money hero + fused source list, restyled attendance/ask.
   Source of visual truth: claude-code-handoff/Candidate Card - Money
   Redesign.html + UX Remap - One Focus Per Page.html frames 3/7/9.
   ==================================================== */

.rep-card .sec {
  border-top: 1px solid var(--rule-2);
  padding: 20px 18px 4px;
}
.rep-card .sec:first-of-type {
  border-top: none;
}
.rep-card .step {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin-bottom: 2px;
}
.rep-card .step-n {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--paper);
  background: var(--civic);
  width: 19px;
  height: 19px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  transform: translateY(3px);
}
.rep-card .sec-kick {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 500;
}
.rep-card .sec-h {
  font-family: var(--serif);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.01em;
  /* Now an <h2> (was a <div>) — reset the UA stylesheet's default h2
     margin-block so this still lays out exactly like the old div. */
  margin: 5px 0 0;
  line-height: 1.2;
}
.rep-card .sec-note {
  font-size: 13px;
  color: var(--ink-3);
  line-height: 1.45;
  margin-top: 10px;
}
@media (min-width: 600px) {
  .rep-card .sec-h {
    font-size: 23px;
  }
}

/* ---- alignment legend + edit-issues fine print ---- */
.rep-card .al-legend {
  display: flex;
  gap: 14px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 10px 0 0;
}
.rep-card .al-legend span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.rep-card .al-legend i {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  display: inline-block;
}
.rep-card .al-legend .i-vote {
  background: var(--civic);
}
.rep-card .al-legend .i-money {
  background: var(--vote-red);
}
/* ---- per-issue card — replaces the old single-line cv2-iss-row--canvas ---- */
.rep-card .iss {
  margin-top: 14px;
  border: 1px solid var(--rule);
  border-radius: 12px;
  overflow: hidden;
  background: var(--paper);
}
.rep-card .iss + .iss {
  margin-top: 10px;
}
.rep-card .iss-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 15px;
  background: var(--paper-2);
}
.rep-card .iss-rank {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-3);
}
.rep-card .iss-name {
  font-family: var(--serif);
  font-size: 16.5px;
  font-weight: 600;
  flex: 1;
  min-width: 0;
}
.rep-card .iss-verdict {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-weight: 600;
  padding: 4px 9px;
  border-radius: 999px;
  white-space: nowrap;
}
.rep-card .iss-verdict.v-mixed {
  background: var(--amber-soft);
  color: var(--gold-text);
}
.rep-card .iss-verdict.v-with {
  background: var(--rc-keep-soft);
  color: var(--rc-keep);
}
.rep-card .iss-verdict.v-against {
  background: var(--vote-red-soft);
  color: var(--vote-red);
}
.rep-card .iss-tracks {
  display: grid;
  gap: 0;
}
@media (min-width: 560px) {
  .rep-card .iss-tracks {
    grid-template-columns: 1fr 1fr;
  }
}
.rep-card .trk {
  display: flex;
  gap: 11px;
  padding: 13px 15px;
  border-top: 1px solid var(--rule-2);
}
@media (min-width: 560px) {
  .rep-card .trk:nth-child(2) {
    border-left: 1px solid var(--rule-2);
  }
}
.rep-card .trk-ic {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
}
.rep-card .trk-ic.vote {
  background: var(--civic-soft);
  color: var(--civic);
}
.rep-card .trk-ic.money {
  background: var(--vote-red-soft);
  color: var(--vote-red);
}
.rep-card .trk-ic.money.ok {
  background: var(--rc-keep-soft);
  color: var(--rc-keep);
}
.rep-card .trk-lab {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.rep-card .trk-val {
  font-size: 13.5px;
  line-height: 1.34;
  margin-top: 3px;
  color: var(--ink-2);
}
.rep-card .trk-val b {
  color: var(--ink);
  font-weight: 600;
}
.rep-card .trk-flag {
  color: var(--vote-red);
  font-weight: 600;
}
.rep-card .trk-good {
  color: var(--rc-keep);
  font-weight: 600;
}
.rep-card .iss-drill-toggle {
  display: block;
  width: 100%;
  text-align: left;
  padding: 9px 15px;
  border-top: 1px solid var(--rule-2);
  background: none;
  border-left: none;
  border-right: none;
  border-bottom: none;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--civic);
  cursor: pointer;
  min-height: 44px;
}
.rep-card .iss-drill-toggle:focus-visible {
  outline: 2px solid var(--civic);
  outline-offset: -2px;
}

/* ---- money hero ---- */
.rep-card .mny-hero {
  margin: 16px 18px 0;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 6px 16px;
}
.rep-card .mny-total {
  font-family: var(--serif);
  font-size: 44px;
  font-weight: 600;
  line-height: 0.95;
  letter-spacing: -0.02em;
  color: var(--civic);
}
@media (min-width: 600px) {
  .rep-card .mny-total {
    font-size: 52px;
  }
}
.rep-card .mny-total .cyc {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 500;
  margin-top: 8px;
}
.rep-card .mny-vs {
  flex: 1;
  min-width: 190px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--ink-2);
  padding-bottom: 2px;
}
.rep-card .mny-vs b {
  color: var(--ink);
  font-weight: 600;
}
.rep-card .mny-vs .mult {
  color: var(--vote-red);
  font-weight: 700;
}

.rep-card .mix {
  margin: 20px 18px 0;
}

/* ---- fused funding-source list (FundingSources.tsx) ---- */
.rep-card .srcs,
.dl-money .srcs {
  margin: 22px 18px 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}
.rep-card .srcs-h,
.dl-money .srcs-h {
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 600;
  margin-bottom: 2px;
}
.rep-card .srcs-sub,
.dl-money .srcs-sub {
  font-size: 12.5px;
  color: var(--ink-3);
  margin-bottom: 12px;
  line-height: 1.4;
}
.rep-card .src,
.dl-money .src {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 2px 12px;
  padding: 14px 0;
  border-top: 1px solid var(--rule-2);
  align-items: start;
}
.rep-card .src:first-of-type,
.dl-money .src:first-of-type {
  border-top: 1px solid var(--rule);
}
.rep-card .src-dot,
.dl-money .src-dot {
  grid-row: 1 / 3;
  width: 10px;
  height: 10px;
  border-radius: 3px;
  margin-top: 5px;
}
.rep-card .src-dot.d-people,
.dl-money .src-dot.d-people {
  background: var(--civic);
}
.rep-card .src-dot.d-pac,
.dl-money .src-dot.d-pac {
  background: var(--vote-red);
}
.rep-card .src-dot.d-good,
.dl-money .src-dot.d-good {
  background: var(--rc-keep);
}
.rep-card .src-dot.d-neutral,
.dl-money .src-dot.d-neutral {
  background: var(--ink-3);
}
.rep-card .src-dot.d-unknown,
.dl-money .src-dot.d-unknown {
  background: var(--rule);
}
.rep-card .src-name,
.dl-money .src-name {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.25;
}
.rep-card .src-amt,
.dl-money .src-amt {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  text-align: right;
  white-space: nowrap;
}
.rep-card .src-pct,
.dl-money .src-pct {
  grid-column: 2 / 4;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
  margin-top: 1px;
}
.rep-card .src-body,
.dl-money .src-body {
  grid-column: 2 / 4;
  margin-top: 6px;
}
.rep-card .src-agenda,
.dl-money .src-agenda {
  font-size: 13px;
  color: var(--ink-2);
  line-height: 1.4;
}
.rep-card .src-tag,
.dl-money .src-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 7px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  font-weight: 600;
  padding: 4px 9px;
  border-radius: 999px;
  line-height: 1.2;
}
.rep-card .src-tag.t-conflict,
.dl-money .src-tag.t-conflict {
  background: var(--vote-red-soft);
  color: var(--vote-red);
}
.rep-card .src-tag.t-align,
.dl-money .src-tag.t-align {
  background: var(--rc-keep-soft);
  color: var(--rc-keep);
}
.rep-card .src-tag.t-none,
.dl-money .src-tag.t-none {
  background: var(--tag-bg);
  /* --ink-3 on --tag-bg is ~4.4:1, just under AA's 4.5:1 — same fix as
     .cv2-sub.blind .cv2-tag. */
  color: oklch(0.5 0.026 260);
}
.rep-card .src-proportion,
.dl-money .src-proportion {
  grid-column: 2 / 4;
  height: 4px;
  border-radius: 2px;
  background: var(--paper-3);
  margin-top: 9px;
  overflow: hidden;
}
.rep-card .src-proportion i,
.dl-money .src-proportion i {
  display: block;
  height: 100%;
  border-radius: 2px;
}
.rep-card .src-proportion i.d-people,
.dl-money .src-proportion i.d-people {
  background: var(--civic);
}
.rep-card .src-proportion i.d-pac,
.dl-money .src-proportion i.d-pac {
  background: var(--vote-red);
}
.rep-card .src-proportion i.d-good,
.dl-money .src-proportion i.d-good {
  background: var(--rc-keep);
}
.rep-card .src-proportion i.d-neutral,
.dl-money .src-proportion i.d-neutral {
  background: var(--ink-3);
}
.rep-card .src-proportion i.d-unknown,
.dl-money .src-proportion i.d-unknown {
  /* --rule (~L0.88) on this bar's --paper-3 track (~L0.972) is ~1.3:1,
     nowhere near AA's 3:1 for a graphical object — scoped darker fill,
     same hue/chroma family as --rule/--ink-3, --rule stays untouched
     elsewhere (it's fine as a border everywhere else it's used). */
  background: oklch(0.6 0.01 260);
}

/* ---- untraced-PAC caveat (mny-caveat) — Tier-A restyle of .cv2-pac-gap ---- */
.rep-card .cv2-pac-gap.mny-caveat {
  margin: 18px 18px 0;
  display: flex;
  gap: 11px;
  padding: 14px 15px;
  background: var(--paper-2);
  border-left: 3px solid var(--amber);
  border-radius: 0 8px 8px 0;
}
.rep-card .cv2-pac-gap.mny-caveat .ic {
  flex: 0 0 auto;
  color: var(--amber);
  font-weight: 700;
}
.rep-card .cv2-pac-gap.mny-caveat span:last-child {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-2);
}
.rep-card .cv2-pac-gap.mny-caveat b {
  color: var(--ink);
  font-weight: 600;
}

/* ---- attendance — presence-led big number (Tier A restyle + minor markup) ---- */
.rep-card .att-band {
  margin: 14px 18px 0;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.rep-card .cmt-outer {
  margin: 14px 18px 0;
  gap: 12px;
}
.rep-card .att-big {
  font-family: var(--serif);
  font-size: 32px;
  font-weight: 600;
  color: var(--rc-keep);
  line-height: 1;
  letter-spacing: -0.01em;
}
/* NEW (§3 att restyle, Build order item 2) — the copy line + band label
   accompanying .att-big; .att-band already carries the flex/gap layout
   above. */
.rep-card .att-txt {
  font-size: 14.5px;
  color: var(--ink-2);
  line-height: 1.4;
  flex: 1;
  min-width: 150px;
}
.rep-card .att-txt b {
  color: var(--ink);
  font-weight: 600;
}
.rep-card .att-chip {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-weight: 600;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--rc-keep-soft);
  color: var(--rc-keep);
}

/* ============================================================
   RepCard §2 — merged money section (Build order items 1-2). Everything
   below styles MoneyVerdict (mny-verdict), RevolvingDoorBand (rd-band), the
   expander/collapse chrome, FundingSources' src-votes sub-block, the
   money & democracy tiles (md-*), and the verdict button pair (.btn-keep/
   .btn-replace — the old .cv2-actions.verdicts/.pick markup this replaced is
   gone from both RepCard.tsx and this stylesheet). Same .rep-card-local
   token aliases as the block above (--civic=navy, --vote-red=red,
   --rc-keep=green, --gold-text/--amber=amber).
   ============================================================ */

/* ---- money verdict — "did their votes follow their donors?" ---- */
.rep-card .mny-verdict,
.dl-money .mny-verdict {
  margin: 14px 18px 0;
  padding: 13px 14px;
  background: var(--paper-2);
  border-radius: 11px;
}
.rep-card .mvd-head,
.dl-money .mvd-head {
  display: flex;
  align-items: baseline;
  gap: 11px;
}
.rep-card .mvd-head .pct,
.dl-money .mvd-head .pct {
  font-family: var(--serif);
  font-size: 32px;
  font-weight: 600;
  color: var(--vote-red);
  line-height: 1;
}
.rep-card .mvd-head span,
.dl-money .mvd-head span {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink-2);
}
.rep-card .mvd-head span b,
.dl-money .mvd-head span b {
  color: var(--ink);
}
.rep-card .mvd-bars,
.dl-money .mvd-bars {
  margin-top: 11px;
  display: grid;
  gap: 7px;
}
.rep-card .mvd-row,
.dl-money .mvd-row {
  display: grid;
  grid-template-columns: 76px 1fr 42px;
  gap: 9px;
  align-items: center;
}
.rep-card .mvd-row .k,
.dl-money .mvd-row .k {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.rep-card .mvd-row .bar,
.dl-money .mvd-row .bar {
  height: 8px;
  border-radius: 4px;
  background: var(--paper-3);
  overflow: hidden;
}
.rep-card .mvd-row .bar i,
.dl-money .mvd-row .bar i {
  display: block;
  height: 100%;
  border-radius: 4px;
}
.rep-card .mvd-row .bar i.bad,
.dl-money .mvd-row .bar i.bad {
  background: var(--vote-red);
}
.rep-card .mvd-row .bar i.you,
.dl-money .mvd-row .bar i.you {
  background: var(--civic);
}
.rep-card .mvd-row .v,
.dl-money .mvd-row .v {
  font-family: var(--mono);
  font-size: 12.5px;
  font-weight: 600;
  text-align: right;
  color: var(--ink);
}
.rep-card .mvd-row .v.bad,
.dl-money .mvd-row .v.bad {
  color: var(--vote-red);
}

/* ---- revolving-door band — documented-record-only, never a guess ---- */
.rep-card .rd-band {
  display: flex;
  gap: 11px;
  margin: 16px 18px 0;
  padding: 12px 14px;
  background: var(--amber-soft);
  border: 1px solid oklch(0.85 0.09 76);
  border-radius: 11px;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-2);
}
.rep-card .rd-band .ic {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: var(--paper);
  border: 1px solid oklch(0.85 0.09 76);
  color: var(--gold-text);
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 14.5px;
  font-weight: 600;
  margin-top: 1px;
}
.rep-card .rd-band b {
  color: var(--ink);
  font-weight: 600;
}
.rep-card .rd-band .src {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
  margin-top: 4px;
}

/* ---- money-section expander / collapse chrome ---- */
.rep-card .mny-expander {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  margin-top: 18px;
  padding: 13px 16px;
  border: 1px solid var(--rule);
  border-radius: 11px;
  background: var(--paper-2);
  font-family: var(--sans);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--civic);
  cursor: pointer;
  text-align: left;
}
.rep-card .mny-expander:hover {
  border-color: oklch(0.78 0.04 262);
  background: var(--civic-soft);
}
.rep-card .mny-expander small {
  display: block;
  font-weight: 400;
  font-size: 12.5px;
  color: var(--ink-3);
  margin-top: 2px;
}
.rep-card .mny-expander .car {
  font-family: var(--mono);
  font-size: 12.5px;
  flex: 0 0 auto;
}
.rep-card .mny-collapse {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 16px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--civic);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: 8px 13px;
  cursor: pointer;
  font-weight: 500;
}
.rep-card .mny-collapse:hover {
  background: var(--civic-soft);
}

/* ---- "did their money vote?" — src-votes sub-block per FundingSources
   row (Frame 7 item 1); grid-column 2/4 to span the row's content columns
   like its sibling .src-body/.src-proportion above. ---- */
.rep-card .src-votes,
.dl-money .src-votes {
  grid-column: 2 / 4;
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px dashed var(--rule-2);
}
.rep-card .src-votes .sv-top,
.dl-money .src-votes .sv-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.rep-card .src-votes .sv-top:last-child,
.dl-money .src-votes .sv-top:last-child {
  margin-bottom: 0;
}
.rep-card .src-votes .sv-lab,
.dl-money .src-votes .sv-lab {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.rep-card .src-votes .mvr-receipt,
.dl-money .src-votes .mvr-receipt {
  margin-top: 7px;
}
.rep-card .mvr-pct,
.dl-money .mvr-pct {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 600;
  padding: 4px 9px;
  border-radius: 999px;
}
.rep-card .mvr-pct.hi,
.dl-money .mvr-pct.hi {
  background: var(--vote-red-soft);
  color: var(--vote-red);
}
.rep-card .mvr-pct.lo,
.dl-money .mvr-pct.lo {
  background: var(--rc-keep-soft);
  color: var(--rc-keep);
}
.rep-card .mvr-dots,
.dl-money .mvr-dots {
  display: flex;
  gap: 5px;
  margin-top: 9px;
  flex-wrap: wrap;
}
.rep-card .mvr-dots i,
.dl-money .mvr-dots i {
  width: 14px;
  height: 14px;
  border-radius: 4px;
  display: inline-block;
}
.rep-card .mvr-dots i.w,
.dl-money .mvr-dots i.w {
  background: var(--vote-red);
}
.rep-card .mvr-dots i.a,
.dl-money .mvr-dots i.a {
  background: var(--paper);
  border: 1.5px solid var(--rc-keep);
}
.rep-card .mvr-receipt,
.dl-money .mvr-receipt {
  display: flex;
  gap: 9px;
  align-items: baseline;
  margin-top: 8px;
  padding: 9px 12px;
  background: var(--paper-2);
  border-radius: 8px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink-2);
}
.rep-card .mvr-receipt .d,
.dl-money .mvr-receipt .d {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-3);
  white-space: nowrap;
}
.rep-card .mvr-receipt .arr,
.dl-money .mvr-receipt .arr {
  font-family: var(--mono);
  color: var(--vote-red);
  font-weight: 600;
}
/* legend after the source list — only when at least one dot strip rendered */
.rep-card .mvc-key,
.dl-money .mvc-key {
  display: flex;
  gap: 18px;
  margin-top: 12px;
  font-size: 12.5px;
  color: var(--ink-2);
  flex-wrap: wrap;
}
.rep-card .mvc-key span,
.dl-money .mvc-key span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.rep-card .mvc-key i,
.dl-money .mvc-key i {
  width: 12px;
  height: 12px;
  border-radius: 3px;
}
.rep-card .mvc-key .kw,
.dl-money .mvc-key .kw {
  background: var(--vote-red);
}
.rep-card .mvc-key .ka,
.dl-money .mvc-key .ka {
  background: var(--paper);
  border: 1.5px solid var(--rc-keep);
}

/* ---- "why this matters" band + democracy tiles (§2 EXPANDED item 5) ---- */
.rep-card .md-why {
  margin: 14px 18px 0;
  padding: 13px 16px;
  border-left: 3px solid var(--civic);
  background: var(--civic-soft);
  border-radius: 0 10px 10px 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ink-2);
}
.rep-card .md-why b {
  color: var(--ink);
  font-weight: 600;
}
.rep-card .md-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin: 14px 18px 0;
}
.rep-card .md-tile {
  border: 1px solid var(--rule);
  border-radius: 12px;
  padding: 15px 16px;
}
.rep-card .md-tile.wide {
  grid-column: 1 / 3;
}
.rep-card .md-k {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
}
.rep-card .md-k .ic {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 600;
  font-family: var(--mono);
}
.rep-card .md-k .ic.vote {
  background: var(--civic-soft);
  color: var(--civic);
}
.rep-card .md-k .ic.roi {
  background: var(--vote-red-soft);
  color: var(--vote-red);
}
.rep-card .md-k .ic.door {
  background: var(--amber-soft);
  color: var(--gold-text);
}
.rep-card .md-k .ic.dark {
  background: var(--tag-bg);
  color: var(--ink-2);
}
.rep-card .md-big {
  font-family: var(--serif);
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-top: 9px;
  line-height: 1.1;
}
.rep-card .md-big small {
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 400;
  color: var(--ink-3);
  letter-spacing: 0;
}
.rep-card .md-txt {
  font-size: 14.5px;
  color: var(--ink-2);
  line-height: 1.5;
  margin-top: 7px;
}
.rep-card .md-txt b {
  color: var(--ink);
  font-weight: 600;
}
.rep-card .md-src {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
  margin-top: 9px;
}
.rep-card .md-roi-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
}
.rep-card .md-roi-bar .in {
  height: 14px;
  border-radius: 4px;
  background: var(--vote-red);
  flex: 0 0 auto;
}
.rep-card .md-roi-bar .out {
  height: 14px;
  border-radius: 4px;
  background: repeating-linear-gradient(
    -45deg,
    var(--vote-red-soft),
    var(--vote-red-soft) 6px,
    oklch(0.93 0.05 27) 6px,
    oklch(0.93 0.05 27) 12px
  );
  border: 1px solid var(--vote-red);
  flex: 1;
}
.rep-card .md-roi-bar .x {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--vote-red);
  white-space: nowrap;
}

/* ---- verdict button pair — whiteboard's .verdict/.btn grid, RepCard.tsx's
   real verdict markup (replaced .cv2-actions.verdicts/.pick; same handlers,
   same keep/replace semantics). ---- */
.rep-card .verdict {
  display: grid;
  gap: 12px;
  margin-top: 20px;
}
@media (min-width: 520px) {
  .rep-card .verdict {
    grid-template-columns: 1fr 1fr;
  }
}
.rep-card .btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 16px 14px;
  border-radius: 12px;
  cursor: pointer;
  text-align: center;
  border: 1.5px solid transparent;
  font-family: var(--sans);
}
.rep-card .btn b {
  font-size: 16px;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 8px;
}
.rep-card .btn small {
  font-size: 12.5px;
  opacity: 0.85;
  font-weight: 400;
}
.rep-card .btn-keep {
  background: var(--rc-keep);
  color: #fff;
}
.rep-card .btn-keep:hover {
  background: var(--rc-keep-2);
}
.rep-card .btn-replace {
  background: var(--paper);
  border-color: var(--vote-red);
  color: var(--vote-red);
}
.rep-card .btn-replace:hover {
  background: var(--vote-red-soft);
}
.rep-card .btn .box {
  width: 17px;
  height: 17px;
  border-radius: 5px;
  border: 2px solid currentColor;
  flex: 0 0 auto;
}

/* ---- Ask anything (SeatChat) — money-redesign paper-2 band ---- */
.dg-deep .seat-chat {
  background: var(--paper-2, oklch(0.985 0.003 258));
  border-top: 1px solid var(--rule, oklch(0.88 0.006 260));
  padding: 20px 18px;
  border-radius: 0 0 14px 14px;
}
.dg-deep .seat-chat .cv2-block-head .lab {
  font-family: var(--serif);
  font-size: 19px;
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink, oklch(0.2 0.035 260));
}

/* ---- seat kicker — flatten the office pill into canvas's single flowing
   mono kicker line ("U.S. HOUSE · TX-21   UP NOV 2026") ---- */
.rep-card .seat-office {
  background: none;
  padding: 0;
  border-radius: 0;
  color: var(--ink-3);
}
.rep-card .seat-office::after {
  content: "\00B7";
  margin-left: 10px;
  color: var(--rule);
}

/* ---- blind-mode header — squared navy avatar + filled reveal CTA, same
   proportions as canvas's cd-avatar/cd-select without breaking the
   blind-first product behavior (identity stays hidden pre-reveal) ---- */
.rep-card .cv2-head.blind {
  background: var(--paper);
}
.rep-card .cv2-photo.blind {
  border-radius: 11px;
  background: var(--civic-soft);
  border: 1px dashed var(--civic);
}
.rep-card .cv2-photo.blind::after {
  color: var(--civic-2);
  font-size: 20px;
}
.rep-card .cv2-name.blind {
  font-size: 18px;
  color: var(--ink);
}
.rep-card .cv2-sub.blind .cv2-tag {
  background: var(--tag-bg);
  border-color: var(--rule);
  /* --ink-3 (the base .cv2-tag color, prototype.css) is ~5:1 against
     --paper but only ~4.4:1 against this pill's --tag-bg fill — just under
     WCAG AA's 4.5:1 for normal text. Scoped, slightly darker override
     (same hue/chroma family) instead of touching the shared --ink-3 token,
     which is fine everywhere else it's used. */
  color: oklch(0.5 0.026 260);
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
}
/* Canvas variant's blind-mode subtext — a plain sentence (screens.css
   .rcard-who .sub, line 228), not the uppercase pill tag above. */
.rep-card .cv2-sub-plain {
  font-size: 12.5px;
  color: var(--ink-3);
  margin-top: 1px;
}
.rep-card .cv2-reveal {
  background: var(--civic);
  border-color: var(--civic);
  color: var(--paper-2);
}
.rep-card .cv2-reveal:hover {
  background: var(--civic-2);
  border-color: var(--civic-2);
}
/* .lab and .reveal-ic set their own color in prototype.css (dark ink /
   --civic respectively) rather than inheriting the button's — both need an
   explicit override or they go invisible against the new navy-filled button. */
.rep-card .cv2-reveal .lab,
.rep-card .cv2-reveal .reveal-ic {
  color: var(--paper-2);
}

/* ---- alignment block — box it like canvas's .cd-align card-within-card,
   enlarge the aggregate % (when present) to a real headline number, and
   compact the per-issue rows toward canvas's thin-track-bar + % reading ---- */
.rep-card .cv2-issues {
  margin: 14px 18px 0;
  padding: 12px 16px;
  border-radius: 10px;
  border: 1px solid var(--rule-2);
  background: var(--paper);
}
/* prototype-c.css's "Section label hierarchy pass" (~line 2259) promotes
   .cv2-block-head .lab to a big serif title with !important, for the
   FUNDING/PACs/INDUSTRY section headers — but its selector also matches the
   ALIGNMENT block's "Aligns with your issues" label (.cv2-issues is a
   .cv2-block-head container too). Canvas (.at-lab, screens.css:234) keeps
   that label as a small mono-uppercase overline, so re-win the cascade here
   with matching !important weight, scoped to .cv2-issues only — the funding
   block keeps the big serif treatment untouched. */
.rep-card .cv2-issues .cv2-block-head .lab {
  font-family: var(--mono) !important;
  font-size: 11.5px !important;
  font-weight: 600 !important;
  letter-spacing: 0.09em !important;
  text-transform: uppercase !important;
  color: var(--ink-3) !important;
}
.rep-card .cv2-block-head .overall {
  font-family: var(--serif);
}
.rep-card .cv2-block-head .overall b {
  /* canvas .at-pct: serif 30px (screens.css:248) — ported verbatim. */
  font-size: 30px;
  font-weight: 600;
  color: var(--civic-2);
}
/* Canvas 2-tier good(green)/bad(red) semantic for the aggregate % (screens.css
   .at-pct.good/.bad) — more specific than the unscoped rule above, which
   remains the fallback when rowVariant isn't 'canvas' (no class present). */
.rep-card .cv2-block-head .overall b.good {
  color: var(--rc-keep);
}
.rep-card .cv2-block-head .overall b.bad {
  color: var(--vote-red);
}
.rep-card .cv2-iss-row.open {
  margin: 0 -16px;
  padding: 0 16px;
}
/* canvas's .align-row.sel: a brand-soft highlight on the open row
   (screens.css:503), scoped to the canvas rowVariant only — the legacy
   ballot CandidateCard's open-row background stays the plain --paper
   inset-rail treatment above. */
.rep-card .cv2-iss-row--canvas.open {
  background: var(--civic-soft);
  border-radius: 8px;
}
.rep-card .cv2-iss-head {
  padding: 9px 0;
  gap: 10px;
}
.rep-card .cv2-iss-head .name {
  font-size: 12.5px;
  font-weight: 600;
  margin-bottom: 4px;
}
.rep-card .cv2-bar {
  height: 6px;
  /* base .cv2-bar track is a hardcoded warm tan, not tied to --rule-2 —
     override so the empty track reads white-palette, not civic-cream. */
  background: var(--rule-2);
}
/* Canvas 2-tier good(green)/bad(red) bar semantic (screens.css
   .align-track i.good/.bad), scoped to the canvas rowVariant only — the
   legacy 3-tier blue/gold/red scheme (.cv2-bar .fill.mid/.low in
   prototype.css) stays untouched for the ballot CandidateCard. */
.rep-card .cv2-iss-row--canvas .cv2-bar .fill.good {
  background: var(--rc-keep);
}
.rep-card .cv2-iss-row--canvas .cv2-bar .fill.bad {
  background: var(--vote-red);
}
.rep-card .cv2-iss-head .meta {
  font-size: 11.5px;
  margin-top: 3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 280px;
}
/* Canvas .align-row shape (voting_record rows only — RepCard always passes
   rowVariant="canvas"): one line, three cells — name | bar | fraction, no
   per-row %. ResearchedPositionRow / WebSearchAlignmentRow keep the
   .topic/.meta/.pct shape above (they render directional badges, not a
   kept/total fraction), so those rules stay in place. */
.rep-card .cv2-iss-row--canvas .cv2-iss-head {
  /* canvas .align-row grid: 1fr 96px 40px (screens.css:253) — ported
     verbatim; was 84px/44px, a hand-approximation that drifted. */
  grid-template-columns: 1fr 96px 40px;
  gap: 12px;
}
.rep-card .cv2-iss-row--canvas .cv2-iss-name {
  /* canvas .ai: 13px (screens.css:254) — was 12.5px. */
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rep-card .cv2-iss-row--canvas .cv2-iss-frac {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-2);
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 3px;
  white-space: nowrap;
}
/* canvas caret affordance (screens.css:504-505): open row = brand-colored
   ▾, closed expandable rows = dim ▸. Direction + dim class are set in the
   JSX (VoterChoiceApp.tsx's AlignmentIssueRow, canvas branch). */
.rep-card .cv2-iss-row--canvas .cv2-iss-frac .chev {
  font-size: 8px;
  color: var(--civic);
  margin-left: 1px;
}
.rep-card .cv2-iss-row--canvas .cv2-iss-frac .chev.dim {
  color: var(--ink-3);
}
.rep-card .cv2-block-head .overall .cv2-overall-frac {
  /* canvas .at-frac: mono 11px, ink-3 (screens.css:251) — was 12px/ink-2. */
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-3);
}
.rep-card .cv2-iss-head .cv2-ws-badge {
  font-size: 11.5px;
  padding: 2px 6px;
  font-family: var(--mono);
}
.rep-card .cv2-iss-head .cv2-ws-conf {
  font-size: 11.5px;
  padding: 1px 4px;
}

/* ---- "See all votes" — canvas's .see-all/.see-all-btn (screens.css:
   506-507), ported verbatim. Lives INSIDE the align-band (.cv2-issues),
   the last row after the issue list — discovery with its data, not a
   detached row (Round-4 ask). Canvas authored these classes but never
   wired them into its own JSX (still uses the old card-evidence row);
   wired here per the Round-4 direction. */
.rep-card .cv2-see-all {
  margin-top: 12px;
  padding-top: 11px;
  border-top: 1px dashed var(--rule-2);
}
.rep-card .cv2-see-all-btn {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--civic);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}
.rep-card .cv2-see-all-btn:hover {
  color: var(--civic-2);
}

/* ---- funding — box it like canvas's .cd-money. ---- */
.rep-card .cv2-disclose {
  margin: 12px 18px 0;
  border-radius: 10px;
  border: 1px solid var(--rule-2);
  background: var(--paper);
  overflow: hidden;
}
.rep-card .cv2-disclose-eyebrow {
  font-size: 11.5px;
}
/* The whole money glance is the disclosure trigger — canvas's clickable
   .money-line + .money-disclose chevron affordance (screens.css:423,429),
   not a separate button in a detached row below (Round-4 ask). Same
   padding the old .cv2-disclose-toggle button used. */
.cv2-money-glance {
  padding: 18px 24px;
}
@media (max-width: 600px) {
  .cv2-money-glance {
    padding: 16px 18px;
  }
}
.cv2-disclose.open .cv2-money-glance {
  border-bottom: 1px dashed var(--rule-2);
}

/* ---- funding glance row — canvas's compact .money-top shape (mono
   FUNDING label + proportional small/large/PAC bar + total $, screens.css:
   253-259) instead of the taller eyebrow/title/mix-text stack. The legend,
   teaser, and median chip ride as further width:100% lines that wrap under
   the row-1 content within this flex-wrap row (matching canvas's
   dashed-rule .money-detail separator, screens.css:406-408). Rendered as a
   real <button> now (was a plain div) — the flex-direction/button-reset
   overrides are needed because the unscoped .cv2-disclose-lab base rule
   (prototype-c.css) sets flex-direction: column and no button reset. ---- */
.rep-card .rc-money-glance {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  width: 100%;
  background: none;
  border: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.rep-card .rc-money-lab {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
  white-space: nowrap;
}
.rep-card .rc-money-bars {
  flex: 1;
  min-width: 80px;
  display: flex;
  height: 9px;
  border-radius: 999px;
  overflow: hidden;
  border: 1px solid var(--rule-2);
}
/* Segment-boundary divider (1.4.11 non-text contrast): the small/large/pac
   fills abut with no separator, and their raw colors are too close in
   lightness for any single divider to hit AA's 3:1 against every neighbor
   (best achievable near-black gets keep|gold to ~2.9:1, gold|red to
   ~3.6:1) — a residual gap rooted in the palette's L-spacing, flagged for
   design; this divider is still a real improvement over the ~2.3-2.9:1
   raw adjacency. */
.rep-card .rc-money-bars i + i {
  border-left: 1.5px solid oklch(0.08 0 0);
}
.rep-card .rc-money-bars i.small {
  background: var(--rc-keep);
}
.rep-card .rc-money-bars i.large {
  background: var(--gold);
}
.rep-card .rc-money-bars i.pac {
  background: var(--vote-red);
}
.rep-card .rc-money-tot {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
}
/* canvas's .money-disclose chevron affordance (screens.css:429) — the
   explicit "FUNDERS & INFLUENCE ▾" text living inside the glance itself,
   pinned to the end of row 1 via margin-left:auto (so it still reads at
   the right edge even when .rc-money-bars is absent, e.g. no fundingMix). */
.rep-card .rc-money-disclose {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--civic);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  margin-left: auto;
}
.rep-card .rc-money-disclose .chev {
  transition: transform 0.15s;
}
/* Compact legend (dot + % + word) under the glance bars — Muxin's explicit
   Round-4 extension BEYOND canvas: canvas's collapsed .money-line carries
   no legend at all (screens.css comment "money-top bar + $ total +
   .money-detail" — no fp-legend), so "what orange vs. red means" only
   surfaced once the panel was expanded. Shrunk fp-legend pattern
   (screens.css:460-467): swatch dot + bold % + one-word label. */
.rep-card .rc-money-legend {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-size: 11px;
  color: var(--ink-2);
}
.rep-card .rc-money-legend span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.rep-card .rc-money-legend i.dot {
  width: 7px;
  height: 7px;
  border-radius: 2px;
  flex-shrink: 0;
}
.rep-card .rc-money-legend i.dot.small {
  background: var(--rc-keep);
}
.rep-card .rc-money-legend i.dot.large {
  background: var(--gold);
}
.rep-card .rc-money-legend i.dot.pac {
  background: var(--vote-red);
}
/* canvas's .money-detail/.md-who teaser sentence (screens.css:410-412) —
   same dashed-rule second-line treatment as .rc-money-median below, since
   both are "detail" rows stacked under the money-top glance row. */
.rep-card .rc-money-teaser {
  width: 100%;
  padding-top: 8px;
  margin-top: 2px;
  border-top: 1px dashed var(--rule-2);
  font-size: 12px;
  color: var(--ink-3);
}
.rep-card .rc-money-teaser b {
  color: var(--ink-2);
  font-weight: 600;
}
.rep-card .rc-money-median {
  width: 100%;
  padding-top: 8px;
  margin-top: 2px;
  border-top: 1px dashed var(--rule-2);
}
/* The reworded median chip ("≈Nx the typical <office> campaign") runs
   noticeably longer than the old bare "N× median" — let it wrap instead of
   forcing a nowrap pill wide enough to overflow on mobile. */
.rep-card .rc-money-median .median-chip {
  white-space: normal;
}

/* ---- industry breakdown (canvas rowVariant) — one progress-bar-per-row
   (screens-results.jsx's .fp-ind/.fi-track, screens.css:460-469) instead of
   the legacy combined stacked bar + swatch-dot list. Rendered only when
   FunderBars gets variant="canvas" (RepCard); scoped under .rep-card so the
   ballot CandidateCard's .cv2-industry-bar/.cv2-industry-list markup and
   styling are untouched. ---- */
.rep-card .cv2-industry-rows {
  display: grid;
  gap: 7px;
}
.rep-card .cv2-industry-row {
  display: grid;
  grid-template-columns: 138px 1fr 56px 36px;
  gap: 10px;
  align-items: center;
}
.rep-card .cv2-industry-row .cir-name {
  font-size: 12.5px;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rep-card .cv2-industry-row .cir-name small {
  display: block;
  font-size: 11.5px;
  color: var(--ink-3);
  white-space: normal;
}
.rep-card .cv2-industry-row .cir-track {
  height: 8px;
  border-radius: 999px;
  background: var(--rule-2);
  overflow: hidden;
}
.rep-card .cv2-industry-row .cir-track i {
  display: block;
  height: 100%;
  background: var(--civic);
  border-radius: 999px;
}
.rep-card .cv2-industry-row .cir-amt {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-2);
  text-align: right;
}
.rep-card .cv2-industry-row .cir-pct {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--ink);
  text-align: right;
}

/* ---- PAC-term tooltip (canvas rowVariant) — the PAC definition moves off
   an always-visible paragraph and onto a keyboard-focusable tooltip term in
   the legend (screens.css .pac-term/.pac-tip, lines 468-474), ported
   verbatim. Scoped under .rep-card so the legacy ballot CandidateCard's
   always-visible .cv2-pac-gloss paragraph is untouched. ---- */
.rep-card .pac-term {
  position: relative;
  color: var(--civic);
  font-weight: 600;
  border-bottom: 1px dotted var(--civic);
  cursor: help;
  outline: none;
}
.rep-card .pac-tip {
  position: absolute;
  left: -6px;
  top: calc(100% + 9px);
  width: 270px;
  /* 1.4.10 reflow: fixed 270px can overflow a 320px viewport once the
     trigger sits near the card edge — clamp to the viewport as a safety
     net (still needs a live-browser check for directional clipping, since
     a CSS-only clamp can't reposition the tooltip to the other side). */
  max-width: calc(100vw - 32px);
  background: var(--paper-2);
  color: var(--ink-2);
  border: 1px solid var(--rule);
  font-family: var(--sans);
  font-weight: 400;
  font-size: 11.5px;
  line-height: 1.5;
  letter-spacing: 0;
  text-transform: none;
  padding: 10px 13px;
  border-radius: 9px;
  box-shadow: 0 16px 36px -18px oklch(0.2 0.03 255 / 0.3);
  z-index: 30;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-3px);
  transition:
    opacity 0.12s,
    transform 0.12s;
  pointer-events: none;
}
.rep-card .pac-tip b {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--civic);
  margin-right: 6px;
}
.rep-card .pac-term:hover .pac-tip,
.rep-card .pac-term:focus .pac-tip {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

/* ---- named-issue-PAC pills (canvas rowVariant) — screens.css .fp-pacs/
   .fp-pac (lines 486-488), ported verbatim, replacing the legacy stacked
   card (full legal name + advocates line + boxed conflict flag) with one
   compact pill + one compact conflict line. Content is kept (Muxin: this
   repo's named-PAC callout is more thorough than canvas's, which doesn't
   have one), only the form shrinks. ---- */
.rep-card .fp-pacs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.rep-card .fp-pac-wrap {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: 100%;
}
/* "what they advocate" line inside the compact canvas PAC (was legacy-only).
   Sits between the pill and the conflict flag. */
.rep-card .fp-pac-wrap .fp-pac-advocates {
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink-2);
  padding: 0 4px;
  text-wrap: pretty;
}
.rep-card .fp-pac {
  font-size: 12px;
  color: var(--ink-2);
  background: var(--paper);
  border: 1px solid var(--rule-2);
  border-radius: 999px;
  padding: 6px 12px;
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
}
.rep-card .fp-pac .sw {
  align-self: center;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.rep-card .fp-pac b {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--civic);
}
/* compact one-line conflict/alignment note under the pill (was a padded,
   bordered box — .cv2-pac-flag in the legacy stacked card). */
.rep-card .fp-pac-flag {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: 11px;
  padding: 0 4px;
}
.rep-card .fp-pac-flag .ic {
  flex-shrink: 0;
}
.rep-card .fp-pac-flag.align {
  color: var(--rc-keep);
}
.rep-card .fp-pac-flag.conflict {
  color: var(--vote-red);
}
.rep-card .fp-pac-flag .msg b {
  color: inherit;
  font-weight: 700;
}

/* ====================================================
   § DELEGATION OVERVIEW
   PORT of design-handoff/keystone-canvas/src/delegation.css (its own "§8 ·
   DELEGATION OVERVIEW → DRILL-DOWN" section) plus the .cd-* unified
   candidate-card rules SeatCard reuses, from
   design-handoff/keystone-canvas/src/candidates.css. Following the
   RAISED-VS-MEDIAN / .cmp precedent above: design tokens (--brand/--keep/
   --replace family) are mapped onto the shipped warm palette, scoped to
   .delegation (already on DelegationWorkspace.tsx's root), reusing the
   EXACT oklch values the .cmp scope in public/candidates.css already
   chose — so keep/replace reads the same color on the compare and
   delegation screens. --brand-2 is added alongside the tokens the plan
   called out because .cd-seatlab .seat-t (a requested selector) needs it;
   same value .cmp already carries.
   The .cd- / .dg- prefixed rules themselves aren't re-scoped under
   .delegation — they're already namespaced by their own prefix, same convention as
   .cmp-* above. .bar-good/.bar-mid/.bar-bad (bare, generic names) ARE
   scoped, same as .cmp .tone-good/.tone-mid/.tone-bad above.
   NOT ported: .cd-delta/.cd-pair/.cd-stage/.cd-explain/.cd-pick-tag
   (separate task) and .rh-dots (no matching rail-header-dots element
   exists in this repo). The source's ".vbtn.keep.is-on"/".vbtn.replace.is-on"
   emphasis (retargeted here in an earlier pass at ".pick.picked"/".pick.replace
   .picked-replace") was dropped along with those dead selectors once
   RepCard.tsx's real verdict buttons became .btn-keep/.btn-replace — no
   replacement rule needed, .btn-keep.picked/.btn-replace.picked-replace
   already carry their own emphasis styling above.
   Loaded via redesign2.css's existing <link> in src/app/layout.tsx.
   ==================================================== */

.delegation {
  /* --brand/--brand-2/--brand-soft point at the app-wide --bf-brand/
     --bf-brand-2 tokens (.bf-app above), not --civic: this scope only
     ever renders inside App2, always under body.bf-app, so --bf-brand
     is already in scope. --civic was the pre-.bf-app-foundation choice
     (same "remap --civic locally" pattern candidates.css's HeadToHead
     uses) but .bf-app's own comment is explicit that --civic is LEFT
     UNTOUCHED app-wide — it doubles as the "keep" green elsewhere — so
     reading it here resolved to the global green civic default, not
     navy: brand accents (dg-kicker, the roll-call provenance badge,
     cd-avatar, dg-print.ready) rendered civic-green instead of the
     canvas's navy. Same fix as .pe-screen's (PolisEntry, PR #237).
     --keep/--replace below are unaffected — already independent of
     --civic, so the "worth keeping" chip/button and vote-fraction bars
     stay green, matching canvas. */
  --brand: var(--bf-brand);
  --brand-2: var(--bf-brand-2);
  --brand-soft: oklch(0.94 0.04 262);
  --keep: oklch(0.45 0.11 159);
  --keep-soft: oklch(0.94 0.04 159);
  --replace: var(--vote-red);
  --replace-soft: oklch(0.94 0.05 28);
}

/* ---------- unified seat card (SeatCard) — ported from candidates.css ---------- */
.cd-card {
  border: 1px solid var(--rule);
  border-radius: 14px;
  background: var(--paper-2);
  box-shadow: var(--shadow-soft);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.cd-card.is-pick {
  border-color: var(--keep);
  box-shadow:
    0 0 0 2px var(--keep-soft),
    var(--shadow-soft);
}
.cd-seatlab {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ink-3);
  padding: 9px 16px;
  border-bottom: 1px solid var(--rule-2);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.cd-seatlab .seat-t {
  color: var(--brand-2);
}
.cd-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px 12px;
}
.cd-avatar {
  width: 44px;
  height: 44px;
  border-radius: 11px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  font-family: var(--serif);
  font-weight: 600;
  font-size: 18px;
  background: var(--brand-soft);
  color: var(--brand-2);
  border: 1px solid var(--rule-2);
}
.cd-card.blind .cd-avatar {
  background: var(--tag-bg);
  /* --ink-3 on --tag-bg is ~4.4:1, just under AA's 4.5:1 — same fix as
     .cv2-sub.blind .cv2-tag. */
  color: oklch(0.5 0.026 260);
}
.cd-who {
  flex: 1;
  min-width: 0;
}
.cd-name {
  font-family: var(--serif);
  font-size: 16.5px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
  display: flex;
  align-items: center;
  gap: 7px;
  line-height: 1.15;
}
.cd-role {
  font-size: 11.5px;
  color: var(--ink-3);
  margin-top: 2px;
  line-height: 1.3;
}
.cd-prov-row {
  padding: 0 16px 12px;
}
/* provenance badge (roll-call vs researched) — also not ported by the
   earlier CSS commit. Mirrors .cmp .prov exactly (candidates.css), the same
   badge HeadToHead.tsx's ProvBadge already renders under .cmp; SeatCard's
   DgProv needs it under .delegation instead. */
.delegation .prov {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  padding: 3px 8px 3px 7px;
  border-radius: 5px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
  line-height: 1.4;
}
.delegation .prov::before {
  font-size: 9px;
}
.delegation .prov.rollcall {
  background: var(--brand);
  color: var(--paper-2);
  border: 1.5px solid var(--brand);
}
.delegation .prov.rollcall::before {
  content: "\25C6"; /* filled diamond */
}
.delegation .prov.researched {
  background: var(--paper-2);
  color: var(--brand-2);
  border: 1.5px dashed var(--brand);
}
.delegation .prov.researched::before {
  content: "\25C7"; /* hollow diamond */
}
.cd-align {
  margin: 0 16px;
  padding: 11px 14px;
  border-radius: 10px;
  background: var(--paper);
  border: 1px solid var(--rule-2);
}
.cd-align-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.cd-align-top .lab {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
}
.cd-pct {
  font-family: var(--serif);
  font-weight: 600;
  font-size: 27px;
  line-height: 1;
}
/* alignment tone helpers for .cd-pct — NOT ported by the earlier CSS commit
   (only the .bar-* track-fill tones were carried over); added here so
   SeatCard's big percentage number actually colors by tone, same values as
   the analogous .cmp .tone-good/.tone-mid/.tone-bad/.tone-na. */
.delegation .tone-good {
  color: var(--keep);
}
.delegation .tone-mid {
  color: var(--gold-text);
}
.delegation .tone-bad {
  color: var(--replace);
}
.delegation .tone-na {
  color: var(--ink-3);
}
.cd-issues {
  margin-top: 10px;
  display: grid;
  gap: 7px;
}
.cd-irow {
  display: grid;
  grid-template-columns: 1fr 70px 30px;
  gap: 10px;
  align-items: center;
}
.cd-irow .ik {
  font-size: 12px;
  color: var(--ink-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cd-track {
  height: 6px;
  border-radius: 999px;
  background: var(--rule-2);
  overflow: hidden;
}
.cd-track i {
  display: block;
  height: 100%;
}
.cd-irow .iv {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  text-align: right;
  color: var(--ink-2);
}
.delegation .bar-good {
  background: var(--keep);
}
.delegation .bar-mid {
  background: var(--gold);
}
.delegation .bar-bad {
  background: var(--replace);
}
/* not in the source (only good/mid/bad exist there) — added so SeatCard's
   n/a issue tracks have a neutral fill, same idea as the .cmp .tone-na
   precedent in public/candidates.css */
.delegation .bar-na {
  background: var(--ink-3);
}
.cd-money {
  margin: 12px 16px 0;
  padding: 11px 14px;
  border-radius: 10px;
  background: var(--paper);
  border: 1px solid var(--rule-2);
}
.cd-money-top {
  display: flex;
  align-items: center;
  gap: 10px;
}
.cd-money-top .lab {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 600;
  white-space: nowrap;
}
.cd-money-top .tot {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--ink);
}
.cd-foot {
  margin-top: auto;
  padding: 13px 16px 15px;
}
.cd-select {
  width: 100%;
  min-height: 44px;
  border-radius: 10px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 13.5px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: var(--brand);
  color: var(--paper-2);
  border: 1.5px solid var(--brand);
  box-shadow: var(--shadow-soft);
}
.cd-select.ghost {
  background: var(--paper);
  color: var(--brand);
}
.cd-card.is-pick .cd-select {
  background: var(--keep);
  border-color: var(--keep);
}
.cd-select:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* ---------- overview shell (DelegationOverview) — ported from delegation.css ---------- */
.dg {
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--paper);
}
.dg .flagbar {
  flex: 0 0 auto;
}

/* ---- overview header + progress ---- */
.dg-ov-head {
  padding: 20px 30px 8px;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}
.dg-ov-intro {
  min-width: 0;
}
.dg-kicker {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brand);
}
.dg-ov-head h2 {
  font-family: var(--serif);
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin: 5px 0 0;
  color: var(--ink);
}
.dg-ov-head .sub {
  font-size: 13px;
  color: var(--ink-3);
  margin: 5px 0 0;
  max-width: 560px;
  line-height: 1.5;
}
.dg-prog {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-shrink: 0;
}
.dg-prog .meter {
  display: flex;
  flex-direction: column;
  gap: 7px;
  align-items: flex-end;
}
.dg-prog .mlab {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.dg-prog .dots {
  display: flex;
  gap: 5px;
}
.dg-prog .dots i {
  width: 26px;
  height: 6px;
  border-radius: 999px;
  background: var(--rule);
  display: block;
}
.dg-prog .dots i.done {
  background: var(--keep);
}
.dg-print {
  min-height: 46px;
  padding: 0 20px;
  border-radius: 11px;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 13.5px;
  border: 1.5px solid var(--rule);
  background: var(--paper-2);
  color: var(--ink-3);
  cursor: not-allowed;
  white-space: nowrap;
}
.dg-print.ready {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--paper-2);
  cursor: pointer;
  box-shadow: var(--shadow-soft);
}

/* ---- the seat grid ---- */
.dg-grid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 18px;
  padding: 16px 30px 10px;
  align-items: start;
}

/* Tiered collapse — NOT present in the source (delegation.css ships no
   media query at all). The original single ~560px breakpoint left the
   3-col grid live at tablet/narrow-desktop widths, where seat cards render
   crushed: mono seat labels wrap letter-by-letter, "Your U.S.
   Representative" truncates, buttons stack awkwardly. Widened to three
   tiers so a card always has enough width to render its content cleanly:
   1 col up to 760px, 2 cols 761–1099px, 3 cols from 1100px. */
@media (max-width: 760px) {
  .dg-grid {
    grid-template-columns: 1fr;
  }
}
@media (min-width: 761px) and (max-width: 1099px) {
  .dg-grid {
    grid-template-columns: 1fr 1fr;
  }
}

/* verdict-status pill in the seat label row */
.dg-status {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 999px;
  white-space: nowrap;
}
.dg-status.todo {
  background: var(--tag-bg);
  /* --ink-3 on --tag-bg is ~4.4:1, just under AA's 4.5:1 — same fix as
     .cv2-sub.blind .cv2-tag. */
  color: oklch(0.5 0.026 260);
}
.dg-status.keep {
  background: var(--keep-soft);
  color: var(--keep);
}
.dg-status.replace {
  background: var(--replace-soft);
  color: var(--replace);
}
/* Open seat (v3 §6b) — a successor pick is neither "keep" nor "replace" (no
   incumbent to reject), so it gets its own tone, reusing the same
   positive/decided visual language as .dg-status.keep. */
.dg-status.successor {
  background: var(--keep-soft);
  color: var(--keep);
}

/* ---- open-seat band on the overview card (between provenance + alignment) ---- */
.cd-openseat {
  margin: 0 16px 12px;
  padding: 10px 13px;
  background: var(--brand-soft, oklch(0.94 0.04 262));
  border-radius: 10px;
  font-family: var(--sans);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-2);
}
.cd-openseat .os-kick {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--brand, var(--bf-brand));
  margin-bottom: 3px;
}

/* ---- funding row — synced thin mix bar (NEW, Frame 1 item 1) — replaces
   .cd-bars; same classes/colors/order as the card's own mix bar. DOM confirmed
   (DelegationOverview.tsx): each segment/swatch is `<i className="mix-sm|
   mix-lg|mix-pac">`, width set inline per-candidate, color from the class —
   so .mix-sm/.mix-lg/.mix-pac need real background rules here (below), not
   inline color as this comment previously (incorrectly) assumed. Matched to
   the card's own mix bar (.cv2-money-map .seg small/large/pac, prototype.css)
   via global --bf-brand/--gold/--vote-red, since that's what .seg.small/
   .seg.large/.seg.pac resolve to and this renders outside .rep-card's local
   token scope. */
.cd-mixbar {
  display: flex;
  height: 9px;
  border-radius: 5px;
  overflow: hidden;
  flex: 1;
  min-width: 0;
  border: 1px solid var(--rule-2);
}
.cd-mixbar i {
  display: block;
  height: 100%;
}
/* shared segment-color classes — used by both .cd-mixbar (bar) and
   .cd-mixkey (legend swatch) below, and available for the seat card's own
   future mix-bar markup too (same classes/colors/order, per the work order). */
.mix-sm {
  background: var(--bf-brand, oklch(0.4 0.155 262));
}
.mix-lg {
  background: var(--gold);
}
.mix-pac {
  background: var(--vote-red);
}
/* legend below the bar (Frame 1 item 1) — zero-width segments still get an
   entry (0% is information, per honest-data). */
.cd-mixkey {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin: 7px 16px 12px;
  font-size: 12.5px;
  color: var(--ink-2);
}
.cd-mixkey span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.cd-mixkey i {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  flex: 0 0 auto;
}
.cd-mixkey b {
  font-weight: 600;
  color: var(--ink);
}
.cd-mixkey .sub {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-3);
}

/* ---- per-card money-influence callout (NEW, Frame 1 item 2) — replaces the
   dead delegation-wide money band; same derivation + numbers as the card's
   own §2 money-verdict read (.mny-verdict below). Red/green matches this
   surface's existing .delegation .bar-good/.bar-bad convention (--keep/
   --replace), not .rep-card's locally-scoped --rc-keep/--vote-red aliases,
   since .cd-influence renders on the overview card, outside .rep-card. */
.cd-influence {
  margin: 0 16px 12px;
  padding: 12px 14px;
  background: var(--replace-soft, oklch(0.955 0.03 27));
  border: 1px solid oklch(0.88 0.06 27);
  border-radius: 11px;
}
.cd-influence.low {
  background: var(--keep-soft, oklch(0.95 0.035 159));
  border-color: oklch(0.86 0.06 159);
}
.cd-influence .k {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--replace);
  font-weight: 600;
}
.cd-influence.low .k {
  color: var(--keep);
}
.cd-influence .big {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin-top: 6px;
}
.cd-influence .big b {
  font-family: var(--serif);
  font-size: 27px;
  font-weight: 600;
  color: var(--replace);
  line-height: 1;
  letter-spacing: -0.01em;
}
.cd-influence.low .big b {
  color: var(--keep);
}
.cd-influence .big span {
  font-size: 12.5px;
  color: var(--ink-2);
  line-height: 1.4;
  flex: 1;
  min-width: 0;
}
.cd-influence .big span b {
  font-family: var(--sans);
  font-size: inherit;
  color: var(--ink);
  letter-spacing: 0;
}
.cd-influence .chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 9px;
}
.cd-influence .chips span {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
  padding: 3px 8px;
  border-radius: 999px;
  background: #fff;
  border: 1px solid oklch(0.88 0.06 27);
  color: var(--replace);
}
.cd-influence .chips .warn {
  color: oklch(0.5 0.13 66);
  border-color: oklch(0.85 0.09 76);
}
.cd-influence .chips .ok {
  color: var(--keep);
  border-color: oklch(0.86 0.06 159);
}
.cd-influence .chips .mut {
  color: var(--ink-3);
  border-color: var(--rule);
}

/* the card is now a button into the deep view */
.cd-card.dg-open {
  cursor: pointer;
  transition:
    box-shadow 0.13s ease,
    transform 0.13s ease;
}
.cd-card.dg-open:hover {
  box-shadow:
    0 0 0 2px var(--brand-soft),
    var(--shadow-card);
  transform: translateY(-2px);
}
.cd-card.dg-open:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
.cd-card.verdict-replace {
  border-color: var(--replace);
  box-shadow:
    0 0 0 2px var(--replace-soft),
    var(--shadow-soft);
}
.cd-card.verdict-replace .cd-select {
  color: var(--replace);
}
/* decided (keep) card: green-filled CTA needs white text for contrast */
.cd-card.is-pick .cd-select {
  color: var(--paper-2);
}

/* ---- excluded (non-2026) seat row ---- */
.dg-excluded {
  margin: 8px 30px 0;
  padding: 12px 16px;
  border: 1px dashed var(--rule);
  border-radius: 12px;
  background: var(--tag-bg);
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  /* No opacity here (was 0.85): it uniformly dilutes every child's contrast
     against the page, dropping even --ink (the app's darkest text token) to
     ~4.49:1 — under AA's 4.5:1. De-emphasis is already carried by the muted
     --tag-bg fill + dashed border + --ink-2/--ink-3 text tones below. */
  cursor: pointer;
}
.dg-excluded:hover {
  border-color: var(--ink-3);
}
.dg-excluded .ri {
  width: 28px;
  height: 28px;
  border-radius: 8px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  background: var(--rule);
  /* --ink-3 on --rule is ~3.5:1, under AA's 4.5:1 (--rule is darker than
     --tag-bg, so the .cv2-sub.blind fix's 0.5 isn't dark enough here —
     needs its own darker override). */
  color: oklch(0.44 0.026 260);
}
.dg-excluded .ex-meta {
  font-size: 13px;
  color: var(--ink-2);
}
.dg-excluded .ex-meta b {
  font-family: var(--serif);
  font-weight: 600;
  color: var(--ink);
}
.dg-excluded .ex-tag {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  /* --ink-3 on --tag-bg is ~4.4:1, just under AA's 4.5:1 — same fix as
     .cv2-sub.blind .cv2-tag. */
  color: oklch(0.5 0.026 260);
}
.dg-excluded-open {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--civic);
  white-space: nowrap;
  flex-shrink: 0;
}
.dg-excluded:hover .dg-excluded-open {
  text-decoration: underline;
}

/* ---- deep-view affordances layered on the reused rail/verdict chrome ---- */
.dg-deep .rc-back {
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 14px 7px 11px;
  border-radius: 999px;
  border: 1px solid var(--brand);
  background: var(--brand-soft);
  color: var(--brand);
  font-weight: 600;
  transition:
    background 0.12s ease,
    color 0.12s ease;
}
.dg-deep .rc-back:hover {
  background: var(--brand);
  color: var(--paper-2);
}
/* wraps the "← All seats" control above .tier-intro — NOT in the source
   (the design's version sits in a standalone .res-context strip this repo
   doesn't have); .rep-center-head is desktop-hidden (mobile-only back
   bar), so the back-to-overview control needs its own always-visible row. */
.dg-back-row {
  margin: 0 0 14px;
}

/* ---- Roster feedback ("Missing a rep? Something look wrong?") ----
   RosterFeedback.tsx — net-new surface, not a design-canvas port. Reuses
   the existing .be-modal-overlay/.be-modal chrome (HandoffModal.tsx/
   BudgetModal.tsx) for the dialog; these rules cover only the trigger row
   and the form fields that chrome doesn't already style. */
.rf-affordance-row {
  display: flex;
  justify-content: center;
  padding: 10px 16px;
}
.rf-trigger {
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-3);
  background: none;
  border: none;
  border-bottom: 1px dashed var(--rule);
  cursor: pointer;
  padding: 2px 0;
}
.rf-trigger:hover {
  color: var(--brand);
  border-bottom-color: var(--brand);
}
.rf-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 12px;
}
.rf-row {
  display: flex;
  gap: 12px;
}
.rf-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
}
.rf-field-narrow {
  flex: 0 0 72px;
}
.rf-field-lab {
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.rf-textarea,
.rf-input {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink);
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: 8px;
  padding: 8px 10px;
}
.rf-textarea {
  min-height: 90px;
  resize: vertical;
}
.rf-textarea:focus,
.rf-input:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}
.rf-submit {
  align-self: flex-start;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 13.5px;
  color: var(--paper-2);
  background: var(--brand);
  border: none;
  border-radius: 999px;
  padding: 9px 18px;
  cursor: pointer;
}
.rf-submit:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.rf-success {
  color: var(--civic-2);
  font-weight: 600;
}
.rf-error {
  color: var(--vote-red);
  font-size: 13px;
}
