/* ICAN Voter Tool — Accessible mode, light theme.
   Candidate rows are mini-dashboards: sectioned header / body / infobar.
   Score + IFF live in the bottom infobar. Sparse data is handled gracefully
   with a "Not available" state. */

:root {
  --ican-red: #EC1A33;
  --crimson: #AE0112;
  --ican-blue: #2D6DE5;
  --navy-blue: #0D1E40;
  --carbon: #232323;
  --white: #FFFFFF;
  --off-white: #FBFBFD;
  --cool-white: #F5F5FF;

  --gray-50: #FAFAFA;
  --gray-100: #F4F4F5;
  --gray-150: #EEEEF0;
  --gray-200: #E4E4E7;
  --gray-300: #D4D4D8;
  --gray-400: #A1A1AA;
  --gray-500: #71717A;
  --gray-600: #52525B;
  --gray-700: #3F3F46;
  --gray-800: #27272A;
  --gray-900: #18181B;

  --party-dem: #2563EB;
  --party-rep: #DC2626;
  --party-npp: #71717A;

  --iff-strong-allied: #059669;
  --iff-allied:        #10B981;
  --iff-leans-allied:  #34D399;
  --iff-neutral:       #A1A1AA;
  --iff-leans-hostile: #F59E0B;
  --iff-hostile:       #F97316;
  --iff-strong-hostile:#EF4444;

  --row-allied-bg:       #F0FDF4;
  --row-leans-allied-bg: #F0FDF4;
  --row-neutral-bg:      var(--gray-50);
  --row-hostile-bg:      #FEF2F2;
  --row-leans-hostile-bg:#FFFBEB;

  --infobar-allied:       #ECFDF5;
  --infobar-leans-allied: #F0FDF4;
  --infobar-neutral:      #FAFAFA;
  --infobar-leans-hostile:#FFFBEB;
  --infobar-hostile:      #FEF2F2;
  --infobar-endorse:      #ECFDF5;
  --infobar-oppose:       #FEF2F2;
  --infobar-monitor:      #FFFBEB;
  --infobar-unavailable:  #FAFAFA;

  --endorse-accent: #10B981;
  --oppose-accent:  #EC1A33;
  --monitor-accent: #FB8C00;

  --font-primary: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-mono: "JetBrains Mono", monospace;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.06);
  --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 2px rgba(0, 0, 0, 0.03);
  --shadow-lg: 0 10px 32px rgba(0, 0, 0, 0.08);
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  font-family: var(--font-primary);
  background: var(--white);
  color: var(--carbon);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
}

a { color: var(--ican-red); text-decoration: none; transition: color 0.15s; }
a:hover { color: var(--crimson); }

button { font-family: inherit; cursor: pointer; border: 0; background: none; }
input { font-family: inherit; }

.page { max-width: 820px; margin: 0 auto; padding: 32px 24px 96px; }

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 32px; background: var(--white);
  border-bottom: 1px solid var(--gray-150);
}
.topbar__brand {
  display: flex; align-items: center; gap: 14px;
  min-width: 0;
}
.topbar__logo {
  height: 30px; width: auto; display: block;
  flex-shrink: 0;
}
.topbar__divider {
  font-family: var(--font-primary);
  color: var(--gray-300);
  font-size: 22px;
  font-weight: 200;
  line-height: 1;
}
.topbar__title {
  font-family: var(--font-mono);
  font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.18em;
  color: var(--gray-700);
  white-space: nowrap;
}
.topbar__donate {
  background: var(--ican-red); color: var(--white);
  padding: 9px 18px; border-radius: 6px;
  font-family: var(--font-mono); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.18em;
  text-decoration: none;
  transition: background 0.15s, transform 0.1s;
  flex-shrink: 0;
}
.topbar__donate:hover { background: var(--crimson); }
.topbar__donate:active { transform: scale(0.98); }
/* Legacy class kept for safety */
.topbar__label { display: none; }

/* ---- Hero ---- */

.hero { padding: 72px 0 48px; }
.hero__overline {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.15em; color: var(--ican-red);
  margin-bottom: 28px; display: flex; align-items: center; gap: 12px;
}
.hero__overline::before {
  content: ""; display: inline-block; width: 40px; height: 2px;
  background: var(--ican-red);
}
.hero__title {
  font-size: 56px; font-weight: 700; letter-spacing: -0.035em;
  line-height: 1.02; color: var(--carbon); margin-bottom: 20px;
}
.hero__subtitle {
  font-size: 20px; color: var(--gray-600); line-height: 1.55;
  margin-bottom: 14px; max-width: 620px; font-weight: 400; letter-spacing: 0.005em;
}
.hero__expansion {
  font-family: var(--font-mono);
  font-size: 12px; color: var(--gray-500); line-height: 1.55;
  margin-bottom: 36px; max-width: 620px;
  letter-spacing: 0.04em;
}

.address-form {
  display: flex; flex-direction: column; gap: 14px;
  margin-bottom: 20px; max-width: 560px;
}
.address-form__label {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--gray-500);
}
.address-form__input {
  background: var(--white); border: 1px solid var(--gray-300);
  border-radius: 10px; color: var(--carbon); padding: 16px 18px;
  font-size: 17px; line-height: 1.4; box-shadow: var(--shadow-sm);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.address-form__input::placeholder { color: var(--gray-400); }
.address-form__input--zip { max-width: 200px; letter-spacing: 0.06em; }
.address-form__input:focus {
  outline: none; border-color: var(--ican-red);
  box-shadow: 0 0 0 4px rgba(236, 26, 51, 0.12);
}
.address-form__submit {
  background: var(--ican-red); color: var(--white); padding: 16px 32px;
  font-weight: 600; font-size: 16px; border-radius: 10px;
  align-self: flex-start; transition: background 0.15s, transform 0.1s;
}
.address-form__submit:hover { background: var(--crimson); }
.address-form__submit:active { transform: scale(0.98); }
.address-form__submit:disabled { opacity: 0.5; cursor: not-allowed; transform: none; }
.hero__privacy {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.02em;
  color: var(--gray-500); max-width: 560px; line-height: 1.6;
}

/* ---- Status banners ---- */

.status {
  padding: 14px 18px; border-radius: 8px; font-family: var(--font-mono);
  font-size: 13px; margin: 20px 0; max-width: 560px;
}
.status--error {
  background: var(--row-hostile-bg); border-left: 3px solid var(--ican-red);
  color: var(--iff-strong-hostile);
}

/* ---- Loading status — clean white card with red top accent (matches the
        save-share panel vibe). Pulsing red dot keeps the in-progress signal. */

.status--loading {
  background: var(--white);
  color: var(--carbon);
  padding: 16px 20px;
  border: 1px solid var(--gray-200);
  border-radius: 12px;
  font-family: var(--font-primary);
  position: relative;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
}
.status--loading::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--ican-red);
}

.status__label {
  font-family: var(--font-primary);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--gray-700);
  margin-bottom: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  line-height: 1;
}
.status__label::before {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--ican-red);
  box-shadow: 0 0 6px rgba(236, 26, 51, 0.80),
              0 0 14px rgba(236, 26, 51, 0.40);
  animation: status-pulse 1.4s ease-in-out infinite;
}
@keyframes status-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.45; transform: scale(1.35); }
}

@keyframes status-cursor-blink {
  to { opacity: 0; }
}

/* ---- Live countdown pill (in ballot header voter section) ---- */
.ballot-header__countdown {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-left: 10px;
  padding: 3px 10px 3px 9px;
  border-radius: 999px;
  background: rgba(236, 26, 51, 0.09);
  color: var(--ican-red);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  vertical-align: 1px;
}
.ballot-header__countdown::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ican-red);
  flex-shrink: 0;
  animation: ican-countdown-pulse 1.6s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes ican-countdown-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.7); }
}

/* ---- Ballot header — official-ballot styling ---- */

.ballot-header {
  margin: 48px 0 36px;
  padding-bottom: 32px;
  border-bottom: 1px solid var(--gray-150);
  /* Sticky topbar (~62px) sits over the page top — give scroll-into-view a
     buffer so the headline isn't clipped behind it. */
  scroll-margin-top: 88px;
}

/* Typewriter address in the ballot header.
   Cursor is a thin red bar that blinks via the existing keyframes. We reserve
   visible space for the address line so the row doesn't reflow as text fills. */
.ballot-header__value--typing {
  display: inline-flex;
  align-items: baseline;
  min-width: 1em;
}
.ballot-header__cursor {
  display: inline-block;
  width: 2px;
  height: 1em;
  background: var(--ican-red);
  margin-left: 2px;
  vertical-align: -0.12em;
  animation: status-cursor-blink 1s steps(2, start) infinite;
}
.ballot-header__overline {
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.2em;
  color: var(--ican-red);
  margin-bottom: 14px;
  display: flex; align-items: center; gap: 12px;
}
.ballot-header__overline::before {
  content: ""; display: inline-block;
  width: 40px; height: 2px;
  background: var(--ican-red);
}
.ballot-header__title {
  font-size: 48px; font-weight: 700;
  letter-spacing: -0.03em; line-height: 1.02;
  color: var(--carbon);
  margin-bottom: 6px;
}
.ballot-header__subtitle {
  font-size: 16px;
  color: var(--gray-600);
  margin-bottom: 28px;
  font-weight: 400;
}
.ballot-header__voter {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 8px 20px;
  padding: 16px 20px;
  background: var(--gray-50);
  border-left: 3px solid var(--carbon);
  margin-bottom: 24px;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.4;
}
.ballot-header__label {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--gray-500);
}
.ballot-header__value {
  color: var(--carbon);
  font-weight: 500;
}
.ballot-header__explainer {
  font-size: 22px;
  line-height: 1.4;
  color: var(--carbon);
  max-width: 720px;
  font-weight: 500;
  letter-spacing: -0.01em;
}
.ballot-header__explainer .ican-green { color: var(--endorse-accent); font-weight: 700; }
.ballot-header__explainer .ican-red   { color: var(--oppose-accent);  font-weight: 700; }

/* ---- Score-scale gauge ------------------------------------------------ */
/* Tactical-IFF-style interactive score scale: gradient bar (−3 hostile red
   → +3 aligned green) with a draggable slider thumb on the bar and a live
   mini score-cap chip to the right that updates numerically + by band-tint
   as the slider moves. The gradient stops match the 7-tier color scale used
   on candidate score caps elsewhere. */
.scale-viz {
  /* --score-color is set dynamically by initScaleVizSlider() based on the
     current slider band. Thumb border + chip border both read from it,
     so the two elements visually unify with the bar position at any score. */
  --score-color: #34D399;
  margin: 4px 0 10px;
  max-width: 720px;
}
.scale-viz__header {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 8px;
}
.scale-viz__intro {
  flex: 1 1 0;
  min-width: 0;
  /* Notice-style: monospace, all caps, justified — reads as a regulatory
     disclosure rather than ad copy. 8px + tight leading packs into ~3
     lines on mobile and 2 on desktop, balancing the chip height. */
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 8px;
  line-height: 1.5;
  letter-spacing: 0;
  text-transform: uppercase;
  text-align: justify;
  color: var(--gray-600, #4b5563);
  margin: 0;
  align-self: center;
}
.scale-viz__intro a { text-transform: uppercase; }
.scale-viz__gauge {
  position: relative;
}
.scale-viz__bar {
  position: relative;
  height: 12px;  /* labels live below the bar now, so bar can be slim */
  border-radius: 6px;
  background: linear-gradient(to right,
    #EC1A33 0%,      /*  −3 strong hostile */
    #FB8C00 16.66%,  /*  −2 hostile */
    #FDD835 33.33%,  /*  −1 leans hostile */
    #FFFFFF 50%,     /*   0 neutral */
    #B0E8D5 66.66%,  /*  +1 leans allied */
    #61D1AC 83.33%,  /*  +2 allied */
    #10B981 100%     /*  +3 strong allied */
  );
  border: 1px solid rgba(15, 23, 42, 0.12);
  overflow: hidden;
}
/* Light sweep — a moving white gradient that crosses the bar once on
   render to draw the eye to the full range of the scale. Sized wider
   than the bar with a translateX past 100% so the trailing edge clears
   the right side fully. Single iteration; lives behind the labels. */
.scale-viz__sweep {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 28%;
  background: linear-gradient(
    to right,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.7) 50%,
    rgba(255, 255, 255, 0) 100%
  );
  transform: translateX(-100%);
  animation: scale-viz-sweep 2.6s cubic-bezier(0.22, 0.61, 0.36, 1) 0.6s 1 forwards;
  pointer-events: none;
  mix-blend-mode: screen;
}
@keyframes scale-viz-sweep {
  0%   { transform: translateX(-100%); opacity: 0; }
  10%  { opacity: 1; }
  90%  { opacity: 1; }
  100% { transform: translateX(370%); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .scale-viz__sweep { animation: none; opacity: 0; }
}

.scale-viz__ticks {
  display: flex;
  justify-content: space-between;
  /* Ticks now sit ABOVE the bar — small, monospaced, color-tinted at the
     extremes so the numeric scale reads as a header on the gauge. */
  margin: 0 0 4px 0;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9px;
  font-weight: 600;
  color: var(--gray-500, #6b7280);
  padding: 0 2px;
}
.scale-viz__tick {
  text-align: center;
  flex: 1;
  letter-spacing: 0.04em;
}
.scale-viz__tick:first-child { text-align: left;  color: var(--oppose-accent, #EC1A33); font-weight: 700; }
.scale-viz__tick:last-child  { text-align: right; color: var(--endorse-accent, #10B981); font-weight: 700; }

/* Band labels — sit BELOW the gradient bar in normal flow. Each label is
   colored to match the gradient region above it (tone-on-tone), so the
   text-color encodes the same signal as the bar position. Saves having
   to compete with the slider thumb / sweep for space inside the bar. */
.scale-viz__bands {
  display: flex;
  margin-top: 5px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1;
}
.scale-viz__band {
  flex: 1;
  text-align: center;
  padding: 0 1px;
  white-space: nowrap;
}
.scale-viz__band--strong-hostile { color: #B91C1C; }
.scale-viz__band--hostile        { color: #C2410C; }
.scale-viz__band--leans-hostile  { color: #B45309; }
.scale-viz__band--neutral        { color: var(--gray-600, #4b5563); }
.scale-viz__band--leans-allied   { color: #047857; }
.scale-viz__band--allied         { color: var(--iff-allied, #10B981); }
.scale-viz__band--strong-allied  { color: var(--iff-strong-allied, #059669); }

/* (.scale-viz__prompt removed — animation demonstrates interactivity.) */

/* ---- Slider thumb on the gradient bar ---- */
/* Native range input, transparent track (the gradient bar IS the track),
   custom-styled thumb that sits over the bar. Z-index above the bar so
   the thumb is the click target. */
.scale-viz__slider {
  position: absolute;
  /* Slider thumb (22px) centers on the 12px bar. Offset = tick-row
     height + gap (~17px) − (thumb − bar) / 2 (~5px) = 12px from the
     gauge top. Bar sits at 17px–29px; slider at 12px–34px puts thumb
     center at 23px = bar center. */
  top: 12px;
  left: -1px;
  right: -1px;
  width: calc(100% + 2px);
  height: 22px;
  margin: 0;
  padding: 0;
  background: transparent;
  -webkit-appearance: none;
     -moz-appearance: none;
          appearance: none;
  cursor: grab;
  z-index: 3;
  outline: none;
}
.scale-viz__slider:active { cursor: grabbing; }
.scale-viz__slider::-webkit-slider-runnable-track {
  background: transparent;
  height: 22px;
  border: 0;
}
.scale-viz__slider::-moz-range-track {
  background: transparent;
  height: 22px;
  border: 0;
}
.scale-viz__slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  border: 1.5px solid var(--score-color);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.22);
  cursor: grab;
  margin-top: 0;
  transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.18s ease;
}
.scale-viz__slider::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: #fff;
  border: 1.5px solid var(--score-color);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.22);
  cursor: grab;
  transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.18s ease;
}
.scale-viz__slider:hover::-webkit-slider-thumb,
.scale-viz__slider:focus-visible::-webkit-slider-thumb {
  transform: scale(1.08);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
}
.scale-viz__slider:hover::-moz-range-thumb,
.scale-viz__slider:focus-visible::-moz-range-thumb {
  transform: scale(1.08);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.3);
}

/* ---- Live demo chip ---- */
/* Same proportions as the per-candidate score cap on the right side of
   each card so voters see the visual match at a glance. As the slider
   moves, JS adds a `--<band>` modifier that tints the chip with the
   identical palette used on real cards. */
.scale-viz__chip {
  flex: 0 0 auto;
  /* Fixed width so the chip doesn't jiggle as the band label cycles
     through "Allied" / "Strong Allied" / "Leans Hostile" / etc. Width
     sized to comfortably hold the widest label ("Strong Hostile") with
     padding and the score number above. */
  width: 108px;
  padding: 6px 8px;
  text-align: center;
  border-radius: 8px;
  background: var(--gray-50, #f9fafb);
  /* Border follows the slider position via the shared --score-color var. */
  border: 1px solid var(--score-color);
  transition: background-color 0.18s ease, border-color 0.18s ease;
}
.scale-viz__chip-label {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 7px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gray-500, #6b7280);
  margin-bottom: 2px;
}
.scale-viz__chip-value {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 20px;
  font-weight: 700;
  line-height: 1;
  /* Text color tracks the slider position via the same --score-color var
     that drives the thumb + chip borders, matching .candidate__cap-score-
     value styling on real candidate cards. */
  color: var(--score-color);
  font-variant-numeric: tabular-nums;
  transition: color 0.18s ease;
}
/* Band label below the score (Neutral / Leans Allied / Allied / Strong
   Allied / etc.) — small, monospace, color-tracks the score via the
   shared --score-color var so the chip's label, number, and border
   all shift together as the slider moves. */
.scale-viz__chip-band {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 8px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--score-color);
  margin-top: 4px;
  transition: color 0.18s ease;
  white-space: nowrap;
}
/* Band tints — soft background fill only; border is driven by --score-color
   set on the .scale-viz root by the slider handler. Print-color-adjust:
   exact applied in @media print to preserve the tint on the printed chip. */
.scale-viz__chip--strong-allied  { background: rgba(16,185,129,0.18); }
.scale-viz__chip--allied         { background: rgba(16,185,129,0.13); }
.scale-viz__chip--leans-allied   { background: rgba(52,211,153,0.13); }
.scale-viz__chip--neutral        { background: var(--gray-50, #f9fafb); }
.scale-viz__chip--leans-hostile  { background: rgba(245,158,11,0.14); }
.scale-viz__chip--hostile        { background: rgba(249,115,22,0.16); }
.scale-viz__chip--strong-hostile { background: rgba(239,68,68,0.18);  }

/* (Single-word band labels fit easily at every viewport — no special
   mobile stacking needed.) */
@media (max-width: 480px) {
  /* On the narrowest screens, drop the inner tick numbers (−2/−1/+1/+2)
     and keep only the extremes and zero — labels would otherwise crowd. */
  .scale-viz__tick:nth-child(2),
  .scale-viz__tick:nth-child(3),
  .scale-viz__tick:nth-child(5),
  .scale-viz__tick:nth-child(6) {
    visibility: hidden;
  }
}

.ballot-header__footnote {
  font-size: 11px;
  line-height: 1.5;
  color: var(--gray-500);
  max-width: 720px;
  margin-top: 10px;
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
}
.ballot-header__research-link {
  color: var(--navy-blue);
  font-weight: 700;
  text-decoration: underline;
  text-decoration-color: var(--gray-300);
  text-underline-offset: 2px;
}
.ballot-header__research-link:hover {
  color: var(--ican-blue);
  text-decoration-color: var(--ican-blue);
}
.ballot-header__footnote--score {
  margin-top: 4px;
  padding-top: 8px;
  border-top: 1px dashed var(--gray-200, #E5E7EB);
}
.ballot-header__info {
  display: inline-block;
  margin-right: 4px;
  color: var(--ican-blue, #2D6DE5);
  font-weight: 700;
}
.ballot-header__prelim {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 3px;
  background: var(--gray-100, #F3F4F6);
  color: var(--carbon, #232323);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 9px;
}
.ballot-header__lock {
  display: inline-block;
  font-size: 10px;
  filter: saturate(0);
  opacity: 0.7;
  margin-right: 1px;
}

/* Contest title row — title on the left, race-analysis link inline right */
.contest__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 8px;
}
.contest__head .contest__title { margin-bottom: 0; }
.contest__head-divider {
  color: var(--gray-300);
  font-size: 18px;
  line-height: 1;
  font-weight: 200;
}

/* Small inline race-analysis link — same scale as the per-candidate
   Full Profile link, sits to the right of the contest title */
.contest__research-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--navy-blue);
  text-decoration: none;
}
.contest__research-link:hover {
  color: var(--ican-blue);
  text-decoration: underline;
}

/* Legacy results-header classes — vestigial, hidden */
.results-header,
.results-header__label,
.results-header__address,
.results-header__title,
.results-header__meta { display: none; }

/* ---- Contest card (wrapper around candidate mini-dashboards) ---- */

.contest {
  background: var(--white); border: 1px solid var(--gray-150);
  border-radius: 14px; padding: 28px 28px 20px; margin-bottom: 20px;
  box-shadow: var(--shadow-sm);
}
.contest__level {
  font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.15em; color: var(--ican-red);
  margin-bottom: 10px;
}
.contest__title {
  font-size: 24px; font-weight: 600; letter-spacing: -0.015em;
  line-height: 1.25; color: var(--carbon); margin-bottom: 8px;
}
.contest__subtitle {
  font-family: var(--font-mono); font-size: 11px; color: var(--gray-500);
  letter-spacing: 0.04em; line-height: 1.55; margin-bottom: 24px;
}

.contest__empty {
  font-family: var(--font-mono); font-size: 11px; color: var(--gray-500);
  letter-spacing: 0.05em; line-height: 1.55;
  padding: 12px 14px;
  background: var(--gray-50);
  border-radius: 8px;
  text-align: center;
}

.measure__title {
  margin: 0 0 18px;
  color: var(--gray-700, #374151);
  font-size: 15px;
  line-height: 1.55;
}
.measure__position {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 14px;
  border-left: 4px solid var(--navy-blue);
  border-radius: 6px;
  background: var(--gray-50);
}
.measure__position--yes { border-left-color: #047857; }
.measure__position--no { border-left-color: var(--ican-red); }
.measure__position-label {
  color: var(--gray-600);
  font: 600 10px var(--font-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
}
.measure__position-value {
  color: var(--navy-blue);
  font-size: 20px;
  text-transform: uppercase;
}
.measure__source {
  display: inline-block;
  margin-top: 12px;
  color: var(--ican-blue);
  font: 600 11px var(--font-mono);
}

/* November Preview — for contests not on June 2 ballot but staged for Nov 3, 2026 */
.contest--preview {
  border-left: 4px solid #6b21a8;
  background: #faf5ff;
}
.contest__preview-badge {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #6b21a8;
  background: #f3e8ff;
  border: 1px solid #c084fc;
  padding: 4px 10px;
  border-radius: 4px;
  margin-bottom: 10px;
  text-transform: uppercase;
}

/* ================================================================
   CANDIDATE CARD — LCARS-style capsule
     .candidate                 — flex row, rounded pill-like container
       .candidate__cap--action  — LEFT end-cap: solid colored action label
       .candidate__content      — MIDDLE: name + party + tags + research
       .candidate__cap--score   — RIGHT end-cap: ICAN Index™ + score
   ================================================================ */

/* The whole card is a link — clickable surface for Research page */
a.candidate { text-decoration: none; color: inherit; }

.candidate {
  display: flex;
  align-items: stretch;
  background: var(--white);
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  overflow: hidden;
  margin-bottom: 8px;
  box-shadow: var(--shadow-card);
  min-height: 78px;
  transition: box-shadow 0.15s, transform 0.1s;
}
a.candidate:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}
.candidate:last-child { margin-bottom: 4px; }

/* Party strip lives inside the action cap (bottom strip) — see below */
.candidate__party-strip { display: none; }

/* ---- LEFT cap: action (only when ICAN has taken a position) ---- */

/* Action cap — always present. Same width across all states for visual rhythm.
   Body + party strip stacked vertically. */
.candidate__cap--action {
  display: flex;
  flex-direction: column;
  width: 92px;
  flex-shrink: 0;
  text-align: center;
  font-family: var(--font-mono);
  overflow: hidden;
}
.candidate__cap-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 8px 6px;
}
/* The cap body is ALWAYS white — the bubble lives inside like a real ballot.
   The mark (check/X) is drawn across the bubble for rated candidates. */
.candidate__cap-body {
  background: var(--white);
  color: var(--carbon);
}

/* Ballot bubble — outlined circle. Color matches the mark for rated cards
   so endorsed/opposed read as a unified color signal. Real-ballot size. */
.candidate__cap-bubble {
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 2px solid var(--carbon);
  background: var(--white);
  position: relative;
  flex-shrink: 0;
}
.candidate--pos-endorse .candidate__cap-bubble {
  border-color: var(--endorse-accent);
  box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
}
.candidate--pos-oppose .candidate__cap-bubble {
  border-color: var(--oppose-accent);
  box-shadow: 0 0 0 3px rgba(236, 26, 51, 0.1);
}
.candidate--pos-monitor .candidate__cap-bubble {
  border-color: var(--monitor-accent);
  box-shadow: 0 0 0 3px rgba(251, 140, 0, 0.1);
}

/* Mark SVG — centered on the bubble, no rotation (rotation was making them
   read as misaligned). Oversized enough to extend past the bubble edge
   symmetrically for a bold "drawn across" feel. */
.candidate__cap-mark {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.candidate--pos-endorse .candidate__cap-mark {
  color: var(--endorse-accent);
  width: 36px; height: 36px;
}
.candidate--pos-oppose .candidate__cap-mark {
  color: var(--oppose-accent);
  width: 32px; height: 32px;
}
.candidate--pos-monitor .candidate__cap-mark {
  color: var(--monitor-accent);
  width: 28px; height: 28px;
}

/* Bottom strip — WHITE for rated, CARBON (with "WATCH") for unrated.
   Party text colored by party on rated cards. */
.candidate__cap-party {
  padding: 4px;
  font-family: var(--font-mono);
  font-size: 9px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.2em;
  line-height: 1;
  text-align: center;
  flex-shrink: 0;
  border-top: 1px solid var(--gray-150);
  background: var(--white);
}
.candidate--party-dem  .candidate__cap-party { color: var(--party-dem); }
.candidate--party-rep  .candidate__cap-party { color: var(--party-rep); }
.candidate--party-npp  .candidate__cap-party { color: var(--gray-500); }
.candidate--party-none .candidate__cap-party { color: var(--gray-500); }

/* Unrated overrides — "WATCH" label in white on carbon */
.candidate--unrated .candidate__cap-party {
  background: var(--carbon);
  color: var(--white);
  border-top: none;
}

/* ---- RIGHT cap: ICAN Index score (only when we have a score) ---- */

.candidate__cap--score {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 8px 14px;
  min-width: 92px;
  border-left: 1px solid var(--gray-150);
  text-align: center;
  position: relative;
}
.candidate--has-score .candidate__cap--score { display: flex; }

/* Flat tint per IFF band */
.candidate--strong-allied   .candidate__cap--score { background: rgba(16,185,129,0.1); }
.candidate--allied          .candidate__cap--score { background: rgba(16,185,129,0.09); }
.candidate--leans-allied    .candidate__cap--score { background: rgba(52,211,153,0.09); }
.candidate--neutral         .candidate__cap--score { background: var(--gray-50); }
.candidate--leans-hostile   .candidate__cap--score { background: rgba(245,158,11,0.1); }
.candidate--hostile         .candidate__cap--score { background: rgba(249,115,22,0.1); }
.candidate--strong-hostile  .candidate__cap--score { background: rgba(239,68,68,0.1); }

.candidate__cap-index-label {
  font-family: var(--font-mono); font-size: 8px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.2em;
  color: var(--gray-500); line-height: 1;
}
.candidate__cap-score-value {
  font-family: var(--font-mono); font-size: 22px; font-weight: 700;
  letter-spacing: -0.025em; line-height: 1;
}
.candidate--strong-allied   .candidate__cap-score-value { color: var(--iff-strong-allied); }
.candidate--allied          .candidate__cap-score-value { color: var(--iff-allied); }
.candidate--leans-allied    .candidate__cap-score-value { color: #047857; }
.candidate--neutral         .candidate__cap-score-value { color: var(--gray-600); }
.candidate--leans-hostile   .candidate__cap-score-value { color: #B45309; }
.candidate--hostile         .candidate__cap-score-value { color: #C2410C; }
.candidate--strong-hostile  .candidate__cap-score-value { color: var(--iff-strong-hostile); }

/* ---- MIDDLE content ---- */

.candidate__content {
  flex: 1;
  min-width: 0;
  padding: 10px 14px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
}

.candidate__name-row {
  display: flex; align-items: flex-end; gap: 8px;
  min-width: 0;
}
.candidate__name {
  font-size: 17px; font-weight: 600;
  letter-spacing: -0.015em; line-height: 1.2;
  color: var(--carbon);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0;
}
/* Party moved to cap — inline party element suppressed */
.candidate__party { display: none; }
.candidate__incumbent { display: none; }

/* Incumbent tag inline with name, small */
/* All in-row tags (INCUMBENT, ICAN ENDORSED, OPPOSED) use the same compact
   size as the signal-flag pills (.flag, e.g. PRELIMINARY) for visual rhythm.
   Solid color and outlined variants share font + padding; only the bg/border
   differs. */
.candidate__incumbent-inline {
  font-family: var(--font-mono);
  font-size: 7px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  line-height: 1.2;
  color: var(--gray-500);
  padding: 2px 5px;
  border: 1px solid var(--gray-300);
  border-radius: 3px;
  flex-shrink: 0;
}
.candidate__ican-tag {
  font-family: var(--font-mono);
  font-size: 7px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  line-height: 1.2;
  color: var(--white);
  padding: 2px 5px;
  border: 1px solid transparent;
  border-radius: 3px;
  flex-shrink: 0;
}
.candidate__ican-tag--endorse { background: var(--endorse-accent); }
.candidate__ican-tag--oppose  { background: var(--oppose-accent); }
.candidate__ican-tag--monitor { background: var(--monitor-accent); }

/* Footer row — Full Profile link + (optional) Also: + partner pills.
   Scrolls horizontally like the signal flag row above when there are many
   partners. Right edge fades to hint there's more to scroll. */
.candidate__partners {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  line-height: 1;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  mask-image: linear-gradient(to right, black calc(100% - 18px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 18px), transparent 100%);
}
.candidate__partners::-webkit-scrollbar { display: none; }
/* Children must not shrink — they keep their full size and the row scrolls */
.candidate__research-link,
.candidate__separator,
.candidate__partners-label,
.candidate__partner { flex-shrink: 0; }
.candidate__research-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--navy-blue);
  text-decoration: none;
  flex-shrink: 0;
}
.candidate__research-link:hover {
  color: var(--ican-blue);
  text-decoration: underline;
}
.candidate__research-link::before {
  content: "🔒";
  font-size: 10px;
  filter: saturate(0);
  opacity: 0.7;
}
.candidate__separator {
  display: inline-block;
  width: 1px;
  height: 11px;
  background: var(--gray-300);
  flex-shrink: 0;
}
.candidate__partners-label {
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--gray-500);
}
.candidate__partner {
  display: inline-flex; align-items: center;
  font-family: var(--font-mono);
  font-size: 8px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  padding: 3px 6px;
  border-radius: 3px;
  line-height: 1;
  color: var(--white);
  background: var(--navy-blue);  /* default for unknown partners */
  text-decoration: none;
  flex-shrink: 0;
  transition: transform 0.1s, box-shadow 0.1s;
}
.candidate__partner:hover,
.candidate__partner:visited,
.candidate__partner:active {
  color: var(--white);  /* override the global a:hover red */
}
.candidate__partner:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
}
/* Per-partner brand colors — only confirmed endorsing partners. Do NOT add
   org names here unless they have publicly endorsed in this race. Listing
   non-endorsing orgs creates legal/disclosure risk. */
.candidate__partner--ladywithabrain      { background: #3DB1EB; }   /* sky blue from her voter guide */
.candidate__partner--dfi                 { background: #1D3557; }   /* DFI Democratic navy (legacy slug) */
.candidate__partner--democratsforisraella { background: #1D3557; }   /* Democrats for Israel LA — Democratic navy */
.candidate__partner--thrivela            { background: #2D4868; }   /* navy from the Thrive LA wordmark */

/* Demo placeholder colors — illustrate variety as future partners come on. */
.candidate__partner--partnera { background: #6B7280; }   /* slate */
.candidate__partner--partnerb { background: #14B8A6; }   /* teal */
.candidate__partner--partnerc { background: #F97316; }   /* orange */
.candidate__partner--partnerd { background: #8B5CF6; }   /* violet */
.candidate__partner--partnere { background: #059669; }   /* emerald */
.candidate__partner--partnerf { background: #BE185D; }   /* magenta */

/* Tag bar — horizontally scrollable single line */
.candidate__flags-row {
  display: flex; gap: 3px; flex-wrap: nowrap;
  align-items: center;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  /* Fade the right edge to hint that content continues */
  mask-image: linear-gradient(to right, black calc(100% - 18px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 18px), transparent 100%);
}
.candidate__flags-row::-webkit-scrollbar { display: none; }
.flag {
  display: inline-flex; align-items: center;
  font-family: var(--font-mono); font-size: 7px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  padding: 2px 4px; border-radius: 2px; line-height: 1.2;
  white-space: nowrap; flex-shrink: 0;
  border: 1px solid transparent;
}
.flag::before { content: none !important; }
.flag--positive {
  background: rgba(16, 185, 129, 0.1); color: var(--iff-strong-allied);
  border-color: rgba(16, 185, 129, 0.3);
}
.flag--negative {
  background: rgba(236, 26, 51, 0.1); color: var(--iff-strong-hostile);
  border-color: rgba(236, 26, 51, 0.3);
}
.flag--warning {
  background: rgba(251, 140, 0, 0.1); color: #B45309;
  border-color: rgba(251, 140, 0, 0.3);
}
.flag--neutral {
  background: var(--white); color: var(--gray-600);
  border-color: var(--gray-300);
}
.flag--tp {
  background: var(--white); color: var(--navy-blue);
  border: 1px dashed var(--gray-300);
}

/* Research link row removed — the entire card IS the link now */
.candidate__research { display: none; }

/* No-data state */
.candidate__unavailable {
  font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.15em; color: var(--gray-500);
}

/* Kill all legacy hooks so nothing from earlier layouts leaks in */
.candidate__topbar,
.candidate__header,
.candidate__top,
.candidate__occupation,
.candidate__body,
.candidate__section,
.candidate__section-label,
.candidate__third-party,
.candidate__metrics,
.candidate__flags,
.candidate__infobar,
.candidate__infobar-left,
.candidate__infobar-right,
.candidate__action-label,
.candidate__action-icon,
.candidate__score-mini,
.candidate__score-value,
.candidate__iff-label,
.candidate__index-label,
.candidate__divider,
.candidate__tp-inline,
.candidate__links,
.candidate__link,
.candidate__link-note,
.candidate__meta,
.metric { display: none; }

/* ---- Header ---- */

.candidate__header {
  padding: 10px 16px 4px;
}

.candidate__top {
  display: flex; align-items: baseline; gap: 10px;
  flex-wrap: nowrap; overflow: hidden;
}
.candidate__name {
  font-size: 18px; font-weight: 600; color: var(--carbon);
  letter-spacing: -0.015em; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Party integrated inline — no badge, just colored mono tag */
.candidate__party {
  all: unset;
  font-family: var(--font-mono); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.15em; line-height: 1;
  flex-shrink: 0;
}
.candidate__party--dem   { color: var(--party-dem); }
.candidate__party--rep   { color: var(--party-rep); }
.candidate__party--npp,
.candidate__party--other { color: var(--gray-500); }

/* Vestigial */
.candidate__meta { display: none; }
.candidate__party {
  font-family: var(--font-mono); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.12em;
  padding: 3px 7px; border-radius: 3px; color: var(--white); line-height: 1;
}
.candidate__party--dem { background: var(--party-dem); }
.candidate__party--rep { background: var(--party-rep); }
.candidate__party--npp,
.candidate__party--other { background: var(--gray-500); }
.candidate__incumbent {
  font-family: var(--font-mono); font-size: 9px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.15em; color: var(--gray-600);
  padding: 3px 8px; border-radius: 3px; background: var(--white);
  border: 1px solid var(--gray-300);
}
/* Occupation removed per compact design */
.candidate__occupation { display: none; }

/* Hide legacy metric strip and sections; flag bar is visible again below */
.candidate__section-label,
.candidate__metrics,
.metric { display: none; }

/* ---- Tag bar (signal flags) — compact single line ---- */

.candidate__body {
  padding: 0 16px 4px;
  margin-top: 2px;
}
.candidate__section { display: block; margin: 0; }
.candidate__flags {
  display: flex;
  gap: 4px;
  flex-wrap: nowrap;
  overflow: hidden;
}
.flag {
  display: inline-flex; align-items: center;
  font-family: var(--font-mono); font-size: 9px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.12em;
  padding: 2px 6px; border-radius: 3px; line-height: 1.3;
  white-space: nowrap; flex-shrink: 0;
  border: 1px solid transparent;
}
.flag::before { content: none !important; }
.flag--positive {
  background: rgba(16, 185, 129, 0.1); color: var(--iff-strong-allied);
  border-color: rgba(16, 185, 129, 0.3);
}
.flag--negative {
  background: rgba(236, 26, 51, 0.1); color: var(--iff-strong-hostile);
  border-color: rgba(236, 26, 51, 0.3);
}
.flag--warning {
  background: rgba(251, 140, 0, 0.1); color: #B45309;
  border-color: rgba(251, 140, 0, 0.3);
}
.flag--neutral {
  background: var(--white); color: var(--gray-600);
  border-color: var(--gray-300);
}
/* Third-party inline chips disappear from body — they're in the infobar */
.candidate__third-party { display: none; }

/* ---- Body (sectioned) ---- */

.candidate__body {
  padding: 0 20px 14px;
}
.candidate__section {
  margin-top: 12px;
}
.candidate__section-label {
  font-family: var(--font-mono);
  font-size: 9px; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.15em; color: var(--gray-500);
  margin-bottom: 8px; display: flex; align-items: center; gap: 8px;
}
.candidate__section-label::after {
  content: ""; flex: 1; height: 1px; background: var(--gray-200);
}

.candidate__flags,
.candidate__third-party {
  display: flex; flex-wrap: wrap; gap: 6px;
}

.flag {
  /* Final cascade winner — kept aligned with .candidate__incumbent-inline and
     .candidate__ican-tag (7px, 2px 5px) so PRELIMINARY / DSA / etc. pills
     read as siblings in the same row, not visibly bigger. */
  font-family: var(--font-mono); font-size: 7px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  padding: 2px 5px;
  border-radius: 3px; line-height: 1.2; white-space: nowrap;
  border: 1px solid transparent;
  display: inline-flex; align-items: center; gap: 4px;
}
.flag::before {
  font-family: var(--font-mono); font-size: 7px; font-weight: 700;
  line-height: 1;
}
.flag--positive {
  background: rgba(16, 185, 129, 0.08); color: var(--iff-strong-allied);
  border-color: rgba(16, 185, 129, 0.28);
}
.flag--positive::before { content: "+"; }
.flag--negative {
  background: rgba(236, 26, 51, 0.08); color: var(--iff-strong-hostile);
  border-color: rgba(236, 26, 51, 0.28);
}
.flag--negative::before { content: "−"; }
.flag--warning {
  background: rgba(251, 140, 0, 0.08); color: #B45309;
  border-color: rgba(251, 140, 0, 0.3);
}
.flag--warning::before { content: "!"; }
.flag--neutral {
  background: var(--white); color: var(--gray-600); border-color: var(--gray-300);
}
.flag--neutral::before { content: "·"; }

.tp-endorsement {
  font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--gray-700); background: var(--white);
  border: 1px dashed var(--gray-300); padding: 3px 8px; border-radius: 3px;
}

/* ---- Metrics strip (key/value data points) ---- */

.candidate__metrics {
  display: flex; flex-wrap: wrap; gap: 14px;
  padding: 0 20px 12px;
}
.metric {
  display: inline-flex; align-items: baseline; gap: 6px;
}
.metric__key {
  font-family: var(--font-mono); font-size: 9px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.15em;
  color: var(--gray-500);
}
.metric__value {
  font-family: var(--font-mono); font-size: 13px; font-weight: 700;
  color: var(--carbon); letter-spacing: -0.01em;
}
.metric__note {
  font-family: var(--font-mono); font-size: 10px;
  color: var(--gray-500); letter-spacing: 0.02em; font-style: italic;
}

/* ---- Infobar (bottom — compact single row) ---- */

.candidate__infobar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 8px 16px;
  border-top: 1px solid var(--gray-150);
  background: var(--gray-50);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
}
.candidate--pos-endorse .candidate__infobar { background: var(--infobar-endorse); }
.candidate--pos-oppose  .candidate__infobar { background: var(--infobar-oppose); }
.candidate--pos-monitor .candidate__infobar { background: var(--infobar-monitor); }
.candidate--strong-allied   .candidate__infobar,
.candidate--allied          .candidate__infobar { background: var(--infobar-allied); }
.candidate--leans-allied    .candidate__infobar { background: var(--infobar-leans-allied); }
.candidate--neutral         .candidate__infobar { background: var(--infobar-neutral); }
.candidate--leans-hostile   .candidate__infobar { background: var(--infobar-leans-hostile); }
.candidate--hostile         .candidate__infobar,
.candidate--strong-hostile  .candidate__infobar { background: var(--infobar-hostile); }
.candidate--pos-endorse     .candidate__infobar { background: var(--infobar-endorse); }
.candidate--pos-oppose      .candidate__infobar { background: var(--infobar-oppose); }
.candidate--pos-monitor     .candidate__infobar { background: var(--infobar-monitor); }

.candidate__infobar-left {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  min-width: 0;
}
.candidate__infobar-right {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}

/* Score ring and IFF label are removed in compact mode — just the number */
.candidate__score-mini,
.candidate__iff-label,
.candidate__index-label { display: none; }

.candidate__score-value {
  font-family: var(--font-mono); font-size: 13px; font-weight: 700;
  letter-spacing: -0.01em; line-height: 1;
}
.candidate--strong-allied   .candidate__score-value { color: var(--iff-strong-allied); }
.candidate--allied          .candidate__score-value { color: var(--iff-allied); }
.candidate--leans-allied    .candidate__score-value { color: #047857; }
.candidate--neutral         .candidate__score-value { color: var(--gray-600); }
.candidate--leans-hostile   .candidate__score-value { color: #B45309; }
.candidate--hostile         .candidate__score-value { color: #C2410C; }
.candidate--strong-hostile  .candidate__score-value { color: var(--iff-strong-hostile); }

/* Action pill — prominent solid color block for ICAN endorsed / opposed */
.candidate__action-label {
  font-family: var(--font-mono); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.15em; line-height: 1;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 9px 5px 6px;
  border-radius: 4px;
  color: var(--white);
}
.candidate--pos-endorse .candidate__action-label { background: var(--endorse-accent); }
.candidate--pos-oppose  .candidate__action-label { background: var(--oppose-accent); }
.candidate--pos-monitor .candidate__action-label { background: var(--monitor-accent); }
.candidate__action-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.22);
  color: var(--white); font-size: 10px; font-weight: 700; line-height: 1;
}

.candidate__divider {
  color: var(--gray-300);
  font-family: var(--font-mono);
  font-size: 10px;
}

.candidate__index-label {
  font-family: var(--font-mono); font-size: 9px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.18em; color: var(--gray-500);
  margin-right: 2px;
}

.candidate__unavailable {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.15em; color: var(--gray-500);
}

.candidate__tp-inline {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  color: var(--gray-600); letter-spacing: 0.05em;
}

.candidate__link {
  font-family: var(--font-mono); font-size: 11px; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--ican-red);
  display: inline-flex; align-items: center; gap: 6px;
}
.candidate__link:hover { color: var(--crimson); }
.candidate__link--research { color: var(--navy-blue); }
.candidate__link--research:hover { color: var(--ican-blue); }
.candidate__link--research::before {
  content: "🔒"; font-size: 10px; filter: saturate(0); opacity: 0.7;
}
.candidate__link-note {
  font-family: var(--font-mono); font-size: 9px; color: var(--gray-500);
  letter-spacing: 0.05em; text-transform: uppercase;
}

/* ---- Save & Share — Apple-accessible, friendly, all Helvetica ----
   Public-facing email capture + viral share surface at the top of the ballot.
   No mono on this surface — the panel is the consumer-action moment, so it
   should feel warm, not tactical. Share buttons carry full platform branding
   (WhatsApp green, iMessage blue) for instant recognition. A floating save
   CTA appears when the panel scrolls out of view. */

.save-share {
  position: relative;
  margin: 0 0 28px;
  padding: 26px 28px 22px;
  background: var(--white);
  border: 1px solid var(--gray-200);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  /* Modal close → scrollIntoView(this) — buffer for sticky topbar. */
  scroll-margin-top: 88px;
}
.save-share::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--ican-red);
}
.save-share__head { margin-bottom: 16px; }

.save-share__eyebrow {
  font-family: var(--font-primary);
  font-size: 13px; font-weight: 600;
  letter-spacing: 0;
  color: var(--ican-red);
  margin-bottom: 8px;
  display: inline-flex; align-items: center; gap: 8px;
}
.save-share__eyebrow--saved { color: var(--endorse-accent); }

.save-share__title {
  font-family: var(--font-primary);
  font-size: 24px; font-weight: 600;
  letter-spacing: -0.015em; line-height: 1.2;
  color: var(--carbon);
  margin: 0;
}
.save-share__body {
  font-family: var(--font-primary);
  font-size: 15px; color: var(--gray-600);
  line-height: 1.55; margin: 8px 0 0;
  max-width: 56ch;
}

.save-share__form {
  display: grid; gap: 8px; align-items: stretch;
  grid-template-columns: 1fr;
}
.save-share__input {
  background: var(--gray-100);
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  color: var(--carbon);
  padding: 12px 14px;
  font-family: var(--font-primary);
  font-size: 15px;
  min-width: 0;
  box-shadow: inset 0 1px 0 rgba(15, 23, 42, 0.02);
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.save-share__input::placeholder { color: var(--gray-500); }
.save-share__input:hover {
  background: var(--white);
  border-color: var(--gray-300);
}
.save-share__input:focus {
  outline: none;
  background: var(--white);
  border-color: var(--ican-red);
  box-shadow: 0 0 0 3px rgba(236, 26, 51, 0.12),
              inset 0 1px 0 rgba(15, 23, 42, 0.02);
}
.save-share__submit {
  background: var(--ican-red); color: var(--white);
  padding: 12px 24px;
  font-family: var(--font-primary);
  font-weight: 600; font-size: 15px;
  letter-spacing: 0;
  border-radius: 10px;
  white-space: nowrap;
  transition: background 0.12s ease, transform 0.08s ease, box-shadow 0.15s ease;
  box-shadow: 0 1px 2px rgba(236, 26, 51, 0.18);
}
.save-share__submit:hover { background: var(--crimson); }
.save-share__submit:active { transform: scale(0.98); }

.save-share__consent {
  display: flex; gap: 9px; align-items: flex-start;
  font-family: var(--font-primary);
  font-size: 13px; font-weight: 400;
  letter-spacing: 0;
  color: var(--gray-600);
  margin-top: 12px;
  line-height: 1.45;
}
.save-share__consent input {
  width: 14px; height: 14px;
  margin-top: 2px;
  accent-color: var(--ican-red);
  flex-shrink: 0;
}
.save-share__error {
  margin-top: 12px;
  padding: 10px 14px;
  border-radius: 10px;
  background: rgba(236, 26, 51, 0.08);
  color: var(--ican-red);
  font-family: var(--font-primary);
  font-size: 14px; font-weight: 500;
}
.save-share--saved::before { background: var(--endorse-accent); }

/* Share row — Apple-style branded pills. Full capsule, subtle gradient depth
   on the colored buttons, no hover-color-flip (text + icon stay native), and
   a slight lift on hover instead of a jarring filter pop. */
.share-row {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 8px;
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--gray-100);
}
.save-share__share--post {
  margin-top: 14px;
  padding-top: 0;
  border-top: none;
}
.share-row__label {
  font-family: var(--font-primary);
  font-size: 13px; font-weight: 500;
  color: var(--gray-500);
  margin-right: 4px;
}
.share-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 16px;
  border: 1px solid transparent;
  border-radius: 999px;
  font-family: var(--font-primary);
  font-size: 14px; font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    transform 0.18s cubic-bezier(.2,.7,.3,1),
    box-shadow 0.18s ease,
    filter 0.18s ease,
    background 0.18s ease;
}
.share-btn:hover {
  transform: translateY(-1px);
  filter: brightness(1.04) saturate(1.04);
}
.share-btn:active {
  transform: translateY(0) scale(0.97);
  filter: brightness(0.96);
  transition-duration: 0.08s;
}
.share-btn__icon {
  width: 15px; height: 15px;
  flex-shrink: 0;
}

/* Native Web Share — only rendered on supporting browsers (iOS/Android,
   Safari/Chrome/Edge desktop). Carbon gradient distinguishes it from the
   colored channel-specific pills; iOS share glyph signals the system sheet. */
.share-btn--native {
  background: linear-gradient(180deg, #3D3D45 0%, #232323 100%);
  color: #fff;
  box-shadow:
    0 1px 1px rgba(15, 23, 42, 0.08),
    0 4px 10px -4px rgba(35, 35, 35, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
.share-btn--native .share-btn__icon { color: #fff; }
.share-btn--native:hover {
  color: #fff;
  box-shadow:
    0 1px 1px rgba(15, 23, 42, 0.08),
    0 6px 14px -4px rgba(35, 35, 35, 0.55),
    inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

.share-btn--whatsapp {
  background: linear-gradient(180deg, #2DDC72 0%, #1FBF5C 100%);
  color: #fff;
  box-shadow:
    0 1px 1px rgba(15, 23, 42, 0.05),
    0 4px 10px -4px rgba(31, 191, 92, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
.share-btn--whatsapp .share-btn__icon { color: #fff; }
.share-btn--whatsapp:hover {
  color: #fff;
  box-shadow:
    0 1px 1px rgba(15, 23, 42, 0.05),
    0 6px 14px -4px rgba(31, 191, 92, 0.55),
    inset 0 1px 0 rgba(255, 255, 255, 0.22);
}

.share-btn--imessage {
  background: linear-gradient(180deg, #3DA1FF 0%, #0A84FF 100%);
  color: #fff;
  box-shadow:
    0 1px 1px rgba(15, 23, 42, 0.06),
    0 4px 10px -4px rgba(10, 132, 255, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.24);
}
.share-btn--imessage .share-btn__icon { color: #fff; }
.share-btn--imessage:hover {
  color: #fff;
  box-shadow:
    0 1px 1px rgba(15, 23, 42, 0.06),
    0 6px 14px -4px rgba(10, 132, 255, 0.55),
    inset 0 1px 0 rgba(255, 255, 255, 0.24);
}

.share-btn--email {
  background: linear-gradient(180deg, #F22D47 0%, #D60E26 100%);
  color: #fff;
  box-shadow:
    0 1px 1px rgba(15, 23, 42, 0.06),
    0 4px 10px -4px rgba(236, 26, 51, 0.50),
    inset 0 1px 0 rgba(255, 255, 255, 0.22);
}
.share-btn--email .share-btn__icon { color: #fff; }
.share-btn--email:hover {
  color: #fff;
  box-shadow:
    0 1px 1px rgba(15, 23, 42, 0.06),
    0 6px 14px -4px rgba(236, 26, 51, 0.60),
    inset 0 1px 0 rgba(255, 255, 255, 0.22);
}

.share-btn--copy {
  background: var(--white);
  color: var(--carbon);
  border-color: var(--gray-200);
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.03);
}
.share-btn--copy .share-btn__icon { color: var(--gray-500); }
.share-btn--copy:hover {
  background: var(--gray-50);
  border-color: var(--gray-300);
  filter: none;
}
.share-btn--copy:hover .share-btn__icon { color: var(--carbon); }

/* ---- Floating Save CTA ----
   Sticky bottom-right button that appears when the save-share panel scrolls
   out of viewport. Tap returns the user to the form and focuses the email
   input. Hidden after the form is submitted. */
.floating-save {
  position: fixed;
  bottom: 22px;
  right: 22px;
  z-index: 100;
  display: inline-flex; align-items: center; gap: 9px;
  background: var(--ican-red);
  color: var(--white);
  font-family: var(--font-primary);
  font-size: 15px; font-weight: 600;
  letter-spacing: 0;
  padding: 14px 22px;
  border: none;
  border-radius: 999px;
  box-shadow: 0 8px 24px rgba(236, 26, 51, 0.32),
              0 2px 6px rgba(15, 23, 42, 0.10);
  cursor: pointer;
  opacity: 0;
  transform: translateY(20px);
  pointer-events: none;
  transition: opacity 0.28s ease, transform 0.28s ease, background 0.12s ease;
}
.floating-save--visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.floating-save:hover { background: var(--crimson); }
.floating-save:active { transform: translateY(0) scale(0.96); }
.floating-save__icon {
  width: 16px; height: 16px;
  flex-shrink: 0;
}

/* ---- Footer ---- */

.footer {
  margin-top: 72px; padding: 40px 0 0; border-top: 1px solid var(--gray-150);
  font-family: var(--font-mono); font-size: 11px; line-height: 1.8;
  color: var(--gray-500); letter-spacing: 0.02em;
}
.footer__paid-for-by { color: var(--gray-700); margin-bottom: 16px; }
.footer__links { display: flex; flex-wrap: wrap; gap: 20px; }
.footer__links a { color: var(--gray-600); }
.footer__links a:hover { color: var(--ican-red); }

/* ---- Save modal — full-screen overlay launched by the floating CTA ----
   Fixes the UX where tapping the floater scrolled all the way back to the
   embedded form (distracting context above). Modal locks focus and dims the
   page so the save action feels deliberate. ---- */

.save-modal-overlay {
  position: fixed; inset: 0;
  background: rgba(15, 23, 42, 0.55);
  z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  opacity: 0;
  transition: opacity 0.2s ease-out;
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
}
.save-modal-overlay--visible { opacity: 1; }

.save-modal {
  position: relative;
  background: var(--white);
  border-radius: 16px;
  padding: 32px 28px 28px;
  max-width: 420px;
  width: 100%;
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
  border-top: 3px solid var(--ican-red);
  transform: translateY(8px);
  transition: transform 0.2s ease-out;
}
.save-modal-overlay--visible .save-modal { transform: translateY(0); }

.save-modal__close {
  position: absolute;
  top: 12px; right: 12px;
  width: 32px; height: 32px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--gray-500);
  background: var(--gray-50);
  transition: background 0.15s, color 0.15s;
}
.save-modal__close:hover {
  background: var(--gray-150);
  color: var(--carbon);
}
.save-modal__close svg { width: 16px; height: 16px; }

.save-modal__title {
  font-size: 22px; font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--carbon);
  margin: 0 32px 6px 0;
}
.save-modal__body {
  font-size: 14px;
  color: var(--gray-600);
  line-height: 1.5;
  margin-bottom: 20px;
}
.save-modal__form {
  display: flex; flex-direction: column; gap: 10px;
}
.save-modal__form input[type="text"],
.save-modal__form input[type="email"] {
  background: var(--gray-100);
  border: 1px solid var(--gray-200);
  border-radius: 10px;
  padding: 13px 14px;
  font-size: 16px;
  color: var(--carbon);
  font-family: inherit;
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.04);
  transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
}
.save-modal__form input:hover {
  background: var(--white);
  border-color: var(--gray-300);
}
.save-modal__form input:focus {
  outline: none;
  background: var(--white);
  border-color: var(--ican-red);
  box-shadow: 0 0 0 4px rgba(236, 26, 51, 0.12);
}
.save-modal__consent {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: 13px;
  color: var(--gray-600);
  line-height: 1.45;
  margin-top: 4px;
  cursor: pointer;
}
.save-modal__consent input[type="checkbox"] {
  margin-top: 2px;
  accent-color: var(--ican-red);
  flex-shrink: 0;
}
.save-modal__submit {
  background: var(--ican-red);
  color: var(--white);
  padding: 14px 24px;
  border-radius: 10px;
  font-size: 16px; font-weight: 600;
  margin-top: 8px;
  transition: background 0.15s, transform 0.1s;
}
.save-modal__submit:hover { background: var(--crimson); color: var(--white); }
.save-modal__submit:active { transform: scale(0.98); }
.save-modal__submit:disabled { opacity: 0.6; cursor: not-allowed; transform: none; }

.save-modal__error {
  background: var(--row-hostile-bg);
  border-left: 3px solid var(--ican-red);
  color: var(--iff-strong-hostile);
  padding: 10px 12px;
  border-radius: 6px;
  font-size: 13px;
  margin-top: 6px;
}

/* ---- Mobile ---- */

@media (max-width: 640px) {
  .hero { padding: 48px 0 32px; }
  .hero__title { font-size: 38px; }
  .hero__subtitle { font-size: 17px; }
  .contest { padding: 22px 18px 16px; }
  .contest__title { font-size: 20px; }
  .ballot-header__title { font-size: 36px; }
  .ballot-header__explainer { font-size: 18px; }
  .save-share { padding: 22px 18px 18px; }
  .save-share__title { font-size: 20px; }
  .save-share__body { font-size: 14px; }
  .save-share__submit { width: 100%; }
  .save-share__eyebrow { font-size: 12px; }
  .share-btn { font-size: 13px; padding: 8px 14px; }
  .share-btn__icon { width: 15px; height: 15px; }
  .floating-save {
    left: 16px; right: 16px; bottom: 16px;
    justify-content: center;
    padding: 14px 18px;
    font-size: 15px;
  }
  .topbar { padding: 14px 20px; }

  /* Candidate card mobile collapse — narrow caps, allow name to wrap */
  .candidate__cap--action { width: 56px; }
  .candidate__cap--score { min-width: 54px; padding: 6px 4px; }
  .candidate__cap-bubble { width: 22px; height: 22px; }
  .candidate--pos-endorse .candidate__cap-mark { width: 38px; height: 38px; }
  .candidate--pos-oppose  .candidate__cap-mark { width: 32px; height: 32px; }
  .candidate__cap-score-value { font-size: 17px; }
  /* "ICAN INDEX™" wordmark eats too much horizontal width on phones — hide it
     on small screens. The score number is self-explanatory; the tooltip-style
     context lives on the page-level explainer. */
  .candidate__cap-index-label { display: none; }
  .candidate__cap-party { font-size: 7px; letter-spacing: 0.15em; }
  .candidate__content { padding: 8px 12px; min-width: 0; }
  /* On mobile, force name + tags to stack:
       - name takes the entire first line (flex-basis: 100%)
       - tags wrap to a second line and lay out horizontally there
     This unbreaks the bug where ICAN ENDORSED + INCUMBENT together compressed
     the name to ~0 width, causing character-by-character vertical wrap (Traci
     Park) or invisible names entirely (Hydee Feldstein Soto). */
  .candidate__name-row {
    flex-wrap: wrap;
    overflow: visible;
    align-items: center;
    gap: 6px;
    min-width: 0;
  }
  .candidate__name {
    flex-basis: 100%;
    min-width: 0;
    font-size: 16px;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: break-word;
    word-break: normal;
    hyphens: auto;
  }
  /* All in-row tags use the same compact size as .flag on mobile too. */
  .candidate__ican-tag,
  .candidate__incumbent-inline {
    font-size: 7px;
    padding: 2px 5px;
    transform: none;
  }

  /* Save modal — tighten on small screens */
  .save-modal-overlay { padding: 16px; }
  .save-modal { padding: 24px 20px 20px; }
  .save-modal__title { font-size: 19px; }
}
@media (min-width: 640px) {
  /* Condensed single-row save form on desktop: name / name / email / button */
  .save-share__form {
    grid-template-columns: 1fr 1fr 1.4fr auto;
    gap: 10px;
  }
  .save-share__input--email { grid-column: 3 / 4; }
}

/* ============================================================
   Sticky topbar — append to assets/css/main.css
   Find the existing `.topbar { ... }` rule and ADD position/sticky
   properties (don't remove existing rules — these stack on top).
   ============================================================ */

.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--white);
  border-bottom: 1px solid var(--gray-200);
  box-shadow: 0 1px 0 rgba(15, 23, 42, 0.02);
  /* Existing padding / flex / brand rules already in main.css remain unchanged. */
}

/* Optional: slightly stronger shadow when the page has actually scrolled.
   Implement only if you also wire a JS scroll listener that toggles a
   .topbar--scrolled class — otherwise drop this rule. The base style above
   is sufficient on its own. */
.topbar--scrolled {
  box-shadow: 0 2px 12px rgba(15, 23, 42, 0.06);
}

/* ---- Ballot-header actions (sort toggle + print) ---------------------- */
/* Two screen-only controls anchored at the top of the ballot — sort toggle
   on the left, print button on the right. Print stylesheet hides this row
   entirely so the printed page doesn't carry either control. */
.ballot-header__actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin: 16px 0 4px;
}

/* ---- Print action (on-screen) ----------------------------------------- */
/* Small text button anchored top-right of the ballot header. Triggers
   window.print(); print stylesheet hides this row entirely so the printed
   page doesn't carry the button visual. */
.ballot-header__print-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--gray-700, #374151);
  background: transparent;
  border: 1px solid var(--gray-300, #d1d5db);
  padding: 9px 16px;
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.ballot-header__print-btn:hover {
  color: var(--ican-red);
  border-color: var(--ican-red);
  background: rgba(236, 26, 51, 0.04);
}
.ballot-header__print-btn:active { transform: scale(0.98); }
.ballot-header__print-icon {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
}

/* QR is print-only — display:none on screen, revealed in @media print. */
.ballot-header__qr { display: none; }

/* ---- Print stylesheet ------------------------------------------------- */
/* Strips chrome (topbar, hero form, footer, save-share, floater, countdowns,
   typewriter cursor) and renders a clean monochrome ballot. Keeps semantic
   ENDORSE/OPPOSE color (green/red) on candidate caps via -webkit-print-color-
   adjust:exact so the printed page stays legible regardless of toner mode.
   Page-break rules ensure contests and candidate cards never split mid-card. */
@media print {
  @page {
    margin: 0.5in 0.5in 0.6in 0.5in;
  }

  body {
    background: #fff !important;
    color: #000 !important;
    font-size: 10pt;
  }

  /* Hide screen-only chrome */
  .topbar,
  .hero,
  .address-form,
  .hero__overline,
  .hero__title,
  .hero__subtitle,
  .hero__expansion,
  .hero__privacy,
  .footer,
  .save-share,
  .ballot-header__actions,
  .ballot-header__countdown,
  .ballot-header__cursor,
  .scale-viz__sweep,
  .scale-viz__slider,
  #status,
  [class*="floater"],
  [class*="floating"],
  [class*="icanvote-floater"] {
    display: none !important;
  }
  /* Print the static gradient bar + the chip's band-tint — preserve the
     full color spectrum so the printed scale visually anchors the per-
     candidate scores. The slider thumb is interactive and hidden above. */
  .scale-viz__bar,
  .scale-viz__chip,
  .scale-viz__chip-value,
  .scale-viz__chip-band {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
    color-adjust: exact !important;
  }
  .scale-viz__bar { border: 0.6pt solid #000 !important; }
  .scale-viz__chip {
    border: 0.6pt solid #888 !important;
    padding: 4pt 6pt !important;
  }

  /* Layout reset — full bleed within page margin */
  .page {
    max-width: 100% !important;
    padding: 0 !important;
    margin: 0 !important;
  }

  /* Ballot header — keep with first contest, anchor QR top-right */
  .ballot-header {
    position: relative !important;
    page-break-after: avoid !important;
    break-after: avoid !important;
    border: 0 !important;
    border-bottom: 1.5pt solid #000 !important;
    padding: 0 0 8pt 0 !important;
    margin: 0 0 12pt 0 !important;
    background: none !important;
    box-shadow: none !important;
  }
  .ballot-header__overline,
  .ballot-header__subtitle {
    color: #000 !important;
  }
  .ballot-header__title {
    font-size: 22pt !important;
    color: #000 !important;
    margin: 2pt 0 4pt 0 !important;
  }
  .ballot-header__voter {
    color: #000 !important;
    margin: 6pt 0 !important;
  }
  .ballot-header__label,
  .ballot-header__value {
    color: #000 !important;
  }
  .ballot-header__explainer,
  .ballot-header__footnote {
    color: #333 !important;
    font-size: 8.5pt !important;
  }
  .ballot-header__research-link {
    color: #000 !important;
  }

  /* QR — appears top-right of header on print */
  .ballot-header__qr {
    display: block !important;
    position: absolute !important;
    top: 0 !important;
    right: 0 !important;
    width: 90pt !important;
    text-align: center !important;
  }
  .ballot-header__qr svg {
    width: 90pt !important;
    height: 90pt !important;
    display: block !important;
    margin: 0 auto !important;
  }
  .ballot-header__qr-cap {
    font-family: 'JetBrains Mono', ui-monospace, monospace !important;
    font-size: 6pt !important;
    margin-top: 2pt !important;
    color: #000 !important;
  }

  /* Contest cards — clean monochrome, never split */
  .contest {
    background: #fff !important;
    border: 1pt solid #888 !important;
    box-shadow: none !important;
    border-radius: 4pt !important;
    padding: 10pt !important;
    margin: 0 0 8pt 0 !important;
    page-break-inside: avoid !important;
    break-inside: avoid !important;
  }
  .contest__level,
  .contest__title,
  .contest__subtitle {
    color: #000 !important;
  }

  /* Candidate cards — full-detail layout that doesn't rely on inherited
     screen rules (some of which use mask-image fades or auto-overflow that
     truncate content on print). Three columns: action cap (left), content
     (middle, flex-grow), score cap (right). All sub-rows explicitly visible. */
  .candidate {
    display: flex !important;
    align-items: stretch !important;
    page-break-inside: avoid !important;
    break-inside: avoid !important;
    background: #fff !important;
    box-shadow: none !important;
    border: 1px solid #aaa !important;
    border-radius: 6pt !important;
    overflow: visible !important;
    margin-bottom: 6pt !important;
  }
  .candidate__cap--action {
    display: flex !important;
    flex-direction: column !important;
    width: 64pt !important;
    flex-shrink: 0 !important;
    overflow: visible !important;
  }
  .candidate__cap-body {
    flex: 1 !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    padding: 6pt 4pt !important;
  }
  .candidate__cap-party {
    display: block !important;
    border-top: 0.6pt solid #ccc !important;
    padding: 3pt !important;
    font-size: 8pt !important;
    text-align: center !important;
  }
  .candidate--party-dem .candidate__cap-party {
    background: var(--party-dem) !important;
    color: #fff !important;
  }
  .candidate--party-rep .candidate__cap-party {
    background: var(--party-rep) !important;
    color: #fff !important;
  }
  .candidate--party-npp .candidate__cap-party {
    background: var(--party-npp) !important;
    color: #fff !important;
  }
  .candidate__content {
    flex: 1 1 0 !important;
    min-width: 0 !important;
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
    padding: 8pt 12pt !important;
    gap: 4pt !important;
    overflow: visible !important;
  }
  .candidate__name-row {
    display: flex !important;
    align-items: center !important;
    flex-wrap: wrap !important;
    gap: 5pt !important;
    overflow: visible !important;
  }
  .candidate__name {
    font-size: 12pt !important;
    font-weight: 700 !important;
    color: #000 !important;
  }
  .candidate__flags-row,
  .candidate__partners {
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 4pt !important;
    overflow: visible !important;
    /* Defeat the screen-side mask-image fade — on print there's no scroll,
       and the gradient mask hides partners/flags past the right edge. */
    mask-image: none !important;
    -webkit-mask-image: none !important;
  }
  .candidate__research-link {
    display: inline-flex !important;
    color: #000 !important;
    text-decoration: underline !important;
  }
  .candidate__cap--score {
    display: flex !important;
    flex-shrink: 0 !important;
    flex-direction: column !important;
    align-items: center !important;
    justify-content: center !important;
    min-width: 70pt !important;
    padding: 6pt 8pt !important;
  }
  .candidate__cap-index-label {
    display: block !important;
    font-size: 6.5pt !important;
    color: #555 !important;
    margin-bottom: 2pt !important;
  }
  .candidate__cap-score-value {
    font-size: 16pt !important;
    font-weight: 700 !important;
    color: #000 !important;
  }

  /* Force background printing on the position bubble + score-cap tints so the
     green/red ENDORSE/OPPOSE signal survives — both Chromium and Safari
     respect print-color-adjust:exact. */
  .candidate__cap-bubble,
  .candidate__cap-mark,
  .candidate__ican-tag,
  .candidate__cap-score-value,
  .candidate__cap--score,
  .candidate__cap-party {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
    color-adjust: exact !important;
  }
  .candidate__cap-bubble {
    width: 22pt !important;
    height: 22pt !important;
    border: 1.5pt solid #000 !important;
    border-radius: 50% !important;
    background: #fff !important;
    position: relative !important;
  }
  .candidate--pos-endorse .candidate__cap-bubble {
    border-color: #2BA563 !important;
  }
  .candidate--pos-oppose .candidate__cap-bubble {
    border-color: #C13522 !important;
  }
  .candidate--pos-endorse .candidate__cap-mark { color: #2BA563 !important; }
  .candidate--pos-oppose  .candidate__cap-mark { color: #C13522 !important; }

  /* Score cap subtle tints — strong colors per band, lighter than screen
     so the printed score is legible at 100% toner saturation. */
  .candidate--strong-allied .candidate__cap--score,
  .candidate--allied .candidate__cap--score,
  .candidate--leans-allied .candidate__cap--score   { background: #E8F7EE !important; }
  .candidate--leans-hostile .candidate__cap--score,
  .candidate--hostile .candidate__cap--score,
  .candidate--strong-hostile .candidate__cap--score { background: #FCEBEC !important; }

  /* ICAN endorse/oppose name tag — keep semantic color */
  .candidate__ican-tag--endorse {
    background: #2BA563 !important;
    color: #fff !important;
  }
  .candidate__ican-tag--oppose {
    background: #C13522 !important;
    color: #fff !important;
  }

  /* Signal flag pills — outlined, monochrome (saves toner, keeps content). */
  .flag {
    display: inline-flex !important;
    border: 0.6pt solid #999 !important;
    background: #fff !important;
    color: #000 !important;
    padding: 1pt 4pt !important;
    border-radius: 2pt !important;
    font-size: 6.5pt !important;
  }

  /* Partner pills — strip color backgrounds, use thin outlines (saves toner,
     keeps the partner attribution legible in B&W). */
  .candidate__partner {
    background: #fff !important;
    color: #000 !important;
    border: 0.6pt solid #888 !important;
    box-shadow: none !important;
    padding: 1pt 4pt !important;
  }

  /* Links — black + underlined for legibility, don't append URL text. */
  a, a:link, a:visited {
    color: #000 !important;
    text-decoration: underline !important;
  }

  /* Trailing footer — appears once at the end of the printed document. */
  #results::after {
    content: "Generated at vote.israelusa.org — your personalized June 2, 2026 California primary ballot. Scan the QR code above to revisit this page on your phone.";
    display: block;
    text-align: center;
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 7.5pt;
    color: #555;
    margin-top: 14pt;
    padding-top: 8pt;
    border-top: 0.6pt solid #ccc;
    page-break-inside: avoid;
  }
}
