
/* ═══════════════════════════════════════════════════════
   CAMPANHA BRASIL — Design System v97 (linguagem de jogo, pixel art)
   Toda decisão visual mora aqui, em custom properties.
   Para retematizar: mexa nos valores do :root.

   A régua é a arte do próprio jogo (as telas de vitória): ilustração
   em pixel art, moldura de traço grosso, paleta noturna quente e
   letra condensada em caixa alta nas faixas. Daí saem as convenções:
     · matiz único de ameixa nos dois temas, nunca cinza neutro;
     · borda de 2px (--ds-border-w): em pixel art a borda é traço;
     · sombra deslocada e SEM desfoque — bloco de cor, não luz difusa;
     · canto reto ou quase (--ds-r-* perto de zero);
     · três vozes tipográficas, cada uma com um trabalho (ver abaixo);
     · foco visível com anel de 2px + offset em tudo que é focável.

   O encanamento herdado da fase anterior continua valendo e independe
   de estilo: tokens como fonte única, contraste AA medido nos dois
   temas, escala de fonte real via --ds-fs, acessibilidade por teclado.
   ═══════════════════════════════════════════════════════ */
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&family=Oswald:wght@500;600;700&family=Silkscreen:wght@400;700&display=swap');

/* ── Tokens ── */
:root {
  /* Background layers — ameixa dessaturada, não zinc.
     Os dois temas partilham a mesma família de matiz: o claro é a versão pálida,
     o escuro a versão profunda. Dá parentesco entre eles e afasta o cinza neutro
     que é a assinatura do visual gerado por IA. */
  --ds-bg:          #f6f4f8;
  --ds-surface:     #ffffff;
  --ds-surface-2:   #f0edf3;
  --ds-surface-3:   #e3dee9;

  /* Borders */
  --ds-border:      #e3dee9;
  --ds-border-2:    #cdc5d6;
  /* Borda de 2px: em pixel art a borda é traço, não fio. Substitui o 1px do
     shadcn nas superfícies que o jogador manipula. */
  --ds-border-w:    2px;

  /* Text — o shadcn só tem foreground + muted-foreground; o jogo precisa de um
     terceiro nível, então text-2 desce um degrau (zinc-600) e text-3 assume o
     muted-foreground do shadcn (zinc-500). Nesta escala os três níveis passam
     em AA sobre --ds-surface, o que não acontecia com zinc-400 em texto de 11px.
     O texto base é zinc-700, cinza e não preto: 10,3:1 sobre branco, ainda
     folgado em AAA, com leitura bem mais macia do que o quase-preto do zinc-950. */
  --ds-text:        #2f2836;
  --ds-text-2:      #574d61;
  --ds-text-3:      #70667a;

  /* Brand accent (primary) — green-700, e não green-600: é o tom mais claro em
     que texto branco ainda passa em AA por cima (4,6:1), o que o botão primário
     e os rótulos verdes exigem. */
  --ds-accent:      #15803d;
  --ds-accent-hov:  #166534;
  --ds-accent-fg:   #ffffff;
  --ds-accent-bg:   #f0fdf4;
  --ds-accent-mid:  #bbf7d0;

  /* Anel de foco — mesma cor da marca, como num tema shadcn customizado */
  --ds-ring:        #15803d;

  /* Amarelo do ícone da marca (ver src/view.php). Decorativo, sempre acompanhado do
     texto, mas escurecido no tema claro para não sumir sobre o branco. */
  --ds-brand-y:     #ca8a04;

  /* Cenário da semana — bege */
  --ds-beige:       #7d5f37;
  --ds-beige-bg:    #f7f1e6;
  --ds-beige-mid:   #e6d7ba;

  /* Semantic — --ds-green é usado só como cor de TEXTO no jogo (nunca como
     preenchimento), então segue o mesmo green-700 do accent. */
  --ds-green:       #15803d;
  --ds-green-bg:    #f0fdf4;
  --ds-green-mid:   #bbf7d0;
  --ds-red:         #b91c1c;
  --ds-red-bg:      #fef2f2;
  --ds-red-mid:     #fecaca;
  --ds-amber:       #b45309;
  --ds-amber-bg:    #fffbeb;
  --ds-amber-mid:   #fde68a;

  /* Estados ainda não apurados no mapa da eleição (o SVG grava fill no elemento,
     então precisa de um token — em dark mode o bege claro ficava ilegível) */
  --ds-map-idle:    #e3dee9;

  /* Estado "apurando" (sigla piscando na grade e no mapa) — amarelo FIXO, sem
     variante escura de propósito: é um estado de processo, não um dado do jogo.
     Se seguisse --ds-amber, no tema escuro piscaria num marrom-avermelhado que
     se confunde com a cor de um candidato. */
  --ds-counting:    #fef3c7;
  --ds-counting-2:  #fde047;
  --ds-counting-fg: #422006;

  /* Radius — pixel art não tem curva suave: o canto é reto ou quase.
     --ds-r-pill mantém o nome (usado em 12 lugares) mas deixou de ser cápsula:
     barra arredondada briga com o traço quadrado do resto. */
  --ds-r-sm:        0;
  --ds-r-md:        2px;
  --ds-r-lg:        2px;
  --ds-r-xl:        4px;
  --ds-r-pill:      2px;

  /* Shadow — deslocada e SEM desfoque. Sombra borrada pressupõe luz difusa e
     antisserrilhado; pixel art trabalha com bloco de cor. */
  --ds-shadow-sm:   2px 2px 0 rgba(47,40,54,.10);
  --ds-shadow:      3px 3px 0 rgba(47,40,54,.13);
  --ds-shadow-md:   4px 4px 0 rgba(47,40,54,.16);
  --ds-shadow-lg:   6px 6px 0 rgba(47,40,54,.20);

  /* Typography ──────────────────────────────────────────────────────────────
     --ds-fs é a escala de fonte do jogador (botões A− / A+ do topo). Todo
     tamanho de texto do jogo é derivado dela, então mexer nesta única variável
     aumenta ou diminui a tipografia inteira — sem ampliar o layout, que é o que
     o zoom fazia. Quem escreve --ds-fs é cbHdrFont(), em topbar.php.
     REGRA: nenhum font-size em px solto no código. Se faltar um degrau, o degrau
     entra aqui — senão ele não acompanha o A−/A+ e a escala racha. */
  --ds-fs:          1;

  /* Três vozes, cada uma com um trabalho ─────────────────────────────────────
     --ds-font          corpo: IBM Plex Sans. Legível em texto corrido e denso.
     --ds-font-display  números e títulos: Oswald. Condensada, ecoa a letra
                        pintada das faixas na arte do jogo, e economiza largura.
     --ds-font-label    rótulos CURTOS em caixa alta: Silkscreen, pixel.
                        NUNCA em número: testado, "34%" fica ilegível (o 3 vira
                        E espelhado, o 4 vira Z). E nunca em texto corrido.
     Peso: Oswald vai só até 700 — em condensada, o 700 pesa como o 900 de uma
     sans normal, então os antigos 800/900 viraram 600/700 aqui. */
  --ds-font:         'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  --ds-font-display: 'Oswald', 'IBM Plex Sans', system-ui, sans-serif;
  --ds-font-label:   'Silkscreen', 'Oswald', ui-monospace, monospace;
  --ds-size-3xs:    calc(9px  * var(--ds-fs));
  --ds-size-2xs:    calc(10px * var(--ds-fs));
  --ds-size-xs:     calc(11px * var(--ds-fs));
  /* (os dois acima são os tamanhos em que a fonte pixel aparece — ver o
     @supports logo abaixo do :root, que os arredonda para pixel inteiro) */
  --ds-size-sm:     calc(12px * var(--ds-fs));
  --ds-size-base:   calc(13px * var(--ds-fs));
  --ds-size-md:     calc(14px * var(--ds-fs));
  --ds-size-lg:     calc(16px * var(--ds-fs));
  --ds-size-xl:     calc(20px * var(--ds-fs));
  --ds-size-2xl:    calc(24px * var(--ds-fs));
  --ds-size-3xl:    calc(34px * var(--ds-fs));

  /* Spacing */
  --ds-space-1:     4px;
  --ds-space-2:     8px;
  --ds-space-3:     12px;
  --ds-space-4:     16px;
  --ds-space-5:     20px;
  --ds-space-6:     24px;

  /* Motion */
  --ds-ease:        cubic-bezier(.4,0,.2,1);
  --ds-duration:    150ms;
}

/* Fonte pixel só fica com o corte seco em tamanho de pixel INTEIRO. Como os
   tamanhos derivam de --ds-fs (0,85 / 1 / 1,15 / 1,3), o A− produzia 8,5px e o
   A+ 11,5px — meio pixel, e a letra amolece. round() resolve; fica dentro de
   @supports porque, sem suporte, um valor inválido aqui derrubaria o token
   inteiro e o texto perderia o tamanho. Sem round() a escala segue como antes. */
@supports (font-size: round(10px, 1px)) {
  :root {
    --ds-size-2xs: round(calc(10px * var(--ds-fs)), 1px);
    --ds-size-xs:  round(calc(11px * var(--ds-fs)), 1px);
  }
}

/* ── Reset ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0 }
html, body {
  margin: 0; padding: 0;
  font-family: var(--ds-font);
  background: var(--ds-bg);
  color: var(--ds-text);
  font-size: var(--ds-size-md);
  line-height: 1.5;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  /* Sem isto o navegador espera ~300ms por um duplo-toque antes de disparar o
     clique, e pinta um retângulo cinza próprio por cima do nosso estado :active. */
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* Diz ao navegador em que tema a página está, para que o que ele desenha sozinho
   — scrollbars, campos nativos, menu do <select> — acompanhe. Sem isto, o tema
   escuro fica com barras de rolagem e dropdowns claros. */
:root { color-scheme: light }
[data-theme="dark"] { color-scheme: dark }

/* ── Movimento ──
   Quem pediu menos animação no sistema recebe menos animação: confete, pulso da
   apuração e destaque do feed param, e as transições viram instantâneas. O jogo
   segue funcionando — nada aqui depende da animação para comunicar estado. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Escolhas que são <button> ──
   Cartão de ação, cartão de partido e célula de estado precisam ser <button>
   para funcionar no teclado e serem anunciados como controle. Estas regras
   devolvem a eles a aparência de cartão/célula que sempre tiveram. */
button.card, button.pcard, button.sc {
  display: block; width: 100%;
  font: inherit; color: inherit;
  -webkit-appearance: none; appearance: none;
}
button.card, button.pcard { text-align: left }
button.sc { text-align: center }

/* ── Foco visível ──
   Assinatura do shadcn: anel de 2px com offset em tudo que recebe foco.
   Substitui o outline padrão do navegador (que o jogo não tinha estilizado). */
:focus-visible {
  outline: 2px solid var(--pc-now);
  outline-offset: 2px;
  border-radius: var(--ds-r-sm);
}

/* ── Screens ── */
/* min-height alto o bastante para a tela não parecer inacabada quando o
   conteúdo é curto, e baixo o bastante para o rodapé legal não ficar sempre uma
   janela inteira abaixo. Com 100vh ele nascia fora da vista em toda tela do
   jogo — no ranking aparecia porque lá não existe .screen. */
.screen { display: none; min-height: 62vh }
/* Troca de tela: antes era corte seco (só o display trocando).
   É ANIMAÇÃO, não transição — de display:none para display:block a transição
   não tem estado inicial para partir e nunca roda; a animação roda. Curta de
   propósito: aqui não há nada a narrar, é só a tela mudando. Onde HÁ o que
   contar (semana → relatório → apuração) continua valendo o loading narrado,
   que é outra coisa. Quem pediu menos animação já é atendido pela regra de
   prefers-reduced-motion lá em cima, que zera a duração. */
@keyframes cb-tela-entra {
  from { opacity: 0; transform: translateY(10px) }
  to   { opacity: 1; transform: none }
}
.screen.active { display: block; animation: cb-tela-entra 240ms ease-out both }
.hidden { opacity: 0; pointer-events: none }
.wrap { max-width: 520px; margin: 0 auto; padding: var(--ds-space-4) var(--ds-space-4) 16px }

/* ── Header ── */
.hdr {
  background: var(--ds-surface);
  padding: 12px var(--ds-space-4);
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--ds-border);
  position: sticky; top: 0; z-index: 100;
}
/* Só posicionamento: tipografia e cores da marca são do componente .logo.
   Havia aqui um '.hdr-logo span { color: accent }' que pintava de verde QUALQUER
   span dentro do link — e depois que a marca virou componente isso passou a
   incluir o "Campanha", que deve ficar na cor do texto. */
.hdr-logo { display: inline-flex; align-items: center; text-decoration: none; color: inherit }

/* ── Marca ──────────────────────────────────────────────────────────────────
   Montada só por cb_logo() (src/view.php). Ícone amarelo, "Campanha" na cor
   do texto e "Brasil" no verde. Mesmo bloco no topo, na tela inicial, no
   overlay de carregamento e no ranking — mudar aqui muda em todos. */
.logo { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap }
.logo-icone { color: var(--ds-brand-y); flex-shrink: 0 }

/* Botão de fonte: largura fixa para o "A" crescer a cada passo sem empurrar a
   barra — o próprio tamanho da letra é o indicador do nível. */
.btn-fonte { width: 30px; padding: 4px 0; display: inline-flex; align-items: center; justify-content: center }

.logo-txt {
  font-family: var(--ds-font-label);
  font-size: var(--ds-size-base);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ds-text);
  line-height: 1.5;
}
/* Verde um degrau mais escuro que --ds-accent: sobre o fundo da página, que
   ainda leva a lavagem da cor da campanha, o accent caía para 4,23:1. */
.logo-br { color: #166534; margin-left: .45em }
.logo-lg .logo-icone { color: var(--ds-brand-y) }
.logo-lg .logo-txt { font-size: var(--ds-size-lg) }

/* ── Content area ── */
.content { background: var(--ds-bg); min-height: calc(100vh - 49px); max-width: 640px; margin: 0 auto; padding: var(--ds-space-4) var(--ds-space-4) 16px }

/* ── Loading overlay ── */
#load-overlay {
  position: fixed; inset: 0;
  background: rgba(250,250,250,.9);
  backdrop-filter: blur(6px);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  z-index: 9999; padding: var(--ds-space-6);
  transition: opacity .3s var(--ds-ease);
}
.load-icon { margin-bottom: var(--ds-space-3); color: var(--ds-text-2) }
.load-title {
  font-family: var(--ds-font-label); font-size: var(--ds-size-xs); font-weight: 400;
  letter-spacing: .02em; text-transform: uppercase;
  color: var(--ds-text); margin-bottom: var(--ds-space-2);
}
.load-msg {
  font-family: var(--ds-font-display); font-size: var(--ds-size-lg); font-weight: 700; letter-spacing: 0; color: var(--ds-text);
  text-align: center; max-width: 340px; line-height: 1.45; margin-bottom: var(--ds-space-1);
}
.load-sub {
  font-size: var(--ds-size-base); color: var(--ds-text-2);
  text-align: center; max-width: 300px; line-height: 1.6; min-height: 52px;
}
.load-bar-bg { width: 220px; height: 6px; background: var(--ds-surface-3); border-radius: var(--ds-r-pill); margin-top: var(--ds-space-4); overflow: hidden }
.load-bar-fill { height: 100%; background: var(--ds-accent); border-radius: var(--ds-r-pill); transition: width .4s var(--ds-ease) }

/* ── Cards ──
   shadcn Card: rounded-lg border bg-card shadow-sm. */
.card {
  background: var(--ds-surface);
  border: var(--ds-border-w) solid var(--ds-border);
  border-radius: var(--ds-r-lg);
  padding: var(--ds-space-4);
  margin-bottom: var(--ds-space-3);
  box-shadow: var(--ds-shadow-sm);
}
.card-green { background: var(--ds-green-bg); border-color: var(--ds-green-mid) }
.card-red { background: var(--ds-red-bg); border-color: var(--ds-red-mid) }

/* ── Section heading ──
   Equivalente ao CardTitle do shadcn: semibold, caixa normal, tracking apertado. */
.section-hd {
  font-family: var(--ds-font-display); font-size: var(--ds-size-lg); font-weight: 600;
  letter-spacing: .01em;
  color: var(--ds-text); margin-bottom: var(--ds-space-3);
  padding-bottom: var(--ds-space-2); border-bottom: 1px solid var(--ds-border);
  display: flex; align-items: center; gap: 6px;
}

/* ── Buttons ──
   shadcn Button: altura ~36px, texto sm/medium, radius md, transição só de cor
   (sem deslocamento no hover), sombra sm nas variantes sólida e outline. */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--ds-space-2);
  min-height: 36px;
  padding: 8px var(--ds-space-4);
  border-radius: var(--ds-r-md);
  border: var(--ds-border-w) solid var(--ds-border-2);
  background: var(--ds-surface);
  color: var(--ds-text);
  font-size: var(--ds-size-base); font-weight: 500;
  font-family: var(--ds-font);
  cursor: pointer; text-align: center; line-height: 1.3;
  transition: background-color var(--ds-duration) var(--ds-ease),
              border-color var(--ds-duration) var(--ds-ease),
              color var(--ds-duration) var(--ds-ease);
  box-shadow: var(--ds-shadow-sm);
}
.btn:hover { background: var(--ds-surface-2) }
.btn-primary { background: var(--ds-accent); color: var(--ds-accent-fg); border-color: var(--ds-accent); font-weight: 500; width: auto; margin: .3rem auto }
.btn-primary:hover { background: var(--ds-accent-hov); border-color: var(--ds-accent-hov) }
/* variante ghost */
.btn-skip { background: transparent; color: var(--ds-text-2); border-color: transparent; box-shadow: none; font-size: var(--ds-size-base); font-weight: 500 }
.btn-skip:hover { background: var(--ds-surface-2); color: var(--ds-text) }
/* variante outline, largura cheia e conteúdo à esquerda */

/* Estado selecionado — equivalente ao Toggle data-state=on do shadcn.
   Genérico (não preso a .btn): vale também para .pcard, que recebe .selected
   quando o jogador escolhe o partido aliado. */
.selected {
  border-color: var(--ds-accent) !important;
  background: var(--ds-accent-bg) !important;
  color: var(--ds-accent);
  box-shadow: var(--ds-shadow-sm);
}
/* Ação escolhida — o card GANHA peso, não perde.
   Antes o card escolhido ia a opacity .6 e o card que deixou de estar
   disponível ia a .45: escolher e não poder escolher ficavam quase iguais na
   tela, e a escolha lia como "desativei isto". Agora o escolhido fica aceso, na
   cor da campanha (--pc-now, que já resolve o par claro/escuro), e só o não
   escolhido apaga. Reaproveita .selected, que já é o estado "escolhido" do
   sistema — o hover do próprio card já perguntava por essa classe, mas nada a
   aplicava. */
.card.selected {
  border-color: var(--pc-now) !important;
  background: color-mix(in srgb, var(--pc-now) 10%, var(--ds-surface)) !important;
  color: var(--ds-text);
  box-shadow: var(--ds-shadow-md);
  opacity: 1 !important;
}
/* O carimbo da escolha: chapa cheia na cor da campanha, não um texto apagado.
   O par background:--pc-now / color:--ds-surface é o mesmo de .wdot.done, e é o
   que faz o carimbo funcionar nos DOIS temas: no claro --pc-now é a variante
   escura da cor (texto branco por cima), no escuro é a clareada (texto na cor
   do painel por cima). Texto fixo em #fff daria 3,2:1 no tema escuro. */
.pick-check {
  display: inline-flex; align-items: center; gap: 4px;
  margin-top: var(--ds-space-2); padding: 2px 8px;
  border-radius: var(--ds-r-md);
  background: var(--pc-now); color: var(--ds-surface);
  font-size: var(--ds-size-2xs); font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
}

/* As duas vagas da semana — a regra de "até duas ações" virou objeto na tela.
   Vaga vazia é contorno tracejado e apagado; vaga preenchida usa o MESMO
   carimbo do card escolhido (--pc-now sobre --ds-surface), para as duas coisas
   lerem como o mesmo gesto. */
.slots { display: flex; gap: var(--ds-space-2); margin-bottom: 10px }
.slot {
  flex: 1 1 0; min-width: 0;
  display: flex; align-items: center; gap: 4px;
  padding: 6px 8px;
  border: var(--ds-border-w) dashed var(--ds-border);
  border-radius: var(--ds-r-md);
  background: transparent;
  /* --ds-text-2, não --ds-text-3: medido contra o fundo lavado pela cor da
     campanha, o -3 cai a 4,45:1 com os candidatos de vermelho — abaixo de AA.
     Quem diz que a vaga está vazia é o contorno tracejado, não um texto fraco. */
  color: var(--ds-text-2);
  font-size: var(--ds-size-2xs); font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden;
}
.slot-on {
  border-style: solid; border-color: var(--pc-now);
  background: var(--pc-now); color: var(--ds-surface);
  text-transform: none; letter-spacing: 0;
}
.slot-on span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap }

.btn.disabled, .btn:disabled, button:disabled {
  opacity: .5 !important;
  pointer-events: none !important;
  cursor: not-allowed !important;
}

/* Botões de ícone do topo — variante outline quadrada do shadcn */
.btn-theme-toggle {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  min-height: 30px; padding: 4px 10px;
  background: var(--ds-surface); color: var(--ds-text);
  border: 1px solid var(--ds-border-2); border-radius: var(--ds-r-md);
  font-size: var(--ds-size-sm); font-weight: 500; font-family: var(--ds-font);
  cursor: pointer; box-shadow: var(--ds-shadow-sm);
  transition: background-color var(--ds-duration) var(--ds-ease), color var(--ds-duration) var(--ds-ease);
}
.btn-theme-toggle:hover { background: var(--ds-surface-2) }
.btn-theme-toggle svg { vertical-align: middle }

/* ── Party cards ── */
.party-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ds-space-2); margin-top: var(--ds-space-3) }
.pcard {
  background: var(--ds-surface); border: var(--ds-border-w) solid var(--ds-border);
  border-radius: var(--ds-r-lg); padding: var(--ds-space-3);
  cursor: pointer; box-shadow: var(--ds-shadow-sm);
  transition: background-color var(--ds-duration) var(--ds-ease), border-color var(--ds-duration) var(--ds-ease);
}
.pcard:hover { background: var(--ds-surface-2); border-color: var(--ds-border-2) }
/* Chip da sigla do partido — fundo no tom do próprio partido, mas só 6% de
   tinta sobre branco. Mais tinta escurece o fundo e derruba o contraste: a 9,4%
   (o que vinha inline) a cor do 'esquerda' ficava em 4,25:1; a 6% sobe para
   4,53:1. Claro nos dois temas, por isso o texto usa sempre --cc (a variante
   para fundo claro), inclusive no escuro. */
.pcard-sigla {
  font-family: var(--ds-font-label); font-size: var(--ds-size-base); font-weight: 700; line-height: 1.3; letter-spacing: .02em;
  display: inline-block; border-radius: var(--ds-r-sm); padding: 2px 8px;
  background: #ffffff;
  background: color-mix(in srgb, var(--cc) 6%, #ffffff);
  border: 1px solid var(--ds-border);
  border: 1px solid color-mix(in srgb, var(--cc) 28%, #ffffff);
  color: var(--cc);
}
/* (a exceção de tema para este chip mora junto da regra genérica de --cc, mais
   abaixo: lá as duas têm a mesma especificidade e vence quem vem por último) */
.pcard-name { font-size: var(--ds-size-sm); color: var(--ds-text-2); margin-top: 2px }
.pcard-desc { font-size: var(--ds-size-sm); color: var(--ds-text-2); line-height: 1.5; margin-top: var(--ds-space-1) }
.pcard-stats { display: flex; gap: var(--ds-space-2); margin-top: var(--ds-space-1); font-size: var(--ds-size-xs); color: var(--ds-text-2); flex-wrap: wrap }

/* ── Week dots ── */
.wdots { display: flex; gap: 6px; margin-bottom: var(--ds-space-3); flex-wrap: wrap; align-items: center }
.wdot { width: 24px; height: 24px; border-radius: var(--ds-r-md); background: var(--ds-surface-2); border: 1px solid var(--ds-border); flex-shrink: 0; transition: background-color var(--ds-duration) var(--ds-ease), border-color var(--ds-duration) var(--ds-ease), color var(--ds-duration) var(--ds-ease), box-shadow var(--ds-duration) var(--ds-ease); display: inline-flex; align-items: center; justify-content: center; font-size: var(--ds-size-xs); font-weight: 500; color: var(--ds-text-2) }
.wdot.done { background: var(--pc-now); border-color: var(--pc-now); color: var(--ds-surface) }
.wdot.active,
.wdot.current { background: var(--pc-now); border-color: var(--pc-now); color: var(--ds-surface); box-shadow: 0 0 0 3px color-mix(in srgb, var(--pc-now) 25%, transparent) }

/* ── Badges & tags ──
   shadcn Badge: rounded-md, borda 1px, text-xs semibold, px-2.5 py-0.5. */
.tag-row { display: flex; gap: var(--ds-space-1); flex-wrap: wrap; margin-bottom: var(--ds-space-2) }
.badge { display: inline-flex; align-items: center; padding: 2px 10px; border-radius: var(--ds-r-md); font-size: var(--ds-size-xs); font-weight: 600; line-height: 1.45; border: 1px solid transparent }
.b-yellow { background: var(--ds-amber-bg); color: var(--ds-amber); border-color: var(--ds-amber-mid) }
.b-green { background: var(--ds-green-bg); color: #166534; border-color: var(--ds-green-mid) }

/* ── Stats row ──
   Cartão de métrica do dashboard shadcn: valor grande semibold, rótulo em
   caixa normal com a cor muted (sem micro-caps). */
.stats-row { display: flex; gap: var(--ds-space-2); margin-bottom: var(--ds-space-4) }
.stat-c { flex: 1; background: var(--ds-surface); border: var(--ds-border-w) solid var(--ds-border); border-radius: var(--ds-r-lg); padding: var(--ds-space-3) var(--ds-space-2); text-align: center; box-shadow: var(--ds-shadow-sm) }
.stat-v { font-family: var(--ds-font-display); font-size: var(--ds-size-2xl); font-weight: 700; letter-spacing: 0; line-height: 1.1; font-variant-numeric: tabular-nums }
.stat-l { font-family: var(--ds-font-label); font-size: var(--ds-size-2xs); color: var(--ds-text-2); margin-top: var(--ds-space-2); font-weight: 400; text-transform: uppercase; letter-spacing: .02em }

/* ── Tabs ──
   shadcn Tabs: TabsList é um trilho com fundo muted e cantos arredondados;
   o gatilho ativo vira um "cartão" claro com sombra sm. Antes essa aparência
   vinha de style inline no ui.js (que anulava por completo as regras daqui);
   agora mora só neste bloco. */
.tab-list {
  display: flex; align-items: center; gap: var(--ds-space-1);
  background: var(--ds-surface-2);
  border-radius: var(--ds-r-lg);
  padding: var(--ds-space-1);
  margin: var(--ds-space-3) 0;
}
.tab-btn {
  flex: 1;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 6px 10px;
  border: none; background: transparent;
  border-radius: var(--ds-r-md);
  font-family: var(--ds-font); font-size: var(--ds-size-base); font-weight: 500;
  color: var(--ds-text-2); cursor: pointer;
  transition: background-color var(--ds-duration) var(--ds-ease), color var(--ds-duration) var(--ds-ease);
}
.tab-btn:hover:not(.active) { color: var(--ds-text) }
.tab-btn.active { background: var(--ds-surface); color: var(--ds-text); box-shadow: var(--ds-shadow-sm) }

/* ── Event boxes ── */
.evbox { padding: 10px 12px; border-radius: var(--ds-r-lg); font-size: var(--ds-size-base); margin-bottom: 5px; line-height: 1.55; border: var(--ds-border-w) solid var(--ds-border); background: var(--ds-surface) }
.ev-pos { background: var(--ds-surface); border-color: var(--ds-border) }
.ev-warn { background: var(--ds-surface); border-color: var(--ds-border) }
.ev-neu { background: var(--ds-surface); border-color: var(--ds-border) }

/* ── Alerts — shadcn Alert (rounded-lg border p-4) ── */
.alert-danger { background: var(--ds-red-bg); border: 1px solid var(--ds-red-mid); border-radius: var(--ds-r-lg); padding: 10px 12px; font-size: var(--ds-size-base); margin-bottom: var(--ds-space-2); color: var(--ds-red) }
.alert-warn { background: var(--ds-amber-bg); border: 1px solid var(--ds-amber-mid); border-radius: var(--ds-r-lg); padding: 10px 12px; font-size: var(--ds-size-base); margin-bottom: var(--ds-space-2); color: var(--ds-amber) }

/* ── Election / Score ── */
.score-board { display: flex; align-items: center; justify-content: center; gap: var(--ds-space-4); padding: var(--ds-space-4) var(--ds-space-3); background: var(--ds-surface); border-radius: var(--ds-r-xl); border: var(--ds-border-w) solid var(--ds-border); box-shadow: var(--ds-shadow-sm); margin-bottom: var(--ds-space-4) }
.score-side { text-align: center; flex: 1 }
.score-num { font-family: var(--ds-font-display); font-size: calc(clamp(22px,7vw,42px) * var(--ds-fs)); font-weight: 700; letter-spacing: 0; line-height: 1; font-variant-numeric: tabular-nums }
.score-sub { font-size: var(--ds-size-sm); color: var(--ds-text-2); margin-top: 3px }
.score-vs { font-size: var(--ds-size-base); color: var(--ds-text-3) }

/* ── Commentary ── */
.alog { max-height: 220px; overflow-y: auto; margin-top: var(--ds-space-2) }

/* ── Misc ── */
.br-stripe { height: 3px; background: linear-gradient(90deg,#009c3b 33%,#ffdf00 33% 66%,#002776 66%); border-radius: var(--ds-r-pill); margin-bottom: var(--ds-space-2) }
.state-grid { display: grid; grid-template-columns: repeat(auto-fill,minmax(48px,1fr)); gap: 4px; margin: var(--ds-space-2) 0 }
.sc { background: var(--ds-surface); border: var(--ds-border-w) solid var(--ds-border); border-radius: var(--ds-r-md); padding: 6px 2px; text-align: center; font-size: var(--ds-size-xs); font-weight: 500; cursor: pointer; transition: background-color var(--ds-duration) var(--ds-ease), border-color var(--ds-duration) var(--ds-ease); color: var(--ds-text) }
.sc:hover { border-color: var(--ds-border-2); background: var(--ds-surface-2) }
/* Amarelo idêntico nos dois temas (ver --ds-counting nos tokens): o pulso indica
   "apurando", e trocar de matiz por tema faria o estado se confundir com a cor
   de um candidato. Texto escuro fixo, legível nos dois extremos do pulso. */
.sc.counting { background: var(--ds-counting); border-color: var(--ds-counting-2); color: var(--ds-counting-fg); font-weight: 700; animation: pulse-counting .8s ease-in-out infinite }
@keyframes pulse-counting { 0%,100%{background:var(--ds-counting)} 50%{background:var(--ds-counting-2)} }
.map-img-wrap { position: relative; width: 100%; margin: 0 auto }

/* ── Candidate color buttons ── */
.btn-spec-n2 { background: #b80000; color: #fff; border-color: #b80000 }
.btn-spec-n1 { background: #cc2222; color: #fff; border-color: #cc2222 }
.btn-spec-0  { background: #16a34a; color: #fff; border-color: #16a34a }
.btn-spec-p1 { background: #2563a8; color: #fff; border-color: #2563a8 }
.btn-spec-p2 { background: #1e3a8a; color: #fff; border-color: #1e3a8a }

/* ── Dark mode — escala zinc escura do shadcn ── */
[data-theme="dark"] {
  --ds-bg:          #14101a;
  --ds-surface:     #1f1926;
  --ds-surface-2:   #2b2334;
  --ds-surface-3:   #3a3045;
  --ds-border:      #352c40;
  --ds-border-2:    #4d4159;
  --ds-text:        #f3eef7;
  --ds-text-2:      #bdb1c9;
  --ds-text-3:      #948aa1;
  --ds-accent:      #22c55e;
  --ds-accent-hov:  #16a34a;
  --ds-accent-fg:   #052e16;
  --ds-accent-bg:   #052e16;
  --ds-accent-mid:  #166534;
  --ds-ring:        #22c55e;
  --ds-brand-y:     #facc15;
  --ds-beige:       #c9a876;
  --ds-beige-bg:    #2a2318;
  --ds-beige-mid:   #4a3d26;
  --ds-green:       #22c55e;
  --ds-green-bg:    #052e16;
  --ds-green-mid:   #166534;
  --ds-red:         #f87171;
  --ds-red-bg:      #450a0a;
  --ds-red-mid:     #7f1d1d;
  --ds-amber:       #f59e0b;
  --ds-amber-bg:    #451a03;
  --ds-amber-mid:   #78350f;
  --ds-map-idle:    #3a3045;
  --ds-shadow-sm:   2px 2px 0 rgba(0,0,0,.45);
  --ds-shadow:      3px 3px 0 rgba(0,0,0,.55);
  --ds-shadow-md:   4px 4px 0 rgba(0,0,0,.6);
  --ds-shadow-lg:   6px 6px 0 rgba(0,0,0,.65);
}
[data-theme="dark"] #load-overlay { background: rgba(9,9,11,.93) }
[data-theme="dark"] canvas { filter: brightness(.9) }
/* O verde claro do dark mode pede texto escuro no estado selecionado */
[data-theme="dark"] .selected { color: var(--ds-text) }

/* Badges de espectro no dark mode — as cores dos candidatos foram escolhidas
   para fundo claro; sobre o zinc escuro elas ficam ilegíveis (2,2:1 a 3,8:1).
   Aqui só o TEXTO sobe de luminosidade: matiz e identidade de cada espectro
   continuam as mesmas, e o fundo/borda em alfa seguem intactos. */
[data-theme="dark"] .b-green { color: #4ade80 }

/* ── Scrollbar ── */
::-webkit-scrollbar { width: 6px; height: 6px }
::-webkit-scrollbar-track { background: transparent }
::-webkit-scrollbar-thumb { background: var(--ds-border-2); border-radius: var(--ds-r-pill) }

/* ── Tables ──
   shadcn Table: cabeçalho em caixa normal, peso medium, cor muted. */
table { border-collapse: collapse; width: 100%; font-size: var(--ds-size-base) }
th { padding: 8px; text-align: left; color: var(--ds-text-2); font-weight: 500; border-bottom: 1px solid var(--ds-border); font-size: var(--ds-size-base) }
td { padding: 8px; border-bottom: 1px solid var(--ds-border) }
tr:hover td { background: var(--ds-surface-2) }
details summary { cursor: pointer; font-size: var(--ds-size-base); color: var(--ds-text-2); user-select: none }
details[open] summary { color: var(--ds-text) }
canvas { background: transparent !important }
#br-map-wrap polygon, #br-map-wrap path, #br-map-wrap g { transition: fill .4s }

/* ── Cenário da semana com arte de tema ─────────────────────────────────────
   Faixa no topo do card, uma por TEMA (7 no banco), não por cenário. O card
   perde o padding próprio e quem espaça é .cena-texto, para a arte sangrar até
   a borda. Sem o arquivo publicado o <img> se remove e o card volta ao que era. */
.cena { padding: 0; overflow: hidden }
.cena-texto { padding: var(--ds-space-4) }
/* O rótulo sai de dentro do texto e sobe para cima da imagem, numa tarja de
   contraste. Assim a arte ganha altura sem empurrar a prosa para baixo. */
.cena-cap { position: relative }
.cena-rot {
  position: absolute; left: 0; top: 0;
  display: flex; align-items: center; gap: 6px;
  padding: 5px var(--ds-space-3);
  background: rgba(31,25,38,.86);
  color: #fff;
  font-family: var(--ds-font-label);
  font-size: var(--ds-size-2xs);
  text-transform: uppercase;
  letter-spacing: .02em;
}
.cena-arte {
  display: block; width: 100%; height: 130px;
  /* Ancorado embaixo: as artes são 800x235 (3,4:1) e a moldura chega a 4,6:1 no
     desktop (603x130), então sobra altura e o corte é vertical — some ~27% da
     imagem. O que interessa nessas cenas (a multidão, a rua, o palanque) está
     na parte de baixo; o céu é o que pode sair. Alinhamento único em vez de um
     mapa arquivo->posição, que envelheceria a cada arte nova.
     Abaixo de ~442px de tela a moldura fica mais estreita que a arte: aí o
     corte passa a ser lateral, a altura aparece inteira e isto não vale mais.
     (Altura 130px e não 120: mais 10px pedidos pelo autor. Cada pixel a mais
     aqui devolve ~2,3% da arte no desktop e sobe a virada acima em ~3,4px.)
     Sem image-rendering: pixelated, pelo mesmo motivo do .retrato — a faixa é
     REDUZIDA, e aí o vizinho-mais-próximo só serrilha. */
  object-fit: cover; object-position: center bottom;
  border-bottom: 2px solid var(--ds-beige-mid);
}

/* Faixa do relatório — mais baixa que a do cenário de propósito: aqui o assunto
   são os números da semana, e uma faixa da mesma altura competiria com eles.
   Fica rente ao topo da tela, com a mesma tarja de rótulo. */
.rel-cap { margin: 0 0 var(--ds-space-4); border: var(--ds-border-w) solid var(--ds-border); overflow: hidden }
.rel-arte {
  display: block; width: 100%; height: 74px;
  object-fit: cover; object-position: center 45%;
}

/* ── A interface veste a campanha ───────────────────────────────────────────
   --pc / --pc-dark são a cor do candidato do jogador, escritas em <html> pelo
   ui.js quando a partida começa (DS.setPlayerColor). --pc-now resolve o par
   conforme o tema, do mesmo jeito que --cc faz nos textos.
   Sem partida em andamento cai no verde da marca, então as telas de abertura e
   o ranking seguem iguais. */
:root               { --pc-now: var(--pc, var(--ds-accent)) }
[data-theme="dark"] { --pc-now: var(--pc-dark, var(--pc, var(--ds-accent))) }

/* Lavagem de 6% no fundo da PÁGINA — as superfícies (cards) ficam limpas, então
   o contraste do texto sobre elas não muda. Jogar de esquerda socialista e de
   extrema-direita passa a ter temperatura diferente. */
body, .content {
  background: var(--ds-bg);
  background: color-mix(in srgb, var(--pc-now) 6%, var(--ds-bg));
}


/* Retrato recortado da arte de vitória.
   SEM image-rendering: pixelated — comparado lado a lado, fica pior. 'pixelated'
   é vizinho-mais-próximo, feito para AMPLIAR pixel art; aqui a imagem é
   REDUZIDA (250px de origem para 44-64px), e o vizinho-mais-próximo descarta
   pixels e serrilha o rosto. A filtragem suave do padrão preserva melhor a
   leitura da arte. */
.retrato {
  object-fit: cover;
  border: 2px solid var(--cc, var(--ds-border-2));
  flex-shrink: 0;
  background: var(--ds-surface-2);
}
.retrato-lg { width: 64px; height: 64px }
.retrato-sm { width: 64px; height: 64px }

/* ── Cor de candidato/partido ──
   As cores vêm do banco (coluna `col`), escolhidas para fundo claro; sobre o
   tema escuro caem para 2,5:1–3,1:1. Todo elemento pintado com uma delas escreve
   duas custom properties em vez de um `color:` fixo — --cc (a cor do banco) e
   --cc-dark (a variante legível, calculada no PHP por cb_colorDark) — e o tema
   escolhe qual vale. Como a escolha é do CSS e não do JS, trocar de tema no meio
   da partida atualiza na hora, sem precisar re-renderizar a tela.
   O seletor por atributo casa só onde --cc foi escrito de propósito. */
[style*="--cc:"] { color: var(--cc) }
[data-theme="dark"] [style*="--cc:"] { color: var(--cc-dark, var(--cc)) }
/* Exceções: dois elementos mantêm fundo CLARO mesmo no tema escuro — o painel
   de pesquisa (.poll-grid-wrap) e o chip da sigla do partido (.pcard-sigla).
   Neles vale --cc, a variante para fundo claro: a clareada, feita para fundo
   escuro, sumiria por cima. Precisam ficar AQUI, depois da regra genérica —
   têm a mesma especificidade que ela, então quem vem por último vence. */
[data-theme="dark"] .poll-grid-wrap [style*="--cc:"],
[data-theme="dark"] .pcard-sigla[style*="--cc:"] { color: var(--cc) }

/* ── Party sigla dark mode ── */
/* (removida a regra que forçava background branco no chip da sigla no tema
   escuro — era um contorno para a cor do partido ficar legível, e deixava de
   pé um retângulo branco no meio do card. Agora o chip mantém nos dois temas a
   tinta da própria cor do partido que já vem inline, e o texto usa a variante
   por tema de --cc, que é o que resolve a legibilidade de verdade.) */

/* ── Poll grid ──
   Em dark mode o painel continua CLARO de propósito (comportamento que já
   existia antes): as cores dos candidatos vêm do banco escolhidas para fundo
   claro e são aplicadas inline em cada barra, então sobre fundo escuro elas
   caem para 2,9:1–3,1:1. Manter o painel claro é o que preserva a leitura
   enquanto essas cores não tiverem variante para tema escuro. */
.poll-grid-wrap {
  background: var(--ds-surface);
  border: 1px solid var(--ds-border);
  border-radius: var(--ds-r-lg);
  padding: 8px;
  margin: 4px 0;
}
/* Tinta do chip do candidato. Saiu do style inline (onde era `${col}14`) para
   cá: inline vence qualquer regra normal, então enquanto estivesse lá o tema
   escuro não teria como desligá-la sem !important. A cor em si continua vindo
   do banco, agora pela variável --chip. */
.chip-tema { background: color-mix(in srgb, var(--chip) 8%, transparent) }

[data-theme="dark"] .poll-grid-wrap {
  /* O painel é CLARO nos dois temas. Em vez de corrigir cor elemento por
     elemento, os tokens são redeclarados aqui: todo descendente passa a
     resolver contra fundo claro, inclusive o que for acrescentado depois. */
  --ds-text:      #2f2836;
  --ds-text-2:    #574d61;
  --ds-text-3:    #70667a;
  --ds-border:    #e3dee9;
  --ds-border-2:  #cdc5d6;
  --ds-surface:   #ffffff;
  --ds-surface-2: #f0edf3;
  --ds-surface-3: #e3dee9;
  /* Cinza de verdade, não um branco disfarçado — um bloco quase branco desse
     tamanho ofusca no tema escuro. Quanto dá para escurecer é limitado pelo
     texto do chip: a variante clara da cor é calculada para 5,5:1 contra BRANCO,
     e cada passo de cinza come essa folga. Medido no navegador, com os cinco
     candidatos, pior caso (Guga, #ca0000): 4,74 em #f4f4f5 e 4,24 em #e9e6ee —
     já abaixo de AA. O que paga o cinza é a linha abaixo, que desliga a tinta de
     8% do chip: sem ela o pior caso sobe para 4,70 neste mesmo fundo. */
  background: #e9e6ee;
  color: var(--ds-text);
  border-color: var(--ds-border);
}
/* Aqui o chip fica sobre cinza, e a tinta era justamente o que derrubava o
   contraste. A identidade da cor não se perde: continuam a borda e o texto na
   cor do candidato, além da barra inteira. */
[data-theme="dark"] .poll-grid-wrap .chip-tema { background: transparent }

/* Tela estreita: só o ícone do logo.
   A barra precisa de logo (190px) + controles (145px) + respiro (32px) = 367px.
   Abaixo disso transbordava — a 320px, em 33px. Some o texto, fica o ícone, que
   continua sendo o link para o início. Consolidar A−/A+ num botão só já tinha
   devolvido o espaço de um controle; isto cobre o resto. */
@media (max-width: 380px) {
  .logo-txt { display: none }
}

/* ── Aviso legal do rodapé ──
   Discreto mas legível: texto pequeno resolvido com --ds-text-2 (não -3), que é
   o que mantém o contraste acima de AA sobre o fundo lavado pela cor da
   campanha. Aviso ilegível não cumpre a função de aviso. */
/* Abas do painel admin. O ranking é uma delas, não um fundo sobre o qual as
   outras aparecem — por isso a aba ativa é a que "encosta" no conteúdo. */
.rk-abas {
  display: flex; gap: 2px; flex-wrap: wrap;
  border-bottom: var(--ds-border-w) solid var(--ds-border);
  margin: .9rem 0 1rem;
}
.rk-aba {
  padding: .5rem 1.1rem; text-decoration: none;
  color: var(--ds-text-2); font-size: var(--ds-size-sm); font-weight: 600;
  border: var(--ds-border-w) solid transparent; border-bottom: none;
  border-radius: 8px 8px 0 0; margin-bottom: calc(var(--ds-border-w) * -1);
}
.rk-aba:hover { color: var(--ds-text); background: var(--ds-surface-2) }
.rk-aba-on {
  color: var(--ds-text); background: var(--ds-surface);
  border-color: var(--ds-border);
  border-bottom: var(--ds-border-w) solid var(--ds-surface);
}

.rodape-legal {
  max-width: 640px;
  margin: var(--ds-space-3) auto 0;
  padding: var(--ds-space-3) var(--ds-space-4) var(--ds-space-4);
  border-top: var(--ds-border-w) solid var(--ds-border);
  color: var(--ds-text-2);
  font-size: var(--ds-size-2xs);
  line-height: 1.55;
}
.rodape-legal p { margin: 0 0 var(--ds-space-2) }
.rodape-legal p:last-child { margin-bottom: 0 }
.rodape-legal b { color: var(--ds-text); font-weight: 700 }
.rodape-tit {
  font-family: var(--ds-font-label);
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--ds-text); font-weight: 700;
}
.rodape-legal a { color: var(--pc-now); text-underline-offset: 2px }

/* Aviso recolhido: só o primeiro parágrafo fica à vista, o resto abre no
   <details>. Elemento nativo de propósito — abre sem JavaScript, o teclado já
   navega nele e o leitor de tela anuncia o estado sozinho. Aviso legal não
   pode depender de script para ser lido. */
.rodape-mais { margin-top: var(--ds-space-3) }
.rodape-mais > summary {
  cursor: pointer; display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--ds-font-label);
  font-size: var(--ds-size-2xs);
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--pc-now);
  padding: 4px 0;
}
.rodape-mais > summary::marker { content: '' }        /* seta padrão fora */
.rodape-mais > summary::-webkit-details-marker { display: none }
.rodape-mais > summary::before { content: '▸'; font-size: 1.1em; line-height: 1 }
.rodape-mais[open] > summary::before { content: '▾' }
.rodape-mais[open] > summary { margin-bottom: var(--ds-space-2) }
.rodape-mais > div > p { margin: 0 0 var(--ds-space-2) }

/* ── Candidate selection screen ── */
.cand-btn {
  display: block; width: 100%; text-align: left;
  border: var(--ds-border-w) solid var(--ds-border);
  border-radius: var(--ds-r-lg);
  background: var(--ds-surface);
  cursor: pointer; font-family: var(--ds-font);
  transition: background-color var(--ds-duration) var(--ds-ease), border-color var(--ds-duration) var(--ds-ease);
  box-shadow: var(--ds-shadow-sm);
  overflow: hidden; margin-bottom: var(--ds-space-3);
  padding: 0;
}
.cand-btn:hover { background: var(--ds-surface-2) }
.cand-btn-stripe { height: 4px; width: 100%; display: block }
.cand-btn-body { padding: 12px 14px 14px }
/* flex-wrap: em tela estreita com o A+ ligado, o nome (pixel, largo) e o rótulo
   de espectro não cabem juntos. Com wrap o rótulo desce para a linha de baixo,
   em vez de partir o nome do candidato ao meio. */
.cand-btn-top { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; flex-wrap: wrap }
.cand-btn-name { font-family: var(--ds-font-label); font-size: var(--ds-size-base); font-weight: 700; letter-spacing: .03em; line-height: 1.4 }
.cand-btn-spec {
  font-size: var(--ds-size-sm); font-weight: 500; color: var(--ds-text-2);
  text-transform: uppercase; letter-spacing: .04em;
}
.cand-btn-desc { font-size: var(--ds-size-base); color: var(--ds-text-2); line-height: 1.5 }

/* ── hdr-logo dark mode ── */
[data-theme="dark"] .hdr-logo { color: var(--ds-text) }
[data-theme="dark"] .logo-br { color: #4ade80 }
[data-theme="dark"] #br-map-wrap { background: var(--ds-bg) }
/* Siglas dos estados no mapa da apuração — o SVG (real ou fallback) grava a cor de
   preenchimento direto no elemento <text>; em dark mode isso vira ilegível sobre o
   mapa escuro, então sobrescrevemos aqui em vez de duplicar lógica no JS. */
[data-theme="dark"] #br-map-svg text { fill: #fff !important }

/* Chart legend */
#chart-legend span {
  font-size: var(--ds-size-base) !important;
  font-weight: 500 !important;
  padding: 5px 14px !important;
  min-width: 90px !important;
  letter-spacing: -.01em;
}

#wconf { text-align: center }

/* Confetti de celebração */
@keyframes confettiDrop{
  0%{transform:translateY(-30px) rotate(0deg);opacity:1}
  85%{opacity:1}
  100%{transform:translateY(105vh) rotate(900deg);opacity:0}
}
@keyframes confettiSway{
  0%,100%{margin-left:0}
  50%{margin-left:20px}
}

/* ── Comentários ao vivo ── */
.live-now{background:var(--ds-surface);border:1px solid var(--ds-amber-mid);border-radius:var(--ds-r-lg);padding:.6rem .75rem;margin-bottom:.5rem;min-height:46px;font-size:var(--ds-size-base);line-height:1.5;transition:border-color .3s;box-shadow:var(--ds-shadow-sm)}
.live-now.done{border-color:var(--ds-border)}
.live-now .ln-sub{font-size:var(--ds-size-sm);color:var(--ds-text-2);margin-top:2px}
.alog-item{background:var(--ds-surface);border:1px solid var(--ds-border);border-radius:var(--ds-r-md);padding:.4rem .6rem;margin-bottom:.3rem;cursor:pointer;font-size:var(--ds-size-base);transition:background-color var(--ds-duration) var(--ds-ease)}
.alog-item:hover{background:var(--ds-surface-2)}
.alog-line{display:flex;align-items:center;gap:.45rem}
.alog-uf{font-size:var(--ds-size-xs);font-weight:600;border-radius:var(--ds-r-sm);padding:1px 6px}
.alog-sub{font-size:var(--ds-size-xs);color:var(--ds-text-3);margin-left:auto}
.alog-caret{font-size:var(--ds-size-xs);color:var(--ds-text-3);transition:transform .2s}
.alog-item.open .alog-caret{transform:rotate(90deg)}
.alog-det{margin-top:.4rem;padding-top:.4rem;border-top:1px solid var(--ds-border);font-size:var(--ds-size-sm);color:var(--ds-text-2);line-height:1.55}
@keyframes alogFlash{0%,100%{box-shadow:var(--ds-shadow-sm)}25%,75%{box-shadow:0 0 0 3px var(--ds-amber-mid)}}
.alog-item.highlight{animation:alogFlash 1.5s ease}
[data-theme="dark"] .live-now{background:var(--ds-surface-2)}

/* ── Páginas de ranking ──────────────────────────────────────────────────────
   Antes estas regras viviam em <style> dentro de ranking.php E de
   ranking_admin.php, duplicadas byte a byte em 11 delas — mudar o visual do
   ranking exigia editar dois arquivos e lembrar de manter os dois iguais.
   Agora moram aqui, com o resto do design system. A única diferença real entre
   as duas páginas era a largura, que virou o modificador .rk-wide. */
.rk-wrap{max-width:720px;margin:0 auto;padding:1rem 1rem 2.5rem}
.rk-wrap.rk-wide{max-width:960px}
.rk-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(128px,1fr));gap:.55rem;margin:.9rem 0}
.rk-card{background:var(--ds-surface);border:1px solid var(--ds-border);border-radius:var(--ds-r-lg);padding:var(--ds-space-3) var(--ds-space-2);text-align:center;box-shadow:var(--ds-shadow-sm)}
.rk-card b{font-family:var(--ds-font-display);font-size:var(--ds-size-2xl);font-weight:700;letter-spacing:0;display:block;line-height:1.2;color:var(--ds-text);font-variant-numeric:tabular-nums}
.rk-card span{font-size:var(--ds-size-sm);color:var(--ds-text-2);font-weight:500}
table.rk{width:100%;border-collapse:collapse;font-size:var(--ds-size-base)}
table.rk th{font-size:var(--ds-size-base);font-weight:500;color:var(--ds-text-2);text-align:left;padding:var(--ds-space-2);border-bottom:1px solid var(--ds-border);white-space:nowrap}
table.rk td{padding:var(--ds-space-2);border-bottom:1px solid var(--ds-border);vertical-align:top}
table.rk tr:hover td{background:var(--ds-surface-2)}
.rk-esp{display:inline-block;font-size:var(--ds-size-xs);border-radius:var(--ds-r-md);padding:2px 8px;font-weight:600;margin-top:2px}
/* só no ranking público */
.rk-geo{display:flex;gap:.4rem;flex-wrap:wrap;margin:.4rem 0 .9rem}
.rk-geo span{font-size:var(--ds-size-xs);background:var(--ds-surface);border:1px solid var(--ds-border);border-radius:var(--ds-r-md);padding:2px 10px;color:var(--ds-text-2)}
.rk-bar-bg{background:var(--ds-surface-2);border-radius:var(--ds-r-pill);height:8px;overflow:hidden;margin-top:4px}
.rk-bar-fill{height:100%;border-radius:var(--ds-r-pill)}
/* só no ranking admin — select e input seguem o Input do shadcn (altura 36, raio md) */
.rk-filtros{display:flex;gap:.45rem;flex-wrap:wrap;margin:.7rem 0}
.rk-filtros select,
.rk-login input{background:var(--ds-surface);color:var(--ds-text);border:1px solid var(--ds-border-2);border-radius:var(--ds-r-md);min-height:36px;padding:0 var(--ds-space-3);font-size:var(--ds-size-base);font-family:var(--ds-font);box-shadow:var(--ds-shadow-sm)}
.rk-filtros select{cursor:pointer}
.rk-res-win{color:var(--ds-green);font-weight:600}
.rk-res-cass{color:var(--ds-red);font-weight:600}
.rk-login{max-width:320px;margin:3rem auto;text-align:center}
.rk-login input{width:100%;margin:.7rem 0;font-size:var(--ds-size-md)}
