/* ==========================================================================
   site/site.css - the projects-hub overlay on the exported election-night page (site/README.md).
   Linked right after app.css by site/apply.mjs, so it wins ties with the export's styles. Hub-owned:
   a re-export never overwrites it. One light theme only, as on the rest of the site.

   Sources (projects-hub origin/main):
     projects/2026-early-vote/src/App.svelte      .live-callout / .live-tag / .live-dot
     shared/components/SubscribePopup.svelte      the pop-up (classes renamed sin-subscribe-*: the Svelte
                                                  originals were component-scoped, here they are global)
     shared/design-tokens.css                     --color-text-muted
     shared/components/Header.svelte, Footer.svelte   phone fixes the export's port predates
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. Current site tokens: Text Muted darkened to #736f66 (4.5:1 on --color-bg-subtle);
      the export's vendored design-tokens.css still has #a19d93.
   -------------------------------------------------------------------------- */
:root {
  --color-text-muted: #736f66;
}


/* --------------------------------------------------------------------------
   2. The live-blog callout (2026-early-vote App.svelte), inserted by site.js right
      after the intro, above the tab bar
   -------------------------------------------------------------------------- */
.live-callout {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  margin: var(--space-4) 0 0;
  padding: var(--space-3);
  background: var(--color-bg-card);
  border: 1px solid var(--color-border-strong);
  border-left: 4px solid #4f46e5;
  text-align: left;
  border-radius: var(--radius-lg);
}

.live-callout p {
  margin: 0;
  font-size: 1.0625rem;
  line-height: 1.45;
  color: var(--color-text-primary);
}

.live-callout a {
  color: #4f46e5;
  font-weight: 600;
}

.live-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  padding: 2px 8px;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #fff;
  background: #4f46e5;
  border-radius: var(--radius-lg);
}

.live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #fff;
}

/* Phones: the tag runs inline with the text and the text is a step smaller, so the callout takes about two fewer
   lines above the live numbers (on the early-vote page it stacks; here the chamber odds should stay near the top). */
@media (max-width: 560px) {
  .live-callout {
    display: block;
    padding: var(--space-2) var(--space-3);
  }

  .live-callout .live-tag {
    margin-right: 6px;
    vertical-align: 1px;
  }

  .live-callout p {
    display: inline;
    font-size: 0.9375rem;
    line-height: 1.45;
  }
}

/* As on the early-vote page, the callout sits inside the intro, above its divider (site.js). If the intro has no
   divider it follows the intro instead, and takes the intro's bottom gap below it too, before the tabs. */
.site-intro > .live-callout {
  margin-bottom: var(--space-2);
}

.enw-main > .live-callout {
  margin: 0 0 var(--space-5);
}


/* --------------------------------------------------------------------------
   3. First-visit pop-up (SubscribePopup.svelte)
   -------------------------------------------------------------------------- */
.sin-subscribe-dialog {
  /* base.css resets every element's margin to 0, which removes the UA's
     dialog:modal { margin: auto } centering, so restore it here. */
  margin: auto;
  width: min(560px, calc(100% - 24px));
  max-height: calc(100dvh - 24px);
  padding: 0;
  border: none;
  border-radius: var(--radius-lg, 4px);
  background: var(--color-bg-card, #fff);
  color: var(--color-text-primary, #1a1918);
  box-shadow: 0 24px 64px rgba(26, 25, 24, 0.28);
  overflow: auto;
}

.sin-subscribe-dialog[open] {
  animation: sin-subscribe-popup-in 180ms ease-out;
}

.sin-subscribe-dialog::backdrop {
  background: rgba(26, 25, 24, 0.55);
  backdrop-filter: blur(2px);
}

@keyframes sin-subscribe-popup-in {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sin-subscribe-dialog[open] {
    animation: none;
  }
}

.sin-subscribe-card {
  position: relative;
  padding: var(--space-6, 32px) var(--space-5, 24px) var(--space-4, 16px);
  text-align: center;
}

/* Sticky, so it stays in view when the dialog has to scroll (short phone screens). The margins pin it
   8px from the card's top-right corner without taking up a line. */
.sin-subscribe-close {
  position: sticky;
  top: var(--space-2, 8px);
  z-index: 1;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  margin: -24px -16px -12px auto;
  border: none;
  border-radius: 50%;
  background: var(--color-bg-card, #fff);
  color: var(--color-text-tertiary, #706c63);
  cursor: pointer;
}

.sin-subscribe-close:hover {
  background: var(--color-bg-subtle, #f5f4f1);
  color: var(--color-text-primary, #1a1918);
}

.sin-subscribe-proof {
  margin: 0 0 var(--space-1, 4px);
  font-size: var(--font-size-label, 15px);
  font-weight: var(--font-weight-medium, 500);
  color: var(--color-text-muted, #736f66);
}

.sin-subscribe-heading {
  margin: 0 0 var(--space-2, 8px);
  font-size: var(--font-size-title, 22px);
  font-weight: var(--font-weight-semibold, 600);
  line-height: 1.25;
}

.sin-subscribe-desc {
  max-width: 440px;
  margin: 0 auto var(--space-4, 16px);
  font-size: var(--font-size-body, 17px);
  color: var(--color-text-secondary, #52504a);
}

.sin-subscribe-embed {
  display: flex;
  justify-content: center;
  min-height: 320px;
}

.sin-subscribe-embed iframe {
  width: 100%;
  max-width: 480px;
  border-radius: var(--radius-md, 3px);
}

/* Phones: the embed already shows the newsletter's name and pitch, so drop our copy of them, and give
   the Substack form (which can't scroll) the width and height it needs once it wraps. */
@media (max-width: 520px) {
  .sin-subscribe-dialog {
    width: calc(100% - 16px);
    max-width: none; /* the UA caps a modal dialog at 100% - 2em - 6px */
  }

  .sin-subscribe-card {
    padding-right: var(--space-2, 8px);
    padding-left: var(--space-2, 8px);
  }

  .sin-subscribe-close {
    margin-right: 0;
  }

  .sin-subscribe-heading,
  .sin-subscribe-desc {
    display: none;
  }

  .sin-subscribe-proof {
    margin-bottom: var(--space-2, 8px);
  }

  .sin-subscribe-embed {
    min-height: 500px;
  }

  .sin-subscribe-embed iframe {
    height: 500px;
  }
}

/* Narrower than about 370px the form wraps onto more lines. */
@media (max-width: 370px) {
  .sin-subscribe-embed {
    min-height: 580px;
  }

  .sin-subscribe-embed iframe {
    height: 580px;
  }
}

.sin-subscribe-dismiss {
  margin-top: var(--space-3, 12px);
  padding: var(--space-1, 4px) var(--space-2, 8px);
  border: none;
  background: none;
  font: inherit;
  font-size: var(--font-size-source, 14px);
  color: var(--color-text-tertiary, #706c63);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.sin-subscribe-dismiss:hover {
  color: var(--color-text-primary, #1a1918);
}


/* --------------------------------------------------------------------------
   4. Header on phones (Header.svelte, projects-hub 0fb9407: "fits at 320px"): the right
      side keeps its full width and the wordmark shrinks instead of being covered.
      The header stays sticky here on purpose (DECISIONS D11; the races table's sticky
      rows and the race drawer sit under it via --enw-header-h).
   -------------------------------------------------------------------------- */
@media (max-width: 560px) {
  .site-header-center {
    flex-shrink: 1;
    min-width: 0;
  }

  .site-header-right {
    flex: 1 0 auto;
  }

  .site-banner {
    height: auto;
    max-height: 22px;
    max-width: 100%;
  }
}


/* --------------------------------------------------------------------------
   5. Footer signup on phones (Footer.svelte): the Substack form can't scroll, so give
      it the height it needs once it wraps, as in the pop-up.
   -------------------------------------------------------------------------- */
@media (max-width: 520px) {
  .site-newsletter-embed iframe {
    height: 500px;
  }
}

@media (max-width: 370px) {
  .site-newsletter-embed iframe {
    height: 580px;
  }
}


/* --------------------------------------------------------------------------
   6. Wide screens: the inline newsletter nudge (site.js, above the Methodology box)
      keeps the bottom block's width when app.css widens the main column for the rail.
   -------------------------------------------------------------------------- */
@media (min-width: 1600px) {
  .enw-main > .site-inline-cta {
    max-width: calc(var(--width-max) - 32px);
    margin-left: auto;
    margin-right: auto;
  }
}


/* --------------------------------------------------------------------------
   5. "County swings" tab (site.js mountSwingsTab)
   -------------------------------------------------------------------------- */
.enw-swings-on #view-estimate,
.enw-swings-on #view-counties {
  display: none !important;
}

.sw-view {
  padding-top: var(--space-3);
}

.sw-intro {
  margin: 0 0 var(--space-3);
  max-width: 46rem;
  color: var(--color-text-secondary, var(--color-text-primary));
  font-size: 1rem;
  line-height: 1.5;
}

.sw-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  margin: 0 0 var(--space-4);
  font-size: 0.9375rem;
}

.sw-controls select {
  margin-left: 6px;
  padding: 4px 8px;
  font: inherit;
  border: 1px solid var(--color-border-strong, #ccc);
  border-radius: var(--radius-lg, 4px);
  background: var(--color-bg-card, #fff);
}

.sw-updated {
  color: var(--color-text-muted, #6b6762);
  font-size: 0.875rem;
}

.sw-h {
  margin: var(--space-4) 0 var(--space-2);
  font-size: 1.0625rem;
}

.sw-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.sw-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}

.sw-table th,
.sw-table td {
  padding: 7px 10px;
  border-bottom: 1px solid var(--color-border, #e6e3df);
  text-align: left;
  white-space: nowrap;
}

.sw-table th {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-muted, #6b6762);
}

.sw-table .sw-n {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.sw-d {
  color: var(--color-dem-dark, #1d4ed8);
}

.sw-r {
  color: var(--color-rep-dark, #a61e1e);
}

.sw-race,
.sw-time {
  color: var(--color-text-muted, #6b6762);
  font-size: 0.8125rem;
}

.sw-empty {
  color: var(--color-text-muted, #6b6762);
  white-space: normal !important;
}

.sw-note {
  margin: var(--space-3) 0 0;
  max-width: 46rem;
  color: var(--color-text-muted, #6b6762);
  font-size: 0.875rem;
  line-height: 1.5;
}

@media (max-width: 560px) {
  .sw-table th,
  .sw-table td {
    padding: 6px 8px;
  }
}

/* summary tiles, House scatter, district table (County swings tab) */
.sw-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-3);
  margin: 0 0 var(--space-4);
}

.sw-tile {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--color-border, #e6e3df);
  border-radius: var(--radius-lg, 4px);
}

.sw-tile-k {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted, #6b6762);
}

.sw-tile-v {
  margin: 4px 0 2px;
  font-size: 2.25rem;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.sw-tile-s {
  font-size: 0.875rem;
  color: var(--color-text-muted, #6b6762);
}

.sw-chart {
  max-width: 720px;
}

.sw-scatter {
  display: block;
  width: 100%;
  height: auto;
}

.sw-scatter .sw-grid {
  stroke: var(--color-border, #e6e3df);
  stroke-width: 1;
}

.sw-scatter .sw-diag {
  stroke: #8a857e;
  stroke-width: 1.5;
  stroke-dasharray: 5 4;
}

.sw-scatter .sw-tick,
.sw-scatter .sw-corner {
  font-size: 12px;
  fill: var(--color-text-muted, #6b6762);
}

.sw-scatter .sw-axis {
  font-size: 13px;
  fill: var(--color-text-primary, #1a1918);
}

.sw-scatter .sw-dot-d {
  fill: rgba(37, 99, 235, 0.45);
  stroke: var(--color-dem-dark, #1d4ed8);
  stroke-width: 0.8;
}

.sw-scatter .sw-dot-r {
  fill: rgba(201, 42, 42, 0.45);
  stroke: var(--color-rep-dark, #a61e1e);
  stroke-width: 0.8;
}

.sw-table .sw-cell {
  border-radius: 2px;
}
