/* ═══════════════════════════════════════════════════
   Pollcast — Unified Design Theme
   Shared across index.html and 2028_dem_primary.html
   ═══════════════════════════════════════════════════ */

/* ── Fonts ────────────────────────────────────────── */
@import url('https://fonts.googleapis.com/css2?family=Arimo:wght@400;500;600;700&display=swap');

/* ── Reset ────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* ── Design tokens ────────────────────────────────── */
:root {
  --bg: #f5f4f0;
  --surface: #ffffff;
  --dem: #0091e2;
  --rep: #e35647;
  --brand: rgb(26, 173, 191);
  --brand-a30: rgba(26, 173, 191, 0.3);
  --brand-a35: rgba(26, 173, 191, 0.35);
  --text: #1a1a1e;
  --text-mid: rgba(26, 26, 30, 0.78);
  --text-dim: rgba(26, 26, 30, 0.45);
  --border: rgba(0, 0, 0, 0.09);
}

/* ── Forecast tabs ────────────────────────────────── */
/* Cross-forecast nav strip rendered above the topline card on the
   senate/house/governor forecast pages. File-folder-tab style: the
   active tab takes the same surface color as the card directly below
   it, so the two visually connect into one continuous block. The
   nav's bottom border becomes the top edge of that block, with the
   active tab "punching through" via a 1px negative margin. */
.forecast-tabs {
  display: flex;
  gap: 2px;
  margin: 0;
  padding: 0;
  /* No bottom border — the card's top border below is the single
     horizontal line at this Y; the active tab covers it for the tab's
     width via -1 margin-bottom, producing a seamless tab→card flow. */
  flex-wrap: wrap;
}
.forecast-tab {
  display: inline-block;
  padding: 10px 18px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  text-decoration: none;
  border: 1px solid transparent;
  border-bottom: none;
  border-radius: 3px 3px 0 0;
  margin-bottom: -1px;
  transition: color 0.15s, background 0.15s;
}
.forecast-tab:hover { color: var(--text); }
.forecast-tab[aria-current="page"] {
  color: var(--text);
  background: var(--surface);
  /* The tab keeps its top/left/right borders to retain a clear "tab"
     shape; combined with the card's removed top border (below), the
     tab and card share one continuous outline with no visible line
     where they meet. */
  border-color: var(--border);
  font-weight: 400;
}

/* The card directly below the forecast tabs drops its top border —
   the active tab's borders + the card's left/right/bottom borders
   together form one continuous outline. With no card-top-border,
   there's no horizontal line at the tab→card seam to give away
   that two elements meet there. */
.forecast-tabs + .chart-card {
  border-top: none;
}

/* When the leftmost tab is active, square the card's top-left corner
   so it shares a flush left edge with the tab. Same trick on the
   right for the rightmost tab. :has() handles the position-aware
   styling without needing a JS class toggle. */
.forecast-tabs:has(.forecast-tab:first-child[aria-current="page"]) + .chart-card {
  border-top-left-radius: 0;
}
.forecast-tabs:has(.forecast-tab:last-child[aria-current="page"]) + .chart-card {
  border-top-right-radius: 0;
}

/* Title rendered inside the topline chart-card, replacing the big H1
   that used to live in the page <header>. Sits as the first child of
   .control-card; topline % numbers and seat chart follow below it. */
.control-title {
  font-family: 'Arimo', sans-serif;
  font-size: clamp(28px, 4vw, 44px);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.015em;
  color: var(--text);
  margin: 0 0 22px;
}

/* ── Rating badges ────────────────────────────────── */
/* Shared across senate/governor/house forecasts. Three-step partisan
   ramp — filled brand color (Solid), medium tint (Likely), pale pastel
   (Lean) — plus a neutral Toss-up. The fill+white-text Solid tier is
   the strongest visual signal so a "this race is decided" badge reads
   instantly even without parsing the label. */
.rating-badge {
  display: inline-block;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.05em;
  padding: 2px 7px;
  border-radius: 2px;
  white-space: nowrap;
  font-weight: 500;
}
.rb-solid-d  { background: #0072c6; color: #ffffff; }
.rb-likely-d { background: #9fd1ee; color: #003d7a; }
.rb-lean-d   { background: #dceffa; color: #0055b3; }
.rb-solid-i  { background: #2e8b56; color: #ffffff; }
.rb-likely-i { background: #a8d6b8; color: #14502a; }
.rb-lean-i   { background: #dff0e3; color: #1f6b37; }
.rb-toss     { background: #e6e3db; color: #5a5854; }
.rb-lean-r   { background: #fbe2dd; color: #a52316; }
.rb-likely-r { background: #f4a89e; color: #6e1208; }
.rb-solid-r  { background: #c8392b; color: #ffffff; }

/* ── Base ─────────────────────────────────────────── */
body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Arimo', sans-serif;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 52px 24px 64px;
}

.container { width: 100%; max-width: 980px; }

/* ── Header ───────────────────────────────────────── */
header { margin-bottom: 36px; }

.site-header {
  display: flex;
  align-items: center;
  padding-bottom: 16px;
  margin-bottom: 28px;
  border-bottom: 1px solid var(--border);
}
.site-header .logo-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}
.site-header img,
.site-header svg {
  height: 44px;
  width: auto;
  display: block;
  flex-shrink: 0;
}
.brand-mark {
  font-family: 'Arimo', sans-serif;
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.02em;
  text-transform: none;
  color: var(--brand);
  line-height: 1;
}

/* .header-top wraps h1 + year-picker side by side (index) */
.header-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}

h1 {
  font-family: 'Arimo', sans-serif;
  font-size: clamp(26px, 4.5vw, 44px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.015em;
}

.subtitle {
  margin-top: 14px;
  font-size: 14px;
  color: var(--text-mid);
  font-weight: 300;
  max-width: 580px;
  line-height: 1.65;
}

/* ── Year picker (index) ──────────────────────────── */
.year-picker {
  display: flex;
  border: 1px solid var(--border);
  border-radius: 3px;
  overflow: hidden;
  align-self: flex-start;
  flex-shrink: 0;
  margin-top: 6px;
}

.year-btn {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.06em;
  padding: 6px 14px;
  background: transparent;
  border: none;
  border-right: 1px solid var(--border);
  color: var(--text-mid);
  cursor: pointer;
  transition: background 0.1s, color 0.1s;
}
.year-btn:last-child { border-right: none; }
.year-btn:hover { color: var(--text); background: rgba(0,0,0,0.03); }
.year-btn.active { background: var(--text); color: #fff; }

/* ── View selector (2028 primary) ─────────────────── */
.view-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  border-top-right-radius: 3px;
  border-top-left-radius: 3px;
  padding: 10px;
  background-color: color(srgb 0.9387 0.9289 0.9077);
  border: 1px solid color(srgb 0.9096 0.9097 0.9098);
  border-bottom: 1px solid color(srgb 0.7956 0.7914 0.7776);
}

.view-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  font-weight: 300;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.view-select {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  padding: 6px 30px 6px 10px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5'%3E%3Cpath d='M0 0l4 5 4-5z' fill='rgba(0,0,0,0.3)'/%3E%3C/svg%3E") no-repeat right 10px center;
  background-size: 8px 5px;
  -webkit-appearance: none;
  appearance: none;
  color: var(--text);
  cursor: pointer;
  outline: none;
  min-width: 200px;
}
.view-select:focus { border-color: var(--brand-a35); }

.poll-badge {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  color: var(--text-dim);
  background: rgba(0,0,0,0.05);
  border-radius: 2px;
  padding: 3px 8px;
}

/* ── Mode toggle (2028 primary) ───────────────────── */
.mode-toggle {
  display: flex;
  gap: 4px;
  margin-bottom: 24px;
}

.mode-btn {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 7px 18px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: none;
  color: var(--text-mid);
  cursor: pointer;
  transition: all 0.1s;
}
.mode-btn:hover { color: var(--text); border-color: rgba(0,0,0,0.2); }
.mode-btn.active {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}

/* ── Chart card ───────────────────────────────────── */
.chart-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 20px 28px;
  position: relative;
}

#chart { width: 100%; display: block; }

/* ── Chart info ───────────────────────────────────── */
.chart-info {
  margin-bottom: 14px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}

.chart-info-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 20px;
}

.chart-info-row + .chart-info-row {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}

.chart-info-date {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-dim);
  white-space: nowrap;
  flex-basis: 100%;
  margin-bottom: 4px;
}

.chart-info-item {
  display: flex;
  align-items: center;
  gap: 5px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  white-space: nowrap;
}

.chart-info-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.chart-info-name {
  color: var(--text-dim);
  font-size: 10px;
}

/* ── No-chart notice (2028 primary) ──────────────── */
.no-chart-notice {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 16px 22px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11.5px;
  color: var(--text-dim);
  display: none;
}

/* ── Legend (index) ───────────────────────────────── */
.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 28px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

.legend-group {
  display: flex;
  align-items: center;
  gap: 20px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  color: var(--text-dim);
}

.legend-swatch-line {
  width: 22px;
  height: 2px;
  border-radius: 1px;
}

.legend-swatch-ci {
  width: 14px;
  height: 14px;
  border-radius: 2px;
}

.legend-swatch-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
}

.legend-sep {
  width: 1px;
  height: 16px;
  background: var(--border);
}

/* ── Table controls ───────────────────────────────── */
.table-controls {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 24px;
  margin-bottom: 10px;
}

.table-search {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: #fff;
  color: var(--text);
  width: 220px;
  outline: none;
}
.table-search:focus { border-color: var(--brand-a35); }
.table-search::placeholder { color: var(--text-dim); }

.table-count {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  color: var(--text-dim);
}

/* ── Polls table ──────────────────────────────────── */
.polls-table-wrap {
  border: 1px solid var(--border);
  border-radius: 3px;
  overflow: hidden;
  overflow-x: auto;
}

.polls-table {
  width: 100%;
  border-collapse: collapse;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
}

.polls-table thead tr {
  background: #f0ede8;
  border-bottom: 1px solid var(--border);
}

.polls-table th {
  padding: 10px 14px;
  text-align: left;
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-mid);
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
}
.polls-table th:hover { color: var(--text); }
.polls-table th.num,
.polls-table td.num { text-align: right; }

/* Sort indicators — index uses sort-asc/sort-desc classes + .sort-icon spans */
.polls-table th.sort-asc .sort-icon::after  { content: ' ↑'; }
.polls-table th.sort-desc .sort-icon::after { content: ' ↓'; }
.polls-table th.sort-asc .sort-icon,
.polls-table th.sort-desc .sort-icon { opacity: 0; }
.polls-table th.sort-asc,
.polls-table th.sort-desc { color: var(--text); }
.sort-icon { opacity: 0.3; font-style: normal; }

/* Sort indicator — 2028 primary uses a simpler .sorted class */
.polls-table th.sorted { color: var(--text); }

.polls-table tbody tr {
  border-bottom: 1px solid rgba(0,0,0,0.05);
  transition: background 0.08s;
}
.polls-table tbody tr:last-child { border-bottom: none; }
.polls-table tbody tr:nth-child(even) { background: #faf9f6; }
.polls-table tbody tr:hover { background: #eef3fa; }

.polls-table td {
  padding: 9px 14px;
  color: var(--text);
  white-space: nowrap;
}

/* Partisan coloring (index) */
.polls-table td.dem-col { color: var(--dem); font-weight: 400; }
.polls-table td.rep-col { color: var(--rep); font-weight: 400; }
.polls-table th.dem-col { color: var(--dem); }
.polls-table th.rep-col { color: var(--rep); }

/* Margin spread coloring (index) */
.polls-table td.spread-d { color: var(--dem); }
.polls-table td.spread-r { color: var(--rep); }
.polls-table td.spread-tie { color: var(--text); }

/* Third-party / misc column (index) */
.third-col {
  color: var(--text-dim);
  font-size: 11px;
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.pollster-col {
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Pages that show a sponsor info bug inside .pollster-col should override
   the overflow locally (`td.pollster-col { overflow: visible; max-width:
   none; }`) so the bug's tooltip can escape; ellipsis behavior moves to
   the inner .pollster-name wrapper below. */
.pollster-name {
  display: inline-block;
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
  white-space: nowrap;
}

/* ── Sponsor info bug ──────────────────────────────
   Small "i" pill rendered beside a pollster name when the poll has a
   sponsor. Hover reveals the sponsor text in a dark tooltip. */
.sponsor-bug {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 13px;
  height: 13px;
  margin-left: 5px;
  border-radius: 50%;
  background: rgba(0,0,0,0.08);
  color: var(--text-dim);
  font-family: 'JetBrains Mono', monospace;
  font-size: 9px;
  font-weight: 600;
  font-style: italic;
  line-height: 1;
  cursor: help;
  vertical-align: middle;
  user-select: none;
}
.sponsor-bug:hover {
  background: rgba(0,0,0,0.18);
  color: var(--text);
  z-index: 50;   /* lift above subsequent rows */
}
.sponsor-bug::after {
  content: 'Sponsor: ' attr(data-sponsor);
  position: absolute;
  top: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  padding: 5px 9px;
  background: var(--text);
  color: var(--surface);
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  font-style: normal;
  font-weight: 400;
  letter-spacing: 0.02em;
  white-space: nowrap;
  border-radius: 3px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s;
  z-index: 20;
}
.sponsor-bug:hover::after { opacity: 1; }

/* In the last two rows of any polls-table, flip the tooltip to point up
   so it extends into the row above (unclipped) instead of past the
   table-wrap's bottom edge (which has overflow:hidden for rounded corners). */
.polls-table tbody tr:nth-last-child(-n+2) .sponsor-bug::after {
  top: auto;
  bottom: calc(100% + 4px);
}

/* ── Poll weight bars ─────────────────────────────── */
.wt-col {
  width: 28px;
  padding-left: 4px !important;
  padding-right: 8px !important;
}
.weight-bars {
  display: flex;
  gap: 2px;
  align-items: center;
}
.weight-bar {
  width: 3px;
  height: 10px;
  border-radius: 1px;
  background: rgba(26,26,30,0.12);
}
.weight-bar.filled {
  background: rgba(26,26,30,0.4);
}

.pollster-col a,
.polls-table td a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: rgba(26, 26, 30, 0.2);
  text-underline-offset: 2px;
}
.pollster-col a:hover,
.polls-table td a:hover { text-decoration-color: var(--text); }

/* ── Show more ────────────────────────────────────── */
.show-more-wrap {
  padding: 12px;
  text-align: center;
  border-top: 1px solid var(--border);
}

.show-more-btn {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
  background: none;
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 6px 20px;
  cursor: pointer;
  transition: color 0.1s, border-color 0.1s;
}
.show-more-btn:hover { color: var(--text); border-color: rgba(0,0,0,0.2); }

/* ── Compare table (2028 primary) ─────────────────── */
.compare-nat-row td { font-weight: 600; }
.delta { font-size: 10px; line-height: 1.4; display: block; }
.delta-pos { color: #1a7a52; }
.delta-neg { color: #9b2020; }
.delta-zero { color: var(--text-dim); }

/* ── Footer ───────────────────────────────────────── */
.footer {
  margin-top: 18px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  color: var(--text-dim);
  opacity: 0.45;
  line-height: 1.6;
}

/* ── Tooltip ──────────────────────────────────────── */
.tooltip {
  position: fixed;
  background: #fff;
  border: 1px solid rgba(0,0,0,0.1);
  border-radius: 3px;
  padding: 12px 15px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11.5px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.12s ease;
  z-index: 100;
  min-width: 190px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.11);
}
.tooltip.visible { opacity: 1; }

.tt-date {
  font-size: 11px;
  color: var(--text-dim);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  margin-bottom: 9px;
  padding-bottom: 7px;
  border-bottom: 1px solid rgba(0,0,0,0.07);
}

.tt-row {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  margin-top: 4px;
  line-height: 1.5;
}

.tt-label { color: var(--text-dim); display: flex; align-items: center; gap: 6px; }
.tt-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
.tt-val { font-weight: 400; }

/* ── Mobile / small screens ───────────────────────── */
@media (max-width: 640px) {
  body { padding: 24px 14px 40px; }
  header { margin-bottom: 24px; }
  .site-header { margin-bottom: 22px; }
  .site-header img,
  .site-header svg { height: 36px; }
  .site-header .brand-mark { font-size: 24px; }
  .subtitle { font-size: 13px; line-height: 1.55; }
  .header-top { gap: 12px; }

  .chart-card { padding: 14px 14px 16px; }
  .control-card { padding: 18px 14px 14px; }

  /* View bar (state selectors etc.) */
  .view-bar { flex-wrap: wrap; gap: 8px; padding: 10px 12px; }
  .view-select { min-width: 0; flex: 1 1 140px; font-size: 12px; }
  .mode-btn { padding: 6px 12px; font-size: 10.5px; }

  /* Table search row stacks */
  .table-controls {
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 18px;
  }
  /* iOS Safari auto-zooms when focusing an input whose font-size is < 16px;
     bump to 16px on mobile to suppress the zoom-in-on-tap behavior. */
  .table-search { width: 100%; font-size: 16px; }
  .table-count { width: 100%; }

  /* Tables: tighter cells, smaller font, hide low-value columns */
  .polls-table { font-size: 11px; }
  .polls-table th { padding: 8px 9px; font-size: 9.5px; letter-spacing: 0.06em; }
  .polls-table td { padding: 7px 9px; }
  .pollster-col { max-width: 130px; }
  .third-col { max-width: 90px; font-size: 10px; }

  /* Year picker wraps under h1 */
  .year-picker { flex-wrap: wrap; }
  .year-btn { padding: 5px 10px; font-size: 10.5px; }

  /* Tooltips: cap width so they don't overflow viewport */
  .tooltip { max-width: calc(100vw - 28px); min-width: 0; padding: 10px 12px; font-size: 11px; }

  /* Legend wraps tighter */
  .legend { gap: 6px 18px; }
  .legend-group { gap: 14px; }

  /* Footer text */
  .footer { font-size: 10px; }
}
