/* ============================================================================
   Real Campeonato — BASE
   ----------------------------------------------------------------------------
   Reset, tipografia e os componentes compartilhados entre painel e site:
   botões, campos, cartões, tabelas, etiquetas, menus, modais, toasts, tooltip,
   esqueletos e as animações de entrada.

   Depende de tokens.css. Nenhuma cor literal aqui — só var(--*).
   ============================================================================ */

/* ------------------------------------------------------------------- RESET */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* `hidden` tem de esconder SEMPRE.
   O atributo vale `display: none` pela folha do navegador — a de menor
   prioridade que existe. Qualquer regra nossa que declare `display` vence:
   `.btn { display: inline-flex }` fazia `<button hidden>` aparecer do mesmo
   jeito, e era por isso que o botão "Remover" surgia em campo de imagem
   vazio. Vale para todo o sistema, não só ali. */
[hidden] { display: none !important; }

/* Durante a troca de tema, tudo é instantâneo. Ver a explicação longa em
   assets/js/tema.js — em resumo, transição sobre valor vindo de custom
   property herdada trava no tema anterior, e o resultado é uma tela meio
   clara e meio escura sem nenhum erro no console. */
.trocando-tema, .trocando-tema *, .trocando-tema *::before, .trocando-tema *::after {
    transition: none !important;
}

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
    background: var(--fundo);
    color: var(--texto);
    font-family: var(--fonte-base);
    font-size: var(--texto-base);
    line-height: 1.55;
    min-height: 100dvh;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* SEM transição de cor aqui, de propósito.
       Trocar o tema muda `--fundo` no <html>; o navegador não reinicia de forma
       confiável uma transição cujo valor vem de custom property herdada, e o
       resultado é o body FICAR PRESO na cor do tema anterior enquanto os
       cartões já viraram — tela metade clara, metade escura, sem erro nenhum.
       A troca instantânea é o comportamento certo e é o que todo o resto faz. */
}

img, svg { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; }
code, kbd { font-family: var(--fonte-mono); font-size: .9em; }
kbd {
    padding: 2px 6px;
    border: 1px solid var(--borda-forte);
    border-bottom-width: 2px;
    border-radius: var(--raio-sm);
    background: var(--superficie-2);
    font-size: var(--texto-xs);
    color: var(--texto-suave);
}

::selection { background: color-mix(in srgb, var(--acento) 25%, transparent); }
:focus-visible { outline: 2px solid var(--acento); outline-offset: 2px; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
    background: var(--borda-forte);
    border-radius: var(--raio-full);
    border: 3px solid var(--fundo);
}
::-webkit-scrollbar-thumb:hover { background: var(--texto-fraco); }

/* -------------------------------------------------------------- TIPOGRAFIA */
h1, h2, h3, h4 {
    font-family: var(--fonte-titulo);
    font-weight: 620;
    letter-spacing: -.022em;
    line-height: 1.22;
    color: var(--texto);
    text-wrap: balance;
}
h1 { font-size: var(--texto-2xl); }
h2 { font-size: var(--texto-xl); }
h3 { font-size: var(--texto-lg); }
h4 { font-size: var(--texto-md); }

.titulo-secao {
    display: flex; align-items: center; gap: var(--esp-2);
    font-size: var(--texto-sm);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--texto-suave);
    margin-bottom: var(--esp-3);
}
.titulo-secao i { color: var(--texto-fraco); }

.texto-suave  { color: var(--texto-suave); }
.texto-fraco  { color: var(--texto-fraco); }
.texto-pequeno { font-size: var(--texto-sm); }
.numero  { font-family: var(--fonte-mono); font-variant-numeric: tabular-nums; }
.tabular { font-variant-numeric: tabular-nums; }
.destaque { font-weight: 650; }
.truncar { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.vazio {
    color: var(--texto-suave);
    padding: var(--esp-6) var(--esp-2);
    text-align: center;
}

/* Texto com o gradiente do acento. Um recurso só, em títulos de destaque. */

/* ------------------------------------------------------------------ GRADES */
.grade { display: grid; gap: var(--esp-4); }
.grade-2 { grid-template-columns: 1fr; }
.grade-3 { grid-template-columns: 1fr; }
.grade-4 { grid-template-columns: repeat(2, 1fr); }
.grade-auto { grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); }
/* Grade de CARTÕES DE JOGO. Existe separada de `.grade-2` porque aquela vira
   duas colunas fixas a partir de 640px, e o cartão de jogo não cabe em 300px:
   ele carrega data, dois escudos, dois nomes, placar e estado. Espremido, os
   nomes viravam "Invenc…" e a linha estourava a borda.

   Aqui a segunda coluna só aparece quando há 340px REAIS para ela — abaixo
   disso os jogos ficam um sob o outro, que é como se lê uma lista de
   resultados no celular. */
/* `min(340px, 100%)` e não `340px` seco: com `auto-fill`, uma faixa de mínimo
   fixo continua valendo 340px mesmo quando o container tem 328 — a coluna
   passa a ser mais larga que o pai e o cartão vaza pela direita. Foi
   exatamente esse o estouro relatado no celular. */
.grade-jogos { grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr)); }
/* Duas colunas e ponto final, para listas com muito confronto por definir.
   `auto-fill` cabe três num monitor largo, e o cartão de 340px é justamente o
   que não sobra para o NOME: "A definir" vira "A …" nos dois lados, e a
   fileira inteira fica com seis reticências e nenhuma informação. Onde os
   confrontos ainda não têm dono, a largura é o que faz a lista ser legível. */
@media (min-width: 780px) {
    /* `minmax(0, 1fr)` e não `1fr` seco: `1fr` é atalho de `minmax(auto, 1fr)`,
       e o mínimo `auto` vale o MIN-CONTENT da coluna. Basta um nome de clube
       que não quebra — os do cartão de partida têm `nowrap` — para a coluna
       exigir mais largura que a metade disponível, e a grade inteira estourar
       para fora do container. Com o mínimo em zero, a coluna aceita encolher e
       quem trunca é o cartão, que já sabe fazer isso. */
    .grade-jogos.grade-jogos-larga { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* Grade de CLUBES: cartão estreito, quatro por fileira no desktop comum.
   Existe separada de `.grade-auto` (350px) porque aquela serve telas de
   conteúdo largo — galerias, contas, elenco —, onde 260px espremeria o texto.
   Aqui o cartão é uma coluna centrada: escudo de 128px, nome e dois selos.
   260 é o mínimo que acomoda isso com folga; abaixo disso o nome de duas
   palavras quebra em três linhas.

   Continua `auto-fill`, e não `repeat(4, …)`: a degradação sai de graça —
   3 colunas por volta de 900px, 2 em 800, 1 no celular — sem nenhum
   breakpoint escrito à mão. Num monitor bem largo pode chegar a 5, que é o
   comportamento certo para uma grade que se ajusta ao espaço. */
.grade-times { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.grade-lateral { grid-template-columns: 1fr; align-items: start; }

.pilha { display: flex; flex-direction: column; gap: var(--esp-4); }
.pilha-2 { display: flex; flex-direction: column; gap: var(--esp-2); }
.linha { display: flex; align-items: center; gap: var(--esp-3); flex-wrap: wrap; }
.linha-fim { margin-left: auto; }

/* ----------------------------------------------------------------- CARTÕES */
.cartao {
    position: relative;
    background: var(--superficie);
    border: 1px solid var(--borda);
    border-radius: var(--raio-lg);
    box-shadow: var(--sombra-sm);
    transition: border-color var(--transicao), box-shadow var(--transicao),
                transform var(--vel) var(--curva-saida);
}
.cartao-corpo { padding: var(--esp-5); }
.cartao-cabeca {
    display: flex; align-items: center; gap: var(--esp-3); flex-wrap: wrap;
    padding: var(--esp-4) var(--esp-5);
    border-bottom: 1px solid var(--borda);
}
.cartao-cabeca h2, .cartao-cabeca h3 { font-size: var(--texto-md); font-weight: 600; }
.cartao-cabeca i { color: var(--texto-fraco); }
.cartao-rodape {
    padding: var(--esp-3) var(--esp-5);
    border-top: 1px solid var(--borda);
    background: var(--superficie-2);
    border-radius: 0 0 var(--raio-lg) var(--raio-lg);
}
/* Cartão que responde ao mouse: só onde há navegação atrás dele. */
/* Fio de acento no topo, para o cartão-herói de cada tela. */
.cartao-realce { overflow: hidden; }
.cartao-realce::before {
    content: ''; position: absolute; inset: 0 0 auto 0; height: 3px;
    background: var(--grad-acento);
}

/* Indicador numérico do dashboard */
.indicador { padding: var(--esp-5); }
.indicador-rotulo {
    display: flex; align-items: center; gap: var(--esp-2);
    font-size: var(--texto-sm);
    color: var(--texto-suave);
    margin-bottom: var(--esp-2);
}
.indicador-valor {
    font-size: var(--texto-3xl);
    font-weight: 650;
    letter-spacing: -.03em;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ BOTÕES */
.btn {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center; gap: var(--esp-2);
    padding: 9px var(--esp-4);
    min-height: 40px;
    border: 1px solid transparent;
    border-radius: var(--raio-sm);
    font-size: var(--texto-base);
    font-weight: 550;
    white-space: nowrap;
    transition: background-color var(--vel-rapida) var(--curva), border-color var(--vel-rapida) var(--curva),
                color var(--vel-rapida) var(--curva), box-shadow var(--vel-rapida) var(--curva),
                transform var(--vel-rapida) var(--curva);
}
.btn:focus-visible { box-shadow: var(--foco); outline: none; }
.btn:active { transform: translateY(1px); }
.btn i { font-size: .95em; }

.btn-primario {
    background: var(--acento);
    color: var(--acento-contraste);
    border-color: var(--acento);
    box-shadow: var(--sombra-sm);
}
.btn-primario:hover { background: var(--acento-forte); border-color: var(--acento-forte); box-shadow: var(--sombra-acento); }

.btn-secundario {
    background: var(--superficie);
    color: var(--texto);
    border-color: var(--borda-forte);
    box-shadow: var(--sombra-sm);
}
.btn-secundario:hover { background: var(--superficie-alt); }

.btn-fantasma { background: transparent; color: var(--texto-suave); }
.btn-fantasma:hover { background: var(--superficie-alt); color: var(--texto); }

.btn-perigo { background: transparent; color: var(--erro); border-color: var(--borda-forte); }
.btn-perigo:hover { background: var(--erro-suave); border-color: var(--erro); }

.btn-alerta { background: transparent; color: var(--alerta); border-color: var(--borda-forte); }
.btn-alerta:hover { background: var(--alerta-suave); border-color: var(--alerta); }

.btn-pequeno { min-height: 32px; padding: 5px var(--esp-3); font-size: var(--texto-sm); }
.btn-grande  { min-height: 48px; padding: 12px var(--esp-6); font-size: var(--texto-md); border-radius: var(--raio); }
.btn-largo { width: 100%; }
.btn[disabled], .btn:disabled { opacity: .5; pointer-events: none; }

.btn-icone {
    display: inline-flex; align-items: center; justify-content: center;
    width: 36px; height: 36px;
    border-radius: var(--raio-sm);
    color: var(--texto-suave);
    transition: background-color var(--vel-rapida) var(--curva), color var(--vel-rapida) var(--curva);
}
.btn-icone:hover { background: var(--superficie-alt); color: var(--texto); }
.btn-icone.perigo:hover { background: var(--erro-suave); color: var(--erro); }
.btn-icone.redondo { border-radius: 50%; }

/* ------------------------------------------------------------------ CAMPOS */
.campo { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--esp-4); }
.campo-rotulo { font-size: var(--texto-sm); font-weight: 550; }
.campo-dica { font-size: var(--texto-sm); color: var(--texto-suave); }

.entrada {
    width: 100%;
    padding: 9px var(--esp-3);
    min-height: 40px;
    background: var(--superficie);
    color: var(--texto);
    border: 1px solid var(--borda-forte);
    border-radius: var(--raio-sm);
    box-shadow: var(--sombra-sm);
    transition: border-color var(--vel-rapida) var(--curva), box-shadow var(--vel-rapida) var(--curva);
}
.entrada::placeholder { color: var(--texto-fraco); }
.entrada:hover { border-color: var(--texto-fraco); }
.entrada:focus { outline: none; border-color: var(--acento); box-shadow: var(--foco); }
.entrada:disabled { background: var(--superficie-alt); color: var(--texto-suave); cursor: not-allowed; }
textarea.entrada { min-height: 88px; resize: vertical; line-height: 1.5; }

select.entrada {
    appearance: none;
    padding-right: var(--esp-8);
    background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                      linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position: calc(100% - 18px) 17px, calc(100% - 13px) 17px;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
}

/* Número da camisa e afins: sem as setinhas do navegador */
.entrada[type="number"] { -moz-appearance: textfield; }
.entrada[type="number"]::-webkit-outer-spin-button,
.entrada[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* Campo com ícone à esquerda (busca) */
.campo-icone { position: relative; }
.campo-icone > i {
    position: absolute; left: var(--esp-3); top: 50%; transform: translateY(-50%);
    color: var(--texto-fraco); pointer-events: none; font-size: var(--texto-base);
}
.campo-icone .entrada { padding-left: var(--esp-8); }

.grupo-campos { display: grid; grid-template-columns: 1fr; gap: 0 var(--esp-4); }

.caixa {
    display: flex; align-items: flex-start; gap: var(--esp-3);
    padding: var(--esp-3);
    border: 1px solid var(--borda);
    border-radius: var(--raio-sm);
    cursor: pointer;
    transition: border-color var(--transicao), background-color var(--transicao);
    margin-bottom: var(--esp-3);
}
.caixa:hover { border-color: var(--borda-forte); background: var(--superficie-2); }
.caixa input { margin-top: 3px; accent-color: var(--acento); width: 16px; height: 16px; }
.caixa-nota { display: block; font-size: var(--texto-sm); color: var(--texto-suave); }

/* Upload com pré-visualização local (sem round-trip ao servidor) */
.upload {
    display: flex; align-items: center; gap: var(--esp-4);
    padding: var(--esp-4);
    border: 1px dashed var(--borda-forte);
    border-radius: var(--raio);
    transition: border-color var(--transicao), background-color var(--transicao);
}
.upload:hover, .upload.arrastando { border-color: var(--acento); background: var(--acento-suave); }
.upload-previa {
    width: 64px; height: 64px; flex-shrink: 0;
    border-radius: var(--raio-sm);
    border: 1px solid var(--borda);
    background: var(--superficie-alt);
    display: grid; place-items: center;
    overflow: hidden;
    color: var(--texto-fraco);
}
/* `contain` + `max-*`, nunca `width/height: 100%` com `cover`.
   Era assim antes, e a prévia mentia duas vezes: esticava um favicon de 32px
   para os 64px da caixa (aparecendo borrado, como se o upload tivesse ampliado
   — e o upload NUNCA amplia) e recortava a logomarca horizontal no quadrado,
   mostrando só o miolo dela. A prévia existe para conferir o que foi gravado;
   ela precisa mostrar a imagem no tamanho que a imagem tem. */
.upload-previa img {
    max-width: 100%; max-height: 100%;
    width: auto; height: auto;
    object-fit: contain;
}
/* Os dois botões na MESMA linha, com a dica embaixo ocupando a largura toda.
   "Remover" numa linha própria gastava uma faixa inteira para uma ação
   secundária — e ficava com o mesmo peso visual de "Escolher imagem". */
.upload-acoes {
    display: flex; flex-wrap: wrap; align-items: center; gap: var(--esp-2);
    min-width: 0; flex: 1;
}
.upload-acoes .campo-dica { flex-basis: 100%; }
/* Ação destrutiva: menor e em vermelho, sem moldura. */
.upload-acoes [data-upload-remover] {
    min-height: 30px;
    padding: 4px var(--esp-3);
    font-size: var(--texto-sm);
    color: var(--erro);
}
.upload-acoes [data-upload-remover]:hover { background: var(--erro-suave); color: var(--erro); }
.upload input[type="file"] { display: none; }

/* --------------------------------------------------------------- SEGMENTOS
   Alternador de opções em linha (período, aba). Substitui <select> quando as
   opções são poucas e a troca precisa ser de um clique só. */
.segmentos {
    display: inline-flex; align-items: center; gap: 2px;
    padding: 3px;
    background: var(--superficie-alt);
    border-radius: var(--raio);
}
.segmentos a, .segmentos button {
    padding: 6px var(--esp-3);
    border-radius: 7px;
    font-size: var(--texto-sm);
    font-weight: 550;
    color: var(--texto-suave);
    white-space: nowrap;
    transition: background-color var(--transicao), color var(--transicao), box-shadow var(--transicao);
}
.segmentos a:hover, .segmentos button:hover { color: var(--texto); }
.segmentos .ativo {
    background: var(--superficie);
    color: var(--texto);
    box-shadow: var(--sombra-sm);
}

/* ----------------------------------------------------------------- TABELAS */
.tabela-envolucro { overflow-x: auto; }

/* CANTO QUADRADO VAZANDO DO CARTÃO ARREDONDADO — o artefato e a cura.
   O `<th>` tem fundo opaco (`--superficie-2`) e a tabela encosta na borda do
   `.cartao`, que é arredondado mas tem `overflow: visible`. Resultado: o
   cabeçalho pinta um retângulo por cima da curva e sobra um biquinho quadrado
   em cada canto. O mesmo vale para a última linha, que tem `:hover` colorido.

   `overflow: hidden` no `.cartao` resolveria e quebraria outra coisa: cartão
   também hospeda menu suspenso e tooltip, que precisam vazar para fora.
   Por isso o recorte fica no ENVÓLUCRO, que já é um contexto de rolagem
   (`overflow-x: auto`) e portanto já recorta o que passa dos seus limites.

   `inherit` em vez de `var(--raio-lg)`: se um dia o raio do cartão mudar, o
   canto acompanha sozinho — duas medidas para a mesma curva é como elas
   divergem. E só os cantos que ENCOSTAM na borda: com `.cartao-cabeca` acima,
   a tabela não é o primeiro filho e o topo não deve arredondar nada. */
.cartao > .tabela-envolucro:first-child {
    border-top-left-radius: inherit;
    border-top-right-radius: inherit;
}
.cartao > .tabela-envolucro:last-child {
    border-bottom-left-radius: inherit;
    border-bottom-right-radius: inherit;
}
.tabela { width: 100%; border-collapse: collapse; }
.tabela th {
    text-align: left;
    padding: var(--esp-3) var(--esp-4);
    font-size: var(--texto-sm);
    font-weight: 600;
    color: var(--texto-suave);
    background: var(--superficie-2);
    border-bottom: 1px solid var(--borda);
    white-space: nowrap;
}
.tabela td {
    padding: var(--esp-3) var(--esp-4);
    border-bottom: 1px solid var(--borda);
    vertical-align: middle;
}
.tabela tbody tr:last-child td { border-bottom: 0; }
.tabela tbody tr { transition: background-color var(--vel-rapida) var(--curva); }
.tabela tbody tr:hover { background: var(--superficie-2); }
.tabela .num { text-align: center; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Geometria FIXA, para tabelas irmãs ficarem coluna sobre coluna.
   `table-layout: fixed` tira a largura do conteúdo e passa para o `colgroup`:
   sem isso, cada tabela de grupo se mede sozinha e as colunas de uma não caem
   sobre as da outra. O nome do time fica com a coluna elástica — é a única que
   varia de tamanho de verdade.

   A largura mínima garante que o `overflow-x` de `.tabela-envolucro` entre em
   ação no celular em vez de espremer dez colunas em 360px. */
/* A largura mínima é a SOMA das colunas, e isso não é detalhe.
   Era 620px com a coluna do clube sem medida: sob `table-layout: fixed` as
   oito colunas numéricas e a forma comem 594px, e sobravam 26px para escudo
   mais nome. No celular a coluna do clube não estava truncada — ela tinha
   colapsado, e a linha aparecia como números sem dono. */
.tabela-tabelada { table-layout: fixed; min-width: 764px; }
.tabela-tabelada .col-pos  { width: 46px; }
.tabela-tabelada .col-time { width: 170px; }
.tabela-tabelada .col-num  { width: 52px; }
/* Cinco selos de resultado lado a lado. */
.tabela-tabelada .col-forma { width: 132px; }

/* --------------------------------------------- CLUBE FIXO, NÚMEROS ROLANDO
   Posição e clube grudam na borda esquerda; as estatísticas passam por baixo.
   É o formato das tabelas de campeonato que todo mundo já conhece, e é o que
   permite ler "quantas vitórias tem o Invencíveis" numa tela de 375px sem
   esconder coluna nenhuma. */
.tabela-tabelada .col-fixa-pos,
.tabela-tabelada .col-fixa-time {
    position: sticky; z-index: 2;
    /* Opaco por obrigação: célula fixa transparente deixa os números
       passarem por baixo do nome enquanto se arrasta. */
    background: var(--superficie);
}
.tabela-tabelada .col-fixa-pos  { left: 0; }
/* Encostada na anterior: 46px é a largura declarada de `.col-pos`, e as duas
   medidas mudam juntas. */
.tabela-tabelada .col-fixa-time { left: 46px; box-shadow: inset -1px 0 0 var(--borda); }
.tabela-tabelada thead .col-fixa-pos,
.tabela-tabelada thead .col-fixa-time {
    /* Acima do corpo: no cruzamento das duas fixações alguém tem de vencer. */
    z-index: 3;
    background: var(--superficie-2);
}
/* O realce da linha precisa alcançar as células fixas, senão elas ficam
   pálidas no meio da linha inteira destacada. */
.tabela-tabelada tbody tr:hover .col-fixa-pos,
.tabela-tabelada tbody tr:hover .col-fixa-time { background: var(--superficie-2); }
/* A faixa da zona de classificação convive com o fio da borda: as duas
   sombras juntas, porque `box-shadow` não se acumula entre regras. */
.tabela-tabelada .col-fixa-pos.pos-classificado { box-shadow: inset 3px 0 0 var(--acento); }
/* O nome do clube sai por inteiro — era o `.truncar` que produzia "Invencí…". */
.tabela-tabelada .time-celula .nome-clube { white-space: nowrap; }

/* No celular as duas colunas fixas encolhem. Não é economia de pixel: elas
   ficam paradas na tela o tempo todo, então cada ponto que ocupam é um ponto
   a menos de estatística visível por vez. 46+170 deixavam 125px de números
   numa tela de 375; 30+158 deixam 157, quase um terço a mais. */
@media (max-width: 639px) {
    .tabela-tabelada { min-width: 736px; }
    .tabela-tabelada .col-pos  { width: 30px; }
    .tabela-tabelada .col-time { width: 158px; }
    .tabela-tabelada .col-fixa-time { left: 30px; }
    /* O respiro lateral padrão das células rouba largura justamente onde ela
       falta; o texto continua legível porque quem separa as colunas aqui é o
       alinhamento à direita dos números. */
    .tabela-tabelada th, .tabela-tabelada td { padding-left: var(--esp-2); padding-right: var(--esp-2); }
}

/* ------------------------------------------------------------ CLASSIFICAÇÃO
   Estas regras VIVIAM em site.css. Mudaram para cá quando o painel passou a
   desenhar a mesma tabela do site (parcial `campeonatos/_classificacao.php`):
   ele não carrega a folha do site, e sem elas a tabela chegava lá crua — sem
   faixa de zona, sem hierarquia entre os números. */

/* Faixa de cor na coluna da posição: quem está na zona de classificação. */
.pos-classificado { box-shadow: inset 3px 0 0 var(--acento); }

.tabela .time-celula { display: flex; align-items: center; gap: var(--esp-3); min-width: 0; }
.tabela-classificacao tbody tr { transition: background-color var(--vel-rapida) var(--curva); }

/* ---------------------------------------------- CLUBE FIXO, NÚMEROS ROLANDO
   A coluna do clube gruda na borda esquerda e as estatísticas rolam por baixo
   dela. É o formato das tabelas de campeonato que todo mundo já conhece, e
   resolve o problema que o recurso anterior só disfarçava.

   Antes, no celular, sete colunas eram ESCONDIDAS e o nome do clube ainda
   saía com reticências. Quem abria a classificação no telefone — que é onde
   ela mais é aberta — via "Invencí…" e não via vitórias, empates, derrotas
   nem gols. A informação não estava comprimida: estava ausente, sem nenhum
   sinal de que existia.

   Agora todas as colunas ficam na tabela e o dedo alcança qualquer uma,
   enquanto escudo e nome nunca sumem — sem eles a linha vira um punhado de
   números sem dono. */
.tabela-classificacao .col-pos {
    position: sticky; left: 0; z-index: 2;
    /* Opaco por obrigação, não por estética: célula fixa transparente deixa
       os números passarem por baixo do nome enquanto se arrasta. */
    background: var(--superficie);
    /* Fio na borda direita: é ele que diz que existe conteúdo rolando ali. */
    box-shadow: inset -1px 0 0 var(--borda);
}
.tabela-classificacao thead .col-pos {
    /* Acima das células do corpo: no cruzamento das duas fixações (topo da
       tabela e coluna da esquerda) alguém tem de vencer. */
    z-index: 3;
    background: var(--superficie-2);
}
/* O realce da linha precisa alcançar a célula fixa, senão ela fica pálida
   no meio da linha inteira destacada. */
.tabela-classificacao tbody tr:hover .col-pos { background: var(--superficie-2); }
/* A faixa da zona de classificação convive com o fio: as duas sombras juntas,
   porque `box-shadow` não se acumula entre regras — a última venceria. */
.tabela-classificacao .col-pos.zona-classificacao,
.tabela-classificacao .col-pos.pos-classificado {
    box-shadow: inset 3px 0 0 var(--acento), inset -1px 0 0 var(--borda);
}
/* O nome do clube sai por inteiro. Era o `.truncar` que produzia "Invencí…". */
.tabela-classificacao .time-celula .nome-clube { white-space: nowrap; }
/* Só os pontos em negrito. O resto da linha fica em `texto-suave`, e é esse
   contraste — não o tamanho da fonte — que faz a coluna P saltar aos olhos. */
.tabela-classificacao .col-destaque { font-weight: 700; }
/* A coluna elástica é a do nome; cortar com reticências evita que um nome
   longo empurre a linha e desalinhe tudo de novo. */
.tabela-tabelada td .identidade-nome {
    display: block;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tabela .acoes { text-align: right; white-space: nowrap; }
.linha-inativa { opacity: .5; }

/* --------------------------------------------------------------- ETIQUETAS */
.etiqueta {
    display: inline-flex; align-items: center; gap: 5px;
    padding: 2px 9px;
    border-radius: var(--raio-full);
    font-size: var(--texto-xs);
    font-weight: 600;
    background: var(--superficie-alt);
    color: var(--texto-suave);
    white-space: nowrap;
}
/* Texto na variante FORTE, não na cor normal. Sobre o fundo suave da mesma
   família, o tom 600 dava ~3.3:1 — abaixo do mínimo de 4.5 para texto pequeno,
   e o selo parecia apagado. O 700 leva a ~5:1 sem mudar a cor que se lê. */
.etiqueta-sucesso { background: var(--sucesso-suave); color: var(--sucesso-forte); }
.etiqueta-erro    { background: var(--erro-suave);    color: var(--erro-forte); }
.etiqueta-alerta  { background: var(--alerta-suave);  color: var(--alerta-forte); }
.etiqueta-info    { background: var(--info-suave);    color: var(--info-forte); }
.etiqueta-acento  { background: var(--acento-suave);  color: var(--acento-forte); }

.pulso {
    width: 7px; height: 7px; border-radius: 50%;
    background: currentColor;
    animation: pulsar 1.6s ease-in-out infinite;
}
@keyframes pulsar { 50% { opacity: .3; } }

/* Selo "AO VIVO": anel que expande, o único elemento que pisca no projeto. */
.selo-vivo {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 3px 10px;
    border-radius: var(--raio-full);
    background: var(--erro-suave);
    color: var(--erro);
    font-size: var(--texto-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
}
.selo-vivo::before {
    content: ''; width: 7px; height: 7px; border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 0 0 currentColor;
    animation: anel-vivo 1.8s var(--curva-saida) infinite;
}
@keyframes anel-vivo {
    0%   { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 60%, transparent); }
    70%  { box-shadow: 0 0 0 7px transparent; }
    100% { box-shadow: 0 0 0 0 transparent; }
}

/* ----------------------------------------------------- AVATAR / IDENTIDADE */
.avatar {
    width: 36px; height: 36px; flex-shrink: 0;
    border-radius: 50%;
    object-fit: cover;
    background: var(--superficie-alt);
    border: 1px solid var(--borda);
}
.avatar-sm { width: 28px; height: 28px; }
.avatar-lg { width: 56px; height: 56px; }
.avatar-xl { width: 96px; height: 96px; }
.avatar-vazio { display: grid; place-items: center; color: var(--texto-fraco); }
.avatar-anel { box-shadow: 0 0 0 3px var(--superficie), 0 0 0 5px var(--acento); }
/* ------------------------------------------------------------------ ESCUDO
   O escudo é a identidade visual do clube e o elemento que mais aparece no
   site — em tabela, agenda, súmula e ficha. Antes era `border-radius: 0`,
   `border: 0`, fundo transparente e 18–26px: um retângulo minúsculo e sem
   acabamento, que fazia toda tela parecer rascunho.

   Agora é uma peça com placa própria: cantos arredondados, fundo e borda que
   dão forma mesmo quando a arte enviada é clara ou recortada torta. */
/* A ARTE MANDA. Nada aqui pode cortar, emoldurar ou colocar fundo atrás dela.
   Era o oposto: `cover` preenchia a caixa cortando o que não coubesse — um
   escudo alto perdia a ponta —, e o fundo com borda desenhava uma placa atrás
   de PNG transparente, que é justamente o que o clube não desenhou.

   `contain` faz a arte caber inteira dentro da caixa que a classe de tamanho
   define. Sobra vira espaço vazio, e vazio é o certo: o escudo é a identidade
   do clube, não um ladrilho do nosso layout. */
.escudo {
    object-fit: contain;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    flex-shrink: 0;
}
/* ESCALA DE TAMANHO — fonte única.
   O tamanho é dito pela CLASSE, no markup, e nunca por `style=""` inline: o
   inline vence qualquer regra de CSS, e ter as duas coisas fazia o escudo
   ignorar em silêncio o tamanho definido no componente. */
.escudo-xs { width: 22px;  height: 22px;  }
.escudo-sm { width: 30px;  height: 30px;  }
.escudo-md { width: 48px;  height: 48px;  }
.escudo-lg { width: 92px;  height: 92px;  }
.escudo-xl { width: 128px; height: 128px; }

/* Espaço reservado quando o clube ainda não tem escudo: mesma caixa, mesmo
   arredondamento — a coluna não dança entre uma linha e outra. */
.escudo-vazio {
    display: inline-grid; place-items: center; flex-shrink: 0;
    background: var(--superficie-alt);
    border: 1px solid var(--borda);
    border-radius: var(--raio-sm);
    color: var(--texto-fraco);
    font-size: 11px;
}
.escudo-vazio.escudo-xs { border-radius: 5px; }
.escudo-vazio.escudo-md { border-radius: var(--raio); font-size: var(--texto-md); }
.escudo-vazio.escudo-lg { border-radius: var(--raio-lg); font-size: var(--texto-xl); box-shadow: var(--sombra-md); }
.escudo-vazio.escudo-xl { border-radius: var(--raio-xl); font-size: var(--texto-xl); box-shadow: var(--sombra-lg); }

.identidade { display: flex; align-items: center; gap: var(--esp-3); min-width: 0; }
/* Nome e clube em LINHAS próprias. Os dois eram `span` puro, sem `display`,
   então quando apareciam um depois do outro dentro do mesmo bloco o HTML os
   emendava numa linha só — "RicardinhoGrêmio Municipal". Dentro de `.identidade`
   (que é flex) o `block` não muda nada: item de flex já se comporta assim. */
.identidade-nome {
    display: block;
    font-weight: 550;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.identidade-sub {
    display: block;
    font-size: var(--texto-sm);
    color: var(--texto-suave);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ------------------------------------------------------------------- MENUS
   Menu suspenso genérico (conta do painel, navegação do site). A abertura é
   por classe, não por :hover: no toque não existe hover, e um menu que só
   abre no mouse é um menu que não existe no celular. */
.menu-raiz { position: relative; }
.menu {
    position: absolute; z-index: var(--z-flutuante);
    top: calc(100% + 8px); right: 0;
    min-width: 210px;
    padding: var(--esp-2);
    background: var(--superficie);
    border: 1px solid var(--borda);
    border-radius: var(--raio);
    box-shadow: var(--sombra-xl);
    opacity: 0; visibility: hidden;
    transform: translateY(-6px) scale(.98);
    transform-origin: top right;
    transition: opacity var(--vel-rapida) var(--curva),
                transform var(--vel-rapida) var(--curva-saida),
                visibility var(--vel-rapida);
}
.menu.aberto { opacity: 1; visibility: visible; transform: none; }
.menu-item {
    display: flex; align-items: center; gap: var(--esp-3);
    width: 100%;
    padding: 8px var(--esp-3);
    border-radius: var(--raio-sm);
    font-size: var(--texto-base);
    color: var(--texto-suave);
    text-align: left;
    transition: background-color var(--vel-rapida) var(--curva), color var(--vel-rapida) var(--curva);
}
.menu-item i { width: 16px; text-align: center; font-size: var(--texto-base); }
.menu-item:hover { background: var(--superficie-alt); color: var(--texto); }
.menu-item.perigo:hover { background: var(--erro-suave); color: var(--erro); }
.menu-titulo {
    padding: var(--esp-2) var(--esp-3) 4px;
    font-size: var(--texto-xs); font-weight: 600;
    text-transform: uppercase; letter-spacing: .07em;
    color: var(--texto-fraco);
}
.menu-separador { height: 1px; background: var(--borda); margin: var(--esp-2) 0; }

/* Véu que escurece o fundo quando uma gaveta abre. Compartilhado: o painel e
   o site têm gavetas diferentes, mas o mesmo pano de fundo. */
.veu-menu {
    position: fixed; inset: 0; z-index: var(--z-veu);
    background: rgb(16 24 40 / .45);
    backdrop-filter: blur(2px);
    opacity: 0; pointer-events: none;
    transition: opacity var(--vel) var(--curva);
}
.veu-menu.visivel { opacity: 1; pointer-events: auto; }

/* ------------------------------------------------------------------ MODAIS */
.sd-modal-veu {
    position: fixed; inset: 0; z-index: var(--z-modal);
    display: grid; place-items: center;
    padding: var(--esp-4);
    background: rgb(16 24 40 / .5);
    backdrop-filter: blur(3px);
    animation: veu-entrar 140ms ease-out;
}
@keyframes veu-entrar { from { opacity: 0; } }
.sd-modal {
    width: min(100%, 460px);
    max-height: 90dvh;
    display: flex; flex-direction: column;
    background: var(--superficie);
    border: 1px solid var(--borda);
    border-radius: var(--raio-lg);
    box-shadow: var(--sombra-xl);
    animation: modal-entrar 220ms var(--curva-saida);
}
@keyframes modal-entrar { from { opacity: 0; transform: translateY(10px) scale(.97); } }
.sd-modal-selecao { width: min(100%, 620px); }
.sd-modal-cabeca {
    display: flex; align-items: center; gap: var(--esp-3);
    padding: var(--esp-5) var(--esp-5) var(--esp-3);
    font-weight: 600;
    font-size: var(--texto-md);
}
.sd-modal-cabeca i { color: var(--texto-suave); }
.sd-modal-corpo {
    padding: 0 var(--esp-5) var(--esp-4);
    overflow-y: auto;
    color: var(--texto-suave);
    line-height: 1.6;
}
.sd-modal-acoes {
    display: flex; justify-content: flex-end; gap: var(--esp-2);
    padding: var(--esp-4) var(--esp-5);
    border-top: 1px solid var(--borda);
}

/* -------------------------------------------------------------- RECORTE 1:1 */
.sd-modal-crop { width: min(100%, 380px); }
.crop-visor {
    position: relative;
    width: 300px; height: 300px;
    margin: 0 auto;
    border-radius: var(--raio);
    overflow: hidden;
    /* Xadrez, e não um cinza chapado: afastando o zoom, o que sobra nos cantos
       é TRANSPARENTE — e transparência sobre fundo escuro é indistinguível de
       um fundo escuro de verdade. Sem o xadrez, quem envia um brasão recortado
       não tem como saber se salvou com fundo ou sem. */
    background:
        conic-gradient(from 90deg at 50% 50%,
            var(--cinza-800) 0 25%, var(--cinza-900) 0 50%,
            var(--cinza-800) 0 75%, var(--cinza-900) 0)
        0 0 / 16px 16px;
    cursor: grab;
    touch-action: none;      /* o arraste é nosso, não do scroll da página */
    user-select: none;
}
.crop-visor:active { cursor: grabbing; }
.crop-visor canvas { display: block; }
/* Mira: reforça que o corte é quadrado e mostra o centro. */
.crop-mira {
    position: absolute; inset: 0;
    pointer-events: none;
    box-shadow: inset 0 0 0 2px rgb(255 255 255 / .85);
    border-radius: var(--raio);
}
.crop-mira::before, .crop-mira::after {
    content: ''; position: absolute; background: rgb(255 255 255 / .25);
}
.crop-mira::before { inset: 33.33% 0; border-block: 1px solid rgb(255 255 255 / .25); background: none; }
.crop-mira::after  { inset: 0 33.33%; border-inline: 1px solid rgb(255 255 255 / .25); background: none; }

.crop-zoom {
    display: flex; align-items: center; gap: var(--esp-3);
    margin-top: var(--esp-4);
    color: var(--texto-fraco);
}
.crop-zoom input { flex: 1; accent-color: var(--acento); }
.crop-dica {
    margin-top: var(--esp-3);
    font-size: var(--texto-sm);
    color: var(--texto-fraco);
    text-align: center;
}

/* ------------------------------------------------------------ FOTO EM 1 CLIQUE */
.foto-botao {
    position: relative;
    display: block; flex-shrink: 0;
    border-radius: 50%;
    cursor: pointer;
    line-height: 0;
}
.foto-botao::after {
    content: '\f030';        /* fa-camera */
    font-family: 'Font Awesome 7 Free'; font-weight: 900;
    position: absolute; inset: 0;
    display: grid; place-items: center;
    border-radius: inherit;
    background: rgb(12 17 29 / .62);
    color: #FFF;
    font-size: var(--texto-sm);
    opacity: 0;
    transition: opacity var(--vel-rapida) var(--curva);
}
.foto-botao:hover::after, .foto-botao:focus-visible::after { opacity: 1; }
/* O keyframe mora aqui, e não em site.css: quem mais usa este botão é o
   PAINEL, que não carrega o CSS do site. */
.foto-botao.enviando::after { content: '\f110'; opacity: 1; animation: girar 1s linear infinite; }
@keyframes girar { to { transform: rotate(360deg); } }
.foto-botao > * { border-radius: inherit; }
/* Escudo não é redondo: a placa dele é quadrada com cantos suaves. */
.foto-quadrada, .foto-quadrada::after { border-radius: var(--raio); }

/* ---------------------------------------------------------------- TITULAR */
.btn-titular {
    display: inline-flex; align-items: center; gap: 7px;
    padding: 6px var(--esp-3);
    border: 1px solid var(--borda);
    border-radius: var(--raio-full);
    font-size: var(--texto-sm); font-weight: 600;
    color: var(--texto-fraco);
    white-space: nowrap;
    transition: background-color var(--vel-rapida) var(--curva),
                color var(--vel-rapida) var(--curva),
                border-color var(--vel-rapida) var(--curva);
}
.btn-titular:hover { border-color: var(--borda-forte); color: var(--texto-suave); }
.btn-titular.ativo {
    background: var(--acento-suave);
    border-color: color-mix(in srgb, var(--acento) 45%, transparent);
    color: var(--acento-forte);
}
.btn-titular.ativo i { color: var(--acento); }
/* Em telas apertadas o rótulo sai e fica só a camisa. */
@media (max-width: 720px) { .btn-titular span { display: none; } }

/* ------------------------------------------------------------------ TOASTS */
#sd-toast-raiz {
    position: fixed; z-index: var(--z-toast);
    bottom: var(--esp-4); left: var(--esp-4); right: var(--esp-4);
    display: flex; flex-direction: column; gap: var(--esp-2);
    pointer-events: none;
}
.sd-toast {
    display: flex; align-items: center; gap: var(--esp-3);
    padding: var(--esp-3) var(--esp-4);
    background: var(--superficie);
    border: 1px solid var(--borda);
    border-left: 3px solid var(--texto-fraco);
    border-radius: var(--raio-sm);
    box-shadow: var(--sombra-xl);
    pointer-events: auto;
    animation: toast-entrar 260ms var(--curva-mola);
}
@keyframes toast-entrar { from { opacity: 0; transform: translateY(14px) scale(.96); } }
.sd-toast.saindo { opacity: 0; transform: translateY(10px); transition: all 180ms ease-in; }
.sd-toast i { flex-shrink: 0; }
.sd-toast-sucesso { border-left-color: var(--sucesso); } .sd-toast-sucesso i { color: var(--sucesso); }
.sd-toast-erro    { border-left-color: var(--erro); }    .sd-toast-erro i    { color: var(--erro); }
.sd-toast-alerta  { border-left-color: var(--alerta); }  .sd-toast-alerta i  { color: var(--alerta); }
.sd-toast-info    { border-left-color: var(--info); }    .sd-toast-info i    { color: var(--info); }

/* ----------------------------------------------------------------- TOOLTIP */
#sd-tooltip {
    /* --seta-x é a posição do centro do elemento apontado, em coordenadas do
       próprio tooltip. O JS a calcula; assim a seta continua sobre o elemento
       mesmo quando a caixa precisa encostar na borda da janela. */
    --seta-x: 50%;
    /* A cor do balão é uma variável e não um valor repetido: a seta é feita de
       bordas e precisa da MESMA cor. Com duas regras de cor concorrendo
       (balão e seta) o tema escuro virava a seta para o lado errado, porque
       `[data-tema] #sd-tooltip::after` e `#sd-tooltip.abaixo::after` têm a
       mesma especificidade e a ordem no arquivo decidia. */
    --balao: var(--cinza-900);
    position: fixed; z-index: var(--z-tooltip);
    padding: 7px 11px;
    background: var(--balao);
    color: #FFF;
    font-size: var(--texto-sm);
    font-weight: 500;
    line-height: 1.4;
    border-radius: var(--raio-sm);
    box-shadow: var(--sombra-lg);
    pointer-events: none;
    opacity: 0;
    transform: translateY(4px);
    transition: opacity var(--vel-rapida) var(--curva), transform var(--vel-rapida) var(--curva-saida);
    max-width: 280px;
    width: max-content;
    text-align: center;
}
#sd-tooltip.visivel { opacity: 1; transform: none; }

/* Seta: triângulo feito de bordas, na cor do balão. */
#sd-tooltip::after {
    content: '';
    position: absolute;
    left: var(--seta-x);
    margin-left: -6px;
    border: 6px solid transparent;
    border-top-color: var(--balao);
    top: 100%;
}
/* Quando não coube em cima, o balão vai para baixo e a seta vira para cima. */
#sd-tooltip.abaixo::after {
    top: auto; bottom: 100%;
    border-top-color: transparent;
    border-bottom-color: var(--balao);
}
#sd-tooltip.abaixo { transform: translateY(-4px); }
#sd-tooltip.abaixo.visivel { transform: none; }

[data-tema="escuro"] #sd-tooltip { --balao: var(--cinza-700); }

/* --------------------------------------------------------------- ESQUELETO
   Placeholder de carregamento. Existe para que blocos alimentados por AJAX
   (ao vivo) não pulem de altura quando o dado chega. */
/* ---------------------------------------------------------------- DIVERSOS */
.barra-acoes { display: flex; align-items: center; gap: var(--esp-2); flex-wrap: wrap; }
.separador { height: 1px; background: var(--borda); border: 0; margin: var(--esp-5) 0; }

.progresso {
    height: 6px;
    background: var(--superficie-alt);
    border-radius: var(--raio-full);
    overflow: hidden;
}
.progresso span {
    display: block; height: 100%;
    background: var(--acento);
    border-radius: var(--raio-full);
    transition: width var(--vel-cena) var(--curva-saida);
}

/* Forma recente do time: V/E/D em bolinhas. */
/* PONTOS, não letras.
   Cinco selos de 18px com V/E/D dentro ocupavam 102px — mais que os 100px
   úteis da coluna — e o excedente acionava a rolagem horizontal do
   invólucro, mesmo numa tela larga em que a tabela inteira caberia.

   Trocar a letra pela cor resolve o espaço e melhora a leitura ao mesmo
   tempo: verde, âmbar e vermelho já são entendidos sem legenda, e uma
   sequência de pontinhos mostra a sequência de resultados em relance, o que
   três letras repetidas não fazem. Cinco pontos de 10px com 5px de intervalo
   somam 70px, com folga de 30px na coluna.

   A LETRA CONTINUA NO HTML, escondida por `font-size: 0`: ela é o que o
   leitor de tela anuncia e o que sobra se a folha de estilo não carregar. O
   `data-tooltip` de cada ponto segue dizendo "Vitória", "Empate", "Derrota". */
/* `vertical-align: middle` porque a caixa é inline-flex: sem isso ela se
   alinha pela LINHA DE BASE de um texto que não existe mais (a letra está em
   `font-size: 0`), e os pontos flutuam acima do centro da célula. */
/* `vertical-align: middle` porque a caixa é inline-flex: sem isso ela se
   alinha pela LINHA DE BASE de um texto que não existe mais (a letra está em
   `font-size: 0`), e os pontos flutuam acima do centro da célula. */
.forma { display: inline-flex; gap: 7px; align-items: center; vertical-align: middle; }

/* O ponto é um DISCO SUAVE COM HALO, não um círculo chapado de cor pura.
   Verde e vermelho em saturação cheia gritam numa tabela que é feita de
   cinza e espaço em branco — o olho vai para os pontos antes de ir para a
   posição do clube, que é o dado principal.

   Duas camadas resolvem isso. O corpo é a cor misturada com a superfície,
   não com transparência: mistura com transparência clareia no tema claro e
   ESCURECE no escuro, e o ponto sumiria lá. Misturar com `--superficie` faz
   os dois temas se ajustarem sozinhos. O halo é a mesma cor a 16%, num
   `box-shadow` de 2px — um contorno que se percebe sem virar borda dura.

   `--forma-cor` existe para o corpo e o halo nunca saírem de tons diferentes:
   cada modificador troca UMA variável, e as duas camadas acompanham. */
.forma span {
    --forma-cor: var(--texto-fraco);
    width: 9px; height: 9px;
    border-radius: 50%;
    font-size: 0;
    flex-shrink: 0;
    background: color-mix(in srgb, var(--forma-cor) var(--forma-mistura, 72%), var(--superficie));
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--forma-cor) 16%, transparent);
}
/* No tema escuro a mistura é com um fundo QUASE PRETO: a 72% ela não suaviza,
   apaga — o ponto vira uma mancha sem cor. Lá o tom já entra mais claro pelos
   próprios tokens (verde-500, vermelho-400), então basta encostar de leve. */
[data-tema="escuro"] .forma span { --forma-mistura: 90%; }
.forma .v { --forma-cor: var(--sucesso); }
/* Empate em CINZA, não em âmbar. Âmbar e vermelho lado a lado, em tamanho de
   ponto e sem rótulo, viram a mesma mancha quente — some justamente a
   distinção que os pontos deviam dar. Cinza não é uma terceira cor
   competindo com as outras duas: é a ausência delas, que é exatamente o que
   um empate é. Também é o único arranjo que sobrevive ao daltonismo
   vermelho-verde, o mais comum. */
.forma .e { --forma-cor: var(--texto-fraco); }
.forma .d { --forma-cor: var(--erro); }

/* ------------------------------------------- NAVEGAÇÃO E ESTADOS DE PÁGINA
   Compartilhados: painel e site usam os mesmos. */
.voltar {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: var(--texto-sm);
    color: var(--texto-suave);
    margin-bottom: var(--esp-3);
    transition: color var(--transicao), gap var(--transicao);
}
.voltar:hover { color: var(--texto); gap: var(--esp-2); }

.estado-vazio {
    display: flex; flex-direction: column; align-items: center;
    gap: var(--esp-3);
    padding: var(--esp-12) var(--esp-5);
    text-align: center;
}
.estado-vazio-icone {
    width: 52px; height: 52px;
    display: grid; place-items: center;
    background: var(--superficie-alt);
    color: var(--texto-fraco);
    border-radius: var(--raio);
    font-size: var(--texto-lg);
}
.estado-vazio h3 { font-size: var(--texto-md); }
.estado-vazio p { color: var(--texto-suave); max-width: 42ch; }

/* ------------------------------------------------------- LISTA DE ATLETAS */
.lista-jogadores { display: flex; flex-direction: column; }
.jogador-linha {
    display: flex; align-items: center; gap: var(--esp-3);
    padding: var(--esp-3) 0;
    border-bottom: 1px solid var(--borda);
    transition: background-color var(--vel-rapida) var(--curva);
}
.jogador-linha:last-child { border-bottom: 0; }
a.jogador-linha { border-radius: var(--raio-sm); padding-inline: var(--esp-2); margin-inline: calc(var(--esp-2) * -1); }
a.jogador-linha:hover { background: var(--superficie-2); }
.jogador-numero {
    width: 30px; height: 30px; flex-shrink: 0;
    display: grid; place-items: center;
    background: var(--superficie-alt);
    color: var(--texto-suave);
    border-radius: var(--raio-sm);
    font-size: var(--texto-sm);
    font-weight: 650;
    font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------- CARTÃO DE JOGO
   Compartilhado: a agenda pública, a lista de partidas do admin e a mesa de
   placar mostram o MESMO confronto. Ficava só em site.css, e por isso a tela
   de Partidas do painel renderizava como texto solto empilhado. */
.jogo {
    display: flex; align-items: center; gap: var(--esp-4);
    padding: var(--esp-3) var(--esp-4);
    background: var(--superficie);
    border: 1px solid var(--borda);
    border-radius: var(--raio);
    transition: border-color var(--transicao), box-shadow var(--transicao), transform var(--transicao);
}
a.jogo:hover { border-color: var(--borda-forte); box-shadow: var(--sombra-md); transform: translateX(3px); }
.jogo-data {
    font-size: var(--texto-sm);
    color: var(--texto-suave);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    min-width: 84px;
    line-height: 1.3;
}
.jogo-times { flex: 1; display: flex; align-items: center; gap: var(--esp-3); min-width: 0; }
.jogo-time { display: flex; align-items: center; gap: var(--esp-2); min-width: 0; flex: 1; }
.jogo-time.fora { justify-content: flex-end; text-align: right; }
.jogo-time span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: 550; }
.jogo-time .escudo, .jogo-time .escudo-vazio { width: 30px; height: 30px; }
.jogo-placar {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    padding: 3px var(--esp-3);
    background: var(--superficie-alt);
    border-radius: var(--raio-sm);
    white-space: nowrap;
}
.jogo-placar.vivo { background: var(--erro-suave); color: var(--erro); }
.jogo-seta { color: var(--texto-fraco); transition: transform var(--transicao); }
a.jogo:hover .jogo-seta { transform: translateX(3px); color: var(--acento); }

/* Slot do estado, à direita. No estreito ele toma só o que precisa. */
.jogo-fim { display: flex; align-items: center; justify-content: flex-end; gap: var(--esp-2); }

/* No celular o selo "Encerrada" sai. Ele é o único do grupo que REPETE o que
   a linha já diz: se há placar, o jogo acabou. "Agendado" e "A definir" ficam,
   porque sem eles não há como saber o estado. Mantê-lo custava 94px do espaço
   dos nomes, e o time virava "Invenc…". */
@media (max-width: 719px) {
    .jogo-fim .etiqueta-sucesso { display: none; }
}

/* Em tela estreita o cartão vira DUAS LINHAS: data e estado em cima, o
   confronto ocupando a largura inteira embaixo.

   Numa linha só, os 84px da data mais o slot de estado deixavam cerca de
   200px para dois escudos, dois nomes e o placar — e os nomes saíam como
   "Invenc…" mesmo depois de todo o resto ter sido enxugado. Não havia mais o
   que cortar: faltava largura, e largura é o que a segunda linha devolve.

   Com o espaço inteiro, o nome também deixa de ser truncado e passa a
   quebrar. Duas linhas de nome legível valem mais que uma linha com
   reticências — aqui o nome do clube é o dado principal do cartão. */
@media (max-width: 519px) {
    .jogo { flex-wrap: wrap; }
    /* Some o `min-width: 84px`: na linha de cima a data toma só o que precisa. */
    .jogo-data { min-width: 0; }
    .jogo-fim  { margin-left: auto; }
    /* `flex-basis: 100%` força a quebra; `order` garante que o confronto fique
       embaixo mesmo vindo antes do estado no HTML. */
    .jogo-times { flex: 1 0 100%; order: 3; }
    .jogo-time span {
        white-space: normal;
        overflow: visible;
        text-overflow: clip;
        overflow-wrap: anywhere;
    }
}

/* Largura FIXA só a partir de 720px: aí todas as linhas reservam o mesmo
   espaço e o placar cai no mesmo eixo, mesmo com estados diferentes — uma
   rodada já disputada (seta estreita) alinha com a seguinte (etiqueta
   "Agendado", larga).

   No celular a regra NÃO vale de propósito. Reservar 92px numa tela de 375
   sai do espaço dos nomes, e o time passa a aparecer como "Invenc…" — ali as
   linhas são lidas uma a uma, e ler o nome importa mais que alinhar colunas
   que ninguém compara de relance.

   `flex-shrink: 0` é obrigatório: sem ele o flex encolheria o slot de volta
   quando o nome fosse longo, e a largura fixa viraria sugestão. */
@media (min-width: 720px) {
    /* Cabe o selo mais largo ("Encerrada") e a seta ao lado dele. */
    .jogo-fim { flex: 0 0 122px; }
}

/* --------------------------------------------------------------- GRÁFICOS
   Moldura dos SVG gerados por graficos.js. Compartilhada entre a ficha do
   atleta (site) e a visão geral (painel). */
.grafico-caixa { display: grid; place-items: center; padding: var(--esp-4); }
/* Legenda do gráfico: o que o número significa. Um eixo sem explicação obriga
   quem lê a deduzir a métrica pelo desenho. */
.grafico-nota {
    margin-top: var(--esp-3);
    max-width: 60ch;
    text-align: center;
    font-size: var(--texto-xs);
    line-height: 1.5;
    color: var(--texto-fraco);
}
.grafico-legenda {
    display: flex; flex-wrap: wrap; justify-content: center; gap: var(--esp-3);
    margin-top: var(--esp-3);
    font-size: var(--texto-sm); color: var(--texto-suave);
}
.grafico-legenda span { display: inline-flex; align-items: center; gap: 6px; }
.grafico-legenda i { width: 9px; height: 9px; border-radius: 3px; display: inline-block; }

/* ------------------------------------------------------------ CHAVEAMENTO
   Escada clássica: cada fase é uma coluna, e os confrontos de uma fase ficam
   verticalmente CENTRADOS em relação aos dois que os alimentaram. Antes as
   colunas usavam `space-around`, que distribui os jogos pelo espaço livre —
   a semifinal não parava no meio das suas quartas e o desenho parecia torto.

   O centro é obtido com `justify-content: center` + `flex: 1` nos jogos: cada
   confronto ocupa a mesma fatia da coluna, então o de cima da fase seguinte
   nasce exatamente entre os dois de cima da anterior. */
.chaveamento {
    display: flex; gap: var(--esp-5);
    align-items: stretch;
    overflow-x: auto;
    padding-bottom: var(--esp-3);
}
.chave-fase {
    flex: 1; min-width: 210px;
    display: flex; flex-direction: column;
}
.chave-fase-titulo {
    font-size: var(--texto-xs); font-weight: 700;
    text-transform: uppercase; letter-spacing: .08em;
    color: var(--texto-suave);
    padding-bottom: var(--esp-3);
    margin-bottom: var(--esp-2);
    border-bottom: 1px solid var(--borda);
}
/* O invólucro dos jogos é quem centraliza; o título fica fixo no topo. */
.chave-jogos { flex: 1; display: flex; flex-direction: column; justify-content: space-evenly; gap: var(--esp-3); }
.chave-jogo {
    border: 1px solid var(--borda);
    border-radius: var(--raio-sm);
    overflow: hidden;
    background: var(--superficie);
    transition: border-color var(--transicao), box-shadow var(--transicao), transform var(--transicao);
}
.chave-jogo:hover { border-color: var(--borda-forte); box-shadow: var(--sombra-md); transform: translateY(-2px); }
.chave-time {
    display: flex; align-items: center; gap: var(--esp-2);
    padding: var(--esp-2) var(--esp-3);
    font-size: var(--texto-sm);
}
.chave-time + .chave-time { border-top: 1px solid var(--borda); }
.chave-time.venceu { font-weight: 650; background: var(--acento-suave); }
.chave-time .placar { margin-left: auto; font-variant-numeric: tabular-nums; font-weight: 650; }
/* Vaga ainda não decidida. O texto aqui não é "A definir": é de ONDE o time
   vem — "1º do Grupo A", "Vencedor do Jogo 3" — que é o que o torcedor
   precisa ler semanas antes de a bola rolar. Itálico e cor fraca deixam claro
   que ainda é uma promessa, não um nome. */
.chave-time.indefinido { color: var(--texto-fraco); font-style: italic; }
/* Pênaltis entre parênteses, do lado do placar: "2 (4)". */
.chave-time .placar small {
    font-size: .8em; font-weight: 600; color: var(--texto-suave); margin-left: 3px;
}
/* Número do jogo e horário. É por este número que a fase seguinte se refere
   a este confronto ("Vencedor do Jogo 3"), então ele precisa estar visível. */
.chave-jogo-topo {
    display: flex; justify-content: space-between; gap: var(--esp-2);
    padding: 5px var(--esp-3);
    background: var(--superficie-2);
    border-bottom: 1px solid var(--borda);
    font-size: var(--texto-xs); color: var(--texto-suave);
    font-variant-numeric: tabular-nums;
}
.chave-jogo-topo span:first-child { font-weight: 700; }

/* ------------------------------------------------------------------- AUTH
   Tela de login. Fica na base (e não no painel) porque não carrega a casca do
   admin: é uma página solta, sem sidebar. */
.palco-auth {
    min-height: 100dvh;
    display: grid; place-items: center;
    padding: var(--esp-5);
    background: var(--fundo);
    background-image: var(--grad-palco);
}
.caixa-auth {
    width: min(100%, 400px);
    padding: var(--esp-8) var(--esp-6);
    background: var(--superficie);
    border: 1px solid var(--borda);
    border-radius: var(--raio-xl);
    box-shadow: var(--sombra-xl);
    animation: subir var(--vel-cena) var(--curva-saida) both;
}
.auth-marca {
    display: flex; flex-direction: column; align-items: center; gap: var(--esp-3);
    margin-bottom: var(--esp-6);
    text-align: center;
    font-weight: 650;
    font-size: var(--texto-lg);
    letter-spacing: -.02em;
}
.auth-marca-icone {
    width: 52px; height: 52px;
    display: grid; place-items: center;
    background: var(--grad-acento);
    color: #FFF;
    border-radius: var(--raio);
    font-size: var(--texto-xl);
    box-shadow: var(--sombra-acento);
}
/* A logomarca de verdade. `width: auto` com `max-width: 100%` deixa a arte no
   formato dela: uma marca horizontal fica horizontal, uma quadrada fica
   quadrada, e nenhuma das duas é esticada. A altura é o único limite. */
.auth-marca-logo {
    height: auto;
    max-height: 80px;
    width: auto;
    max-width: 100%;
    object-fit: contain;
}

/* ------------------------------------------------------------------- ERROS */
.cartao-erro {
    width: min(100%, 460px);
    margin: var(--esp-16) auto;
    padding: var(--esp-10) var(--esp-6);
    text-align: center;
    background: var(--superficie);
    border: 1px solid var(--borda);
    border-radius: var(--raio-xl);
    box-shadow: var(--sombra-lg);
}
.erro-icone {
    width: 64px; height: 64px;
    margin: 0 auto var(--esp-4);
    display: grid; place-items: center;
    border-radius: 50%;
    background: var(--alerta-suave);
    color: var(--alerta);
    font-size: var(--texto-2xl);
}
/* Título em caixa normal e frase com medida de leitura: em versal e coladas
   na borda do cartão, três linhas de texto viravam um bloco de aviso. */
.cartao-erro h2 {
    text-transform: none;
    letter-spacing: -.01em;
    font-size: var(--texto-xl);
    line-height: 1.25;
}
.cartao-erro p {
    color: var(--texto-suave);
    margin: var(--esp-3) auto var(--esp-6);
    max-width: 34ch;
    line-height: 1.55;
}
/* Ações empilhadas e centradas: a secundária é um caminho alternativo, não
   um par do botão principal. */
.cartao-erro .aovivo-acoes { flex-direction: column; align-items: center; gap: var(--esp-3); }
.cartao-erro .aovivo-acoes .btn-fantasma { font-size: var(--texto-sm); }

/* -------------------------------------------------------------- ANIMAÇÕES
   Duas entradas nomeadas, usadas por painel e site. Tudo o mais é transição
   de estado — animação de entrada em excesso cansa quem usa o sistema todo
   dia (o admin), então ela mora quase só no site público. */
@keyframes subir   { from { opacity: 0; transform: translateY(14px); } }
@keyframes surgir  { from { opacity: 0; } }
/* Revelação no scroll. O estado inicial só é aplicado quando o JS assume o
   controle (html.js-reveal); sem JS, nada some — o conteúdo fica legível. */
.js-reveal [data-revelar] { opacity: 0; transform: translateY(18px); }
[data-revelar].revelado {
    opacity: 1; transform: none;
    transition: opacity var(--vel-cena) var(--curva), transform var(--vel-cena) var(--curva-saida);
}

/* ------------------------------------------------------------- BREAKPOINTS */
@media (min-width: 640px) {
    .grade-2 { grid-template-columns: repeat(2, 1fr); }
    .grade-4 { grid-template-columns: repeat(4, 1fr); }
    .grupo-campos { grid-template-columns: 1fr 1fr; }
    #sd-toast-raiz { left: auto; width: 380px; }
}
@media (min-width: 1024px) {
    .grade-3 { grid-template-columns: repeat(3, 1fr); }
    .grade-lateral { grid-template-columns: 380px 1fr; }
    .grupo-campos-3 { grid-template-columns: repeat(3, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
    }
    .js-reveal [data-revelar] { opacity: 1; transform: none; }
}

/* ------------------------------------------------- FAIXA DE INDICADORES */
/* Ícone + número + rótulo em linha. Nasceu na ficha do clube, mas a ficha
   de acervo do painel usa o mesmo componente — por isso vive aqui, e não em
   site.css: componente compartilhado em CSS de uma área só é exatamente
   como o admin já apareceu sem estilo antes. */
.faixa-indicadores {
    /* auto-fit reage à largura do CONTÊINER, não da janela. Isso importa no
       painel, onde o mesmo bloco vive dentro de um cartão ao lado de uma
       sidebar de 260px: media query de viewport acharia que há espaço de
       sobra e espremeria seis colunas num cartão estreito. As telas do site
       ainda fixam a contagem nos seus breakpoints. */
    display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
    border-top: 1px solid var(--borda);
    background: var(--superficie);
}
.indicador-item {
    display: flex; align-items: center; gap: var(--esp-3);
    padding: var(--esp-4) var(--esp-5);
    border-bottom: 1px solid var(--borda);
}
.indicador-item-icone {
    width: 38px; height: 38px; flex-shrink: 0;
    display: grid; place-items: center;
    border-radius: var(--raio);
    background: var(--superficie-alt);
    color: var(--texto-suave);
    font-size: var(--texto-base);
}
.indicador-item-icone.acento  { background: var(--acento-suave);  color: var(--acento); }
.indicador-item-icone.sucesso { background: var(--sucesso-suave); color: var(--sucesso); }
.indicador-item-icone.erro    { background: var(--erro-suave);    color: var(--erro); }
.indicador-item-icone.alerta  { background: var(--alerta-suave);  color: var(--alerta); }
.indicador-item-icone.info    { background: var(--info-suave);    color: var(--info); }
.indicador-item b {
    display: block;
    font-size: var(--texto-xl); font-weight: 750;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}
.indicador-item small {
    font-size: var(--texto-xs); color: var(--texto-suave);
    text-transform: uppercase; letter-spacing: .06em;
}


/* Modal largo: para EXPANDIR conteúdo (listas, tabelas), não para formulário.
   O modal padrão tem 460px porque formulário largo demais fica ruim de ler —
   a linha do olho fica longa e o campo seguinte some do campo de visão.
   A EXCEÇÃO é o formulário que não é uma pilha de campos e sim uma GRADE
   (o montador de grupos, que exibe colunas lado a lado). Ali a largura não
   estica linha nenhuma: ela cabe mais colunas. Por isso a largura extra é
   uma classe à parte, e não um relaxamento desta regra. */
.sd-modal-grande { width: min(100%, 720px); }
.sd-modal-grande .sd-modal-corpo { overflow-y: auto; }
.sd-modal-grade { width: min(100%, 840px); }
.sd-modal-grade .sd-modal-corpo { overflow-y: auto; }

/* ================================================================== ETIQUETAS
   Campo de tags do editor de notícias. A caixa inteira PARECE um input: a
   borda é dela, não do campo de texto de dentro. Sem isso as pílulas ficam
   flutuando ao lado de um input pequeno e a relação entre as duas coisas se
   perde. */
.campo-tags {
    display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
    position: relative;
    min-height: 44px;
    padding: 7px 10px;
    background: var(--superficie-2);
    border: 1px solid var(--borda);
    border-radius: var(--raio);
    cursor: text;
    transition: border-color var(--transicao), box-shadow var(--transicao);
}
.campo-tags:focus-within {
    border-color: var(--acento);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--acento) 18%, transparent);
}
.campo-tags-entrada {
    flex: 1; min-width: 140px;
    border: 0; background: none; outline: none;
    color: var(--texto);
    font: inherit; font-size: var(--texto-base);
    padding: 3px 0;
}
.tag-pilula {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 3px 4px 3px 10px;
    border-radius: var(--raio-full);
    background: var(--acento-suave);
    color: var(--acento-forte);
    font-size: var(--texto-sm); font-weight: 600;
    white-space: nowrap;
}
.tag-remover {
    display: grid; place-items: center;
    width: 18px; height: 18px;
    border-radius: 50%;
    color: inherit; opacity: .6;
    font-size: 10px;
    transition: opacity var(--transicao), background var(--transicao);
}
.tag-remover:hover { opacity: 1; background: color-mix(in srgb, var(--acento) 22%, transparent); }

/* A lista de sugestões flutua sobre o conteúdo seguinte: empurrando o layout,
   o formulário inteiro pularia a cada tecla digitada. */
/* MESMA PALETA DO BALÃO DO PATROCINADOR (`.balao-marca`, em site.css): folha
   branca com moldura fina, cabeçalho em `--superficie-alt` e sombra dupla.
   É o mesmo objeto conceitual — um painel que salta de um elemento e traz
   informação secundária —, e o sistema já tinha resolvido esse tom uma vez.

   As pílulas ficam no tom `alt`, como as etiquetas escolhidas logo acima: é o
   único cinza da tela e não briga com o cabeçalho, que usa o mesmo.

   FLUXO DE PÍLULAS, não coluna nem grade de colunas iguais. A coluna única
   virava rolagem interminável numa tela larga; a grade de colunas fixas dava a
   toda pílula a mesma largura, e "secult" ocupava o espaço de uma etiqueta de
   quarenta letras. `flex-wrap` faz cada uma medir o próprio conteúdo. */
.campo-tags-sugestoes {
    position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 20;
    max-height: 280px; overflow-y: auto;
    display: flex; flex-wrap: wrap; align-content: flex-start;
    gap: 6px;
    background: var(--superficie);
    border: 1px solid var(--borda);
    border-radius: 14px;
    box-shadow: var(--sombra-lg), var(--sombra-xl);
    padding: var(--esp-2);
}
/* PÍLULA, não linha de lista. Sobre o fundo branco do painel, um botão sem
   preenchimento vira texto solto: em grade não há sequer a linha divisória que
   uma lista em coluna dava, e o resultado é uma sopa de palavras onde não se
   distingue onde termina uma etiqueta e começa a outra.

   A forma é a MESMA da `.tag-pilula` que a escolha produz — arredondada, com
   fundo próprio. Assim o gesto fica óbvio: o que está na lista é o que vai
   virar pílula acima. A diferença é a cor: aqui neutra (ainda não é sua),
   lá no acento (já escolhida). */
.campo-tags-sugestao {
    display: inline-flex; align-items: center; gap: var(--esp-2);
    /* LARGURA DO CONTEÚDO. `width: 100%` fazia sentido na grade, onde a célula
       mandava; no fluxo de pílulas ele esticaria cada uma até o fim da linha e
       voltaria a coluna única. */
    width: auto;
    /* Teto só para o caso extremo: uma etiqueta muito longa não pode ocupar a
       fileira inteira sozinha. Aí o nome trunca com reticências. */
    max-width: 100%;
    padding: 5px 6px 5px 12px;
    border-radius: var(--raio-full);
    background: var(--superficie-alt);
    border: 1px solid var(--borda);
    text-align: left;
    color: var(--texto);
    font-size: var(--texto-sm); font-weight: 550;
    transition: background-color var(--vel-rapida) var(--curva),
                border-color var(--vel-rapida) var(--curva),
                color var(--vel-rapida) var(--curva);
}
/* No hover ela ANTECIPA o resultado: assume a cor que vai ter depois de
   escolhida. Confirma o destino antes do clique, sem precisar de texto. */
.campo-tags-sugestao:hover,
.campo-tags-sugestao:focus-visible {
    background: var(--acento-suave);
    border-color: var(--acento);
    color: var(--acento-forte);
}
/* Cabeçalho da lista, só no modo "todas as etiquetas". Discreto de propósito:
   é uma legenda, não um item clicável, e precisa ser lido como diferente das
   opções logo abaixo — daí caixa alta miúda e cor fraca. */
/* Cabeçalho igual ao `.balao-cabeca`: faixa em `--superficie-alt`, separada
   por uma linha de `--borda` e com o texto miúdo em `--texto-fraco`. Sangra
   até as bordas anulando o padding do painel — faixa que para antes da borda
   parece um retângulo esquecido no meio do painel. */
.campo-tags-titulo {
    /* `100%` mediria a caixa de CONTEÚDO do painel, e a faixa sobraria 16px
       antes da borda direita. O `calc` devolve os dois paddings. */
    flex: 0 0 calc(100% + var(--esp-2) * 2);
    margin: calc(var(--esp-2) * -1) calc(var(--esp-2) * -1) var(--esp-2);
    padding: 8px 14px 7px;
    background: var(--superficie-alt);
    border-bottom: 1px solid var(--borda);
    border-radius: 13px 13px 0 0;   /* 14 do painel menos a borda de 1px */
    font-size: 8.5px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .1em;
    color: var(--texto-fraco);
}
.campo-tags-nome {
    min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.campo-tags-sugestao small {
    /* O contador nunca encolhe: ele tem duas ou três letras e é o que dá a
       dica de qual etiqueta é a estabelecida. Quem cede espaço é o nome. */
    flex-shrink: 0;
    padding: 1px 7px;
    border-radius: var(--raio-full);
    /* Branco sobre a pílula cinza: precisa contrastar com o fundo dela. */
    background: var(--superficie);
    border: 1px solid var(--borda);
    color: var(--texto-fraco);
    font-size: var(--texto-xs); font-weight: 600;
    line-height: 1.5;
}
.campo-tags-sugestao:hover small {
    background: var(--superficie);
    border-color: var(--acento);
    color: var(--acento-forte);
}

/* ------------------------------------------------------- ENVIO EM LOTE
   As fotos ESCOLHIDAS, antes de subir. Deliberadamente parecido com a galeria
   já salva logo acima: são a mesma coisa em dois momentos, e desenhá-las
   diferente faria a pessoa procurar a diferença que não existe.

   O que separa as duas é a moldura tracejada — o tracejado é a convenção de
   "provisório" e diz, sem escrever, que aquilo ainda não está no álbum. */
.upload-lote-acoes {
    display: flex; align-items: center; gap: var(--esp-3); flex-wrap: wrap;
    margin-bottom: var(--esp-3);
}
.upload-lote-grade {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(min(110px, 100%), 1fr));
    gap: var(--esp-3);
    margin-bottom: var(--esp-3);
}
.lote-item {
    position: relative; margin: 0;
    aspect-ratio: 1;
    border-radius: var(--raio);
    overflow: hidden;
    background: var(--superficie-alt);
    border: 1px dashed var(--borda-forte);
}
.lote-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* O tamanho do arquivo sobre a foto: é o dado que explica por que um envio
   demora, e a única pista de que a imagem veio direto da câmera. */
.lote-item figcaption {
    position: absolute; left: 0; right: 0; bottom: 0;
    padding: 2px 6px;
    background: linear-gradient(to top, rgb(0 0 0 / .68), transparent);
    color: #FFF;
    font-size: var(--texto-xs);
    text-align: right;
}
.lote-tirar {
    position: absolute; top: 5px; right: 5px;
    display: grid; place-items: center;
    width: 26px; height: 26px;
    border-radius: 50%;
    background: rgb(0 0 0 / .62);
    color: #FFF;
    font-size: 12px;
    transition: background var(--transicao);
}
.lote-tirar:hover { background: var(--erro); }

/* ---------------------------------------------------- GALERIA DO ADMIN
   Miniaturas quadradas com o botão de remover no canto. `aspect-ratio` em vez
   de altura fixa: fotos de proporções diferentes ficariam com alturas
   diferentes e a grade viraria uma serra. */
.galeria-admin {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
    gap: var(--esp-3);
}
.galeria-admin-item {
    position: relative; margin: 0;
    aspect-ratio: 1;
    border-radius: var(--raio);
    overflow: hidden;
    background: var(--superficie-alt);
    border: 1px solid var(--borda);
}
.galeria-admin-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.galeria-admin-remover {
    position: absolute; top: 5px; right: 5px;
    display: grid; place-items: center;
    width: 26px; height: 26px;
    border-radius: 50%;
    background: rgb(0 0 0 / .62);
    color: #FFF;
    font-size: 12px;
    opacity: 0;
    transition: opacity var(--transicao), background var(--transicao);
}
.galeria-admin-item:hover .galeria-admin-remover,
.galeria-admin-remover:focus-visible { opacity: 1; }
.galeria-admin-remover:hover { background: var(--erro); }
/* Em telas de toque não existe hover: o botão fica sempre visível, senão não
   haveria como remover uma foto pelo celular. */
@media (hover: none) {
    .galeria-admin-remover { opacity: 1; }
}

/* ------------------------------------------------- COLUNAS DISPENSÁVEIS
   Colunas de tabela que somem no celular e voltam quando há largura. Moram
   aqui, e não em site.css, porque painel e site têm tabelas largas — e o
   painel não carrega a folha do site: a coluna sumia no estreito e não
   voltava nunca. */
.esconde-sm { display: none; }
.esconde-md { display: none; }
@media (min-width: 640px)  { .esconde-sm { display: table-cell; } }
@media (min-width: 1100px) { .esconde-md { display: table-cell; } }

/* ------------------------------------------------------------ CONTADOR
   Contagem de caracteres ao lado do campo. Fica discreta enquanto sobra
   espaço e só chama atenção quando o limite se aproxima — um número em
   vermelho o tempo todo vira ruído e deixa de avisar. */
.contador {
    font-family: var(--fonte-mono);
    font-size: var(--texto-xs);
    font-variant-numeric: tabular-nums;
    color: var(--texto-fraco);
    transition: color var(--transicao);
    float: right;
}
.contador-perto     { color: var(--alerta); font-weight: 700; }
.contador-estourado { color: var(--erro);   font-weight: 700; }

/* ------------------------------------------------- CARTÃO DE GALERIA (admin)
   A lista de álbuns é visual: uma tabela de títulos não diria qual é qual. */
.galeria-cartao { display: flex; flex-direction: column; overflow: hidden; }
.galeria-cartao-capa {
    position: relative; display: block;
    aspect-ratio: 16 / 10; overflow: hidden;
    background: var(--superficie-alt);
}
.galeria-cartao-capa img { width: 100%; height: 100%; object-fit: cover; }
.galeria-cartao-vazia {
    display: grid; place-items: center; width: 100%; height: 100%;
    color: var(--texto-fraco); font-size: var(--texto-2xl);
}
.galeria-cartao-conta {
    position: absolute; right: var(--esp-3); bottom: var(--esp-3);
    display: inline-flex; align-items: center; gap: 5px;
    padding: 2px var(--esp-3);
    border-radius: var(--raio-full);
    background: rgb(0 0 0 / .6);
    color: #FFF;
    font-size: var(--texto-xs); font-weight: 700;
}
/* Foto + legenda como uma unidade: escrever a legenda longe da imagem
   obrigaria a decorar qual é qual. */
.galeria-admin-foto { display: flex; flex-direction: column; gap: 6px; }
.entrada-mini { padding: 5px var(--esp-2); min-height: 32px; font-size: var(--texto-xs); }

/* ------------------------------------------------------------ REDES SOCIAIS
   O ícone no rótulo do campo carrega a cor da marca — é como a pessoa
   identifica a rede antes de ler o nome. Cores literais aqui são a exceção
   justificada à regra de só usar tokens: são as cores DAS MARCAS, não do
   sistema, e não mudam com o tema. */
.rede-icone { width: 16px; text-align: center; margin-right: 5px; }
.rede-facebook  { color: #1877F2; }
.rede-instagram { color: #E4405F; }
.rede-twitter   { color: var(--texto); }
.rede-youtube   { color: #FF0000; }
.rede-whatsapp  { color: #25D366; }

/* ------------------------------------------------------- CAMPO COM ERRO
   Aviso de validação feito por nós, e não pelo navegador.

   A bolha nativa (`required`) não serve para todo campo: quando o controle
   está escondido — o `input[type=file]` do componente de upload é
   `display:none` — o navegador se recusa a enviar o formulário e NÃO mostra
   mensagem nenhuma, porque não há onde ancorá-la. O resultado é um botão
   Salvar que não faz nada e ninguém explica. */
.campo-erro {
    display: flex; align-items: center; gap: 6px;
    margin-top: 6px;
    color: var(--erro-forte);
    font-size: var(--texto-sm); font-weight: 600;
}
.campo-erro i { font-size: var(--texto-xs); }

/* A moldura tracejada do upload acende junto: a mensagem diz o que fazer, a
   borda diz ONDE. */
.upload.invalido { border-color: var(--erro); background: var(--erro-suave); }
