/* SONLAS CSS v17 — 2026-08-13 */
/* ===========================================================================
   SISTEMA DE TEMAS — v3 (tokenização, §I1)
   ---------------------------------------------------------------------------
   REGRA QUE NÃO PODE SER QUEBRADA: os tokens `--c-*` e `--tier-*` guardam
   **canais RGB separados por espaço** — sem `#`, sem `rgb()`, sem vírgula.
   É isso que permite ao Tailwind compor opacidade via `<alpha-value>`
   (`rgb(var(--c-gold) / <alpha-value>)`) e faz as 29 classes com `/opacidade`
   (82 usos no markup) funcionarem. Guardar hex aqui quebraria as 82 EM SILÊNCIO:
   cor sólida onde deveria haver transparência, sem nenhum erro no console.

   FONTE ÚNICA DE COR (§I1.1): as variáveis legadas (`--bg`, `--gold`, `--text`…),
   que `.btn-*`, `.alert*` e o shell consomem, DERIVAM destes tokens logo abaixo.
   Não crie um segundo conjunto — foi o que produziu a divergência
   lendas.php × theme-extend.js na v2.

   `:root` = LIGHT (também é o que o ADMIN usa, pois ele nunca recebe `.dark`).
   `html.dark` = DARK (default de produto no site público).
   Os DOIS temas definem o conjunto COMPLETO: token presente num e ausente no
   outro não gera erro — a cor simplesmente não aplica. Conferir por diff de listas.
   =========================================================================== */

:root {
    /* ---- superfícies (papel semântico igual nos dois temas: 900 = página, 800 = cartão) ---- */
    --c-bg-900: 244 246 251;
    --c-bg-800: 255 255 255;
    --c-brasao-fundo: 10 17 40;  /* v10: placa do brasao — navy da marca, IGUAL nos 2 temas (ver nota v10) */
    --c-bg-700: 238 241 247;
    --c-bg-600: 230 234 242;
    --c-bg-500: 217 223 235;
    --c-border: 222 227 236;
    --c-border-strong: 197 205 219;

    /* ---- texto (todos medidos >= AA 4.5 na pior superfície do tema) ---- */
    --c-text: 10 17 40;          /* 16.52:1 em bg.700 */
    --c-text-muted: 88 97 116;  /*  5.24:1 em bg.700 */
    --c-text-subtle: 97 105 124; /*  4.86:1 em bg.700 */

    /* ---- dourado. No light precisa ser ESCURO para servir de TEXTO (5.55:1);
            por isso o texto SOBRE o dourado inverte para branco (6.00:1). ---- */
    --c-gold: 117 91 42;
    --c-gold-light: 127 100 49;
    --c-gold-dark: 90 70 32;
    --c-on-gold: 255 255 255;

    /* ---- estados ---- */
    --c-pago: 15 122 55;
    --c-pendente: 134 96 0;
    --c-rejeitado: 193 21 43;

    /* A barra é uma SUPERFÍCIE própria: no dark ela é quase preta, no light é quase branca.
       `--c-on-topbar` é a cor do texto SOBRE ela. Sem estes dois, o `.brand` usava `--text`
       (que inverte por tema) sobre um gradiente cravado escuro → texto escuro sobre escuro. */
    --c-topbar-de: 255 255 255;
    --c-topbar-ate: 244 246 251;
    --c-on-topbar: 10 17 40;
    --c-perigo-on-topbar: 193 21 43;

    /* Tipos de evento do feed (§I12 item 1). Nome encode PAPEL, nunca cor (§I12.1):
       quem le --c-evento-rodada sabe o que e; --c-evento-azul mentiria no dia da troca. */
    --c-evento-rodada: 29 78 216;
    --c-evento-badge: 126 34 206;
    --c-evento-inscricao: 21 101 52;

    /* ICONE de medalha (EMENDA 17). Deliberadamente NAO reusa a medalha-BADGE: aquela e texto
       FIXO sobre gradiente FIXO (excecao §I12.3); esta e cor VARIAVEL que inverte com o tema.
       Reusar seria recolapsar dois papeis distintos, na direcao contraria a EMENDA 6. */
    --c-medalha-ouro: 133 109 53;
    --c-medalha-prata: 113 113 113;
    --c-medalha-bronze: 149 102 67;

    /* ---- tiers: o badge é a cor sobre 13% dela mesma, então o valor muda por tema.
            Escolhi o MAIS CLARO que ainda passa AA, preservando o matiz do dark. ---- */
    /* Afinados contra a PIOR superficie onde o chip cai, nao contra bg-800: o herói do
       perfil (perfil.php:120) é `from-bg-800 to-bg-700`, e na ponta bg-700 o chip a 13%
       escurece o fundo. Medir no branco dava 4.1x — reprova. Não reafine no branco. */
    --tier-aprendiz-text: 92 97 105;
    --tier-guerreiro-text: 127 87 63;
    --tier-cavaleiro-text: 97 97 97;
    --tier-guardiao-text: 118 93 43;
    --tier-vanguarda-text: 35 104 124;
    --tier-mitico-text: 20 110 73;
    --tier-ascendente-text: 104 50 202;
    --tier-lendario-text: 167 56 56;

    /* Papel SUPERFICIE (§I13) — 1.4.11, 3:1 contra a TRILHA adjacente (bg-bg-900/60),
       nao 4.5:1 contra o fundo. Criterio diferente do -text, logo valor diferente:
       escurecer para o texto passar APROXIMA a barra da trilha. Nao unifique os dois.
       ⚠️ A trilha vive DENTRO do heroi, que e gradiente — entao sao DUAS trilhas, nao uma
       (§I9.1). Afinei estes valores contra 3.05 na trilha clara e os 8 reprovaram na escura
       (2.87–2.95). Refeitos contra AS DUAS, com margem: pior 3.26. Nao reafine contra uma so. */
    --tier-aprendiz-surface: 130 134 143;
    --tier-guerreiro-surface: 168 126 99;
    --tier-cavaleiro-surface: 134 134 134;
    --tier-guardiao-surface: 157 132 83;
    --tier-vanguarda-surface: 51 145 174;
    --tier-mitico-surface: 53 150 111;
    --tier-ascendente-surface: 154 111 232;
    --tier-lendario-surface: 232 84 84;

    /* ---- legadas: DERIVADAS dos tokens (fonte única, §I1.1) ---- */
    --bg: rgb(var(--c-bg-900));
    --bg-soft: rgb(var(--c-bg-700));
    --bg-muted: rgb(var(--c-bg-600));
    --bg-card: rgb(var(--c-bg-800));
    --border: rgb(var(--c-border));
    --border-strong: rgb(var(--c-border-strong));
    --text: rgb(var(--c-text));
    --text-muted: rgb(var(--c-text-muted));
    --text-subtle: rgb(var(--c-text-subtle));
    --gold: rgb(var(--c-gold));
    --gold-light: rgb(var(--c-gold-light));
    --gold-dark: rgb(var(--c-gold-dark));
    --on-gold: rgb(var(--c-on-gold));
    --ok: rgb(var(--c-pago));
    --danger: rgb(var(--c-rejeitado));
    --warn: rgb(var(--c-pendente));

    /* não-cor e tons de apoio (iguais nos dois temas salvo onde redefinido) */
    --accent: #1a4bd6;
    --accent-hover: #1440b8;
    --accent-soft: #e7edff;
    --gold-soft: #fbf5e5;
    --purple: #7c3aed;
    --purple-soft: #f2e9ff;
    --ok-bg: #e6f7ee;
    --ok-border: #b9e6ce;
    --danger-bg: #fde9ec;
    --danger-border: #f4b8c0;
    --warn-bg: #fff5d6;
    --warn-border: #f0dfa6;
    --info: #1a4bd6;
    --info-bg: #e7edff;
    --info-border: #c9d5ff;
    --radius: 12px;
    --radius-lg: 16px;
    --shadow-sm: 0 1px 2px rgba(10, 17, 40, 0.05);
    --shadow-md: 0 6px 20px rgba(10, 17, 40, 0.08);
    --shadow-lg: 0 18px 40px rgba(10, 17, 40, 0.12);
    --shadow-glow: 0 0 0 4px rgba(26, 75, 214, 0.14);
    --shadow-gold: 0 0 0 4px rgba(122, 95, 44, 0.22);
}

html.dark {
    --c-bg-900: 11 14 20;
    --c-bg-800: 16 21 33;
    --c-brasao-fundo: 10 17 40;  /* v10: mesmo valor de proposito — o brasao foi desenhado sobre este navy */
    --c-bg-700: 22 28 42;
    --c-bg-600: 30 37 55;
    --c-bg-500: 37 46 66;
    --c-border: 35 43 61;
    --c-border-strong: 47 58 85;

    --c-text: 231 236 243;       /* 15.8:1 em bg.900 */
    --c-text-muted: 168 178 197; /*  7.98:1 na pior superfície */
    --c-text-subtle: 138 147 166;/*  5.52:1 na pior superfície */

    --c-gold: 201 169 106;       /* claro: serve de texto (8.62:1) e de botão */
    --c-gold-light: 231 206 151;
    --c-gold-dark: 162 134 78;
    --c-on-gold: 10 17 40;       /* texto escuro sobre o dourado (8.34:1) */

    --c-pago: 62 207 106;
    --c-pendente: 245 183 67;
    --c-rejeitado: 239 91 111;

    --c-topbar-de: 10 17 40;
    --c-topbar-ate: 16 25 61;
    --c-on-topbar: 238 241 251;
    --c-perigo-on-topbar: 255 177 187;

    --c-evento-rodada: 147 197 253;
    --c-evento-badge: 216 180 254;
    --c-evento-inscricao: 134 239 172;

    /* no escuro os valores historicos ja passam (12.32 · 10.73 · 6.15), entao ficam */
    --c-medalha-ouro: 255 209 102;
    --c-medalha-prata: 201 201 201;
    --c-medalha-bronze: 201 138 90;

    --tier-aprendiz-text: 144 149 157;
    --tier-guerreiro-text: 183 138 110;
    --tier-cavaleiro-text: 176 176 176;
    --tier-guardiao-text: 201 169 106;
    --tier-vanguarda-text: 59 167 200;
    --tier-mitico-text: 79 224 166;
    --tier-ascendente-text: 169 122 255;
    --tier-lendario-text: 255 92 92;

    /* Papel SUPERFICIE (§I13) — 1.4.11, 3:1 contra a TRILHA adjacente (bg-bg-900/60),
       nao 4.5:1 contra o fundo. Criterio diferente do -text, logo valor diferente:
       escurecer para o texto passar APROXIMA a barra da trilha. Nao unifique os dois. */
    --tier-aprendiz-surface: 138 143 152;
    --tier-guerreiro-surface: 181 135 106;
    --tier-cavaleiro-surface: 176 176 176;
    --tier-guardiao-surface: 201 169 106;
    --tier-vanguarda-surface: 59 167 200;
    --tier-mitico-surface: 79 224 166;
    --tier-ascendente-surface: 169 122 255;
    --tier-lendario-surface: 255 92 92;

    /* apoio específico do dark */
    --accent: #6f9dff;
    --accent-hover: #8db3ff;
    --accent-soft: #16203a;
    --gold-soft: #1d1a12;
    --purple: #b794f6;
    --purple-soft: #1e1730;
    --ok-bg: #10251a;
    --ok-border: #1f5137;
    --danger-bg: #2a1216;
    --danger-border: #5d2530;
    --warn-bg: #2a2010;
    --warn-border: #5c4718;
    --info: #6f9dff;
    --info-bg: #16203a;
    --info-border: #294067;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-md: 0 6px 20px rgba(0, 0, 0, 0.45);
    --shadow-lg: 0 18px 40px rgba(0, 0, 0, 0.55);
    --shadow-glow: 0 0 0 4px rgba(111, 157, 255, 0.22);
    --shadow-gold: 0 0 0 4px rgba(201, 169, 106, 0.26);
}


* { margin: 0; padding: 0; box-sizing: border-box; }

html, body { min-height: 100%; }


/* ---------------------------------------------------------------------------
   Badges de tier (§I4) — regras consumidas por lendas.php e ui_public.php.
   O PHP emite APENAS a classe `lenda-tier--<slug>`; zero `style` inline, zero hex no PHP.
   As opacidades .13 e .33 são as de hoje (os sufixos `22` e `55` do hex antigo).
   Por que os tokens mudam por tema: o fundo do chip é 13% da PRÓPRIA cor, então ele
   acompanha o tema em vez de contrastar com ele — nenhum hex único serve aos dois
   (prova em docs/dark-audit.md). Tokenizar é o que resolve, não escolher cor melhor.
   --------------------------------------------------------------------------- */
/* Geometria base do chip. Estes valores sao os que ja estavam no ar — esta rodada mexe em
   COR, nao em forma, entao nao ha motivo para o badge mudar de tamanho.
   Havia um segundo `.lenda-tier` mais abaixo no arquivo com estes mesmos valores; como tinham a
   mesma especificidade, o de baixo vencia e metade do bloco de cima nunca aplicava. Unificado
   aqui, ao lado das regras .lenda-tier--<slug> que pintam cada tier. Nao duplicar de novo. */
.lenda-tier {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: 0.02em;
}
.lenda-tier--aprendiz { background: rgb(var(--tier-aprendiz-text) / .13); color: rgb(var(--tier-aprendiz-text)); border: 1px solid rgb(var(--tier-aprendiz-text) / .33); }
.lenda-tier--guerreiro { background: rgb(var(--tier-guerreiro-text) / .13); color: rgb(var(--tier-guerreiro-text)); border: 1px solid rgb(var(--tier-guerreiro-text) / .33); }
.lenda-tier--cavaleiro { background: rgb(var(--tier-cavaleiro-text) / .13); color: rgb(var(--tier-cavaleiro-text)); border: 1px solid rgb(var(--tier-cavaleiro-text) / .33); }
.lenda-tier--guardiao { background: rgb(var(--tier-guardiao-text) / .13); color: rgb(var(--tier-guardiao-text)); border: 1px solid rgb(var(--tier-guardiao-text) / .33); }
.lenda-tier--vanguarda { background: rgb(var(--tier-vanguarda-text) / .13); color: rgb(var(--tier-vanguarda-text)); border: 1px solid rgb(var(--tier-vanguarda-text) / .33); }
.lenda-tier--mitico { background: rgb(var(--tier-mitico-text) / .13); color: rgb(var(--tier-mitico-text)); border: 1px solid rgb(var(--tier-mitico-text) / .33); }
.lenda-tier--ascendente { background: rgb(var(--tier-ascendente-text) / .13); color: rgb(var(--tier-ascendente-text)); border: 1px solid rgb(var(--tier-ascendente-text) / .33); }
.lenda-tier--lendario { background: rgb(var(--tier-lendario-text) / .13); color: rgb(var(--tier-lendario-text)); border: 1px solid rgb(var(--tier-lendario-text) / .33); }

body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    background: var(--bg);
    color: var(--text);
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

/* Sticky footer no admin */
body.is-admin {
    background: var(--bg-soft);
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}
body.is-admin .wrap { flex: 1; }

::selection { background: var(--gold-light); color: #0a1128; }

a { color: inherit; }

.topbar {
    position: sticky;
    top: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.85rem 1.5rem;
    border-bottom: 1px solid var(--border);
    background: linear-gradient(180deg, rgb(var(--c-topbar-de)) 0%, rgb(var(--c-topbar-ate)) 100%);
    color: rgb(var(--c-on-topbar));
    box-shadow: 0 4px 24px rgba(10, 17, 40, 0.4);
}

.is-admin .topbar {
    background: linear-gradient(180deg, #0a1128 0%, #10193d 100%);
    /* A barra do admin e cravada ESCURA aqui, independente do tema. Mas os tokens de texto
       SOBRE ela (`--c-on-topbar`, `--c-perigo-on-topbar`) seguem o tema — e o admin roda com
       o :root (claro), cujo on-topbar e 10 17 40 (escuro): ficava texto escuro sobre o navy,
       ilegivel. Antes so o fundo estava sobrescrito; o texto faltava. Forco os valores do tema
       ESCURO, que sao os certos para uma barra escura e ja tem contraste validado. */
    --c-on-topbar: 238 241 251;
    --c-perigo-on-topbar: 255 177 187;
}
.is-admin .topbar .brand { color: #eef1fb; }
.is-admin .topbar .brand em { color: var(--gold-light); border-left-color: rgba(255,255,255,0.15); }
.is-admin .topbar .brand img {
    border-color: rgba(200, 163, 92, 0.5);
    box-shadow: 0 0 0 2px rgba(200, 163, 92, 0.2);
}

.brand {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    color: var(--text);
    text-decoration: none;
    font-weight: 700;
    font-size: 0.95rem;
    letter-spacing: -0.01em;
}

.brand img {
    border-radius: 8px;
    width: 30px;
    height: 30px;
    border: 1px solid var(--border);
    object-fit: cover;
}

.brand em {
    font-style: normal;
    font-weight: 500;
    color: var(--text-muted);
    font-size: 0.85rem;
    padding-left: 0.4rem;
    border-left: 1px solid var(--border);
    margin-left: 0.15rem;
}

.topnav {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 0.35rem;
}

/* N4 da auditoria: em >=1024px os itens da nav mediam 29-31px de altura. Piso de 40px para
   alvo de toque, sem alterar o espacamento horizontal nem a densidade da barra.
   Em <=820px os itens ja ficam em 46px (menu aberto), entao a regra nao muda nada la. */
.topnav a,
.topnav button {
    min-height: 40px;
}

.topnav a {
    color: rgb(var(--c-on-topbar) / 0.72);
    text-decoration: none;
    font-size: 0.88rem;
    font-weight: 600;
    padding: 0.5rem 0.85rem;
    border-radius: 8px;
    transition: color 0.15s, background 0.15s, box-shadow 0.15s;
    white-space: nowrap;
    position: relative;
}

.topnav a:hover { color: rgb(var(--c-on-topbar)); background: rgb(var(--c-on-topbar) / 0.08); }
.topnav a.is-active {
    color: var(--gold-light);
    background: rgba(200, 163, 92, 0.14);
    box-shadow: inset 0 -2px 0 var(--gold-light);
}
.topnav-sep { flex: 1; }
.topnav-logout {
    color: rgb(var(--c-perigo-on-topbar)) !important;
    border: 1px solid rgb(var(--c-perigo-on-topbar) / 0.35);
}
.topnav-logout:hover { background: rgb(var(--c-perigo-on-topbar) / 0.14) !important; color: rgb(var(--c-perigo-on-topbar)) !important; }

/* Ícones inline no topnav (visitante) */
.topnav a [data-lucide] {
    width: 15px;
    height: 15px;
    vertical-align: -3px;
    margin-right: 4px;
    opacity: 0.85;
}
.topnav a.is-active [data-lucide],
.topnav a:hover [data-lucide] { opacity: 1; }

/* Live pill (dot vermelho pulsando) */
.topnav .topnav-live { display: inline-flex; align-items: center; gap: 6px; }
.topnav .live-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: #ff4b5c;
    box-shadow: 0 0 0 0 rgba(255,75,92,0.6);
    animation: livePulse 1.6s ease-out infinite;
    display: inline-block;
}
@keyframes livePulse {
    0%   { box-shadow: 0 0 0 0 rgba(255,75,92,0.55); }
    70%  { box-shadow: 0 0 0 6px rgba(255,75,92,0); }
    100% { box-shadow: 0 0 0 0 rgba(255,75,92,0); }
}

/* CTA "Inscrever-se" dourado.

   ⚠️ REGRESSAO DA B2, ACHADA NA MEDICAO DA v17 e consertada aqui: as regras estavam escritas
   como `.topnav .topnav-cta`, mas a B2 tirou o CTA de dentro do `<nav class="topnav">` e o pos
   em `.topnav-acoes`, que e IRMA da nav. Nenhum seletor casava mais: computado ao vivo, o CTA
   vinha `background-image: none`, `padding: 0px`, `font-weight: 400`, `display: block`, 24px de
   altura — ou seja, o botao dourado que a propria B2 existe para manter sempre a vista (achado
   N2) era, ha versoes, um link de texto pelado. Nao aparece em nenhum grep de CSS: a regra
   existe, so nao ALCANCA. Mesma familia do §V17.0 — o instrumento mediu a fonte, nao a resposta.

   O `.topnav a` tambem nao alcanca a area de acoes, entao caixa, tipografia e alvo de toque
   (piso de 40px, N4) vem escritos por inteiro aqui em vez de herdados. */
.topnav-acoes .topnav-cta {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding: 0.5rem 0.85rem;
    border-radius: 8px;
    font-size: 0.88rem;
    font-weight: 800;
    text-decoration: none;
    white-space: nowrap;
    background: linear-gradient(180deg, var(--gold-light), var(--gold));
    color: var(--on-gold) !important;
    box-shadow: 0 2px 10px -2px rgba(200,163,92,0.55);
    transition: background 0.15s, box-shadow 0.15s;
}
.topnav-acoes .topnav-cta:hover {
    background: linear-gradient(180deg, #f0d99a, var(--gold-light));
    box-shadow: 0 4px 14px -2px rgba(200,163,92,0.7);
}
.topnav-acoes .topnav-cta [data-lucide] {
    width: 15px;
    height: 15px;
    margin-right: 4px;
    opacity: 1;
}

/* Mesma causa, mesmo conserto: a busca ficava em 28.6px de altura porque o piso de 40px do N4
   mora em `.topnav a, .topnav button` e nao chega ate aqui. Nao muda largura nenhuma. */
.topnav-acoes .topnav-search { min-height: 40px; }

/* §V17.1 — porta de entrada do admin, na AREA DE ACOES.
   Sucede o antigo `.topnav-admin`, que so aparecia para quem JA estava logado e ainda por cima
   dentro do painel "Mais": quem precisava entrar tinha de saber a URL de cor. Agora o link
   existe nos dois estados (Login / Admin) e mora ao lado do CTA.

   ⚠️ O seletor NAO pode ser `.topnav .topnav-login`: `.topnav-acoes` e IRMA da nav, nao filha
   dela, entao nada de `.topnav a` alcanca o que mora aqui — foi o que matou a regra antiga
   quando a B2 tirou o CTA e as acoes de dentro do `<nav>`. Por isso a caixa e a tipografia
   vem escritas por inteiro, e nao herdadas.

   DISCRETO de proposito: e caminho de OPERADOR. Competir com o CTA dourado trocaria a acao que
   a pagina publica existe para provocar. Mesma opacidade dos itens da nav (0.72), so menor —
   o contraste ja validado do `--c-on-topbar` continua valendo nos dois temas. */
.topnav-acoes .topnav-login {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 40px;
    padding: 0.4rem 0.6rem;
    border-radius: 8px;
    border: 1px solid rgb(var(--c-on-topbar) / 0.18);
    background: transparent;
    color: rgb(var(--c-on-topbar) / 0.72);
    font-size: 0.78rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.topnav-acoes .topnav-login:hover {
    color: rgb(var(--c-on-topbar));
    border-color: var(--gold);
    background: rgb(var(--c-on-topbar) / 0.08);
}
.topnav-acoes .topnav-login [data-lucide] { width: 14px; height: 14px; opacity: 0.85; }
.is-admin .admin-nav-burger span { background: rgb(var(--c-on-topbar)); }
.is-admin .admin-nav-burger:hover { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.15); }

/* Burger mobile (admin) */
.admin-nav-burger {
    display: none;
    cursor: pointer;
    padding: 0.5rem;
    border-radius: 8px;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    gap: 4px;
    width: 40px;
    height: 40px;
    margin-left: auto;
    background: transparent;
    border: 1px solid transparent;
    transition: border-color 0.15s, background 0.15s;
}
.admin-nav-burger:hover { background: var(--bg-muted); border-color: var(--border); }
.admin-nav-burger span {
    display: block;
    width: 20px;
    height: 2px;
    background: var(--text);
    border-radius: 2px;
    transition: transform 0.2s, opacity 0.2s;
}
.admin-nav-burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.admin-nav-burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.admin-nav-burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* ===========================================================================
   NAV REORGANIZADA (item B2)
   Antes: 14-15 itens de mesmo peso numa faixa unica. Em 1024px quebrava em duas linhas;
   em <=820px TUDO (inclusive CTA e busca) ficava atras do burger — ver docs/nav-audit.md N2/N3.
   Agora: primarios sempre visiveis + acoes (busca, CTA) sempre visiveis + secundarios no "Mais".

   DEGRADACAO GRACIOSA (§0.2.1, requisito): o painel so e ESCONDIDO quando existe `.js-ok`
   no <html>, classe que o app.js poe. Sem JS nada esconde e todos os links continuam
   alcancaveis — a falha degrada para "menu aberto demais", nunca para "link inacessivel".
   =========================================================================== */

.topnav-acoes {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-left: auto;
}

/* Botao "Mais" — mesma linguagem visual dos itens da nav */
.topnav-mais {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 40px;
    padding: 0.5rem 0.8rem;
    border-radius: 8px;
    border: 1px solid transparent;
    background: transparent;
    /* mesma cor dos demais itens da barra escura — `--text-muted` e do tema claro e ficava
       ilegivel sobre a topbar (contraste ~2:1). */
    color: rgb(var(--c-on-topbar) / 0.72);
    font-family: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.topnav-mais:hover { color: rgb(var(--c-on-topbar)); background: rgb(var(--c-on-topbar) / 0.08); }
.topnav-mais.is-active { color: var(--gold-light); }
.topnav-mais[aria-expanded="true"] {
    background: rgb(var(--c-on-topbar) / 0.10);
    color: rgb(var(--c-on-topbar));
}

/* Busca ⌘K sem JS: o overlay de busca e 100% JS, entao sem JS o botao nao faz NADA — e ainda
   aparecia como um retangulo vazio, porque o icone do Lucide tambem e desenhado por script
   (achado do Argus na revisao, testando com `script-src none` de verdade).
   Controle morto e pior que controle ausente: escondemos o botao quando o JS nao esta vivo.
   Isto NAO conflita com a degradacao graciosa do §0.2.1 — aquela regra protege LINKS de navegacao,
   e nenhum link some: sem JS o painel inteiro fica visivel. Busca e recurso opcional, nao rota. */
html:not(.js-ok) .topnav-search { display: none; }

/* Toggle de tema (§I3): sem JS ele nao alterna nada — e controle morto e pior que ausente
   (EMENDA 11). Mesmo raciocinio da busca e do botao "Mais". */
html:not(.js-ok) .topnav-tema { display: none; }

.topnav-tema {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 40px;
    padding: 0.4rem 0.6rem;
    border-radius: 8px;
    border: 1px solid var(--border);
    background: transparent;
    color: rgb(var(--c-on-topbar) / 0.72);
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.topnav-tema:hover { color: rgb(var(--c-on-topbar)); border-color: var(--gold); }
.topnav-tema-ico { font-size: 0.95rem; line-height: 1; }

/* Mesmo raciocinio para o botao "Mais": sem JS ele nao alterna nada E o painel ja esta visivel,
   entao ele seria um controle morto ao lado da lista que ele deveria revelar. */
html:not(.js-ok) .topnav-mais { display: none; }

/* Painel dos secundarios (nav publica). Escondido SO quando o JS esta vivo.
   `.topnav-colapsavel` (nav do admin) NAO entra aqui de proposito: ela e uma barra normal no
   desktop e so colapsa em <=820px. Reusar a mesma classe fazia a nav do admin sumir por
   completo em 1024px — o burger fica display:none e nao existe botao "Mais" no ramo do admin. */
.js-ok .topnav-secundaria {
    display: none;
}
.js-ok .topnav-secundaria.is-aberto {
    display: flex;
}

/* Desktop: o painel vira dropdown ancorado a direita */
@media (min-width: 821px) {
    .topnav-secundaria {
        position: absolute;
        top: calc(100% - 0.35rem);
        right: 0.9rem;
        z-index: 60;
        flex-direction: column;
        align-items: stretch;
        min-width: 220px;
        padding: 0.4rem;
        border-radius: 12px;
        border: 1px solid var(--border);
        background: var(--bg-card);
        box-shadow: 0 18px 40px -12px rgba(10, 17, 40, 0.35);
    }
    .topnav-secundaria a {
        border-radius: 8px;
        color: var(--text) !important;
    }
    .topnav-secundaria a:hover { background: var(--bg-muted); }
    .topnav-secundaria a.is-active { background: var(--accent-soft); color: var(--accent) !important; }
    /* sem JS o dropdown nao pode ficar flutuando sobre o conteudo: vira faixa estatica */
    html:not(.js-ok) .topnav-secundaria {
        position: static;
        flex-direction: row;
        flex-wrap: wrap;
        min-width: 0;
        box-shadow: none;
        border: 0;
        background: transparent;
        padding: 0;
    }
    /* No fallback sem JS os secundarios voltam para a BARRA, entao precisam da cor da barra — nao
       a do dropdown. Por isso --c-on-topbar e nao --text: a barra e superficie propria e inverte
       junto com o tema. Cravar a cor clara aqui deixaria o link invisivel no tema claro. */
    html:not(.js-ok) .topnav-secundaria a { color: rgb(var(--c-on-topbar) / 0.72) !important; }
    html:not(.js-ok) .topnav-secundaria a:hover { color: rgb(var(--c-on-topbar)) !important; }
}


/* ===========================================================================
   COMPACTACAO DA BARRA — teto 1023px (v17, MEDIDO)

   Separado do bloco <=820px de proposito. Ate a v16 as duas coisas moravam juntas, e o teto
   delas era o mesmo 820 do COLAPSO (burger + painel full-width). Mas sao perguntas diferentes:
   "a barra ainda cabe?" nao e "o painel ainda e dropdown?". Medido, a barra em tamanho cheio
   (marca + Camp/Ranking/Live + as 5 acoes) exige 979.19px — ou seja, ela JA quebrava em duas
   linhas de 821px ate ~979px ANTES da v17 (baseline v16 medido: 836.73px exigidos em 821px de
   tela, `.topnav-primaria` em 2 linhas). O buraco existia desde a B2 e ninguem tinha medido a
   faixa; a v17 o alargaria ate ~980px, porque o link de login e o CTA consertado somam largura.
   Elevar o teto para 1023 fecha os dois: o de hoje e o que eu traria.

   1024 e o ponto de virada: em 1024 a barra cheia sobra 44.81px (~4.5%). Abaixo disso ela usa
   este tratamento — que NAO e novo, e o mesmo que a B2 ja desenhou para a barra estreita.

   O teto vai em `em` (63.9375em = 1023px na fonte padrao) pelo MESMO motivo do limiar de
   93.75em mais abaixo — e aqui isso NAO e polimento: sem a conversao a v17 REGRIDE. Medido com
   a fonte padrao do Chrome em 24px, controle positivo em pagina nua antes de ler:
       v16 (reconstituida) em 1280px .... 1 linha, ok
       v17 com o teto em `px` em 1280px . 2 LINHAS   <- regressao que eu teria introduzido
       v17 com o teto em `em` em 1280px . 1 linha, ok
   Com o teto em px a compactacao DESLIGA em 1024px de tela enquanto o conteudo, todo em rem,
   ainda exige a barra compacta. Em `em` ela acompanha a fonte do leitor.

   RESIDUO DECLARADO, e nao e desta fatia: com fonte grande, 900px e 1024px ainda quebram. A v16
   quebrava nos MESMOS pontos e em 900px/24px quebrava PIOR (3 linhas contra 2). Fechar isso
   exigiria mover tambem o teto do COLAPSO (`max-width: 820px`, bloco da B2) para `em`, o que
   muda quando o burger aparece para todo mundo — decisao de produto, nao unidade de CSS.

   A MARCA fica de fora: `.brand` continua encolhendo so em <=820px. O orcamento permite (sem
   mexer nela ainda sobram ~82px de folga em 821px) e a marca e identidade, nao densidade.
   O CTA e a busca continuam NA BARRA em qualquer largura — achado N2 da B2, intocado.
   =========================================================================== */
@media (max-width: 63.9375em) {
    .topnav-primaria { gap: 0.1rem; }
    .topnav-primaria a { padding: 0.5rem 0.55rem; font-size: 0.8rem; }
    .topnav-acoes { gap: 0.25rem; }
    .topnav-search kbd { display: none; }   /* nao existe atalho de teclado nessa faixa */
    .topnav-mais-txt { display: none; }     /* so o icone, para caber */
    .topnav-login-txt { display: none; }    /* idem: fica so o icone de entrar */
    .topnav-tema-txt { display: none; }     /* idem */
    .topnav-mais { padding: 0.5rem 0.6rem; }
}

/* ===========================================================================
   §V17.2 — PROMOVIDOS na barra: Times, Hall, Stats, Recordes, Seasons

   Os cinco existem DUAS vezes no HTML — uma copia em `.topnav-primaria`, outra em
   `.topnav-secundaria` — porque CSS nao move um elemento entre PAIS diferentes. Exatamente uma
   das copias esta `display:none` em qualquer largura, e `display:none` tira o duplicado tambem
   da arvore de acessibilidade: o leitor de tela nunca ouve o link duas vezes.

   O limiar abaixo NAO foi escolhido, foi MEDIDO em Chromium de verdade, em larguras exatas, com
   os ROTULOS REAIS, nos DOIS temas e nos DOIS estados do link de login:

     conteudo exigido, PIOR caso ........ 1481.04px  (tema CLARO — ali o proprio botao de tema
                                          diz "Escuro", 8.17px mais largo que o "Claro" do tema
                                          escuro — e link ja logado, "Admin", +5.45px sobre
                                          "Login"). Cabe em UMA linha ate 1481px; quebra em 1480.
     caso mais ESTREITO ................. 1467.41px  (tema escuro + "Login")
     LIMIAR ............................. 1500px
     MARGEM ............................. 18.96px (~1.28%)

   A margem e maior que os 13.62px que separam o estado mais estreito do mais largo da MESMA
   barra: uma folga menor que a variacao entre dois estados normais nao e folga. Cortar no
   encaixe exato (1481) daria uma barra que so sobrevive por arredondamento de subpixel — que e
   literalmente o defeito 1479->1499 da v7.x. Conta completa em docs/nav-v17.md.

   CONSEQUENCIA DECLARADA: viewports de 1440 e abaixo ficam com o burger. Nao e escolha do
   limiar, e aritmetica — 1481px de conteudo nao entram em 1440px de tela. Encurtar rotulo e
   decisao de produto, nao de CSS.

   🔴 POR QUE `em` E NAO `px` (achado W-1 do Argus, e ele expos um buraco na minha medicao).
   A barra inteira e dimensionada em `rem` (fonte 0.88rem, padding 0.5rem/0.85rem, gap 1rem) e
   nao ha `font-size` fixo no `html`/`body` — ou seja, ela ESCALA com a fonte padrao do
   navegador. Um limiar em `px` NAO escala. Medido pelo Argus: com a fonte padrao do Chrome em
   24px, `min-width: 1500px` casava TRUE em 1600px de tela enquanto o conteudo em rem ja nao
   cabia — a barra quebrava em duas linhas ACIMA do limiar, exatamente onde eu declarei que nao
   quebrava.

   A minha margem de 18,96px nunca protegeu contra isto: ela cobre o ESTADO da barra (tema,
   rotulo de login), que e variacao de CONTEUDO. Escala de texto e outro EIXO, e eu media so um.

   `93.75em` = 1500px na fonte padrao de 16px, entao o NUMERO MEDIDO NAO MUDA para quem usa o
   padrao — o limiar so passa a acompanhar quem le com fonte maior, que e o unico jeito de a
   promessa "cabe sem quebrar" seguir verdadeira para essa pessoa.

   E o par e `(min-width)` + `not all and (min-width)` DE PROPOSITO, nao `max-width: 93.74em`:
   assim eles sao complementares por construcao, sem faixa morta. Um par `1499px`/`1500px` deixa
   1499,5px sem dono — ali NENHUMA das duas regras casa, os dois `display:none` somem e o leitor
   ve os cinco promovidos DUPLICADOS. Nao e teorico em tela com devicePixelRatio fracionario.

   Abaixo do limiar nada muda em relacao a v16 — os cinco voltam para o painel "Mais", na ordem
   de sempre, e a faixa <=820px continua exatamente como a B2 a deixou.
   =========================================================================== */
@media not all and (min-width: 93.75em) {
    .topnav-primaria .topnav-prom { display: none; }
}
@media (min-width: 93.75em) {
    .topnav-secundaria .topnav-prom-alt { display: none; }
}

/* O "Mais" so reivindica a pagina atual quando ela esta MESMO escondida ali dentro.
   `is-active` (secundario de verdade: Feed/Rival/Perfil/Status) acende sempre; `is-ativo-prom`
   acende so abaixo do limiar, porque acima dele o promovido ativo esta a vista na barra e ja
   acendeu la — realcar os dois diria que o item visivel esta guardado no painel. */
@media not all and (min-width: 93.75em) {
    .topnav-mais.is-ativo-prom { color: var(--gold-light); }
}


.wrap {
    width: 100%;
    max-width: 1040px;
    margin: 0 auto;
    padding: 2rem 1.5rem 3.5rem;
}

/* O ADMIN respira no desktop; o PUBLICO nao muda.
   Medido em admin/index.php?camp=8 com o seed largo: a tabela de inscritos precisa de 1175px, mas o
   .wrap travava em 1040 e o container mostrava 734 — 441px de rolagem INTERNA em qualquer monitor,
   com 880px sobrando nas laterais em 1920. O <body> nunca estourava (por isso a auditoria de
   transbordo dava 0 e o usuario arrastava mesmo assim: sao as duas coisas ao mesmo tempo).
   1600px foi escolhido por medicao, nao por gosto: full-bleed daria o MESMO resultado de rolagem em
   1280/1440/1920 e esticaria o layout de borda a borda sem ganho. Escopado em .is-admin — o
   comprimento de linha do site publico continua o de leitura. */
.is-admin .wrap { max-width: 1600px; }

.site-footer {
    text-align: center;
    padding: 1.25rem;
    color: var(--text-subtle);
    font-size: 0.8rem;
    border-top: 1px solid var(--border);
    background: #fff;
}
body.is-admin .site-footer { background: #fff; }

h1 {
    font-size: clamp(1.55rem, 3vw, 1.9rem);
    font-weight: 700;
    letter-spacing: -0.025em;
    margin-bottom: 0.35rem;
    color: var(--text);
}

h2 {
    font-size: 1.05rem;
    font-weight: 700;
    margin-bottom: 0.85rem;
    letter-spacing: -0.01em;
    color: var(--text);
    display: flex;
    align-items: center;
    gap: 0.55rem;
    flex-wrap: wrap;
    padding-left: 0.75rem;
    border-left: 3px solid var(--accent);
}

h3 { font-size: 0.95rem; font-weight: 650; }

.lead {
    color: var(--text-muted);
    margin-bottom: 1.25rem;
    max-width: 60ch;
    font-size: 0.95rem;
}

.hero {
    padding: 0.5rem 0 1.5rem;
    border-bottom: 1px solid var(--border);
    margin-bottom: 1.75rem;
}

.hero .lead { margin-bottom: 1.25rem; }

.page-header {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.15rem 1.25rem 1rem;
    margin-bottom: 1.25rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: linear-gradient(135deg, #ffffff 0%, #f8faff 100%);
    box-shadow: var(--shadow-sm);
    flex-wrap: wrap;
    position: relative;
    overflow: hidden;
}
.page-header::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 4px;
    background: linear-gradient(180deg, var(--gold) 0%, var(--accent) 100%);
}

.page-header h1 { margin-bottom: 0.2rem; }

.page-header-actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 0.75rem;
    margin: 1.25rem 0 1.5rem;
}

.stat {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 0.95rem 1.05rem;
    transition: border-color 0.15s, transform 0.15s;
}

.stat:hover {
    border-color: var(--border-strong);
    transform: translateY(-1px);
}

.stat strong {
    display: block;
    font-size: 1.35rem;
    font-weight: 700;
    letter-spacing: -0.025em;
    color: var(--text);
    line-height: 1.1;
    margin-bottom: 0.25rem;
}

.stat span {
    font-size: 0.75rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
}

.card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 1.25rem 1.4rem;
    margin-bottom: 1rem;
    box-shadow: var(--shadow-sm);
    transition: box-shadow 0.15s, border-color 0.15s, transform 0.15s;
}

.card:hover { box-shadow: var(--shadow-md); }

.card-accent { border-left: 3px solid var(--accent); }
.card-gold   { border-left: 3px solid var(--gold); }
.card-danger { border-left: 3px solid var(--danger); }
.card-ok     { border-left: 3px solid var(--ok); }

.card-solid {
    background: var(--bg-soft);
    box-shadow: none;
}

.grid-2 {
    display: grid;
    grid-template-columns: 1.15fr 1fr;
    gap: 1rem;
    align-items: start;
}

@media (max-width: 820px) {
    /* `1fr` carrega `minmax(auto, 1fr)`, e esse `auto` NAO encolhe abaixo do min-content do
       conteudo — entao a faixa fica mais larga que o proprio container e empurra o documento.
       Medido em 360px no admin/stats.php: faixa 371.7px dentro de um container de 331px.
       `minmax(0, 1fr)` deixa a faixa encolher. Mesmo padrao do grid do perfil (v3 §10.1). */
    .grid-2 { grid-template-columns: minmax(0, 1fr); }
    .topbar { padding: 0.7rem 0.9rem; flex-wrap: wrap; }
    .wrap { padding: 1.25rem 0.9rem 2rem; }
    .brand span em { display: none; }
    .brand span { font-size: 0.9rem; }
    .admin-nav-burger { display: inline-flex; }

    /* A nav do admin colapsa APENAS aqui (<=820px); no desktop ela e barra normal. */
    .js-ok .topnav-colapsavel { display: none; }
    .js-ok .topnav-colapsavel.is-aberto { display: flex; }

    /* Painel dos secundarios: faixa full-width abaixo da barra.
       N1: a regra base tem `flex-wrap: wrap`; em coluna com altura limitada isso quebrava os
       itens em COLUNAS NOVAS sobrepostas, em vez de empilhar. Ver docs/nav-audit.md N1. */
    .topnav-secundaria,
    .topnav-colapsavel {
        order: 99;
        flex-basis: 100%;
        flex-direction: column;
        flex-wrap: nowrap;
        align-items: stretch;
        gap: 0;
        margin-top: 0.7rem;
        padding-top: 0.35rem;
        border-top: 1px solid var(--border);
        /* N1b: teto fixo de 500px cortava a lista sem aviso; agora acompanha a tela e rola. */
        max-height: calc(100vh - 4.5rem);
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
    .topnav-secundaria a,
    .topnav-colapsavel a {
        padding: 0.75rem 0.85rem;
        border-radius: 0;
        border-bottom: 1px solid var(--border);
    }
    .topnav-sep { display: none; }
    .page-header { padding-bottom: 0.75rem; margin-bottom: 1rem; }
    .admin-tabs { width: 100%; overflow-x: auto; flex-wrap: nowrap; scrollbar-width: thin; }
    .admin-tab { flex-shrink: 0; }
    .camp-grid { grid-template-columns: 1fr; gap: 0.7rem; }
}

@media (max-width: 480px) {
    h1 { font-size: 1.3rem; }
    .card { padding: 1rem; border-radius: 12px; }
    .btn { padding: 0.55rem 0.85rem; font-size: 0.85rem; }
    .actions { gap: 0.4rem; }
    .stats { gap: 0.5rem; }
    .stat { padding: 0.75rem 0.85rem; }
    .stat strong { font-size: 1.2rem; }
    .lendas-dist-row { grid-template-columns: 90px 1fr 35px; }
    .lendas-dist-min { display: none; }
    .rank-row { grid-template-columns: 70px 1fr 34px; font-size: 0.82rem; }
}

/* Scrollbar-none util pra nav horizontal quando precisar */
.scrollbar-none::-webkit-scrollbar { display: none; }
.scrollbar-none { -ms-overflow-style: none; scrollbar-width: none; }

/* Details/summary menu — remove default arrow */
details > summary { list-style: none; }
details > summary::-webkit-details-marker { display: none; }
details > summary::marker { content: ''; }

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 0.65rem 1rem;
    border-radius: 10px;
    border: 1px solid transparent;
    font-weight: 600;
    font-size: 0.88rem;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;
    font-family: inherit;
    line-height: 1.2;
    white-space: nowrap;
}

.btn:active { transform: translateY(1px); }

.btn-primary {
    background: linear-gradient(180deg, var(--accent) 0%, var(--accent-hover) 100%);
    color: #fff;
    box-shadow: 0 3px 10px rgba(26, 75, 214, 0.28), inset 0 1px 0 rgba(255,255,255,0.15);
}
.btn-primary:hover {
    box-shadow: 0 6px 18px rgba(26, 75, 214, 0.4), inset 0 1px 0 rgba(255,255,255,0.2);
    transform: translateY(-1px);
}

.btn-gold {
    background: linear-gradient(180deg, var(--gold-light) 0%, var(--gold) 100%);
    /* Era `#0a1128` fixo. No light o dourado precisa ser ESCURO para servir de texto
       (5.55:1), e aí texto escuro sobre ele cai para 3.12:1. O token inverte por tema:
       escuro sobre dourado claro (dark, 8.34:1) · branco sobre dourado escuro (light, 6.00:1). */
    color: var(--on-gold);
    box-shadow: 0 3px 10px rgba(200, 163, 92, 0.35), inset 0 1px 0 rgba(255,255,255,0.4);
    font-weight: 700;
}
.btn-gold:hover { box-shadow: 0 6px 18px rgba(200, 163, 92, 0.5); transform: translateY(-1px); }

.btn-ghost {
    background: #fff;
    border-color: var(--border);
    color: var(--text);
}
.btn-ghost:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }

/* `.btn-ghost` cravava `background: #fff`. Com `--text` claro no dark, virava texto quase branco
   sobre branco: 1.19:1, o pior contraste do site inteiro (era o "Consultar inscrição" da home).
   No dark ele passa a ser contorno sobre o fundo do cartão. */
html.dark .btn-ghost {
    background: var(--bg-card);
    border-color: var(--border-strong);
    color: var(--text);
}
html.dark .btn-ghost:hover {
    background: var(--bg-muted);
    border-color: var(--gold);
    color: var(--gold-light);
}

/* ---------------------------------------------------------------------------
   CTAs de página (item B4).
   Os CTAs de campeonato/index.php e obrigado.php usavam SÓ classes da paleta Tailwind
   customizada (bg-gold, text-bg-900, shadow-glow, border-border-strong...), que está
   DESLIGADA (§0.4) — 0 ocorrências no CSS gerado. Renderizavam como texto com padding,
   sem fundo e sem borda. Não é refinamento estético: eles não tinham estilo nenhum.

   Reuso o sistema `.btn` que já existe aqui em vez de criar um paralelo. `.btn-cta` é só
   o modificador de TAMANHO/ênfase, para garantir alvo de toque >= 44px (o `.btn` base dá
   ~38px) sem mexer nos botões do admin, que continuam como estavam.
   Hierarquia: `.btn-gold` = ação primária (preenchida) · `.btn-ghost` = secundária (contorno).
   --------------------------------------------------------------------------- */
.btn-cta {
    min-height: 44px;
    padding: 0.75rem 1.25rem;
    font-size: 0.95rem;
    font-weight: 700;
}

/* Foco visível por teclado em TODO botão do sistema — não existia, e o §B4 exige.
   `:focus-visible` não dispara em clique de mouse, então não polui o uso com ponteiro. */
.btn:focus-visible,
.topnav a:focus-visible,
.topnav button:focus-visible,
.admin-nav-burger:focus-within {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
    border-radius: 10px;
}

/* Aviso de validacao Riot pendente (B5 / EMENDA 3), em obrigado.php.
   AVISO, nao erro: a inscricao deu certo — so a validacao do perfil na Riot ficou pendente.
   Por isso usa a paleta `warn` (ambar), nunca a de `danger`. Paleta desligada (§0.4), entao
   as cores vem das variaveis do proprio campeonato.css. */
.alerta-riot-pendente {
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    margin: 0 auto 1rem;
    padding: 0.9rem 1.1rem;
    border-radius: 12px;
    border: 1px solid var(--warn-border, #f0d9a0);
    background: var(--warn-bg, #fdf6e3);
    color: var(--warn, #8a6300);
    font-size: 0.9rem;
    line-height: 1.5;
}
.alerta-riot-pendente p { margin: 0; }
.alerta-riot-pendente span { font-size: 1.1rem; line-height: 1.3; }

/* Em telas estreitas os dois CTAs ocupam a linha inteira e param de brigar por espaço. */
@media (max-width: 480px) {
    .btn-cta { width: 100%; }
}

.btn-ok       { background: var(--ok-bg);     border-color: var(--ok-border);     color: var(--ok); }
.btn-ok:hover { background: #dff4e6; }

.btn-danger       { background: var(--danger-bg);   border-color: var(--danger-border); color: var(--danger); }
.btn-danger:hover { background: #fbdee2; }

.btn-info       { background: var(--info-bg);     border-color: var(--info-border);   color: var(--info); }
.btn-info:hover { background: #e3e7ff; }

.btn-sm {
    padding: 0.4rem 0.7rem;
    font-size: 0.78rem;
    border-radius: 8px;
}

.btn:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

.actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; }

/* Formulários */
.form-group { margin-bottom: 1rem; }

.form-group label {
    display: block;
    font-size: 0.82rem;
    font-weight: 600;
    margin-bottom: 0.35rem;
    color: var(--text);
}

.form-group input,
.form-group select,
.form-group textarea {
    width: 100%;
    padding: 0.7rem 0.85rem;
    border-radius: 10px;
    border: 1px solid var(--border);
    background: #fff;
    color: var(--text);
    font: inherit;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: var(--shadow-glow);
}

.form-group input[type="checkbox"] {
    width: auto;
    margin-right: 0.35rem;
    accent-color: var(--accent);
}

.hint { font-size: 0.78rem; color: var(--text-muted); margin-top: 0.3rem; }

/* Alertas */
.alert {
    padding: 0.75rem 0.95rem;
    border-radius: 10px;
    margin-bottom: 1rem;
    font-size: 0.9rem;
    border: 1px solid;
    display: flex;
    gap: 0.5rem;
    align-items: flex-start;
}

.alert-error { background: var(--danger-bg); border-color: var(--danger-border); color: var(--danger); }
.alert-ok    { background: var(--ok-bg);     border-color: var(--ok-border);     color: var(--ok); }
.alert-warn  { background: var(--warn-bg);   border-color: var(--warn-border);   color: var(--warn); }

/* PIX */
.pix-box { text-align: center; }

.pix-box img {
    width: min(210px, 70vw);
    height: auto;
    border-radius: 10px;
    border: 1px solid var(--border);
    margin: 0.75rem auto;
    display: block;
    background: #fff;
    box-shadow: var(--shadow-sm);
}

.pix-key {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    background: var(--bg-soft);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 0.75rem;
    word-break: break-all;
    margin: 0.75rem 0;
    font-size: 0.9rem;
}

/* Badges */
.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.55rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 650;
    letter-spacing: 0.02em;
    border: 1px solid transparent;
}

.badge::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    opacity: 0.7;
}

.badge-aguardando_pix { background: var(--warn-bg);   color: var(--warn);   border-color: var(--warn-border); }
.badge-pago           { background: var(--ok-bg);     color: var(--ok);     border-color: var(--ok-border); box-shadow: 0 0 0 3px rgba(6, 137, 76, 0.08); }
.badge-rejeitado      { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-border); }
.badge-cancelado      { background: var(--bg-muted);  color: var(--text-muted); border-color: var(--border); }
.badge-gold           { background: linear-gradient(135deg, var(--gold-light), var(--gold)); color: #0a1128; border-color: var(--gold-dark); box-shadow: 0 0 0 3px rgba(200,163,92,0.18); font-weight: 700; }

/* Origem: inscrito criado pelo import completo de partida (v8).
   Le APENAS o prefixo `riot-import:` de `observacao_admin` — marcador de proveniencia gravado pelo
   servico do Rivet (interface congelada §V8.3). Nunca escreve.

   ⚠️ PROPRIEDADE DECLARADA, medida com o Rivet: `observacao_admin` e TEXTO LIVRE de admin
   (admin/confirmar.php:31,37), sem validacao nem prefixo reservado. Hoje ha 0 linhas com o prefixo
   fora do import, entao o badge nao mente — mas nada IMPEDE um admin de digitar 'riot-import: x' e
   ganhar o badge. Ele reflete uma CONVENCAO DE TEXTO, nao um fato estrutural. Para nao poder mentir
   seria preciso coluna ou flag, e isso e decisao de contrato, nao de render.

   Cor: azul do --c-evento-rodada, o unico token semantico livre (verde/amarelo/cinza/vermelho/ouro
   ja sao status de pagamento). Nome pelo PAPEL, nao pela cor (§I12.1). */
.badge-import {
    background: rgb(var(--c-evento-rodada) / 0.12);
    color: rgb(var(--c-evento-rodada));
    border: 1px solid rgb(var(--c-evento-rodada) / 0.30);
}

/* Tabelas */
.table-wrap { overflow-x: auto; margin: 0 -0.25rem; }

/* ==========================================================================
   EMENDA 7 — LINHA DE TABELA VIRA CARTAO NO CELULAR (<=768px)
   UM mecanismo para as N telas: a tabela ganha `.tbl-cartao` e cada <td> ganha
   `data-label="<cabecalho>"`. Nada de implementacao por pagina.

   POR QUE CARTAO E NAO ESCONDER COLUNA: a auditoria (docs/admin-audit.md) mediu
   `financeiro` estourando 308px com apenas 5 colunas — sao colunas LARGAS, nao
   muitas. Esconder metade de 5 deixa uma tabela que ja nao informa. O cartao
   REEMPILHA: nenhum dado sai da tela, so muda de arranjo. A queixa do usuario era
   "arrastar pra o lado", nao "informacao demais".

   RoTULO VISIVEL, nao so acessivel (§0.13): empilhar destroi o cabecalho de coluna,
   entao cada campo carrega o proprio rotulo em `::before`. `aria-label` sozinho seria
   invisivel para quem enxerga — e o dado ficaria sem identificacao na tela.
   Celula SEM `data-label` (coluna de acoes) nao ganha rotulo: `attr()` vazio nao pinta.
   ========================================================================== */
@media (max-width: 768px) {
    .tbl-cartao thead { display: none; }
    .tbl-cartao,
    .tbl-cartao tbody,
    .tbl-cartao tr,
    .tbl-cartao td { display: block; width: 100%; }

    .tbl-cartao tr {
        border: 1px solid var(--border);
        border-radius: 10px;
        background: var(--bg-card);
        padding: 0.5rem 0.7rem;
        margin-bottom: 0.6rem;
    }
    .tbl-cartao tr:last-child { margin-bottom: 0; }

    .tbl-cartao td {
        display: grid;
        grid-template-columns: minmax(0, 38%) minmax(0, 1fr);
        gap: 0.6rem;
        align-items: baseline;
        padding: 0.28rem 0;
        border: 0;
        /* `!important` porque varios <td> trazem `white-space:nowrap` INLINE, e inline
           vence folha. E justamente esse nowrap que engorda a coluna e produz o
           arrastar horizontal — no cartao ele tem de ceder. */
        white-space: normal !important;
        overflow-wrap: anywhere;
    }
    .tbl-cartao td::before {
        content: attr(data-label);
        font-weight: 700;
        font-size: 0.74rem;
        letter-spacing: 0.02em;
        text-transform: uppercase;
        color: var(--text-muted);
    }
    /* o wrapper existe para o modo tabela; em cartao nao ha o que rolar */
    .table-wrap:has(.tbl-cartao) { overflow-x: visible; margin: 0; }
}

table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.88rem;
}

th, td {
    text-align: left;
    padding: 0.85rem 0.6rem;
    border-bottom: 1px solid var(--border);
    vertical-align: middle;
}

thead th {
    color: var(--text-muted);
    font-weight: 600;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    background: var(--bg-soft);
    border-bottom: 1px solid var(--border);
    position: sticky;
    top: 0;
}

tbody tr {
    transition: background 0.12s;
}

tbody tr:hover {
    background: var(--accent-soft);
}

/* Filtros pill */
.filters {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    margin-bottom: 1rem;
}

.filters a {
    text-decoration: none;
    color: var(--text-muted);
    border: 1px solid var(--border);
    border-radius: 999px;
    padding: 0.32rem 0.75rem;
    font-size: 0.78rem;
    font-weight: 600;
    background: #fff;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
}

.filters a:hover {
    color: var(--text);
    border-color: var(--border-strong);
}

.filters a.active {
    color: #fff;
    background: linear-gradient(180deg, var(--accent) 0%, var(--accent-hover) 100%);
    border-color: var(--accent-hover);
    box-shadow: 0 3px 10px rgba(26, 75, 214, 0.3);
}

/* Camp layout — sidebar esquerda + conteúdo direita */
.camp-layout {
    display: grid;
    grid-template-columns: 240px 1fr;
    gap: 1.5rem;
    align-items: start;
    margin-top: 0.25rem;
}

.camp-side {
    position: sticky;
    top: 5rem;
    align-self: start;
    background: linear-gradient(180deg, #ffffff 0%, #f7f9fd 100%);
    border: 1px solid var(--border);
    border-radius: 16px;
    padding: 0.85rem 0.7rem 0.7rem;
    box-shadow: var(--shadow-sm);
    max-height: calc(100vh - 6rem);
    overflow-y: auto;
    scrollbar-width: thin;
}

.camp-side-head {
    padding: 0.4rem 0.6rem 0.85rem;
    border-bottom: 1px solid var(--border);
    margin-bottom: 0.6rem;
}
.camp-side-title {
    font-weight: 800;
    font-size: 0.95rem;
    color: var(--text);
    letter-spacing: -0.01em;
    line-height: 1.25;
    word-break: break-word;
}
.camp-side-meta {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.35rem;
    font-size: 0.72rem;
    color: var(--text-muted);
    font-weight: 600;
}
.camp-side-share {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.4rem;
    padding: 0.25rem 0.5rem;
    background: var(--gold-soft);
    border: 1px solid rgba(200, 163, 92, 0.35);
    border-radius: 6px;
    color: var(--gold-dark);
    font-size: 0.72rem;
    font-weight: 700;
    text-decoration: none;
    max-width: 100%;
    transition: background 0.15s;
}
.camp-side-share span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: ui-monospace, monospace;
    font-size: 0.68rem;
}
.camp-side-share:hover { background: #f5e7bf; }

.camp-side-section { padding: 0.4rem 0; }
.camp-side-label {
    padding: 0.4rem 0.75rem 0.5rem;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    font-weight: 800;
    color: var(--text-subtle);
}

.camp-side nav {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.side-tab {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    padding: 0.6rem 0.75rem;
    border-radius: 10px;
    color: var(--text-muted);
    text-decoration: none;
    font-size: 0.88rem;
    font-weight: 600;
    transition: color 0.15s, background 0.15s, transform 0.1s, box-shadow 0.15s;
    position: relative;
    border: 1px solid transparent;
}
.side-tab svg {
    flex-shrink: 0;
    opacity: 0.55;
    transition: opacity 0.15s, transform 0.15s;
}
.side-tab:hover {
    color: var(--accent);
    background: var(--accent-soft);
    border-color: rgba(26, 75, 214, 0.12);
}
.side-tab:hover svg { opacity: 1; transform: scale(1.1); }
.side-tab-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-tab-count {
    background: var(--bg-muted);
    color: var(--text-muted);
    font-size: 0.7rem;
    font-weight: 800;
    padding: 0.1rem 0.45rem;
    border-radius: 999px;
    min-width: 22px;
    text-align: center;
}
.side-tab:hover .side-tab-count {
    background: rgba(26, 75, 214, 0.15);
    color: var(--accent);
}

.side-tab.is-active {
    color: #0a1128;
    background: linear-gradient(135deg, var(--gold-light) 0%, var(--gold) 100%);
    border-color: var(--gold-dark);
    box-shadow: 0 4px 14px rgba(200, 163, 92, 0.35), inset 0 1px 0 rgba(255,255,255,0.45);
    text-shadow: 0 1px 0 rgba(255,255,255,0.35);
}
.side-tab.is-active svg { opacity: 1; }
.side-tab.is-active .side-tab-count {
    background: rgba(10, 17, 40, 0.15);
    color: #0a1128;
}

.camp-side-foot {
    margin-top: 0.5rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--border);
    display: flex;
    justify-content: center;
}
.camp-side-foot .btn { width: 100%; justify-content: center; }

.camp-main { min-width: 0; }

/* Colapsa a sidebar quando a tabela NAO cabe ao lado dela.
   O limiar e MEDIDO, nao estimado: a tabela de inscritos (seed largo) precisa de 1175px, e o
   container e o .wrap menos 306px de cromo (padding + barra de 240 + gap). Varrendo o intervalo:
       1280 -> sobra 201px de rolagem     1440 -> sobra 41px
       1480 -> quase (rola 1px)           1500 -> CABE (rola 0)
   Escolhi 1500 e nao 1480 de proposito: 1480 e o ponto de empate, e limiar no empate deixa 1px de
   rolagem residual na propria fronteira. Um pixel nao incomoda ninguem, mas limiar sem margem quebra
   ao primeiro dado um pouco mais largo — e dado mais largo e exatamente o que trouxe esta rodada.
   Abaixo de 1500 a barra empilha e a tabela usa a largura toda; de 1500 para cima ela fica ao lado. O valor antigo era 960px — bom para o layout, cego para
   a largura da TABELA, que e o que o usuario arrastava.
   `.camp-layout` so renderiza no admin (conferido no DOM: 0 ocorrencias nas paginas publicas),
   entao elevar o limiar aqui nao alcanca o site publico. */
@media (max-width: 1499px) {
    .camp-layout {
        grid-template-columns: 1fr;
        gap: 1rem;
    }
    .camp-side {
        position: static;
        max-height: none;
        padding: 0.75rem;
    }
    .camp-side-head { padding-bottom: 0.65rem; margin-bottom: 0.35rem; }
    .camp-side-section { padding: 0.25rem 0; }
    .camp-side-label { padding: 0.35rem 0.5rem; }
    .camp-side nav {
        flex-direction: row;
        flex-wrap: wrap;
        gap: 0.3rem;
    }
    .side-tab { padding: 0.5rem 0.75rem; font-size: 0.82rem; }
    .side-tab-label { flex: 0 1 auto; }
    .side-tab-count { padding: 0.05rem 0.4rem; font-size: 0.68rem; }
    .camp-side-foot { display: none; }
}

/* Admin nav (tabs) — estilo op.gg/League */
.admin-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
    padding: 0.5rem;
    background: linear-gradient(180deg, #ffffff 0%, #f4f6fb 100%);
    border: 1px solid var(--border);
    border-radius: 14px;
    margin-bottom: 1.5rem;
    box-shadow: var(--shadow-sm);
    max-width: 100%;
}

.admin-tab {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 1rem;
    border-radius: 10px;
    color: var(--text-muted);
    text-decoration: none;
    font-size: 0.85rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    transition: color 0.15s, background 0.15s, transform 0.1s, box-shadow 0.15s;
    position: relative;
    border: 1px solid transparent;
}

.admin-tab svg {
    flex-shrink: 0;
    opacity: 0.6;
    transition: opacity 0.15s, transform 0.15s;
}

.admin-tab:hover {
    color: var(--accent);
    background: var(--accent-soft);
    border-color: rgba(26, 75, 214, 0.12);
}
.admin-tab:hover svg { opacity: 1; transform: scale(1.08); }

.admin-tab.is-active {
    color: #0a1128;
    background: linear-gradient(135deg, var(--gold-light) 0%, var(--gold) 100%);
    border-color: var(--gold-dark);
    box-shadow: 0 4px 14px rgba(200, 163, 92, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.45);
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.35);
}
.admin-tab.is-active svg { opacity: 1; }

.admin-tab.is-active::after {
    content: '';
    position: absolute;
    inset: -3px;
    border-radius: 12px;
    background: linear-gradient(135deg, var(--gold) 0%, transparent 60%);
    opacity: 0.25;
    z-index: -1;
    filter: blur(6px);
}

/* Rank de Lendas */
.lenda-progress {
    height: 6px;
    background: var(--bg-muted);
    border-radius: 3px;
    overflow: hidden;
    margin-top: 0.5rem;
    max-width: 320px;
}
.lenda-progress > div {
    height: 100%;
    transition: width 0.4s ease;
}

.lendas-dist {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}
.lendas-dist-row {
    display: grid;
    grid-template-columns: 130px 1fr 40px 50px;
    gap: 0.6rem;
    align-items: center;
    font-size: 0.9rem;
}
.lendas-dist-label { font-weight: 600; }
.lendas-dist-bar {
    height: 14px;
    background: var(--bg-muted);
    border-radius: 7px;
    overflow: hidden;
}
.lendas-dist-bar > div { height: 100%; border-radius: 7px; transition: width 0.4s ease; }
.lendas-dist-count { text-align: right; font-variant-numeric: tabular-nums; }
.lendas-dist-min { color: var(--text-subtle); font-size: 0.78rem; text-align: right; }

.rank-top {
    display: inline-flex;
    width: 24px; height: 24px;
    align-items: center; justify-content: center;
    border-radius: 50%;
    font-weight: 800;
    font-size: 0.85rem;
    color: #fff;
}
.rank-top-1 { background: linear-gradient(135deg,#ffd54a,#c8971d); }
.rank-top-2 { background: linear-gradient(135deg,#dcdcdc,#8f8f8f); }
.rank-top-3 { background: linear-gradient(135deg,#e0925b,#9b5a2b); }

/* Manual team slot: N jogadores */
.team-players {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 0.75rem;
}

/* Progress bar */
.progress {
    height: 6px;
    background: var(--bg-muted);
    border-radius: 3px;
    overflow: hidden;
    margin-top: 4px;
    max-width: 220px;
}
.progress > div {
    height: 100%;
    background: linear-gradient(90deg, var(--gold) 0%, var(--accent) 100%);
    transition: width 0.3s ease;
}

/* Rank bars */
.rank-bars { display: flex; flex-direction: column; gap: 0.55rem; }
.rank-row {
    display: grid;
    grid-template-columns: 90px 1fr 40px;
    align-items: center;
    gap: 0.75rem;
    font-size: 0.9rem;
}
.rank-bar {
    height: 12px;
    background: var(--bg-muted);
    border-radius: 6px;
    overflow: hidden;
}
.rank-bar > div {
    height: 100%;
    background: linear-gradient(90deg, var(--gold) 0%, var(--accent) 100%);
    border-radius: 6px;
}
.rank-count { text-align: right; color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* Top MMR */
.topmmr {
    list-style: none;
    padding: 0;
    margin: 0;
    counter-reset: mmr;
}
.topmmr li {
    display: grid;
    /* A 2a coluna carrega o NOME do jogador, que pode ser longo (`TierAscendente#BR1` mede
       149px). Em `auto` ela nao encolhe e a linha inteira estoura — medido em 360px: faixas
       somando 338px num container de 297px. `minmax(0, auto)` permite encolher; o truncamento
       fica no proprio link, abaixo. */
    grid-template-columns: 30px minmax(0, auto) 1fr auto;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--border);
    font-size: 0.92rem;
}
.topmmr li:last-child { border-bottom: none; }
.topmmr li::before {
    counter-increment: mmr;
    content: counter(mmr);
    display: none;
}
.topmmr li > a { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topmmr-rank { color: var(--text-muted); font-size: 0.82rem; }
.topmmr-mmr { font-weight: 700; }

/* Bracket */
.bracket-scroll {
    overflow-x: auto;
    padding-bottom: 0.5rem;
}
.bracket {
    display: flex;
    gap: 2rem;
    min-width: max-content;
}
.bracket-round {
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    gap: 1rem;
    min-width: 220px;
}
.bracket-round h3 {
    text-align: center;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin: 0 0 0.5rem;
}
.match {
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
    box-shadow: var(--shadow-sm);
}
.match.done { opacity: 0.95; }
.match-team {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
    padding: 0.55rem 0.75rem;
    border-bottom: 1px solid var(--border);
    font-size: 0.9rem;
}
.match-team:last-child { border-bottom: none; }
.match-team.win {
    background: #eefaf1;
    font-weight: 600;
    color: #157a3a;
}
.match-team.lose {
    color: var(--text-muted);
    text-decoration: line-through;
}
.team-label.empty { color: var(--text-subtle); font-style: italic; }

/* Breadcrumb */
.crumbs {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.85rem;
    color: var(--text-muted);
    margin-bottom: 0.85rem;
    flex-wrap: wrap;
}
.crumbs a {
    color: var(--text-muted);
    text-decoration: none;
    padding: 0.15rem 0.4rem;
    border-radius: 6px;
}
.crumbs a:hover { color: var(--accent); background: var(--accent-soft); }
.crumb-sep { color: var(--text-subtle); }
.crumb-current { color: var(--gold-dark); font-weight: 700; background: var(--gold-soft); padding: 0.15rem 0.5rem; border-radius: 6px; }

/* Grid de campeonatos */
.camp-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 0.85rem;
    margin-bottom: 1.5rem;
}

.camp-card {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 1.15rem 1.25rem;
    background: linear-gradient(180deg, #ffffff 0%, #fbfcff 100%);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    text-decoration: none;
    color: var(--text);
    box-shadow: var(--shadow-sm);
    transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
    position: relative;
    overflow: hidden;
}
.camp-card::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: linear-gradient(180deg, var(--gold) 0%, var(--accent) 100%);
    opacity: 0;
    transition: opacity 0.15s;
}
.camp-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow-md);
    border-color: var(--border-strong);
}
.camp-card:hover::before { opacity: 1; }

.camp-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.camp-card-head h3 {
    font-size: 1rem;
    letter-spacing: -0.01em;
}

.camp-prize {
    font-size: 0.85rem;
    color: var(--text-muted);
    margin-bottom: 0.25rem;
}

.camp-stats {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem 1rem;
    font-size: 0.82rem;
    color: var(--text-muted);
}
.camp-stats strong {
    color: var(--text);
    font-size: 0.95rem;
    display: block;
    letter-spacing: -0.01em;
}

.camp-card-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-top: 0.5rem;
    padding-top: 0.85rem;
    border-top: 1px solid var(--border);
    flex-wrap: wrap;
}

/* Regras / listas */
.rules { padding-left: 1.1rem; }
.rules li { margin: 0.4rem 0; color: var(--text-muted); font-size: 0.92rem; }

/* Item de lista com divisor (usado na Lista de campeonatos) */
.list-item {
    padding: 0.9rem 0;
    border-bottom: 1px solid var(--border);
}
.list-item:last-child { border-bottom: 0; }
.list-item strong { font-size: 0.95rem; }
.list-item .hint { margin-top: 0.25rem; }

/* Login */
.login-box {
    max-width: 380px;
    margin: 3rem auto;
}

/* Times manuais — slot */
.team-slot {
    padding: 0.85rem 0;
    border-bottom: 1px solid var(--border);
}
.team-slot:last-of-type { border-bottom: 0; }

.team-slot-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.team-slot-title {
    font-weight: 700;
    font-size: 0.85rem;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* Roleta v2 (§V20) — palco maior, brilho dourado, transições por estado. */
.roulette-stage {
    position: relative;
    overflow: hidden;
    min-height: 220px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    gap: 0.5rem;
    text-align: center;
    margin: 1rem 0;
    background: radial-gradient(circle at 50% 40%, rgba(201,169,106,0.18), transparent 65%),
                linear-gradient(180deg, #1a1a20, #0f0f14);
    border: 1px solid rgba(201,169,106,0.35);
    border-radius: 14px;
    box-shadow: inset 0 0 0 1px rgba(255,255,255,0.03), 0 12px 30px -12px rgba(0,0,0,0.5);
    transition: box-shadow .25s, border-color .25s;
}
.roulette-stage.spinning {
    border-color: rgba(201,169,106,0.7);
    box-shadow: inset 0 0 40px rgba(201,169,106,0.15), 0 18px 44px -14px rgba(201,169,106,0.35);
}
.roulette-stage.countdown { border-color: rgba(255,255,255,0.15); }
.roulette-stage.revealing {
    border-color: rgba(48,209,88,0.5);
    box-shadow: inset 0 0 40px rgba(48,209,88,0.1), 0 18px 44px -14px rgba(48,209,88,0.3);
}

/* Overlay de brilho girando durante o spin. */
.roulette-stage.spinning::before {
    content: '';
    position: absolute; inset: -50%;
    background: conic-gradient(from 0deg, transparent 0deg, rgba(201,169,106,0.18) 90deg, transparent 180deg, rgba(201,169,106,0.18) 270deg, transparent 360deg);
    animation: roleta-spin 1.4s linear infinite;
    pointer-events: none;
}
@keyframes roleta-spin { to { transform: rotate(360deg); } }

.roulette-name {
    position: relative; z-index: 1;
    font-size: clamp(1.8rem, 5vw, 2.6rem);
    font-weight: 900;
    letter-spacing: -0.02em;
    color: #fff;
    min-height: 2.6rem;
    text-shadow: 0 2px 20px rgba(201,169,106,0.4);
}
.roulette-stage.countdown .roulette-name {
    font-size: clamp(3rem, 10vw, 6rem);
    color: #C9A96A;
}
.roulette-stage.revealing .roulette-name { color: #C9A96A; }

.roulette-name.pulse { animation: roleta-pulse .6s ease-out; }
@keyframes roleta-pulse {
    0%   { transform: scale(0.6); opacity: 0; }
    50%  { transform: scale(1.15); opacity: 1; }
    100% { transform: scale(1); opacity: 1; }
}

.roulette-sub {
    position: relative; z-index: 1;
    color: rgba(255,255,255,0.65);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.15em;
    font-weight: 700;
}

/* Card revelado com "flip in" (§V20). */
.team-card--reveal {
    opacity: 0;
    transform: translateY(14px) scale(0.94);
    transition: opacity .35s ease, transform .35s ease;
}
.team-card--in {
    opacity: 1;
    transform: translateY(0) scale(1);
    box-shadow: 0 12px 30px -14px rgba(201,169,106,0.5);
    border-color: rgba(201,169,106,0.5);
}

.teams-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 0.75rem;
    margin-top: 1rem;
}

.team-card {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 1rem;
    background: #fff;
    box-shadow: var(--shadow-sm);
    transition: transform 0.15s, box-shadow 0.15s;
}

.team-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }

.team-card h3 { color: var(--text); font-size: 0.9rem; margin-bottom: 0.5rem; letter-spacing: -0.01em; }
.team-card p { color: var(--text-muted); font-size: 0.88rem; }

.spinning .roulette-name {
    animation: flicker 0.06s linear infinite;
}

@keyframes flicker {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.45; }
}

code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.85em;
    background: var(--bg-soft);
    padding: 0.1em 0.4em;
    border-radius: 4px;
    border: 1px solid var(--border);
}

/* Divider textual */
.section-divider {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 1.5rem 0 1rem;
    color: var(--text-subtle);
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.14em;
}
.section-divider::before,
.section-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--border);
}

/* ============================================================
   Formulário de campeonato com abas — minimalista, tema claro
   ============================================================ */
.camp-form-wrap { display: grid; gap: 1rem; }

.camp-form { padding: 0 !important; overflow: hidden; }

.camp-form-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1rem 1.25rem;
    border-bottom: 1px solid var(--border);
    flex-wrap: wrap;
    background: #fff;
}

.camp-form .ftab-radio { position: absolute; opacity: 0; pointer-events: none; }

.ftab-nav {
    display: flex;
    overflow-x: auto;
    scrollbar-width: none;
    background: #fff;
    border-bottom: 1px solid var(--border);
}
.ftab-nav::-webkit-scrollbar { display: none; }

.ftab-nav label {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    padding: .85rem 1.15rem;
    font-size: .875rem;
    font-weight: 600;
    color: var(--text-muted);
    border-bottom: 2px solid transparent;
    cursor: pointer;
    white-space: nowrap;
    transition: color .15s, border-color .15s;
    user-select: none;
    margin-bottom: -1px;
}
.ftab-nav label:hover { color: var(--text); }
.ftab-nav label [data-lucide] { width: 1rem; height: 1rem; opacity: .7; }
.ftab-nav label:hover [data-lucide] { opacity: 1; }

.ftab-panel { display: none; padding: 1.25rem; background: #fff; }

#ftab-basico:checked ~ .ftab-nav label[for="ftab-basico"],
#ftab-time:checked   ~ .ftab-nav label[for="ftab-time"],
#ftab-premio:checked ~ .ftab-nav label[for="ftab-premio"],
#ftab-pontos:checked ~ .ftab-nav label[for="ftab-pontos"],
#ftab-pix:checked    ~ .ftab-nav label[for="ftab-pix"],
#ftab-status:checked ~ .ftab-nav label[for="ftab-status"] {
    color: var(--gold-dark);
    border-bottom-color: var(--gold);
}
#ftab-basico:checked ~ .ftab-nav label[for="ftab-basico"] [data-lucide],
#ftab-time:checked   ~ .ftab-nav label[for="ftab-time"] [data-lucide],
#ftab-premio:checked ~ .ftab-nav label[for="ftab-premio"] [data-lucide],
#ftab-pontos:checked ~ .ftab-nav label[for="ftab-pontos"] [data-lucide],
#ftab-pix:checked    ~ .ftab-nav label[for="ftab-pix"] [data-lucide],
#ftab-status:checked ~ .ftab-nav label[for="ftab-status"] [data-lucide] { opacity: 1; }

#ftab-basico:checked ~ .ftab-panel-basico,
#ftab-time:checked   ~ .ftab-panel-time,
#ftab-premio:checked ~ .ftab-panel-premio,
#ftab-pontos:checked ~ .ftab-panel-pontos,
#ftab-pix:checked    ~ .ftab-panel-pix,
#ftab-status:checked ~ .ftab-panel-status { display: block; }

.ftab-foot {
    padding: .9rem 1.25rem;
    border-top: 1px solid var(--border);
    background: var(--bg-soft, #fafbfd);
    display: flex;
    align-items: center;
    gap: .75rem;
    justify-content: flex-end;
}
/* §V20 — Wizard: separa "Voltar" à esquerda, contador no meio, botões finais à direita. */
.ftab-foot [data-wiz="prev"] { margin-right: auto; }
.ftab-foot [data-wiz="prev"][disabled] { opacity: .35; pointer-events: none; }
@media (max-width: 540px) {
    .ftab-foot { flex-wrap: wrap; }
    .ftab-foot #camp-wizard-progress { order: -1; flex-basis: 100%; }
}

.ftab-subsection { margin-top: 1.25rem; }
.ftab-subtitle {
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .12em;
    color: var(--text-muted);
    margin: 0 0 .6rem;
}

.ftab-check {
    display: flex;
    align-items: flex-start;
    gap: .7rem;
    padding: .1rem 0;
    cursor: pointer;
}
.ftab-check input[type=checkbox] {
    margin-top: .2rem;
    flex: 0 0 auto;
    accent-color: var(--gold);
    width: 1.1rem;
    height: 1.1rem;
}
.ftab-check strong { display: block; color: var(--text); font-size: .93rem; font-weight: 600; }
.ftab-check span { display: block; font-size: .8rem; color: var(--text-muted); margin-top: .1rem; line-height: 1.4; }

.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: .75rem; }
@media (max-width: 800px) {
    .grid-3 { grid-template-columns: repeat(2, 1fr); }
    .grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
    .grid-3, .grid-4 { grid-template-columns: 1fr; }
    .ftab-nav label span { display: none; }
    .ftab-nav label { padding: .8rem .95rem; }
    .ftab-nav label [data-lucide] { width: 1.15rem; height: 1.15rem; opacity: 1; }
}

.prize-dist { display: flex; gap: .6rem; flex-wrap: wrap; align-items: center; }
.prize-slot { display: inline-flex; align-items: center; gap: .4rem; }
.prize-slot input { width: 64px; text-align: right; }
.prize-medal {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.65rem;
    height: 1.65rem;
    border-radius: 50%;
    font-size: .68rem;
    font-weight: 800;
    color: #1a1a1a;
    flex: 0 0 auto;
}
.medal-1 { background: linear-gradient(135deg, #ffd76a, #c9a24b); }
.medal-2 { background: linear-gradient(135deg, #e2e6ec, #a4b0be); }
.medal-3 { background: linear-gradient(135deg, #d68d5b, #a5673f); color: #fff; }
.prize-percent { font-weight: 600; color: var(--text-muted); font-size: .85rem; }

/* Botão de busca global */
.topnav-search{background:transparent;border:1px solid var(--border);color:var(--text-muted);padding:.3rem .55rem;border-radius:8px;cursor:pointer;font-family:inherit;font-size:.78rem;display:inline-flex;align-items:center;gap:.35rem;transition:all .15s}
.topnav-search:hover{border-color:var(--gold);color:var(--gold)}
.topnav-search kbd{background:rgb(var(--c-on-topbar) / .10);border-radius:4px;padding:1px 5px;font-size:10px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.is-admin .topnav-search{color:#c9d1d9;border-color:rgba(255,255,255,0.12)}
.is-admin .topnav-search:hover{border-color:var(--gold-light);color:var(--gold-light)}

/* ==========================================================================
   EMENDA 11 (§I12) — classes semanticas para o markup. O Rivet emite a CLASSE,
   os valores moram aqui. Nome encode PAPEL, nunca COR (§I12.1).
   ========================================================================== */

/* --- item 1: chips do feed, por TIPO DE EVENTO ---------------------------- */
.chip-evento {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
}
.chip-evento--rodada    { background: rgb(var(--c-evento-rodada) / .16);    color: rgb(var(--c-evento-rodada));    border: 1px solid rgb(var(--c-evento-rodada) / .30); }
.chip-evento--badge     { background: rgb(var(--c-evento-badge) / .16);     color: rgb(var(--c-evento-badge));     border: 1px solid rgb(var(--c-evento-badge) / .30); }
.chip-evento--inscricao { background: rgb(var(--c-evento-inscricao) / .16); color: rgb(var(--c-evento-inscricao)); border: 1px solid rgb(var(--c-evento-inscricao) / .30); }
/* camp_fim ja era token (text-gold) e ja passava nos dois temas — vira classe so por simetria */
.chip-evento--camp-fim  { background: rgb(var(--c-gold) / .16);            color: var(--gold);                    border: 1px solid rgb(var(--c-gold) / .30); }

/* --- itens 3 e 5: KPI e status REUSAM token existente ---------------------
   Vitorias/Winrate/Titulos e o status ATIVO nao precisam de token novo: --c-pago,
   --c-rejeitado e --c-gold ja existem, ja invertem e ja passam AA. Inventar
   --c-verde-kpi seria criar um segundo vocabulario para a mesma ideia. */
.kpi--positivo { color: var(--pago); }
.kpi--negativo { color: var(--rejeitado); }
.kpi--titulo   { color: var(--gold); }

/* alpha menor que os chips de evento de proposito: a 16% este chip dava 4.34 no
   tema claro. Menos tint = fundo mais claro = mais contraste com o proprio texto. */
.chip-status--ativo {
    background: rgb(var(--c-pago) / .10);
    color: var(--pago);
    border: 1px solid rgb(var(--c-pago) / .30);
}

/* --- item 6: MEDALHA do podio — EXCECAO DECLARADA (§I12.3) ----------------
   NAO tokenizar. O fundo e gradiente da paleta default (nao inverte) e o texto era
   text-bg-900 (inverte), entao reprovava nos DOIS temas por motivos opostos.
   Varri o espaco RGB inteiro: com as paradas de hoje, a MELHOR cor de texto possivel
   e preto puro e ainda da 4.06 — nao existe valor que passe, em tema nenhum.
   Por isso duas coisas mudam juntas, e as duas sao FIXAS:
     1) texto fixo #0a1128 (nao acompanha o tema)
     2) gradiente ESTREITADO — a faixa antiga varria de quase-branco a medio, e era a
        largura da faixa, nao a cor do texto, que tornava o par impossivel.
   Uma classe compartilhada pelos 3 call sites (rank/duplas/seasons): tres edicoes
   paralelas do mesmo trecho e como divergencia nasce (§I12.2). */
.medalha {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    font-weight: 900;
    color: #0a1128;           /* FIXO — ver acima. Nao trocar por token. */
}
.medalha--1 { background: linear-gradient(135deg, #fef08a, #ca8a04); }  /* yellow-200 -> 600 · pior 6.36 */
.medalha--2 { background: linear-gradient(135deg, #e5e7eb, #9ca3af); }  /* gray-200   -> 400 · pior 7.36 */
.medalha--3 { background: linear-gradient(135deg, #fdba74, #ea580c); }  /* orange-300 -> 600 · pior 5.25 */

/* --- EMENDA 17: icone de medalha (herda currentColor) --------------------
   Medido contra o card e contra a linha em hover (bg-700/40), 1.4.3 4.5:1:
     light 4.72 · 4.65 · 4.70      dark 12.32 · 10.73 · 6.15 */
.medalha-icone--1 { color: rgb(var(--c-medalha-ouro)); }
.medalha-icone--2 { color: rgb(var(--c-medalha-prata)); }
.medalha-icone--3 { color: rgb(var(--c-medalha-bronze)); }

/* --- os DOIS estados de status que faltavam ------------------------------
   O enum e ('upcoming','active','finished') e so `active` tinha classe. Os outros dois caiam
   num fallback neutro — chip sem cor, em silencio, que e o mesmo padrao vazio que esta rodada
   vem caçando. `upcoming` usa ouro (previsto/atencao) e `finished` usa o mudo (encerrado). */
.chip-status--upcoming {
    background: rgb(var(--c-gold) / .12);
    color: var(--gold);
    border: 1px solid rgb(var(--c-gold) / .30);
}
.chip-status--finished {
    background: rgb(var(--c-text-muted) / .12);
    color: var(--text-muted);
    border: 1px solid rgb(var(--c-text-muted) / .30);
}

/* ==========================================================================
   MODAL DE CONFIRMACAO (v9) — substitui o window.confirm() nativo.
   O <dialog> e construido UMA vez pelo app.js (lazy). Aqui so mora a aparencia.

   Por que <dialog> e nao div: showModal() da foco-trap e Esc NATIVOS. Reimplementar
   armadilha de foco a mao e onde esse tipo de componente costuma falhar em
   acessibilidade — o navegador ja faz certo, e de graca.

   Tokenizado: usa as mesmas variaveis do resto (--bg-card, --border, --text...), entao
   nasce pronto para os 2 temas. O admin e claro fixo, mas se o publico usar um dia,
   funciona sem tocar aqui.
   ========================================================================== */
.modal-confirmar {
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--bg-card);
    color: var(--text);
    padding: 0;
    max-width: min(30rem, calc(100vw - 2rem));
    width: 100%;
    box-shadow: 0 24px 64px -12px rgba(0, 0, 0, 0.45);
}
.modal-confirmar::backdrop {
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(2px);
}
.modal-caixa { padding: 1.1rem 1.25rem 1rem; }
.modal-titulo {
    margin: 0 0 0.5rem;
    font-size: 1.02rem;
    font-weight: 800;
    letter-spacing: 0.01em;
}
.modal-corpo {
    margin: 0;
    color: var(--text-muted);
    font-size: 0.9rem;
    line-height: 1.5;
    overflow-wrap: anywhere;
}
.modal-forte { margin-top: 0.9rem; }
.modal-forte-rotulo {
    display: block;
    font-size: 0.78rem;
    color: var(--text-muted);
    margin-bottom: 0.3rem;
}
.modal-forte-eco {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-weight: 700;
    color: var(--text);
}
.modal-forte-campo {
    width: 100%;
    padding: 0.5rem 0.65rem;
    border: 1px solid var(--border-strong);
    border-radius: 8px;
    background: var(--bg);
    color: var(--text);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.88rem;
}
.modal-forte-campo:focus { outline: 2px solid var(--gold); outline-offset: 1px; }
.modal-acoes {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1.1rem;
}
/* botao desabilitado precisa PARECER desabilitado — senao o usuario clica e nada acontece,
   que e pior do que nao poder clicar. */
.modal-acoes .btn[disabled] { opacity: 0.45; cursor: not-allowed; }

@media (max-width: 480px) {
    .modal-acoes { flex-direction: column-reverse; }
    .modal-acoes .btn { width: 100%; }
}
/* ===========================================================================
   BRASÃO DA SONLAS LEAGUE — v10          (detalhe completo em docs/brasao-v10.md)
   ---------------------------------------------------------------------------
   O brasão é ouro + prata sobre transparente, desenhado para fundo escuro. No tema
   claro o card é BRANCO PURO (--c-bg-800: 255 255 255), e a cor mais comum do
   CONTORNO é prata — que contra branco praticamente não separa. Medindo a silhueta
   (o pixel opaco que encosta no fundo, não o miolo), boa parte do contorno fica
   abaixo de 3:1 no claro.

   POR ISSO o brasão sempre se senta numa PLACA NAVY, nos DOIS temas — não só no
   claro. Três motivos:
     1. Elimina a dependência de tema: ele encosta sempre na mesma superfície,
        aquela para a qual foi desenhado (o -og.png já vem com esse fundo sólido e
        o theme-color do manifest é o mesmo #0a1128).
     2. Melhora GRANDE na separação do contorno — da ordem de 4x menos contorno
        abaixo de 3:1 do que contra o branco.
     3. UM mecanismo em vez de dois. Placa só-no-claro seria um fork de tema, que
        divergiria na primeira mudança (§0.11). No escuro a placa é quase invisível
        contra o fundo: custo visual nulo, consistência de graça.

   DUAS RESSALVAS DE ENUNCIADO, porque o número aqui é fácil de exagerar:

   a) NÃO é conformidade integral com 3:1. Mesmo sobre a placa sobra contorno
      abaixo do alvo — a arte tem contorno escuro, e escuro sobre navy escuro
      separa pouco. O ganho é grande; a meta não é atingida por completo.

   b) LOGO E MARCA SÃO ISENTOS do WCAG 1.4.11 pelo texto da própria norma. Não há
      requisito a cumprir neste elemento: aplicamos o critério VOLUNTARIAMENTE,
      como régua de qualidade visual. O residual do item (a) não é violação.

   Os percentuais medidos ficam no doc, e lá como DIREÇÃO e ordem de grandeza — não
   como valor fechado. Duas medições independentes do mesmo cenário deram frações
   bem diferentes (mesma direção) porque o número depende de limiar de alfa, de
   anti-aliasing na borda e do tamanho do raster medido. Número de contraste de ARTE
   não é número de token: token é exato, arte é método-dependente.

   E o método importou mais que o número: a primeira passada mediu TODO pixel opaco,
   o que trata a arte como se fosse texto e conta preenchimento interno — e apontou
   o tema ERRADO como o pior. O que decide se o brasão "some" é a silhueta.
   =========================================================================== */

.brasao {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: rgb(var(--c-brasao-fundo));
    border: 1px solid rgb(var(--c-gold) / 0.28);
    border-radius: 16px;
    padding: 0.75rem;
    line-height: 0;             /* mata o espaço de baseline sob a <img> */
    flex-shrink: 0;
}

.brasao img {
    display: block;
    width: 100%;
    height: auto;
    max-width: 100%;
}

/* Hero da home: grande, mas encolhe junto com a tela.
   `display: flex` (e nao o inline-flex do .brasao) porque aqui o brasao ocupa a
   PROPRIA LINHA — como inline ele dividia a linha com o rotulo "… League · Arena"
   logo abaixo, e `margin-inline: auto` nao centra elemento inline. */
.brasao-hero {
    display: flex;
    width: min(220px, 46vw);
    padding: 1rem;
    border-radius: 22px;
    margin-inline: auto;
}

/* Ao lado de um <h1>: acompanha a altura do título sem empurrar o layout. */
.brasao-titulo {
    width: 84px;
    padding: 0.6rem;
    border-radius: 14px;
}

/* Detalhe do camp: o menor. 48px de largura com o asset -96 = exatamente 2x,
   que é o que deixa nítido em tela retina sem baixar arquivo maior à toa. */
.brasao-camp {
    width: 48px;
    padding: 0.45rem;
    border-radius: 12px;
}

@media (max-width: 640px) {
    .brasao-hero  { width: min(160px, 44vw); }
    .brasao-titulo { width: 64px; }
    .brasao-camp   { width: 40px; }
}

/* Separador entre itens e augments na "build campeã" (v11).
   Existe como classe porque `w-px`/`bg-border`/`mx-1` NÃO estão no build estático do
   Tailwind deste projeto — classe fora do build não estiliza nada e falha em SILÊNCIO,
   que foi como o ícone de campeão saiu com o tamanho natural na primeira passada. */
.rec-sep {
    display: inline-block;
    width: 1px;
    align-self: stretch;
    min-height: 1.5rem;
    margin: 0 0.25rem;
    background: var(--border);
}

/* ===========================================================================
   MODO STREAMER — chip e toggle na barra do admin (v14)
   ---------------------------------------------------------------------------
   O chip e DELIBERADAMENTE chamativo. Ele nao decora: e o unico sinal de que os
   dados na tela estao mascarados. Um indicador discreto falha exatamente no
   momento em que importa — o operador esquece que ligou, ve dado mascarado e
   acha que o banco esta errado; ou pior, esquece que DESLIGOU e segue gravando
   stream com e-mail de inscrito na tela.
   Admin e tema CLARO fixo, mas as cores saem de token: se o admin ganhar tema
   escuro um dia, o chip acompanha sem segunda edicao.
   =========================================================================== */

.topnav-streamer {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0;
}

.chip-streamer {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    background: rgb(var(--c-aviso, 184 134 11) / 0.18);
    border: 1px solid rgb(var(--c-aviso, 184 134 11) / 0.55);
    color: rgb(var(--c-aviso, 184 134 11));
    font-size: 0.7rem;
    font-weight: 900;
    letter-spacing: 0.06em;
    white-space: nowrap;
}

.topnav-streamer-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.55rem;
    border-radius: 8px;
    border: 1px solid var(--border);
    background: transparent;
    color: inherit;
    font-size: 0.78rem;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
}

.topnav-streamer-btn:hover { border-color: var(--border-strong); }

/* Alvo de toque de 44px no celular sem inchar a barra no desktop (§ mobile). */
@media (max-width: 768px) {
    .topnav-streamer-btn { padding: 0.5rem 0.7rem; }
}
