/* /races/: race cards, one horizontally scrolling, snapping row per office
   on wide screens and a single column on phones. Tokens only (theme.css),
   so the ink scale, paper and party fills follow dark mode on their own.
   The two candidates' poll numbers share one style: neither is bolder,
   bigger or brighter than the other. */

.races-intro { max-width: 72ch; color: var(--ink-600); margin: 0 0 var(--sp-5); }
.races-updating { max-width: 72ch; margin: 0 0 var(--sp-5); }

/* ---------------------------------------------------------------- tabs */
.races-tablist {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-4);
  padding: 0 0 var(--sp-3);
  border-bottom: 1px solid var(--ink-200);
  scroll-margin-top: calc(var(--nav-h) + var(--sp-3));
}
/* --races-tabs-h is the tab strip's height, set by races.js once the strip
   shows (0 without it), so a link to an office lands below the tabs. */
.races-tablist[hidden] { display: none; }
.races-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 44px;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--ink-300);
  border-radius: var(--r-full);
  background: var(--paper);
  color: var(--ink-700);
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  transition: background-color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.races-tab:hover { background: var(--ink-50); border-color: var(--ink-400); }
.races-tab:focus-visible { outline: 3px solid var(--civic-blue); outline-offset: 2px; }
.races-tab[aria-selected="true"] { background: var(--ink-900); border-color: var(--ink-900); color: var(--paper); }
.races-tab-count {
  display: inline-block;
  min-width: 1.6em;
  padding: 0 var(--sp-1);
  border: 1px solid var(--ink-300);
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  line-height: 1.5;
  text-align: center;
}
.races-tab[aria-selected="true"] .races-tab-count { border-color: currentColor; }

/* -------------------------------------------------------------- panels */
.races-panel { margin: 0 0 var(--sp-8); scroll-margin-top: calc(var(--nav-h) + var(--sp-3) + var(--races-tabs-h, 0px)); }
.races-panel[hidden] { display: none; }
.races-panel-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin: 0 0 var(--sp-3); }
.races-panel-title { font-size: var(--fs-lg); margin: 0; }
.races-scroll { display: flex; gap: var(--sp-2); }
.races-scroll[hidden] { display: none; }
.races-scroll-btn { min-width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
.races-scroll-btn[aria-disabled="true"] { opacity: 0.45; cursor: default; }

/* position: relative makes the row the containing block of the absolutely
   positioned .visually-hidden labels inside its cards. Without it they are
   not clipped by the row's overflow, and a long row of cards widened the
   whole page instead of scrolling inside itself. */
.races-row {
  position: relative;
  list-style: none;
  margin: 0;
  padding: var(--sp-1) var(--sp-1) var(--sp-4);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(18.5rem, 21rem);
  /* Each card keeps its own height: a count or an open Sources list on
     one card does not stretch every other card in the row. */
  align-items: start;
  gap: var(--sp-4);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--sp-1);
  scroll-behavior: smooth;
}
.races-item { display: flex; scroll-snap-align: start; }

/* ---------------------------------------------------------------- card */
.race-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-4);
  background: var(--paper);
  color: var(--ink-800);
  border: 1px solid var(--ink-200);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  scroll-margin-top: calc(var(--nav-h) + var(--sp-3));
}
.race-card:target { border-color: var(--civic-blue); box-shadow: var(--shadow-glow-blue); }
.race-card-head { display: flex; flex-direction: column; gap: var(--sp-1); }
.race-card-title { margin: 0; font-size: var(--fs-md); line-height: 1.3; color: var(--ink-900); }
.race-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-2);
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--ink-600);
}
.race-card-stage { font-weight: 600; color: var(--ink-700); }

.race-ratings { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-2); }
.race-card a.race-rating {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 2px var(--sp-2);
  border: 1px solid var(--ink-300);
  border-radius: var(--r-full);
  background: var(--ink-50);
  color: var(--ink-700);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-decoration: none;
}
.race-card a.race-rating:hover,
.race-card a.race-rating:focus-visible { border-color: var(--civic-blue); color: var(--ink-900); }

/* Candidates: portrait or initials, who they are, the polling average. */
.race-cands { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-3); }
.race-cand { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; align-items: center; gap: var(--sp-3); }
.race-avatar {
  width: 44px;
  height: 44px;
  border-radius: var(--r-full);
  border: 2px solid var(--ink-300);
  background: var(--ink-100);
  object-fit: cover;
}
.race-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-color: transparent;
  background: var(--neutral-strong);
  color: var(--always-white);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.02em;
}
.race-initials.party-D { background: var(--party-D); }
.race-initials.party-R { background: var(--party-R); }
.race-initials.party-I { background: var(--party-I); }
.race-cand-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.race-cand-name { font-weight: 600; color: var(--ink-900); overflow-wrap: anywhere; }
/* A member's name links to their record in the same ink as a name that
   does not, so the link adds no weight; the underline marks it. */
.race-card .race-cand-name a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--ink-300);
  text-underline-offset: 2px;
}
.race-card .race-cand-name a:hover { text-decoration-color: currentColor; }
.race-cand-tags { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
.race-cand-role { font-size: var(--fs-xs); color: var(--ink-600); }
.race-cand-pct {
  min-width: 4.5ch;
  text-align: right;
  font-size: var(--fs-lg);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink-900);
}

/* The state's unofficial count, filled by races.js on election night. */
.race-count { padding: var(--sp-3) 0; border-top: 1px solid var(--ink-200); border-bottom: 1px solid var(--ink-200); }
.race-count[hidden] { display: none; }
.race-count-head { margin: 0 0 var(--sp-2); font-size: var(--fs-sm); font-weight: 700; color: var(--ink-900); }
.race-count-lines { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-1); }
.race-count-line {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: baseline;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--ink-800);
}
/* The party pill stays beside the name; only the name wraps. */
.race-count-who { display: flex; flex-wrap: nowrap; align-items: baseline; gap: var(--sp-1); }
.race-count-name { min-width: 0; overflow-wrap: anywhere; }
.race-count-pct { font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.race-count-votes { color: var(--ink-600); font-variant-numeric: tabular-nums; text-align: right; }
.race-count-more,
.race-count-note { margin: var(--sp-2) 0 0; font-size: var(--fs-xs); color: var(--ink-600); }
/* Once the office is counting: a card with no count of its own says so. */
.race-count-none { margin: 0; font-size: var(--fs-sm); color: var(--ink-700); }
.race-count-none[hidden] { display: none; }

.race-poll { margin: 0; font-size: var(--fs-sm); color: var(--ink-600); }
.race-poll-label { font-weight: 600; color: var(--ink-700); }
.race-poll time { white-space: nowrap; }
/* Once the office is counting (races.js adds .polls-closed), the poll
   numbers leave the candidate rows, where a results tracker prints the
   vote share, and are listed on the poll line under "Final polling
   average", in quieter type. Before then the line names no values; the
   rows carry them. */
.race-poll-values { display: none; }
.race-card.polls-closed .race-poll-values { display: inline; }
.race-card.polls-closed .race-cand { grid-template-columns: 44px minmax(0, 1fr); }
.race-card.polls-closed .race-cand-pct { display: none; }
.race-card.polls-closed .race-poll,
.race-card.polls-closed .race-poll-label { color: var(--ink-500); font-weight: 400; }

.race-why { margin: 0; font-size: var(--fs-sm); color: var(--ink-700); }

.race-sources { font-size: var(--fs-sm); }
.race-sources > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  min-height: 32px;
  color: var(--ink-700);
  font-weight: 600;
  cursor: pointer;
}
/* inline-flex drops the native disclosure triangle, so a chevron marks
   that the list opens (down when closed, up when open). */
.race-sources > summary::after {
  content: '';
  display: inline-block;
  width: 0.45em;
  height: 0.45em;
  margin-left: var(--sp-1);
  border: solid currentColor;
  border-width: 0 2px 2px 0;
  transform: translateY(-0.15em) rotate(45deg);
}
.race-sources[open] > summary::after { transform: translateY(0.1em) rotate(-135deg); }
.race-sources-count { font-weight: 400; color: var(--ink-600); }
.race-sources ul { margin: var(--sp-2) 0 0; padding-left: 1.1rem; display: flex; flex-direction: column; gap: var(--sp-2); }
.race-source-meta { display: block; font-size: var(--fs-xs); color: var(--ink-600); }

.race-links {
  list-style: none;
  margin: 0;
  padding: var(--sp-2) 0 0;
  border-top: 1px solid var(--ink-200);
  display: flex;
  flex-direction: column;
  gap: 0;
  font-size: var(--fs-sm);
  color: var(--ink-600);
}
/* A full-size tap target: for most races this link is the reader's route
   to the count on election night. */
.race-links a { display: inline-flex; align-items: center; min-height: 44px; }

/* -------------------------------------------------------- methodology */
.races-method { max-width: 72ch; margin: var(--sp-8) 0 0; padding: var(--sp-6) 0 0; border-top: 1px solid var(--ink-200); }
.races-method h2 { font-size: var(--fs-lg); margin: 0 0 var(--sp-3); }
.races-method ul { padding-left: 1.1rem; line-height: 1.7; color: var(--ink-700); }
.races-nav { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.races-disclaimer { margin: 0; }

/* Below 992px the sticky header is two rows (brand, then search), as in
   learn.css, so one --nav-h would leave a linked card or office under it. */
@media (max-width: 991.98px) {
  .races-tablist,
  .race-card { scroll-margin-top: calc(var(--nav-rows-h-mobile) + var(--sp-3)); }
  .races-panel { scroll-margin-top: calc(var(--nav-rows-h-mobile) + var(--sp-3) + var(--races-tabs-h, 0px)); }
}

/* -------------------------------------------------------------- phones */
@media (max-width: 599.98px) {
  .races-tab { padding: var(--sp-2) var(--sp-3); }
  .races-row {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: minmax(0, 1fr);
    padding: 0;
    overflow-x: visible;
    scroll-snap-type: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .races-tab { transition: none; }
  .races-row { scroll-behavior: auto; }
}
