@font-face { font-family: Geist; src: url('/fonts/Geist-Variable.woff2') format('woff2'); font-weight: 100 900; font-display: swap; }
@font-face { font-family: 'Geist Serif'; src: url('/fonts/GeistSerif-Regular.woff2') format('woff2'); font-weight: 400; font-display: swap; }
:root {
  --ground: #f5f3ee; --surface: #ebe8e1; --raised: #e2dfd7; --active: #dedbd3;
  --text: #161616; --muted: #6b6862; --border: #b4b0a7;
  /* Old Glory Blue and Old Glory Red, the US flag's official colors. */
  --blue: #0a3161; --red: #b31942;
  --negative: #a12525; --primary: #161616; --primary-ink: #f5f3ee;
  --font: Geist, Arial, sans-serif; --serif: 'Geist Serif', Georgia, serif;
  --radius: 8px; --ease: cubic-bezier(.22, 1, .36, 1);
}
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
html:has(dialog[open]) { overflow: hidden; }
/* viewport-fit=cover lets the page run under a landscape notch; keep content inside the safe area. */
body { margin: 0; padding-inline: env(safe-area-inset-left) env(safe-area-inset-right); background: var(--ground); color: var(--text); font: 16px/1.5 var(--font); -webkit-font-smoothing: antialiased; }
/* No double-tap zoom on controls, so a quick second tap on a pill is a tap. */
a, button, label { touch-action: manipulation; }
h1, h2, h3, p, ol, fieldset { margin: 0; padding: 0; }
a { color: inherit; text-decoration: none; }
button, input { font: inherit; }
button { cursor: pointer; color: inherit; border: 0; }
button, a, summary { -webkit-tap-highlight-color: transparent; }
button:disabled { cursor: wait; opacity: .7; }
button svg, a svg { flex: none; }
[hidden] { display: none !important; }
:focus-visible { outline: 2px solid var(--text); outline-offset: 5px; }
::selection { background: var(--text); color: var(--ground); }
.frame { width: min(660px, calc(100% - 40px)); margin-inline: auto; }
.num { font-variant-numeric: tabular-nums; }
.quiet { color: var(--muted); font-size: 12px; }
.sr-only, .skip-link:not(:focus) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.skip-link:focus { position: absolute; z-index: 10; padding: 12px; background: var(--text); color: var(--ground); }
.bar { display: flex; align-items: center; justify-content: space-between; min-height: 76px; padding: 16px 40px; }
.brand { display: inline-flex; gap: 14px; align-items: center; font: 400 20px/1 var(--serif); letter-spacing: -.02em; white-space: nowrap; }
.brand svg { flex: none; }
.mark-canton { fill: var(--blue); }
.mark-stripes { fill: var(--red); }
.bar nav a { display: inline-flex; gap: 8px; align-items: center; font-size: 14px; min-height: 44px; }
.bar nav a:hover svg { transform: translateX(3px); }
.title-row { text-align: center; padding: 38px 0 32px; }
/* The public masthead follows Clanker Chat. The ballot itself retains app-scale text. */
h1 { font: 400 clamp(48px, 6.1vw, 88px)/1.05 var(--serif); letter-spacing: -.04em; white-space: nowrap; }
.title-row .lede { font-size: 17px; color: var(--muted); margin: 24px auto 0; max-width: 36ch; }
/* The term clock, updated by app.js. The time itself is ink, the label stays quiet. */
.term-line { margin-bottom: 20px; font-size: 13px; color: var(--muted); }
#countdown { color: var(--text); }
.incumbent { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; margin-top: 16px; padding: 0 16px; border-radius: 999px; background: var(--surface); font-size: 13px; }
.incumbent img { object-fit: contain; }
.ballot-panel { margin-top: 4px; }
/* One row per lab, like a printed ballot: the lab on the left, its models as choices. */
fieldset { border: 0; min-width: 0; border-bottom: 1px solid var(--surface); }
.lab { display: grid; grid-template-columns: 168px minmax(0, 1fr); align-items: center; gap: 16px; min-height: 60px; padding: 8px 0; border-top: 1px solid var(--surface); }
.lab-name { display: flex; align-items: center; gap: 12px; font-size: 13px; color: var(--muted); }
.model-logo { flex: none; width: 22px; height: 22px; object-fit: contain; }
.lab-models { display: flex; flex-wrap: wrap; gap: 8px; }
.candidate { position: relative; display: inline-flex; align-items: center; min-height: 44px; padding: 0 18px; border: 1px solid var(--raised); border-radius: 999px; cursor: pointer; transition: background-color 160ms var(--ease), color 160ms var(--ease), transform 160ms var(--ease); }
.candidate:active { transform: scale(.97); }
.candidate:has(input:checked) { background: var(--blue); border-color: var(--blue); color: var(--primary-ink); }
.candidate:has(input:focus-visible) { outline: 2px solid var(--text); outline-offset: 3px; }
.candidate input { appearance: none; position: absolute; opacity: 0; width: 100%; height: 100%; inset: 0; margin: 0; cursor: pointer; }
.candidate input:focus-visible { outline: none; }
.candidate-name { font-size: 14px; font-weight: 500; white-space: nowrap; }
/* The action stays in reach while the twelve-model ballot scrolls. */
.vote-action { position: sticky; bottom: 0; z-index: 1; padding: 20px 0 calc(16px + env(safe-area-inset-bottom)); background: var(--ground); }
.primary { display: flex; justify-content: center; align-items: center; gap: 12px; min-height: 48px; padding: 10px 28px; border-radius: 999px; background: var(--primary); color: var(--primary-ink); font-size: 14px; font-weight: 500; transition: transform 160ms var(--ease), opacity 160ms; }
#cast-vote { width: min(340px, 100%); margin-inline: auto; }
.primary:active { transform: scale(.975); }
.form-status { text-align: center; font-size: 12px; }
.form-status:not(:empty) { margin-top: 12px; }
.form-status[data-error] { color: var(--negative); }
/* After voting: one line under the ballot that leads back to the results. */
.vote-receipt { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0 10px; margin-top: 16px; font-size: 14px; color: var(--muted); }
#receipt-model { color: var(--text); }
.vote-receipt a { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; color: var(--text); font-weight: 500; }
.vote-receipt svg { width: 16px; height: 16px; }
.vote-receipt a:hover svg, .imprint-promo a:hover svg, .results-actions a:hover svg { transform: translateX(3px); }
a svg { transition: transform 160ms var(--ease); }
/* A plain line, no outline, so it never reads as a second button: "By imprint | AI that knows you →". */
.imprint-promo { display: flex; justify-content: center; margin-top: 48px; }
.imprint-card { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; font-size: 13px; color: var(--muted); }
.imprint-by { font-size: 12px; }
.imprint-card img { object-fit: contain; }
.imprint-rule { width: 1px; height: 18px; margin-inline: 6px; background: var(--raised); }
.imprint-line { color: var(--text); }
.imprint-card svg { width: 15px; height: 15px; }
/* Opening motion, like Clanker Chat: the masthead rises in line by line, then the ballot rows follow. */
@keyframes rise { from { opacity: 0; transform: translateY(12px); } }
.title-row > *, .lab, .vote-action, .imprint-promo, .fine-print { animation: rise 800ms var(--ease) both; }
.title-row > :nth-child(2) { animation-delay: 60ms; }
.title-row > :nth-child(3) { animation-delay: 120ms; }
.title-row > :nth-child(4) { animation-delay: 180ms; }
.lab:nth-of-type(1) { animation-delay: 220ms; }
.lab:nth-of-type(2) { animation-delay: 265ms; }
.lab:nth-of-type(3) { animation-delay: 310ms; }
.lab:nth-of-type(4) { animation-delay: 355ms; }
.lab:nth-of-type(5) { animation-delay: 400ms; }
.lab:nth-of-type(6) { animation-delay: 445ms; }
.lab:nth-of-type(7) { animation-delay: 490ms; }
.lab:nth-of-type(n + 8) { animation-delay: 535ms; }
.vote-action { animation-delay: 380ms; }
.imprint-promo, .fine-print { animation-delay: 600ms; }
.fine-print { display: flex; justify-content: center; gap: 12px; margin: 24px 0 30px; color: var(--muted); font-size: 12px; }
.fine-print a:hover { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
dialog { width: min(640px, calc(100% - 32px)); max-height: calc(100dvh - 32px); overflow-y: auto; overscroll-behavior: contain; padding: 28px; border: 0; border-radius: var(--radius); background: var(--ground); color: var(--text); }
dialog[open] { animation: dialog-in 260ms var(--ease) both; }
@keyframes dialog-in { from { opacity: 0; transform: translateY(8px); } }
dialog::backdrop { background: rgb(22 22 22 / .5); }
.dialog-heading { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
h2 { font: 400 28px/1.15 var(--serif); letter-spacing: -.025em; }
.dialog-close { display: inline-flex; justify-content: center; align-items: center; min-height: 44px; font-size: 13px; background: transparent; padding: 0 4px; }
.dialog-close:hover { text-decoration: underline; text-underline-offset: 4px; }
.race-total { margin-top: 4px; font-size: 13px; color: var(--muted); }
/* Parliament-style hemicycle: 100 seats split by vote share. Leader blue, second red, third ink. */
.hemicycle-wrap { position: relative; max-width: 520px; margin: 20px auto 0; }
.hemicycle { display: block; width: 100%; height: auto; overflow: visible; }
.seats.blue { fill: var(--blue); }
.seats.red { fill: var(--red); }
.seats.ink { fill: var(--text); }
.seats.rest { fill: var(--border); }
.seats.empty { fill: var(--surface); }
/* Seats sweep in wedge by wedge whenever the dialog opens or the counts change. */
.seats { transform-box: view-box; transform-origin: 100px 100px; animation: seats-in 700ms var(--ease) both; }
.seats:nth-child(2) { animation-delay: 90ms; }
.seats:nth-child(3) { animation-delay: 180ms; }
.seats:nth-child(n + 4) { animation-delay: 270ms; }
@keyframes seats-in { from { opacity: 0; transform: scale(.94); } }
.leader { position: absolute; left: 50%; bottom: 0; transform: translateX(-50%); width: 40%; display: grid; justify-items: center; gap: 2px; text-align: center; }
.leader-logos { display: flex; gap: 6px; margin-bottom: 4px; }
.leader-logos img { object-fit: contain; }
.leader-share { font: 400 52px/1 var(--serif); letter-spacing: -.03em; color: var(--blue); }
.leader-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 500; }
.results-actions { display: flex; justify-content: center; margin-top: 24px; }
#results-x { width: min(340px, 100%); }
.ranking { list-style: none; margin-top: 24px; padding-top: 8px; border-top: 1px solid var(--surface); }
.rank-row { display: grid; grid-template-columns: 18px 10px 20px minmax(0, 1fr) auto 52px; align-items: center; gap: 10px; padding: 8px 0; }
.rank { font-size: 12px; color: var(--muted); text-align: right; }
.swatch { width: 10px; height: 10px; border-radius: 50%; background: var(--border); }
.rank-row.blue .swatch { background: var(--blue); }
.rank-row.red .swatch { background: var(--red); }
.rank-row.ink .swatch { background: var(--text); }
.rank-row.none .swatch { background: transparent; border: 1px solid var(--raised); }
.rank-row img { object-fit: contain; }
.rank-name { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; min-width: 0; font-size: 14px; font-weight: 500; }
.rank-row.none .rank-name, .rank-row.none .rank-share { color: var(--muted); }
.rank-votes { font-size: 12px; color: var(--muted); white-space: nowrap; }
.rank-share { font-size: 14px; text-align: right; }
.rank-row.blue .rank-share { color: var(--blue); }
.rank-row.red .rank-share { color: var(--red); }
.your-choice { font-size: 11px; font-weight: 400; color: var(--muted); white-space: nowrap; }
/* The visitor's own pick gets a soft band, so it's easy to find right after voting. */
.rank-row.mine { margin-inline: -10px; padding-inline: 10px; border-radius: 8px; background: var(--surface); }
.past-terms { margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--surface); }
.past-terms h3 { font-size: 13px; font-weight: 400; color: var(--muted); }
.past-terms ol { list-style: none; margin-top: 4px; }
.past-terms li { display: grid; grid-template-columns: 64px auto minmax(0, 1fr) 52px; align-items: center; gap: 10px; padding: 8px 0; }
.past-term { font-size: 12px; color: var(--muted); }
.past-logos { display: flex; gap: 4px; }
.past-logos img { object-fit: contain; }
.results-footer { display: flex; justify-content: space-between; align-items: center; margin-top: 12px; }
.text-button { display: inline-flex; gap: 7px; align-items: center; justify-content: center; padding: 8px 0; min-height: 44px; font-size: 12px; background: transparent; }
.text-button:hover { text-decoration: underline; text-underline-offset: 4px; }
#results-status:not(:empty) { margin-top: 8px; }
.about-dialog h3 { font-size: 14px; font-weight: 500; margin: 24px 0 8px; }
.about-dialog > p { font-size: 14px; color: var(--muted); }
.about-dialog p a { text-decoration: underline; text-underline-offset: 3px; }
.about-dialog .credits { font-size: 12px; margin-top: 24px; }
.legal-links { display: flex; gap: 20px; margin-top: 20px; font-size: 12px; }
/* Hover fills only where there is a pointer, so taps on phones don't leave pills highlighted. */
@media (hover: hover) {
  .candidate:hover:not(:has(input:checked)) { background: var(--surface); }
  .primary:hover { opacity: .88; }
  .incumbent:hover { background: var(--raised); }
  .imprint-card:hover .imprint-line { text-decoration: underline; text-underline-offset: 3px; }
}
@media (min-width: 1800px) { .title-row { padding-top: 72px; } }
@media (max-width: 760px) {
  .bar { padding-inline: 20px; min-height: 64px; }
  .title-row { padding-top: 32px; }
  h1 { font-size: clamp(42px, 10vw, 72px); }
  .title-row .lede { font-size: 16px; max-width: 30ch; margin-top: 20px; }
}
@media (max-width: 480px) {
  .frame { width: calc(100% - 32px); }
  .bar { padding-inline: 16px; }
  .brand { font-size: 17px; gap: 11px; }
  .brand svg { width: 21px; height: 21px; }
  .bar nav a { font-size: 13px; }
  .title-row { padding: 24px 0 28px; }
  h1 { font-size: clamp(38px, 10.4vw, 49px); }
  .lab { grid-template-columns: 76px minmax(0, 1fr); gap: 12px; min-height: 64px; padding: 8px 0; }
  .lab-name { flex-direction: column; align-items: flex-start; gap: 6px; font-size: 11px; line-height: 1.2; }
  .model-logo { width: 20px; height: 20px; }
  .candidate { padding: 0 12px; }
  .candidate-name { font-size: 13px; }
  .vote-action { padding-top: 24px; }
  .imprint-promo { margin-top: 40px; }
  /* Dialogs become bottom sheets: full width, thumb-reachable, clear of the home indicator. */
  dialog { width: 100%; max-width: none; margin: auto 0 0; max-height: calc(100dvh - 16px); border-radius: 16px 16px 0 0; padding: 0 20px calc(24px + env(safe-area-inset-bottom)); }
  dialog[open] { animation: sheet-in 340ms var(--ease) both; }
  .dialog-heading { position: sticky; top: 0; z-index: 1; padding: 14px 0 6px; background: var(--ground); }
  .dialog-heading h2 { font-size: 26px; }
  .leader { width: 46%; }
  .leader-logos img { width: 22px; height: 22px; }
  .leader-share { font-size: 36px; }
  .leader-name { font-size: 12px; }
  .rank-row { grid-template-columns: 16px 10px 20px minmax(0, 1fr) 50px; gap: 9px; }
  .rank-votes { display: none; }
}
/* Smallest phones (iPhone SE 1st gen, small Androids): the header must fit 320px without scrolling sideways. */
@media (max-width: 359px) {
  .brand { font-size: 15px; gap: 9px; }
  .brand svg { width: 19px; height: 19px; }
  .bar nav a svg { display: none; }
  .lab { grid-template-columns: 64px minmax(0, 1fr); }
}
/* Phones held sideways: little height, so the masthead tightens and the results chart is capped. */
@media (max-height: 480px) and (orientation: landscape) {
  .bar { min-height: 52px; padding-block: 6px; }
  .title-row { padding: 8px 0 16px; }
  .term-line { margin-bottom: 8px; }
  h1 { font-size: 40px; }
  .title-row .lede { margin-top: 8px; font-size: 15px; }
  .vote-action { padding: 10px 0 calc(8px + env(safe-area-inset-bottom)); }
  dialog { max-height: calc(100dvh - 16px); padding: 20px 24px; }
  .hemicycle-wrap { max-width: 300px; margin-top: 12px; }
  .leader-share { font-size: 32px; }
  .leader-logos img { width: 20px; height: 20px; }
}
@keyframes sheet-in { from { transform: translateY(40px); opacity: .4; } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; animation: none !important; } }
