/* ============================================
   To Dentro — design "Vibrante" (mobile-first)
   Fonte: Nunito · Gradiente roxo→rosa
   - inputs com 16px (iOS não dá zoom)
   - áreas de toque com mínimo de 44px
   ============================================ */

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

:root {
    /* =========================================================================
       CAMADA 1 — PIGMENTO. Valor bruto, sem cargo, e é o ÚNICO lugar do arquivo
       em que cada um destes quatro hexadecimais aparece.
       =========================================================================
       O `design-system.md` §1 prescreve esta camada desde a T-0015; ela entra
       agora porque o modo escuro a tornou obrigatória, e por um motivo
       mecânico, não estético: as ilhas de papel do palco precisam do MESMO
       valor que um semântico da página tem — e `var()` dentro de custom
       property é substituída NO PONTO DE USO, então `--palco-papel-tinta:
       var(--cor-texto)` seguiria a página para o escuro. O pigmento não segue
       ninguém: ele não é redeclarado por pele nenhuma, nem por modo nenhum.

       ⚠️ PIGMENTO NUNCA APARECE EM REGRA DE COMPONENTE. Quem lê daqui é a
       camada 2 (semântico) e a camada 3 (token de peça), logo abaixo. Um
       `color: var(--tinta-1)` num seletor é a camada 1 vazando, e vazamento
       de camada 1 é o que faz uma rampa virar um segundo vocabulário — foi
       assim que o `--byu-*` nasceu.

       Só entram os degraus que comprovadamente faltam. Rampa com degrau que
       ninguém referencia é inflação de design system.

       =========================================================================
       ⚠️ TD-076 APOSENTOU `--cinza-100`, `--cinza-700` E `--cinza-900`
       =========================================================================
       Os três eram a camada 1 da paleta ANTIGA e saíram inteiros da folha nesta
       tarefa. A saída é AUTORIZADA e não silenciosa: as travas de cargo que os
       guardavam (`Invariantes_do_design_system_test`, F6) declaram
       `cai_quando: ADR que troque a paleta e aposente a camada 1 atual`, e
       TD-076 é esse ADR. Elas continuam valendo — com TETO e não igualdade, o
       valor pode sumir de graça e não pode ganhar dono novo (TD-077).
       `--branco` FICA: `--tinta-texto` o lê, e `--tinta-texto` é invariante de
       modo com teste guardando (`Contrato_do_modo_de_cor_test`). */
    --branco: #ffffff;

    /* =========================================================================
       CAMADA 1 — A PELE CLARA DA DIREÇÃO B, "A CABINE" (TD-076, T-0031)
       =========================================================================
       ESTE É O ÚNICO LUGAR DA FOLHA EM QUE CADA UM DESTES HEXADECIMAIS APARECE.
       A camada 2 (os nomes semânticos que as ~7.900 linhas abaixo já consomem)
       LÊ daqui com `var()` — nenhum semântico foi renomeado, porque renomear
       derrubaria o piso de 55 consumidores de `var(--cor-texto-suave)` que o
       invariante F5 cobra.

       A REGRA QUE GERA OS DOIS MODOS, e é UMA regra e não duas paletas:
         · ELEVAR É SEMPRE CLAREAR — no escuro o cartão ganha luz sobre o
           carvão; no claro o CHÃO se tinge (papel violáceo) e o cartão sobe até
           o branco.
         · INTERAGIR É ANDAR NA DIREÇÃO DA TINTA — por isso o hover CLAREIA no
           escuro e ESCURECE no claro. Um par de tokens, dois comportamentos.
         · PREENCHIMENTO VIVO VAI AO EXTREMO DE LUMINÂNCIA OPOSTO AO PAPEL, e a
           tinta em cima dele vai ao extremo DO papel. É por isso que AA sai
           barato dos dois lados.

       O QUE MUDA DE TRAÇO, E NÃO SÓ DE COR (TD-076 §7):
         · No ESCURO o fio NÃO separa (1,19:1) — quem separa é o degrau de
           superfície mais a sombra, e por isso a sombra é profunda. NENHUM
           ESTADO PODE DEPENDER DE COR DE BORDA lá.
         · No CLARO o fio VOLTA a separar (1,27:1) e a sombra RECUA: sombra
           pesada em papel claro lê como sujeira.

       ⚠️ `--tinta-1/2/3` NÃO SÃO PARENTES DE `--tinta`, `--tinta-cartao`,
       `--tinta-texto` E `--tinta-texto-suave`. Aquela família é a FAIXA DE TINTA
       da página inicial (T-0015, 6g), uma superfície escura fixa que não gira
       com modo nenhum; esta é a escala de TEXTO da pele. Nomes parecidos,
       cargos distintos — registrado aqui para ninguém unificar os dois por
       simetria de nome. */

    /* AS SUPERFÍCIES, do fundo para a frente. `--cor-fundo` é o papel e mora na
       camada 2 (lá está o porquê: ele tem espelho em PHP e precisa do literal). */
    --moldura:    #ddd7ea;              /* a moldura da página, fora do papel */
    --sup-cartao: var(--branco);        /* 1,24:1 acima do papel */
    --sup-hover:  #eeeaf7;              /* interação anda para a tinta: ESCURECE (1,18:1) */
    --sup-press:  #e6e0f3;
    --sup-campo:  #f3f0fa;              /* o poço do formulário fica ABAIXO do cartão */

    /* AS TINTAS. Medidas sobre cartão · papel · pressionado.
       ⚠️ A PRIMEIRA VEM EM TRIPLETE, e o triplete tem DOIS consumidores — que é
       o teste que separa indireção útil de indireção decorativa. A elevação da
       pele clara é sombra TINGIDA com a tinta (`rgb(...) / alfa`), e `rgb()` com
       alfa precisa dos componentes; sem o triplete, `--sombra-tinta` seria o
       valor da tinta escrito uma segunda vez — dois lugares para uma cor, que é
       o defeito que esta folha já pagou três vezes. (A banda tinha o mesmo
       arranjo e o PERDEU nesta tarefa, porque o halo saiu e sobrou um
       consumidor só: ver `--palco-1`.) */
    --tinta-1-rgb: 39 32 57;            /* #272039 */
    --tinta-1: rgb(var(--tinta-1-rgb)); /* 15,53 · 12,54 · 12,07 */
    --tinta-2: #4c4360;                 /*  9,21 ·  7,44 ·  7,16 */
    --tinta-3: #5c5470;                 /*  6,90 ·  5,58 ·  5,52 — 4,90 até no canto mais tingido */

    /* OS FIOS. `--fio-controle` é o ÚNICO token que praticamente não muda entre
       os modos, e o motivo é medido: ele precisa ser visto contra os DOIS
       extremos (4,49 no cartão claro, 4,30 no poço escuro). */
    --fio-1:        #e6e2f0;            /* contorno de cartão: 1,27:1 — no claro ele existe */
    --fio-2:        #d5cde6;            /* interativo: 1,53:1 */
    --fio-controle: #7b719b;            /* contorno de CAMPO: 4,49 no cartão, 3,62 no papel */
    --fio-pendente: #7f6aaf;            /* o tracejado "ainda não aconteceu": 4,58 no cartão */

    /* O ACENTO — e ele faz os DOIS trabalhos que `--cor-primaria` fazia mal:
       preenchimento (branco em cima 6,51:1) e tinta (sobre o papel 5,26:1). */
    --acento:       #5c31f6;
    --acento-forte: #4d20e0;            /* hover: mais presença (branco em cima 8,08:1) */
    --acento-fundo: #4318c4;            /* pressionado: afunda (9,69:1) */

    /* ⚠️ A TINTA QUE VAI EM CIMA DE PREENCHIMENTO VIVO, e ela NÃO é
       `--tinta-texto`. `--tinta-texto` é a tinta da superfície de MARCA
       (`--grad`, `--cor-primaria`), invariante de modo e guardada por teste;
       esta gira, porque o preenchimento vivo gira. TD-076 registra que
       `--chassi` fazia dois trabalhos e foi QUEBRADO em quatro nomes — este é
       um dos quatro, e juntá-lo de volta é desfazer a correção. */
    --tinta-viva: var(--branco);

    /* AS SEMÂNTICAS COMO PIGMENTO. As pastilhas são TOKEN SÓLIDO e nunca rgba:
       pastilha em rgba compõe com o substrato, e o substrato muda no hover —
       TD-076 matou essa classe inteira de defeito ao torná-las sólidas. */
    --verde: #0f5f2c;                   /* o verde canônico da casa não sobrevive */
    --pastilha-verde: #e2efe7;          /* numa pastilha da própria cor: 6,58:1 aqui */
    --ambar: #7a5b12;
    --pastilha-ambar: #efebe3;          /* 5,30:1 */
    --rosa: #c2103a;
    --pastilha-rosa: #f8e2e7;           /* 4,96:1 */
    --rosa-forte: #a30d31;
    --rosa-solido: var(--rosa);         /* destrutivo confirmado, tinta branca: 6,12:1 */
    --pastilha-neutra: #eceaf0;         /* 5,95:1 com a tinta-3 */
    --pastilha-acento: #ebe6fe;         /* 5,36:1 */

    /* O ANEL DE FOCO E A FOLGA. Medido: anel encostado direto no preenchimento
       vivo dá 2,01:1 nos DOIS modos — reprova idêntico dos dois lados. A folga
       resolve os dois, porque ela mostra o extremo oposto. */
    --anel:       #38206f;              /* 13,09 no cartão · 10,57 no papel */
    --anel-folga: var(--branco);        /* 6,51 contra a tecla · 13,09 contra o anel */

    /* AS TECLAS DE PESO SECUNDÁRIO E A DESTRUTIVA. */
    --tecla-fantasma:       #f2f0f7;
    --tecla-fantasma-hover: #e4dff0;
    --tecla-fantasma-off:   #f5f4f8;
    --tecla-perigo:         #fae9ed;
    --tecla-perigo-hover:   #f6d7de;

    /* OS FUNDOS DE BLOCO — aviso, recibo, risco e fila. */
    --fundo-aviso:   #f6f1e4;
    --fundo-recibo:  #eff6f2;
    --fundo-risco:   #fcf2f4;
    --fundo-risco-2: #f7dfe4;
    --fundo-fila:    #faf9fc;

    /* AS LISTRAS DO MEDIDOR INDETERMINADO e o trilho das barras.
       `--listra-forte` LÊ `--ambar` em vez de repetir o hexadecimal: `var()`
       dentro de custom property é substituída NO PONTO DE USO, então uma
       declaração só serve os dois modos e o par (token, modo) continua tendo UM
       lugar. É a mesma escrita de `--cor-roxo-claro` desde a T-0016. */
    --listra-forte: var(--ambar);
    --listra-fraca: #d8cdb9;            /* 4,01:1 entre as duas listras */
    --trilho-barra: #e7e5ee;
    --marca-barra:  #c3c0cf;

    /* OS DOIS CAMPOS DE COR DA PÁGINA. No ESCURO a sala tem LUZ: dois brilhos
       que CLAREIAM o papel. No CLARO a mesma luz seria branco sobre branco,
       então ela vira TINTA e os dois cantos ESCURECEM o papel — o degrau do
       cartão SOBE de 1,24 para 1,29 no canto quente e 1,39 no violeta. No claro
       o campo de cor AJUDA a separação em vez de comer, que é o oposto do
       escuro. Sem `background-attachment: fixed` e sem `backdrop-filter`: os
       dois geram a caixa branca fantasma no Chromium do usuário. */
    --campo-1: radial-gradient(900px 520px at 8% -6%, rgba(255, 205, 150, 0.26), transparent 62%);
    --campo-2: radial-gradient(820px 640px at 104% 106%, rgba(124, 58, 237, 0.085), transparent 60%);

    /* ⚠️ O GRADIENTE SOBREVIVE, MAS NÃO COMO ASSINATURA DA PÁGINA (TD-076 §4).
       Ele era `linear-gradient(135deg, violet-600, fuchsia-600, pink-600)` — os
       três valores padrão do Tailwind no arranjo mais repetido da internet, e o
       diagnóstico da T-0030 é que ali não havia decisão de marca, havia default.
       O que fica é o SELO da marca; a matiz continua, o arranjo sai da página.
       ⚠️ Ele NÃO pode ser redeclarado no bloco escuro (teste guardando): é a
       marca, e o pior par dela — branco sobre `#db2777`, 4,60:1 — não depende do
       fundo da página. */
    --grad: linear-gradient(135deg, #7c3aed 0%, #c026d3 60%, #db2777 100%);
    --cor-primaria: #7c3aed;
    --cor-primaria-escura: #6d28d9;
    --cor-rosa: #db2777;

    /* =========================================================================
       A MARCA TEM DOIS CARGOS, E O MODO CLARO ESCONDEU A DIVISÃO
       =========================================================================
       `--cor-primaria` é a marca como PREENCHIMENTO: superfície sob texto
       branco. O par que ela responde é `branco SOBRE ela` — 5,70:1.
       `--cor-acento` é a marca como TINTA E SINAL: link, anel de foco, limite
       de componente, sublinhado de guia, preenchimento do medidor. O par que
       ELA responde é o contrário — `ela SOBRE a superfície` — 5,08:1.

       ⚠️ NO CLARO OS DOIS VALORES COINCIDEM, E FOI ISSO QUE ESCONDEU A DIVISÃO.
       `--cor-acento` nasce com o valor que `--cor-primaria` já tinha, então o
       reapontamento dos 43 usos NÃO MUDA UM PIXEL: aqui diferença visual é
       REGRESSÃO, não conformidade (Classe 2 do protocolo de TD-045 §7.3).

       NO ESCURO NENHUM VALOR ÚNICO SERVE AOS DOIS, e é a medição que prova que
       sempre foram dois cargos — não é preferência, é aritmética:
         · `#7c3aed` como TINTA sobre a página escura ....... 3,10:1  REPROVA
         · `#7c3aed` como TINTA sobre o cartão escuro ....... 2,71:1  REPROVA
         · `#7c3aed` como LIMITE sobre o trilho do medidor .. 2,45:1  REPROVA
         · `#b69bff` sob texto branco ...................... 2,30:1  REPROVA
       É a mesma forma do defeito `--cor-borda` × `--limite`: um nome fazendo
       dois trabalhos ficou invisível até uma medição separar os dois — e o
       modo escuro É essa medição.

       O QUE **NÃO** REAPONTA e continua em `--cor-primaria`, por ser
       preenchimento: `.seta-acomp.aberto`, `.admin-link.ativa`, `.admin-av.grad`,
       a chave ligada, os dois `accent-color` (o navegador põe branco por cima) e
       todo consumidor de `--grad`. (Das duas primeiras: `.admin-av.grad` e a
       família `.admin-link` inteira saíram da folha na T-0031 — a lista é do
       estado de então e fica como está, porque é o registro daquela decisão.)

       ⚠️ TD-076 FECHOU A DIVISÃO EM VEZ DE MANTÊ-LA: `--acento` faz os dois
       trabalhos com folga nos dois modos (branco em cima 6,51:1; como tinta
       sobre o papel 5,26:1), então a camada 2 inteira lê UM pigmento. O que
       continua em `--cor-primaria` é a MARCA, e marca não é acento. */
    --cor-acento: var(--acento);
    /* ⚠️ `--cor-fundo` NÃO ESCURECE MAIS SEM QUE `--cor-texto-suave` SEJA
       REMEDIDO. Em `#f4f0fb` ele está a 4,73:1 e o piso é 4,5. O próximo degrau
       plausível, `#f2eefa`, o levaria a 4,65:1 — 3 % de folga, e a régua deste
       projeto (TD-079) mede cada tinta contra a superfície que não perdoa. Era
       `#faf8ff` (L* 97,9) e passou a `#f4f0fb` (L* 95,4): o ganho não é
       conforto, é que o cartão branco sai de 1,05:1 para 1,12:1 contra a página
       e a SUPERFÍCIE volta a separar — hoje quem separava era a borda, e foi por
       isso que `--cor-borda` virou limite de componente em sete lugares.
       Remedido contra o valor novo: `--cor-texto` 13,28:1 · `--cor-texto-suave`
       4,73:1 · `--cor-acento` como tinta 5,08:1 · `--cor-erro-texto` 5,45:1 ·
       `--limite` como borda 4,03:1. Nenhuma tinta reprova.
       ⚠️ `--cor-neutro-fundo` NÃO acompanha, e a recusa é medida: em `#eae5f2`
       o cinza secundário cairia para 4,30:1 e recriaria, no mesmo dia, o defeito
       que a T-0015 gastou duas passagens para fechar.
       ⚠️ ESTE VALOR TEM UM ESPELHO EM PHP: `Tema::corDeFundo()`, que alimenta o
       `background_color` do manifesto. Os dois mudam no MESMO commit ou o
       aplicativo instalado abre com uma cor que a página não tem.

       =========================================================================
       ⚠️ TD-076: O PAPEL PASSOU A SER VIOLÁCEO, E ESTE TOKEN É A EXCEÇÃO DA
       CAMADA 1 — ELE CARREGA O LITERAL EM VEZ DE LER UM PIGMENTO
       =========================================================================
       O usuário recusou a inversão ingênua da paleta escura: papel branco mais
       cartão branco é escada de degrau ZERO. A saída foi TINGIR O CHÃO — o papel
       desce a `#e9e5f2` e o cartão sobe até o branco, o que dá 1,24:1 de degrau
       real, contra os 1,12:1 anteriores.

       POR QUE ELE NÃO É `var(--sup-pagina)` COMO OS IRMÃOS: porque TRÊS testes
       comparam o valor deste token, como STRING, com o hexadecimal que o PHP
       manda (`Tema::corDaBarra(Escuro)` e `Tema::corDeFundo()`). `var(--x)` de um
       lado e `#e9e5f2` do outro nunca casam, e o espelho — que é a trava certa
       para uma cópia, porque não crava valor e reprova na divergência — deixaria
       de proteger o BUG-TD-009. Então o hexadecimal do papel mora AQUI, e é aqui
       que ele existe uma vez por modo. Um `--sup-pagina` separado seria dois
       nomes para uma cor, que é o defeito que esta casa já pagou três vezes.
       Remedido contra o papel novo: `--cor-texto` 12,54:1 · `--cor-texto-suave`
       5,58:1 · `--cor-acento` como tinta 5,26:1 · `--cor-erro-texto` 4,96:1 ·
       `--limite` como fio 3,62:1. Nenhuma tinta reprova. */
    /* ⚠️ T-0038: O ESPELHO EM PHP SAIU DAQUI. A barra do navegador e o fundo do
       manifesto passaram a espelhar `--dono-fundo` (o cabeçalho do arquivo do
       Stitch, que veste toda tela do leiaute do painel). Este token continua
       sendo o papel das telas que não são do dono (login, cadastro, termos,
       console), e continua com o literal: é o padrão desta camada. */
    --cor-fundo: #e9e5f2;
    --cor-texto: var(--tinta-1);

    /* ⚠️ O DEGRAU DO MEIO ESTAVA SEM NOME, E POR ISSO NINGUÉM O LIA (T-0031).
       A camada 2 tinha `--cor-texto` (tinta-1) e `--cor-texto-suave` (tinta-3):
       o degrau do meio existia como pigmento e não tinha cargo, então toda
       hierarquia de três níveis desta folha era escrita com DOIS. É o texto
       de apoio que ainda é DADO — a linha da parte do álbum, a prosa da zona
       de risco —, forte demais para `-suave` e secundário demais para a tinta
       cheia. Medido: 9,21:1 no cartão claro e 10,52:1 no cartão escuro.
       ⚠️ NOME NOVO E NÃO SEGUNDO NOME PARA UMA COR: `--tinta-2` é pigmento sem
       cargo (a regra da camada 1 acima), e é justamente o que falta a ele.
       Os `--fundo-*`, `--tecla-*`, `--sup-press` e `--anel-folga` NÃO ganham
       gêmeo `--cor-*`: eles já nascem com o cargo no nome, e duplicá-los seria
       o defeito de "dois nomes para uma cor" que esta casa já pagou três vezes. */
    --cor-texto-medio: var(--tinta-2);

    /* PASSAGEM A DA CORREÇÃO DE AA (T-0015, TD-044 P4 / TD-045 item 6).
       `--cor-texto-suave` era #7a7290 e REPROVAVA AA como texto em CINCO
       superfícies medidas: 4,30:1 sobre --cor-fundo · 4,07:1 sobre
       --cor-info-fundo · 3,97:1 sobre --cor-neutro-fundo · 4,36:1 sobre
       #fbfaff (.form-keys) · 4,40:1 sobre #fcfbff (.admin-tabela tr:hover).
       Com #6f6785 os mesmos cinco pares medem 5,04 · 4,78 · 4,66 · 5,11 · 5,15,
       e 5,31:1 sobre o cartão branco. É o tom que já existia no arquivo como
       apelido `-forte`: o apelido morreu, o valor ficou, e agora vale para os
       43 usos de uma vez. DOIS NOMES PARA UMA COR APODRECEM — foi por isso que
       a correção da F6 pela metade deixou o par errado vivo em 43 lugares.
       ⚠️ T-0031: o NOME não mudou — o VALOR BASE mudou, e por isso o F4 está
       declarado `aberta` no registro de travas (TD-077) até o gate da etapa 4.
       Os 74 consumidores continuam intactos, que é a razão de a camada 2 não ter
       sido renomeada: renomear derrubaria o piso de 55 que o F5 cobra. */
    --cor-texto-suave: var(--tinta-3);
    --cor-borda: var(--fio-1);
    --cor-roxo-claro: var(--pastilha-acento);
    /* SOB O PONTEIRO **DENTRO DE UM CARTÃO** — e ele NÃO é `--cor-roxo-claro`.
       `--cor-roxo-claro` foi calibrado contra a PÁGINA (#f4f0fb), onde o degrau
       existe; sobre o cartão BRANCO ele mede 1,11:1, que é o gêmeo numérico do
       NC-05 que a T-0021 acabou de consertar — superfície declarada que não
       separa nada. Este token é o degrau MEDIDO contra o cartão:
         · claro  #e9e1fa sobre #ffffff .......... 1,26:1
         · escuro #332c46 sobre #282136 .......... 1,17:1
       ⚠️ NO ESCURO ELE CLAREIA, e isso é a regra e não o gosto: a escada deste
       produto sobe sempre (o cartão dá 1,14:1 sobre a página, e este é o degrau
       seguinte). `--cor-roxo-claro` no escuro ESCURECERIA a linha — luminância
       0,01539 contra 0,01805 do cartão —, e linha que afunda sob o ponteiro lê
       como desativada. Tintas remedidas SOBRE esta superfície: `--cor-texto`
       11,80:1 (claro) e 10,31:1 (escuro); a seta em `--cor-acento` 4,51:1 e
       5,74:1. Nenhuma reprova. */
    --cor-sob-ponteiro: var(--sup-hover);
    --cor-erro-fundo: var(--pastilha-rosa);
    /* ⚠️ A BORDA SEMÂNTICA PASSOU A SER A PRÓPRIA TINTA, e é decisão de TD-076
       §7, não economia: no ESCURO fio é textura (1,12-1,34:1) e NENHUM estado
       pode depender de cor de borda. Estes quatro `-borda` vestem a faixa
       esquerda de 4px dos painéis, que é o que carrega o significado — e faixa
       precisa passar em 3:1. Com a tinta do próprio matiz ela mede 4,96:1 no
       claro e 5,76:1 no escuro (erro), acima do piso de objeto gráfico. */
    --cor-erro-borda: var(--rosa);
    /* Mesma passagem: era #e11d48, que media 4,24:1 sobre --cor-erro-fundo e
       4,46:1 sobre --cor-fundo — reprovava nos dois. Com #c2103a mede 5,52:1 e
       5,81:1. O vermelho claro segue servindo BORDA e ÍCONE (--cor-erro-borda),
       onde o critério é 3:1 e não 4,5:1. */
    --cor-erro-texto: var(--rosa);
    --cor-sucesso-fundo: var(--pastilha-verde);
    --cor-sucesso-borda: var(--verde);
    /* ⚠️ O VERDE CANÔNICO DA CASA (`#15803d`) NÃO SOBREVIVE NUMA PASTILHA DA
       PRÓPRIA COR: 4,27:1, medido na calibragem de TD-076. Escurecido para
       `#0f5f2c` em `--verde`, ele mede 6,58:1 sobre `--pastilha-verde`. */
    --cor-sucesso-texto: var(--verde);

    /* =========================================================================
       TOKENS DA F6 — cota, prazo e download em partes
       =========================================================================
       Nenhum valor visual solto: cor, espaço e raio das peças novas saem daqui.
       O resto do arquivo ainda tem número cravado (ele entrou byte a byte do
       sistema antigo, TD-012 item 3) — tokenizar o legado é da F8, com o mesmo
       diff visual como critério de saída.

       ⚠️ CADA PAR DE COR ABAIXO FOI MEDIDO (WCAG 2.1, texto normal, AA = 4,5:1).
       O número está no comentário porque par não medido é par que reprova:
         · --cor-texto        sobre --cor-info-fundo ......... 13,1:1
         · --cor-aviso-texto  sobre --cor-aviso-fundo ........  5,6:1
         · --cor-erro-texto   sobre --cor-erro-fundo .........  5,5:1
         · --cor-neutro-texto sobre --cor-neutro-fundo .......  8,0:1
         · --cor-texto-suave sobre --cor-fundo .............. 5,0:1
       E os preenchimentos do medidor contra o trilho (componente, AA = 3:1):
         · --medidor-normal 4,8:1 · --medidor-aviso 4,0:1 · --medidor-critico 5,2:1 */

    /* Informação permanente, situação normal */
    --cor-info-fundo: var(--pastilha-acento);
    --cor-info-borda: var(--fio-2);

    /* Informação permanente que virou aviso (80 % da cota, reta final do prazo) */
    --cor-aviso-fundo: var(--pastilha-ambar);
    --cor-aviso-borda: var(--ambar);
    --cor-aviso-texto: var(--ambar);

    /* Fato consumado, sem ação possível (prazo encerrado) */
    --cor-neutro-fundo: var(--pastilha-neutra);
    --cor-neutro-borda: var(--fio-2);
    --cor-neutro-texto: var(--tinta-3);

    /* Medidor de progresso.
       ⚠️ `--medidor-aviso` E `--medidor-critico` PERDERAM OS VALORES PRÓPRIOS.
       Eles existiam porque o medidor é objeto gráfico (piso 3:1) e podia ser
       mais escuro que a tinta semântica; com a paleta nova a tinta já mede
       4,0:1 e 5,2:1 sobre o trilho, e dois valores para um significado é o
       defeito de DIVERGÊNCIA que o F7 existe para pegar. Agora é UM. */
    --medidor-trilho: var(--trilho-barra);
    --medidor-normal: var(--cor-acento);
    --medidor-aviso: var(--ambar);
    --medidor-critico: var(--rosa);

    /* Espaçamento em escala de 4 px e raios — usados pelas peças da F6 */
    --e-1: 4px;
    --e-2: 8px;
    --e-3: 12px;
    --e-4: 16px;
    --e-5: 20px;
    --raio-md: 12px;
    --raio-lg: 16px;
    --raio-pilula: 999px;

    /* ⚠️ O BOTÃO DEIXOU DE SER PÍLULA (TD-076 §5), E É QUEBRA DELIBERADA COM O
       VOCABULÁRIO ANTERIOR: é o que separa "console" de "página de festa".
       `--raio-tecla` são 9px e `--raio-peca` 14px, os dois degraus da direção B.
       ⚠️ `--raio-pilula` NÃO MORREU e não deve morrer: SELO continua pílula (selo
       não é botão), e a barra do medidor, o trilho do progresso e as peças do
       convite continuam lendo dele. Trocar os 14 consumidores de uma vez seria
       esquadrar a régua de progresso junto com o botão. */
    --raio-tecla: 9px;
    --raio-peca: 14px;

    /* =========================================================================
       CAMADA 2, GRUPO A — semânticos que TODA tela tem (T-0015, TD-045 item 1)
       =========================================================================
       Declarados aqui com os valores do PAINEL; cada `.visual-*` do convite
       SOBRESCREVE os mesmos nomes. É esta tabela que faz um só botão, um só
       cartão e um só campo servirem as duas peles sem que ninguém repinte
       componente compartilhado com hexadecimal na mão — o que hoje custava 71
       regras de tema.

       A pergunta que decide se um semântico entra aqui é uma só: "toda tela do
       produto tem isso?". SIM entra no `:root` e cada pele sobrescreve; NÃO
       (envelope, papel, ouro) é declarado só dentro de `.visual-*`. */

    /* A superfície de cartão. Era `#fff` literal em dezenas de regras; aqui ela
       ganha nome para que a pele possa trocá-la sem tocar em componente. */
    --cor-cartao: var(--sup-cartao);

    /* A coluna: fundo → superfície → cartão são TRÊS superfícies distintas.
       No painel a do meio é igual ao fundo; no convite ela é o papel.
       ⚠️ A DECLARAÇÃO ESCURA DELE SAIU, e a remoção é medida e não estética: os
       DOIS únicos consumidores de `var(--cor-superficie)` são `.tema-convite
       .topo` e `.tema-convite .palco`, e `.visual-classico`/`.visual-jardim`
       redeclaram o token nos dois. Ou seja, o `#221c30` do bloco escuro nunca
       pintou pixel nenhum — a família do convite não tem por onde ligar o modo
       escuro (o alternador só existe em `views/layouts/painel.php`). */
    --cor-superficie: var(--cor-fundo);

    /* ⚠️ LIMITE DE COMPONENTE — NÃO É COR DE TEXTO.
       Este hexadecimal é o `--cor-texto-suave` APOSENTADO como texto na
       passagem A: como texto ele reprova AA (3,97:1 sobre `--cor-neutro-fundo`).
       Quem o reencontrar num diff e concluir que a correção não foi aplicada
       está lendo o cargo errado: como LIMITE o critério da WCAG 1.4.11 é 3:1, e
       ele mede 4,53:1 sobre branco e 4,30:1 sobre `--cor-fundo` — passa com
       folga. A cor não saiu da paleta; saiu do CARGO.

       E a distinção que precisa ficar na declaração porque o nome não a carrega:
       `--cor-borda` é DECORATIVA (filete, separador de seção) e é ISENTA de
       limiar; limite de campo e de componente é ESTE token, com ≥ 3:1. Foi por
       essa linha não existir que `--cor-borda` virou borda de campo e chegou a
       1,21:1 — em SETE lugares, e não em cinco: a enumeração publicada estava
       curta e a Emenda 1 do design system a corrigiu (§7.5). Os sete, por
       SELETOR e nunca por número de linha, que envelhece em um dia:
       `.campo select` · `.campo input, .campo textarea` (o campo principal do
       painel, o que faltava) · `.acomp-lista input` · `.busca-input` ·
       `.detalhe-form input` · `.evento-aba` · `.foto-upload-campo
       input[type="file"]`.

       ESPESSURA 1px, A MESMA EM REPOUSO E EM FOCO (designer-visual): "traço
       fino em 4,53:1 lê como filete; traço grosso em 3,4:1 lê como caixa". Era
       1.5px com `--cor-borda`; o contraste subiu e a espessura desceu de
       propósito, e as regras de `:focus` só trocam a COR — a largura vem daqui,
       então as duas não têm como divergir.

       `.campo-checkbox` FICA DE FORA e continua em `--cor-borda`, com motivo
       medido: ali a borda não é o limite do controle — o controle é o
       `<input type="checkbox">` NATIVO, que o navegador desenha. A caixa em
       volta é contêiner de agrupamento e alvo de toque. A pergunta que decide o
       próximo caso: *a borda é a única coisa que diz "isto é um controle"?*
       Se sim, `--limite`; se o controle se identifica sozinho, `--cor-borda`.

       INVARIANTE DE ESTADO FINAL desta seção, verificável sem navegador:

           grep -c 'border: 1[.]5px solid var(--cor-borda)'  →  1

       e o único sobrevivente é o `.campo-checkbox`. Mais que 1 significa que um
       limite de componente voltou para o token decorativo.

       ⚠️ O `[.]` NÃO É ENFEITE — ELE É O QUE FAZ O COMANDO NÃO SE CONTAR.
       Escrito como `1.5px`, o padrão casaria esta própria linha de comentário e
       o invariante mediria 2 para sempre, com o segundo sendo a explicação do
       primeiro. `[.]` casa o ponto literal do CSS e NÃO casa a si mesmo, então
       a prosa fica de fora e o comando publicado é o comando que roda. É o
       mesmo defeito que estragou três contadores do design system (§7.6, a
       regra "nenhum contador publicado é o total cru de um grep cujo padrão
       case prosa") — escrito aqui na forma que o resolve.

       ⚠️ T-0031: O CARGO CONTINUA, O VALOR MUDOU. `--fio-controle` é o contorno
       de CAMPO da direção B e é o único token que praticamente não muda entre os
       modos — 4,49:1 no cartão claro e 4,30:1 no poço escuro —, porque ele
       precisa ser visto contra os dois extremos. `#7a7290` saiu inteiro da
       folha; a trava F2 (teto de 1 dono) absorve a saída sozinha. */
    --limite: var(--fio-controle);

    /* Foco: UM anel para o produto inteiro. `outline: none` sem substituto
       medido ≥ 3:1 é defeito, não estilo.
       ⚠️ O ANEL DEIXOU DE SER O ACENTO. Anel roxo vivo encostado num
       preenchimento roxo vivo mede 2,01:1 — reprova idêntico nos dois modos, e
       reprova justamente para quem o anel existe. `--anel` é o extremo da tinta
       (13,09:1 no cartão claro) e `--anel-folga` é o extremo do papel; quem
       precisa das duas faces usa as duas (`.tecla:focus-visible`). */
    --foco: var(--anel);
    --foco-largura: 2px;
    --foco-desvio: 2px;

    /* Elevação TINGIDA com a tinta do próprio visual, nunca preta: preto sobre
       papel tingido suja para cinza. `var()` dentro de custom property é
       substituída no PONTO DE USO, então um cartão dentro de `.visual-jardim`
       recebe a sombra verde sem que a escala seja escrita duas vezes.
       ⚠️ T-0031: ele LÊ o triplete da tinta em vez de repetir o valor dela. Era
       `42 36 56`, que é `#2a2438` — a tinta ANTIGA escrita numa segunda notação,
       e por isso invisível a qualquer varredura de hexadecimal. */
    --sombra-tinta: var(--tinta-1-rgb);

    /* A FORÇA sai da GEOMETRIA (T-0016, modo escuro). As três sombras continuam
       escritas UMA vez; o que muda por modo é a tinta e o alfa. Redeclarar
       `--elev-1..3` dentro do bloco escuro duplicaria a geometria em duas strings
       que vão divergir — é o mesmo defeito do âmbar com dois valores e dos dois
       `462px` de TD-045.
       ⚠️ `--sombra-a1: 0` NO ESCURO É DECISÃO, NÃO ESQUECIMENTO. `--elev-1` é o
       cartão em repouso, e no escuro ele já está separado por 1,14:1 de
       SUPERFÍCIE mais uma régua a 1,17:1. Sombra ali só sujaria a borda. Quem
       reencontrar o zero num diff e "consertar" para `.28` põe uma auréola cinza
       em todo cartão do produto. */
    --sombra-a1: 0.06;
    --sombra-a2: 0.10;
    --sombra-a3: 0.16;
    --elev-1: 0 1px 2px rgb(var(--sombra-tinta) / var(--sombra-a1)), 0 2px 6px rgb(var(--sombra-tinta) / var(--sombra-a1));
    --elev-2: 0 4px 14px rgb(var(--sombra-tinta) / var(--sombra-a2));
    --elev-3: 0 10px 30px rgb(var(--sombra-tinta) / var(--sombra-a3));

    /* O CABEÇALHO É O ÚNICO LUGAR QUE AINDA PRECISA DE SOMBRA NO ESCURO, e o
       motivo é de geometria e não de gosto: `.topo` é FIXO e passa POR CIMA do
       conteúdo enquanto se rola, então a superfície dele e a do cartão que passa
       por baixo são A MESMA — elevação por superfície não resolve. Token de
       componente, e não uma redeclaração de `.topo` dentro do bloco escuro: o
       bloco de modo contém EXCLUSIVAMENTE linhas `--token: valor`. */
    --elev-topo: var(--elev-1);

    /* -------------------------------------------------------------------------
       A ELEVAÇÃO DA PEÇA DO CONSOLE (T-0031) — o segundo token de componente
       -------------------------------------------------------------------------
       ⚠️ ELE EXISTE PARA NÃO MEXER EM `--elev-1`, E ISSO É O PONTO INTEIRO.
       `--sombra-a1: 0` no escuro é DECISÃO da T-0016, escrita duas regras acima
       com o aviso de que "consertar" o zero põe uma auréola em todo cartão do
       produto. Ela continua valendo para os 18 destinos que leem `--elev-1`.

       SÓ QUE A DIREÇÃO B DECIDIU O CONTRÁRIO PARA O CONSOLE, e por escrito, na
       §1 do demo aprovado: "no escuro o fio não separa (1,19:1); quem separa é o
       degrau de superfície MAIS a sombra, e por isso a sombra é profunda".
       MEDIDO POR MIM na tela servida, na pele escura, antes de escrever isto:
       `.cabine-cartao`, `.cabine-rail`, `.cabine-avisos`, `.cabine-risco` e os 14
       cartões de conta renderizavam `rgba(0,0,0,0)` — sombra declarada e alfa
       zero, ou seja, NADA —, e o que sobrava para separar era 1,15:1 de
       superfície contra a página e 1,12:1 de fio. A zona de risco era pior:
       1,08:1 contra o cartão que a hospeda.

       ENTÃO A ELEVAÇÃO VIRA TOKEN DE COMPONENTE, como `--elev-topo` já é. No
       claro ele É `--elev-1` — leitura, não cópia, então zero pixel muda na pele
       que o usuário aprovou. No escuro ele é a elevação de repouso do demo, com a
       geometria de lá: um fio de LUZ por dentro da aresta de cima (a peça se
       levanta), uma sombra de contato de 1px e uma sombra profunda com raio
       negativo, que é o que dá profundidade sem borrar a vizinhança.

       ⚠️ POR QUE NÃO `var(--elev-2)`, QUE SERIA UMA LINHA SÓ: `--elev-2` é o
       degrau de HOVER desta mesma peça (`.cabine-conta:hover`, `.admin-conta:hover`).
       Apontar o repouso para ele apagaria a diferença entre parado e sob o
       ponteiro — a escada teria dois degraus com a mesma altura. */
    --elev-cabine: var(--elev-1);

    /* Colunas. 32rem substitui os dois `max-width: 462px` que vinham copiados
       de um tema aposentado: 462 ÷ 16 = 28,875rem não está em escala nenhuma, e
       em `rem` a coluna acompanha quem aumenta a fonte do sistema (WCAG 1.4.4).
       Em 375px de viewport as duas larguras são recortadas pela tela — o
       convidado no celular não vê diferença. */
    --coluna-convite: 32rem;

    /* ⚠️ A MEDIDA DE LEITURA — 38rem (608px), e ela é o que separa "alargar o
       contêiner" de "ter desktop". Alargar a coluna para 1160px e deixar o
       parágrafo ocupar tudo produz linhas de 1128px: em 18px de Nunito são ~124
       caracteres, contra os 45–75 em que o olho não perde a volta da linha.
       608px em 18px dão ~67. Quem escreve bloco de TEXTO na página inicial usa
       esta medida; quem escreve GRADE (passos, benefícios) usa a largura toda —
       é essa distinção que faz a tela grande parecer tela grande. */
    --medida: 38rem;

    /* Movimento. `--mov-cena` é EXCEÇÃO DECLARADA: a diretriz da casa é
       150–300ms, e só o envelope abrindo passa disso, porque é o único momento
       teatral do produto. Nenhuma outra transição do sistema pode usá-la. */
    --mov-rapido: 160ms;
    --mov-medio: 240ms;
    --mov-cena: 650ms;
    --curva-padrao: cubic-bezier(0.4, 0, 0.2, 1);
    --curva-entrada: cubic-bezier(0, 0, 0.2, 1);
    --curva-saida: cubic-bezier(0.4, 0, 1, 1);

    /* Camadas. Nenhum `z-index` novo fora desta escala. */
    --z-ornamento: -1;
    --z-conteudo: 2;
    --z-cabecalho: 10;
    --z-capa: 20;

    /* =========================================================================
       AS DUAS FAMÍLIAS — Nunito no corpo, Space Grotesk no display (TD-076 §6)
       =========================================================================
       A segunda família é o que dá PERSONALIDADE TIPOGRÁFICA à direção B, e ela
       tem cargo estreito e declarado: DISPLAY (manchete, número grande),
       NÚMERO (tudo que é medida, com `tabular-nums`) e MICRO-RÓTULO (as
       maiúsculas espaçadas). Texto corrido continua em Nunito — trocar a fonte
       do corpo mudaria a leitura de 18 telas para ganhar nada.

       ⚠️ `--f-corpo` REPETE O QUE O `body` JÁ DECLARA, e repetir é o ponto: as
       peças que precisam VOLTAR para o corpo depois de um ancestral em display
       (é o caso de `.palco-meta` dentro da banda) precisam de um nome para pedir
       de volta. Sem ele, a volta seria a lista de fallback escrita à mão uma
       segunda vez — e as duas listas divergiriam no primeiro ajuste.

       ⚠️ A LISTA DE RESERVA IMPORTA MAIS DO QUE PARECE: as duas famílias vêm por
       webfont com `display=swap`, então o navegador PINTA NO RESERVA e troca
       depois. O reserva não é o caso raro — é o PRIMEIRO QUADRO DE TODA VISITA
       FRIA (a lição da tipografia medida na T-0021). Por isso o reserva do
       display é a Nunito, e não `sans-serif` genérico: o primeiro quadro fica
       com a fonte do produto em vez de com a fonte do aparelho. */
    --f-corpo: 'Nunito', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
    --f-display: 'Space Grotesk', 'Nunito', -apple-system, "Segoe UI", Arial, sans-serif;

    /* Tipo — oito degraus. O legado ainda tem 42 tamanhos cravados e
       arredondá-los para cá é da F8, com lista branca (arredondar MUDA pixels e
       por isso não é diff-limpo). O que entra a partir de agora usa a escala.
       `--fs-3` é o piso de campo: abaixo de 16px o iOS dá zoom sozinho. */
    --fs-1: 0.7rem;
    --fs-2: 0.85rem;
    --fs-3: 1rem;
    --fs-4: 1.125rem;
    --fs-5: 1.5rem;
    --fs-6: 1.8rem;
    --fs-7: 2.25rem;

    /* O oitavo degrau, que `design-system.md` §2.7 já especificava e o `:root`
       não declarava (achado do `designer-visual`, §A.3). Ele existe por UM
       motivo medido: a manchete da página inicial parava de crescer em 480px de
       viewport, porque `clamp(--fs-6, 7.5vw, --fs-7)` bate o teto quando
       7,5 % da largura chega a 36px — 7,5 % de 480 = 36. De 480 a 2560 a
       manchete tinha exatamente o mesmo tamanho, e é isso que fazia a página
       "parecer mobile" numa tela de 1600. Com `--fs-8` o teto passa a valer em
       682,7px e o valor em 375px NÃO MUDA (7,5 vw = 28,1 < 28,8, o mínimo
       vence). */
    --fs-8: 3.2rem;

    /* Entrelinha — os três degraus do design system (§2.7). `--lh-normal` é o
       1.6 que o `body` já aplica ao produto inteiro: o token não muda pixel
       nenhum, só dá NOME ao valor que já vigora, para que o que entra a partir
       de agora não volte a cravar número. */
    --lh-apertado: 1.25;
    --lh-normal: 1.6;
    --lh-solto: 1.75;

    /* Espaço — a mesma lei de N × 4px que a F6 já usava, com os degraus que
       faltavam. */
    --e-6: 24px;
    --e-8: 32px;
    --e-10: 40px;

    /* O degrau que a faixa de tinta pediu (T-0015, sub-etapa 6g). Ele NÃO é
       valor novo: é 16 × 4px, a mesma lei dos oito acima. Existe porque o maior
       degrau da escala eram 40px, e 40px de respiro vertical dentro de uma
       faixa que sangra de ponta a ponta lê como tarja, não como abertura — o
       recuo interno da faixa tem de ser MAIOR que o vão entre dois blocos
       quaisquer da página, que é justamente `--e-10`. */
    --e-16: 64px;

    --raio-sm: 8px;
    --raio-xl: 24px;
    --alvo-toque: 44px;

    /* O TEXTO BRANCO SOBRE SUPERFÍCIE ESCURA — o palco do painel e a capa do
       convite. O valor coincide com `--cor-cartao`, e a coincidência é de
       PALETA, não de cargo: ali `#ffffff` é SUPERFÍCIE de cartão, aqui é TINTA
       DE TEXTO sobre superfície escura. É a mesma distinção que o comentário de
       `--limite` faz três telas acima — a cor não sai da paleta, sai do cargo.
       Escrever `color: var(--cor-cartao)` faria a próxima pele escura herdar a
       cor do cartão dela como cor de texto.
       ⚠️ ELE NASCEU NA FAIXA DE TINTA DA PÁGINA INICIAL (T-0015, 6g), COM CINCO
       IRMÃOS — `--tinta`, `--tinta-cartao`, `--tinta-texto-suave`, `--quente`,
       `--confirmado-escuro` — e o teto `--brilho-alfa-max`. A T-0017 trocou a
       página pela vitrine (TD-082), que tem a paleta do arquivo do Stitch em
       tokens `--vitrine-*`; os seis ficaram sem consumidor nenhum na folha
       (contado em 2026-10-06) e saíram junto com a faixa. Este fica: tem
       dezessete consumidores fora dela (mesma contagem). */
    --tinta-texto: var(--branco);
    /* =========================================================================
       O CANHOTO — a banda da festa que abre o painel do dono (TD-076, T-0031)
       =========================================================================
       Direção: `demos/demo-painel-B-cabine.html`, do `designer-visual`, aprovada
       pelo usuário. SUBSTITUI a banda da direção A ("o palco", T-0016), e a
       substituição foi decisão explícita do usuário em 2026-09-05: deixar a
       banda como estava faria a tela ter DUAS identidades convivendo — e foi
       identidade misturada que abriu a T-0030.

       ⚠️ O PREFIXO CONTINUA `--palco-*` E AS CLASSES CONTINUAM `.palco-*`.
       Não é descuido: `Contrato_de_layout_test` prende `.palco-info`,
       `.palco-meta` e `.palco-titulo` por SELETOR, `Regua_na_tela_test` prende
       `.palco-farol-num` e `Tema_do_convite_test` prende `.palco-destinos` e
       `.palco-destino`. Renomear tudo para `canhoto-*` trocaria o vocabulário de
       27 classes e 6 asserções para não mudar um pixel — e este produto já
       registrou que renome puro é recusado (arbitragem T-0016). O OBJETO mudou
       de nome na prosa; o vocabulário do código fica.

       A TESE, e ela resolve UMA tensão: a banda é CELEBRAÇÃO e a direção B é
       CONTENÇÃO. O erro fácil seria escolher um dos dois. A saída não é o
       meio-termo: é trocar o MATERIAL. A banda deixa de ser superfície pintada e
       passa a ser um OBJETO — o canhoto, a metade do convite que fica com quem
       dá a festa. Tem papel, tem grão, tem um rasgo com duas mordidas nas bordas
       e uma linha picotada separando o que FICA (a festa e o número) do que SAI
       (o link do convite). O rasgo DIZ alguma coisa: ele explica, pela forma, a
       única ação que a tela tem.

       O QUE FOI APOSENTADO, com o motivo de cada um:
         · `--palco-3` E `--palco-brilho-alfa` — os três `radial-gradient` de
           brilho e o `linear-gradient` de três paradas. É a assinatura que
           TD-076 §4 aposentou. A superfície agora é CHAPADA, e o ganho é medido:
           sem gradiente não há banding, e o teto deixa de ser um canto e passa a
           ser a banda inteira (a de produção só chegava a 2,20:1 contra o papel
           escuro NUM canto; esta está a 1,93 em TODA a área).
         · `--palco-piso` — ele existia porque o degrau banda/página INVERTIA de
           sinal entre os modos, com a separação migrando para a ponta escura do
           gradiente. Sem gradiente não há duas pontas: `--palco-1` é o piso e o
           teto é `--palco-teto`. Régua sem gradiente para medir é régua sem
           trabalho.
         · `--palco-halo` E `--palco-halo-alfa` — sombra EXTERNA não pode existir
           aqui: `mask` recorta tudo que o elemento pinta, inclusive `box-shadow`
           externo, e o resultado seria uma sombra cortada nas mordidas. A
           profundidade vem de duas sombras INTERNAS (que a máscara preserva),
           mais o degrau e a silhueta.

       ⚠️ QUATRO TOKENS MUDAM COM A PELE; ONZE NÃO MUDAM COM NADA. A banda é um
       OBJETO IMPRESSO, e tinta impressa não troca com a luz da sala — é a mesma
       decisão que TD-076 §9 tomou para o QR. Por isso os invariantes moram SÓ
       aqui no `:root` e NÃO são repetidos no bloco escuro: se um dia aparecerem
       lá, alguém repintou à mão o que era pigmento. */

    /* AS DUAS SUPERFÍCIES DA BANDA.
       ⚠️ `--palco-1-rgb` SAIU JUNTO COM O HALO. Ele existia porque a sombra
       externa da banda consumia o MESMO roxo em `rgb(... / alfa)`, e o triplete
       era o que impedia o valor de ser escrito duas vezes. Sem halo — `mask`
       recorta sombra externa — sobrou UM consumidor, e triplete com um
       consumidor só é indireção sem trabalho. As duas sombras internas que
       ficaram são PRETAS (`rgb(0 0 0 / .22)` e `/ .65`), não são esta cor. */
    --palco-1: #3a1a78;                  /* 10,60:1 ABAIXO do papel */
    --palco-2: #4a2a91;                  /* selo, campo e trilho: degrau interno 1,27 */

    /* ⚠️ AS DUAS RÉGUAS — NUNCA TINTA. São o pixel mais claro que o grão produz
       sobre cada superfície (branco a .085). TODO par da banda foi medido contra
       ELAS, e não contra a cor chapada: medir contra a chapada é medir o caso
       fácil. Se alguém as pintar numa superfície, o teto vira piso e a medição
       perde o sentido. Mexeu na superfície ou no alfa do grão? Mede de novo. */
    --palco-teto:   #4b2d83;             /* teto de `--palco-1` · 10,14:1 contra o papel */
    --palco-teto-2: #593c9a;             /* teto de `--palco-2` */

    /* OS INVARIANTES DE MODO — pigmento, não pele. Cada valor está medido contra
       os DOIS tetos (`--palco-teto` no claro, `#5a40ab` no escuro), e o pior dos
       dois é o que manda. A tinta da banda continua sendo `--tinta-texto`, que já
       é o branco invariante da superfície de marca e tem teste guardando. */
    --palco-suave: #cfc2ea;              /* 6,27 no claro · 4,56 no escuro — AA nas duas */
    --palco-menta: #5fd39a;              /* 5,63 no claro · 4,09 no escuro — objeto gráfico (≥3) */

    /* ⚠️ NA BANDA, FIO É LUZ (alfa) E PREENCHIMENTO É TINTA (sólido).
       A divisão é MEDIDA e não estética: preenchimento em rgba compõe com o que
       estiver atrás, e `--palco-suave` sobre branco-a-.14 mede 4,26 no claro e
       3,23 no escuro — REPROVA nas duas. É a mesma classe de defeito que TD-076
       matou nas pastilhas ao torná-las sólidas. Fio é objeto gráfico (piso 3:1)
       e composto ele mede 4,36 e 3,50. */
    --palco-fio:   rgb(255 255 255 / 0.55);  /* contorno · 4,36 claro · 3,50 escuro */
    --palco-luz:   rgb(255 255 255 / 0.28);  /* o fio de luz do topo: 4,03:1 no escuro */
    --palco-toque: rgb(255 255 255 / 0.12);  /* hover do vazado · branco em cima 7,50 / 5,69 */

    /* A opacidade do grão. NÃO é enfeite isento: camada de ruído sobre superfície
       é o fundo real de cada glifo, e é ela que produz os dois `--palco-teto*`.
       Sobre superfície chapada ele não está lá para matar banding (não há banding
       sem gradiente) — está para o objeto ler como CARTÃO e não como div. */
    --palco-grao-alfa: 0.085;

    /* O raio do rasgo — as duas mordidas que fazem o canhoto ser canhoto. */
    --palco-mordida: 9px;

    /* ⚠️ ESTE TOKEN NÃO É COR, E ELE EXISTE PORQUE UMA TRAVA COBROU — o que é a
       trava funcionando. `mask-image` lê SÓ o canal ALFA da imagem: qualquer cor
       opaca produz exatamente o mesmo recorte, e o preto é a forma canônica de
       escrever "alfa 1" dentro de um gradiente. Escrito à mão, `#000` nas quatro
       declarações de máscara reprovava no F8 ("hexadecimal literal pintando
       propriedade normal") — e o F8 estava CERTO quanto à forma: quem carrega
       literal é token. Aqui o literal ganha nome, cargo e um lugar só, e a cerca
       volta a proteger de verdade: se alguém trocar isto por `#fff` amanhã, o
       recorte inverte e o token diz onde mexer.
       Ele é invariante de modo, de pele e de tudo: alfa não tem paleta. */
    --mascara-cheia: #000;

    /* =========================================================================
       AS ILHAS DE PAPEL — os quatro pigmentos INVARIANTES DE MODO da banda
       =========================================================================
       A banda é o único lugar do produto em que uma superfície CLARA vive dentro
       de uma superfície ESCURA: o bilhete de data e o botão "Copiar". Elas liam
       `--cor-cartao`/`--cor-texto`/`--cor-texto-suave`, que são semânticos DA
       PÁGINA — e semântico de página gira com o modo. Medido, e são três
       desfechos e nenhum aceitável:
         · os dois giram ....... o bilhete vira um buraco na banda (1,86:1) e a
                                 tinta sobre ele mede 1,03:1
         · só a tinta gira ..... 1,28:1 e 2,54:1 sobre papel branco
         · só a superfície gira. 1,03:1
       Com os pigmentos abaixo o bilhete continua sendo o que a anatomia diz que
       ele é — papel branco sólido — nos DOIS modos. É a peça que mata o
       BUG-TD-055, e ela não pode depender de qual modo está ligado.

       ⚠️ TRÊS DELES SÃO O MESMO HEXADECIMAL DE UM PIGMENTO DA PELE CLARA, E ISSO
       É DECLARADO. `#272039` é o valor de `--tinta-1` no claro, `#5c5470` o de
       `--tinta-3` e `#eceaf0` o de `--pastilha-neutra`. Escrevê-los como
       `var(--tinta-1)` seria mais bonito e ERRADO: os pigmentos da pele GIRAM com
       o modo, e no escuro o bilhete ficaria com tinta clara sobre papel branco.
       A coincidência é de PALETA, não de CARGO — a mesma distinção que
       `--tinta-texto` faz com `--cor-cartao` desde a T-0015. TD-076 revogou, no
       registro de travas, justamente a trava que proibia dois tokens com o mesmo
       valor: ela proibia esta correção.

       INVARIANTE, por SELETOR: os únicos consumidores destes quatro são
       `.palco-bilhete`, `.palco-bilhete-dia`, `.palco-bilhete-mes`,
       `.palco-btn-claro` e `.palco-btn-claro:hover`. Um sexto seletor lendo
       semântico de página DENTRO da banda é o defeito voltando. */
    --palco-papel: var(--branco);        /* contra o teto da banda 10,49 claro · 7,62 escuro */
    --palco-papel-tinta: #272039;        /* sobre o papel 15,53:1 */
    --palco-papel-suave: #5c5470;        /* sobre o papel 7,10:1 */
    --palco-papel-toque: #eceaf0;        /* o papel sob o dedo; a tinta nele dá 13,01:1 */

    /* =========================================================================
       O PAINEL DO DONO NO ARQUIVO DO STITCH (T-0038) — a família `--dono-*`
       =========================================================================
       A paleta do arquivo (`vibrant_rsvp_mobile_experience/DESIGN.md`) — a MESMA
       família da vitrine (`--vitrine-*`), que não alcança aqui porque é escopada
       em `.tema-vitrine`. Ela veste o cabeçalho e o rodapé de TODA tela de
       `layouts/painel` e o conteúdo das telas do dono (`.dono`).

       ⚠️ POR QUE NO `:root` E NÃO NUM ESCOPO DE CLASSE, como a vitrine: o
       cabeçalho e o rodapé desta família não têm ancestral comum com classe
       própria (`Tema::Painel` não emite classe no `<body>`, por contrato), e
       declarar a paleta três vezes — no topo, no rodapé e no `.dono` — seria
       três lugares para cada cor. É a mesma forma do `--palco-*`: um bloco no
       `:root` e as linhas que giram no `:root.modo-escuro`, nas regras de ouro
       daquele bloco (só token, nenhum token só no escuro, nenhum hexadecimal
       repetido dentro dele).

       PIGMENTOS (não giram com o modo): a banda da festa, o bilhete, os botões
       violeta e as sombras coloridas — superfície escura ou papel impresso em
       QUALQUER modo. PAPÉIS (giram): o resto, com o nome do trabalho que fazem.

       ⚠️ TRÊS HEXADECIMAIS COINCIDEM COM TOKENS DE OUTRO CARGO E ISSO É
       DECLARADO: `#3a1a78` (`--palco-1` claro), `#e9e5f2` (`--cor-fundo` claro)
       e `#006c44` (o verde do selo da vitrine). A coincidência é de PALETA, não
       de CARGO — `--palco-1` gira com o modo e o meio do degradê do arquivo não. */

    /* Pigmentos */
    --dono-palco-inicio: #27104d;
    --dono-palco-meio: #3a1a78;
    --dono-palco-fim: #1a0b36;
    --dono-noite: #1d1335;                   /* surface-dark */
    --dono-violeta: #6633ee;                 /* primary-container: o botão cheio */
    --dono-violeta-fundo: #4d00d3;           /* primary: o botão sob o ponteiro, o mês do bilhete */
    --dono-menta: #6ffcb5;                   /* secondary-fixed: destaque sobre a banda */
    --dono-menta-forte: #4fdf9b;             /* secondary-fixed-dim: o ponto da página pública */
    --dono-menta-tinta: #002112;             /* on-secondary-fixed: o ícone do aviso de sucesso */
    --dono-verde-papel: #006c44;             /* verde sobre papel branco, nos dois modos */
    --dono-erro-ponto: #ba1a1a;              /* o ponto de "recusados" sobre a banda */
    --dono-bilhete-tinta: #110b22;
    --dono-bilhete-ano: #6b647b;             /* 5,62:1 sobre o bilhete branco */
    --dono-palco-luz-roxa: rgb(102 51 238 / 0.2);
    --dono-palco-luz-rosa: rgb(171 0 165 / 0.2);
    --dono-palco-vidro-leve: rgb(255 255 255 / 0.05);
    --dono-palco-vidro: rgb(255 255 255 / 0.1);
    --dono-palco-vidro-forte: rgb(255 255 255 / 0.15);
    --dono-palco-vidro-sob: rgb(255 255 255 / 0.25);
    --dono-palco-picote: rgb(255 255 255 / 0.2);
    --dono-palco-ponto: rgb(255 255 255 / 0.4);
    --dono-palco-tinta-60: rgb(255 255 255 / 0.6);
    --dono-palco-tinta-70: rgb(255 255 255 / 0.7);
    --dono-palco-tinta-80: rgb(255 255 255 / 0.8);
    --dono-palco-pe: rgb(0 0 0 / 0.25);
    --dono-farol-fundo: rgb(29 19 53 / 0.8);
    --dono-menta-20: rgb(111 252 181 / 0.2);
    --dono-menta-15: rgb(111 252 181 / 0.15);
    --dono-menta-brilho: 0 0 12px rgb(95 211 154 / 0.6);
    --dono-sombra-palco: 0 25px 50px -12px rgb(0 0 0 / 0.25);
    --dono-sombra-bilhete: 0 8px 16px rgb(0 0 0 / 0.25);
    --dono-sombra-interna: inset 0 2px 4px rgb(0 0 0 / 0.05);
    --dono-sombra-papel: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
    --dono-sombra-tecla: 0 8px 20px -2px rgb(102 51 238 / 0.35);
    --dono-sombra-tecla-sob: 0 12px 28px -2px rgb(102 51 238 / 0.45);
    --dono-sombra-tecla-grande: 0 10px 26px -2px rgb(102 51 238 / 0.4);
    --dono-sombra-tecla-grande-sob: 0 14px 32px -2px rgb(102 51 238 / 0.5);
    --dono-sombra-salvar: 0 6px 20px rgb(77 0 211 / 0.35);
    --dono-sombra-salvar-sob: 0 8px 24px rgb(77 0 211 / 0.45);
    --dono-sombra-aba: 0 2px 8px rgb(102 51 238 / 0.25);

    /* Papéis — o claro */
    /* O papel do arquivo — e o ESPELHO do PHP desde a T-0038: `Tema::Painel`
       manda este valor para a barra do navegador (`corDaBarra`) e para o
       fundo do aplicativo instalado (`corDeFundo`), com teste comparando os dois
       lados. Mudou aqui, muda lá no mesmo commit. */
    --dono-fundo: #fdf7ff;
    --dono-sup-baixa: #f7f1ff;               /* surface-container-low */
    --dono-sup-baixa-60: rgb(247 241 255 / 0.6);
    --dono-sup-media: #f2ebfa;               /* surface-container */
    --dono-sup-alta: #ece6f4;                /* surface-container-high */
    --dono-sup-maxima: #e6e0ef;              /* surface-container-highest / surface-variant */
    --dono-sutil: #e9e5f2;                   /* surface-subtle: filetes e o chip "opcional" */
    --dono-perigo-zona: rgb(236 230 244 / 0.6);
    --dono-cartao: var(--branco);            /* surface-container-lowest */
    --dono-borda-cartao: rgb(229 225 238 / 0.6);
    --dono-borda-cartao-cheia: #e5e1ee;      /* card-border */
    --dono-tracejado: #cac3d9;               /* outline-variant: os pontos e o tracejado da foto */
    --dono-texto-forte: #110b22;             /* text-primary-dark */
    --dono-texto: #1c1a24;                   /* on-surface */
    --dono-texto-medio: #494456;             /* on-surface-variant */
    --dono-texto-suave: #6b647b;             /* text-muted: 5,34 no papel · 5,08 no -low · 4,54 no "opcional" */
    --dono-roxo: var(--dono-violeta-fundo);  /* primary como TINTA */
    --dono-roxo-sob: var(--dono-violeta);    /* o preenchimento roxo sob o ponteiro */
    --dono-roxo-10: rgb(77 0 211 / 0.1);
    --dono-pastilha-roxa: #e7deff;           /* primary-fixed */
    --dono-pastilha-roxa-sob: #ccbeff;       /* primary-fixed-dim */
    --dono-tinta-roxa: #1f0060;              /* on-primary-fixed */
    --dono-verde: var(--dono-verde-papel);   /* o ajuste AA da vitrine: #006c44, não o #138855 do arquivo */
    --dono-verde-10: rgb(0 108 68 / 0.1);
    --dono-aviso-linha: #005233;             /* on-secondary-fixed-variant: 8,60:1 sobre a pastilha verde */
    --dono-pastilha-verde: #e8faf2;          /* badge-success-bg */
    --dono-pastilha-menta: var(--dono-menta);
    --dono-menta-30: rgb(111 252 181 / 0.3);
    --dono-tinta-menta: #007349;             /* on-secondary-container */
    --dono-rosa: #83007e;                    /* tertiary */
    --dono-rosa-vivo: #ab00a5;               /* tertiary-container */
    --dono-rosa-10: rgb(171 0 165 / 0.1);
    --dono-erro: var(--dono-erro-ponto);     /* error */
    --dono-erro-sob: #ffdad6;                /* error-container */
    --dono-erro-sob-tinta: #93000a;          /* on-error-container */
    --dono-erro-10: rgb(186 26 26 / 0.1);
    --dono-erro-40: rgb(255 218 214 / 0.4);
    --dono-erro-cheio-tinta: var(--branco);
    --dono-luz-roxa: rgb(231 222 255 / 0.3);
    --dono-luz-menta: rgb(111 252 181 / 0.2);
    --dono-sombra-topo: 0 1px 8px rgb(29 19 53 / 0.03);
    --dono-sombra-rodape: 0 -1px 8px rgb(29 19 53 / 0.02);
    --dono-sombra-cartao: 0 8px 24px -4px rgb(29 19 53 / 0.06), 0 2px 6px -1px rgb(29 19 53 / 0.04);
    --dono-sombra-secao: 0 4px 20px -2px rgb(29 19 53 / 0.05), 0 1px 4px rgb(29 19 53 / 0.03);
    --dono-sombra-leve: 0 1px 2px rgb(0 0 0 / 0.05);
    --dono-sombra-media: var(--dono-sombra-papel);

    /* Letra, escala e medidas do arquivo (DESIGN.md) */
    --dono-letra: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
    --dono-icones: 'Material Symbols Outlined';
    --dono-titulo-xl: 2.5rem;                /* 40px — headline-xl */
    --dono-titulo-lg: 1.75rem;               /* 28px — headline-lg */
    --dono-titulo-md: 1.25rem;               /* 20px — headline-md */
    --dono-titulo-sm: 1.0625rem;             /* 17px — headline-sm */
    --dono-corpo-lg: 1rem;                   /* 16px — body-lg */
    --dono-corpo-md: 0.875rem;               /* 14px — body-md */
    --dono-corpo-sm: 0.8125rem;              /* 13px — body-sm e label-md */
    --dono-miudo: 0.75rem;                   /* 12px — text-xs */
    --dono-rotulo: 0.6875rem;                /* 11px — label-sm */
    --dono-topo-altura: 5rem;                /* o cabeçalho de 80 px */
    --dono-largura: 80rem;                   /* max-w-7xl */

    /* A raiz declara o esquema do documento. O motivo de isto morar no
       elemento RAIZ está no bloco do modo escuro, logo abaixo. */
    color-scheme: light;
}

/* =============================================================================
    O MODO ESCURO - e ele e UM BLOCO, com UM lugar por par (token, modo)
   =============================================================================
   Decisao do usuario (TD-048, 2026-08-21): A PRIMEIRA VISITA E SEMPRE CLARA.
   Quem abre o sistema com o aparelho no escuro ve o claro uma vez e aperta o
   botao; a escolha fica no cookie `td_modo` e vale dai em diante. NAO existe
   `prefers-color-scheme` decidindo nada nesta folha, e a razao e estrutural:
   seguir o sistema na primeira visita exige a paleta escura escrita em DOIS
   lugares - `@media (prefers-color-scheme: dark) { :root:not(.modo-claro) }`
   MAIS `:root.modo-escuro` -, ~35 declaracoes duplicadas em blocos distantes,
   que e a forma exata do defeito "dois valores para o mesmo nome" que este
   produto ja pagou tres vezes. Aqui o bloco escuro existe UMA vez.

   A CLASSE VAI NO <html> E NAO NO <body>, E O MOTIVO SAO PIXELS QUE NINGUEM
   DESENHA. `color-scheme` so pinta os controles NATIVOS, a barra de rolagem e o
   canvas a partir do elemento RAIZ. Este produto e feito de controle nativo -
   date, time, number, select, checkbox, radio, file, <progress>, <details> -, e
   a tela de criar evento sozinha usa oito deles. Sem `color-scheme: dark` na
   raiz, o seletor abre um menu branco e o calendario abre branco dentro de uma
   pagina quase preta. E o defeito mais visivel que um modo escuro pode ter e ele
   nao aparece em captura de tela nenhuma. Por isso este bloco NAO usa `body.` e
   por isso a classe de modo nao sai de `Pagina::classesDoBody()`: modo e
   atributo do DOCUMENTO, nao da pagina.

   O CONVITE NAO ENTRA, E ISSO E ESTRUTURA E NAO DISCIPLINA: o alternador so
   existe em `views/layouts/painel.php`, entao `layouts/publico` NAO TEM ONDE
   ligar o modo escuro. Nenhuma regua do convidado dobra.

   ESTE BLOCO CONTEM EXCLUSIVAMENTE LINHAS `--token: valor`, como o bloco de um
   `.visual-*`. Uma `color:` ou um `padding:` aqui dentro significa que uma peca
   foi repintada a mao em vez de ler a camada 2 - e essa peca vai divergir.

   A REGUA DE OITO PARES, medida no escuro ANTES do primeiro pixel
   (docs/modo-escuro.md §1) e REFEITA para a pele da direcao B (TD-076), que
   trocou os oito valores sem trocar UMA regra:
     1. tinta sobre papel ......... #f4f3f7 / #17131f ...... 16,54:1  (piso 4,5)
     2. secundaria sobre papel .... #a89cc3 / #17131f .......  7,14:1  (piso 4,5)
     3. secundaria sobre cartao ... #a89cc3 / #241f32 .......  6,23:1  (piso 4,5)
     4. secundaria sobre aviso .... #a89cc3 / #392f36 .......  5,44:1  (piso 4,5)
     5. texto na marca ............ #ffffff / #db2777 .......  4,60:1  (piso 4,5)
     6. borda de campo ............ #7b719b / #241f32 .......  3,55:1  (piso 3,0)
     7. anel de foco .............. #f4f3f7 / pagina e cartao 16,54 e 14,43:1
     8. medidor sobre o trilho .... #b3a1ff / #373244 .......  4,84:1  (piso 3,0)

   A TRAVA DE MEDICAO INVERTE AQUI: no claro a superficie de referencia e a mais
   ESCURA; no escuro e a mais CLARA. Os pares 3 e 4 sao medidos contra o cartao e
   contra o fundo de aviso justamente por isso - medir a secundaria so contra a
   pagina (7,14:1) seria repetir, de cabeca para baixo, o erro de medir contra a
   superficie que perdoa.

   =============================================================================
    ⚠️ O QUE ESTE BLOCO DEIXOU DE PRECISAR ESCREVER (T-0031)
   =============================================================================
   Ele tinha 33 linhas e passou a ter as da CAMADA 1. A camada 2 quase inteira
   SUMIU daqui, e nao por descuido: `var()` dentro de custom property e
   substituida NO PONTO DE USO, entao `--cor-texto: var(--tinta-1)` declarado uma
   unica vez no `:root` ja entrega a tinta CLARA quando esta classe esta ligada.
   Redeclarar cada semantico aqui seria escrever a mesma indirecao duas vezes -
   dois lugares para um par, que e exatamente o que este bloco existe para nao
   ter.

   TRES EXCECOES, e cada uma tem motivo verificavel:
     · `--cor-fundo` carrega LITERAL nos dois modos porque tem espelho em PHP
       (`Tema::corDaBarra(Escuro)`), e espelho compara STRING.
     · `--cor-acento` e redeclarado aqui de proposito: e a prova, cobrada por
       `Contrato_do_modo_de_cor_test`, de que a marca como TINTA gira e a marca
       como PREENCHIMENTO nao.
     · `--sombra-*` e `--elev-topo` sao numeros de elevacao, nao cor, e nao tem
       pigmento de onde ler.
   ============================================================================= */
:root.modo-escuro {
    color-scheme: dark;

    /* =========================================================================
       CAMADA 1 — A PELE ESCURA, "A CABINE"
       =========================================================================
       AS SUPERFICIES. A pagina NAO e preta: #000 com texto claro produz halo
       severo e cansaco em uso longo, que e literalmente a queixa que abriu a
       T-0016. E ela e tingida de ROXO, nao cinza - o produto continua
       reconhecivel com a luz apagada. Mais alto = mais claro, como no claro:
       ELEVAR E SEMPRE CLAREAR. */
    --moldura:    #0f0d14;          /* o carvao: o extremo ESCURO da escala */
    --cor-fundo:  #17131f;          /* o papel (camada 2, mas com o literal aqui) */
    --sup-cartao: #241f32;          /* 1,15:1 acima do papel */
    --sup-hover:  #2a233a;          /* interacao anda para a tinta: CLAREIA */
    --sup-press:  #302842;

    /* ⚠️ TRES TOKENS LEEM `--moldura` EM VEZ DE REPETIR `#0f0d14`, e a leitura
       nao e economia de digitacao: e a regra "um lugar por par (token, modo)",
       cobrada por teste. Os TRES sao cargos DISTINTOS (TD-076 quebrou o antigo
       `--chassi` em quatro nomes justamente porque no claro eles vao para lados
       opostos: `#f3f0fa`, `#ffffff` e `#ffffff`). Aqui os tres calham no MESMO
       ponto da escala, que e o extremo escuro - e o extremo escuro tem UM nome,
       que e a moldura. Quem quiser separa-los de novo declara o literal e o
       teste avisa. */
    --sup-campo:  var(--moldura);   /* o poco AFUNDA abaixo do cartao */
    --tinta-viva: var(--moldura);   /* a tinta em cima de preenchimento vivo */
    --anel-folga: var(--moldura);

    /* AS TINTAS. As margens do escuro sao MAIORES que as do claro de proposito:
       texto claro sobre fundo escuro perde definicao por halo, e o minimo da
       WCAG foi calibrado em condicoes que nao modelam esse efeito. Onde a norma
       da 4,5, aqui se entrega 6. Nao "otimize" isto depois.
       Medidas sobre moldura · papel · cartao · pressionado. */
    --tinta-1: #f4f3f7;             /* 16,54 · 14,43 · 13,58 · 12,61 */
    --tinta-2: #c8c1d9;             /* 10,52 ·  9,18 ·  8,63 ·  8,02 */
    --tinta-3: #a89cc3;             /*  7,14 ·  6,23 ·  5,86 ·  5,44 */

    /* ⚠️ NO ESCURO FIO E TEXTURA, NAO INFORMACAO (TD-076 §7), e a consequencia
       de projeto e dura: NENHUM ESTADO PODE DEPENDER DE COR DE BORDA aqui. Quem
       separa e o degrau de superficie mais a sombra, e e por isso que a sombra
       deste modo e profunda. `--fio-controle` NAO entra neste bloco: ele e o
       unico token que praticamente nao muda entre os modos, porque precisa ser
       visto contra os DOIS extremos (4,49 no cartao claro, 3,55 aqui). */
    --fio-1: #2e2740;               /* 1,19:1 */
    --fio-2: #3a3350;               /* 1,42:1 */
    --fio-pendente: #8677ab;        /* o tracejado "ainda nao aconteceu": 3,98:1 */

    /* O ACENTO. Ele responde por DOIS pares e passa nos dois: tinta escura em
       cima dele (8,69:1) e ele como tinta sobre o cartao. Hover e PRESSIONADO
       andam na direcao da tinta - no escuro, isso e mais LUZ. */
    --acento:       #b3a1ff;
    --acento-forte: #c7baff;        /* hover: mais presenca (10,93:1) */
    --acento-fundo: #9d8cff;        /* pressionado: afunda (7,01:1) */

    /* AS SEMANTICAS COMO PIGMENTO. Cada uma inverte do mesmo jeito: a pastilha
       vira uma superficie escura tingida do matiz e a tinta vira um tom claro do
       mesmo matiz. `--rosa-solido` NAO e `--rosa`: no destrutivo confirmado a
       tinta em cima e escura, e branco sobre `#ff8fa0` daria 2,99:1. */
    --verde: #5fd39a;  --pastilha-verde:  #2c3640;   /* 6,60:1 */
    --ambar: #f5c05e;  --pastilha-ambar:  #3f3438;   /* 7,15:1 */
    --rosa:  #ff8fa0;  --pastilha-rosa:   #402e40;   /* 5,76:1 */
    --rosa-forte: #ffb3be;
    --rosa-solido: #ff5c72;         /* tinta escura em cima: 6,46:1 */
    --pastilha-neutra: #352f45;     /* 4,99:1 */
    --pastilha-acento: #37304d;     /* 5,59:1 */

    /* O ANEL vai ao extremo da tinta, como no claro - so que o extremo virou o
       outro lado. Ele LE `--tinta-1` pelo mesmo motivo dos tres da moldura. */
    --anel: var(--tinta-1);

    --tecla-fantasma:       #2d293b;
    --tecla-fantasma-hover: #3c364b;
    --tecla-fantasma-off:   #2b2639;
    --tecla-perigo:         #3a2a3d;
    --tecla-perigo-hover:   #50364c;

    --fundo-aviso:   #392f36;
    --fundo-recibo:  #272837;
    --fundo-risco:   #312336;
    --fundo-risco-2: #462e41;
    --fundo-fila:    #282336;

    /* `--listra-forte` NAO entra: ele le `var(--ambar)` no `:root` e a leitura
       resolve no ponto de uso, entao ele ja acompanha o modo sozinho. */
    --listra-fraca: #604c2e;        /* 4,90:1 entre as duas listras */
    --trilho-barra: #373244;
    --marca-barra:  #524e5d;

    /* OS DOIS CAMPOS DE COR. No escuro a sala tem LUZ: os dois brilhos CLAREIAM
       o papel, ao contrario do claro, onde a mesma luz vira tinta. */
    --campo-1: radial-gradient(900px 520px at 8% -6%, rgba(255, 232, 205, 0.035), transparent 62%);
    --campo-2: radial-gradient(820px 640px at 104% 106%, rgba(124, 58, 237, 0.12), transparent 60%);

    /* AS QUATRO LINHAS DA BANDA que a pele escura tem direito de escrever. Se um
       dia aparecer aqui um `--palco-suave` ou um `--palco-papel*`, o objeto
       deixou de ser impresso e virou pintado. */
    --palco-1: #4b2ea3;                  /* 1,93:1 ACIMA do papel */
    --palco-2: #5b3fb8;                  /* degrau interno 1,26 - o MESMO do claro (1,27) */
    --palco-teto:   #5a40ab;             /* 2,40:1 contra o papel */
    --palco-teto-2: #694fbe;

    /* =========================================================================
       CAMADA 2 — as DUAS excecoes, e o porque de nao haver mais nenhuma
       =========================================================================
       `--cor-primaria` NAO ENTRA AQUI, e e o par que prova a divisao de cargo:
       ela e PREENCHIMENTO e responde por "branco sobre ela" (5,70:1), que nao
       depende do fundo da pagina. Quem muda e a marca como TINTA. */
    --cor-acento: var(--acento);    /* pagina 9,26:1 · cartao 8,08:1 · trilho 4,84:1 */

    /* ELEVACAO. A hierarquia NUNCA dependeu da sombra: elevacao e SUPERFICIE, e a
       sombra e reforco que so existe onde ha luz para tirar. Claro: 1,24:1 entre
       cartao e pagina. Escuro: 1,15:1. A mesma separacao, pelo mesmo canal. A
       tinta vira preta porque no escuro nao ha papel tingido embaixo para o preto
       sujar - a §6.5 do designer sobrevive inteira, aplicada ao contrario. E os
       alfas SOBEM: no claro o fio separa e a sombra recua; aqui o fio e textura e
       a sombra e que faz o trabalho. */
    --sombra-tinta: 0 0 0;
    --sombra-a1: 0;
    --sombra-a2: 0.45;
    --sombra-a3: 0.65;
    --elev-topo: var(--elev-2);

    /* A elevacao de repouso da peca do console, e a UNICA sombra que esta pele
       escreve com geometria propria. O porque inteiro esta na declaracao do
       token no `:root`; aqui ficam as tres camadas, que sao as do demo aprovado:
       fio de LUZ na aresta de cima, contato de 1px, e a profunda de raio
       negativo. Os alfas sao numeros e nao pigmento — a tinta continua vindo de
       `--sombra-tinta`, que nesta pele e preta. */
    --elev-cabine:
        inset 0 1px 0 rgb(255 255 255 / 0.05),
        0 1px 1px rgb(var(--sombra-tinta) / 0.5),
        0 10px 24px -14px rgb(var(--sombra-tinta) / 0.85);

    /* =========================================================================
       O PAINEL DO DONO NO ARQUIVO DO STITCH (T-0038) — o que gira no escuro
       =========================================================================
       O arquivo não desenha o escuro; ele é DERIVADO da paleta escura da vitrine
       (`:root.modo-escuro .tema-vitrine`), valor por valor onde a peça existe
       lá. Os pigmentos (banda, bilhete, botão violeta) NÃO entram aqui. Pares
       calculados pela fórmula da WCAG sobre o cartão `--dono-noite` (T-0038):
       texto 15,48:1 · médio 10,29:1 · suave 8,59:1 (7,08:1 no pior papel,
       `--dono-sup-maxima`) · roxo 10,34:1 · verde 10,33:1 · erro 10,33:1. */
    --dono-fundo: #110b22;                   /* espelho de Tema::Painel->corDaBarra(Escuro) */
    --dono-sup-baixa: #171030;
    --dono-sup-baixa-60: rgb(23 16 48 / 0.6);
    --dono-sup-media: #1a1236;
    --dono-sup-alta: #241a42;
    --dono-sup-maxima: #2c2250;
    --dono-sutil: var(--dono-sup-maxima);
    --dono-perigo-zona: rgb(36 26 66 / 0.6);
    --dono-cartao: var(--dono-noite);
    --dono-borda-cartao: rgb(255 255 255 / 0.08);
    --dono-borda-cartao-cheia: rgb(255 255 255 / 0.12);
    --dono-tracejado: rgb(202 195 217 / 0.35);
    --dono-texto-forte: var(--branco);
    --dono-texto: #f5eefd;
    --dono-texto-medio: #cac3d9;
    --dono-texto-suave: #b9b2ca;
    --dono-roxo: #ccbeff;
    --dono-roxo-sob: var(--dono-tinta-roxa);
    --dono-roxo-10: rgb(102 51 238 / 0.26);
    --dono-pastilha-roxa: rgb(102 51 238 / 0.32);
    --dono-pastilha-roxa-sob: rgb(102 51 238 / 0.4);
    --dono-tinta-roxa: #e7deff;
    --dono-verde: var(--dono-menta-forte);
    --dono-verde-10: rgb(79 223 155 / 0.14);
    --dono-aviso-linha: var(--dono-texto);
    --dono-pastilha-verde: rgb(38 194 129 / 0.16);
    --dono-pastilha-menta: rgb(38 194 129 / 0.2);
    --dono-menta-30: rgb(38 194 129 / 0.2);
    --dono-tinta-menta: var(--dono-menta);
    --dono-rosa: #ffabef;
    --dono-rosa-vivo: var(--dono-rosa);
    --dono-rosa-10: rgb(196 40 187 / 0.24);
    --dono-erro: #ffb4ab;
    --dono-erro-sob: rgb(255 180 171 / 0.16);
    --dono-erro-sob-tinta: #ffdad6;
    --dono-erro-10: rgb(255 180 171 / 0.14);
    --dono-erro-40: var(--dono-erro-sob);
    --dono-erro-cheio-tinta: #690005;
    --dono-luz-roxa: rgb(102 51 238 / 0.18);
    --dono-luz-menta: rgb(38 194 129 / 0.1);
    --dono-sombra-topo: 0 1px 0 rgb(255 255 255 / 0.07);
    --dono-sombra-rodape: 0 -1px 0 rgb(255 255 255 / 0.05);
    --dono-sombra-cartao: 0 0 0 1px rgb(255 255 255 / 0.08);
    --dono-sombra-secao: var(--dono-sombra-cartao);
    --dono-sombra-leve: var(--dono-sombra-cartao);
    --dono-sombra-media: 0 0 0 1px rgb(255 255 255 / 0.14), 0 8px 20px -6px rgb(0 0 0 / 0.5);
}


html {
    -webkit-text-size-adjust: 100%;
}

/* ⚠️ `background-color` E `background-image` VÊM SEPARADOS, E NÃO É ESTILO — é a
   mesma separação que a abertura da página inicial da T-0015 fazia: com o atalho `background`,
   um navegador que falhe a imagem entrega a página sem cor de fundo nenhuma.
   Os dois campos de cor (`--campo-1`, `--campo-2`) são a "sala" da direção B: no
   ESCURO eles CLAREIAM o papel (a sala tem luz) e no CLARO eles o ESCURECEM (a
   mesma luz sobre branco seria branco, então ela vira tinta). Medido: o degrau
   do cartão sobe de 1,24 para 1,29 no canto quente e 1,39 no violeta — no claro
   o campo de cor AJUDA a separação, que é o oposto do que ele faz no escuro.
   ⚠️ A FAMÍLIA DO CONVITE NÃO OS RECEBE: `.tema-convite` declara `background:`
   no atalho, e atalho ZERA `background-image`. A proteção é estrutural, não
   disciplina. E nada de `background-attachment: fixed`, que é proibido nesta
   folha com bug pago. */
body {
    font-family: var(--f-corpo);
    background-color: var(--cor-fundo);
    background-image: var(--campo-1), var(--campo-2);
    background-repeat: no-repeat;
    color: var(--cor-texto);
    line-height: 1.6;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    -webkit-tap-highlight-color: transparent;
}

.container {
    width: 100%;
    max-width: 560px;
    margin: 0 auto;
    padding: 0 16px;
}

/* -----------------------------------------------------------------------------
   A COLUNA DE LEITURA — a medida de leitura, e SÓ ela
   -----------------------------------------------------------------------------
   ELE MORA AQUI, ENTRE OS PRIMITIVOS DE LEIAUTE, E NÃO NA SEÇÃO DA PÁGINA
   INICIAL. O motivo é a §13.7: a segunda tela que precisar de coluna de leitura
   (a T-0016 vai precisar) tem de ACHAR esta classe, e não reinventá-la dentro da
   própria família — foi assim que a medida se espalhou por seis seletores.

   ⚠️ ELE JÁ TEVE UM `margin-inline: auto`, E ELE FOI REMOVIDO DEPOIS DE MEDIDO
   NA TELA. Vale escrever por que, porque o erro é sedutor e vai tentar voltar.
   A §13 raciocinou sobre EIXO — o centro matemático da caixa — e concluiu que
   centrar todas as caixas no mesmo centro acabaria com o desalinho. Acabou com o
   desalinho do CENTRO e criou um pior: o que o olho segue ao descer uma página
   em português é a BORDA ESQUERDA, e centrar caixas de larguras diferentes num
   mesmo centro serrilha as DUAS bordas. Medido pelo Coordenador no navegador:

       borda esquerda ANTES da §13:  185 185 185 185 185 185 185 185 445  (1 salto)
       borda esquerda COM a §13:     185 445 445 185 445 185 445 445 445  (5 saltos)

   Uma página pode ter um único centro e mesmo assim ziguezaguear dos dois lados
   — foi exatamente o que aconteceu, e o usuário reprovou a tela pela segunda
   vez. Pior ainda: os `<h2>` das duas grades ficavam em 185 e os blocos que eles
   encabeçam em 445, o título a 260px do próprio conteúdo.

   O QUE VALE AGORA: **UMA BORDA ESQUERDA, DUAS LARGURAS.** Toda caixa começa em
   185; a coluna termina em 793 e a faixa em 1313. A direita fica serrilhada, e
   isso NÃO é defeito — é a borda solta de uma composição alinhada à esquerda, a
   mesma que todo parágrafo deste arquivo tem.

   COMO SE USA, e a escolha é EXPLÍCITA no HTML: quem tem a classe é COLUNA (a
   medida de leitura); quem não tem é FAIXA (a largura toda do contêiner).
   Nenhum bloco escolhe por omissão. Uma página declara no máximo essas duas
   larguras; uma terceira exige ADR (§13.5).

   ⚠️ NÃO REDECLARE A MEDIDA NUM SELETOR DE COMPONENTE. A trava L1 da §13.5
   conta as declarações ancoradas da medida na folha inteira e exige UMA — esta.
   Duas significam que a medida está se espalhando de novo.

   E É POR ISSO QUE A REGRA TEM UMA LINHA SÓ: a trava L3 conta o corpo desta
   regra e espera EXATAMENTE 1. Se aparecer 2, alguém devolveu o eixo centrado.
   -------------------------------------------------------------------------- */
.coluna-leitura {
    max-width: var(--medida);
}

/* -----------------------------------------------------------------------------
   O CABEÇALHO — CHAPADO, E O MOTIVO ESTÁ MEDIDO
   -----------------------------------------------------------------------------
   ⚠️ ESTA REGRA JÁ TEVE `backdrop-filter: blur(8px)` E UM FUNDO A 92% DE ALFA.
   Vale escrever por que os dois saíram juntos, porque o par é sedutor e volta.

   O DESFOQUE É PROIBIDO NESTE PROJETO, e a proibição foi paga com bug: ele gera
   uma caixa branca fantasma no Chromium do usuário e trava a captura de tela.
   A folha desligava o desfoque em UMA pele (`.tema-convite .topo`) e o deixava
   ligado na REGRA BASE — ou seja, ligado na página inicial, no login, no
   cadastro, nos termos, no painel do dono e no admin. Desligar por pele nunca
   foi conserto: o conserto é a declaração não existir.

   E O ALFA SAIU JUNTO, QUE É A PARTE QUE SE ESQUECE. Os 92% só faziam sentido
   ALIMENTANDO o desfoque; sem ele, o que passa por baixo aparece NÍTIDO a 8%.
   Este cabeçalho é `sticky`, então em toda página com rolagem passa conteúdo
   por baixo dele. Medido (composição alfa sobre `--cor-fundo` #faf8ff):

     em repouso ...................... rgb(254,6 254,4 255)  = #fffeff
     com texto #2a2438 por baixo ..... #eeedef   ΔE*ab 5,87
     com foto escura por baixo ....... #ebebeb   ΔE*ab 6,93
     com a ponta rosa #db2777 ........ #fceef4   ΔE*ab 7,45
     com a ponta roxa #7c3aed ........ #f5effe   ΔE*ab 8,60

   O limiar do olho é ΔE*ab ≈ 2,3. Ou seja: o cabeçalho mudaria de cor entre
   2,5x e 3,7x o perceptível, ACOMPANHANDO a rolagem — uma mancha que anda. Com
   borda nítida, isso não lê como profundidade; lê como sujeira.

   POR QUE `--cor-cartao` E NÃO `--cor-superficie`: em repouso o translúcido de
   hoje compõe #fffeff, que dista ΔE*ab 0,335 de `--cor-cartao` (#ffffff) — um
   sétimo do limiar, invisível — e ΔE*ab 3,87 de `--cor-superficie` (#faf8ff no
   painel), que é visível E apagaria a distinção entre o cabeçalho e a página.
   Chapado em `--cor-cartao` é o único valor que preserva o que está na tela.

   O QUE SUBSTITUI A PROFUNDIDADE: `--elev-1`, permanente. A sombra dá ao
   cabeçalho a fronteira física que o desfoque fingia dar — sem JavaScript, sem
   o bug, e com a tinta certa em cada pele (`--sombra-tinta` resolve no uso).
   É a correção escrita em docs/painel-e-desktop.md §D.1.
   -------------------------------------------------------------------------- */

.topo {
    background: var(--cor-cartao);
    border-bottom: 1px solid var(--cor-borda);
    box-shadow: var(--elev-topo);
    padding: 14px 0;
    position: sticky;
    top: 0;
    z-index: 10;
}

.topo-flex {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

/* Cabeçalho mínimo (páginas públicas do convidado) */
.topo-centro {
    justify-content: center;
}

.logo {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
}

/* A altura da marca é DERIVADA, não escolhida: 36 px é o piso medido em
   docs/marca.md §5.1, por dois caminhos independentes — (1) a espessura do
   contorno do balão é A/24 e precisa de ≥ 1,5 px para uma diagonal não virar
   névoa cinza; (2) o visto precisa de três faixas de ≥ 2 px para ler como
   visto, e ele tem 28 das 168 unidades de altura. Os dois dão A ≥ 36 px.
   Antes daqui eram 32 px no painel e 34 px no convite: dois números, nenhum
   declarado, os dois abaixo do piso. Abaixo de 36 px não se encolhe a marca:
   troca-se de versão (o só-ícone, que vai até 16 px).
   `width: auto` é obrigatório — a marca nunca é esticada. */
.logo-img {
    height: 36px;
    width: auto;
    display: block;
}

.hero-logo {
    max-width: 340px;
    width: 100%;
    height: auto;
    display: block;
    margin: 0 auto 6px;
}

.menu {
    display: flex;
    align-items: center;
    gap: 16px;
}

.menu a {
    color: var(--cor-texto);
    text-decoration: none;
    font-size: 0.92rem;
    font-weight: 700;
    padding: 8px 2px;
}

.menu a:hover {
    color: var(--cor-acento);
}

.form-inline {
    display: inline;
}

/* -----------------------------------------------------------------------------
   O ALTERNADOR DE MODO DE COR (TD-048)
   -----------------------------------------------------------------------------
   Ele é o primeiro item do `.menu`, no `.topo` — o mesmo cabeçalho do dono e do
   admin. Nunca ao lado de "Sair": ação terminal não faz vizinhança com controle
   que se toca com frequência.

   ⚠️ QUEM DECIDE QUAL GLIFO APARECE É O MESMO CSS QUE DECIDIU O MODO, e essa é
   a peça inteira do desenho. Um rótulo escrito pelo PHP mentiria no instante em
   que o `app.js` trocasse a classe sem recarregar; dois glifos governados pelo
   seletor de modo não têm como discordar da tela. No claro aparece a LUA (o que
   o botão liga é o escuro); no escuro aparece o SOL.

   O nome acessível é único e neutro ("Alternar entre modo claro e escuro"),
   porque `aria-pressed` não é acionável por CSS e estado falado errado é pior
   que estado nenhum. Ele descreve a AÇÃO, não o ESTADO.

   ⚠️ NADA DE `transition` NA TROCA DE MODO. Trocar a página inteira com
   transição produz ~200ms de cores intermediárias, e nenhuma delas foi medida.
   A única transição aqui é a do `color` do próprio glifo sob o dedo, que é
   feedback de controle e não de tema.
   -------------------------------------------------------------------------- */
.modo-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--alvo-toque);
    height: var(--alvo-toque);
    padding: 0;
    border: 0;
    border-radius: var(--raio-pilula);
    background: none;
    color: var(--cor-texto-suave);
    cursor: pointer;
    transition: color var(--mov-rapido) var(--curva-padrao);
}

.modo-btn:hover {
    color: var(--cor-texto);
}

/* A família do painel ainda não tem a regra única de `:focus-visible` (é da F8),
   então este botão declara o próprio anel — e declara `outline` e
   `outline-offset` e NADA MAIS: a forma é do componente, o foco é o anel. */
.modo-btn:focus-visible {
    outline: var(--foco-largura) solid var(--foco);
    outline-offset: var(--foco-desvio);
}

.modo-glifo {
    display: none;
    line-height: 0;
}

.modo-glifo-escuro {
    display: inline-flex;
}

:root.modo-escuro .modo-glifo-escuro {
    display: none;
}

:root.modo-escuro .modo-glifo-claro {
    display: inline-flex;
}

.btn-link {
    background: none;
    border: none;
    padding: 8px 2px;
    color: var(--cor-erro-texto);
    font-size: 0.92rem;
    font-weight: 700;
    font-family: inherit;
    cursor: pointer;
}

.btn-link:hover {
    text-decoration: underline;
}

/* ---------------- Conteúdo ---------------- */

main {
    flex: 1;
    padding: 26px 16px 56px;
}

/* ⚠️ A SOMBRA DO CARTÃO ERA UM `rgba` CRAVADO — `rgba(80,52,160,.18)`, um roxo
   que não é token nenhum e que a cerca do F8 não vê porque ela caça hexadecimal.
   Ela vira `--elev-1`, que é a escala do sistema e já sabe se comportar nos dois
   modos: rasa no claro (o fio é quem separa, 1,27:1) e profunda no escuro (onde
   o fio é textura e a sombra faz o trabalho sozinha). E o raio desce de 24px
   para `--raio-peca`, que é o degrau da direção B. */
.card {
    background: var(--cor-cartao);
    border: 1px solid var(--cor-borda);
    border-radius: var(--raio-peca);
    padding: 24px 20px;
    box-shadow: var(--elev-1);
    margin-bottom: 20px;
}

.card h1 {
    font-family: var(--f-display);
    font-size: 1.4rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    margin-bottom: 8px;
}

/* ⚠️ `.card h2` VESTE 18 TELAS: mexer no TAMANHO aqui mexe na hierarquia de
   todas elas, e a T-0020 já mediu isso. O que entra é família e peso — a
   personalidade tipográfica da direção B —, não a escala. */
.card h2 {
    font-family: var(--f-display);
    font-size: 1.15rem;
    font-weight: 700;
    letter-spacing: -0.015em;
}

.subtitulo {
    color: var(--cor-texto-suave);
    margin-bottom: 20px;
}

.centro {
    text-align: center;
}

/* ---------------- Formulários ---------------- */

.campo {
    margin-bottom: 18px;
    flex: 1;
}

.campo label {
    display: block;
    font-weight: 700;
    font-size: 0.9rem;
    margin-bottom: 6px;
}

.campo label small {
    font-weight: 400;
    color: var(--cor-texto-suave);
}

/* -----------------------------------------------------------------------------
   O POÇO DO FORMULÁRIO — `--sup-campo`, e no ESCURO ele é o que faz o campo
   existir
   -----------------------------------------------------------------------------
   A regra "elevar é sempre clarear" lida ao contrário: o campo é onde se ESCREVE,
   ele fica ABAIXO do cartão, e por isso ele afunda. No claro isso é refinamento
   (`#f3f0fa` contra o cartão branco); no ESCURO é o que separa o campo de nada —
   antes desta troca o interior do campo era `--cor-cartao`, exatamente a mesma
   superfície do cartão em volta, e o único sinal de que ali havia um controle era
   o fio, que no escuro mede 1,19:1 nas bordas decorativas. Agora o poço é o
   carvão da moldura e o degrau é real.

   ⚠️ A FAMÍLIA DO CONVITE FICA COMO ESTÁ, e a exceção é declarada logo abaixo em
   `.tema-convite`: `--sup-campo` é pigmento da pele do PAINEL, e TD-076 não toca
   a família pública. Sem a exceção, o violeta claro do poço cairia dentro dos
   cartões creme e verde do convite.
   -------------------------------------------------------------------------- */
.campo select {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--limite);
    border-radius: var(--raio-tecla);
    font-size: 16px;
    font-family: inherit;
    font-weight: 600;
    background: var(--sup-campo);
    color: var(--cor-texto);
    min-height: 48px;
}

/* T-0031 4a (BUG-TD-136): o halo deriva do acento — a nota inteira está em
   `.campo input:focus`, mais abaixo. */
.campo select:focus {
    outline: none;
    border-color: var(--cor-acento);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--cor-acento) 15%, transparent);
}

.config-pagamento {
    border: 1px dashed var(--cor-borda);
    border-radius: 16px;
    padding: 16px;
    margin-bottom: 18px;
}

.config-pagamento legend {
    font-weight: 800;
    font-size: 0.92rem;
    padding: 0 8px;
    color: var(--cor-acento);
}

.campo-dica {
    display: block;
    color: var(--cor-texto-suave);
    font-size: 0.8rem;
    margin-top: 4px;
}

.campo input,
.campo textarea {
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--limite);
    border-radius: var(--raio-tecla);
    font-size: 16px; /* evita zoom automático no iOS */
    font-family: inherit;
    font-weight: 600;
    background: var(--sup-campo);
    color: var(--cor-texto);
    min-height: 48px;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.campo textarea {
    resize: vertical;
}

/* ⚠️ T-0031 4a (BUG-TD-136) — O HALO LÊ O MESMO TOKEN QUE A BORDA. Era
   `rgba(124, 58, 237, .15)`: a primária velha a 15%, escrita à mão, debaixo de
   uma borda que já era `--cor-acento` — dois violetas a 9° no mesmo campo,
   MEDIDOS na engine nas duas peles. `color-mix()` deriva o halo do acento em
   vez de copiá-lo: não existe segunda fonte (nem tripleto `-rgb` para manter
   em sincronia), e ele acompanha a pele escura (#b3a1ff) e qualquer repintura
   futura sozinho. Num navegador sem `color-mix()` a declaração inteira cai e
   sobra a borda, que é quem carrega o 1.4.11 (5,78:1 no poço claro, 8,69:1 no
   escuro) — o halo é reforço, não o indicador. O convite não passa por aqui:
   `.tema-convite .campo input:focus` redeclara borda e `box-shadow: none`. */
.campo input:focus,
.campo textarea:focus {
    outline: none;
    border-color: var(--cor-acento);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--cor-acento) 15%, transparent);
}

/* ⚠️ A EXCEÇÃO DO CONVITE, e ela é a metade que impede a pele do painel de
   vazar para a família pública. `--sup-campo` é pigmento da direção B e não tem
   valor declarado em `.visual-classico` nem em `.visual-jardim`; sem estas três
   linhas, o poço violeta do painel apareceria dentro dos cartões creme e verde
   do convite. O convite continua com o campo BRANCO sobre o papel, que é o que
   a T-0015 mediu e o usuário aprovou. */
.tema-convite .campo select,
.tema-convite .campo input,
.tema-convite .campo textarea {
    background: var(--cor-cartao);
}

/* PLACEHOLDER NÃO É RÓTULO, e o piso dele é 4,5:1 como o de qualquer texto.
   `#b8b2c9` sobre o interior branco do campo media 2,05:1 — REPROVAVA, vivo, no
   campo principal do painel. É o N5 do `design-system.md` §6, e a correção é a
   mesma que a família do convite já recebeu na T-0015: `--limite`, que mede
   4,53:1 sobre branco e serve aos DOIS limiares (texto 4,5 e borda 3,0).
   `opacity: 1` acompanha porque o Firefox aplica opacidade própria ao
   placeholder — sem ela o 4,53:1 medido não é o que a tela mostra lá. */
.campo input::placeholder,
.campo textarea::placeholder {
    color: var(--limite);
    opacity: 1;
    font-weight: 500;
}

.campo small {
    display: block;
    color: var(--cor-texto-suave);
    font-size: 0.8rem;
    margin-top: 4px;
}

.campo-grupo {
    display: flex;
    flex-direction: column;
    gap: 0;
}

/* A virada de `.campo-grupo` para linha migrou para o bloco `--bp-1` do fim do
   arquivo (era `420px`, valor que não está em escala nenhuma; passou a 30rem).
   ⚠️ ACHADO: `.campo-grupo` não tem NENHUM consumidor — não aparece em
   `views/` nem em `assets/js/`. A regra e a virada estão vivas no CSS e mortas
   na tela. Registrado para a F8; não removida aqui porque limpeza de legado tem
   critério de saída próprio (TD-012 item 3). */

/* ---------------- Botões ---------------- */

/* -----------------------------------------------------------------------------
   ⚠️ TD-076 §4 e §5 — O BOTÃO DEIXA DE SER GRADIENTE E DEIXA DE SER PÍLULA
   -----------------------------------------------------------------------------
   O gradiente saiu porque ele era `violet-600 → fuchsia-600 → pink-600` a 135°,
   os três valores padrão do Tailwind no arranjo mais repetido da internet: não
   era marca, era default. E a pílula saiu porque é ela que faz uma tela de
   operação parecer página de festa. O preenchimento vivo agora é UM acento
   sólido, e a tinta em cima dele vai ao extremo do papel (`--tinta-viva`) — a
   regra (c) da direção, que é o que faz o par medir 6,51:1 no claro e 8,69:1 no
   escuro sem ninguém escolher cor de texto à mão.

   ⚠️ A FAMÍLIA DO CONVITE NÃO PERDE O GRADIENTE: `.tema-convite .btn` redeclara
   `background: var(--grad)`, e `--grad` é redeclarado dentro de cada
   `.visual-*`. O botão da festa continua sendo o botão da festa.

   O HOVER E O PRESSIONADO ANDAM NA DIREÇÃO DA TINTA — no claro `--acento-forte`
   ESCURECE, no escuro CLAREIA. Um par de tokens, dois comportamentos, uma regra.
   E a sombra RECUA: sombra pesada em papel claro lê como sujeira, e a que existe
   agora é a `--elev-1` do sistema, que já sabe se aprofundar no escuro.
   -------------------------------------------------------------------------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 50px;
    padding: 13px 24px;
    background: var(--cor-acento);
    color: var(--tinta-viva);
    border: none;
    border-radius: var(--raio-tecla);
    font-family: var(--f-display);
    font-size: 1rem;
    font-weight: 700;
    cursor: pointer;
    text-align: center;
    text-decoration: none;
    box-shadow: var(--elev-1);
    transition:
        transform var(--mov-rapido) var(--curva-padrao),
        background-color var(--mov-rapido) var(--curva-padrao),
        box-shadow var(--mov-rapido) var(--curva-padrao);
}

.btn:hover {
    transform: translateY(-1px);
    background: var(--acento-forte);
    box-shadow: var(--elev-2);
}

.btn:active {
    transform: translateY(0);
    background: var(--acento-fundo);
}

.btn-auto {
    width: auto;
}

/* A TECLA FANTASMA — peso secundário. Superfície própria (`--tecla-fantasma`) em
   vez da pastilha de acento: a pastilha É informação nesta paleta (fundo de
   estado), e usá-la como fundo de botão faz o mesmo pigmento dizer duas coisas. */
.btn-secundario {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 46px;
    padding: 10px 20px;
    background: var(--tecla-fantasma);
    color: var(--cor-acento);
    border: none;
    border-radius: var(--raio-tecla);
    font-family: var(--f-display);
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
    text-align: center;
    text-decoration: none;
}

/* A superficie sob o dedo passa a ser semantica. Era `#e9e1fb` literal; com o
   modo escuro isso seria um lilas CLARO sob um rotulo CLARO (`--cor-texto`
   vira `#e6e1f0`) - 1,3:1. `--cor-info-fundo` gira junto e mede 12,53:1 no
   escuro. No claro a superficie clareia de `#e9e1fb` para `#f5f1fd`: mudanca
   de pixel DECLARADA, e o par continua sendo a tinta cheia sobre lilas. */
.btn-secundario:hover {
    background: var(--tecla-fantasma-hover);
}

/* O PRESSIONADO EXISTIA COMO PIGMENTO E NÃO EXISTIA COMO ESTADO: `--sup-press`
   estava declarado nos dois modos e ninguém o lia. Ele é o terceiro degrau da
   escada de interação — repouso, ponteiro, dedo —, e sem ele o botão secundário
   não devolve nada ao clique. A regra vale nos dois modos sem token por modo:
   interagir é andar na direção da tinta, e `--sup-press` já sabe para que lado. */
.btn-secundario:active {
    background: var(--sup-press);
    transform: translateY(1px);
}

/* -----------------------------------------------------------------------------
   `.btn.btn-suave` — A AÇÃO PRINCIPAL EM PESO SECUNDÁRIO
   -----------------------------------------------------------------------------
   MODIFICADOR de `.btn`, e não componente novo: ele herda largura, altura
   mínima, raio de pílula e alvo de toque, e troca SÓ o peso. Essa é a exigência
   escrita do `designer-visual` (§13) para a página pública com o cadastro
   fechado: "o botão secundário tem o mesmo tamanho e o mesmo alvo de toque do
   primário — só troca de peso".

   POR QUE NÃO REUSEI `.btn-secundario`, que já existe e tem estas cores: porque
   ele tem 46px de altura contra os 50px do primário e raio de 14px contra 999px.
   Trocá-lo pelo primário mudaria o ALVO junto com o peso, e é justamente o alvo
   que a especificação manda manter — quem chega numa porta fechada continua
   tendo uma ação do mesmo tamanho.

   Contraste medido pelo designer: `#7c3aed` sobre `#f5f1fd` = 5,12:1 (AA para
   texto normal, com folga). A borda é `--cor-borda` e não `--limite` por decisão
   dele: quem identifica este controle é o RÓTULO, que passa em 5,12:1; a borda
   aqui é filete decorativo, e o filete é isento de limiar (§2.4 do sistema).
   -------------------------------------------------------------------------- */
.btn-suave {
    border: 1px solid var(--cor-borda);
    background: var(--cor-roxo-claro);
    color: var(--cor-acento);
    box-shadow: none;
}

/* Sob o dedo: a borda vira `--limite` e o botão sobe uma elevação. É o mesmo
   estado que o design system descreve para o card de escolha do visual, e evita
   escurecer o fundo à mão — o `#e9e1fb` de `.btn-secundario:hover` é literal
   legado que a F8 vai tokenizar, e uma SEGUNDA cópia dele só aumentaria o
   trabalho daquela passagem. */
.btn-suave:hover {
    border-color: var(--limite);
    box-shadow: var(--elev-1);
}

/* ⚠️ A TECLA DESTRUTIVA GANHOU SUPERFÍCIE PRÓPRIA (`--tecla-perigo`) E DEIXOU DE
   USAR `--cor-erro-fundo`. A troca não é de cor, é de CARGO: `--cor-erro-fundo`
   é a PASTILHA DO ESTADO DE ERRO — ela diz "alguma coisa deu errado" —, e um
   botão em repouso não está em erro nenhum, ele só é perigoso. Usar a mesma
   superfície para as duas coisas é o defeito de divergência ao contrário: um
   pigmento dizendo dois significados. TD-076 §8: vermelho gasto SÓ no
   irreversível, e o irreversível aqui é a AÇÃO, não a situação.
   E foi assim que o `:hover` deixou de ser uma regra que não muda nada — ele
   repetia `--cor-erro-fundo` e, medido, não movia um pixel. Agora escurece. */
.btn-perigo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 46px;
    padding: 10px 20px;
    background: var(--tecla-perigo);
    color: var(--cor-erro-texto);
    border: none;
    border-radius: var(--raio-tecla);
    font-family: var(--f-display);
    font-size: 0.95rem;
    font-weight: 600;
    cursor: pointer;
}

/* A TINTA TAMBÉM ANDA NO HOVER, e `--rosa-forte` existe exatamente para isto:
   ele é o vermelho que ganha presença quando o fundo escurece. Sem ele a única
   coisa que se movia era a superfície, e o rótulo perdia contraste relativo.
   Medido: 5,90:1 no claro e 6,31:1 no escuro contra `--tecla-perigo-hover`. */
.btn-perigo:hover {
    background: var(--tecla-perigo-hover);
    color: var(--rosa-forte);
}

.btn-mini {
    min-height: 38px;
    padding: 6px 14px;
    font-size: 0.85rem;
}

/* Honeypot: tirado da tela sem usar display:none (alguns bots detectam) */
.hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

/* ---------------- Alertas ---------------- */

.alerta {
    border-radius: var(--raio-peca);
    padding: 13px 18px;
    margin-bottom: 16px;
    font-size: 0.95rem;
    font-weight: 600;
}

.alerta ul {
    margin-left: 18px;
}

.alerta a {
    font-weight: 800;
    color: inherit;
}

/* O texto usa o vermelho ESCURO: `--cor-erro-texto` sobre `--cor-erro-fundo`
   mede 4,2:1 e reprova AA (o `.alerta` é 0,95rem/600 — não é "texto grande").
   A borda continua no vermelho claro, onde o critério é 3:1. Medido, não
   estimado; a mesma medição do bloco de tokens no topo do arquivo. */
.alerta-erro {
    background: var(--cor-erro-fundo);
    border: 1px solid var(--cor-erro-borda);
    color: var(--cor-erro-texto);
}

.alerta-sucesso {
    background: var(--cor-sucesso-fundo);
    border: 1px solid var(--cor-sucesso-borda);
    color: var(--cor-sucesso-texto);
}

/* ---------------- Painel do usuário ---------------- */

.painel-cabecalho {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 22px;
}

.painel-cabecalho h1 {
    /* O título da tela é DISPLAY (TD-076 §6): a segunda família entrou na mesma
       requisição de fonte e até esta tarefa só era lida dentro da banda. */
    font-family: var(--f-display);
    font-size: 1.45rem;
    font-weight: 800;
    letter-spacing: -0.015em;
}

.painel-cabecalho .subtitulo {
    margin-bottom: 0;
    font-size: 0.95rem;
}

/* A virada de `.painel-cabecalho` para linha migrou para o bloco `--bp-1` do fim
   do arquivo — mesmo valor de sempre (480px = 30rem), agora em `rem`. */

/* ⚠️ ERA `font-size: 3rem` PORQUE O CONTEÚDO ERA UM EMOJI: o tamanho do desenho
   saía da tipografia. Com SVG o desenho tem caixa própria, e `.ico-vazio` a
   declara. O `font-size` sai: um bloco com 48px de linha e sem texto dentro
   reserva altura que ninguém usa. */
.evento-vazio {
    margin-bottom: var(--e-1);
    color: var(--cor-texto-suave);
}

.ico-vazio {
    width: 48px;
    height: 48px;
    vertical-align: baseline;
}

/* -----------------------------------------------------------------------------
   ⚠️ O CARTÃO DE EVENTO SAIU DAQUI — ele virou O PALCO (T-0016, direção A)
   -----------------------------------------------------------------------------
   `.evento-head`, `.data-tile` (com `.dia` e `.mes`), `.evento-head h2`,
   `.selo-futuro`, `.evento-detalhes` e `.evento-acoes` foram REMOVIDOS, e não
   repintados: a festa deixou de ser um cartão claro entre avisos e passou a ser
   a banda escura que abre a tela. As regras novas estão na seção "O PALCO", logo
   abaixo do link do convite; a marcação está em `views/painel/index.php`.

   ⚠️ E É AQUI QUE O BUG-TD-055 MORRE, POR ANATOMIA E NÃO POR REMENDO.
   `.data-tile .mes` era branco de 11,2px/800 com `opacity: 0.92` sobre `--grad`.
   Medido por mim contra a folha antes de apagar:

       parada #7c3aed (0%) ..... 5,06:1  (sem a opacidade: 5,70:1)
       parada #c026d3 (60%) .... 4,19:1 ❌ (sem a opacidade: 4,71:1)
       parada #db2777 (100%) ... 4,09:1 ❌ (sem a opacidade: 4,60:1)

   A conta publicada no design system dizia "4,60:1 — passa", e ela estava certa
   para BRANCO CHEIO: o que ela ignorou é que a MESMA regra aplicava `opacity`.
   No palco a peça vira o BILHETE — papel branco sólido, dia em `--cor-texto`
   (14,92:1), mês em `--cor-texto-suave` (5,31:1), zero `opacity`, zero texto
   branco sobre gradiente.

   REGRA DE SISTEMA QUE SAI DAQUI: `opacity` sobre TEXTO é proibida no produto, e
   o motivo é de método antes de ser de cor — a opacidade torna o par dependente
   do que está atrás, e ele deixa de ser mensurável no dia em que o fundo mudar.
   O comentário de `.termos-versao` já documenta a mesma remoção pelo mesmo
   motivo; `.data-tile .mes` era o caso que tinha sobrevivido à varredura.
   -------------------------------------------------------------------------- */

/* Selos / chips de status */

.selo {
    display: inline-block;
    /* SELO CONTINUA PÍLULA — é o que a direção B preservou da forma anterior
       (TD-076 §5: "selo não é botão"). O que sai é o literal. */
    font-family: var(--f-display);
    font-size: 0.74rem;
    font-weight: 800;
    padding: 3px 12px;
    border-radius: var(--raio-pilula);
    white-space: nowrap;
    margin-top: 4px;
}

/* ⚠️ `.selo-futuro` SAIU JUNTO: ele só vestia "faltam N dias" e "é amanhã!" no
   card de evento, e as duas frases foram para `.palco-selo`. `.selo-hoje` e
   `.selo-passado` FICAM porque `views/painel/convidados.php` também os usa —
   morte medida por seletor, uma peça de cada vez. */

.selo-hoje {
    background: var(--cor-sucesso-fundo);
    color: var(--cor-sucesso-texto);
}

/* `#f1eff6` era, byte a byte, `--cor-neutro-fundo`. Zero pixel no claro; no
   escuro a superficie passa a acompanhar a tinta que ja vinha do token. */
.selo-passado {
    background: var(--cor-neutro-fundo);
    color: var(--cor-texto-suave);
}

/* Barra de progresso das confirmações */

.progresso {
    margin-bottom: 18px;
}

.progresso-info {
    display: flex;
    justify-content: space-between;
    font-size: 0.85rem;
    font-weight: 700;
    margin-bottom: 6px;
}

.progresso-info b {
    color: var(--cor-acento);
}

.barra {
    height: 10px;
    border-radius: var(--raio-pilula);
    /* Era `#efeaf9` cravado — o MESMO valor de `--medidor-trilho`, que já
       existia com nome desde a F6. Duas fontes de verdade para um trilho é como
       o produto acaba com dois cinzas de progresso. */
    background: var(--medidor-trilho);
    overflow: hidden;
}

/* ⚠️ A LARGURA VEM DO ELEMENTO, NUNCA DO FIM DE UMA ANIMAÇÃO. O `app.js` escreve
   `span.style.width` a partir de `data-progresso` (CSSOM, que a CSP `style-src
   self` não bloqueia — o que ela bloqueia é o atributo `style=""` no HTML). A
   transição só faz o valor CHEGAR; sob `prefers-reduced-motion` ela some e o
   valor continua lá. Se o enchimento fosse um `@keyframes` com a largura no
   `to{}`, desligar a animação deixaria a barra em 0% e quem pediu menos
   movimento leria "ninguém confirmou".
   `0.6s ease` eram DUAS fugas de token na mesma linha: 600ms está fora da
   diretriz de 150–300ms da casa (só `--mov-cena` passa disso, e é exceção
   reservada ao envelope) e `ease` não é nenhuma das três curvas do sistema. */
/* ⚠️ T-0031 4a (BUG-TD-135) — O PREENCHIMENTO-BASE DEIXA DE SER O DEGRADÊ
   APOSENTADO. `--grad` sobrevive num lugar só (o selo da marca, TD-076 §4), e
   esta regra era o seu último consumidor na família do painel: nenhum pixel
   dela aparecia (o palco a cobre com `--palco-menta`), até a etapa 3 reusar o
   par `.barra` + `<span>` no console — porque é o gancho que o `app.js` lê — e
   o degradê voltar a pintar a barra de Confirmações nas duas peles. A base
   passa a `--cor-acento`, o preenchimento vivo do sistema: quem quiser outra
   cor redeclara por cima (o palco e a cabine fazem isso), e quem esquecer de
   redeclarar herda a pele, e não a assinatura morta. Zero pixel muda hoje. */
.barra span {
    display: block;
    height: 100%;
    width: 0;
    border-radius: var(--raio-pilula);
    background: var(--cor-acento);
    transition: width var(--mov-medio) var(--curva-padrao);
}

/* Box do link do convite */

.convite-link {
    background: linear-gradient(135deg, #f6f1ff, #fdf2f8);
    border-radius: 18px;
    padding: 14px;
    margin-bottom: 18px;
}

/* -----------------------------------------------------------------------------
   NÚMERO É TINTA, RÓTULO É `--cor-texto-suave` — e este aqui é rótulo
   -----------------------------------------------------------------------------
   Esta regra pintava o rótulo com `--grad` recortado no glifo
   (`background-clip: text` + `color: transparent`). Três motivos para sair, e
   nenhum é de gosto:
     1. O PAR NÃO É MENSURÁVEL. O glifo tem um gradiente inteiro dentro; não
        existe "a cor do texto". Medido nas paradas: 5,70:1 no roxo e 4,60:1 no
        rosa — o mesmo rótulo muda de razão ao longo de si mesmo, e o pior ponto
        está a 0,10 do piso de 4,5.
     2. A §4.4 do design system já proíbe texto em gradiente.
     3. A direção A gasta o canal de cor num lugar só: a banda.

   ⚠️ ELA VESTE DUAS TELAS, E UMA DELAS É DO CONVIDADO — e a correção certa NÃO é
   escopar o seletor. `views/painel/galeria.php` ("Link da galeria") e
   `views/convite/presentes.php` ("PIX copia e cola"). Apontar para
   `--cor-texto-suave` acerta nas duas famílias sem uma segunda regra, porque
   `.visual-classico` e `.visual-jardim` REDECLARAM o semântico.
   E na tela do convidado a COR nem chega a mudar: `.tema-convite .convite-link
   label` (0,2,1) já vencia esta regra (0,1,1) desde antes, com `background:
   none` e `color: var(--cor-texto)`. O que muda lá é 0,32px de corpo
   (0,72rem → `--fs-1`, 11,52px → 11,2px), e a troca existe para o tamanho sair
   da escala em vez de ser número cravado.
   ⚠️ O rótulo do link do convite NO PAINEL DO DONO não passa mais por aqui: ele
   entrou no palco e é `.palco-link-rot`. */
.convite-link label {
    display: block;
    font-size: var(--fs-1);
    font-weight: 900;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--cor-texto-suave);
    margin-bottom: 8px;
}

.convite-link-linha {
    display: flex;
    gap: 8px;
}

/* ⚠️ `--fs-3` SÃO 16px, E O PISO É DE CAMPO E NÃO DE ESTÉTICA — BUG-TD-076.
   Abaixo de 16px o iOS dá zoom sozinho ao focar o campo, e o zoom não volta:
   quem toca aqui para copiar o link do convite fica com a página ampliada no
   meio da festa. Este era o ÚNICO `<input>` da folha fora do piso — media
   0,83rem (13,28px) contra os 16px de `.campo input`, `.busca-input`,
   `.detalhe-form input`, `.acomp-lista input` e `.palco-campo`, todos com o
   mesmo motivo escrito ao lado.
   Ele veste três telas — o PIX do convidado, o link da galeria e o campo de cota
   do admin —, e no admin ele é `size="6"`: a largura do campo acompanha o corpo
   da letra, então a coluna "Armazenamento" da tabela cresce alguns pixels com
   esta linha. Está medido junto com o BUG-TD-074 e cabe. */
.convite-input {
    flex: 1;
    min-width: 0;
    padding: 10px 12px;
    border: 1px solid var(--cor-borda);
    border-radius: 12px;
    font-size: var(--fs-3);
    font-family: inherit;
    font-weight: 600;
    color: var(--cor-texto-suave);
    background: var(--cor-cartao);
}

/* ⚠️ T-0031 4a — MEDIDO NA ENGINE: este botão era o último `--grad` VIVO na
   família do painel. `views/painel/galeria.php` o emite como `.btn.btn-copiar`
   e, por vir depois de `.btn` na folha, ele vencia o preenchimento sólido nas
   duas peles (89×44 de degradê aposentado na galeria do dono). Passa ao mesmo
   par de `.btn` (`--cor-acento` + `--tinta-viva`, regra (c) de TD-076). Onde o
   botão vive em outra pele, ela já vence: no convite, `.tema-convite .btn`
   (0,2,0) mantém o `--grad` do visual; no palco, `.palco-btn-claro` vem depois
   e mantém o papel — os dois conferidos na engine antes e depois. A anatomia
   (raio, recuo, corpo) não muda aqui: não é decisão desta etapa. */
.btn-copiar {
    border: none;
    border-radius: 12px;
    padding: 0 18px;
    background: var(--cor-acento);
    color: var(--tinta-viva);
    font-size: 0.9rem;
    font-weight: 800;
    font-family: inherit;
    cursor: pointer;
    min-height: 44px;
}

/* =============================================================================
   O PALCO — a banda escura que abre o painel do dono (T-0016, direção A)
   =============================================================================
   Direção: `docs/opcoes-painel/opcao-a.html`, do `designer-visual`, escolhida
   pelo usuário entre três ("gostei da opçao A"). Tokenização e anatomia:
   `design-system.md` §14, do `especialista-ui`. Os tokens estão no `:root`.

   A APOSTA, EM UMA FRASE: a vibração fica num ÚNICO campo de cor, onde ela é
   barata — o roxo da marca como TEXTO sobre a página clara mede 5,08:1 e não tem
   folga para saturar mais; os mesmos acentos sobre a banda escura medem de 5,5:1
   a 16:1. O resto da página continua branco e sem cor.

   =============================================================================
    A COMPOSIÇÃO — uma borda esquerda, duas larguras (§13.9)
   =============================================================================
   O palco é FAIXA (a largura do contêiner), a grade de destinos é FAIXA, a grade
   da conta é FAIXA, e o único bloco de texto corrido — o aviso da zona de perigo
   — é COLUNA, com `.coluna-leitura` NA VIEW. Todos começam na MESMA aresta
   esquerda. A borda direita fica serrilhada, e isso não é defeito.

   ⚠️ O PROTÓTIPO CRAVA A MEDIDA DE LEITURA À MÃO no aviso da zona de perigo —
   uma `max-width` com o valor `38rem` escrito no seletor do componente —, E ISSO
   REPROVA. É exatamente o que a trava L4 (alvo ZERO) existe para pegar:
   transcrita, ela leva o L4 de 0 para 1. Aqui a medida vem de `.coluna-leitura`,
   que é o único lugar da folha que pode declará-la.

   ⚠️ E ESTE PARÁGRAFO NÃO ESCREVE O PAR `propriedade: valor` JUNTO, DE PROPÓSITO.
   A primeira versão dele escrevia, e o L4 subiu para 1 medindo a PRÓPRIA
   EXPLICAÇÃO — com a folha limpa. É a §7.6 acontecendo dentro do comentário que
   documenta a §7.6, e ela derruba de passagem uma frase publicada na §13.5:
   *"alvo ZERO é imune ao problema do comentário casando no grep"*. Não é: alvo
   zero é imune a contador que INFLA por uso legítimo, e continua vulnerável à
   prosa que cita o literal. Quem for documentar uma proibição, cite as duas
   metades SEPARADAS — o comando publicado tem de ser o comando que roda.

   =============================================================================
    A PELE, AS ILHAS DE PAPEL, E O DEFEITO QUE ESTE PARÁGRAFO ESCONDIA
   =============================================================================
   ⚠️ ESTE COMENTÁRIO DIZIA O CONTRÁRIO DO QUE ACONTECIA NA TELA, E A TELA
   ESTAVA ERRADA. Ele afirmava que a pele é vestida "nos dois blocos de texto
   que NÃO contêm papel". `.palco-sobre` CONTÉM papel: o bilhete de data é filho
   dele. Custom property herda pela ÁRVORE, não pela intenção — então o dia do
   bilhete lia o `--cor-texto` da PELE (branco) sobre o papel branco e media
   1,00:1, e o mês lia `--palco-suave` `#d9cdf0` sobre branco e media 1,51:1.
   Renderizado com o motor de verdade em 2026-08-21: `color: rgb(255,255,255)`
   sobre `background-color: rgb(255,255,255)`. A peça cuja anatomia inteira é
   "papel branco sólido" — a que mata o BUG-TD-055 — estava INVISÍVEL no modo
   claro, e nenhuma leitura de código pegou isso porque o CSS lê certo: o
   seletor pede `--cor-texto`, e é o ANCESTRAL que responde outra coisa.

   A CORREÇÃO NÃO É MOVER A PELE, É TIRAR AS ILHAS DA CONVERSA. Papel dentro de
   banda escura não é semântico de página: é PIGMENTO, e pigmento não gira com
   modo nem com pele. Os quatro `--palco-papel*` do `:root` fazem isso, e a
   inversão some — o bilhete lê o mesmo branco com a pele por cima, sem pele, no
   modo claro e no modo escuro.
   O QUE FICA: a pele continua em `.palco-sobre` e `.palco-farol` (mover para a
   banda é mudança de cascata e é passagem B); a banda declara só `--foco`. O
   que MUDOU é que a pele deixou de alcançar o que não era dela.

   =============================================================================
    ⚠️ A PALAVRA "PALCO" JÁ EXISTIA NESTA FOLHA, COM OUTRO SIGNIFICADO
   =============================================================================
   `.tema-convite .palco` (duas regras, mais `views/convite/mostrar.php`) é o
   palco DO CONVITE: a superfície onde o papel aparece quando o envelope sai.
   Não há colisão de SELETOR — `.palco` e `.palco-*` são nomes distintos, e
   aquela regra é escopada em `.tema-convite`, família que o painel nunca veste.
   Há colisão de VOCABULÁRIO, e ela fica registrada aqui em vez de descoberta
   depois: o prefixo `.palco-*` é o mesmo dos tokens `--palco-*` publicados na
   §14 do design system, e por isso ele fica; quem for renomear renomeia o mais
   antigo e sem documento, que é o do convite. Está no relatório como consulta.
   -------------------------------------------------------------------------- */

/* ⚠️ O CONTÊINER NÃO RECORTA, e a mudança é correção de defeito e não estilo:
   `overflow: hidden` aqui foi a causa raiz do BUG-TD-102, em que o anel de foco
   de um `<summary>` colado na borda foi comido. Agora cada METADE se recorta
   sozinha com `mask`, e o contêiner só isola o empilhamento. */
.painel-palco {
    /* O anel de foco branco: o anel padrão é `--anel` (roxo escuro no claro), e
       roxo escuro sobre roxo escuro é anel que ninguém vê — justamente para quem
       o anel existe. Aqui ele mede 13,13:1 no claro e 9,46:1 no escuro. */
    --foco: var(--tinta-texto);

    position: relative;
    isolation: isolate;
    margin-bottom: var(--e-5);
    border-radius: var(--raio-peca);
    color: var(--tinta-texto);
}

/* -----------------------------------------------------------------------------
   AS DUAS METADES DO CANHOTO
   -----------------------------------------------------------------------------
   Elas carregam a MESMA superfície chapada e se recortam sozinhas: o corpo morde
   os cantos de BAIXO, o pé morde os de CIMA, e juntas as quatro meias-luas viram
   dois furos inteiros em cima da linha do rasgo.

   ⚠️ A ÂNCORA É A BORDA DE CADA METADE, e não uma distância até o pé. É
   deliberado: em 320px o campo do link toma a linha inteira e os dois botões
   descem — o pé cresce de ~92px para ~152px, e qualquer `calc(100% - Xpx)`
   escrito à mão passaria a apontar para o lugar errado.

   ⚠️ `background-color` É OBRIGATÓRIO E VEM SOZINHO: a superfície é chapada de
   propósito (TD-076 §4 aposentou o gradiente como assinatura), e sem gradiente
   não há banding nem canto mais claro — o teto deixa de ser um ponto e passa a
   ser a banda inteira.
   -------------------------------------------------------------------------- */
.palco-corpo,
.palco-pe {
    position: relative;
    background-color: var(--palco-1);
}

.palco-corpo {
    border-radius: var(--raio-peca) var(--raio-peca) 0 0;
    overflow: hidden;                   /* é o grão que pede, e aqui não há foco dentro */
    padding: var(--e-6) var(--e-6) 24px;
    /* As duas sombras são INTERNAS de propósito — máscara não recorta o que está
       dentro da caixa, e recortaria uma sombra externa nas mordidas. Em cima,
       LUZ (a peça se levanta); embaixo, sombra (a peça tem espessura). Nas duas
       peles, sem token por modo. */
    box-shadow: inset 0 1px 0 var(--palco-luz);
    -webkit-mask-image:
        radial-gradient(circle var(--palco-mordida) at 0 100%, transparent calc(var(--palco-mordida) - 1px), var(--mascara-cheia) var(--palco-mordida)),
        radial-gradient(circle var(--palco-mordida) at 100% 100%, transparent calc(var(--palco-mordida) - 1px), var(--mascara-cheia) var(--palco-mordida));
    mask-image:
        radial-gradient(circle var(--palco-mordida) at 0 100%, transparent calc(var(--palco-mordida) - 1px), var(--mascara-cheia) var(--palco-mordida)),
        radial-gradient(circle var(--palco-mordida) at 100% 100%, transparent calc(var(--palco-mordida) - 1px), var(--mascara-cheia) var(--palco-mordida));
    /* ⚠️ A LEGADA VEM ANTES DA PADRÃO, e a ordem importa: no Blink as duas são
       propriedades distintas e a última declarada ganha. E A DEGRADAÇÃO É BOA de
       propósito — sem suporte a composição, o padrão `add` soma as duas camadas,
       a união fica opaca em tudo e a banda simplesmente vira um retângulo. Some
       o rasgo, não some a tela.
       ⚠️ O OPACO DA MÁSCARA É TOKEN (`--mascara-cheia`) E NÃO `#000` À MÃO: a
       cerca do F8 cobrou, e cobrou certo — quem carrega literal é token. `mask`
       lê só o ALFA, então o valor não pinta nada; ver a declaração dele. */
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
}

.palco-pe {
    border-radius: 0 0 var(--raio-peca) var(--raio-peca);
    padding: 18px var(--e-6) var(--e-5);
    box-shadow: inset 0 -1px 0 rgb(0 0 0 / 0.22);
    -webkit-mask-image:
        radial-gradient(circle var(--palco-mordida) at 0 0, transparent calc(var(--palco-mordida) - 1px), var(--mascara-cheia) var(--palco-mordida)),
        radial-gradient(circle var(--palco-mordida) at 100% 0, transparent calc(var(--palco-mordida) - 1px), var(--mascara-cheia) var(--palco-mordida));
    mask-image:
        radial-gradient(circle var(--palco-mordida) at 0 0, transparent calc(var(--palco-mordida) - 1px), var(--mascara-cheia) var(--palco-mordida)),
        radial-gradient(circle var(--palco-mordida) at 100% 0, transparent calc(var(--palco-mordida) - 1px), var(--mascara-cheia) var(--palco-mordida));
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
}

/* O PICOTE — a linha entre o que FICA e o que SAI.
   ⚠️ SEM `opacity`. O tracinho é `--palco-suave` inteiro (6,27:1 no claro,
   4,56:1 no escuro contra o teto da banda): baixar opacidade rebaixa contraste,
   e é exatamente assim que se perde uma linha medida — é a regra que o
   BUG-TD-055 comprou. O que controla a discrição é a ALTURA (2px) e a cadência
   (6 ligados, 8 desligados). */
.palco-pe::before {
    content: "";
    position: absolute;
    left: var(--palco-mordida);
    right: var(--palco-mordida);
    top: 0;
    height: 2px;
    background-image: repeating-linear-gradient(90deg, var(--palco-suave) 0 6px, transparent 6px 14px);
}

/* O GRÃO. Filtro SVG INLINE (`feTurbulence` + `feColorMatrix saturate=0`), nunca
   `data:` URI e nunca arquivo — é o que a CSP `style-src 'self'` permite sem
   asset novo. Sobre superfície CHAPADA ele não está lá para matar banding (não
   há banding sem gradiente): está para o objeto ler como CARTÃO e não como div.
   ⚠️ Ele NÃO é enfeite isento: ruído sobre superfície é o fundo real de cada
   glifo, e é esta camada que produz os dois `--palco-teto*`. */
.palco-grao {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: var(--palco-grao-alfa);
    pointer-events: none;
}

.palco-conteudo {
    position: relative;                 /* acima do grão */
    display: grid;
    gap: var(--e-6);
}

/* A PELE — só nos dois blocos que são texto de ponta a ponta. Ver o cabeçalho
   desta seção para o porquê de ela não morar na banda. */
.palco-sobre,
.palco-farol {
    --cor-texto: var(--tinta-texto);       /* 8,29:1 no teto da banda */
    --cor-texto-suave: var(--palco-suave); /* 5,50:1 no teto da banda */

    min-width: 0;
    color: var(--cor-texto);
}

/* ⚠️ `.palco-farol-rot` E `.palco-farol-num` TÊM DOIS CONSUMIDORES DESDE A
   PASSAGEM DO ADMIN, e quem for escopar estas regras precisa ler isto antes.
   O segundo é `views/admin/index.php`, o farol do consumo do mês — a §B.4 de
   `docs/painel-e-desktop.md` lista "o componente do Farol" entre as peças que
   o dono e o admin COMPARTILHAM e não podem divergir, e compartilhar componente
   é usar a mesma classe, não copiar a regra com outro nome.
   Escrever `.painel-palco .palco-farol-rot` aqui apagaria o rótulo e o número
   do admin SEM ERRO NENHUM aparecendo — os dois voltariam ao tamanho de corpo,
   e um farol de 51,2px que vira 16px não quebra nada, só deixa de ser farol.
   O que NÃO é compartilhado é a PELE (`.palco-sobre, .palco-farol`), que
   redeclara `--cor-texto` para branco: no admin o farol mora num
   `.painel-status` claro e a tinta é a da página. É por isso que o admin usa
   as peças de dentro e nunca o contêiner `.palco-farol`. */
.palco-rotulo,
.palco-farol-rot,
.palco-link-rot {
    font-family: var(--f-display);
    font-size: var(--fs-1);
    font-weight: 800;
    letter-spacing: 0.18em;
    text-transform: uppercase;
}

.palco-rotulo,
.palco-farol-rot {
    color: var(--cor-texto-suave);
}

.palco-identidade {
    display: flex;
    gap: var(--e-4);
    align-items: flex-start;
    margin-top: var(--e-2);
}

/* -----------------------------------------------------------------------------
   BUG-TD-068 — A COLUNA AO LADO DO BILHETE, E POR QUE ELA PRECISA DO PISO ZERO
   -----------------------------------------------------------------------------
   Item de fila `flex` nasce com o piso em `min-content`, e `min-content` de um
   bloco de texto é a maior PALAVRA que ele contém. Um local ou um endereço com
   um token longo sem espaço fixava esse piso acima do espaço disponível, a fila
   estourava a banda e o recorte da banda (então em `.painel-palco`) comia o excedente.

   A CONTA, medida na folha e não estimada: em 375px o conteúdo do `.container`
   dá 343px; o recuo de 24px de cada lado sobra 295px; o bilhete leva 74px fixos
   mais o vão de 16px, e restam **205px** para o que mora aqui.

   ⚠️ QUEM COBRA O RECUO MUDOU DE ELEMENTO NA T-0031, E A CONTA NÃO MUDOU. Era
   `.palco-conteudo`; com o canhoto em duas metades, o recuo subiu para
   `.palco-corpo` (`24px 24px 24px`), que é a metade que hospeda esta coluna. O
   número continua 295px porque o valor continua 24px — mas quem for remedir
   precisa medir o elemento CERTO, senão acha 343 e conclui que sobra espaço.

   ⚠️ O QUE MORA AQUI MUDOU NO BUG-TD-080, e o piso zero continua necessário: a
   linha da meta (local e endereço) SAIU desta coluna e virou irmã de
   `.palco-identidade`, com os 295px inteiros. Ficaram o título e o selo — e o
   título é dado do usuário do mesmo jeito, com o mesmo token longo possível.

   ⚠️ E O RECORTE QUE ENGOLIA O EXCEDENTE TROCOU DE DONO, o que NÃO desarma o
   defeito: `.painel-palco` deixou de ter `overflow: hidden` (era ele que comia o
   anel de foco no BUG-TD-102), mas `.palco-corpo` tem — é o grão que pede —, e
   `.palco-titulo` tem o seu próprio, com `-webkit-line-clamp`. Ou seja, o
   sumiço silencioso continua possível nos dois níveis, e o piso zero continua
   sendo metade da correção.

   ⚠️ O QUE MUDOU COM A REPAGINADA, e é isto que torna o defeito pior do que
   parece: antes da T-0016 esta linha era `.evento-detalhes`, ficava FORA da fila
   do bilhete e usava a largura cheia do cartão. A repaginada reduziu o espaço em
   cerca de 40% E trocou "estoura e aparece" por "some sem avisar". Truncar em
   silêncio é pior que quebrar feio: ninguém reporta o que não vê.

   O par é o mesmo que `.album-parte-linha` e `.convidado-info` + `.convidado-contato`
   já usavam nesta folha — piso zero no item da fila, quebra de token no texto —,
   e as duas metades são necessárias: só o piso zero deixa a caixa encolher e o
   token vazar dela; só a quebra não adianta enquanto o piso segurar a caixa.
   -------------------------------------------------------------------------- */
.palco-info {
    min-width: 0;
}

/* -----------------------------------------------------------------------------
   O BILHETE — a ilha de papel, e é ela que substitui o `.data-tile`
   -----------------------------------------------------------------------------
   Papel BRANCO SÓLIDO dentro da banda escura. Gradiente sobre gradiente sumiria;
   o papel mede 8,29:1 contra o teto da banda, e a tinta sobre ele 14,92:1.
   ⚠️ ZERO `opacity`. É a peça que mata o BUG-TD-055 — ver o bloco de remoção do
   `.data-tile` mais acima, com as três razões medidas.
   `tabular-nums` no dia: o número troca de largura ao trocar de dia sem isso, e
   um bilhete que muda de largura sozinho desalinha o título ao lado. */
.palco-bilhete {
    flex: 0 0 auto;
    width: 74px;
    padding: 11px 0 9px;
    text-align: center;
    background: var(--palco-papel);
    border-radius: var(--raio-peca);
    /* a sombrinha do bilhete é interna à banda e não passa por máscara nenhuma */
    box-shadow: 0 10px 22px -14px rgb(0 0 0 / 0.65);
}

.palco-bilhete-dia {
    display: block;
    font-family: var(--f-display);
    font-size: var(--fs-6);
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.03em;
    font-variant-numeric: tabular-nums;
    color: var(--palco-papel-tinta);  /* 15,53:1 sobre o papel */
}

.palco-bilhete-mes {
    display: block;
    font-family: var(--f-display);
    font-size: var(--fs-1);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--palco-papel-suave);  /* 7,10:1 sobre o papel */
}

/* Até TRÊS linhas e depois reticências: protótipo trabalha com dado curto, e um
   título de 80 caracteres em 375px é o caso que ele nunca faz.
   ⚠️ A quebra de token entra junto com o piso zero de `.palco-info` (BUG-TD-068):
   aqui o recorte é da PRÓPRIA caixa, então uma palavra maior que a linha some
   dentro dela sem estourar nada — o mesmo sumiço silencioso, num lugar onde nem
   a borda da banda denunciaria. */
.palco-titulo {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
    overflow-wrap: anywhere;
    font-family: var(--f-display);
    /* `clamp()` e não degrau cravado: o nome da festa é o objeto da dobra e
       precisa crescer com a tela sem passar por cima do farol em 375px. */
    font-size: clamp(1.6875rem, 5.4vw, 2.5rem);
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: -0.035em;
}

/* O SELO DA CONTAGEM.
   ⚠️ O PREENCHIMENTO DEIXOU DE SER `rgba` E VIROU TOKEN SÓLIDO (`--palco-2`), e
   a troca é a mesma correção de arquitetura que TD-076 fez nas pastilhas:
   preenchimento em rgba COMPÕE com o que estiver atrás, e o que está atrás muda
   (grão, teto, modo). Branco sobre o sólido mede 8,28:1 no claro e 6,06:1 no
   escuro, e nenhum dos dois depende do substrato.
   O FIO continua em alfa, e essa metade da divisão é deliberada: na banda FIO É
   LUZ e PREENCHIMENTO É TINTA. Fio é objeto gráfico (piso 3:1) e composto ele
   mede 4,36 e 3,50; um preenchimento no mesmo alfa mediria 4,26 e 3,23 — reprova
   nas duas. Um alfa de fio para a banda inteira (`--palco-fio`), e não dois.
   ⚠️ CONTINUA PÍLULA: TD-076 §5 tirou o raio de pílula do BOTÃO, e selo não é
   botão. `white-space: nowrap` é o único da banda, e é de propósito: "faltam 27
   dias" quebrado ao meio deixa de ser um selo. */
.palco-selo {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-top: var(--e-2);
    padding: 6px 13px;
    border: 1px solid var(--palco-fio);
    border-radius: var(--raio-pilula);
    font-family: var(--f-display);
    font-size: var(--fs-1);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    white-space: nowrap;
    background: var(--palco-2);
    color: var(--cor-texto);
}

/* A LINHA DA META — data, hora, local e endereço, e são os dois últimos que
   trazem token longo do mundo real (BUG-TD-068). `anywhere` e não `break-word`
   porque é o valor que esta folha já usa nos três lugares onde o dado é do
   usuário (`.convidado-contato`, `.album-parte-linha`, o `<pre>` do depurador),
   e porque ele também baixa o `min-content` — a caixa passa a poder encolher em
   qualquer caixa em que a ponham.
   ⚠️ DESDE O BUG-TD-080 ELA NÃO MORA MAIS DENTRO DE `.palco-info`: é irmã de
   `.palco-identidade`, filha direta de `.palco-sobre`, e por isso usa a largura
   inteira da banda. Em 375px são 295px medidos, contra os 205px que ela tinha ao
   lado do bilhete — e o endereço caiu de três linhas para duas. Quem for
   escopar esta regra em `.palco-info` some com ela da tela. */
.palco-meta {
    list-style: none;
    display: grid;
    gap: var(--e-1);
    margin-top: var(--e-3);
    font-size: var(--fs-2);
    line-height: var(--lh-normal);
    overflow-wrap: anywhere;
    color: var(--cor-texto-suave);
}

/* -----------------------------------------------------------------------------
   O FAROL — o número que decide o buffet
   -----------------------------------------------------------------------------
   Destaque por TAMANHO, POSIÇÃO e ISOLAMENTO: ele não gasta canal de cor, é
   branco puro. NUNCA em gradiente — a §4.4 proíbe texto em gradiente e a ponta
   rosa mede 4,36:1.
   ⚠️ O `border-left: 1px solid rgba(255,255,255,.22)` DO PROTÓTIPO NÃO ENTROU:
   ele mede 1,74:1 contra o teto da banda, ou seja, é uma linha de CSS que não
   desenha nada. A separação do farol já está feita pelo vão de 40px e pelo salto
   de `--fs-5` para `--fs-8`. (Proposta de remoção do `especialista-ui`, C-UI-05.)
   `clamp()` e não `--fs-8` cravado, pelo mesmo motivo do farol da miniatura da
   página inicial da T-0015 (que saiu com a T-0017):
   em 375px o farol de 51,2px ficaria quase o dobro do `<h1>` da saudação. */
.palco-farol-num {
    font-family: var(--f-display);
    font-size: clamp(var(--fs-6), 7.5vw, var(--fs-8));
    font-weight: 700;
    line-height: 0.95;
    letter-spacing: -0.045em;
    font-variant-numeric: tabular-nums;
    margin: var(--e-1) 0;
}

.palco-farol-obs {
    font-size: var(--fs-2);
    color: var(--cor-texto-suave);
}

/* A régua das confirmações dentro do palco. Ela REUSA `.progresso`/`.barra` — a
   mesma peça, a mesma marcação, o mesmo gancho de `app.js` — e troca só o par de
   cor, que é o que a superfície escura obriga a trocar. Três linhas, cada uma
   com o número ao lado. */
.palco-conf {
    margin-top: var(--e-4);
    max-width: 20rem;
}

.palco-conf .progresso {
    margin-bottom: 0;
}

/* O "6 de 12": menta como TEXTO no teto da banda mede 6,46:1. */
.palco-conf .progresso-info b {
    color: var(--palco-menta);
}

/* ⚠️ O TRILHO TAMBÉM SAIU DO `rgba`, pelo mesmo motivo do selo: superfície em
   alfa dentro da banda compõe com o grão e com o teto, e o par deixa de ser
   mensurável no dia em que qualquer um dos dois mudar. Sólido, a menta contra
   ele mede 4,44:1 no claro e 3,22:1 no escuro — acima dos 3:1 da WCAG 1.4.11
   para objeto gráfico. */
.palco-conf .barra {
    background: var(--palco-2);
    box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.28);
}

/* ⚠️ ESTE É O LUGAR DO VERDE, E É O ÚNICO EM QUE ELE OCUPA ÁREA GRANDE
   (TD-076 §9): o painel do dono é celebração, e celebração é onde o verde pode
   ocupar área. Ele é MASSA e não tinta — nenhuma palavra da banda é verde, o que
   dispensa a menta de passar em texto e a deixa livre para ser saturada. */
.palco-conf .barra span {
    background: var(--palco-menta);
}

/* -----------------------------------------------------------------------------
   O PÉ — o que SAI daqui: o link do convite
   -----------------------------------------------------------------------------
   ⚠️ `.palco-link` DEIXOU DE CARREGAR O RECUO: ele agora mora dentro de
   `.palco-pe`, que é a metade recortada do canhoto e é quem tem o `padding`.
   A classe fica porque a view a emite e porque ela continua sendo o gancho do
   bloco; o que ela perdeu foi a geometria, que subiu um nível. */
.palco-link {
    position: relative;
}

.palco-link-rot {
    display: block;
    margin-bottom: var(--e-2);
    color: var(--palco-suave);       /* 6,27:1 no teto claro · 4,56:1 no escuro */
}

.palco-link-linha {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

/* `--fs-3` são 16px, e o piso é de campo, não de estética: abaixo de 16px o iOS
   dá zoom sozinho ao focar. `text-overflow: ellipsis` recorta o que se VÊ e não
   o que se COPIA — o valor inteiro continua selecionável, que é literalmente o
   que o dono faz aqui. */
.palco-campo {
    flex: 1 1 18rem;
    min-width: 0;
    min-height: 46px;
    padding: 11px 15px;
    border: 1px solid var(--palco-fio);          /* 4,36:1 claro · 3,50:1 escuro */
    border-radius: var(--raio-tecla);
    font-family: var(--f-display);
    font-size: var(--fs-3);
    font-weight: 500;
    text-overflow: ellipsis;
    background: var(--palco-2);
    color: var(--tinta-texto);                   /* 8,28:1 claro · 6,06:1 escuro */
}

/* ⚠️ RAIO DE TECLA E NÃO PÍLULA. É TD-076 §5, e vale INCLUSIVE dentro da peça
   mais festiva do produto — é o que separa "console" de "página de festa". */
.palco-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 46px;
    padding: 11px 20px;
    border-radius: var(--raio-tecla);
    font-family: var(--f-display);
    font-size: var(--fs-2);
    font-weight: 600;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition:
        transform var(--mov-rapido) var(--curva-padrao),
        background-color var(--mov-rapido) var(--curva-padrao),
        box-shadow var(--mov-rapido) var(--curva-padrao);
}

/* A SEGUNDA ILHA DE PAPEL. ⚠️ O COMENTÁRIO ANTERIOR AQUI DIZIA "`--cor-texto`
   aqui é o da PÁGINA e não o da pele", e ele estava certo por ACIDENTE: este
   botão está em `.palco-link`, fora de `.palco-sobre`, então escapava da pele —
   enquanto o bilhete, que o mesmo parágrafo citava como irmão, NÃO escapava e
   media 1,00:1. Comentário que sobrevive à própria razão é a próxima pessoa
   errando com confiança, então ele sai inteiro.
   O QUE VALE AGORA: papel é PIGMENTO (`--palco-papel*`), invariante de pele E
   de modo. Sem isso, no escuro a superfície viraria `#282136` (1,86:1 contra o
   teto da banda) e a tinta `#e6e1f0` sobre papel branco (1,28:1) — os dois
   desfechos medidos no `:root`. */
.palco-btn-claro {
    border: 1px solid var(--palco-papel);
    background: var(--palco-papel);
    color: var(--palco-papel-tinta);             /* 14,92:1 sobre o papel */
    box-shadow: 0 8px 18px -10px rgb(0 0 0 / 0.6);
}

.palco-btn-claro:hover {
    background: var(--palco-papel-toque);
}

/* ⚠️ AQUI O HOVER CLAREIA NOS DOIS MODOS, e não é exceção à regra "interagir é
   andar na direção da tinta": é a regra lida certo. Dentro da banda o papel
   local é escuro nas DUAS peles, então a tinta é clara nas duas e a interação
   anda para a luz nas duas. É a única região do sistema onde isso acontece. */
.palco-btn-vazado {
    border: 1px solid var(--palco-fio);
    background: transparent;
    color: var(--tinta-texto);
}

.palco-btn-vazado:hover {
    background: var(--palco-toque);   /* branco em cima: 7,50 claro · 5,69 escuro */
}

.palco-btn:active {
    transform: scale(0.97);
}

/* ⚠️ `:disabled` NÃO EXISTE EM PEÇA NENHUMA DO PROTÓTIPO, e o produto tem o
   estado. Sem `opacity` — a proibição de `opacity` sobre texto vale aqui também:
   a superfície e o rótulo trocam para o par NEUTRO, que já existe e mede 8,05:1.
   `aria-disabled` é a forma certa quando o botão precisa continuar focalizável;
   o seletor cobre as duas. */
.palco-btn:disabled,
.palco-btn[aria-disabled="true"] {
    border-color: var(--cor-neutro-borda);
    background: var(--cor-neutro-fundo);
    color: var(--cor-neutro-texto);
    box-shadow: none;
    cursor: not-allowed;
    transform: none;
}

/* ⚠️ A REGRA DE FOCO DECLARA `outline` E `outline-offset`, E NADA MAIS. É o R3 da
   §13.7 virando anatomia: `border-radius` numa regra de `:focus-visible`
   esquadra toda pílula do produto no instante do foco de teclado — foi o defeito
   R2, achado em DUAS regras na T-0015. A forma é do componente; o foco é o anel.
   O anel já acompanha o `border-radius` do elemento sozinho. */
.painel-palco :focus-visible {
    outline: var(--foco-largura) solid var(--foco);
    outline-offset: var(--foco-desvio);
}

/* -----------------------------------------------------------------------------
   OS CINCO DESTINOS — peso igual, zero cor
   -----------------------------------------------------------------------------
   São os cinco caminhos da tela e nenhum deles é "o principal": por isso mesmo
   tamanho, mesmo peso e nenhuma cor. A grade se conta sozinha (`auto-fit`), que
   é medição do ESPAÇO que existe e não palpite sobre o aparelho — a mesma tese
   que tirou cinco media queries desta folha — eram QUATRO até T-0020, e a grade
   absorveu `Temas` sem uma regra nova.
   ⚠️ `Excluir` NÃO ESTÁ AQUI. A ação destrutiva saiu da fileira de navegação e
   foi para a zona de perigo, no pé da página: um botão de apagar do mesmo
   tamanho e na mesma fila dos cinco destinos é um erro de clique esperando
   acontecer. */
.palco-destinos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
    gap: 10px;
    margin-bottom: var(--e-5);
}

.palco-destino {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 54px;
    padding: 13px 15px;
    border: 1px solid var(--cor-borda);
    border-radius: var(--raio-tecla);
    box-shadow: var(--elev-1);
    background: var(--cor-cartao);
    color: var(--cor-texto);
    font-family: var(--f-display);
    font-size: var(--fs-2);
    font-weight: 600;
    text-decoration: none;
    transition:
        transform var(--mov-rapido) var(--curva-padrao),
        background-color var(--mov-rapido) var(--curva-padrao),
        box-shadow var(--mov-rapido) var(--curva-padrao),
        border-color var(--mov-rapido) var(--curva-padrao);
}

/* ⚠️ O HOVER GANHOU SUPERFÍCIE, E É O QUE FAZ ELE SOBREVIVER AO MODO ESCURO:
   `border-color` sozinha era o único sinal, e no escuro fio é TEXTURA (1,19:1) —
   ou seja, o estado existia no CSS e não existia na tela. `--cor-sob-ponteiro`
   escurece no claro e clareia no escuro, que é a regra "interagir é andar na
   direção da tinta" resolvendo os dois modos com um token só. */
.palco-destino:hover {
    transform: translateY(-1px);
    background: var(--cor-sob-ponteiro);
    border-color: var(--cor-info-borda);
    box-shadow: var(--elev-2);
}

.palco-destino:active {
    transform: translateY(0);
}

/* ⚠️ ERA `font-size: 1.2rem`, QUE É MEDIDA DE GLIFO DE TEXTO. Com o emoji, o
   tamanho do ícone saía da tipografia; com SVG ele sai da caixa, e 22px é o
   degrau que mantém o alvo visual do destino sem competir com o rótulo ao lado.
   A cor é a secundária: o rótulo é quem lê, o ícone é quem localiza. */
.palco-destino-icone {
    display: flex;
    flex: none;
    line-height: 0;
    color: var(--cor-texto-suave);
}

.palco-destino-icone .ico {
    width: 22px;
    height: 22px;
}

/* Sob o ponteiro o ícone acompanha a tinta cheia: é o mesmo movimento do fundo,
   e sem ele o ícone fica pálido justamente no item que está vivo. */
.palco-destino:hover .palco-destino-icone {
    color: var(--cor-acento);
}

/* -----------------------------------------------------------------------------
   A CONTA E A ZONA DE PERIGO — o pé da página
   -----------------------------------------------------------------------------
   As DUAS faixas empilhadas de hoje (o prazo da conta e o armazenamento) viram
   UMA seção, ao pé. Elas continuam sendo `.painel-status`, com os estados que já
   tinham: a cor do estado é REFORÇO, e quem carrega a informação é a frase.
   Achatá-las num cartão roxo único apagaria o "⚠️" que o dono precisa ver. */
.painel-secao-titulo {
    margin: var(--e-8) 0 var(--e-3);
    /* Micro-rótulo: caixa alta, muito espaçado e pequeno. É o cargo em que a
       Nunito arredondada some e a Space Grotesk desenha — a `.rotulo` da
       direção B, com o nome que esta folha já tinha. */
    font-family: var(--f-display);
    font-size: var(--fs-1);
    font-weight: 800;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--cor-texto-suave);
}

.painel-conta-grade {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
    gap: var(--e-3);
    align-items: start;
}

/* ⚠️ OS DOIS SELETORES SÃO NOMEADOS, E `> *` NÃO SERVE AQUI — ISSO É CASCATA, NÃO
   ESTILO. `.painel-conta-grade > *` tem especificidade (0,1,0), a MESMA de
   `.painel-status` e de `.alerta`; e as duas moram DEPOIS nesta folha (linhas
   ~859 e ~3150 contra esta). Empate de especificidade quem resolve é a ordem, e
   a ordem perde para elas: a regra existiria e não pintaria nada. Escrita com a
   classe do filho, ela vale (0,2,0) e vence em qualquer ordem de arquivo.
   O vão entre os cartões é o `gap` da grade; a margem que cada peça carrega
   sozinha na pilha vertical não vale dentro dela. */
.painel-conta-grade > .painel-status,
.painel-conta-grade > .alerta {
    margin-bottom: 0;
}

.painel-perigo {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-4);
    margin: var(--e-8) 0 var(--e-10);
    padding-top: var(--e-5);
    border-top: 1px solid var(--cor-borda);
}

/* A MEDIDA DE LEITURA NÃO ESTÁ AQUI. Ela vem de `.coluna-leitura`, na view — é a
   trava L4 (alvo ZERO) e ela reprova a etapa se alguém escrever `38rem` à mão. */
.painel-perigo-aviso {
    font-size: var(--fs-2);
    line-height: var(--lh-normal);
    color: var(--cor-texto-suave);
}

/* -----------------------------------------------------------------------------
   A ENTRADA EM ESCADA — ela revela a ORDEM DE LEITURA (palco → destinos → conta)
   -----------------------------------------------------------------------------
   `--mov-medio` + `--curva-entrada`, os que JÁ EXISTEM. O protótipo traz
   `cubic-bezier(.16,1,.3,1)` com o nome `--curva-entrada`, que é o nome de uma
   curva viva e diferente; redefini-la mudaria os três consumidores atuais em
   silêncio. O argumento decisivo não é o desvio de 3,5px: é que o produto já tem
   este gesto — o `@keyframes inicio-peca-chega`, que nasceu na miniatura do
   painel da página inicial da T-0015 (um cartão subindo sobre superfície
   escura) e hoje anima a capa do convite. Duas curvas para o mesmo gesto em duas telas do
   mesmo produto é a inconsistência que o design system existe para impedir.
   Os três atrasos são LITERAIS de propósito: são uma sequência, não uma escala
   reutilizável, e `--mov-cena` é exceção reservada ao envelope. */
@keyframes painel-entra {
    from {
        opacity: 0;
        transform: translateY(14px);
    }

    to {
        opacity: 1;
        transform: none;
    }
}

.painel-entra {
    animation: painel-entra var(--mov-medio) var(--curva-entrada) both;
}

.painel-entra-1 { animation-delay: 60ms; }
.painel-entra-2 { animation-delay: 120ms; }
.painel-entra-3 { animation-delay: 180ms; }

/* -----------------------------------------------------------------------------
   MOVIMENTO REDUZIDO NO PALCO — o que SAI e o que FICA, item por item
   -----------------------------------------------------------------------------
   Sem regra global de `.001ms`: ela apagaria junto o feedback de estado, que é o
   contrário do que quem liga a preferência está pedindo.
     · entrada em escada .......... SAI (movimento de cena, decorativo)
     · enchimento da régua ........ sai o DESLIZE, fica o VALOR — a largura está
       no elemento (`app.js` escreve `style.width`), nunca no fim de uma
       animação; sem esse cuidado a barra ficaria em 0% e quem pediu menos
       movimento leria "ninguém confirmou"
     · translação do destino ...... SAI; a mudança de SOMBRA fica, e é ela que
       continua respondendo ao ponteiro
     · `:hover`, `:active`, `:focus-visible` ... FICAM. Feedback de estado não
       herda o corte
     · "Copiar" → "Copiado!" ...... FICA, e é obrigatório: é a única confirmação
       de que a ação aconteceu (está em `app.js`, e não em CSS, justamente para
       não haver como cortá-la aqui por engano)
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .painel-entra {
        animation: none;
    }

    .barra span {
        transition: none;
    }

    .palco-destino:hover,
    .palco-destino:active {
        transform: none;
    }

    .palco-btn:active {
        transform: none;
    }
}

/* ---------------- Lista de convidados (dono da festa) ---------------- */

.lote {
    margin-top: 18px;
    border-top: 1px solid var(--cor-borda);
    padding-top: 14px;
}

.lote summary {
    cursor: pointer;
    font-weight: 800;
    color: var(--cor-acento);
    padding: 8px 0;
}

.lote form {
    margin-top: 12px;
}

/* ---------------- Convidados (painel do dono) ---------------- */

/* Utilitário: esconder elemento (controlado via app.js) */
.oculto {
    display: none !important;
}

/* Layout largo do painel no desktop (body.painel-largo via $paginaLarga) */
.painel-largo .container {
    max-width: 1160px;
}

.grade-convidados {
    display: grid;
    grid-template-columns: 1fr;
    gap: 20px;
    align-items: start;
}

/* As duas colunas de `.grade-convidados` migraram para o bloco `--bp-3` do fim
   do arquivo. O VALOR não mudou (1024px = 64rem); mudou a unidade, e em `rem`
   quem aumenta a fonte do sistema recebe o leiaute simples mais cedo, que é o
   comportamento certo (WCAG 1.4.4). */

/* Grade genérica do painel: usa a largura toda em 2 colunas (mesma ideia da
   tela de convidados). Reutilizada em evento, sugestões e galeria. */
.grade-painel { display: grid; grid-template-columns: 1fr; gap: 20px; align-items: start; }
.grade-painel .form-secao { margin-bottom: 0; }
.coluna-lado { display: grid; gap: 20px; align-content: start; }
.coluna-lado .form-secao { margin-bottom: 0; }
.metricas-lado { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.convite-link-espaco { margin-top: 18px; }
/* As duas colunas de `.grade-painel` migraram para o bloco `--bp-3` do fim do
   arquivo, com o mesmo valor (1024px = 64rem). */

/* Acompanhantes no formulário de cadastro */
.acomp-campos {
    margin: 12px 0 16px;
    padding: 14px;
    background: var(--cor-roxo-claro);
    border-radius: var(--raio-peca);
}

.acomp-titulo {
    display: block;
    /* Micro-rótulo — mesmo cargo de `.painel-secao-titulo`. */
    font-family: var(--f-display);
    font-size: 0.78rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--cor-acento);
    margin-bottom: 8px;
}

.acomp-lista {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.acomp-lista input {
    width: 100%;
    min-height: 44px;
    padding: 10px 14px;
    font: 600 16px 'Nunito', sans-serif;
    color: var(--cor-texto);
    background: var(--cor-cartao);
    border: 1px solid var(--limite);
    border-radius: 12px;
}

.acomp-lista input:focus {
    outline: none;
    border-color: var(--cor-acento);
}

.btn-leve-mais {
    margin-top: 10px;
    border: none;
    background: transparent;
    color: var(--cor-acento);
    font: 800 0.88rem 'Nunito', sans-serif;
    cursor: pointer;
    padding: 6px 0;
}

.btn-leve-mais:hover {
    text-decoration: underline;
}

.acomp-campos small {
    display: block;
    margin-top: 8px;
    font-size: 0.76rem;
    color: var(--cor-texto-suave);
}

/* Seta que mostra/esconde os acompanhantes na lista */
/* ⚠️ ESTE BOTÃO CONTINUA COM A FAMÍLIA DO CORPO, E NÃO COM A DE DISPLAY. O
   rótulo dele é `▾ N acomp.`, e o `▾` (U+25BE) é COPY DE ESPECIFICAÇÃO
   (`docs/especificacao-funcional.md`:180 e :514, RF-024) — não é ícone, e por
   isso não virou SVG na varredura da T-0031. Space Grotesk não cobre esse
   ponto de código; posto ali, o glifo cairia no reserva e mudaria de desenho
   sem ninguém pedir. A família de texto é quem tem o glifo. */
.seta-acomp {
    border: none;
    background: var(--cor-roxo-claro);
    color: var(--cor-acento);
    font: 800 0.74rem var(--f-corpo);
    border-radius: var(--raio-pilula);
    padding: 3px 10px;
    margin-left: 6px;
    cursor: pointer;
    vertical-align: middle;
}

/* ⚠️ T-0031 4a (BUG-TD-136) — `--cor-primaria` é MARCA (TD-076 §4) e não pinta
   controle: aberto, o botão dos acompanhantes é preenchimento vivo, e o par é o
   de `.btn` — `--cor-acento` com `--tinta-viva` em cima. Medido: 6,51:1 no
   claro e 8,69:1 no escuro (onde o violeta velho dava 2,80:1 contra o cartão). */
.seta-acomp.aberto {
    background: var(--cor-acento);
    color: var(--tinta-viva);
}

/* A FILEIRA DE CHIPS SE CONTA SOZINHA — e é o exemplo mais curto do porquê.
   Antes: 2 colunas na base e uma media query de 560px abrindo 4. (A regra está
   escrita em prosa, e não copiada, porque uma media query citada dentro de um
   comentário É CONTADA pelo grep que publica o placar lá no fim do arquivo — o
   contador mediria a própria explicação.)
   A media query pergunta a largura da JANELA; o que decide quantos chips cabem é a
   largura da CAIXA. `auto-fit` mede a caixa:
     · 328px de contêiner (viewport 360) → 2 colunas — igual a hoje
     · 1160px                            → 4 colunas de 282px — igual a hoje
     · e entre 560 e 606 de viewport passam a ser 3 e não 4, porque 4 chips de
       124px com o número grande dentro é aperto, não leiaute.
   `auto-fit` COLAPSA a trilha vazia, então quatro chips numa grade que caberia
   oito continuam quatro colunas de largura igual, sem faixa sobrando.
   ⚠️ A LINHA ACIMA DIZIA "um número de 1,2rem" E ENVELHECEU NA T-0016, quando o
   número passou a ler o token da escala. Não escrevo o tamanho aqui de novo: ele
   mora na regra logo abaixo, e número em prosa envelhece igual a comentário de
   código — foi assim que três documentos deste projeto passaram a afirmar coisas
   que já não eram verdade, todas certas no dia em que foram escritas. */
.stats-fila {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
    gap: 10px;
    margin-bottom: 20px;
}

.stat-chip {
    background: var(--cor-cartao);
    border: 1px solid var(--cor-borda);
    border-radius: var(--raio-peca);
    padding: 9px 10px;
    text-align: center;
}

/* NÚMERO É TINTA. O destaque vem de TAMANHO, PESO e `tabular-nums` — não de cor.
   O gradiente recortado no glifo saiu pelos três motivos da §14.6: o par não é
   mensurável (5,70:1 no roxo e 4,60:1 no rosa, dentro do MESMO número), a §4.4
   proíbe texto em gradiente, e a direção A gasta o canal de cor num lugar só.
   `tabular-nums` porque estes quatro números ficam empilhados em cartões de
   mesma largura: sem ele, "1/2" e "11/12" desalinham a coluna a cada confirmação
   que chega.

   =============================================================================
    ⚠️ BUG-TD-069 — O TAMANHO MUDOU JUNTO, E A MUDANÇA FICA DECLARADA AQUI
   =============================================================================
   Esta regra media 1,2rem e passou a ler `--fs-5`, que vale 1,5rem: o número
   cresceu 25% numa tela (`views/painel/convidados.php`) que NÃO estava no
   escopo da repaginada. A troca não foi invenção — a §14.6 do design system
   prescreve `--fs-5` nesta linha, e o gate confirmou que não quebra: a fila é
   `auto-fit` de piso 8,5rem, dá duas colunas em 375px e o maior número servido
   cabe. O defeito foi de RELATÓRIO: a passagem 1 não declarou a mudança, e quem
   lesse concluiria que a tela não mudou.

   A REGRA QUE FICA, e ela vale para a próxima troca: substituir literal por
   token é EQUIVALÊNCIA; se o valor muda junto, é mudança de design e entra
   DECLARADA na lista branca da etapa, nunca de carona. O próprio design system
   escreve isso um parágrafo abaixo da tabela que prescreveu este `--fs-5`.
   ⚠️ E NÃO EXISTIA EQUIVALÊNCIA A ESCOLHER: a escala não tem 1,2rem. `--fs-4`
   fica 6% abaixo e `--fs-5` 25% acima — qualquer um dos dois é mudança de valor,
   e o que não existe é a opção de não mudar nada mantendo o token.

   UM FATO MEDIDO POR MIM QUE NEM A §14.6 NEM O GATE TINHAM NA MESA, e que é
   decisão do `especialista-ui` e não minha: a 1,5rem este número passa a ser
   MAIOR que o `<h1>` da própria tela, que é `.painel-cabecalho h1` a 1,45rem e
   não tem sobrescrita em nenhum ponto de virada. A 1,2rem ele ficava abaixo.
   Inverter a hierarquia pode ser intencional — no palco o farol é
   deliberadamente maior que o título —, mas num chip de FILTRO isso não está
   escrito em lugar nenhum. Vai como consulta, e não como correção minha: tamanho
   de token é anatomia de componente, e anatomia não é do frontend. */
.stat-numero {
    display: block;
    /* NÚMERO É DISPLAY. É o cargo mais visível da direção B — `.inst-num` e
       `.heroi-num` da cabine — e o que mais separa esta tela da anterior: a
       Nunito arredondada some do dado e fica na prosa. `-0.02em` é o aperto
       que o número grande pede para não abrir a coluna. */
    font-family: var(--f-display);
    letter-spacing: -0.02em;
    font-size: var(--fs-5);
    font-weight: 900;
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto);
    line-height: 1.2;
}

.stat-rotulo {
    font-family: var(--f-display);
    font-size: 0.66rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--cor-texto-suave);
}

.stat-destaque {
    background: var(--cor-roxo-claro);
    /* Era `#ded2f7`, a um passo de `--cor-info-borda` (`#ddd0f7`) e sem nome. */
    border-color: var(--cor-info-borda);
}

/* Cards de estatística clicáveis (filtram a lista) */
a.stat-chip { text-decoration: none; cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s, background 0.15s; }
/* A ESCADA DE SUPERFÍCIE NO PONTEIRO: elevar é clarear no escuro e tingir no
   claro — `--sup-hover` já sabe para que lado andar, e a sombra passa a ser a
   `--elev-2` do sistema em vez de um roxo literal da paleta aposentada. */
a.stat-chip:hover { border-color: var(--cor-acento); transform: translateY(-1px);
    background: var(--sup-hover); box-shadow: var(--elev-2); }
.stat-chip.ativo { border-color: var(--cor-acento); background: var(--cor-roxo-claro); }

.acao-centro { text-align: center; margin-top: 4px; }
.filtro-ativo { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    font-size: 0.85rem; font-weight: 700; color: var(--cor-texto-suave); margin-bottom: 14px; }

.lista-topo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.lista-topo h2 {
    margin-bottom: 0;
}

.busca-form {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-width: 200px;
    justify-content: flex-end;
    margin-bottom: 14px;
}

.busca-input {
    flex: 1;
    max-width: 260px;
    min-height: 44px;
    padding: 9px 14px;
    font: 600 16px 'Nunito', sans-serif;
    color: var(--cor-texto);
    background: var(--cor-fundo);
    border: 1px solid var(--limite);
    /* CAMPO NÃO É PÍLULA na direção B: a pílula é o selo. Um `<input>` de texto
       em 999px é o que faz a tela de operação parecer página de festa (TD-076
       §5), e o campo da direção B tem o mesmo raio da tecla. */
    border-radius: var(--raio-tecla);
}

.busca-input:focus {
    outline: none;
    border-color: var(--cor-acento);
}

/* N10 do `design-system.md` §6, FECHADO: `--cor-rosa` é PREENCHIMENTO e nunca
   TEXTO — media 4,13:1 sobre a superfície de informação no claro e 3,49:1 no
   escuro. Os dois consumidores (este e `.acomp-x`) são a MESMA ação: desfazer.
   `--cor-erro-texto` é a tinta que o produto já tem para isso, mede 5,51:1 e
   8,00:1, e é a mesma família do `:hover` que `.acomp-x` já usava — o hover
   dizia "erro" enquanto a tinta dizia "marca".
   ⚠️ DESDE A T-0035 ESTE É O ÚNICO CONSUMIDOR: `.acomp-x` virou lixeira CINZA
   (`--cor-texto-suave`), por decisão do usuário — o vermelho no chip passou a
   ser o "não vai" da marca da resposta, e um remover vermelho ao lado dele
   seria lido como resposta. */
.busca-limpar {
    font-size: 0.85rem;
    font-weight: 800;
    color: var(--cor-erro-texto);
    text-decoration: none;
}

.lista-convidados {
    list-style: none;
}

.convidado {
    padding: 14px 0;
    border-bottom: 1px solid var(--cor-borda);
}

.convidado:last-child {
    border-bottom: none;
}

/* ⚠️ E4 (`fluxos-e-acessibilidade.md` §7): o selo passou de `✅ 19/08 · 21:30`
   para `✅ Confirmado · 19/08 · 21:30`, e a conferência da quebra em 360px é
   desta etapa. A conta, com `.selo { white-space: nowrap }`:
     · caixa da lista em 360px de tela = 286px
     · avatar 44 + dois vãos de 12 = 68px fixos
     · o selo com a palavra passa de ~126px para ~204px
     · sobra para o nome e o telefone: 286 − 68 − 204 = 14px.
   Catorze pixels. O nome sairia uma letra por linha — e o selo NÃO encolhe,
   porque item de flex não vai abaixo do próprio conteúdo mínimo e `nowrap` faz
   o mínimo ser a frase inteira. Quem cede é sempre o nome, que é o dado.
   (As duas larguras de selo são ESTIMADAS por métrica de glifo, não lidas de um
   navegador — não há captura de tela nesta máquina. A conclusão não depende da
   precisão delas: mesmo errando 15 % para menos, sobrariam 45px para nome mais
   telefone, e a linha continuaria quebrada.)
   A correção é estrutural e não cosmética: a linha passa a QUEBRAR. O nome tem
   piso de 11rem; quando avatar + nome + selo não cabem, o selo desce sozinho
   para a segunda linha e `margin-left: auto` o mantém à direita — a mesma
   posição que ele ocupa na tela grande, então a leitura não muda de lugar
   quando o aparelho muda. Os três voltam a caber numa linha só a partir de
   ~522px de tela (44 + 12 + 176 + 12 + 204 = 448 de caixa), então o desktop
   inteiro — inclusive a coluna de lista de 510px em 64rem — continua exatamente
   como estava. */
.convidado-linha {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
}

/* Sozinho na segunda linha, o selo vai para a direita. Na linha cheia esta
   margem não faz nada: `.convidado-info` tem `flex-grow`, e a resolução das
   larguras flexíveis consome a folga ANTES de as margens automáticas verem
   qualquer coisa. Uma declaração, os dois estados. */
.convidado-linha > .selo {
    margin-left: auto;
}

.convidado-avatar {
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* As iniciais são glifo de peça, não prosa: display, como todo selo. */
    font-family: var(--f-display);
    font-size: 0.95rem;
    font-weight: 900;
    color: var(--cor-acento);
    background: var(--cor-roxo-claro);
}

.convidado-avatar.avatar-ok {
    color: var(--cor-sucesso-texto);
    background: var(--cor-sucesso-fundo);
}

/* `flex: 1 1 11rem` e não `flex: 1` (= `1 1 0%`): com base zero o nome nunca
   força a quebra, porque um item de base zero "cabe" em qualquer sobra — e era
   por isso que a linha se espremia em vez de quebrar. 11rem (176px) é o piso do
   dado: `Maria Aparecida` em 16px cabe, e o telefone mascarado
   `(11) 99999-0001` em 0,78rem também. `min-width: 0` continua, senão o nome
   longo empurraria a caixa e devolveria a rolagem horizontal pela outra porta. */
.convidado-info {
    flex: 1 1 11rem;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.convidado-info strong {
    font-family: var(--f-display);
    line-height: 1.3;
}

.convidado-contato {
    font-variant-numeric: tabular-nums;
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--cor-texto-suave);
    overflow-wrap: anywhere;
}

.convidado-info .selo {
    margin-top: 0;
}

/* Acompanhantes do convidado */
.acomp-chips {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin: 10px 0 0 56px;
}

.acomp-rotulo {
    font-size: 0.74rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--cor-texto-suave);
}

.acomp-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    /* CHIP CONTINUA PÍLULA — a pílula não morreu, ela virou vocabulário de SELO
       (TD-076 §5). O que sai é o literal: quem carrega valor é token. */
    font-family: var(--f-display);
    font-size: 0.82rem;
    font-weight: 700;
    color: var(--cor-acento);
    background: var(--cor-roxo-claro);
    border-radius: var(--raio-pilula);
    /* 5px à esquerda desde a T-0035 (eram 12): quem abre o chip agora é o
       círculo da marca, e ele já traz o próprio respiro. */
    padding: 4px 6px 4px 5px;
}

/* -----------------------------------------------------------------------------
   A MARCA DA RESPOSTA DO ACOMPANHANTE (T-0035, decisão do usuário)
   -----------------------------------------------------------------------------
   Um círculo antes do nome, no desenho do selo `Confirmado`: check verde para
   quem vai, X vermelho para quem não vai, relógio cinza para quem ainda não tem
   resposta. É DECORATIVA (`aria-hidden`): o estado continua escrito no chip, e a
   cor nunca é o único sinal (CA-310). Os valores são os da demo aprovada; o
   tamanho é em `em`, e a marca acompanha o corpo do chip.

   O `sem resposta` fica só na tinta suave, sem pastilha, como na demo, e por
   isso o relógio é maior (1.25em contra .95em dos outros dois).

   Medido como cor PINTADA no Edge (T-0035), desenho contra o fundo imediato,
   piso de 3:1 para objeto gráfico — claro: check 6,58 · X 4,96 · relógio 5,84
   · lixeira 5,84 (5,76 sobre o `:hover`); escuro: 6,60 · 5,76 · 4,85 · 4,85
   (4,88 sobre o `:hover`). O círculo quase some contra o chip (1,0x:1): quem o
   desenha é o anel de 1px na própria tinta, a 5,04:1 ou mais nos dois modos. */
.acomp-marca {
    display: inline-grid;
    place-items: center;
    width: 1.45em;
    height: 1.45em;
    border-radius: 50%;
    flex: none;
    margin-right: 2px;
}

.acomp-marca svg {
    width: 0.95em;
    height: 0.95em;
}

.acomp-marca-vai {
    background: var(--cor-sucesso-fundo);
    color: var(--cor-sucesso-texto);
    box-shadow: inset 0 0 0 1px var(--cor-sucesso-borda);
}

.acomp-marca-nao {
    background: var(--cor-erro-fundo);
    color: var(--cor-erro-texto);
    box-shadow: inset 0 0 0 1px var(--cor-erro-borda);
}

.acomp-marca-sem {
    color: var(--cor-texto-suave);
}

.acomp-marca-sem svg {
    width: 1.25em;
    height: 1.25em;
}

/* O REMOVER DE UM ACOMPANHANTE é uma lixeira CINZA desde a T-0035 (era um ×
   vermelho, que o dono lia como "não vai"). O vermelho fica só no `:hover`, que
   é quando o gesto já é de remover. O botão vermelho `Remover` da linha, que
   apaga o convidado inteiro, não mudou. */
.acomp-x {
    display: inline-grid;
    place-items: center;
    border: none;
    background: transparent;
    color: var(--cor-texto-suave);
    font-size: 0.95rem;
    font-weight: 900;
    line-height: 1;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    cursor: pointer;
}

.acomp-x:hover {
    background: var(--cor-erro-fundo);
}

/* Ações por convidado (acompanhante / contato / remover) */
.convidado-acoes {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 14px;
    margin: 10px 0 0 56px;
}

.convidado-detalhe summary {
    cursor: pointer;
    font-size: 0.85rem;
    font-weight: 800;
    color: var(--cor-acento);
    padding: 4px 0;
    list-style: none;
}

.convidado-detalhe summary::-webkit-details-marker {
    display: none;
}

.detalhe-form {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 8px;
}

.detalhe-form input {
    flex: 1;
    min-width: 150px;
    min-height: 44px;
    padding: 9px 12px;
    font: 600 16px 'Nunito', sans-serif;
    color: var(--cor-texto);
    border: 1px solid var(--limite);
    border-radius: 12px;
}

.detalhe-form input:focus {
    outline: none;
    border-color: var(--cor-acento);
}

.convidado-detalhe small {
    display: block;
    margin-top: 6px;
    font-size: 0.76rem;
    color: var(--cor-texto-suave);
}

/* A media query de 560px que abria `.stats-fila` em 4 colunas SAIU: a grade se
   conta sozinha (ver a regra dela). */

/* ---------------- Convite público ---------------- */

.convite-card {
    padding: 0;
    overflow: hidden;
    text-align: center;
}

.convite-topo {
    background: var(--grad);
    color: var(--tinta-texto);
    padding: 30px 20px 26px;
}

.convite-chamada {
    font-size: 0.74rem;
    font-weight: 900;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    opacity: 0.9;
    margin-bottom: 8px;
}

.convite-titulo {
    font-size: 1.6rem;
    font-weight: 900;
    line-height: 1.25;
}

.convite-corpo {
    padding: 24px 20px 26px;
}

.convite-detalhes {
    display: inline-block;
    text-align: left;
    margin-bottom: 8px;
}

/* -----------------------------------------------------------------------------
   O RECADO É TEXTO LIVRE DO DONO — E POR ISSO A TIPOGRAFIA AQUI É DE LEITURA
   -----------------------------------------------------------------------------
   ⚠️ NÃO DEVOLVER `font-style: italic` NEM `font-weight: 600` A ESTA REGRA.
   Eles estavam aqui e, somados ao que o tema traz (`.tema-convite
   .convite-recado`, que pedia `Great Vibes` em `--fs-6`), produziram TRÊS
   defeitos ao mesmo tempo numa caixa que hospeda até 1000 caracteres digitados
   por quem cria a festa (`maxlength` do textarea em `views/painel/evento.php`):

     1. família caligráfica, desenhada para nome próprio curto, servindo texto
        corrido;
     2. itálico por cima de uma letra que já nasce inclinada;
     3. e o pior: peso 600 numa família que só carrega a face 400 — a Great
        Vibes era pedida ao Google Fonts sem eixo de peso nenhum
        (`Tema::hrefDasFontes()`), então o navegador FABRICA o negrito. A
        Imperial Script, que a substituiu na T-0035, também só tem a face 400:
        o aviso vale igual para a cursiva de hoje.

   O item 3 medido nesta folha, a 28,8px, contando pixel com tinta no canvas:
   Great Vibes 400 = 2.946 px de tinta, Great Vibes 600 = 5.598 px — quase o
   DOBRO de tinta com o avanço IDÊNTICO (690,59px nos dois). O traço engorda e
   as letras não se afastam: elas crescem umas por dentro das outras. Era isso
   que fazia "TESTE DE RECADO AOS CONVIDADOS" se atropelar na tela.

   `font-family: inherit` e não a pilha escrita de novo: a família de texto do
   produto é declarada UMA vez nesta folha, na regra `body`. Repetir a pilha
   aqui criaria a segunda fonte da verdade que já custou o BUG-TD-009. Nenhum
   ancestral do recado declara família (conferido: as famílias de exibição desta
   folha vivem sempre no próprio elemento — título, nome, idade, seção), então
   `inherit` resolve na Nunito.

   `font-weight: 400` E NÃO 500: medido aqui, a Nunito é carregada com
   `wght@400;600;700;800;900` e NÃO tem a face 500. A 18px, o peso 500 rende
   1.070 px de tinta e 328,41px de avanço — número por número o mesmo que 400,
   porque o navegador cai para 400 e não sintetiza nada. Declarar 500 seria
   escrever um peso que a família não tem, que é a forma exata do defeito 3
   acima; 400 é a mesma tela com a declaração verdadeira. (A face 600 existe de
   verdade — 1.361 px de tinta, 332,26px — e é outra tela, não esta.)
   -------------------------------------------------------------------------- */
.convite-recado {
    background: var(--cor-roxo-claro);
    border-radius: 14px;
    padding: 12px 16px;
    color: var(--cor-texto-suave);
    font-family: inherit;
    font-size: var(--fs-4);
    font-weight: 400;
    line-height: 1.55;
    margin-top: 8px;
}

/* ---------------- Lista de presentes ---------------- */

/* Borda em gradiente (cards de destaque nas páginas públicas) */
.card-presentes,
.card-borda {
    border: 2px solid transparent;
    background:
        linear-gradient(var(--cor-cartao), var(--cor-cartao)) padding-box,
        var(--grad) border-box;
}

.presentes-cabecalho {
    text-align: center;
    margin-bottom: 22px;
}

.presentes-cabecalho h2 {
    font-size: 1.3rem;
    margin-bottom: 6px;
}

.presentes-cabecalho .subtitulo {
    margin-bottom: 14px;
}

.presentes-cabecalho::after {
    content: "";
    display: block;
    width: 56px;
    height: 4px;
    border-radius: var(--raio-pilula);
    background: var(--grad);
    margin: 0 auto;
}

/* -----------------------------------------------------------------------------
   ⚠️ ACHADO DESTA PASSAGEM, E ELE FICA REGISTRADO EM VEZ DE SER "CORRIGIDO"
   -----------------------------------------------------------------------------
   AS SETE REGRAS ABAIXO — `.presentes-grid`, `.presente-card`, `.presente-card:hover`,
   `.presente-foto`, `.presente-sem-foto`, `.presente-info`, `.presente-nome` e
   `.presente-desc` — NÃO RENDERIZAM EM LUGAR NENHUM. Varrido nesta tarefa sobre
   `views/`, `app/`, `public/assets/js/` e a árvore do sistema antigo: zero
   ocorrências. A tela pública de presentes passou a ser o acordeão `.sug-*`
   (`views/convite/presentes.php`) e estas ficaram para trás — é a mesma morte de
   `.presente-valor`, que já saiu por este motivo.
   O QUE SOBROU VIVO da família: `.presentes-cabecalho` e `.presentes-cabecalho::after`,
   e as duas moram na tela do CONVIDADO, que veste `.tema-convite` e mantém o
   gradiente da festa de propósito — ela não é uma das duas superfícies da direção B.
   NÃO REMOVO AQUI: limpeza de legado tem critério de saída próprio (TD-012 item 3,
   "diff visual vazio") e a §7.2 proíbe misturá-la com uma passagem de pele —
   duas passagens, nunca uma. Vai para a lista da passagem B, ao lado de
   `.form-keys`, `.campo-hint`, `.admin-rodape-nota`, `.integra-futura`,
   `.integra-logo-mp`, `.integra-logo-wa` e `.em-breve`. (`.admin-link.desabilitado`
   estava nesta lista e JÁ SAIU na T-0031 3e, junto com a família `.admin-link`.)
   ⚠️ E O QUE ISSO SIGNIFICA PARA QUEM LER O PORTÃO DA PELE: a linha `.presente*`
   dele conta REGRAS, não pixels. A família aparece alcançada porque as regras
   leem os tokens novos; nenhuma tela muda por causa disso.
   -------------------------------------------------------------------------- */
.presentes-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 14px;
}

.presente-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
    background: var(--cor-cartao);
    border: 1px solid var(--cor-borda);
    border-radius: var(--raio-peca);
    padding: 10px;
    transition: transform 0.15s, box-shadow 0.15s, background-color 0.15s;
}

.presente-card:hover {
    transform: translateY(-2px);
    background: var(--sup-hover);
    box-shadow: var(--elev-2);
}

.presente-foto {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: 12px;
    display: block;
}

.presente-sem-foto {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2.6rem;
    background: var(--cor-roxo-claro);
}

.presente-info {
    flex: 1;
    padding: 0 2px;
}

.presente-nome {
    font-family: var(--f-display);
    font-size: 0.9rem;
    font-weight: 700;
    line-height: 1.35;
}

/* ⚠️ `.presente-valor` FOI REMOVIDO, E É REMOÇÃO — NÃO REPINTURA. Ele era uma das
   seis peças de `background-clip: text` do painel, mas não renderiza em lugar
   nenhum: zero referências em `views/`, `app/`, `public/assets/js/` e `tests/`,
   varrido por mim antes de apagar. Repintá-lo gastaria anatomia numa regra que
   nenhuma tela desenha; é o critério de PASSAGEM B da §7.2 (diferença visual
   zero porque o seletor está morto, e não porque a correção não fez nada). */

/* Mensagem do aniversariante sobre o presente */
.presente-desc {
    margin-top: 6px;
    padding: 8px 10px;
    background: var(--cor-roxo-claro);
    border-radius: 10px;
    font-size: 0.8rem;
    font-weight: 600;
    font-style: italic;
    color: var(--cor-texto-suave);
    line-height: 1.45;
}

.btn-comprar {
    min-height: 42px;
    padding: 8px 14px;
    font-size: 0.9rem;
}

/* DESABILITADO REPROVAVA AA HOJE, NO CLARO, E NINGUEM TINHA MEDIDO: `.btn-comprar`
   herda `color: var(--tinta-texto)` de `.btn` (branco, para o gradiente), e a
   regra so trocava o FUNDO para `#d8d3e6`. Branco sobre `#d8d3e6` mede 1,46:1.
   O par neutro e o mesmo que `.palco-btn:disabled` ja usa - 8,05:1 no claro,
   8,45:1 no escuro - e sem `opacity`, que tornaria o par immensuravel. */
.btn-comprar:disabled {
    background: var(--cor-neutro-fundo);
    color: var(--cor-neutro-texto);
    box-shadow: none;
    cursor: not-allowed;
    transform: none;
}

.confirmado-banner {
    border-top: 4px solid;
    border-image: var(--grad) 1;
}

/* Card do PIX (página de presentes do convidado) */
.pix-card .pix-qr {
    display: flex;
    justify-content: center;
    margin-bottom: 20px;
}

/* ⚠️ ESTE `#fff` NÃO É SUPERFÍCIE DE CARTÃO E NÃO PODE VIRAR `--cor-cartao`.
   São os 8px de ZONA SILENCIOSA do QR Code, que a norma exige em branco:
   um leitor de código só separa módulo claro de módulo escuro se a moldura
   for clara. Apontá-lo para o cartão faria o PIX parar de ser lido no dia
   em que existisse um cartão escuro — um defeito que não aparece em captura
   de tela nenhuma, só na câmera de quem vai pagar. */
.pix-card .pix-qr img,
.pix-card .pix-qr canvas {
    border: 8px solid #fff;
    border-radius: 14px;
    box-shadow: 0 6px 22px -10px rgba(80, 52, 160, 0.35);
}

.pix-copia label {
    text-align: left;
}

/* Input de arquivo */
.campo input[type="file"] {
    padding: 10px;
    font-size: 0.88rem;
    font-weight: 600;
    min-height: 48px;
}

.campo input[type="file"]::file-selector-button {
    border: none;
    border-radius: 10px;
    padding: 8px 14px;
    margin-right: 10px;
    background: var(--cor-roxo-claro);
    color: var(--cor-acento);
    font-family: inherit;
    font-weight: 800;
    font-size: 0.85rem;
    cursor: pointer;
}

/* Prévia da foto de perfil do aniversariante (form do evento) */
.foto-perfil-previa {
    display: block;
    width: 96px;
    height: 96px;
    border-radius: 50%;
    object-fit: cover;
    border: 3px solid var(--cor-borda);
    margin-bottom: 10px;
}

.btn-largo {
    width: 100%;
}

/* ⚠️ A SEÇÃO "Estatísticas (admin)" FOI REMOVIDA INTEIRA — as três regras eram
   CSS MORTO. `.estatistica`, `.estatistica-numero` e `.estatistica-rotulo` têm
   zero referências em `views/`, `app/`, `public/assets/js/` e `tests/`, varrido
   por mim antes de apagar. `.estatistica-numero` era a quarta das seis peças de
   `background-clip: text`; as outras duas saem junto porque eram os irmãos do
   mesmo componente, e apagar só o filho deixaria um contêiner órfão.
   Quem procurar as estatísticas do admin: elas são `.admin-stats`/`.stat`, que
   estão vivas e ficam noutra seção. */

/* ---------------- Links alternativos ---------------- */

.link-alternativo {
    margin-top: 20px;
    text-align: center;
    font-size: 0.92rem;
    color: var(--cor-texto-suave);
    font-weight: 600;
}

.link-alternativo a {
    color: var(--cor-acento);
    font-weight: 800;
    text-decoration: none;
}

.link-alternativo a:hover {
    text-decoration: underline;
}

/* ---------------- Rodapé ---------------- */

.rodape {
    border-top: 1px solid var(--cor-borda);
    padding: 16px 0;
    text-align: center;
    color: var(--cor-texto-suave);
    font-size: 0.85rem;
}

.rodape .desenvolvido {
    margin-top: 2px;
    font-size: 0.8rem;
}

.rodape a {
    color: var(--cor-acento);
    font-weight: 700;
    text-decoration: none;
}

.rodape a:hover {
    text-decoration: underline;
}

/* As regras de tela grande deste trecho migraram para o bloco `--bp-2` do fim do
   arquivo, com o mesmo valor (768px = 48rem). */


.sug-grade {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    gap: 12px; margin-top: 6px;
}

.sug-card .sug-ic { font-size: 1.9rem; display: block; margin-bottom: 6px; }


/* ----- Painel do dono (tema vibrante) ----- */
.icone-grade { display: flex; flex-wrap: wrap; gap: 8px; }
.icone-opcao { cursor: pointer; }
.icone-opcao input { position: absolute; opacity: 0; width: 0; height: 0; }
.icone-opcao span {
    display: flex; align-items: center; justify-content: center; width: 46px; height: 46px;
    font-size: 1.4rem; border: 2px solid var(--cor-borda); border-radius: 12px;
    background: var(--cor-cartao); transition: transform 0.12s, border-color 0.12s, background 0.12s;
}
.icone-opcao input:checked + span {
    border-color: var(--cor-acento); background: var(--cor-roxo-claro); transform: scale(1.06);
}
/* ⚠️ ANEL DE FOCO ESCRITO À MÃO — e ele é o pior dos quatro, porque foco é
   exatamente o que não pode sumir para quem depende dele. `#7c3aed` sobre o
   cartão escuro mede 2,71:1, abaixo do piso de 3:1; `--cor-acento` mede 6,70:1.
   ⚠️ A LARGURA E O DESVIO CONTINUAM CRAVADOS AQUI (`2px`), e isso é dívida
   registrada, não descuido: unificar os três tratamentos de foco do painel numa
   regra só é da F8, e trocar a COR sem mexer na forma é o que cabe nesta etapa.
   Os valores cravados coincidem com `--foco-largura`/`--foco-desvio`. */
.icone-opcao input:focus-visible + span { outline: 2px solid var(--cor-acento); outline-offset: 2px; }

.sug-lista-painel { list-style: none; }
.sug-item-painel {
    display: flex; align-items: center; gap: 12px; padding: 12px 2px;
    border-bottom: 1px solid var(--cor-borda);
}
.sug-item-painel:last-child { border-bottom: none; }
.sug-item-ic { font-size: 1.5rem; flex-shrink: 0; width: 30px; text-align: center; }
.sug-item-txt { flex: 1; min-width: 0; }
.sug-item-txt strong { display: block; font-size: 0.95rem; }
.sug-item-txt small { color: var(--cor-texto-suave); font-size: 0.82rem; }

/* ⚠️ PASTILHA E BLOCO SÃO DOIS CARGOS, E A DIREÇÃO B OS SEPAROU (TD-076).
   `--cor-aviso-fundo` é `--pastilha-ambar`: a superfície de um SELO — coisa
   pequena, com uma palavra dentro. Este aqui é um BLOCO de frase inteira, e o
   par de bloco é `--fundo-aviso`. Usar a pastilha nos dois faz o mesmo pigmento
   dizer duas coisas, que é o defeito que a `.btn-perigo` já corrigiu ao sair de
   `--cor-erro-fundo`. Medido com a tinta que já estava aqui (`--cor-aviso-texto`):
   5,59:1 no claro e 7,71:1 no escuro. */
.alerta-aviso {
    background: var(--fundo-aviso);
    border: 1px solid var(--cor-aviso-borda);
    color: var(--cor-aviso-texto);
}

/* ============================================
   Sugestões em 2 níveis: cards (categoria) + modal
   ============================================ */

.ico { width: 24px; height: 24px; display: block; }
.oculto { display: none; }

/* =============================================================================
   OS ÍCONES DE INTERFACE — o que substituiu os emoji da área autenticada
   =============================================================================
   TD-076, decisão do usuário em 2026-09-05. Emoji é glifo COLORIDO: ele não lê
   `currentColor`, então não acompanha pele, nem modo, nem estado — e cada
   aparelho desenha o seu. O desenho de traço acompanha os três de graça, porque
   a cor dele é a cor do texto ao lado.

   ⚠️ `.ico-biblioteca` É O SPRITE E ELE NÃO PODE SER `display: none`: em parte
   dos navegadores um ancestral com `display:none` impede o `<use>` de resolver
   o símbolo. `width/height: 0` + `position: absolute` tira a caixa do fluxo sem
   tirar o elemento da árvore de renderização — que é a diferença que faz os
   ícones aparecerem.

   ⚠️ `.ico-em-linha` NÃO TEM `width` FIXA EM PIXEL: ele acompanha a altura da
   linha em que mora (`1em`) e desce meio pixel com `vertical-align`, para que um
   ícone dentro de um `<h1>` cresça com o título e um dentro de um `<small>`
   encolha com ele. Ícone de 24px cravado dentro de uma legenda de 13px é o que
   fazia o emoji parecer maior que a frase. */
.ico-biblioteca {
    position: absolute;
    width: 0;
    height: 0;
    overflow: hidden;
}

.ico-em-linha {
    display: inline-block;
    width: 1em;
    height: 1em;
    vertical-align: -0.125em;
    flex: none;
}

/* Ícone que abre uma frase: ele fica na base da primeira linha e ganha um vão
   próprio, para o texto não encostar nele quando a frase quebrar. */
.ico-frase {
    margin-right: 0.45em;
}

/* ----- Convidado: acordeão de cards ----- */
.sug-acordeao { display: flex; flex-direction: column; gap: 10px; }

.sug-acc-head {
    width: 100%; display: flex; align-items: center; gap: 12px; padding: 14px;
    background: none; border: none; cursor: pointer; text-align: left; font-family: inherit;
}

.sug-acc-tit { flex: 1; min-width: 0; }

.sug-acc-seta {
    width: 9px; height: 9px; flex-shrink: 0; margin-right: 4px;
    border-right: 2px solid var(--ouro, var(--cor-primaria)); border-bottom: 2px solid var(--ouro, var(--cor-primaria));
    transform: rotate(45deg); transition: transform 0.25s;
}
.sug-acc.aberto .sug-acc-seta { transform: rotate(-135deg); }
.sug-acc-corpo { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; }
.sug-acc.aberto .sug-acc-corpo { max-height: 1200px; }
.sug-acc-inner { padding: 0 14px 14px; }

.sug-modal-lista { list-style: none; }
.sug-modal-lista li { padding: 12px 4px; border-bottom: 1px dashed var(--cor-borda); }
.sug-modal-lista li:last-child { border-bottom: none; }
.sug-modal-lista strong { display: block; color: var(--cor-texto); font-size: 1rem; }
.sug-modal-lista span { display: block; color: var(--cor-texto-suave); font-size: 0.84rem; margin-top: 2px; }
.sug-modal-vazio { color: var(--cor-texto-suave); text-align: center; }

/* ----- Painel: alternar tipo (card / sugestão) ----- */
.tipo-switch { display: flex; gap: 10px; margin-bottom: 18px; flex-wrap: wrap; }
.tipo-opcao { flex: 1; min-width: 130px; cursor: pointer; }
.tipo-opcao input { position: absolute; opacity: 0; }
.tipo-opcao span {
    display: block; text-align: center; padding: 12px; border: 2px solid var(--cor-borda);
    border-radius: 14px; font-weight: 800; color: var(--cor-texto-suave); background: var(--cor-cartao);
}
.tipo-opcao input:checked + span {
    border-color: var(--cor-acento); background: var(--cor-roxo-claro); color: var(--cor-acento);
}
.tipo-opcao input:disabled + span { opacity: 0.5; }

/* ----- Painel: seletor de ícone SVG ----- */
.icone-opcao span { color: var(--cor-texto-suave); }
.icone-opcao input:checked + span { color: var(--cor-acento); }

/* ----- Painel: blocos de card + itens ----- */
.cat-bloco { border: 1px solid var(--cor-borda); border-radius: var(--raio-peca); padding: 14px; margin-bottom: 14px; }
.cat-cabecalho { display: flex; align-items: center; gap: 12px; }
.cat-ic { color: var(--cor-acento); display: flex; flex-shrink: 0; }
.cat-ic .ico { width: 30px; height: 30px; }
.cat-info { flex: 1; min-width: 0; }
.cat-info strong { display: block; }
.cat-info small { color: var(--cor-texto-suave); font-size: 0.8rem; }
.cat-itens { list-style: none; margin-top: 12px; border-top: 1px solid var(--cor-borda); padding-top: 6px; }
.cat-itens li { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--cor-borda); }
.cat-itens li:last-child { border-bottom: none; }
.cat-item-txt { flex: 1; min-width: 0; }
.cat-item-txt strong { display: block; font-size: 0.92rem; font-weight: 700; }
.cat-item-txt small { color: var(--cor-texto-suave); font-size: 0.8rem; }
.cat-item-x { background: none; border: none; color: var(--cor-erro-texto); font-size: 1.4rem; line-height: 1; cursor: pointer; padding: 0 6px;
    border-radius: var(--raio-tecla); }
/* O ×  de remover é destrutivo: sob o dedo ele mostra a superfície da tecla de
   perigo, e não um cinza qualquer. Mesmo par de `.btn-perigo` em repouso. */
.cat-item-x:hover { background: var(--tecla-perigo); }
.cat-vazio { color: var(--cor-texto-suave); font-size: 0.88rem; margin-top: 10px; }

/* ============================================
   Painel: abas do evento + formulário em seções
   ============================================ */

/* CINCO PÍLULAS DESDE A T-0020, E NENHUM TOKEN MUDOU — isso é medido, não sorte.
   `flex-wrap: wrap` mais `flex: 0 0 auto` absorvem a quinta sozinhos. A soma dos
   cinco rótulos mais os quatro vãos dá 578,8 px (métrica média) a 620,9 px (peso
   800) contra 328 px de caixa em 360 px de tela: a barra QUEBRA em 2 ou 3 linhas.
   Diminuir o vão para `--e-1` foi testado antes de recusado — ganharia 16 px
   contra uma pílula de 110, e não remove linha nenhuma.
   ⚠️ ROLAGEM HORIZONTAL É PROIBIDA AQUI, contra a convenção de mercado que
   recomenda rolar abas em tela estreita. Três motivos, em ordem de peso: WCAG
   2.1 SC 1.4.10 (Reflow) exige refluxo em 320 px sem rolagem em duas dimensões e
   barra de navegação não é exceção; isto NÃO é um `role="tablist"` colado a um
   painel, são cinco `<a>` dentro de um `<nav>`, então o argumento do "modelo
   mental de uma linha" não se aplica; e "nenhuma rolagem horizontal em 360 px" é
   o requisito mais pesado do `layout.json`. Nada de `overflow-x`,
   `flex-wrap: nowrap` ou `scroll-snap` nesta regra.
   Os dois valores abaixo eram literais (`8px`/`20px`) cujos tokens já existiam:
   apontá-los é REAPONTA-TOKEN, e diferença visual aqui seria REGRESSÃO. */
.evento-abas {
    display: flex; gap: var(--e-2); margin-bottom: var(--e-5); flex-wrap: wrap;
}
/* -----------------------------------------------------------------------------
   ⚠️ A ABA ATIVA SAI DO GRADIENTE, E É O MESMO DEFEITO QUE `.admin-link.ativa` E
   `.admin-av.grad` JÁ TINHAM CORRIGIDO — ESTA TINHA FICADO PARA TRÁS
   -----------------------------------------------------------------------------
   O rótulo tem 0,85rem/800 (13,6px: TEXTO NORMAL, piso 4,5:1) e o branco sobre
   `--grad` mede 5,70:1 na parada roxa e 4,60:1 na parada rosa — o mesmo rótulo
   muda de razão ao longo de si mesmo e o pior ponto raspa o piso. É a §14.6
   desta folha, aplicada num terceiro lugar.
   O que entra é o tratamento da direção B para item de navegação selecionado
   (`.rail a[aria-current]` da cabine): a superfície AFUNDA um degrau
   (`--sup-press`) e quem diz "é este" é um FIO DE ACENTO interno de 2px — que
   sobrevive a daltonismo e a impressão em preto e branco, porque é posição e
   não cor. Medido: rótulo 12,07:1 no claro e 12,61:1 no escuro; o fio de acento
   5,06:1 e 6,27:1 contra a superfície pressionada (piso de objeto gráfico: 3:1).
   A PÍLULA SAI JUNTO: aba não é selo, é controle — `--raio-tecla`.
   -------------------------------------------------------------------------- */
.evento-aba {
    flex: 0 0 auto; padding: 8px 16px; text-decoration: none; font-weight: 800; font-size: 0.85rem;
    font-family: var(--f-display);
    color: var(--cor-texto-suave); background: var(--cor-cartao); border: 1px solid var(--fio-2);
    border-radius: var(--raio-tecla); white-space: nowrap; transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.evento-aba:hover { color: var(--cor-texto); background: var(--sup-hover); border-color: var(--cor-acento); }
.evento-aba.ativa { color: var(--cor-texto); background: var(--sup-press); border-color: var(--fio-2);
    box-shadow: inset 2px 0 0 var(--acento); }

/* ⚠️ ESTA É A PEÇA MAIS REPETIDA DAS DUAS SUPERFÍCIES, e era ela que mantinha a
   tela com cara da paleta anterior mesmo depois de os tokens trocarem: raio de
   18px (o degrau da paleta de festa) e uma sombra em `rgba(60,40,20,…)` — um
   MARROM, que não é a tinta de nenhuma das duas peles. `--raio-peca` é o degrau
   de peça da direção B e `--elev-1` é a sombra do sistema, que já sabe ser rasa
   no papel claro (sombra pesada em claro lê como sujeira) e profunda no escuro,
   onde o fio não separa e quem separa é o degrau mais a sombra. */
.form-secao {
    background: var(--cor-cartao); border: 1px solid var(--cor-borda); border-radius: var(--raio-peca);
    margin-bottom: 16px; overflow: hidden; box-shadow: var(--elev-1);
}
.secao-cab { padding: 16px 20px 13px; border-bottom: 1px solid var(--cor-borda); background: var(--cor-roxo-claro); }
.secao-cab h2 { font-family: var(--f-display); font-size: 1.08rem; font-weight: 800; letter-spacing: -0.015em; }
.secao-cab p { color: var(--cor-texto-suave); font-size: 0.86rem; margin-top: 2px; }
.secao-corpo { padding: 18px 20px; }

/* Formulários do painel: mais compactos e proporcionais (não afeta login/convite) */
.form-secao .campo { margin-bottom: 13px; }
.form-secao .campo label { font-size: 0.84rem; margin-bottom: 4px; }
/* ⚠️ ERA `min-height: 42px`, E 42 NÃO É UM NÚMERO: a primeira linha deste
   arquivo escreve a regra da casa — "áreas de toque com mínimo de 44px" — e o
   formulário compacto do painel passava 2px por baixo dela em TODO campo de
   TODA tela do dono e do admin. O alvo agora sai do token, então não há como os
   dois divergirem de novo. Custo: 2px por campo. O `font-size: 16px` da regra
   base continua valendo aqui (é ele que impede o zoom automático do iOS) — o
   compacto encolhe o RESPIRO, nunca a letra. */
.form-secao .campo input,
.form-secao .campo select,
.form-secao .campo textarea {
    min-height: var(--alvo-toque); padding: 9px 13px; border-radius: 10px; font-weight: 600;
}
.form-secao .campo-dica { font-size: 0.78rem; }
/* Botão de ação dentro de uma seção: largura automática e tamanho proporcional.
   ⚠️ T-0031 4a (BUG-TD-136): a `box-shadow: 0 6px 16px -8px rgba(124, 58, 237,
   .5)` SAIU daqui. Era o brilho violeta do `.btn` antigo, sobrevivendo num
   seletor (0,3,0) que vencia a decisão nova de `.btn` — `--elev-1`, e `--elev-2`
   sob o ponteiro — em TODO botão de formulário do painel e do admin, nas duas
   peles (medido na engine: "Adicionar à lista" e "Baixar QR Code" carregavam o
   brilho). Sem a linha, o botão da seção segue o contrato de `.btn` inteiro,
   inclusive o `:hover`, que antes ficava preso por especificidade. */
.form-secao .secao-corpo .btn {
    width: auto; min-height: var(--alvo-toque); padding: 10px 22px; font-size: 0.92rem;
}

/* DOIS CAMPOS LADO A LADO QUANDO OS DOIS CABEM — medido na caixa, não na
   janela. 15rem (240px) é a largura em que um `<input type="date">` mostra o
   widget nativo inteiro sem cortar. Duas colunas a partir de 496px DE CAIXA,
   que no cartão do painel é ~570px de tela: dez pixels depois dos 560 de antes.
   ⚠️ O GANHO DE VERDADE ESTÁ NO DESKTOP, E ELE CONSERTA UM CORTE. O segundo
   `.campo-grid` da tela do evento (`views/painel/evento.php:400`, Tipo da chave
   + chave PIX) mora dentro de `.coluna-lado`, que a partir de 64rem é a FAIXA
   DE 360px de `.grade-painel.inverso`. Seguindo a cadeia: 360 → `.form-secao`
   358 → `.secao-corpo` 318. A media query antiga perguntava se a JANELA tinha
   560; com 1024 ela tinha, e abria duas colunas de 151px numa caixa de 318 —
   dentro de uma delas, um `<select>` cuja opção mais longa é `Chave aleatória`,
   que não cabe em 151px com seta e recuo. Como as trilhas de um `1fr` não
   descem abaixo do conteúdo mínimo do item, a grade estourava a caixa; e como
   `.form-secao` tem `overflow: hidden`, o excedente era CORTADO, não rolado.
   Medindo a caixa, esse trecho fica em UMA coluna de 318px e o corte
   desaparece. É o retrato do defeito que a conversão inteira ataca: a media
   query de viewport acertava a tela e errava a caixa. */
.campo-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: 0 16px; }

.opcional {
    display: inline-block; font-size: 0.66rem; font-weight: 800; text-transform: uppercase;
    /* ⚠️ O FUNDO ERA `--cor-borda`, E ISSO REPROVAVA: `--cor-borda` é FILETE
       DECORATIVO e é isento de limiar justamente porque ninguém escreve em cima
       dele — usá-lo como SUPERFÍCIE de uma pastilha com texto tira a isenção e
       cobra 4,5:1. `--cor-texto-suave` sobre `#ece7f7` mede 4,38:1 e sobre
       `--cor-neutro-fundo` mede 4,66:1, que é o par que o design system já
       publica medido. Achado por varredura da TELA RENDERIZADA, em 16 telas nos
       dois modos — nenhuma das listas N1..N14 o tinha, porque ele nasce da
       COMBINAÇÃO de dois tokens certos usados em cargos trocados. */
    letter-spacing: 0.04em; color: var(--cor-texto-suave); background: var(--cor-neutro-fundo);
    border-radius: var(--raio-pilula); padding: 2px 8px; vertical-align: middle; margin-left: 4px;
}

.campo-checkbox { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 0.88rem;
    margin-top: 10px; cursor: pointer; padding: 10px 13px; border: 1.5px solid var(--cor-borda);
    border-radius: 10px; color: var(--cor-texto); transition: border-color 0.15s, background 0.15s; }
.campo-checkbox:hover { border-color: var(--cor-acento); background: var(--cor-roxo-claro); }
/* ⚠️ T-0031 4a (BUG-TD-136): `accent-color` lia a MARCA. Passa ao acento, que
   clareia no escuro — 6,51:1 no claro e 7,18:1 no escuro contra o cartão, onde
   `#7c3aed` media 2,80:1 (reprovava 1.4.11). O glifo é escolha do navegador
   pela luminância do acento (branco sobre #5c31f6 = 6,51; preto sobre #b3a1ff = 9,46). */
.campo-checkbox input[type="checkbox"] { width: 19px; height: 19px; min-height: 0; accent-color: var(--cor-acento); flex-shrink: 0; cursor: pointer; }

/* -----------------------------------------------------------------------------
   `.campo-curto` — o campo cujo CONTEÚDO é curto (idade: 1 a 3 sinais)
   -----------------------------------------------------------------------------
   `.campo input` é `width: 100%`, que é o certo para texto livre e é ruim para
   um número de até três dígitos: a caixa promete um parágrafo. O rótulo, a dica
   e a área de toque continuam com a largura inteira — o que encolhe é só a
   caixa. Largura em `rem` porque este arquivo não tem escala de largura para
   respeitar (a única é `--coluna-convite`, que é a coluna do convite).
   -------------------------------------------------------------------------- */
.campo-curto input { max-width: 9rem; }

/* =============================================================================
   `.escolha-visual` — A FILEIRA DE ESCOLHA DO VISUAL DO CONVITE (RF-019)
   =============================================================================
   O único componente realmente novo da T-0015. Anatomia do `especialista-ui`
   (§3.5) mais os requisitos de acessibilidade do `especialista-ux` (§1.7).

   ⚠️ A MINIATURA É DESENHADA PELOS PRÓPRIOS TOKENS DO VISUAL — NÃO É IMAGEM.
   O `<span>` da miniatura recebe a classe do visual (`.visual-classico`,
   `.visual-jardim`), que é exatamente o mesmo bloco de tokens que veste o
   `<body>` do convite; as regras abaixo consomem `--envelope` e `--ouro` de
   lá. ZERO byte novo, ZERO requisição nova e ZERO possibilidade de a miniatura
   divergir do visual real — uma captura de tela divergiria no dia seguinte à
   primeira repintura. Visual novo aparece na fileira sem uma linha de CSS nova.

   O PORTÃO DOS 96 px ESTÁ MEDIDO: os dois envelopes diferem em 3,03:1 de
   luminância entre si (#1e2c4f L=0,0264 · #6b7c53 L=0,1817 — conferido por mim
   nesta etapa). Acima de 3:1 eles se distinguem por LUMINÂNCIA e não só por
   matiz, isto é, também para quem não separa verde de azul. Somados ao nome
   sempre visível e à marca `✓ Escolhido`, são TRÊS sinais não cromáticos.

   NOMENCLATURA QUE NÃO É ENFEITE: nenhuma destas classes pode começar por
   `.visual-`. A varredura permanente (`tests/Unit/Contrato_do_visual_test.php`)
   casa `\.visual-[a-z-]+\s*\{` e EXIGE que o bloco contenha só linhas de token
   — um `.visual-miniatura { background: … }` reprovaria a suíte inteira, e com
   razão: seria um visual mudando a FORMA de alguma coisa.
   ============================================================================= */

/* MEDIDO NA ETAPA 7 — a fileira foi conferida em aparelho e o VEREDITO É QUE
   ELA JÁ ESTAVA CERTA. A cadeia de caixas, seguida elemento a elemento a partir
   do HTML real (`views/painel/evento.php`: a seção mora dentro de
   `.coluna-lado`, que é a faixa de 360px de `.grade-painel.inverso` — NÃO a
   coluna larga):
     · 360px de tela → `.container` 328 → `.form-secao` 326 → `.secao-corpo` 286
       → coluna de 137px → miniatura de 109×96. `Clássico` (~65px) e
       `✓ Escolhido` (~75px) cabem, e o alvo de toque mede 137×172 — três vezes
       o mínimo de 44. Nada a corrigir.
     · 320px → coluna de 117, miniatura 89×96. Ainda cabe.
     · 1160px → a faixa lateral tem 360, então `.secao-corpo` tem 318 e a coluna
       fica em 153px, com a miniatura em 125×96. O desktop também já estava bem,
       e é por isso que a fileira NÃO ganhou breakpoint nenhum.
   O que mudou, então, e por quê:
     · `auto-fit`/`minmax(7rem, 1fr)` acrescenta o PISO que não existia: abaixo
       de ~268px de caixa (aparelho dobrado fechado, ou fonte do sistema
       aumentada) a fileira vira pilha em vez de espremer dois cards de 97px. E
       um terceiro visual entra numa linha de três sem uma linha de CSS nova, que
       é o que o comentário abaixo promete e o `1fr 1fr` não cumpria.
     · `max-width: 28rem` é TETO PREVENTIVO e hoje não é alcançado por nenhuma
       largura de tela — está aqui porque a seção pode mudar de coluna na T-0016,
       e na coluna larga (~780px) o `1fr` daria cards de 363 com a miniatura em
       3,8:1: um envelope achatado nessa proporção deixa de parecer envelope. */
.escolha-visual {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
    max-width: 28rem;
    gap: var(--e-3);
    /* `<fieldset>` traz borda, padding e margem do navegador. Ele está aqui
       pelo AGRUPAMENTO semântico (com `aria-labelledby` no `<h2>` da seção),
       não pela moldura. */
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;
}

.escolha-visual-opcao {
    display: block;
    position: relative;
    cursor: pointer;
}

/* ⚠️ NUNCA `display: none` NEM `visibility: hidden` NESTE INPUT. As duas tiram
   o campo da ordem de tabulação E da árvore de acessibilidade — o grupo
   deixaria de existir para quem navega por teclado ou por leitor de tela. O
   rádio continua no fluxo, apenas recolhido; é a mesma técnica que
   `.icone-opcao` já usa no formulário de sugestões. */
.escolha-visual-opcao input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

.escolha-visual-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--e-2);
    padding: var(--e-3);
    background: var(--cor-cartao);
    /* A LARGURA É 2px NOS TRÊS ESTADOS e só a COR muda. O design system pede
       `--cor-borda` em repouso, `--limite` sob o dedo e 2px `--foco` no
       selecionado; alternar 1px/2px faria o card inteiro pular ao ser
       escolhido, e movimento que ninguém pediu num grupo de escolha lê como
       defeito. Esta borda NÃO é limite de componente no sentido da WCAG
       1.4.11: o controle se identifica pela miniatura e pelo nome, então
       `--cor-borda` é o token certo para o repouso. */
    border: 2px solid var(--cor-borda);
    border-radius: var(--raio-lg);
    transition: border-color 0.15s, background 0.15s;
}

.escolha-visual-opcao:hover .escolha-visual-card {
    border-color: var(--limite);
}

.escolha-visual-opcao input:checked + .escolha-visual-card {
    border-color: var(--foco);
    background: var(--cor-roxo-claro);
}

/* O anel de foco aparece NO CARD quando o rádio recebe foco. Sem isto, quem
   navega por teclado não sabe onde está — e `outline: none` sem substituto
   medido ≥ 3:1 é defeito, não estilo. */
.escolha-visual-opcao input:focus-visible + .escolha-visual-card {
    outline: var(--foco-largura) solid var(--foco);
    outline-offset: var(--foco-desvio);
}

.escolha-visual-miniatura {
    display: block;
    width: 100%;
    /* 96 px é o portão do designer: é nesta altura que os dois visuais têm de
       se distinguir. */
    height: 96px;
    border-radius: var(--raio-md);
    background: var(--envelope);
    /* O FILETE DE OURO, em duas camadas de sombra interna e sem custar caixa:
       a primeira repinta a borda de 4 px com o próprio envelope, a segunda
       desenha 5 px de ouro por baixo — sobra 1 px de ouro, recuado 4 px da
       margem. É filete, não moldura. */
    box-shadow: inset 0 0 0 var(--e-1) var(--envelope), inset 0 0 0 5px var(--ouro);
}

/* `--fs-3` E NÃO `0.92rem`, e a troca é MEDIDA (T-0020). O literal antigo não
   estava em escala nenhuma — era fuga de token — e o degrau até a faixa de
   inventário era de 1,12 px (razão 1,082). Com `--fs-3` a razão vai a 1,176, o
   mesmo patamar do `.termos h3 → h4` que esta casa já aceitou.
   ⚠️ ZERO MUDANÇA DE QUEBRA, conferido antes de aplicar: `Princesa e Sapo` mede
   111,2 px a 14,72 px e 120,9 px a 16 px — quebra nos DOIS casos no card de
   109 px (tela de 360) e cabe nos DOIS no card de 190 px (largura de projeto).
   Consumidor desta regra depois da T-0020: UM, o card de tema. As três seções
   que a vestiam em `evento.php` saíram na mesma entrega. */
.escolha-visual-nome {
    font-size: var(--fs-3);
    font-weight: 800;
    color: var(--cor-texto);
    text-align: center;
}

/* =============================================================================
   `.escolha-visual-pecas` — A FAIXA DE INVENTÁRIO DO CARD DE TEMA (T-0020)
   =============================================================================
   Três linhas por card, sempre na mesma ordem (capa → ilustração → selo), e é
   ela que responde "o tema leva figura e selo junto?". Sem ela o card mente por
   omissão. As palavras saem de `TemaDoConvite::pecas()`, nunca da folha nem da
   view.

   ⚠️ NO HTML ELA É IRMÃ DA MINIATURA, NUNCA DESCENDENTE DELA. O `<span>` da
   miniatura carrega `.visual-classico`/`.visual-jardim`, e esses blocos
   REDECLARAM `--cor-texto`, `--cor-texto-suave`, `--cor-cartao` e `--cor-borda`
   com os valores do CONVITE — que não seguem o modo escuro do painel. Aninhada
   ali, a faixa cairia para 1,05:1 / 1,24:1 / 2,12:1 / 2,35:1 no escuro, e no
   claro TODOS os pares passam: é o defeito que só existe com a luz apagada
   (mesma forma do BUG-TD-071). A pele do convite é FOLHA da árvore: não pode ter
   filho de texto.

   O TAMANHO É MEDIDO, NÃO ESCOLHIDO. Na largura de projeto o card tem 190 px de
   caixa interna, e `Cores: marinho e dourado` (24 caracteres) mede 193,4 px a
   `--fs-3` — estouraria e a faixa nasceria com 4 linhas onde foi desenhada para
   ter 3. A `--fs-1` quebra exatamente as mesmas 4 das 6 linhas que `--fs-2`
   quebra em 360 px, e entrega 11,2 px de corpo: menor por menor. `--fs-2` é o
   MAIOR degrau da escala que mantém a faixa em TRÊS linhas na largura de
   projeto.

   O `gap` é `--e-1` e a entrelinha é `--lh-apertado`, e os dois são coisas
   diferentes de propósito: `--e-1` separa ITENS, `--lh-apertado` é a entrelinha
   DENTRO de um item que quebra. Entrelinha solta num item de lista curto empurra
   o card sem ganhar leitura.

   PROIBIDO AQUI: `text-overflow: ellipsis`, `white-space: nowrap` e
   `-webkit-line-clamp`. Inventário recortado é inventário mentiroso — o dono
   precisa saber que o tema troca o selo. Linha que não cabe QUEBRA (4 das 6
   quebram em 360 px), e altura fixa no card reprovaria a WCAG 1.4.12: com
   espaçamento de texto forçado a pior linha vai a 210 px num card de 190 e
   precisa poder virar duas linhas sem perder conteúdo.

   ALINHADA À ESQUERDA NUM CARD CENTRADO, e é a arbitragem que faz a faixa
   existir: o dono compara os dois cards LINHA A LINHA, e comparação exige aresta
   compartilhada. Centradas, `Cores: marinho e dourado` (24) e
   `Cores: oliva e dourado` (22) começam em abscissas diferentes e o olho perde a
   correspondência no par que veio comparar. Contado dentro do card de 190 px:
   5 saltos na borda esquerda com a faixa centrada, 3 com ela à esquerda — e os 3
   que sobram são o nome e a marca, que são etiquetas de uma linha e não blocos
   de leitura. A regra "uma borda esquerda" do `layout.json` se aplica à relação
   ENTRE os dois cards, não à vertical interna de um card de 137 px, onde o olho
   toma o card como um glifo só.

   NENHUMA TRANSIÇÃO, e a ausência é regra: se alguém acrescentar uma, ela entra
   na regra de `prefers-reduced-motion` lá embaixo junto com a da borda — mas a
   VISIBILIDADE da marca `✓ Escolhido` não, porque ela é feedback de estado.
   ============================================================================= */
.escolha-visual-pecas {
    display: grid;
    gap: var(--e-1);
    /* A faixa é quem dá o eixo esquerdo do card. Sem isto ela seria centrada
       pelo `align-items: center` do card e sairia do tamanho do texto — o mesmo
       motivo pelo qual a miniatura também declara `width: 100%`. */
    width: 100%;
    text-align: left;
}

.escolha-visual-peca {
    font-size: var(--fs-2);
    line-height: var(--lh-apertado);
    /* O VALOR É O QUE MUDA ENTRE OS DOIS CARDS, então ele AVANÇA: tinta cheia e
       um degrau de peso acima do rótulo — um, não dois, porque `800` colidiria
       com o nome do tema. Medido sobre as duas superfícies em que a faixa vive,
       nos dois modos: 14,92:1 e 13,41:1 no claro, 12,04:1 e 12,53:1 no escuro. */
    font-weight: 700;
    color: var(--cor-texto);
}

/* O RÓTULO É ANDAIME REPETIDO IGUAL NOS DOIS CARDS (`Cores:`, `Ilustração:`,
   `Selo:`), então ele RECUA. A linha sem rótulo — `Sem ilustração`, a única das
   seis — sai inteira como valor, que é o que ela é.
   ⚠️ O PAR APERTADO, DECLARADO: sobre o card ESCOLHIDO (`--cor-roxo-claro`) no
   modo claro este rótulo mede 4,77:1, com 0,27 de folga sobre o piso de 4,5:1
   (`--fs-2` a peso 600 não é texto grande). Sobre o card não escolhido mede
   5,31:1, e no escuro 6,32:1 e 6,08:1. Aceito por CARGO: `--cor-texto-suave`
   existe exatamente para ser texto secundário em superfície de painel, e trocar
   por `--cor-neutro-texto` seria vazamento de cargo (a forma do BUG-TD-073).
   CONSEQUÊNCIA QUE FICA ESCRITA: `--cor-roxo-claro` NÃO PODE ESCURECER mais de
   um degrau sem que este par seja remedido. */
.escolha-visual-peca-rotulo {
    font-weight: 600;
    color: var(--cor-texto-suave);
}

/* A marca de escolhido é TEXTUAL, não só a borda, e está nos DOIS cards: quem
   a mostra é o `:checked`, porque a troca acontece no toque, sem recarregar a
   página. `visibility` e não `display` para o card não mudar de altura quando o
   dono troca de visual. Ela já leva `aria-hidden` na marcação — o rádio nativo
   anuncia "marcado" sozinho. */
/* ⚠️ O `✓` DELA TAMBÉM É COPY, e não ícone: `docs/T-0020-especificacao-ux-temas.md`
   :175 escreve `✓ Escolhido` e há caso de aceite cobrando a marcação inteira.
   Ficou fora da varredura de emoji da T-0031 pelo mesmo motivo do `▾`. */
.escolha-visual-marca {
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.04em;
    color: var(--cor-acento);
    visibility: hidden;
}

.escolha-visual-opcao input:checked + .escolha-visual-card .escolha-visual-marca {
    visibility: visible;
}

.escolha-visual-apoio {
    margin-top: var(--e-3);
    font-size: 0.8rem;
    color: var(--cor-texto-suave);
}

/* O RESPIRO ENTRE A ÚLTIMA LINHA DE APOIO E O BOTÃO `Aplicar tema` (T-0020).
   A folha zera toda margem no `*`, e `.escolha-visual-apoio` só declara
   `margin-top` — sem esta regra o botão encostaria no texto e leria como se
   pertencesse à última frase, e não à seção. Nas telas irmãs esse respiro vem
   de graça do `margin-bottom` de `.campo`, que aqui não existe: entre a fileira
   e o botão não há campo nenhum.
   ⚠️ POR QUE NÃO EM `.form-secao .secao-corpo .btn`: aquela regra veste também
   `presentes.php` e `convidados.php`, onde o botão JÁ recebe 18px do `.campo`
   acima dele — somar 16 ali seria mexer em três telas para consertar uma. E não
   em `.escolha-visual-apoio` direto, porque isso afastaria também a PRIMEIRA
   linha de apoio da segunda, que é um par e foi desenhado junto. */
.escolha-visual-apoio + .btn {
    margin-top: var(--e-4);
}

/* A troca de card marcado é FEEDBACK e permanece; o que sai aqui é a transição
   decorativa da cor da borda. */
@media (prefers-reduced-motion: reduce) {
    .escolha-visual-card { transition: none; }
}

.foto-upload { display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; }
.foto-perfil-previa {
    width: 84px; height: 84px; border-radius: 50%; object-fit: cover;
    border: 3px solid var(--cor-cartao); box-shadow: 0 0 0 2px var(--cor-borda); flex-shrink: 0;
}
.foto-placeholder { display: flex; align-items: center; justify-content: center; background: var(--cor-roxo-claro); color: var(--cor-texto-suave); }
.foto-placeholder .ico { width: 32px; height: 32px; }
.foto-upload-campo { width: 100%; min-width: 0; }
.foto-upload-campo input[type="file"] {
    display: block; width: 100%; max-width: 100%; box-sizing: border-box;
    border: 1px solid var(--limite); border-radius: 10px; padding: 9px 10px;
    font-size: 0.82rem; font-weight: 600; background: var(--cor-cartao); color: var(--cor-texto); margin-bottom: 12px;
}
.foto-upload-campo input[type="file"]::file-selector-button {
    border: none; border-radius: 8px; padding: 7px 12px; margin-right: 8px;
    background: var(--cor-roxo-claro); color: var(--cor-acento);
    font-family: inherit; font-weight: 800; font-size: 0.8rem; cursor: pointer;
}

/* ⚠️ ESTA ERA A ÚNICA `max-width` DO ARQUIVO, e por isso ela foi invertida.
   `max-width` é desktop-first: o estilo base descrevia a tela grande e a media
   query CORRIGIA o celular. Numa folha que se declara mobile-first isso não é
   estilo, é a direção errada — quem lê a regra base lê o caso raro, e o caso
   comum vive dentro de uma exceção. Agora a base é a coluna (celular) e o
   `--bp-1` abre a linha.
   MUDANÇA DECLARADA, e é de UM pixel de fronteira: `max-width: 480px` INCLUÍA
   480; `min-width: 30rem` também inclui 480. Em exatamente 480px de viewport a
   fileira passa a ser linha, e antes era coluna. Acima e abaixo, nada muda. */
.form-acoes { display: flex; flex-direction: column-reverse; gap: 12px; align-items: stretch; }
.form-acoes .btn, .form-acoes .btn-secundario { width: 100%; }

/* ============================================
   Painel admin (dashboard) + modo manutenção
   ============================================ */

/* A lateral do admin migrou para o bloco `--bp-3` do fim do arquivo, e o VALOR
   MUDOU: 820px → 64rem (1024px). O motivo é medido e é do `designer-visual`
   (§A.2): em 820px a coluna de conteúdo do admin fica com 820 − 32 − 230 − 18 =
   540px, e dentro dela mora uma TABELA DE SETE COLUNAS — 77px por coluna. A
   lateral aparecia antes de o conteúdo caber. Em 1024 a mesma conta dá 734px, e
   a lateral sobe de 230 para 15rem (240px) para ficar na escala. */
/* ⚠️ `minmax(0, 1fr)` E NÃO `1fr` — É AQUI QUE MORRE O BUG-TD-074.
   `1fr` é `minmax(auto, 1fr)`: o PISO da faixa é o `min-content` do que mora
   dentro dela, e o que mora aqui é uma tabela de sete colunas cujo `min-content`
   MEDIDO é 873px. O resultado era a faixa inteira nascendo com 891px em 375, 768
   E 900px de janela — a lateral, o cabeçalho e a tabela os três com a MESMA
   largura de 891 — e o documento rolando na horizontal nas duas maiores. Em
   375px o efeito era pior e mais escondido: o navegador esticava a própria
   viewport para 908px, e a conta `scrollWidth <= innerWidth` PASSAVA enquanto a
   tela estava errada.
   Com o piso em `0` a faixa passa a valer o que a janela dá, e a tabela volta a
   rolar DENTRO de `.admin-tabela-corpo` — que é `overflow-x: auto` desde sempre e
   nunca chegava a rolar, porque a caixa crescia junto com o conteúdo.
   ⚠️ Vale para os DOIS estados da grade: o de uma coluna aqui e o de duas em
   `--bp-3`. Lá 15rem + vão saem de 976 úteis e sobram 718 para a tabela de 873:
   sem o piso zero, o admin estouraria em 1024px também. */
.admin { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; }

/* =============================================================================
   O QUE SAIU DA FOLHA NA T-0031 ETAPA 3e — e COMO ISSO FOI PROVADO
   =============================================================================
   A etapa 3 trocou a marcação do console pela da cabine. Estas famílias
   pararam de nascer e saíram daqui — REMOÇÃO, não repintura, em tarefa própria
   e com medição, como o bloco de `.cabine-tecla` (§8) tinha escrito que seria:

       .admin-nav   .admin-nav-titulo   .admin-nav nav   .admin-link (+ :hover,
       :active, .ativa, .desabilitado, .desabilitado:hover, .ativa .admin-cont)
       .admin-cont   .admin-acao (+ :hover, :active, :disabled,
       [aria-disabled], .admin-conta .admin-acao, [aria-labelledby=…])
       .admin-conta-cab (+ .admin-conta-bancada > …)   .admin-tav (+ .admin-sub)
       .status-pill (+ .status-pill .ico-em-linha)

   ⚠️ A PROVA DE CADA UMA É DUPLA, e uma só não bastaria:
     1. AUSENTE NO DOM SERVIDO. 26 telas do sistema (as 5 seções do console, as
        5 do dono, o convite em 4 estados, a galeria em 3, login, cadastro,
        termos, aceite, troca de senha, prazo encerrado, 404 e a página do modo
        manutenção com o modo LIGADO), renderizadas pelo Apache com as fixtures
        de aceite e lidas por `DOMDocument` — 52 renderizações, NAS DUAS PELES.
        Não é `grep` no fonte: no fonte as oito só aparecem DENTRO de comentário
        (o mesmo engano que já contou `.cabine-pular` num comentário e declarou
        pendente uma etapa pronta), e `.admin-cont` casaria com `.admin-conteudo`
        e `.admin-contas`, que estão VIVAS.
     2. SEM LEITOR EM JAVASCRIPT. Varridos os quatro arquivos de
        `public/assets/js/` — classe sem regra pode ser gancho de comportamento
        (`.form-excluir` é exatamente isso), e varredura que só olha a folha
        acusaria o gancho e ensinaria o time a ignorar o próprio alarme.

   ⚠️ `.admin-av` FICOU, E ELA ESTAVA NA LISTA QUE ME MANDARAM REMOVER: ela é
   emitida seis vezes na Visão geral e na seção Usuários, nas duas peles. O que
   já tinha saído era o modificador `.admin-av.grad`, e confundir os dois teria
   apagado o disco da inicial de cada conta. A lista era hipótese; a medida é
   que decide.
   ============================================================================= */

/* ⚠️ `.admin-link-ic` FICA, E É DECISÃO DE ESCOPO E NÃO DE MEDIDA: ela tem a
   MESMA prova das de cima (ausente nas 52 renderizações, sem leitor em JS), mas
   não estava na lista desta etapa. Sobrar regra morta é barato; remover regra
   que ninguém pediu para remover é diff que o próximo tem de auditar sem mandato.
   Vai no relatório junto com as outras 94 medidas nesta varredura. */
.admin-link-ic { width: 22px; text-align: center; font-size: 1.05rem; }

/* -----------------------------------------------------------------------------
   FOCO — UM anel para o admin inteiro (N14)
   -----------------------------------------------------------------------------
   O produto já tem três regras irmãs desta, com o mesmo corpo e o mesmo motivo:
   `.tema-vitrine :focus-visible` (a página inicial, desde a T-0017), `.painel-palco :focus-visible` e
   `.tema-convite :focus-visible`. O admin era a família que ainda confiava no
   padrão do navegador por cima de superfícies coloridas.
   ⚠️ A REGRA DECLARA `outline` E `outline-offset`, E NADA MAIS. `border-radius`
   numa regra de `:focus-visible` esquadra toda pílula do produto no instante do
   foco de teclado — foi o defeito R2, achado em duas regras na T-0015. A forma é
   do componente; o foco é o anel, e o anel já acompanha o raio sozinho.
   A chave tem regra própria (mais abaixo) porque o `<input>` dela é 0×0 e está
   em `opacity: 0`: o anel dela precisa nascer no TRILHO, que é a peça que se vê.
   -------------------------------------------------------------------------- */
.admin :focus-visible {
    outline: var(--foco-largura) solid var(--foco);
    outline-offset: var(--foco-desvio);
}
.em-breve { margin-left: auto; font-family: var(--f-display); font-size: 0.6rem; font-weight: 800;
    text-transform: uppercase; background: var(--cor-borda); color: var(--cor-texto-suave);
    border-radius: var(--raio-pilula); padding: 2px 7px; }

/* =============================================================================
   ⚠️ OS QUATRO CARTÕES DE INDICADOR DO ADMIN SAÍRAM DAQUI (T-0016, §B.4)
   =============================================================================
   Eram sete regras — `.admin-stats`, `.stat`, `.stat-top`, `.stat-ic`,
   `.stat-trend`, `.stat-num`, `.stat-rot` — e as sete tinham UM consumidor só,
   `views/admin/index.php`. Com o bloco fora da view elas ficaram sem nenhum, e
   por isso a correção aqui é REMOÇÃO e não repintura: repintar regra que tela
   nenhuma renderiza é gastar anatomia em CSS morto.

   POR QUE OS CARTÕES SAÍRAM, e a razão é medida e não estética: dois dos quatro
   mostravam `$totalUsuarios` e `$totalEventos` — os MESMOS dois números que os
   contadores da lateral já mostram, na mesma tela, a 240px de distância. O mesmo
   fato duas vezes. No lugar dos quatro ficaram O FAROL (o consumo do mês contra
   o teto, o único número desta tela com consequência — RN-045/RN-047) e uma
   fileira de inventário com os dois números que sobraram, em `.stats-fila` /
   `.stat-chip`, que JÁ EXISTIAM e já são número em tinta.

   ⚠️ E É AQUI QUE `background-clip: text` FECHA EM 1 NA FOLHA INTEIRA.
   `.stat-num` era a dívida declarada da passagem do painel do dono — está
   escrito com todas as letras em `tests/Unit/Contrato_do_visual_test.php`, numa
   lista branca por IGUALDADE. Com esta remoção a lista fica com uma peça só,
   `.inicio-passos li::before`, aprovada na T-0015 com piso de 24px justificado —
   e a lista branca do teste FOI EDITADA junto, porque lista que se ajusta
   sozinha não guarda nada. A T-0017 levou essa última peça junto com a página
   (TD-082: o desenho novo não tem texto em degradê), e a lista ficou VAZIA.

   NÃO CONFUNDIR COM `.stat-numero`/`.stat-rotulo`/`.stat-chip`/`.stats-fila`:
   nomes parecidos, componente OUTRO — são os chips da lista de convidados do
   dono (`views/painel/convidados.php`), continuam vivos e agora servem também o
   inventário do admin. A §14.6 do design system afirma que `.stat-num` também
   renderizava em `painel/convidados.php`; varri as views e NÃO renderiza — o que
   existe lá é `.stat-numero`. Um `-o` de diferença.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   A LINHA DE INVENTÁRIO — o que sobrou dos quatro cartões
   -----------------------------------------------------------------------------
   Convidados e Confirmados: os dois números que NÃO estavam duplicados na
   lateral. Eles são inventário — crescem sozinhos e ninguém age sobre eles —,
   então são uma LINHA e não dois cartões: a redução de quatro cartões para um
   farol existe para o inventário parar de competir com o número que decide, e
   devolvê-lo em forma de cartão desfaria a redução com outro nome (§B.4 escreve
   "1 farol + 1 linha de inventário", e o desenho dela é uma linha).
   NÚMERO É TINTA, RÓTULO É `--cor-texto-suave` — a mesma regra do farol e dos
   chips do dono: 14,92:1 no número e 5,04:1 no rótulo, sobre `--cor-fundo`.
   `tabular-nums` porque estes números mudam a cada confirmação que chega, e sem
   ele a linha inteira se reposiciona a cada visita.
   -------------------------------------------------------------------------- */
.admin-inventario {
    margin-bottom: var(--e-5);
    font-size: var(--fs-2);
    font-weight: 700;
    line-height: var(--lh-normal);
    color: var(--cor-texto-suave);
}

.admin-inventario b {
    font-family: var(--f-display);
    font-weight: 900;
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto);
}

/* As duas colunas migraram para o bloco `--bp-3`, e o VALOR MUDOU: 860px →
   64rem (1024px). Mesmo motivo da lateral, mais um: 860 e 820 eram dois pontos
   de virada a 40px um do outro na MESMA tela, e nenhum dos dois foi escolhido —
   cada um nasceu do componente que o pediu. As duas grades do admin passam a
   virar no mesmo lugar. */
.admin-grid2 { display: grid; grid-template-columns: 1fr; gap: 18px; }
.admin-grid2 .form-secao { margin-bottom: 0; }

.admin-lista { list-style: none; margin: 0; padding: 0; }
.admin-lista li { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--cor-borda); }
.admin-lista li:last-child { border-bottom: 0; }
.admin-av { width: 38px; height: 38px; border-radius: 50%; background: var(--cor-roxo-claro); color: var(--cor-acento);
    display: flex; align-items: center; justify-content: center; font-family: var(--f-display);
    font-weight: 800; font-size: 0.82rem; flex-shrink: 0; }
/* ⚠️ `.admin-av.grad` SAIU DA FOLHA (T-0031), E É REMOÇÃO — NÃO REPINTURA.
   O `especialista-backend` tirou a classe `grad` da marcação em
   `views/admin/_conta.php` durante a T-0021 e deixou o registro escrito lá:
   "a regra fica órfã na folha". Varrido de novo nesta tarefa sobre `views/`,
   `public/assets/js/` e `app/`: a única ocorrência é `class="admin-av"`, sem
   modificador. Repintá-la para a paleta nova gastaria anatomia numa regra que
   nenhuma tela desenha — é o critério de PASSAGEM B da §7.2 (diferença visual
   zero porque o seletor está morto, e não porque a correção não fez nada). */
.admin-lista-info { flex: 1; min-width: 0; }
.admin-lista-info b { display: block; font-weight: 800; font-size: 0.92rem; }
.admin-lista-info span { color: var(--cor-texto-suave); font-weight: 700; font-size: 0.78rem; }
.admin-quando { font-family: var(--f-display); font-variant-numeric: tabular-nums;
    color: var(--cor-texto-suave); font-weight: 700; font-size: 0.76rem; white-space: nowrap; }
.admin-vazio { color: var(--cor-texto-suave); font-weight: 700; text-align: center; padding: 16px 0; }

.admin-saude { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--cor-borda); }
.admin-saude:last-child { border-bottom: 0; }
.admin-saude-nome { font-weight: 800; font-size: 0.9rem; }

/* -----------------------------------------------------------------------------
   A FAMÍLIA DE EMBLEMAS — tinha TRÊS literais, e um deles reprovava
   -----------------------------------------------------------------------------
   0,72rem são 11,52px: TEXTO NORMAL. O piso é 4,5:1 e não 3:1 — o limiar de
   texto grande começa em 18,66px/700. É essa conta que decide as duas correções
   abaixo, e é ela que ninguém tinha feito.
   -------------------------------------------------------------------------- */
.badge { font-family: var(--f-display); font-size: 0.72rem; font-weight: 800; padding: 4px 10px;
    border-radius: var(--raio-pilula); white-space: nowrap; }
.badge-ok { background: var(--cor-sucesso-fundo); color: var(--cor-sucesso-texto); }

/* ⚠️ BUG-TD-059 — `#8a7fb0` sobre `#f1eef7` mede 3,19:1 e REPROVA AA. Vivia em
   cinco pontos de `views/admin/index.php`: armazenamento não configurado,
   usuário inativo, evento encerrado, conexão do B2 e a chave secreta.
   O par certo já estava na folha, com nome e cargo declarado — "fato consumado,
   sem ação possível" —, e mede 8,05:1. E `#f1eef7` some de passagem: ele diferia
   de `--cor-neutro-fundo` `#f1eff6` em UMA unidade de azul. Dois literais para a
   mesma superfície. */
.badge-off { background: var(--cor-neutro-fundo); color: var(--cor-neutro-texto); }

/* ⚠️ AQUI O DEFEITO NÃO É CONTRASTE, É DIVERGÊNCIA — e é por isso que ninguém o
   achou. O par literal `#9a5b00` sobre `#fff4e5` mede 4,99:1 e PASSA; nenhuma
   varredura de contraste o pegaria. O que ele é: um SEGUNDO âmbar para o mesmo
   significado, ao lado de `--cor-aviso-fundo`/`--cor-aviso-texto` (5,95:1), que
   é o âmbar que o ADR-0022 criou depois de o produto errar a mesma cor três
   vezes. Dois valores para um semântico é exatamente como nasce o quarto erro. */
.badge-warn { background: var(--cor-aviso-fundo); color: var(--cor-aviso-texto); }

.admin-tabela-corpo { padding: 6px 8px; overflow-x: auto; }
.admin-tabela { width: 100%; border-collapse: collapse; }
.admin-tabela thead th { text-align: left; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em;
    color: var(--cor-texto-suave); font-weight: 800; padding: 10px 12px; border-bottom: 1px solid var(--cor-borda); }
.admin-tabela tbody td { padding: 12px; border-bottom: 1px solid var(--cor-borda); font-weight: 700; font-size: 0.9rem; vertical-align: middle; }
.admin-tabela tbody tr:last-child td { border-bottom: 0; }
/* N12 — `#fcfbff` era literal órfão: mais um branco-quase-branco na folha, ao
   lado de `#fbfaff` e do cartão. `--cor-roxo-claro` é a superfície de realce
   que o produto já tem, e a troca tira um literal da paleta.
   ⚠️ E DECLARO O QUE ELA *NÃO* CONSERTA, porque medi antes de escrever: o
   realce continua quase invisível — `#fcfbff` mede 1,03:1 contra o cartão
   branco e `--cor-roxo-claro` mede 1,11:1. Oito centésimos. Realce de linha é
   decoração e é ISENTO de limiar, então não há reprovação nenhuma aqui; o que
   há é uma correção de VOCABULÁRIO, não de contraste, e chamá-la de correção
   de contraste seria vender o que ela não entrega.
   ⚠️ E O QUE ELA CUSTA: `--cor-texto-suave` sobre a superfície nova mede
   4,77:1 contra os 5,15:1 de antes. É QUEDA, e passa — o piso é 4,5:1 e a
   folga cai de 0,65 para 0,27. Entra declarada em vez de descoberta depois. */
.admin-tabela tbody tr:hover { background: var(--cor-roxo-claro); }
/* ⚠️ `.admin-tav` E `.admin-tav .admin-sub` SAÍRAM (T-0031 3e — ver "O QUE SAIU
   DA FOLHA" na §admin). `.admin-sub` FICA: ela é emitida cinco vezes por conta
   na seção Usuários, e era só o ANCESTRAL que morreu.
   ⚠️ E O QUE A SEGUNDA REGRA PROTEGIA CONTINUA PROTEGIDO, o que eu conferi
   ANTES de tirá-la: ela dava `overflow-wrap: anywhere` ao e-mail dentro da
   tabela de sete colunas (BUG-TD-074). No DOM de hoje o e-mail é um `<span>`
   sem classe dentro de `.cabine-pessoa`, e `.cabine-pessoa span` já declara o
   mesmo `anywhere` pelo mesmo motivo (BUG-TD-068). Nenhum e-mail ficou sem
   quebra — a proteção mudou de dono junto com a marcação. */
.admin-sub { color: var(--cor-texto-suave); font-size: 0.78rem; font-weight: 700; }

/* -----------------------------------------------------------------------------
   BUG-TD-075 — A CAIXA QUE ENCERRA A FESTA, NA COLUNA MAIS ESTREITA DA TABELA
   -----------------------------------------------------------------------------
   Ela arma "Encerrar a festa atual agora": apaga fotos antes da data prometida
   ao dono e NÃO PODE SER DESFEITO (RN-063). Dentro da coluna estreita o rótulo
   quebrava em quatro linhas, o `<label>` inteiro é clicável e o alvo virava um
   borrão de 112×112px MEDIDO, com o marcador de 19px flutuando no meio dele —
   um alvo cuja forma é a do texto que quebrou, e não a do controle.
   O QUE MUDA, e é o mínimo: o marcador ANCORA na primeira linha (posição fixa em
   relação ao canto, em vez de "no meio do que sobrou"), o alvo ganha piso
   próprio de 44px — o mínimo de toque desta casa — e a caixa passa a se
   distinguir do botão comum que mora no mesmo formulário, por fio e por respiro.
   ⚠️ A TINTA É TOKEN EXISTENTE NO PAPEL EM QUE ELE FOI DECLARADO: o comentário
   de `--cor-erro-borda` diz, com número, que o vermelho claro "segue servindo
   BORDA e ÍCONE". Nenhum token é redefinido e nenhuma cor nova entra na folha.
   OS TRÊS NÚMEROS, medidos e não estimados: o fio sai de `--cor-borda` (#ece7f7,
   1,13:1 sobre o papel — a folha a declara decorativa e isenta) para
   `--cor-erro-borda` (#f5c2cd, 1,56:1), ou seja, a fronteira fica MAIS visível
   do que era, não menos. E o rótulo sobre a superfície de `:hover` mede 13,45:1
   no claro e 12,11:1 no escuro. Quem carrega a informação continua sendo a
   FRASE ("Encerrar a festa atual agora" + o aviso abaixo dela); a cor é reforço,
   como a §da zona de perigo já manda.
   ⚠️ O AVISO de 12,48px que mora logo abaixo dela NÃO é desta passagem — é do
   `especialista-ui` e continua exatamente como estava.
   ⚠️ REESCOPADO NA T-0021, e o motivo é que a regra teria MORRIDO EM SILÊNCIO:
   a seção Usuários deixou de ser `.admin-tabela` e virou uma lista de cartões
   (`.admin-conta`), então `.admin-tabela .campo-checkbox` passou a não casar com
   nada — a varredura de consumidores confirmou que as TRÊS caixas desta família
   moram hoje em `views/admin/_conta.php`. A correção do BUG-TD-075 continua
   inteira, e agora ela cobre também as duas caixas de confirmação dos botões que
   destroem, que são exatamente do mesmo tipo: alvo que arma um ato irreversível.
   -------------------------------------------------------------------------- */
/* ⚠️ `margin-bottom` DESCEU DE `--e-3` PARA `--e-2` NA T-0021, e é o mesmo
   orçamento vertical do bloco `.admin-conta-bancada` (G2 da UX). O `min-height`
   de 44px — que é o alvo, e é o que este bloco existe para proteger — NÃO
   mudou. */
.admin-conta .campo-checkbox {
    align-items: flex-start;
    min-height: var(--alvo-toque);
    margin-bottom: var(--e-2);
    border-color: var(--cor-erro-borda);
}

/* O MARCADOR PASSA A TER TAMANHO PRÓPRIO, e não o do texto que quebrou: 24px é
   o alvo mínimo da WCAG 2.2 (2.5.8), e ancorado no topo ele fica sempre no mesmo
   ponto em relação ao canto da caixa — o operador procura no mesmo lugar em
   qualquer largura, em vez de caçar 19px no meio de quatro linhas.
   `margin-top` de 1px alinha a caixa com a primeira linha do rótulo (0,88rem em
   linha de 22,5px).
   ⚠️ RESSALVA MEDIDA, e ela fica registrada em vez de escondida: o `<label>`
   inteiro continua clicável e continua tão alto quanto o texto (112px medidos em
   375px). Encolher o ALVO exigiria separar `<input>` e `<label for>` e redesenhar
   a célula, o que esta passagem não faz. O que muda aqui é o que dá para mudar
   sem redesenho: âncora, tamanho do controle, fronteira e respiro. */
.admin-conta .campo-checkbox input[type="checkbox"] {
    width: 24px;
    height: 24px;
    margin-top: 1px;
}

/* O `:hover` da regra base viria DEPOIS desta na cascata e devolveria a borda
   roxa ao passar o mouse — a distinção sumiria justamente no instante em que o
   ponteiro está em cima do alvo perigoso. */
.admin-conta .campo-checkbox:hover {
    border-color: var(--cor-erro-texto);
    background: var(--cor-erro-fundo);
}
/* ⚠️ `.admin-acao` E AS SUAS QUATRO REGRAS DE ESTADO SAÍRAM (T-0031 3e — ver
   "O QUE SAIU DA FOLHA" na §admin). Quem veste botão de linha no console agora
   é `.cabine-tecla` (§8), e a medida que autorizou a remoção está lá: nas cinco
   seções servidas, os botões chegam como `cabine-tecla cabine-tecla--acesa`,
   `--fantasma` ou `--perigo`, INCLUSIVE o "Tentar de novo" da fila do
   armazenamento, que era o único `.admin-acao` fora de `.admin-conta`. */

/* CONSEQUÊNCIA MEDIDA DO BUG-TD-076, e ela é minha: `.form-inline` é
   `display: inline`, então o rótulo "Cota (GB)" divide a linha com o campo ao
   lado. Com o campo a 16px ele passou a medir 97px (eram 84), e em 900px o
   rótulo quebrava no meio — "Cota" numa linha e "(GB)" na outra, com o campo
   entre os dois. Uma unidade separada do seu rótulo é rótulo errado. */
.admin-cota .form-inline label {
    white-space: nowrap;
}
/* -----------------------------------------------------------------------------
   O ANEL DE FOCO DUPLO — a direção B mostra as DUAS faces (TD-076 §2)
   -----------------------------------------------------------------------------
   MEDIDO: um anel encostado direto num preenchimento vivo dá 2,01:1 nos DOIS
   modos — reprova idêntico dos dois lados, e é por isso que um contorno de UMA
   face só não resolve. A folga (`--anel-folga`) mostra o extremo OPOSTO ao do
   anel: branco no claro, carvão no escuro. O par passa a medir 6,51:1 contra a
   tecla e 13,09:1 contra o anel no claro; no escuro os dois invertem e medem
   com a mesma folga. `--anel-folga` estava declarado nos dois modos desde a
   troca de paleta e NINGUÉM O LIA.
   ⚠️ O `outline` NÃO VIRA `none`: ele fica transparente de propósito, para que
   no modo de alto contraste do sistema (onde `box-shadow` é descartado) o anel
   volte a existir sozinho. A demo escrevia `outline:none`; esta é a única
   diferença deliberada, e ela só acrescenta.
   ⚠️ ESPECIFICIDADE: `.admin :focus-visible` (0,2,0) mora acima nesta folha e
   empata com estes seletores — quem resolve empate é a ordem, e por isso este
   bloco fica DEPOIS dele. Mover um dos dois inverte o resultado em silêncio.
   ⚠️ ESTA É A ÚNICA REGRA DA ETAPA 3e EM QUE SAIU SELETOR E NÃO REGRA: a lista
   tinha `.admin-acao:focus-visible` e `.admin-link:focus-visible` no meio de
   QUATRO seletores vivos. Apagar a regra inteira teria tirado o anel duplo de
   `.btn`, `.btn-secundario`, `.btn-perigo` e `.evento-aba` — telas que ninguém
   estava olhando, quebradas por uma limpeza de admin. Os dois saem; os quatro
   ficam. O anel das teclas do console tem regra própria em `.cabine-tecla:
   focus-visible` (§8), com o mesmo par de sombras, então nenhum botão do
   console ficou sem anel.
   -------------------------------------------------------------------------- */
.btn:focus-visible,
.btn-secundario:focus-visible,
.btn-perigo:focus-visible,
.evento-aba:focus-visible {
    outline: var(--foco-largura) solid transparent;
    outline-offset: var(--foco-desvio);
    box-shadow: 0 0 0 2px var(--anel-folga), 0 0 0 4px var(--anel);
}

/* -----------------------------------------------------------------------------
   A SEÇÃO USUÁRIOS COMO LISTA DE CARTÕES (T-0021)
   -----------------------------------------------------------------------------
   A tabela de sete colunas desta seção já estourava a página — BUG-TD-074 mediu
   873px de mínimo, com a coluna do e-mail sozinha fixando 231. A T-0021
   acrescenta, por conta, a barra de prazo, um grupo de extensão com quatro
   caminhos e mais quatro atos. O porquê inteiro da troca por cartões, com as
   duas razões que fecham a saída do `display: block`, está no topo de
   `views/admin/_conta.php`, junto do HTML.

   ⚠️ UMA COLUNA, E A GRADE `auto-fit` SAIU DESTA LISTA (§2.5 da UX). Ela
   continua sendo o idioma da casa para grades de cartões — o que mudou é que
   ESTA lista não é uma grade de cartões: é uma FILA ORDENADA por urgência. Os
   três motivos, e nenhum é gosto: (a) o `layout.json` manda UMA BORDA ESQUERDA,
   e duas colunas de linhas curtas criam uma segunda borda e uma leitura em
   zigue-zague; (b) numa grade, "a mais urgente" e "a segunda" ficam lado a lado
   e a fila deixa de ser fila; (c) com `auto-fit` a altura da trilha é a do item
   mais alto, então abrir uma conta empurrava a vizinha — o alvo mudando de lugar
   debaixo do dedo, numa tela em que o operador abre e fecha dezenas de vezes.

   ⚠️ NENHUM PONTO DE VIRADA NOVO, E AGORA MENOS AINDA: o placar publicado —
   três `^@media (min-width` e zero `^@media (max-width` — continua valendo, e a
   coluna única não precisa nem do `min()` dentro do `minmax()` que a grade
   exigia para não transbordar em 360px.

   ⚠️ A SEÇÃO EVENTOS NÃO É TOCADA: ela continua em `.admin-tabela`, e nenhum
   seletor deste bloco a alcança (§12 item 8 da especificação da T-0021).
   -------------------------------------------------------------------------- */
.admin-contas {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--e-4);
    list-style: none;
    align-items: start;
}

/* O cartão é `.form-secao`. O `margin-bottom` dele viraria vão duplo dentro de
   uma grade que já tem `gap` — e vão duplo entre cartões lidos como irmãos é o
   que faz a lista parecer dois grupos. */
.admin-conta {
    margin-bottom: 0;
    transition: background-color var(--mov-rapido) var(--curva-padrao),
                box-shadow var(--mov-rapido) var(--curva-padrao);
}

/* -----------------------------------------------------------------------------
   A PEÇA DO CONSOLE HERDA A ELEVAÇÃO DO CONSOLE (T-0031, etapa 3b)
   -----------------------------------------------------------------------------
   ⚠️ O SELETOR É ESCOPADO POR `.cabine` DE PROPÓSITO, E ISSO É A REGRA INTEIRA.
   `.form-secao` veste 18 telas do produto e a sombra dela está CERTA em 17
   delas; o que a direção B mudou foi a pele do CONSOLE. Trocar `--elev-1` na
   regra de `.form-secao` repintaria as 18; escopar por `.cabine` alcança as
   cinco seções do admin e nada mais.

   POR QUE ELA PRECISOU EXISTIR, medido na tela servida na pele ESCURA: os 14
   cartões de conta são `class="form-secao admin-conta"` e renderizavam
   `rgba(0,0,0,0)` — o mesmo alfa zero de `--elev-1` que apagou a sombra das
   peças `.cabine-*`. Sem esta regra, o console escuro ficaria com metade das
   peças ganhando profundidade e a maior delas — a lista de contas, que é o
   corpo da seção Usuários — continuando chapada ao lado. Meia correção numa tela
   é pior que nenhuma: ela cria um degrau que ninguém decidiu.

   NO CLARO NADA MUDA: `--elev-cabine` LÊ `--elev-1` no `:root`. */
.cabine .form-secao {
    box-shadow: var(--elev-cabine);
}

/* A ESCADA DE SUPERFÍCIE NA FILA DE CONTAS (§7 da cabine: "contas no console,
   convidados no painel: mesmo material"). Elevar é clarear no escuro e tingir no
   claro — `--sup-hover` sabe para que lado andar, e a sombra sobe um degrau.
   ⚠️ SEM `transform`: a demo levanta o cartão 1px, e aqui isso seria um alvo se
   movendo debaixo do dedo numa peça que tem oito botões dentro. Fica o que dá
   profundidade e sai o que mexe. */
.admin-conta:hover {
    background: var(--sup-hover);
    box-shadow: var(--elev-2);
}

/* -----------------------------------------------------------------------------
   A LINHA DE TRIAGEM — o `<summary>` fechado (BUG-TD-099)
   -----------------------------------------------------------------------------
   Nove contas ocupavam 7.306px de rolagem porque o cartão mostrava TUDO de TODA
   conta, sempre. A linha fechada devolve à lista o que a tabela tinha de bom —
   nome · legenda · barra · marcadores, comparáveis descendo UMA borda esquerda —
   sem os 873px que a tabela exigia.

   ⚠️ O ALVO É A LINHA TODA, NÃO O TRIÂNGULO: `min-height: var(--alvo-toque)`
   sobre o `<summary>` inteiro, que é o que a linha 1 desta folha manda.

   ⚠️ O MARCADOR NATIVO SAI COM SUBSTITUTO, E O SUBSTITUTO DIZ O ESTADO POR
   FORMA: a seta gira em `[open]`. É o MESMO idioma do acordeão da página inicial
   (hoje `.vitrine-duvida`, cuja seta também gira pelo estado), já vivo nesta
   casa — nenhum mecanismo novo. Estado por cor sozinho é proibido pelo
   `layout.json`.

   ⚠️ `:hover` É SUPERFÍCIE + TINTA, `[open]` É FORMA — e os dois não podem se
   confundir. "Sob o ponteiro" usa `--cor-sob-ponteiro` mais a marca no nome;
   "aberta" é a seta girada mais o corpo revelado.
   ⚠️ AS DUAS FRASES QUE ESTAVAM AQUI ERAM FALSAS E FORAM CORRIGIDAS PELA TELA,
   não por releitura: (a) "sob o ponteiro usa `--cor-roxo-claro`, exatamente como
   `.admin-tabela tbody tr:hover`" — o mesmo token, mas a tabela mora sobre a
   PÁGINA e a linha mora dentro de um CARTÃO, onde ele media 1,11:1 (ver a regra
   de `:hover`, mais abaixo); e (b) "o anel de foco vem de `.admin
   :focus-visible`, que já veste o `<summary>` sem uma linha nova" — vestia e não
   PINTAVA, recortado pelo `overflow: hidden` do cartão (BUG-TD-102, a regra de
   `:focus-visible` logo abaixo).

   -----------------------------------------------------------------------------
   AS DUAS FAIXAS DE FLEX SAÍRAM, E A GRADE DO DEMO ENTROU (T-0031, etapa 3b)
   -----------------------------------------------------------------------------
   ⚠️ O QUE ESTAVA ESCRITO AQUI DESCREVIA UM MECANISMO QUE A ETAPA 3 APAGOU, e
   comentário que descreve mecanismo morto é mentira documentada. O histórico
   fica em uma linha, porque o DEFEITO que ele nomeia é o mesmo de hoje: com
   `flex`, cada célula começava onde a anterior acabasse, e a promessa com que a
   UX ratificou a troca tabela → cartões ("comparável descendo a coluna") caía.

   A ETAPA 3 TROCOU A MARCAÇÃO E O DEFEITO VOLTOU EM OUTRO LUGAR. MEDIDO POR MIM
   nesta etapa, no Edge, com as 14 contas das fixtures, nas quatro larguras
   (768/1024/1280/1440 dão o MESMO resultado, porque a anatomia de flex não muda
   com a largura):
     · `.cabine-pessoa`  → 1 abscissa   (a borda esquerda, certa)
     · `.cabine-festa`   → 10 abscissas · espalhamento 123,9px
     · `.cabine-selo`    → 12 abscissas · espalhamento 177,2px
     · `.cabine-prazo`   → 1 abscissa, mas em FAIXA PRÓPRIA: ele não coube na
                           faixa do nome (a faixa mede 798px e o conjunto pedia
                           986px), então a "coluna do prazo" era uma segunda
                           linha, não uma coluna.
   Altura da linha fechada: 115,1 a 149,5px — irregular, porque o número de
   faixas dependia do conteúdo.

   O QUE ENTRA NO LUGAR: a grade do demo, escrita UMA vez em `.cabine-conta-leitura`
   (§7, mais abaixo) e consumida TAMBÉM por este seletor. Ela é a mesma peça com
   dois nomes — `.admin-conta-linha` é o nome que a marcação emite hoje e o que
   carrega a âncora, o marcador apagado e a seta; `.cabine-conta-leitura` é o nome
   do demo aprovado. As duas leem a MESMA regra, então não há duas geometrias
   para manter em sincronia, e o dia em que a marcação adotar o nome do demo nada
   precisa mudar aqui.

   O QUE ESTE SELETOR CONTINUA SENDO DONO (e por isso NÃO entra na regra
   compartilhada): a altura de alvo, o recuo de `--e-5` (que alinha a linha
   fechada com a bancada aberta), a margem de rolagem da âncora, o cursor, o
   `list-style` e a seta.
   -------------------------------------------------------------------------- */
.admin-conta-linha {
    position: relative;
    min-height: var(--alvo-toque);
    /* 20px = `--e-5`, o mesmo recuo horizontal de `.secao-corpo`: a linha fechada
       e a bancada aberta começam na MESMA abscissa.
       ⚠️ O RECUO DA DIREITA É MAIOR, E O EXCEDENTE É A PISTA DA SETA. Ela saiu do
       fluxo (ver a regra de `::after`, mais abaixo), então nenhuma coluna reserva
       espaço para ela: quem reserva é este recuo. `--e-5` do cartão MAIS `--e-4`
       de pista — a caixa do glifo mede 4,7px (medida pelo box model, não
       estimada), então sobram 11,3px entre a coluna do prazo e a seta. Sem isto a
       seta pinta POR CIMA da coluna encostada à direita, que é justamente a do
       prazo. */
    padding: var(--e-3) calc(var(--e-5) + var(--e-4)) var(--e-3) var(--e-5);
    /* -------------------------------------------------------------------------
       A ÂNCORA ATERRISSAVA DEBAIXO DO CABEÇALHO GRUDADO
       -------------------------------------------------------------------------
       Todo ato desta seção volta por `#conta-{id}` no `Location` do PRG
       (`AdminController::destinoDoPRG`), e o `id` mora no `<summary>`. Sem
       margem de rolagem, o navegador alinha o TOPO do summary ao topo da janela
       — e `.topo` é `position: sticky`, então ele pinta por cima.

       MEDIDO na tela, com as nove contas, indo à 1ª e à 3ª conta:
       320/360/375/390px → o `<summary>` fica INTEIRAMENTE coberto (99,8px de
       altura, 99,8px cobertos; o topo dele para em y = 0 e o `.topo` vai até
       y = 121). Não é só o nome: é a linha toda. O operador é levado à conta
       certa e não vê nada dela.
       430px → 73px cobertos de 99,8. 480px → 72,5 de 73,8.
       ⚠️ DE 640px PARA CIMA NÃO ACONTECE COM NOVE CONTAS, e a razão importa: a
       página fica curta demais para a rolagem chegar ao alinhamento pedido
       (`scrollY` bate o máximo antes). O defeito é REAL e depende de haver
       rolagem suficiente — no desktop ele aparece com uma lista maior. Dizer
       "em todas as larguras" seria falso.

       ⚠️ OS DOIS LITERAIS EM px SÃO FUGA DE TOKEN, E ELA É DECLARADA. `.topo`
       não tem altura fixa: ela é EMERGENTE do embrulho de `.topo-flex`, e foi
       medida — 121px abaixo de 405px de janela, 73px de 405px para cima. 129 =
       121 + 8 de respiro; 81 = 73 + 8 (o valor de 30rem fica no bloco de 30rem).
       Entre 405 e 479px a base sobra 56px: sobra de ar acima da conta nunca
       esconde nada, e fechar essa faixa custaria um ponto de virada novo.

       ⚠️ E ESTA NÃO É A CORREÇÃO DE RAIZ. A de raiz é `scroll-padding-top` no
       elemento de rolagem, que conserta TODA âncora do produto de uma vez; ela
       alcança 18 telas e foi adiada por decisão do Coordenador, registrada como
       dívida para a T-0028 (o lote de sistema). O que está aqui é local e
       resolve esta seção.

       ⚠️ T-0038: O CABEÇALHO DEIXOU DE SER `.topo`. O do arquivo do Stitch
       (`.dono-topo`) tem altura FIXA de 80px em toda largura e não embrulha mais
       — então os dois números viraram um: 80 + 8 de respiro. Os 129px de antes
       ficariam com 41px de sobra no celular, e os 81px do bloco de 30rem
       deixariam 7px da conta debaixo do cabeçalho. */
    scroll-margin-top: 88px;
    cursor: pointer;
    list-style: none;
}

.admin-conta-linha::-webkit-details-marker {
    display: none;
}

/* -----------------------------------------------------------------------------
   O ANEL DE FOCO PRECISA CABER DENTRO DO CARTÃO (BUG-TD-102)
   -----------------------------------------------------------------------------
   ⚠️ QUEM NAVEGA ESTA SEÇÃO POR TECLADO NÃO VIA ONDE ESTAVA. E o anel estava
   declarado, certo, ao pixel e à cor: `.admin :focus-visible` desenhava
   `2px solid var(--foco)` com `outline-offset: 2px`, e o valor COMPUTADO no
   `<summary>` confirmava isso. Ele simplesmente não era pintado.

   A CAUSA É GEOMETRIA, não cascata: `.form-secao` tem `overflow: hidden` (é ele
   que faz o raio de 18px recortar o cabeçalho colorido das seções) e
   `padding: 0`, então o `<summary>` fica a 1px de dentro do cartão — a espessura
   da borda. Com deslocamento POSITIVO o anel se estende 4px para FORA da borda
   do summary, ou seja, 3px além da borda do cartão: inteiro dentro da região
   que o `overflow: hidden` recorta.

   ⚠️ NÃO "SIMPLIFIQUE" TIRANDO O `overflow: hidden` DE `.form-secao`: ele é o
   que recorta o cabeçalho colorido ao raio do cartão e alcança dezenas de telas.
   A peça que cede é o anel, que é local.

   ⚠️ E ESTA É A LIÇÃO QUE FICA, porque duas medições anteriores passaram por
   aqui e aprovaram: LER O VALOR COMPUTADO DO `outline` NÃO PROVA QUE O ANEL É
   PINTADO. Valor computado não sabe se um ancestral recortou. O que provou foi
   captura de tela do `<summary>` com foco de teclado real, antes e depois.

   CONSEQUÊNCIA ACEITA: com deslocamento negativo os dois cantos superiores do
   anel ficam levemente arredondados pelo raio do cartão. Anel visível com canto
   arredondado é melhor que anel invisível com canto exato.

   Só o deslocamento muda: largura, estilo e cor continuam vindo da regra da
   família, que é a única dona da APARÊNCIA do anel (`outline-offset` não faz
   parte do atalho `outline`, então nada aqui é reposto por ela). A
   especificidade (0,3,0) vence `.admin :focus-visible` (0,2,0) por peso e não
   por ordem — o mesmo caminho que `.switch input:focus-visible + .switch-trilho`
   já usa nesta folha. */
.admin .admin-conta-linha:focus-visible {
    outline-offset: -2px;
}

/* -----------------------------------------------------------------------------
   SOB O PONTEIRO — dois canais, e o segundo é o do precedente (P2 da revisão)
   -----------------------------------------------------------------------------
   ⚠️ ESTA REGRA JÁ EXISTIA E ESTAVA ERRADA POR MEDIÇÃO, NÃO POR GOSTO. Ela
   pintava `--cor-roxo-claro`, o mesmo token que `.admin-tabela tbody tr:hover`
   usa — só que a tabela mora SOBRE A PÁGINA e a linha mora DENTRO DE UM CARTÃO
   BRANCO. O mesmo token, na superfície errada, media 1,11:1 no claro e 1,04:1
   no escuro: uma superfície declarada que não separava nada. É o gêmeo numérico
   do NC-05 que esta mesma tarefa consertou. O token novo
   (`--cor-sob-ponteiro`) é o degrau medido CONTRA O CARTÃO — e no escuro ele
   CLAREIA, ao contrário do anterior, que afundava a linha.

   ⚠️ E VOLTA O CANAL DO PRECEDENTE. `.inicio-duvida summary:hover` — o
   acordeão da página inicial da T-0015 (saiu com a T-0017), e o único anterior a este — RECUSOU superfície por
   escrito ("nenhuma superfície nova, nenhum fundo, nenhuma borda… Medido:
   5,41:1") e disse "sob o ponteiro" TINGINDO o texto com a cor que o bloco já
   usa para "interativo". Aqui os dois convivem: a superfície separa a LINHA das
   vizinhas (é uma lista de nove, o `.inicio-duvida` não tinha cartão), e a tinta
   no nome diz que a linha inteira é o alvo. Nenhum canal sozinho é o único
   indicador de nada — o estado aberto/fechado continua dito por FORMA (a seta
   girando), como manda o `layout.json`.

   ⚠️ SEM TRANSIÇÃO, E É DECISÃO E NÃO ESQUECIMENTO: o realce sob o ponteiro é
   instantâneo, igual ao do precedente. Quem varre nove linhas com o mouse não
   quer nove desvanecimentos atrás de si.
   -------------------------------------------------------------------------- */
/* ⚠️ E O PAR INTEIRO MORA EM `@media (hover: hover)` — ACRESCENTADO NA ETAPA 9.
   No aparelho de toque o `:hover` é aplicado no toque e FICA aplicado até o
   toque seguinte. Consequência medida na própria anatomia desta linha: uma conta
   FECHADA carregaria a superfície E a tinta de "sob o ponteiro", enquanto a
   conta ABERTA ao lado não teria nenhuma das duas — exatamente a confusão entre
   superfície/tinta e FORMA que o cabeçalho acima proíbe por escrito, e com o
   sinal invertido.
   AGRAVANTE QUE FECHA O ARGUMENTO: esta folha declara
   `-webkit-tap-highlight-color: transparent` e a linha não tem `:active`, então
   no telefone o toque não devolve NADA no instante da pressão — o único retorno
   visível é justamente esse realce grudado, que aparece depois e no lugar
   errado.
   ⚠️ `@media (hover: hover)` era ZERO ocorrência nesta folha antes desta linha, e
   o escopo fica NESTE par de propósito: `.admin-perigo-linha:hover` (mais
   abaixo) é a mesma classe de defeito SEM o agravante, e alargar escopo na
   etapa 9 de uma tarefa de 13 é como nasce o defeito seguinte. Fica anotado, não
   consertado aqui.
   ⚠️ E ELE NÃO É PONTO DE VIRADA: `hover` não é `min-width` nem `max-width`; o
   placar de larguras de virada desta folha continua sendo três. */
@media (hover: hover) {
    .admin-conta-linha:hover {
        background: var(--cor-sob-ponteiro);
    }

    .admin-conta-linha:hover .admin-conta-nome {
        color: var(--cor-acento);
    }
}

/* -----------------------------------------------------------------------------
   A SETA SAI DO FLUXO — e é isso que destrava a grade de quatro colunas
   -----------------------------------------------------------------------------
   ⚠️ ERA `margin-left: auto` MAIS `flex: 0 0 auto`: as duas só falam FLEX, e a
   linha deixou de ser flex nesta etapa. Num contêiner de grade a seta vira um
   item auto-posicionado, e o `especialista-backend` mediu no papel onde ela cai:
   linha 2, coluna 1 — um "›" solto embaixo do nome. Eu MEDI a variante na tela
   antes de escolher, e ela é pior do que o papel dizia, porque `order: 1` em
   `.admin-conta-marcadores` muda a ordem de auto-posicionamento: nas duas contas
   COM marcador a seta ficava na linha 2 coluna 1 e os MARCADORES na linha 2
   coluna 2 — a faixa de marcadores começando na segunda coluna.

   TRÊS SAÍDAS FORAM PESADAS, e a diferença entre elas é o que a linha custa:
     (a) `grid-column: 1 / -1` (o que o backend propôs) — resolve o item solto,
         mas põe a seta numa FAIXA PRÓPRIA embaixo das quatro colunas: +18px de
         faixa +11px de vão em CADA linha, 406px de rolagem nas 14 contas, para
         desenhar um glifo de 4,7px.
     (b) uma quinta trilha só para ela — obriga `.cabine-contas-cabeca` a nascer
         com cinco trilhas para os quatro rótulos dela, ou os rótulos deixam de
         cair sobre as colunas. Duas geometrias para manter em sincronia.
     (c) TIRAR A SETA DO FLUXO. Ela não é conteúdo nem coluna: é o marcador de
         "isto abre", que substitui o triângulo nativo. Fora do fluxo ela não
         participa de grade nenhuma, a grade fica com as QUATRO trilhas do demo,
         e `.cabine-contas-cabeca` continua valendo exatamente como o demo a
         escreveu. É a escolha.

   O PREÇO DECLARADO de (c): quem sai do fluxo não reserva espaço, então o recuo
   à direita da linha passou a carregar a pista dela (ver a regra base). É uma
   dependência entre duas regras, e está escrita nos dois lados de propósito.

   `top: 50%` mais `translateY(-50%)`: a linha fechada mede de 49,8px (uma faixa,
   no desktop) a 273,6px (tudo empilhado, a 375px). Ancorar no topo deixaria a
   seta grudada no nome no telefone e centrada no desktop — dois lugares para a
   mesma peça. Centrada, ela diz "a linha INTEIRA abre" nas duas anatomias.
   ⚠️ O `translateY` ENTRA NAS DUAS REGRAS DE `transform`, e não pode ser
   esquecido na de `[open]`: `transform` é uma propriedade só, e a segunda regra
   substitui a primeira inteira — sem o deslocamento ali, a seta pularia meia
   altura para baixo no instante em que a conta abre.
   -------------------------------------------------------------------------- */
.admin-conta-linha::after {
    content: "\203A";
    position: absolute;
    top: 50%;
    right: var(--e-5);
    font-size: var(--fs-4);
    line-height: 1;
    color: var(--cor-acento);
    transform: translateY(-50%) rotate(90deg);
    transition: transform var(--mov-rapido) var(--curva-padrao);
}

.admin-conta-caixa[open] > .admin-conta-linha::after {
    transform: translateY(-50%) rotate(-90deg);
}

/* Aberta, a linha vira cabeçalho da bancada e precisa do fio que `.secao-cab` já
   dava ao cartão. Fechada ele não existe — nove fios sob nove linhas coladas
   leriam como uma tabela sem colunas. */
.admin-conta-caixa[open] > .admin-conta-linha {
    border-bottom: 1px solid var(--cor-borda);
}

/* O NOME É A CHAVE (§2.2 item 1) e é o que `Ctrl+F` procura. `anywhere` porque
   nome longo NUNCA pode empurrar a legenda para fora nem produzir rolagem
   horizontal — é o estado 10 da §6.2 da UX.

   ⚠️ O `flex: 1 1 10rem` SAIU, E SAIU POR MEDIÇÃO E NÃO POR GOSTO. Ele era o
   elástico da faixa 1 enquanto o `<summary>` era um contêiner flex E o nome era
   filho DIRETO dele. A etapa 3 embrulhou o nome dentro de `.cabine-pessoa`
   (nome + e-mail), então já antes desta etapa o `flex` do nome era propriedade
   de um filho de GRADE: conferido no valor computado da tela servida, ele
   resolvia `1 1 160px` e não governava largura nenhuma. Quem hospeda o elástico
   agora é a TRILHA (`minmax(0, 2fr)`), na regra da grade. Declaração que não
   pinta nada não é inofensiva: ela é a primeira coisa que alguém lê ao procurar
   por que a coluna tem a largura que tem. */
.admin-conta-nome {
    font-family: var(--f-display);
    font-size: var(--fs-3);
    font-weight: 800;
    line-height: var(--lh-apertado);
    overflow-wrap: anywhere;
    min-width: 0;
}

/* LEGENDA E BARRA VIAJAM JUNTAS OU NÃO VIAJAM: a barra é rotulada por
   `aria-labelledby` apontando para a legenda, e separá-las poria o rótulo
   acessível dentro de um `<details>` fechado.

   -----------------------------------------------------------------------------
   ⚠️ A BASE É O TELEFONE — E ELA MUDOU AQUI, PORQUE A BARRA ESTAVA SENDO CORTADA
   -----------------------------------------------------------------------------
   A base desta célula era a regra do DESKTOP (`flex: 0 1 23rem`), e no telefone
   ela CORTAVA A BARRA DE PRAZO. Medido nas NOVE contas do banco — e a advertência
   é parte do achado: a legenda longa mora na 3ª e na 5ª conta, então medir só a
   PRIMEIRA devolve zero transbordo e esconde o defeito inteiro.

   | janela | transbordo do `<summary>` | a barra além da borda do cartão |
   |--------|---------------------------|---------------------------------|
   | 320px  | 47,0px                    | 46,5px   (2 das 9 contas)       |
   | 360px  |  7,0px                    |  6,5px   (2 das 9 contas)       |
   | 375px  |  0                        |  —                              |
   | 390px  |  0                        |  —                              |

   A CONTA: o `min-content` da célula é 303px — legenda `nowrap` de 217,5px, mais
   `--e-2`, mais os 88px da barra —, e a caixa interna do cartão mede 256px em
   320 e 296px em 360. 303 − 256 = 47; 303 − 296 = 7. O resto sai pela direita.

   ⚠️ E NÃO HAVIA ERRO NENHUM NA TELA: nem reticências, nem rolagem, nem aviso.
   `document.scrollWidth > innerWidth` devolve FALSE nas duas larguras, porque
   quem impede a rolagem é o MESMO `overflow: hidden` de `.form-secao` que corta
   a barra. O gate de "zero rolagem horizontal" passava POR CONSTRUÇÃO, não por
   mérito.
   REGRA DE SISTEMA QUE FICA: dentro de um ancestral com `overflow: hidden`,
   transbordo se mede POR CAIXA (`elemento.scrollWidth > elemento.clientWidth`),
   nunca pelo documento — o documento não sabe o que o recorte comeu. O
   comentário anterior desta regra dizia "medido e sem rolagem horizontal": o
   fato estava certo, o que ele provava é que estava errado.

   ⚠️ O BLOCO DE FLEX DESTA CÉLULA FOI REMOVIDO NA T-0031 ETAPA 3b, E DUAS DAS
   SUAS DECLARAÇÕES JÁ ESTAVAM MORTAS ANTES DISSO. Medido no valor computado da
   tela servida, ANTES de eu tocar em qualquer coisa: o elemento resolvia
   `display: grid` e `gap: 2px`, e não `display: flex` / `gap: var(--e-2)` — quem
   vencia era `.cabine-prazo` (§7), que é mais tarde na folha e tem a mesma
   especificidade. Ou seja: a etapa 3, ao pôr `class="admin-conta-prazo
   cabine-prazo"` no mesmo elemento, já tinha entregado a célula à regra do demo,
   e este bloco continuava aqui descrevendo um mecanismo que não existia mais.
   `flex: 0 1 100%` e `order: 1` seguem o mesmo caminho: numa GRADE eles não
   pintam nada. Fica valendo `.cabine-prazo`, que é a peça do demo, e o que
   sobrevive aqui é só a largura da barra, logo abaixo.
   O QUE A GRADE FAZ NO LUGAR: no telefone a célula é uma linha da pilha, com
   legenda e barra empilhadas por dentro (é o que `.cabine-prazo` já faz); no
   desktop ela é a quarta coluna, encostada à direita. A barra inteira, nas duas
   anatomias — conferido por caixa e não pelo documento, como a regra de sistema
   acima manda. */

/* A legenda diz o estado por TEXTO — que é a regra do `layout.json` — e fica em
   `--cor-texto`, o par que esta superfície já usa. A cor do estado continua
   viva na BARRA (`.medidor-alerta`/`.medidor-encerrado`), como reforço.
   ⚠️ O `white-space: nowrap` SAIU, E FOI A TELA QUE O TIROU. Ele existia porque
   `sem festa · faltam 60 d` quebra feio no meio do separador — e isso continua
   verdade. O que mudou é que, com a linha em GRADE, `nowrap` deixou de ser uma
   preferência e virou um PISO DE LARGURA: um item que não pode quebrar não
   encolhe, ele transborda a própria trilha e é COMIDO pelo `overflow: hidden` de
   `.form-secao` — sem reticências, sem rolagem e sem aviso, que é a classe de
   defeito que esta mesma célula já pagou uma vez.
   MEDIDO por mim na tela, com o `nowrap` ainda vivo, nas 14 contas das fixtures:
   a 320px de janela a trilha mede 187px e DUAS contas transbordavam 39px cada;
   a 360, 375, 768, 1024, 1280 e 1440 o transbordo era zero. Sem `nowrap` o
   transbordo é zero nas SETE larguras.
   E ELE NÃO ERA "MELHOR ONDE CABIA": quebrar só acontece quando não cabe. Onde
   sobra espaço a linha segue inteira — a diferença entre `normal` e `nowrap` é
   nula na trilha larga e é a diferença entre embrulhar e sumir na trilha
   estreita.
   ⚠️ `17rem` É A COLUNA DA LEGENDA quando o pai é FLEX. Na grade quem manda é a
   trilha, e este `flex-basis` fica inerte — mantido porque `.admin-conta-prazo`
   volta a ser flex em qualquer contexto que não seja a linha de triagem.

   ⚠️⚠️ O NÚMERO DE 2026-08-29 ESTÁ VENCIDO, E O SENTIDO DA REGRA DE SISTEMA
   MUDOU COM ELE. Aquela medição foi feita com a legenda em NUNITO: pior caso
   255,7px, e o pior FALLBACK (Arial) em 263,8px, o que dava os 8,2px de folga que
   justificaram 17rem. A direção B pôs `--f-display` (Space Grotesk) nesta
   legenda, e eu REMEDI a mesma string (`sem festa · venceu há 1000 d ·
   estendido`) na fonte que a tela usa hoje, a 13,6px/600:

       Space Grotesk (preferida) .... 267,6px   ← agora é ELA a mais larga
       Arial ........................ 263,8px
       Nunito ....................... 251,5px
       Segoe UI ..................... 249,5px

   A folga de 17rem caiu de 8,2px para 4,4px, e a REGRA precisa de uma emenda:
   "dimensionar pelo pior FALLBACK" pressupunha que a fonte desejada fosse a mais
   estreita, o que era verdade com a Nunito e deixou de ser. O que fica:
   TODA LARGURA FIXA QUE HOSPEDA TEXTO SE DIMENSIONA PELA MAIS LARGA DA
   FAMÍLIA INTEIRA — preferida INCLUÍDA —, e trocar a família obriga a remedir. */
.admin-conta-legenda {
    /* `sem festa · faltam 60 d` é meio rótulo e meio número; display com
       `tabular-nums` mantém a coluna alinhada conta a conta. */
    font-family: var(--f-display);
    font-variant-numeric: tabular-nums;
    flex: 0 1 17rem;
    font-size: var(--fs-2);
    font-weight: 700;
    color: var(--cor-texto);
}

/* `.medidor` nasce `width: 100%`, que numa linha de triagem comeria a faixa
   inteira. Aqui ela é uma coluna curta: a forma do rebanho lida num relance,
   descendo a lista. */
.admin-conta-prazo .medidor {
    width: 5.5rem;
    flex: 0 0 auto;
}

/* FAIXA CHEIA, na mesma abscissa do nome (§15.2.2 regra 5). Serve a três coisas
   de uma vez: cumpre a `composicao_da_pagina.REGRA` do `layout.json` (uma borda
   esquerda) DENTRO do componente, impede que o marcador longo (`22 arquivos não
   saíram do armazenamento`) empurre a legenda, e mantém a fileira de cima
   estável em todas as linhas. São no máximo DOIS marcadores
   (`ContaNaAdministracao::marcadores()`), então o pior caso da faixa é conhecido.

   ⚠️ ESTE É O ÚNICO FILHO DA LINHA QUE O DEMO NÃO TEM, e por isso a colocação
   dele é a única que esta folha precisa inventar. `grid-column: 1 / -1` diz
   "atravessa todas as trilhas, quantas forem" — funciona igual nas três
   anatomias (uma, duas e quatro colunas) e por isso mora aqui, fora dos blocos
   de virada.

   ⚠️ `flex: 0 1 100%` E `order: 1` SAÍRAM: numa grade nenhum dos dois pinta. O
   `order` fazia trabalho real enquanto a linha era flex (devolvia a seta para a
   fileira do nome), e é justamente por isso que ele não podia FICAR: na grade
   ele continua alterando a ORDEM DE AUTO-POSICIONAMENTO, e foi assim que, na
   variante que MEDI antes de escolher, a seta caiu na linha 2 coluna 1 e os
   marcadores na linha 2 coluna 2. Propriedade que sobrevive a uma troca de
   contexto fazendo outra coisa é pior que propriedade morta. */
.admin-conta-marcadores {
    display: flex;
    grid-column: 1 / -1;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--e-2);
    min-width: 0;
}

/* `.badge` nasce `nowrap` — certo para `Ativo`, errado para
   `22 arquivos não saíram do armazenamento`, que em 360px sairia da caixa. O
   marcador é FRASE, e frase embrulha. */
.admin-conta-marcadores .badge {
    white-space: normal;
}

/* ⚠️ `.admin-conta-bancada > .admin-conta-cab` SAIU (T-0031 3e — ver "O QUE
   SAIU DA FOLHA" na §admin). `.admin-conta-bancada` continua VIVA e é só o
   filho que morreu: o cabeçalho de identidade da conta virou `.cabine-pessoa`
   dentro do `<summary>`. */

/* -----------------------------------------------------------------------------
   O RITMO DA BANCADA — um degrau abaixo, e ele foi MEDIDO, não sentido
   -----------------------------------------------------------------------------
   G2 da UX: *uma conta aberta, com a zona de perigo fechada, cabe numa tela de
   720px*. Medido no navegador a 1280px, o pior caso do seed (uma conta com festa
   atual, que ganha a caixa de encerrar, e com a exclusão bloqueada por RF-136)
   dava **786px** — 66px acima do teto, enquanto a mais curta dava 677.

   Onde estavam os 66: a bancada empilha CINCO blocos, e três deles se separam
   por *fio e respiro* de `--e-4` em cima e `--e-4` embaixo do fio. São 32px por
   separador, 96px em três, mais 16px por ato empilhado. Numa PÁGINA esse é o
   ritmo certo; numa superfície de trabalho revelada por um clique, ele é 18% da
   altura em ar.

   ⚠️ O QUE MUDA É O DEGRAU DA ESCALA, NÃO A REGRA: os separadores continuam
   sendo fio + respiro, e o respiro continua sendo token (`--e-3`, um degrau
   abaixo de `--e-4`). Nenhum valor solto entra, nenhum fio some, e nada disto
   alcança a Visão Geral, Integrações ou Configurações — tudo está escopado em
   `.admin-conta`/`.admin-conta-bancada`.

   ⚠️ E NENHUM ALVO DE TOQUE ENCOLHE: os `min-height: 44px` de `.admin-acao`,
   `.convite-input`, `.campo-checkbox` e dos dois `<summary>` ficam intactos —
   o que sai é o vão ENTRE eles, nunca o alvo.
   (T-0031 3e: `.admin-acao` não existe mais — os outros três continuam valendo,
   e o que aconteceu com o alvo do console está escrito no bloco "O ALVO DE 44px
   DO CONSOLE SAIU DAQUI", mais abaixo.)

   MEDIDO DEPOIS, no navegador, as nove contas do seed abertas uma a uma com a
   zona de perigo fechada, a 1280px e a 768px: **601 a 706px**, todas abaixo do
   teto de 720.

   ⚠️ A FOLGA DO PIOR CASO É DE 14px, E FICA DITA: uma conta cujo nome, cujo
   `ocupacao_aviso` ou cuja frase de fila quebrem em mais UMA linha passa de 720.
   Quem precisar de folga de verdade tem duas saídas ESTRUTURAIS, e nenhuma delas
   é apertar mais a escala — pôr os dois caminhos de extensão lado a lado em
   caixa larga (~52px) ou tirar o inventário `Eventos · Cadastro` da bancada
   (~20px). As duas são do `especialista-ui`, e vão declaradas no RELATORIO.

   ⚠️ E EM 360px A CONTA ABERTA MEDE 885 a 1.070px, porque tudo empilha: G2 não
   vale ali, e nem foi escrito para valer — o gate de 360px é o de ZERO ROLAGEM
   HORIZONTAL, medido e cumprido. O resto é do `especialista-responsividade`.
   -------------------------------------------------------------------------- */
.admin-conta-bancada {
    /* 18px era valor solto; `--e-4` é o token do mesmo degrau, e ele já é o
       recuo que o resto do cartão usa. `--e-5` mantém os 20px horizontais de
       `.secao-corpo`, que é o que alinha a bancada com a linha fechada. O rodapé
       é um degrau menor porque ali não há separação a fazer: o que vem antes
       dele é o `<summary>` da zona de perigo, que já tem 44px de corpo próprio. */
    padding: var(--e-4) var(--e-5) var(--e-3);
}

/* ⚠️ OS OUTROS DEGRAUS DESTA MESMA REDUÇÃO NÃO MORAM AQUI, E É DE PROPÓSITO:
   eles foram aplicados NA REGRA QUE JÁ EXISTIA (`.admin-bloco`/`.admin-atos`,
   `.admin-ato`, `.admin-estender`, `.admin-estender-data`,
   `.admin-conta .campo-checkbox`), e não numa segunda regra com o mesmo seletor.
   Duas regras para o mesmo seletor são o que faz a próxima leitura consertar a
   de cima e não ver a de baixo — a folha já registra a varredura de seletor
   repetido como defeito. Cada valor mora numa casa só. */
/* -----------------------------------------------------------------------------
   A ZONA DE PERIGO — o segundo e ÚLTIMO nível de revelação (§4.2 da UX)
   -----------------------------------------------------------------------------
   ⚠️ ELA É FRONTEIRA, NÃO PESO. O erro comum é o oposto — destrutivo = mais
   vermelho, maior, mais visível —, e está de cabeça para baixo: peso visual
   ATRAI O DEDO, e nesta tela o mesmo clique apaga foto de festa de cliente real
   de um balde compartilhado. O ato destrutivo precisa ser o mais difícil de
   acertar por acidente, e ele não precisa ser achado: quem veio apagar já sabia.

   Por isso o `<summary>` da zona é DISCRETO (`--cor-texto-suave`, o par que
   `.admin-sub` já usa nesta superfície) e não compete com os dois `.btn-perigo`
   que moram dentro dele. A cerca vermelha continua sendo de `.admin-ato-perigo`,
   onde ela sempre esteve.

   ⚠️ E O CLIQUE EXTRA É PAGO SÓ POR QUEM VAI APAGAR — o caminho mais raro e mais
   perigoso —, enquanto os ~350px que ele guarda são economizados por todo mundo:
   é o que faz uma conta aberta caber numa tela.
   -------------------------------------------------------------------------- */
.admin-perigo {
    /* O MESMO fio e o MESMO respiro de `.admin-bloco`/`.admin-atos`, e pelo
       mesmo motivo: a zona é o terceiro assunto da bancada, não um quarto
       vocabulário. Os valores acompanham o orçamento de G2. */
    margin-top: var(--e-3);
    padding-top: var(--e-2);
    border-top: 1px solid var(--cor-borda);
}

.admin-perigo-linha {
    display: flex;
    align-items: center;
    gap: var(--e-2);
    /* O recuo mora na REGRA BASE e nao no :hover: declarado so no hover, o rotulo
       andaria 8px para a direita no instante em que o ponteiro chega — alvo que se
       move debaixo do dedo, numa linha que abre a zona destrutiva. */
    padding: 0 var(--e-2);
    margin: 0 calc(var(--e-2) * -1);
    min-height: var(--alvo-toque);
    font-size: var(--fs-2);
    font-weight: 800;
    color: var(--cor-texto-suave);
    cursor: pointer;
    list-style: none;
}

.admin-perigo-linha::-webkit-details-marker {
    display: none;
}

/* ⚠️ A ZONA CONTINUA DISCRETA EM REPOUSO — é decisão escrita logo acima
   ("fronteira, não peso": peso visual atrai o dedo, e este clique apaga foto de
   cliente). O que a direção B acrescenta é o RETORNO ao ponteiro e ao aberto:
   `--fundo-risco-2` é a superfície do gatilho da zona na cabine, e ela só
   aparece quando o operador já está em cima dela ou já a abriu. Em repouso a
   linha continua exatamente como estava. */
.admin-perigo-linha:hover,
.admin-perigo[open] > .admin-perigo-linha {
    color: var(--cor-texto);
    background: var(--fundo-risco-2);
    border-radius: var(--raio-tecla);
}

.admin-perigo-linha::after {
    content: "\203A";
    flex: 0 0 auto;
    font-size: var(--fs-4);
    line-height: 1;
    color: var(--cor-acento);
    transform: rotate(90deg);
    transition: transform var(--mov-rapido) var(--curva-padrao);
}

.admin-perigo[open] > .admin-perigo-linha::after {
    transform: rotate(-90deg);
}

/* O CORPO DA ZONA GANHA SUPERFÍCIE PRÓPRIA. Sem ela, os dois atos destrutivos
   moravam no mesmo branco do resto da bancada, e a única fronteira era o vão.
   `--fundo-risco` é a superfície de bloco de risco da direção B — no claro ela
   é um rosa quase branco (o alarme é a AÇÃO, não a situação: TD-076 §8), no
   escuro é um degrau real acima do cartão. O fio interativo fecha a caixa. */
.admin-perigo-corpo {
    margin-top: var(--e-2);
    padding: var(--e-3);
    background: var(--fundo-risco);
    border: 1px solid var(--fio-2);
    border-radius: var(--raio-peca);
}

/* ⚠️ `.admin-conta-cab` SAIU (T-0031 3e — ver "O QUE SAIU DA FOLHA" na §admin).
   O que ela armava — quem é a conta à esquerda, o estado com o interruptor à
   direita, empilhando em caixa estreita — é hoje o `<summary>` da conta, com
   `.admin-conta-linha` e `.cabine-conta-leitura`. */

.admin-atos-linha {
    display: flex;
    align-items: center;
    gap: var(--e-2);
}

/* Os dois blocos de baixo do cartão — o armazenamento e os atos — são assuntos
   diferentes do prazo que vem acima deles. Fio e respiro, o mesmo par que
   `.painel-perigo` já usa para separar assunto dentro de uma tela.
   ⚠️ O RESPIRO DESCEU UM DEGRAU NA T-0021 (`--e-4` → `--e-3` acima do fio,
   `--e-2` abaixo), e o fio ficou: com o cartão nascendo fechado, a bancada é uma
   superfície de trabalho revelada por um clique, e o orçamento dela é o de G2 —
   *uma conta aberta cabe numa tela*. O porquê inteiro, com os números medidos,
   está no bloco "O RITMO DA BANCADA" acima. */
.admin-bloco,
.admin-atos {
    margin-top: var(--e-3);
    padding-top: var(--e-2);
    border-top: 1px solid var(--cor-borda);
}

/* Cada ato é um bloco que se sucede a outro; sem respiro entre eles, cinco
   botões viram uma coluna de botões sem dono. (`--e-4` → `--e-2` na T-0021,
   pelo mesmo orçamento.) */
.admin-ato {
    margin-bottom: var(--e-2);
}

.admin-atos > :last-child {
    margin-bottom: 0;
}

/* =============================================================================
   ⚠️ O ALVO DE 44px DO CONSOLE SAIU DAQUI, E ELE NÃO FOI SUBSTITUÍDO — LEIA
   =============================================================================
   Este era o par `.admin-conta .admin-acao, [aria-labelledby="fila-do-
   armazenamento"] .admin-acao { min-height: var(--alvo-toque) }`, escrito na
   T-0021 depois de medir 34px em 90 botões: a PRIMEIRA LINHA desta folha manda
   "áreas de toque com mínimo de 44px", e são botões que apagam foto de cliente.

   Ele saiu porque `.admin-acao` não existe mais no DOM de nenhuma das 26 telas
   servidas (T-0031 3e — ver "O QUE SAIU DA FOLHA" na §admin): a regra já não
   alcançava elemento nenhum, e mantê-la seria fingir uma proteção.

   ⚠️ MAS A PROTEÇÃO EM SI NÃO VOLTOU POR OUTRA PORTA, e isso é ACHADO desta
   etapa, não conserto dela: quem veste os botões do console agora é
   `.cabine-tecla`, cujo `min-height` é 40px (§8) — quatro abaixo do piso da
   casa, nos mesmos botões destrutivos. Os 44px foram perdidos quando a marcação
   trocou, na etapa 3, e NÃO nesta remoção. Mexer nos 40px é decisão do
   `especialista-ui` (o número vem do demo aprovado) com o
   `especialista-responsividade`, e vai no relatório como consulta.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   O CANAL DO TRACEJADO — "marcado, ainda não aconteceu"
   -----------------------------------------------------------------------------
   Fio inteiro = já aconteceu; tracejado = está na fila. A fila do armazenamento
   é o único lugar do produto que mostra trabalho PENDENTE, e ela não tinha
   nenhuma marca disso: era um formulário solto no corpo da seção, do tamanho e
   da cor de todos os outros. `--fio-pendente` e `--fundo-fila` estavam
   declarados nos dois modos e ninguém os lia.
   O canal sobrevive a daltonismo e a impressão em preto e branco, porque não é
   cor: é traço. Medido: o tracejado dá 4,37:1 contra a superfície da fila no
   claro e 3,98:1 no escuro (piso de objeto gráfico: 3:1).
   ⚠️ O GANCHO É O `aria-labelledby` QUE A `<section>` JÁ DECLARA, pelo mesmo
   motivo da regra acima: a view é do `especialista-backend` e não é alterada
   aqui. Se um dia a seção ganhar classe própria, os dois seletores trocam.
   -------------------------------------------------------------------------- */
[aria-labelledby="fila-do-armazenamento"] .admin-ato {
    padding: var(--e-3);
    border: 1px dashed var(--fio-pendente);
    border-radius: var(--raio-tecla);
    background: var(--fundo-fila);
}

/* -----------------------------------------------------------------------------
   O RELATO DA CARONA — o recibo do que o sistema fez sem o operador
   -----------------------------------------------------------------------------
   `views/admin/_carona.php` §7.12: a carona roda DURANTE o GET e este bloco é o
   recibo dela. Recibo é o oposto da fila — fila é o que vai acontecer, recibo é
   o que aconteceu —, e a direção B dá a cada um sua superfície: `--fundo-fila`
   com tracejado lá, `--fundo-recibo` com fio inteiro aqui. Sem isso o relato
   era mais uma seção branca no meio de sete seções brancas.
   -------------------------------------------------------------------------- */
[aria-labelledby="relato-da-carona"] .secao-corpo {
    background: var(--fundo-recibo);
}

/* O MESMO PISO PARA OS CAMPOS: medi 43px no campo da cota — um pixel abaixo da
   regra da casa, em 360, 768 e 1440. Um pixel não é discussão de gosto: é a
   diferença entre cumprir e não cumprir a linha 1 desta folha. */
.admin-conta .convite-input {
    min-height: var(--alvo-toque);
}

/* Os DOIS atos que apagam ganham cerca própria, e ela não é decoração: o balde é
   um só para desenvolvimento e produção, então a fronteira entre "estender" e
   "apagar" precisa ser visível antes do clique, não depois. Quem carrega a
   informação continua sendo a FRASE da §7 dentro da caixa de confirmação; a
   cerca é reforço.

   ⚠️ O LIMITE ERA VERMELHO CLARO E NÃO ERA FRONTEIRA NENHUMA — NC-05 da T-0021.
   Medido de novo por mim, nos dois temas: a SUPERFÍCIE da cerca contra o cartão
   mede 1,11:1 no claro e 1,01:1 no escuro (no escuro ela simplesmente não
   existe), e o fio de 1px em `--cor-erro-borda` mede 1,56:1 e 1,76:1 — os dois
   abaixo do piso de 3:1 de objeto gráfico. A UX conta com esta cerca como uma
   das TRÊS fronteiras que substituem o peso visual dos atos destrutivos, e uma
   fronteira que não se vê não é uma das três.
   A tinta passa a ser `--limite`: 4,53:1 no claro e 4,72:1 no escuro contra o
   cartão, MEDIDO. Neutro, já existente na folha, zero cor nova — e mais fiel à
   decisão "fronteira, não peso" do que uma cerca rosa invisível: o vermelho
   continua vivo onde ele informa, que é a superfície da cerca, o rótulo e o
   contorno de 2px do próprio botão que apaga. */
.admin-ato-perigo {
    padding: var(--e-3);
    border: 1px solid var(--limite);
    border-radius: var(--raio-md);
    background: var(--cor-erro-fundo);
}

/* NC-06 — O NÚMERO PUBLICADO DESCREVIA A MINORIA DOS CASOS. O comentário do
   BUG-TD-075 justifica o fio da caixa com "de 1,13:1 para 1,56:1, a fronteira
   fica MAIS visível", e isso vale sobre o CARTÃO — onde mora UMA das três
   caixas. As outras DUAS moram dentro da cerca, e lá o mesmo par mede 1,40:1 no
   claro e 1,78:1 no escuro (MEDIDO). E não é uma caixa qualquer: é a `required`,
   a camada de confirmação que funciona sem JavaScript.
   Dentro da cerca o fio vai para `--limite` — 4,08:1 claro e 4,75:1 escuro
   contra a superfície da cerca, MEDIDO. Fora da cerca o BUG-TD-075 continua
   inteiro, e o `:hover` continua vermelho nos três casos: ele tem especificidade
   maior e é reforço de estado, não a fronteira em repouso. */
.admin-ato-perigo .campo-checkbox {
    border-color: var(--limite);
}

/* ⚠️ ACHADO NO NAVEGADOR, E SÓ NO NAVEGADOR: DENTRO DA CERCA O BOTÃO SUMIA.
   `.btn-perigo` pinta a própria superfície com `--cor-erro-fundo` — o mesmo
   valor que a cerca acima usa —, então o retângulo do botão media 1,00:1
   contra o fundo em que ele estava e lia como TEXTO VERMELHO SOLTO, não como
   controle. Nenhuma leitura de código pega isso: as duas regras estão certas
   separadas, e o defeito só existe quando uma mora dentro da outra.
   O contorno usa a MESMA tinta do rótulo (`--cor-erro-texto`), que mede
   5,52:1 sobre `--cor-erro-fundo` — bem acima dos 3:1 que a WCAG 1.4.11 pede
   para o limite de um controle — e gira junto no modo escuro, porque os dois
   lados do par são tokens. Nenhuma cor nova entra na folha.
   2px e não 1px: é o botão que apaga foto de cliente num balde compartilhado;
   ele é o alvo que mais precisa ser encontrado de propósito e o que menos pode
   ser acertado por engano. */
.admin-ato-perigo .btn-perigo {
    border: 2px solid var(--cor-erro-texto);
}

/* -----------------------------------------------------------------------------
   O DESTRUTIVO CONFIRMADO — `--rosa-solido`, o único vermelho CHEIO do produto
   -----------------------------------------------------------------------------
   TD-076 §8: vermelho gasto só no irreversível, e cheio só quando o operador JÁ
   DISSE QUE SIM. Até aqui a folha tinha o pigmento declarado nos dois modos e
   nenhum estado que o lesse — o botão em repouso e o botão armado eram o mesmo
   objeto, e a caixa `required` era a única diferença entre os dois.
   O ESTADO EXISTE NO APP e não foi inventado aqui: `views/admin/_conta.php` e
   `views/admin/_fila.php` põem um `<input type="checkbox" required>` dentro de
   `.campo-checkbox`, no MESMO formulário do botão. `:has()` lê esse estado sem
   uma linha de JavaScript e sem tocar na marcação — que não é minha nesta etapa.
   ⚠️ DEGRADAÇÃO: navegador sem `:has()` mostra o botão em repouso, que é o que
   já existia hoje. Some o reforço, não some o controle nem a confirmação.
   Medido: `--tinta-viva` sobre `--rosa-solido` 6,12:1 no claro e 6,46:1 no
   escuro (no escuro a tinta viva é o carvão, não o branco — branco daria 2,99).
   -------------------------------------------------------------------------- */
.admin-ato-perigo:has(.campo-checkbox input:checked) .btn-perigo {
    background: var(--rosa-solido);
    color: var(--tinta-viva);
    border-color: var(--rosa-solido);
}

.admin-ato-perigo:has(.campo-checkbox input:checked) .btn-perigo:hover {
    background: var(--rosa-forte);
    color: var(--tinta-viva);
}

/* O grupo de extensão. `<fieldset>` pelo AGRUPAMENTO — a `<legend>` é o rótulo
   de grupo da §7.1 e dá UM nome acessível aos dois formulários que moram dentro
   dele —, e a moldura tracejada é a mesma de `.config-pagamento`, o outro grupo
   desta natureza no produto. `min-width: 0` porque `<fieldset>` traz um
   `min-content` implícito do navegador que impede o filho de encolher. */
.admin-estender {
    /* `--e-4` → `--e-2` e `--e-3` → `--e-2` na T-0021, pelo orçamento de G2: o
       grupo já é uma caixa dentro de uma caixa dentro de um cartão, e quem
       separa os dois caminhos é a moldura tracejada, não o vão. */
    margin-bottom: var(--e-2);
    padding: var(--e-2);
    border: 1px dashed var(--cor-borda);
    border-radius: var(--raio-md);
    min-width: 0;
}

.admin-estender legend {
    padding: 0 var(--e-2);
    font-size: var(--fs-2);
    font-weight: 800;
    color: var(--cor-acento);
}

/* Os três botões rápidos se contam sozinhos: em caixa larga cabem lado a lado,
   em 360px empilham. Rótulo longo (`+30 dias · até 27/09/2026`) não pode ser
   cortado — é a data que RF-132 manda estar na tela ANTES do clique. */
.admin-estender-rapidos {
    display: flex;
    flex-wrap: wrap;
    gap: var(--e-2);
}

.admin-estender-data {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--e-2);
    /* `--e-3` → `--e-2` na T-0021, mesmo orçamento. */
    margin-top: var(--e-2);
}

/* O controle nativo de data tem largura própria em cada navegador; sem um piso
   ele encolhe abaixo do que o próprio `dd/mm/aaaa` ocupa e o campo passa a ser
   um retângulo com texto cortado. */
.admin-estender-data .convite-input {
    min-width: 9rem;
}

.integra { display: flex; align-items: flex-start; gap: 16px; padding: 18px 0; border-bottom: 1px solid var(--cor-borda); }
.integra:last-child { border-bottom: 0; }
.integra-logo { width: 48px; height: 48px; border-radius: 14px; display: flex; align-items: center; justify-content: center;
    font-size: 1.4rem; flex-shrink: 0; background: var(--cor-roxo-claro); }
.integra-logo-b2 { background: #e21e23; }
.integra-logo-mp { background: #00b1ea; }
.integra-logo-wa { background: #25d366; }
.integra-meta { flex: 1; min-width: 0; }
.integra-lin1 { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.integra-lin1 b { font-weight: 900; font-size: 1rem; }
.integra-meta p { margin: 4px 0 0; color: var(--cor-texto-suave); font-weight: 700; font-size: 0.84rem; }
.integra-futura { opacity: 0.7; }
.form-keys { margin: 14px 0 6px; padding: 16px; background: #fbfaff; border: 1px solid var(--cor-borda); border-radius: 14px; }
.campo-hint { display: block; color: var(--cor-texto-suave); font-weight: 700; font-size: 0.74rem; margin-top: 4px; }
.integra-testar { margin-top: 4px; }
.admin-rodape-nota { color: var(--cor-texto-suave); font-weight: 700; font-size: 0.82rem; text-align: center; margin-top: 6px; }
.admin-config-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }

/* ⚠️ ACHADO, e ele vale mais que a conversão: `.metricas` (e `.metrica`,
   `.metrica-ic`, `.metrica-num`, `.metrica-rot`) não tem NENHUM consumidor —
   não aparece em `views/` nem em `assets/js/`. O que existe na galeria é
   `.metricas-lado`, que é outra regra. Cinco regras e uma media query vivas no
   CSS e mortas na tela. Registrado para a F8; não removidas aqui porque limpeza
   de legado tem critério de saída próprio (TD-012 item 3). A media query, essa
   sim, sai — pelo mesmo motivo das outras. */
.metricas { display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 12px; margin-bottom: 18px; }
.metrica { background: var(--cor-cartao); border: 1px solid var(--cor-borda); border-radius: var(--raio-peca);
    padding: 16px; text-align: center; box-shadow: var(--elev-1); }
.metrica-ic { display: block; color: var(--cor-texto-suave); }
.metrica-ic .ico-em-linha { width: 22px; height: 22px; vertical-align: baseline; }
/* Número é tinta — mesma correção de `.stat-numero`, mesmo motivo (§14.6). */
.metrica-num { display: block; font-family: var(--f-display); letter-spacing: -0.02em; font-size: var(--fs-6);
    font-weight: 900; line-height: 1.25; font-variant-numeric: tabular-nums; color: var(--cor-texto); }
.metrica-rot { display: block; font-family: var(--f-display); font-size: 0.8rem; color: var(--cor-texto-suave); font-weight: 700; }

/* ⚠️ `.status-pill` E `.status-pill .ico-em-linha` SAÍRAM (T-0031 3e — ver
   "O QUE SAIU DA FOLHA" na §admin). A pílula não é emitida em NENHUMA das 26
   telas servidas, nem no console nem fora dele — e o "fora dele" precisou ser
   medido, porque o nome não é de admin e ela poderia viver em qualquer tela.
   ⚠️ E A CONSULTA QUE A SEGUNDA REGRA RESPONDIA ESTÁ RESPONDIDA DE OUTRO JEITO,
   sem perder o número: ela existia para que o ponto de estado medisse os 7px do
   desenho quando o glifo `●` virasse `<svg class="ico-em-linha">`. Na marcação
   de hoje o ponto é `.cabine-ponto`, que declara `width: 7px; height: 7px` —
   o MESMO valor, agora sem depender do corpo de texto da pílula em volta.
   ⚠️ `.status-ok` e `.status-on` FICAM: elas têm a mesma medida de órfãs, mas
   não estavam na lista desta etapa (ver a nota de escopo em `.admin-link-ic`). */
.status-ok { background: var(--cor-sucesso-fundo); color: var(--cor-sucesso-texto); }

/* A SEGUNDA ocorrência do âmbar literal, gêmea de `.badge-warn` e com a mesma
   medida: 4,99:1 no par literal, 5,95:1 no par com nome. Ela é a pílula que diz
   "Em manutenção" no alto da tela — e é ela, junto com o rótulo em texto da
   chave, que carrega a GRAVIDADE que o trilho da chave deixou de carregar. */
.status-on { background: var(--cor-aviso-fundo); color: var(--cor-aviso-texto); }

/* =============================================================================
   BUG-TD-060 — A CHAVE REPROVAVA A WCAG 1.4.11 NOS DOIS ESTADOS
   =============================================================================
   `.switch` é um controle de interface: o critério que vale é 1.4.11 (contraste
   de não-texto, piso 3:1 contra as cores ADJACENTES). Medido antes e depois, e
   as duas peças adjacentes são o cartão branco (fora) e a bolinha branca
   (dentro) — que, sendo as duas brancas, dão a MESMA razão:

       desligado  #cfc9de ......... 1,61:1  ❌      `--limite` #7a7290 .. 4,53:1 ✔
       ligado     #e0992a ......... 2,40:1  ❌   `--cor-primaria` #7c3aed  5,70:1 ✔

   ⚠️ T-0031 4a (BUG-TD-128 / BUG-TD-136): A COLUNA DA DIREITA ENVELHECEU. O
   ligado passa de `--cor-primaria` (marca, invariante de modo — TD-076 §4) a
   `--cor-acento` (o preenchimento vivo, que clareia no escuro). Medido contra
   as adjacentes de CADA pele — cartão e bolinha, que são `--cor-cartao`:
       ligado    `--cor-acento`   #5c31f6 / #ffffff .... 6,51:1 ✔  (claro)
       ligado    `--cor-acento`   #b3a1ff / #241f32 .... 7,18:1 ✔  (escuro)
       ligado    `--cor-primaria` #7c3aed / #241f32 .... 2,80:1 ❌  (o que estava no ar)
       desligado `--limite`       #7b719b ............... 4,49:1 claro · 3,55:1 escuro ✔

   ⚠️ E O QUE O TEXTO NORMATIVO PERMITE, porque sem isso a correção pareceria
   incompleta: o Understanding do SC 1.4.11 diz, com todas as letras, que o
   critério NÃO exige que as cores que diferenciam ESTADOS de um mesmo componente
   contrastem entre si quando os estados não aparecem lado a lado. Ligado e
   desligado nunca são vistos juntos — cada um contrasta com o que está ao lado
   DELE, e é isso que as duas colunas acima medem.

   ⚠️ POR QUE O LIGADO É NEUTRO E NÃO SEMÂNTICO, e esta é a metade que importa:
   a MESMA classe veste DUAS chaves de significado oposto — o modo manutenção
   (onde ligado é ruim) e o cadastro de usuários (onde ligado é bom). Cor que
   muda de sentido conforme a tela não é semântica, é armadilha. A chave diz
   LIGADO/DESLIGADO; a CONSEQUÊNCIA é dita por texto — `.switch-rotulo` já
   renderiza "Manutenção ativada"/"Sistema no ar" e "Cadastro aberto"/"Cadastro
   desativado" — e a gravidade, pela pílula `.status-on` da família de aviso.
   É a regra `estado_nunca_so_por_cor` aplicada ao controle que mais precisava
   dela.

   `--limite` é o token cujo cargo declarado é literalmente "limite de
   componente, critério 1.4.11 = 3:1". Ele foi criado para este trabalho e esta
   é a primeira vez que ele o faz.

   E as DURAÇÕES saem de literal: `0.2s` não é `--mov-rapido` (160ms) nem
   `--mov-medio` (240ms), e uma transição sem curva usa o `ease` do navegador,
   que não é nenhuma das três curvas do sistema. Mesma correção que o `.barra
   span` recebeu na passagem do painel do dono, pelo mesmo motivo.
   ========================================================================== */
.switch { display: inline-flex; align-items: center; gap: 12px; cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch-trilho { width: 52px; height: 30px; border-radius: var(--raio-pilula); background: var(--limite); position: relative; transition: background-color var(--mov-rapido) var(--curva-padrao); flex-shrink: 0; }
.switch-bolinha { position: absolute; top: 3px; left: 3px; width: 24px; height: 24px; border-radius: 50%; background: var(--cor-cartao); transition: left var(--mov-rapido) var(--curva-padrao); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); }
.switch input:checked + .switch-trilho { background: var(--cor-acento); }
.switch input:checked + .switch-trilho .switch-bolinha { left: 25px; }

/* O anel nasce no TRILHO e não no `<input>`: o input é 0×0 e está em
   `opacity: 0`, então o anel dele seria invisível — justamente para quem o anel
   existe. Os três valores agora vêm dos tokens do produto (`2px solid
   var(--cor-primaria)` e `2px` eram os mesmos números escritos à mão, então o
   pixel não muda: o que muda é a folha passar a ter UM anel e não três). */
.switch input:focus-visible + .switch-trilho { outline: var(--foco-largura) solid var(--foco); outline-offset: var(--foco-desvio); }
.switch-rotulo { font-weight: 700; }
.manutencao-dica { margin-top: 14px; color: var(--cor-texto-suave); font-size: 0.9rem; }
.manutencao-dica a { color: var(--cor-acento); font-weight: 700; }

/* ----- Página pública de manutenção ----- */
.manutencao-body { background: linear-gradient(160deg, #f6f3ff 0%, #ede9fe 55%, #fbe0f0 100%); min-height: 100vh; display: flex; }
.manutencao-wrap { margin: auto; padding: 24px 16px; width: 100%; max-width: 520px; }
.manutencao-card { background: var(--cor-cartao); border: 1px solid #ece7f7; border-radius: 24px; padding: 28px 24px 32px; text-align: center; box-shadow: 0 24px 60px -28px rgba(80, 40, 140, 0.45); }
.manutencao-art { width: 100%; max-width: 380px; height: auto; display: block; margin: 0 auto 12px; }
.manutencao-titulo { font-size: 1.5rem; font-weight: 900; color: var(--cor-texto); margin-bottom: 10px; }
.manutencao-texto { color: #6b6483; font-size: 1rem; line-height: 1.6; margin-bottom: 14px; }
.manutencao-texto strong { color: #6d28d9; }
.manutencao-rodape { color: #9a93ad; font-size: 0.85rem; }
.manutencao-admin { display: inline-block; margin-top: 18px; font-size: 0.8rem; color: #b6aecb; text-decoration: none; }
.manutencao-admin:hover { color: var(--cor-acento); text-decoration: underline; }

/* -----------------------------------------------------------------------------
   PÁGINAS DE ERRO (404 e 500) — a única peça que elas não acharam pronta
   -----------------------------------------------------------------------------
   As duas telas de erro deixaram de ter folha própria (`app.css` REMOVIDO,
   TD-045 item 4). Tudo o que elas desenham é reúso declarado, e nada disso
   nasceu aqui: `.container` > `.card.centro` > `.evento-vazio` + `<h1>` +
   `.subtitulo` + `.link-alternativo` é a MESMA anatomia de
   `views/termos/nao-encontrada.php`, `views/convite/nao-encontrado.php` e
   `views/auth/cadastro.php`. Tela de erro não é família nova de componente.

   O `<pre>` do detalhe é o único caso sem peça equivalente na folha — não há
   uma só declaração `monospace` no arquivo inteiro, conferido. Ele só existe
   com `APP_DEBUG=true` (`Kernel::responderExcecao()` manda `detalhe` como
   `null` quando o depurador está desligado, que é sempre em produção), e o que
   ele carrega é CAMINHO DE ARQUIVO: uma palavra única, longa e sem espaço onde
   quebrar. Sem esta regra ele estoura a largura do cartão e dá rolagem
   horizontal à PÁGINA INTEIRA no celular — `overflow-wrap: anywhere` quebra
   dentro da palavra, que é o que um caminho é.

   CINZA E NÃO VERMELHO, de propósito: o vermelho deste produto é do que o
   VISITANTE precisa resolver (`.alerta-erro`), e um caminho de arquivo não é
   isso — é fato consumado de diagnóstico, o mesmo cargo do
   `.painel-status-encerrado`. Par medido por mim (WCAG 2.1, texto normal):
   `--cor-neutro-texto` sobre `--cor-neutro-fundo` = **8,05:1**.

   `text-align: left` porque o cartão é `.centro` e caminho centrado não se lê.
   -------------------------------------------------------------------------- */
/* O RESPIRO VERTICAL DA PÁGINA, e ele precisa existir AQUI por um defeito já
   medido e já documentado neste arquivo: `.container { padding: 0 16px }` é UMA
   CLASSE (0,1,0) e vence `main { padding: 26px 16px 56px }`, que é UM TIPO
   (0,0,1) — o `<main>` do produto inteiro tem `padding-top: 0` em todas as
   larguras (ver a nota no bloco de 48rem). Nas 18 telas isso não aparece porque
   existe um `<header class="topo">` empurrando o conteúdo para baixo; ESTAS DUAS
   NÃO TÊM CABEÇALHO, e sem esta regra o cartão encosta na borda de cima da
   janela.

   É o mesmo remendo que `.inicio` fazia na página inicial da T-0015 (a vitrine
   da T-0017 paga o topo fixo em `.vitrine`), pelo mesmo motivo, com o mesmo token e
   sem tocar no ritmo vertical das outras telas — a correção de raiz
   (`main.container { padding-top: … }`) mexe nas 18 de uma vez e não é desta
   etapa. */
.erro-pagina {
    padding-block: var(--e-10);
}
.erro-detalhe {
    margin-top: var(--e-4);
    padding: var(--e-3);
    border: 1px solid var(--cor-neutro-borda);
    border-radius: var(--raio-md);
    background: var(--cor-neutro-fundo);
    color: var(--cor-neutro-texto);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--fs-2);
    line-height: var(--lh-normal);
    text-align: left;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* ============================================
   Galeria de fotos (álbum colaborativo)
   ============================================ */

/* Painel: área do QR + passos */
.galeria-qr-area { display: flex; flex-direction: column; align-items: center; gap: 18px; }
.galeria-qr { background: var(--cor-cartao); padding: 10px; border: 1px solid var(--cor-borda); border-radius: var(--raio-peca); }
.galeria-qr img, .galeria-qr canvas { display: block; }
.galeria-qr-acoes { align-self: stretch; min-width: 0; }
#baixar-qr { display: flex; width: fit-content; max-width: 100%; margin: 4px auto 0; }
.galeria-passos { margin: 8px 0 14px 18px; color: var(--cor-texto); font-size: 0.92rem; }
.galeria-passos li { margin-bottom: 4px; }

/* Convidado: envio de fotos */
.galeria-upload { text-align: center; }
.galeria-upload .btn { margin-top: 6px; }
/* "Enviando 3 de 8…" é contagem: display e `tabular-nums`, senão a frase pula de
   largura a cada foto que sobe. */
.galeria-status { margin-top: 14px; font-family: var(--f-display); font-variant-numeric: tabular-nums;
    font-weight: 700; min-height: 1.2em; }
.galeria-grade { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; margin-top: 16px; }
.gfoto { position: relative; aspect-ratio: 1 / 1; border-radius: 10px; overflow: hidden; background: rgba(255, 255, 255, 0.08); }
.gfoto img { width: 100%; height: 100%; object-fit: cover; display: block; opacity: 0.5; transition: opacity 0.3s; }
.gfoto.ok img { opacity: 1; }
.gfoto-marca { position: absolute; right: 4px; bottom: 4px; width: 24px; height: 24px; border-radius: 50%;
    display: none; align-items: center; justify-content: center; color: var(--tinta-texto); font-weight: 900; font-size: 0.85rem; }
.gfoto.ok .gfoto-marca { display: flex; background: rgba(29, 158, 117, 0.95); }
.gfoto.ok .gfoto-marca::after { content: '✓'; }
.gfoto.erro .gfoto-marca { display: flex; background: #e24b4a; }
.gfoto.erro .gfoto-marca::after { content: '!'; }

/* -----------------------------------------------------------------------------
   `.btn-galeria` — O BOTÃO SECUNDÁRIO DO ENVIO DE FOTOS
   -----------------------------------------------------------------------------
   ⚠️ ELE TAMBÉM TINHA `backdrop-filter: blur(4px)`, a segunda das duas violações
   vivas da proibição. Saiu pelo mesmo motivo do `.topo`.

   MAS AQUI O DESFOQUE ESCONDIA COISA PIOR, e isso só apareceu quando a página
   foi RENDERIZADA com o motor de verdade em vez de lida: este botão não fica
   sobre o fundo preto da câmera. Ele nasce DENTRO de
   `<section class="card card-borda galeria-upload">` (views/galeria/mostrar.php),
   e `.tema-convite .card` pinta `--cor-cartao`, que é `#ffffff` nos DOIS visuais.
   Então o que havia era `color: #fff` sobre `rgba(255,255,255,0.16)` sobre
   branco: o fundo compõe #ffffff exato e o rótulo mede 1,00:1 contra ele.
   Branco no branco — o botão estava INVISÍVEL, e o desfoque de um branco liso
   continua branco liso, então ele nunca ajudou.

   O QUE SUBSTITUI A PROFUNDIDADE: a tinta que esta folha JÁ declara para um
   controle secundário sobre cartão nesta família — a mesma de
   `.tema-convite .btn-secundario`: cartão chapado, rótulo em `--cor-texto` e o
   limite de 1 px em `--limite`. Não é cor nova, é reuso. Medido:

     visual-classico  rótulo #232838 sobre #ffffff .. 14,66:1  (piso 4,5:1)
                      limite #8d8069 sobre #ffffff ..  3,87:1  (piso 3:1)
     visual-jardim    rótulo #1f3a28 sobre #ffffff .. 12,40:1  (piso 4,5:1)
                      limite #7a8b61 sobre #ffffff ..  3,69:1  (piso 3:1)

   A geometria NÃO muda (pílula, mesmo alvo de toque): quem decide forma é o
   design system, e o que este conserto troca é só a tinta que estava ilegível.
   ⚠️ docs/painel-e-desktop.md §D.1 sugeriu `rgba(255,255,255,.22)` "sobre o
   fundo preto da câmera". A premissa está errada e foi medida: sobre o cartão
   branco esse valor compõe #ffffff e o botão seguiria em 1,00:1. Fica registrado
   para o `designer-visual` confirmar a tinta.
   -------------------------------------------------------------------------- */
.btn-galeria { display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    margin-top: 10px; padding: 11px 20px; border: 1px solid var(--limite);
    border-radius: var(--raio-pilula); cursor: pointer;
    font: inherit; font-weight: 800; color: var(--cor-texto); background: var(--cor-cartao); }
.btn-galeria:disabled { opacity: 0.5; }

/* Câmera embutida (estilo WhatsApp) — overlay fullscreen */
body.cam-travado { overflow: hidden; }
.cam-overlay { position: fixed; inset: 0; z-index: 2000; background: #000; display: none;
    flex-direction: column; }
.cam-overlay.cam-aberta { display: flex; }
.cam-video { flex: 1; width: 100%; height: 100%; object-fit: cover; background: #000; min-height: 0; }
.cam-topo { position: absolute; top: 0; left: 0; right: 0; z-index: 2; display: flex;
    align-items: center; justify-content: space-between; padding: 14px 16px;
    padding-top: calc(14px + env(safe-area-inset-top, 0px));
    background: linear-gradient(rgba(0, 0, 0, 0.55), transparent); }
.cam-icone { width: 42px; height: 42px; border: 0; border-radius: 50%; cursor: pointer;
    background: rgba(0, 0, 0, 0.4); color: var(--tinta-texto); font-size: 1.2rem; line-height: 1; }
.cam-contador { color: var(--tinta-texto); font-weight: 800; text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6); }
.cam-barra { position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; display: flex;
    align-items: center; justify-content: space-between; padding: 22px 30px;
    padding-bottom: calc(22px + env(safe-area-inset-bottom, 0px));
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.55)); }
.cam-galeria { width: 52px; height: 52px; border: 0; border-radius: 14px; cursor: pointer;
    background: rgba(255, 255, 255, 0.18); color: var(--tinta-texto); display: flex; align-items: center; justify-content: center; }
.cam-espaco { width: 52px; height: 52px; } /* equilibra o disparo no centro */
/* ⚠️ OS DOIS ÚNICOS `#fff` DE SUPERFÍCIE QUE SOBRAM NESTA FOLHA, E ELES FICAM.
   Cargo declarado: aqui `#ffffff` NÃO é cartão — é BRANCO FÍSICO (o disco do
   obturador e o clarão do flash) sobre o overlay `#000` da câmera, que é
   literal pela mesma razão. Apontá-los para `--cor-cartao` faria o obturador
   e o flash ESCURECEREM no dia em que a câmera alcançasse uma pele escura —
   um flash que escurece é a definição de token errado.
   Por que é seguro hoje, e a condição está escrita para quem mudar isso: a
   câmera é montada por `assets/js/galeria.js`, que só é servido pela galeria
   pública (`Tema::Convite`), e o convite NÃO tem modo escuro (TD-048 §6.1).
   INVARIANTE, por SELETOR e nunca por linha: as ÚNICAS ocorrências de
   `background: #fff` nesta folha são `.cam-disparo` e `.cam-flash`. Uma
   terceira significa que uma superfície voltou a ser literal. */
.cam-disparo { width: 74px; height: 74px; border-radius: 50%; cursor: pointer;
    background: #fff; border: 5px solid rgba(255, 255, 255, 0.45); box-shadow: 0 0 0 2px #fff inset; }
.cam-disparo:active { transform: scale(0.94); }
.cam-flash { position: absolute; inset: 0; z-index: 3; background: #fff; opacity: 0; pointer-events: none; }
.cam-flash-on { animation: cam-flash-anim 0.32s ease-out; }
@keyframes cam-flash-anim { 0% { opacity: 0.85; } 100% { opacity: 0; } }

/* Dono: ver / baixar / remover as fotos enviadas */
.galeria-vazia { text-align: center; color: var(--cor-texto-suave); padding: 22px 8px; line-height: 1.6; }
.fotos-grade { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
.foto-card { margin: 0; border: 1px solid var(--cor-borda); border-radius: var(--raio-peca); overflow: hidden;
    background: var(--cor-cartao); box-shadow: var(--elev-1); display: flex; flex-direction: column; }
/* O lugar da foto enquanto ela nao chega. Era `#f3eefc` literal - um quadrado
   claro no meio de uma grade escura. */
.foto-thumb { display: block; aspect-ratio: 1 / 1; background: var(--cor-roxo-claro); }
.foto-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.foto-rodape { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 7px 9px; }
.foto-autor { font-size: 0.78rem; font-weight: 700; color: var(--cor-texto-suave);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.foto-acoes { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.foto-acoes form { margin: 0; }
.foto-acao { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
    border: 0; background: transparent; border-radius: 8px; cursor: pointer; font-size: 0.95rem;
    text-decoration: none; line-height: 1; }
/* ⚠️ OS DOIS ERAM ALFA DA PALETA APOSENTADA — `rgba(124,58,237,.1)` é o violeta
   antigo e `rgba(226,75,74,.14)` é o vermelho que a F3 tirou da folha, os dois
   sobrevivendo dentro de um `rgba()` que nenhuma varredura de hexadecimal pega.
   E alfa sobre superfície variável é a mesma classe de defeito do `opacity`
   sobre texto: o par deixa de ser mensurável quando o cartão troca de pele.
   `--sup-hover` é o degrau de ponteiro do sistema e `--tecla-perigo` é a
   superfície da tecla destrutiva em repouso — os dois sólidos, os dois medidos. */
.foto-acao:hover { background: var(--sup-hover); }
.foto-acao-remover:hover { background: var(--tecla-perigo); }

@keyframes mnt-cursor { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
.manutencao-art .cursor { animation: mnt-cursor 1s steps(1) infinite; }
@keyframes mnt-digitar { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(3px); } }
.manutencao-art .maos { animation: mnt-digitar 0.5s ease-in-out infinite; }
@keyframes mnt-girar { to { transform: rotate(360deg); } }
.manutencao-art .eng { transform-box: fill-box; transform-origin: center; }
.manutencao-art .eng1 { animation: mnt-girar 7s linear infinite; }
.manutencao-art .eng2 { animation: mnt-girar 5s linear infinite reverse; }
@keyframes mnt-ret { 0%, 100% { opacity: 0.2; } 50% { opacity: 1; } }
.reticencias span { animation: mnt-ret 1.4s infinite; }
.reticencias span:nth-child(2) { animation-delay: 0.2s; }
.reticencias span:nth-child(3) { animation-delay: 0.4s; }


/* ----- Dress code (lista de sugestões de vestimenta) ----- */
.dresscode-lista {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 4px;
}
.dresscode-lista li {
    position: relative;
    padding: 10px 14px 10px 34px;
    border-radius: 12px;
    font-weight: 600;
}
.dresscode-lista li::before {
    content: "";
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 8px;
    height: 8px;
    border-radius: 50%;
}


/* =============================================================================
   F6 — COTA, PRAZO E DOWNLOAD EM PARTES (telas do dono)
   =============================================================================
   Três funções novas, DUAS peças: `painel-status` (informação permanente que às
   vezes vira aviso) e `medidor` (quanto de quanto). Componente novo só quando os
   existentes comprovadamente não atendem — `alerta` não servia porque ele é
   transitório por natureza (some ao recarregar, some ao corrigir), e cota e
   prazo são o contrário: estão sempre lá, e é por estarem sempre lá que o dono
   percebe quando mudam.

   ⚠️ CA-093: nada aqui — nem classe, nem `content` de CSS — fala de franquia,
   egresso, tráfego, excedente ou custo. A cota, em GB, é a única informação de
   infraestrutura que o dono vê (RN-054).
   ========================================================================== */

/* ----- Informação permanente com estado ------------------------------------ */

/**
 * O ESTADO NUNCA É DITO SÓ PELA COR. Quem lê a frase recebe a informação
 * inteira: é o texto da §6 que carrega o `⚠️`, o "está cheio" e o "faltam N
 * dias". Fundo, borda e a faixa de 4 px à esquerda são REFORÇO — se a cor
 * sumisse toda, a tela continuaria dizendo a mesma coisa.
 */
.painel-status {
    display: grid;
    gap: var(--e-2);
    padding: var(--e-3) var(--e-4);
    margin-bottom: var(--e-4);
    background: var(--cor-info-fundo);
    border: 1px solid var(--cor-info-borda);
    border-left-width: 4px;
    /* A FAIXA DE 4px É METADE DO QUE CARREGA O SIGNIFICADO DO PAINEL (a outra é
       a tinta), então ela é objeto gráfico com piso de 3:1 — não é ornamento
       isento. Aqui a marca é LIMITE e não preenchimento: no escuro `#7c3aed`
       sobre `--cor-info-fundo` mede 2,82:1 e REPROVA; `--cor-acento` mede 6,97:1. */
    border-left-color: var(--cor-acento);
    /* 16px era o raio da paleta anterior; `--raio-peca` (14px) é o degrau de
       PEÇA da direção B, o mesmo que o cartão e a banda leem. */
    border-radius: var(--raio-peca);
    color: var(--cor-texto);
}

.painel-status-texto {
    font-size: 0.95rem;
    font-weight: 700;
    line-height: 1.45;
}

/* Situação normal — a informação está ali, sem pedir nada. */
.painel-status-normal {
    background: var(--cor-info-fundo);
    border-color: var(--cor-info-borda);
    border-left-color: var(--cor-acento);
}

/* Virou aviso: 80 % da cota, últimos 15 dias do prazo, último dia das partes. */
.painel-status-alerta {
    /* Bloco, não pastilha — o mesmo par de `.alerta-aviso`, e pelo mesmo
       motivo. Medido com `--cor-aviso-texto`: 5,59:1 claro · 7,71:1 escuro. */
    background: var(--fundo-aviso);
    border-color: var(--cor-aviso-borda);
    border-left-color: var(--medidor-aviso);
    color: var(--cor-aviso-texto);
}

/**
 * Crítico: não cabe mais uma foto, então o portão do envio JÁ PODE ESTAR
 * RECUSANDO (ver `TextoDaCota::paraODono`). É o estado que precisa parar o olho
 * do dono no meio da festa, e por isso é o único que empresta o vermelho.
 */
.painel-status-cheio {
    background: var(--cor-erro-fundo);
    border-color: var(--cor-erro-borda);
    border-left-color: var(--cor-erro-texto);
    color: var(--cor-erro-texto);
}

/**
 * Fato consumado: o prazo acabou e não há nada a fazer. Cinza, não amarelo —
 * aviso que pede pressa depois de a coisa já ter acontecido é ruído, e ainda
 * sugere ao dono que ele chegou tarde por descuido.
 *
 * =============================================================================
 *  `.painel-status-neutro` — O MESMO CARGO COM O NOME CERTO (T-0020)
 * =============================================================================
 * A aba `Temas` precisa deste cinza para o estado "combinação própria": a festa
 * usa uma combinação que não é nenhum dos temas, NADA está errado, e o bloco
 * está lá toda vez que o dono abre a tela — até ele aplicar um tema. É o cargo
 * de `-encerrado` (*fato consumado, sem ação obrigatória*) com um nome que
 * descreve o CARGO em vez da SITUAÇÃO do primeiro consumidor.
 *
 * ⚠️ ELE ENTRA COMO SEGUNDO SELETOR DESTE GRUPO, E NÃO COMO BLOCO NOVO. Duplicar
 * as quatro declarações criaria dois nomes para a mesma cor, e "dois nomes para
 * uma cor apodrecem" é regra escrita desta casa. Seletor de grupo dá o nome de
 * cargo sem duplicar valor nenhum — e a varredura de seletor repetido já
 * classifica "segunda linha de um seletor de grupo" como NÃO defeito.
 * INVARIANTE: os dois ficam no MESMO bloco. Em blocos separados é regressão.
 * Eles colapsam em `neutro` no dia em que alguém for dono do PHP que emite a
 * string `encerrado` (hoje interpolada em `_cota.php`, `galeria.php` e
 * `admin/index.php`).
 *
 * ⚠️ CORREÇÃO DE FATO, T-0021: `views/admin/_conta.php` SAIU desta lista. O
 * cartão da conta virou `<details>` e a legenda do prazo subiu para a linha de
 * triagem, onde não há `.painel-status`: quem carrega o estado ali é a FRASE da
 * §7.6 (`.admin-conta-legenda`, em `--cor-texto`) mais a barra
 * (`.medidor-alerta`/`.medidor-encerrado`, que continuam intactas). A varredura
 * de consumidores foi refeita hoje sobre `views/`.
 *
 * ⚠️ E O ACHADO NC-02 ABAIXO PERDEU O CASO QUE O ORIGINOU. Ele foi medido
 * porque `.painel-status` tinha passado a morar dentro do cartão da conta —
 * e é exatamente esse uso que deixou de existir. **A regra FICA**, porque ela
 * protege qualquer `.painel-status` que volte a morar dentro de um cartão; o
 * que eu declaro, e é só o que eu conferi, é que **o caso do cartão da conta
 * não existe mais**. Se ela tem ou não outro consumidor dentro de `.form-secao`
 * hoje, eu não medi — e por isso não afirmo.
 *
 * ⚠️ ACHADO NC-02 — DENTRO DE UM CARTÃO, NO MODO ESCURO, ESTE BLOCO NÃO TEM
 * SUPERFÍCIE. `--cor-neutro-fundo` (#262233) e `--cor-cartao` (#282136) diferem
 * em luminância por 0,00010: razão 1,00:1. O limite de 1 px dá 1,30:1. Sobre a
 * PÁGINA, que é o uso de produção de hoje, o degrau é 1,14:1 e funciona — mas
 * ninguém tinha medido dentro de um cartão porque `.painel-status` nunca tinha
 * morado num. Logo: **a `border-left-width: 4px` herdada de `.painel-status`
 * (8,44:1 contra o cartão) é o ÚNICO separador que resta, e é requisito de
 * implementação — não pode ser removida nem "simplificada", e o bloco não pode
 * virar um `<p>` solto com a frase.**
 */
.painel-status-encerrado,
.painel-status-neutro {
    background: var(--cor-neutro-fundo);
    border-color: var(--cor-neutro-borda);
    border-left-color: var(--cor-neutro-texto);
    color: var(--cor-neutro-texto);
}

/* ----- Medidor -------------------------------------------------------------- */

/**
 * `<progress>` DE VERDADE, e não uma `div` com `role="progressbar"` pendurado:
 * o elemento nativo já leva papel, valor, mínimo e máximo para a tecnologia
 * assistiva, e continua funcionando com o CSS bloqueado. O rótulo aponta para a
 * frase da §6 (`aria-labelledby`), então nem aqui inventamos texto.
 *
 * E o valor entra por atributo, nunca por `style=` inline: a CSP desta
 * aplicação é `style-src 'self'` e derruba estilo inline em silêncio
 * (config/security.php).
 */
/**
 * ⚠️ O FIO NÃO É ENFEITE: SEM ELE O TRILHO VAZIO NÃO É UM OBJETO (P3 da revisão
 * estética da T-0021). MEDIDO na marcação servida, nas nove contas de
 * demonstração: as barras da lista do admin desenham em média 5,08px de tinta
 * num trilho de 88px (5,8 %), e DUAS desenham ZERO pixel. Isso não é artefato de
 * semeadura — é o estado de REPOUSO de conta saudável, que é o caso majoritário.
 * Sem contorno, a "coluna de barras que se lê sem ler" da UX vira, em repouso,
 * uma fileira de manchas cinza flutuando: o leitor não vê uma régua quase vazia,
 * vê um borrão. O fio devolve a RÉGUA — a caixa existe mesmo quando a tinta não.
 * Medido contra o trilho: 3,84:1 no claro e 4,28:1 no escuro (piso de objeto
 * gráfico é 3:1).
 *
 * ⚠️ `box-sizing: border-box` é global (linha 11 desta folha), então o fio come
 * de DENTRO: a barra continua medindo 88px de largura e 10px de altura na lista
 * do admin, e nenhuma coluna se move. MEDIDO depois de aplicar, não suposto.
 *
 * ⚠️ RECUSADO, E NÃO REABRIR: dar largura mínima ao preenchimento para que o
 * 0 % "apareça". Barra é régua, e régua que mente na origem não é régua — zero
 * tem de desenhar zero. O que faltava era a caixa, não a tinta.
 */
/* ⚠️ AS MARCAS DA RÉGUA (T-0031). O bloco acima argumenta que "o fio devolve a
   RÉGUA — a caixa existe mesmo quando a tinta não", e parava aí: uma caixa
   vazia é uma caixa, não uma régua. `--marca-barra` é o pigmento das marcas de
   escala, declarado nos dois modos desde a troca de paleta e sem um único
   consumidor. Com ele, um trilho a 5,8 % continua LEGÍVEL como proporção,
   porque há contra o que comparar. Uma marca a cada 10 % — a mesma escala da
   cabine —, e a marca é sub-pixel de propósito: ela é fundo de leitura, não
   informação, e quem carrega o valor continua sendo o preenchimento.
   ⚠️ MEDIDO E DECLARADO: a marca contra o trilho dá 1,43:1 no claro e 1,53:1 no
   escuro — ABAIXO dos 3:1 da WCAG 1.4.11, e de propósito. O critério vale para
   "parte de objeto gráfico NECESSÁRIA para entender o conteúdo", e esta não é:
   o valor é dito pelo preenchimento e pela legenda em número ao lado. É o mesmo
   cargo — e a mesma isenção — de `--cor-borda` como filete e do realce de linha
   da tabela, os dois já declarados isentos nesta folha. Subir a marca até 3:1 a
   faria competir com o preenchimento, que é quem tem de ser lido. O par é o
   mesmo da demo aprovada (`.barra-marcas`), byte a byte.
   ⚠️ A DECLARAÇÃO É REPETIDA EM `::-webkit-progress-bar` PORQUE PRECISA SER: no
   Blink o pseudo-elemento do trilho pinta POR CIMA do fundo do elemento, e sem
   a segunda cópia as marcas existiriam só no Firefox.
   ⚠️ E ELAS SOMEM NO INDETERMINADO: `.medidor:indeterminate` declara
   `background-image` e vence esta por ordem — as listras são o desenho daquele
   estado, e régua com listra por cima seria ruído sobre ruído. */
.medidor {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    display: block;
    width: 100%;
    height: 10px;
    border: 1px solid var(--limite);
    border-radius: var(--raio-pilula);
    background-color: var(--medidor-trilho);
    background-image: repeating-linear-gradient(90deg, var(--marca-barra) 0 1px, transparent 1px 10%);
    overflow: hidden;
}

/**
 * ⚠️ ESTA REGRA NÃO É DECORAÇÃO: `[hidden]` é uma declaração `display:none` do
 * navegador, de especificidade ZERO — qualquer seletor de classe a vence. Sem
 * ela, `.medidor { display: block }` deixaria a barra VISÍVEL com o atributo
 * `hidden` posto, e o JS acharia que a escondeu.
 */
.medidor[hidden] {
    display: none;
}

.medidor::-webkit-progress-bar {
    background-color: var(--medidor-trilho);
    background-image: repeating-linear-gradient(90deg, var(--marca-barra) 0 1px, transparent 1px 10%);
    border-radius: var(--raio-pilula);
}

.medidor::-webkit-progress-value {
    background: var(--medidor-normal);
    border-radius: var(--raio-pilula);
    transition: width 0.4s ease;
}

.medidor::-moz-progress-bar {
    background: var(--medidor-normal);
    border-radius: var(--raio-pilula);
}

.medidor-alerta::-webkit-progress-value { background: var(--medidor-aviso); }
.medidor-alerta::-moz-progress-bar { background: var(--medidor-aviso); }
.medidor-cheio::-webkit-progress-value { background: var(--medidor-critico); }
.medidor-cheio::-moz-progress-bar { background: var(--medidor-critico); }

/* ENCERRADO — a régua do prazo que já venceu (§7.6 da T-0021). Cinza, e não
   vermelho: é fato consumado, e aviso que pede pressa depois de a coisa ter
   acontecido é ruído. É o mesmo cargo — e o mesmo token — de
   `.painel-status-encerrado`, que é a moldura em que esta barra sempre mora.
   ⚠️ SEM ESTE PAR, A BARRA CHEIA DE UMA CONTA VENCIDA SAIRIA NO ROXO DE
   `--medidor-normal`, porque `.medidor-encerrado` não casaria com nada e a
   regra base venceria: texto de "venceu há 42 d" com moldura de "tudo bem",
   que a §7.6 chama, com estas palavras, de pior que não ter moldura. */
.medidor-encerrado::-webkit-progress-value { background: var(--cor-neutro-texto); }
.medidor-encerrado::-moz-progress-bar { background: var(--cor-neutro-texto); }

/**
 * INDETERMINADO — enquanto o servidor assina os endereços da parte não dá para
 * saber quanto falta, e uma barra parada em 0 % nesse momento parece travamento.
 * `<progress>` sem `value` é indeterminado por definição; as listras são o
 * desenho desse estado.
 */
/* ⚠️ AS LISTRAS GANHARAM PAR PRÓPRIO (`--listra-forte`/`--listra-fraca`), e o
   motivo é medido: com `--medidor-normal` sobre `--medidor-trilho` as duas
   listras mediam o contraste do PREENCHIMENTO contra o TRILHO, que é outra
   pergunta — o estado indeterminado não tem preenchimento, ele tem duas
   listras, e o que precisa ser visível é uma CONTRA A OUTRA. O par novo mede
   4,01:1 no claro e 4,90:1 no escuro entre as duas, acima dos 3:1 de objeto
   gráfico. E o âmbar diz "trabalhando", que é exatamente o estado. */
.medidor:indeterminate {
    background-image: repeating-linear-gradient(
        115deg,
        var(--listra-forte) 0 12px,
        var(--listra-fraca) 12px 24px
    );
    background-size: 48px 100%;
    animation: medidor-anda 1.1s linear infinite;
}

.medidor:indeterminate::-webkit-progress-bar { background: transparent; }
.medidor:indeterminate::-moz-progress-bar { background: transparent; }

@keyframes medidor-anda {
    to { background-position: 48px 0; }
}

/* ----- Download do álbum em partes ------------------------------------------ */

.album-download {
    margin-top: var(--e-5);
    padding-top: var(--e-5);
    border-top: 1px solid var(--cor-borda);
}

.album-download h3 {
    font-size: 1.02rem;
    font-weight: 800;
}

/* O tom que PASSA em AA sobre o fundo do painel — ver os tokens no topo. */
.album-download .subtitulo,
.album-resumo {
    color: var(--cor-texto-suave);
}

.album-download .subtitulo {
    margin: var(--e-1) 0 var(--e-3);
}

.album-resumo {
    font-family: var(--f-display);
    font-variant-numeric: tabular-nums;
    font-size: 0.85rem;
    font-weight: 800;
    margin-bottom: var(--e-2);
}

.album-ultimo-dia {
    margin-bottom: var(--e-3);
}

/**
 * A LISTA DE PARTES É O ELEMENTO MAIS PESADO DESTA TELA, e ela nasce em COLUNA.
 * `Parte 2 de 5 · 412 fotos · 980 MB · Baixada em 12/05` mais um botão não cabem
 * lado a lado em 360 px: numa tabela isso vira rolagem horizontal, e o dono que
 * abre o painel no celular no dia seguinte à festa é o caso comum. A partir de
 * 560 px, e só a partir daí, texto e botão dividem a linha.
 */
.album-partes {
    list-style: none;
    display: grid;
    gap: var(--e-2);
    margin: 0 0 var(--e-3);
    padding: 0;
}

/* COLUNA EM 360px, LINHA QUANDO OS DOIS CABEM — sem media query, e a troca é a
   mesma que a F6 pediu. O que muda é QUEM decide: era a largura da janela, e
   agora é a largura da caixa. A diferença é medível e não é acadêmica — a partir
   de 64rem esta lista mora na coluna larga de `.grade-painel.inverso`, e a
   pergunta "a janela tem 560?" não diz nada sobre a faixa em que a linha vive.
   15rem é o piso do texto (`Parte 2 de 5 · 412 fotos · 980 MB · Baixada em
   12/05`), 9rem é o do botão. Somados ao vão de 16px, a linha se forma a partir
   de 400px DE CAIXA — em 360px de tela a caixa tem 260 e a lista empilha,
   exatamente como o requisito manda. */
.album-parte {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-2) var(--e-4);
    padding: var(--e-3);
    background: var(--cor-cartao);
    border: 1px solid var(--cor-borda);
    border-radius: var(--raio-tecla);
}

.album-parte:hover {
    background: var(--sup-hover);
}

.album-parte-linha {
    flex: 1 1 15rem;
    /* O primeiro consumidor do degrau de tinta do meio: a linha é DADO
       (`Parte 2 de 5 · 412 fotos · 980 MB`), secundária ao botão que está ao
       lado, e forte demais para o par de apoio. 9,21:1 claro · 10,52:1 escuro. */
    color: var(--cor-texto-medio);
    font-variant-numeric: tabular-nums;
    font-size: 0.9rem;
    font-weight: 700;
    line-height: 1.4;
    min-width: 0;
    overflow-wrap: anywhere;
}

/**
 * A parte já baixada muda de fundo E de rótulo do botão — mas quem carrega a
 * informação é a própria linha, que ganha `· Baixada em {dd/mm}` do servidor
 * (RF-091). Sem o verde, a tela continua dizendo o que aconteceu.
 */
/* ⚠️ PASTILHA VIRA BLOCO, PELO MESMO MOTIVO DE `.alerta-aviso`: a parte baixada é
   uma LINHA inteira, não um selo, e o par de bloco do "já aconteceu" é
   `--fundo-recibo` — a mesma superfície do relato da carona, que é o outro
   recibo do produto. O verde continua sendo verde e continua sendo reforço:
   quem carrega a informação é o `· Baixada em {dd/mm}` que o servidor escreve
   na própria linha (RF-091). */
.album-parte.baixada {
    background: var(--fundo-recibo);
    border-color: var(--fio-2);
}

/* `flex: 1 1 9rem` e não `width: 100%`: empilhado, o botão cresce e ocupa a
   linha inteira (o alvo cheio que o celular precisa, idêntico ao que a F6
   entregou); em linha, ele parte de 9rem e divide a folga com o texto. Um só
   valor cobre os dois estados, sem `width` que precise ser desfeito depois. */
.album-baixar {
    flex: 1 1 9rem;
}

/* ⚠️ `opacity: 0.55` SAIU: rebaixar opacidade rebaixa o CONTRASTE junto, e o par
   deixa de ser mensurável — é a §14.5 desta folha, e é a mesma correção que
   `.admin-acao:disabled` recebeu. `--tecla-fantasma-off` é o tom já certo para
   o estado, com a tinta de apoio por cima, e não depende do que está atrás. */
.album-baixar:disabled {
    background: var(--tecla-fantasma-off);
    color: var(--cor-texto-suave);
    box-shadow: none;
    transform: none;
    cursor: default;
}

/* A §6 chama a segunda ação de LINK: mesmo alvo de toque, peso visual menor. */
.album-baixar-de-novo {
    background: transparent;
    color: var(--cor-acento);
    text-decoration: underline;
}

.album-baixar-de-novo:hover {
    background: var(--cor-roxo-claro);
}

.album-status {
    min-height: 1.3em;
    margin-bottom: var(--e-2);
    font-size: 0.88rem;
    font-weight: 700;
}

.album-progresso {
    margin-bottom: var(--e-2);
}

/* A media query de 560px que virava `.album-parte` em linha SAIU: o `flex-wrap`
   da própria regra faz a virada, e faz contra a caixa real. */

/* -----------------------------------------------------------------------------
   O MOTIVO DA RECUSA, NA TELA DO CONVIDADO (CA-103 / RF-061)
   -----------------------------------------------------------------------------
   `galeria.js` já escrevia o motivo em `.gfoto-motivo` — mas o elemento não
   tinha estilo nenhum e vivia dentro de uma célula quadrada de 84 px com
   `overflow: hidden`: o texto existia no HTML e não aparecia em lugar nenhum.
   Sobrava o `title`, que não existe em toque. "O resultado de cada uma aparece
   na tela" ficava cumprido no papel e não na tela.

   A célula que falhou passa a ocupar a LINHA INTEIRA da grade, com a miniatura
   pequena ao lado do texto. É a única forma de uma frase de cem caracteres ser
   legível ali — e ela precisa ser legível, porque é o único canal que o convidado
   tem no meio da festa (§11 item 6).
   -------------------------------------------------------------------------- */

.gfoto-motivo {
    display: none;
}

.gfoto.erro {
    grid-column: 1 / -1;
    aspect-ratio: auto;
    display: flex;
    align-items: center;
    gap: var(--e-3);
    padding: var(--e-2) var(--e-3);
    background: var(--cor-erro-fundo);
    border: 1px solid var(--cor-erro-borda);
}

.gfoto.erro img {
    width: 44px;
    height: 44px;
    flex: 0 0 auto;
    border-radius: var(--raio-md);
    opacity: 1;
}

.gfoto.erro .gfoto-marca {
    position: static;
    flex: 0 0 auto;
}

.gfoto.erro .gfoto-motivo {
    display: block;
    flex: 1;
    min-width: 0;
    font-size: 0.82rem;
    font-weight: 700;
    line-height: 1.35;
    color: var(--cor-erro-texto);
}

/* =============================================================================
   MOVIMENTO REDUZIDO — o que some e, principalmente, o que NÃO some
   =============================================================================
   NÃO existe aqui a regra global de `*{animation-duration:0.01ms}`, e a ausência
   é a decisão: ela apagaria o preenchimento do medidor e o pulso do estado
   justamente para quem pediu menos movimento — o feedback sumiria antes de
   existir. O que sai é movimento DECORATIVO e PERPÉTUO; o que fica é todo estado.

   Fica de propósito, e cada um por um motivo:
     · o preenchimento do medidor CHEGA no valor certo, só não desliza até ele;
     · as listras do indeterminado param, mas continuam visíveis — elas são a
       única prova de que o pedido está em andamento;
     · o flash da câmera embutida continua: ele não é enfeite, é a confirmação
       de que a foto foi tirada, e é a única que existe naquela tela.
   ========================================================================== */

@media (prefers-reduced-motion: reduce){
    .medidor::-webkit-progress-value { transition: none; }
    .medidor:indeterminate { animation: none; }
    .barra span { transition: none; }
    /* ⚠️ A RÉGUA DO CONSOLE (`.cabine-barra .cabine-barra-fill`) NÃO FREIA AQUI,
       e o motivo foi MEDIDO na T-0031 4a: ela ganhou especificidade própria
       (0,2,0) e deixou de herdar este `.barra span`; uma linha (0,2,0) neste
       bloco PERDE POR ORDEM para a regra dela, que vem ~3.000 linhas depois —
       a engine devolveu `width 0.24s` sob `reduce` com a linha aqui. O freio
       dela mora no bloco 11 da cabine, no fim da folha, depois da régua. */

    /* AS DUAS SETAS DA SEÇÃO USUÁRIOS (T-0021). Elas nasceram copiando
       `.inicio-duvida summary::after` — mesma transição de `transform` —, mas a
       cópia parou antes do freio: o precedente ESTAVA coberto (saiu com a
       página inicial antiga na T-0017; a seta da vitrine tem o freio dela) e estas
       duas ficaram fora dos cinco blocos, com `transition: transform 0.16s` vivo
       no valor computado. Duas peças idênticas com tratamentos opostos na mesma
       folha.
       ⚠️ O FATO SOBREVIVE AO CORTE, e é por isso que basta tirar a transição: a
       seta girada vem da regra `[open]`, não do fim da animação. Quem pediu menos
       movimento continua vendo QUAL conta está aberta — só não vê o giro. */
    .admin-conta-linha::after,
    .admin-perigo-linha::after { transition: none; }

    .manutencao-art .cursor,
    .manutencao-art .maos,
    .manutencao-art .eng1,
    .manutencao-art .eng2,
    .reticencias span { animation: none; }

    .btn:hover,
    .btn:active { transform: none; }}

/* =============================================================================
   TERMOS, ACEITE E CIÊNCIA DO CONVIDADO — F7/3 (RF-006, RF-082, RF-086)
   =============================================================================
   ⚠️ TUDO AQUI É CLASSE, NUNCA `style=""` NA MARCAÇÃO. A CSP do app é `self` e
   bloqueia TANTO `on*=""` QUANTO `style=""` inline — não só `<style>` e
   `<script>`. Um `onchange` inline foi a causa raiz do modo manutenção que "não
   ativava" (lição paga com bug, ver context.json).

   ⚠️ E NENHUMA REGRA AQUI PODE DEPENDER DE QUEM ESTÁ OLHANDO. RN-075: a caixa
   do convidado aparece igual — presença, texto, destaque, COR e estado inicial —
   para qualquer visitante. Uma classe `.campo-aceite--ja-aceitou` com outra cor
   entregaria a mesma informação que um texto diferente, e transformaria o
   convite num verificador da lista de convidados (RN-037/TD-011).
   ============================================================================= */

.campo-aceite {
    margin-top: 18px;
}

.campo-aceite label {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    font-weight: 600;
    cursor: pointer;
}

/* Toque mínimo de 44px é regra do projeto (mobile-first): a caixa é o alvo mais
   difícil de acertar num formulário, e errá-la na porta da festa custa uma
   confirmação de presença. */
/* ⚠️ T-0031 4a (BUG-TD-136): a caixa lia a MARCA; passa ao acento. Ela é
   emitida em QUATRO telas de duas famílias — cadastro e termos (painel: 6,51:1
   claro, 7,18:1 escuro contra o cartão) e convite e galeria do convidado.
   ⚠️ NO CONVITE O ACENTO AINDA É O DO PAINEL: `.visual-classico` e
   `.visual-jardim` não declaram `--acento`, então a caixa da festa segue
   #5c31f6 (antes seguia #7c3aed — mesma classe de vazamento, e a primária
   NUNCA poderia ser redeclarada por um visual, porque é marca). Com o token
   certo lido aqui, basta o visual declarar o seu `--acento` para a caixa
   acompanhar a festa. Consulta aberta ao especialista-ui na T-0031 4a. */
.campo-aceite input[type="checkbox"] {
    width: 22px;
    height: 22px;
    min-width: 22px;
    margin: 11px 0;
    accent-color: var(--cor-acento);
}

.campo-aceite small {
    display: block;
    margin-top: 6px;
    margin-left: 32px;
}

/* O RESUMO (RF-086). Ele é o texto que a pessoa lê antes de concordar: legível
   antes de bonito. Sem tamanho reduzido — texto de consentimento em corpo 12
   é consentimento que ninguém leu. */
.aceite-resumo {
    margin: 0 0 10px;
    line-height: 1.55;
}

.rodape-termos {
    margin: 6px 0;
}

/* =============================================================================
   A PÁGINA DE TERMOS — texto longo, lido no celular
   =============================================================================
   ELA MUDOU DE FAMÍLIA NA T-0015 (etapa 6d): saiu de `tema-convite` +
   `visual-classico` e passou a ser página do PRODUTO (`Tema::Painel`). O
   argumento é o mesmo da página inicial e está em `identidade-visual.md` §13 —
   uma página institucional vestida de papel-e-ouro se oferece à prateleira do
   "convite digital", que é justamente a que o posicionamento recusa. Termos é o
   produto falando de si; não é festa de ninguém.

   Quase nada precisou mudar AQUI, e é o resultado esperado: estas regras nunca
   foram de pele — são ritmo de texto longo. Quem vestia a página era o `<body>`.

   ⚠️ A LARGURA NÃO MUDOU, E É DECISÃO MEDIDA (não é omissão).
   `painel-e-desktop.md` §A.3 fecha `--medida: 38rem` (608px) como TETO de
   parágrafo — 45 a 75 caracteres. Régua do próprio documento (608px = ~67
   caracteres a 18px de Nunito → 8,06px/caractere a 16px, que é o corpo daqui);
   caixa de desktop (`.container` −32, `.card` −2 de limite e −56 de recuo a
   partir de 48rem):

     · antes, coluna do convite (32rem):    422px =  52,4 caracteres
     · agora, coluna do painel (35rem):     470px =  58,3 caracteres
     · com `painel-largo` e sem coluna:    1070px = 132,8 caracteres
     · com `painel-largo` + `--medida`:     550px =  68,2 caracteres

   A troca de família já melhorou a medida sozinha, e 470px estão 138px ABAIXO
   do teto: NÃO HÁ defeito de leitura a corrigir. Ligar `painel-largo` aqui é o
   "erro clássico de alargar o contêiner e chamar de desktop", com esse nome, na
   §A.3 — e a quarta linha passa na faixa mas põe um cartão de 608px boiando em
   1128px, com 520px de vão e nada para pôr neles. Documento jurídico de texto
   corrido não tem composição para ocupar 1160px.
   Em 375px as quatro hipóteses rendem a MESMA linha: a tela recorta antes de
   qualquer `max-width`. A escolha é de tablet e desktop.
   ============================================================================= */
.termos h2,
.termos h3,
.termos h4 {
    margin-top: 22px;
    margin-bottom: 8px;
}

.termos p,
.termos li {
    line-height: 1.65;
}

.termos ul {
    margin: 8px 0 8px 20px;
}

/* O filete era `rgba(0, 0, 0, .12)` — preto puro diluído, que é o que o design
   system proíbe para superfície e elevação ("preto sobre papel tingido suja para
   cinza"). Sobre o cartão branco ele resolvia em #e0e0e0, um cinza neutro num
   produto cujas fronteiras são tingidas de roxo. Vira token: MUDA PIXEL de
   propósito, e é item declarado da etapa.
   Vale para as DUAS telas que exibem o documento (a pública e a de novo aceite),
   e isso é a intenção: é o mesmo documento. */
.termos hr {
    border: 0;
    border-top: 1px solid var(--cor-borda);
    margin: 26px 0;
}

/* `opacity: .85` sobre TEXTO saiu, e o motivo é de método antes de ser de cor:
   opacidade torna o contraste dependente do que está atrás, e o par deixa de ser
   mensurável no dia em que o fundo não for branco puro — foi exatamente esse o
   limite que impediu de medir o campo e o alerta do tema antigo sobre a
   fotografia (design-system.md §6). O papel de "texto secundário" tem token.
   Medido: #2a2438 a 85% sobre #fff resolvia em #4a4556 = 9,22:1;
   `--cor-texto-suave` #6f6785 sobre #fff = 5,31:1. Os dois passam AA em 0,9rem
   (14,4px, critério 4,5:1) — a troca perde folga e ganha auditabilidade, que é o
   que se quer numa linha que existe para ser discreta. */
.termos-versao {
    margin-top: 26px;
    font-size: .9rem;
    color: var(--cor-texto-suave);
}

/* A tela de NOVO aceite mostra o documento inteiro dentro de uma caixa rolável:
   ele precisa estar ali (mandar ler noutra aba é como se produz aceite que
   ninguém leu), mas o botão tem de continuar alcançável sem uma rolagem de
   página inteira.

   ⚠️ O `rgba(0, 0, 0, .12)` DA BORDA FICOU DE PROPÓSITO, e não é descuido de
   quem tokenizou o `<hr>` logo acima. Esta borda é a única fronteira de uma
   REGIÃO ROLÁVEL — quem não a enxerga não sabe que há texto embaixo —, então ela
   cai no critério de limite de componente (1.4.11, 3:1) e o token dela seria
   `--limite`, não `--cor-borda`. `--cor-borda` #ece7f7 sobre o interior branco
   mede 1,21:1, que é a não conformidade N7 do design system.
   Não é mudança desta etapa: os limites de componente saíram numa lista branca
   FECHADA (Emenda 1, §7.5 — sete seletores nomeados), e `.termos-rolagem` não
   está nela. Ampliar lista branca depois do fato é o que o protocolo proíbe.
   Fica REGISTRADO aqui como pendência endereçada ao `especialista-ui`. */
.termos-rolagem {
    max-height: 46vh;
    overflow-y: auto;
    padding: 14px 16px;
    /* Era `rgba(0,0,0,.12)`: preto sobre preto no modo escuro, ou seja, a caixa
       de rolagem dos termos perderia a unica fronteira que ela tem. */
    border: 1px solid var(--cor-borda);
    border-radius: 14px;
    margin-bottom: 8px;
}

/* =============================================================================
   AS PELES DO CONVITE — `.visual-classico` e `.visual-jardim`
   =============================================================================
   REGRA VERIFICÁVEL POR grep, e ela é o que impede um quarto vocabulário de
   token nascer neste arquivo (TD-045 item 1):

     UM BLOCO `.visual-*` CONTÉM EXCLUSIVAMENTE LINHAS `--token: valor`.
     Zero `color:`, zero `background:`, zero `padding:`.

   Se um visual precisar mudar a FORMA de alguma coisa, ele não é um visual — é
   componente novo, e passa pelo designer (distinguir-se na miniatura de 96px) e
   pelo `especialista-ui`. É isso que faz a galeria escalar sem virar manutenção
   infinita: o custo de um visual é um bloco de declarações, não um dialeto.

   A classe entra no `<body>` ao lado de `tema-convite`, e as duas saem de UM
   valor (`App\Apresentacao\VisualDoConvite`), junto com a cor da barra do
   navegador — que é a trava do BUG-TD-009 descida um andar.
   ============================================================================= */

.visual-classico {
    /* Camada 2, grupo A — os mesmos nomes do `:root`, outros valores */
    --cor-fundo: #e9e0cd;
    --cor-superficie: #f7f2e8;
    --cor-cartao: var(--branco);
    --cor-texto: #232838;
    --cor-texto-suave: #4d5670;
    --cor-borda: #ddd2ba;
    --limite: #8d8069;
    --foco: #232838;
    --sombra-tinta: 35 40 56;
    --grad: linear-gradient(120deg, #2f4471, #1e2c4f);

    /* Camada 2, grupo B — só o convite tem */
    --envelope: #1e2c4f;
    --envelope-claro: #2f4471;
    --ouro: #b8893f;
    --ouro-claro: #eed6a8;
    --ouro-fundo: #f2e9d6;
    --ouro-texto: #7a5c26;
    --guirlanda: url(../img/guirlanda-classico.svg);
}

.visual-jardim {
    --cor-fundo: #dfe6d2;
    --cor-superficie: #eef2e6;
    --cor-cartao: var(--branco);
    --cor-texto: #1f3a28;
    --cor-texto-suave: #4a6350;
    --cor-borda: #cfd8c2;
    --limite: #7a8b61;
    --foco: #1f3a28;
    --sombra-tinta: 31 58 40;
    --grad: linear-gradient(120deg, #3c7a57, #20543c 60%, #163b29);

    --envelope: #6b7c53;
    --envelope-claro: #7a8b61;
    --ouro: #b8893f;
    --ouro-claro: #eed6a8;
    --ouro-fundo: #f2e9d6;
    --ouro-texto: #7a5c26;
    --guirlanda: url(../img/guirlanda-jardim.svg);
}


/* =============================================================================
   `.tema-convite` — A ESTRUTURA DA FAMÍLIA PÚBLICA
   =============================================================================
   O outro lado da separação: aqui mora a FORMA (coluna, cabeçalho mínimo,
   rodapé, anatomia da capa e do papel) e NENHUM hexadecimal de paleta. Toda cor
   sai da camada 2, e é por isso que trocar de pele é trocar um bloco de tokens.

   ⚠️ PROIBIÇÕES PAGAS COM BUG. ELAS NUNCA VALERAM SÓ "DAQUI PARA BAIXO", mas o
   teste que as guardava varria só regras com `.tema-convite` — e por isso a
   folha conviveu com duas violações vivas na família do PAINEL (`.topo` e
   `.btn-galeria`), justamente onde a marca mora. Desde a T-0015 a varredura é da
   FOLHA INTEIRA e ANCORADA em início de declaração, e é por isso que este
   parágrafo pode continuar citando os nomes: prosa não é uso.
   Sem `backdrop-filter: blur()` e sem `background-attachment: fixed` (os dois
   geram uma caixa branca fantasma no Chromium do usuário); sem `style=""` e sem
   `on*=""` na marcação, porque a CSP é `self` e bloqueia os DOIS, não só os
   blocos.
   ============================================================================= */

.tema-convite {
    background: var(--cor-fundo);
    color: var(--cor-texto);

    /* RELEVO DE TINTA — para texto claro assentado sobre superfície de cor (o
       nome da capa). NÃO é elevação: elevação faz um objeto flutuar sobre a
       página; isto dá ESPESSURA à tinta sobre o material. As duas camadas de
       baixo são a geometria que a casa já fala (a segunda de `--elev-1` e a de
       `--elev-3`); a de cima, `0 1px 0`, é a aresta de contato — sem desfoque,
       porque é ela que segura o fio de um script caligráfico, e desfoque ali
       vira borrão.

       Os alfas são MAIS PESADOS que os de `--sombra-a1..3` de propósito: aquela
       escala foi calibrada para sombra sobre superfície BRANCA; aqui o campo é
       escuro e médio, e 0,06/0,10/0,16 desapareceriam.

       ⚠️ ELE MORA AQUI, E NÃO EM `:root`, E A RAZÃO FOI MEDIDA NO NAVEGADOR.
       Propriedade personalizada que contém `var()` é substituída no elemento
       ONDE ELA É DECLARADA, não onde é usada — e o valor já substituído é que
       desce por herança. Declarado em `:root`, este token resolvia com a tinta
       da RAIZ (42 36 56) e a tinta da pele nunca chegava: medido na página viva
       em 2026-08-26, com `--sombra-tinta` valendo `31 58 40` no próprio
       `.capa-nome` enquanto a sombra saía roxa.
       `.tema-convite` está no MESMO elemento que `.visual-jardim` e
       `.visual-classico` (o `<body>` carrega as duas classes), então aqui a
       substituição enxerga a tinta da pele.

       ⚠️ `--elev-1`, `--elev-2` e `--elev-3` TÊM O MESMO DEFEITO e continuam em
       `:root`: medido na mesma página, cabeçalho, cards, botões e palco saem
       todos com a tinta da raiz sob a pele oliva. NÃO foi consertado junto —
       mexer na elevação de todo o produto não cabe nesta entrega. Está aberto
       como defeito próprio. */
    --relevo-tinta:
        0 1px 0    rgb(var(--sombra-tinta) / 0.55),
        0 2px 6px  rgb(var(--sombra-tinta) / 0.45),
        0 10px 30px rgb(var(--sombra-tinta) / 0.35);
}

/* A coluna do convite vale para as três telas públicas (convite, sugestões e
   galeria): elas são a mesma família de página. 32rem substitui os 462px que
   vinham copiados de um tema aposentado. */
.tema-convite main.container {
    max-width: var(--coluna-convite);
    position: relative;
    z-index: var(--z-conteudo);
}

/* Cabeçalho mínimo: a logo sobre o papel, e não sobre o cartão do painel.
   O par `backdrop-filter: none` que morava aqui FOI REMOVIDO, e a remoção é a
   decisão: ele desligava uma declaração que a regra base não faz mais. Desligar
   o que ninguém liga é peso morto — e pior, ensina a quem lê que a folha ainda
   usa vidro. Mesma régua do parágrafo do `.logo-img` logo abaixo. O `box-shadow`
   saiu pelo mesmo motivo: a base já dá `--elev-1`, e `--sombra-tinta` resolve no
   uso, então cada pele continua com a sombra da própria tinta. */
.tema-convite .topo {
    background: var(--cor-superficie);
    border-bottom: 1px solid var(--cor-borda);
    z-index: var(--z-cabecalho);
}

/* A REGRA `.tema-convite .logo-img { height: 34px }` FOI REMOVIDA na T-0016, e a
   remoção é a decisão: a mesma marca vinha em 34 px aqui e 32 px no painel, dois
   números sem derivação nenhuma. O piso medido é 36 px (docs/marca.md §5.1) e
   agora vale para as duas famílias, na regra base. Sobreposição que devolve o
   mesmo valor da base é peso morto: some. A família pública NÃO tem tamanho
   próprio de marca — se um dia tiver, ele volta aqui, com a derivação junto. */

.tema-convite .rodape {
    border-top: 1px solid var(--cor-borda);
    color: var(--cor-texto-suave);
}

.tema-convite .rodape a {
    color: var(--cor-texto);
}

/* UM anel de foco para o produto inteiro, e ele NUNCA é ouro: sobre o envelope
   o ouro mede 1,44:1 (achado A4 do designer). Ouro é ornamento; foco é
   significado, e um canal visual se gasta uma vez, com um sentido só.

   ⚠️ O `border-radius: 2px` SAIU DAQUI TAMBÉM, E É A MESMA CORREÇÃO (R2, §13.6).
   O defeito estava DUPLICADO: a linha existia nesta regra e na `.inicio`, e
   corrigir só uma teria deixado o convite — que tem botão-pílula, selo redondo e
   cartão de `--raio-lg` — com a mesma esquadria no foco de teclado. Aqui o custo
   era ainda maior: `.tema-convite :focus-visible` (0,2,0) alcança a capa, o selo
   e os cartões do convite inteiro.
   REGRA DA CASA: a regra de foco declara `outline` e `outline-offset`, e NADA
   MAIS. A forma é do componente. */
.tema-convite :focus-visible {
    outline: var(--foco-largura) solid var(--foco);
    outline-offset: var(--foco-desvio);
}

/* -----------------------------------------------------------------------------
   A CAPA — o envelope lacrado
   -----------------------------------------------------------------------------
   `position: fixed` é decisão de ESTRUTURA e não de estilo: com as duas cenas
   irmãs no fluxo, `visibility:hidden` continuava reservando altura — era isso
   que deixava uma tela vazia embaixo antes de abrir. Não regredir.

   E é a ÚNICA coisa `position: fixed` dentro do `<main>` que pode ter z-index
   POSITIVO neste projeto, porque ela não é decorativa: é a cena que tem de
   cobrir o papel até alguém tocar. Ornamento fixo continua obrigado a
   `--z-ornamento`, que é negativo.
   -------------------------------------------------------------------------- */
.tema-convite .capa {
    position: fixed;
    inset: 0;
    z-index: var(--z-capa);
    width: min(var(--coluna-convite), 100%);
    margin-inline: auto;
    background: var(--envelope);
    /* ⚠️ ERA `overflow: hidden` NOS DOIS EIXOS, e o eixo vertical estava
       CORTANDO O ÚNICO BOTÃO DA TELA. Medido: a cena tem um piso de altura de
       ~448px (topo 242 + ação 206, com `.capa-meio` já encolhido a zero pelo
       `min-height: 0`). Num celular deitado — 640×360, que é o mesmo aparelho
       de 375px virado — a caixa tem 360px de altura e `hidden` come os últimos
       ~88: o selo `TOQUE PARA ABRIR` fica fora da tela, sem barra de rolagem,
       sem nada. O convidado não consegue abrir o convite, e a única pista é que
       não há pista. O mesmo acontece em pé com a fonte do sistema aumentada,
       porque a cena inteira é dimensionada em `rem`.
       `overflow-x: hidden` guarda o recorte horizontal da guirlanda, que é o
       que o `hidden` existia para fazer; `overflow-y: auto` devolve o alcance.
       Quando a cena cabe — que é o caso normal, em pé — não aparece barra
       nenhuma e nada muda.
       ⚠️ O QUE ISTO NÃO CONSERTA, e fica escrito para não passar por pronto: no
       mesmo aperto, `.capa-meio` encolhe a zero (é o que o `min-height: 0` dela
       autoriza, de propósito) e o cartucho de data passa a pintar por cima da
       ação. O botão fica alcançável, que era o bloqueio; a sobreposição é
       cosmética e mora na regra elástica, que é do `designer-visual`. Não mexi
       no `min-height: 0` porque ele também governa como a figura de encaixe é
       espremida em tela baixa, e isso eu não tenho como medir aqui. */
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0 var(--e-5) env(safe-area-inset-bottom, var(--e-4));
    transition: opacity var(--mov-cena) var(--curva-saida), visibility var(--mov-cena);
}

/* DUAS PORTAS PARA A MESMA CENA, e as duas precisam existir:
   `:target` abre o convite SEM JAVASCRIPT (o botão é um link para a própria
   capa); `[data-aberto]` é o caminho do `app.js`, que intercepta o clique, não
   suja o endereço e ainda leva o foco para o nome. Sem a primeira, quem estiver
   com o JS desligado fica preso atrás de uma capa que cobre a tela inteira. */
.tema-convite .capa:target,
.tema-convite .capa[data-aberto="sim"] {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

/* AS FLORES DOS CANTOS — a moldura em aquarela do visual Jardim.

   ELAS SAÍRAM EM 2026-08-19 E VOLTARAM EM 2026-08-27, as duas vezes por
   decisão do usuário (TD-044 item 6 registrou a saída). A GUIRLANDA FICA:
   ela pende do topo, elas emolduram os cantos, e as duas convivem.

   ⚠️ O LUGAR FOI CORRIGIDO OLHANDO A TELA. Na primeira tentativa foram
   `position: fixed` com `--z-ornamento`, copiando o arranjo anterior a
   T-0015 — e ficaram ATRÁS da capa, que é opaca, ou seja invisíveis na
   única tela em que o usuário as queria. Ele apontou os dois cantos com
   setas. Agora são ABSOLUTAS DENTRO da capa, no arranjo da demo aprovada.

   OS DESLOCAMENTOS SÃO NEGATIVOS de propósito: a arte TRANSBORDA a borda e
   o `overflow` da capa a corta, que é o que faz ela parecer pendurada na
   quina em vez de colada dentro. É o mesmo recorte que a guirlanda usa.

   AS DUAS SÃO DIFERENTES ENTRE SI — largura e opacidade — e isso vem da
   demo e de TD-042: pontas iguais reproduzem a costura simétrica que
   aquele ADR rejeitou. A de baixo é menor e mais apagada porque divide o
   canto com o botão de abrir, e competir com ele seria roubar o toque.

   ⚠️ NÃO existe regra para o `Clássico`, e a ausência é a decisão: quem não
   desenha as imagens é a VIEW, porque `floraisDeCanto()` devolve lista
   vazia para aquela pele. Esconder por CSS faria o convidado do Clássico
   baixar 84 KB de arte que nunca apareceria. */
/* A CAIXA QUE RECORTA A MOLDURA, e ela existe por um defeito medido.

   As duas artes TRANSBORDAM a borda de propósito (é o que as faz parecer
   penduradas na quina, e é o arranjo da demo aprovada). Só que `.capa` é
   `overflow: hidden auto`: o transbordo lateral é recortado pelo `hidden`
   do eixo X, mas o transbordo PARA BAIXO vira área rolável — e o `auto` do
   eixo Y desenhava uma barra de rolagem em pé dentro do convite. O dono do
   produto viu antes de mim, porque eu conferi só a rolagem horizontal.

   Esta caixa tem o tamanho exato da capa e recorta o que sobra: o
   transbordo continua existindo, a área rolável não. Tirá-la traz a barra
   de volta — não é embrulho decorativo. */
.visual-jardim .capa-moldura {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
}

.visual-jardim .capa-moldura .floral-canto {
    position: absolute;
    height: auto;
    pointer-events: none;
}

.visual-jardim .capa-moldura .floral-sup-dir {
    top: -1.5rem;
    right: -8%;
    width: 48%;
    opacity: 0.85;
}

.visual-jardim .capa-moldura .floral-inf-esq {
    bottom: -1.5rem;
    left: -10%;
    width: 44%;
    opacity: 0.6;
}

/* A GUIRLANDA pende da borda de cima. A ALTURA é que manda (não a largura):
   72→96px mantêm presença física quase constante de 375px a telas grandes, sem
   breakpoint e sem salto. Nas telas estreitas o recorte come ~18px de cada
   ponta — a zona sacrificial de 4% da peça, que não contém nada essencial. */
.tema-convite .capa::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: clamp(72px, 17vw, 96px);
    background-image: var(--guirlanda);
    background-repeat: no-repeat;
    background-position: center top;
    background-size: auto 100%;
    pointer-events: none;
}

.tema-convite .capa-topo {
    position: relative;
    z-index: var(--z-conteudo);
    flex: 0 0 auto;
    text-align: center;
    /* Ornamento não encosta em texto: a primeira linha começa abaixo da tinta
       mais baixa da guirlanda (≈84% da altura da peça) com 8px de respiro. */
    padding-top: calc(clamp(72px, 17vw, 96px) * 0.84 + 8px);
}

/* -----------------------------------------------------------------------------
   ⚠️ DÍVIDA DECLARADA (T-0024): AS TRÊS REGRAS ABAIXO SÃO CSS MORTO
   -----------------------------------------------------------------------------
   `.capa-monograma`, `.capa-coracao` e `.capa-idade` deixaram de ser emitidas
   por `views/convite/mostrar.php` em 2026-08-26: o monograma saiu da capa por
   decisão do usuário olhando a tela pronta. Nenhuma marcação do sistema carrega
   essas três classes hoje — conferido por varredura em `views/`.

   ELAS FICAM DE PROPÓSITO, e a decisão é do `designer-visual`: `.capa-idade`
   pode ganhar consumidor de novo, e removê-las agora seria decidir por
   antecipação uma coisa que não é de quem tocou este arquivo. GATILHO DE
   REMOÇÃO: a mesma tarefa que voltar a resolver onde a idade aparece.

   ⚠️ ENQUANTO ISSO, ELAS NÃO SÃO REFERÊNCIA DE NADA. Quem for medir contraste,
   escala ou uso de `--ouro-claro` nesta folha não pode contar estas três: elas
   descrevem uma peça que não está na tela.
   -------------------------------------------------------------------------- */

/* MONOGRAMA — display em ouro claro. Acima de 24px o limiar é 3:1, e
   `#eed6a8` mede 3,20:1 sobre o oliva e 9,70:1 sobre o marinho. Era o único
   lugar da capa em que o ouro era cor de sinal, e era por ser GRANDE. */
.tema-convite .capa-monograma {
    margin: 0;
    font-family: 'Poiret One', Georgia, serif;
    font-size: clamp(2.8rem, 13vw, 4.2rem);
    line-height: 1;
    color: var(--ouro-claro);
    letter-spacing: 0.05em;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.28em;
}

.tema-convite .capa-coracao {
    font-size: 0.2em;
    color: var(--tinta-texto);
    transform: translateY(-0.8em);
}

.tema-convite .capa-idade {
    font-size: 0.66em;
}

/* O GESTO DE CHEGADA — nasceu na miniatura do painel da página inicial da
   T-0015 e ficou quando a T-0017 trocou a página: a capa do convite o REUSA
   (nome e linha, logo abaixo), e um segundo keyframe para o mesmo gesto é a
   inconsistência que a arbitragem T-0016 recusou. O nome ficou o de origem
   para não mexer nas duas regras do convite. Sem bloco `to`: o estado base É o
   estado final, e sob movimento reduzido o elemento simplesmente está lá. */
@keyframes inicio-peca-chega {
    from {
        opacity: 0;
        transform: translateY(14px);
    }
}

/* O NOME É O TOPO INTEIRO. Com o monograma fora, ele herda a escala que a
   inicial dourada tinha (13vw é o declive DELA, não um terceiro declive) e a
   posição que o `padding-top` de `.capa-topo` já reserva sob a guirlanda — daí
   `margin: 0`: os 0,35rem existiam para afastá-lo do monograma, e o monograma
   não existe mais. Afastar de nada é empurrar por engano.

   `line-height: 1.15` porque a letra é script de swash alto: em 1 os glifos
   transbordam a caixa nos dois sentidos e, num nome que quebre em duas linhas,
   os descendentes batem nos ascendentes de baixo. A meia-entrelinha do topo
   ainda protege o respiro de 8px contra a guirlanda.

   A LETRA É A IMPERIAL SCRIPT DESDE A T-0035 (escolha do usuário; antes, Great
   Vibes), e o `* 1.12` sobre o clamp de antes é o da demo aprovada. A régua
   que reproduz esse número é a LARGURA, medida no Edge por canvas: em "XV da
   Carol" a Great Vibes tem 1,13 vez a largura de tinta da Imperial no mesmo
   corpo (pela altura seriam 1,38, e o nome estouraria a capa). A razão muda
   com as letras ("Alice" sai 0,87, mais LARGA na Imperial), então 1.12 é o
   fator aprovado olhando a festa da Carol, e não uma constante das duas
   letras. A mesma régua dá o fator de `.sug-titulo b`, mais abaixo.

   NUNCA acrescentar `letter-spacing` aqui: o script é LIGADO e espacejar quebra
   as ligaduras entre as letras.

   `text-shadow` é a ESPESSURA DA TINTA, e é também a correção de contraste: o
   Understanding da SC 1.4.3 avisa que fonte de fio é renderizada mais fraca que
   a cor declarada, e escurecer o campo colado ao traço devolve isso. Piso
   medido = o número de hoje (4,53:1 no Jardim, 13,74:1 no Clássico), porque
   toda camada é mais ESCURA que o envelope; na borda do traço sobe a 5,4–6,4:1
   no Jardim. Nenhum par pode descer. */
.tema-convite .capa-nome {
    margin: 0;
    font-family: 'Imperial Script', cursive;
    font-size: calc(clamp(2.6rem, 13vw, 3.9rem) * 1.12);
    line-height: 1.15;
    color: var(--tinta-texto);
    text-wrap: balance;
    text-shadow: var(--relevo-tinta);
    /* O gesto de chegada do produto, REUSADO — e não um keyframe novo: dois
       nomes para o mesmo gesto é a inconsistência que a arbitragem T-0016 já
       recusou. O keyframe não tem bloco `to`, então o estado base É o estado
       final: sob movimento reduzido o nome fica simplesmente lá. */
    animation: inicio-peca-chega var(--mov-medio) var(--curva-entrada) both;
}

/* A LINHA EM VERSALETE É BRANCA, e isso é a proposta P1 aprovada pelo usuário:
   em `--ouro-claro` ela media 3,20:1 e REPROVAVA (texto pequeno, limiar 4,5:1);
   em branco puro mede 4,53:1 sobre o oliva e 13,74:1 sobre o marinho. A caixa
   alta é do `text-transform` — no documento a frase é como o tema a escreve. */
.tema-convite .capa-linha {
    margin: 0.5rem 0 0;
    font-size: var(--fs-1);
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--tinta-texto);
    font-weight: 700;
    /* UM degrau de escada, com o literal de 120ms que a miniatura da página
       inicial da T-0015 usava.
       A ordem carrega sentido: de quem é a festa, depois que festa é. */
    animation: inicio-peca-chega var(--mov-medio) var(--curva-entrada) 120ms both;
}

/* O ESPAÇO ELÁSTICO: figura de encaixe OU cartucho de data. Nunca os dois. */
.tema-convite .capa-meio {
    position: relative;
    z-index: 1;
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
    display: flex;
    align-items: flex-end;
    justify-content: center;
}

.tema-convite .capa-figura {
    max-height: 100%;
    width: auto;
    max-width: 96%;
    object-fit: contain;
}

/* O cartucho: filete de ouro, a data em display tabular, filete de ouro. */
.tema-convite .capa-cartucho {
    display: flex;
    align-items: center;
    gap: var(--e-4);
    align-self: center;
    width: 100%;
    max-width: 22rem;
    margin: 0 0 var(--e-6);
    color: var(--tinta-texto);
    font-family: 'Poiret One', Georgia, serif;
    font-size: var(--fs-4);
    letter-spacing: 0.08em;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.tema-convite .capa-cartucho::before,
.tema-convite .capa-cartucho::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: var(--ouro);
}

.tema-convite .capa-acao {
    position: relative;
    z-index: var(--z-conteudo);
    flex: 0 0 auto;
    padding-bottom: var(--e-5);
}

/* O SELO É O BOTÃO — variação de botão, não componente novo. Herda a máquina de
   estados; o que muda é a anatomia: 9rem, redondo, o rótulo abaixo. O rótulo
   mora DENTRO do link porque é o nome acessível do único elemento interativo da
   tela — e porque alvo grande é o que a pessoa acerta de primeira. */
.tema-convite .capa-abrir {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--e-2);
    text-decoration: none;
    padding: var(--e-2);
    border-radius: var(--raio-xl);
}

.tema-convite .capa-selo {
    position: relative;
    display: grid;
    place-items: center;
    width: 9rem;
    height: 9rem;
}

/* A FOLHA E O SAPO OCUPAM A MESMA CÉLULA.

   `.capa-selo` é grade de uma célula só, e sem esta linha os dois filhos
   viravam DUAS FILEIRAS — a folha empilhada abaixo do sapo em vez de
   debaixo dele. Com `grid-area: 1 / 1` eles se sobrepõem, e o alinhamento
   de cada um decide a altura: o sapo centrado, a folha no chão. */
.tema-convite .capa-selo > * {
    grid-area: 1 / 1;
}

/* A VITÓRIA-RÉGIA — a base que faz o sapo parecer sentado.

   `align-self: end` encosta a folha na borda de baixo da caixa do selo, e
   é o sapo que se apoia nela, não o contrário. A largura é a caixa inteira
   porque a folha é MAIS LARGA que o bicho — é o que dá a leitura de "em
   cima de" em vez de "atrás de".

   ⚠️ ELA NÃO ACOMPANHA O `hover` do sapo, de propósito: o bicho levanta e
   a folha fica. Água não sobe junto com quem está em cima dela — e a
   transformação está declarada em `.capa-selo-arte`, que é só a imagem. */
.tema-convite .capa-selo-agua {
    /* MAIS LARGA QUE A CAIXA DO SELO, e o motivo e a proporcao.
       Em 100% a folha tinha exatamente a largura do sapo, entao nao sobrava
       folha aparecendo dos lados — o bicho cobria a elipse inteira e a base
       lia como pequena demais. Na arte original a folha era ~1,7 vez o vulto
       do sapo; aqui ela transborda a celula e o `justify-self` a mantem
       centrada, sobrando dos dois lados. A caixa do selo NAO cresce: quem
       transborda e so o desenho, e a capa recorta o eixo horizontal. */
    width: 145%;
    justify-self: center;
    height: auto;
    align-self: end;
    display: block;
}

.tema-convite .capa-selo-arte {
    width: 100%;
    height: 100%;
    display: block;
    transition: transform var(--mov-rapido) var(--curva-padrao);
}

/* A ARTE DO SELO PODE SER FOTO, E A CAIXA É QUADRADA.
   `.capa-selo` mede 9rem × 9rem e o sapo do tema é DEITADO (360×302). Sem
   `contain`, a caixa estica o bicho — e imagem de personagem esticada é o
   tipo de defeito que ninguém reporta e todo mundo vê. O SVG do selo de
   fábrica ignora esta linha: `object-fit` não se aplica a elemento que já
   preenche a própria caixa. */
.tema-convite .capa-selo-foto {
    object-fit: contain;

    /* OS PES ENCOSTAM NA SOMBRA DA FOLHA, e o numero saiu de medicao.
       A caixa do selo tem 144px e a arte do sapo, com `contain`, pinta 121.
       Centralizada, sobravam 11px embaixo e os pes iam PARAR ABAIXO da linha
       da sombra da vitoria-regia — o bicho afundava na folha em vez de sentar
       nela. Alinhada ao topo, a base pintada cai exatamente sobre a sombra.
       Se a arte do sapo for trocada por outra de proporcao diferente, esta
       linha precisa ser remedida: ela depende da altura pintada. */
    /* DESCE UM POUCO em vez de encostar no topo: com a folha maior, o sapo
       alinhado ao topo ficava com os pes ACIMA da barriga da elipse e voltava
       a ler como pairando. 35% desloca a arte pintada para baixo dentro da
       caixa, e o vulto do bicho passa a repousar sobre a folha em vez de
       tangenciar a borda dela. O numero e de medicao, nao de gosto. */
    object-position: center 35%;
}

/* O anel de folhinhas repintado por CLASSE, e não por atributo `fill`: é assim
   que a CSP `self` continua satisfeita (nada de `style=""`) e que cada visual
   pinta a mesma arte com a sua paleta. */
.tema-convite .capa-selo-arte .orn-folha { fill: var(--ouro-claro); }
.tema-convite .capa-selo-arte .orn-ponto { fill: var(--ouro); }
.tema-convite .capa-selo-arte .orn-fio   { stroke: var(--ouro); opacity: 0.6; }

.tema-convite .capa-selo-inicial {
    font-family: 'Poiret One', Georgia, serif;
    font-size: 26px;
    fill: var(--tinta-texto);
}

.tema-convite .capa-abrir:hover .capa-selo-arte,
.tema-convite .capa-abrir:focus-visible .capa-selo-arte {
    transform: translateY(-3px) rotate(-3deg);
}

/* A ONDA NA ÁGUA — a ÚNICA animação perpétua do produto, e o que ela faz é
   dizer "toque aqui". Sob movimento reduzido ela para (ver o bloco do fim). */
.tema-convite .capa-selo::before,
.tema-convite .capa-selo::after {
    content: "";
    position: absolute;
    left: 2%;
    right: 2%;
    top: 72%;
    height: 26%;
    border-radius: 50%;
    border: 1.5px solid var(--ouro-claro);
    opacity: 0;
    animation: capa-onda 3.4s ease-out infinite;
    pointer-events: none;
}

.tema-convite .capa-selo::before {
    animation-delay: 1.7s;
}

@keyframes capa-onda {
    0%   { transform: scale(0.72); opacity: 0.5; }
    75%  { transform: scale(1.45); opacity: 0; }
    100% { opacity: 0; }
}

/* "TOQUE PARA ABRIR" em BRANCO PURO. Sem `opacity: .85`, que era o achado A1:
   opacidade COMPÕE cor, e o composto `#e9ebe5` media 3,77:1 na única instrução
   da capa. Branco puro mede 4,53:1 sobre o oliva. Custo: zero. */
.tema-convite .capa-toque {
    font-size: var(--fs-1);
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--tinta-texto);
    font-weight: 600;
}

/* -----------------------------------------------------------------------------
   O PALCO E O PAPEL
   -------------------------------------------------------------------------- */

/* O papel sangra até a borda da coluna: os 16px de respiro do `.container` são
   devolvidos aqui, e cada bloco do convite carrega o próprio recuo. */
.tema-convite .palco {
    position: relative;
    width: calc(100% + var(--e-4) * 2);
    margin-inline: calc(var(--e-4) * -1);
    background: var(--cor-superficie);
    box-shadow: var(--elev-3);
    min-height: 100svh;
}

.tema-convite .convite {
    opacity: 0;
    transform: translateY(1.2rem);
    transition: opacity 420ms var(--curva-entrada) 120ms, transform 420ms var(--curva-entrada) 120ms;
}

/* O papel aparece quando a capa sai — pelas MESMAS duas portas dela.
   420ms e não 800ms: o convidado está de pé, no celular, às vezes na porta da
   festa. Com 800 ele esperava 920ms para começar a ler. */
.tema-convite .capa:target ~ .palco .convite,
.tema-convite .convite[data-aberto="sim"] {
    opacity: 1;
    transform: none;
}

/* -----------------------------------------------------------------------------
   ⚠️ O QUE SAIU DAQUI NA T-0037, E POR QUE SAIU INTEIRO
   -----------------------------------------------------------------------------
   As regras do papel ANTIGO — `.convite-folha`, `.convite-rotulo`,
   `.convite-titulo` e `.convite-titulo-destaque`, `.convite-foto`,
   `.convite-nome`, `.convite-idade(-num)`, `.convite-divisa`, `.convite-data*`,
   `.convite-local`, `.convite-mapas`, `.convite-recado`, `.convite-secao` e a
   pele de `.dresscode-lista` — descreviam peças que `views/convite/mostrar.php`
   deixou de emitir quando a parte de dentro passou ao arranjo da demo aprovada
   (`To Dentro/docs/demo-T-0037-convite-novo.html`). Conferido por varredura em
   `views/` e `app/`: nenhuma marcação as emite. Elas não ficaram "de reserva",
   pelo mesmo motivo do anel do selo: duas formas para a mesma peça é a segunda
   fonte da verdade que esta casa já pagou. As decisões que elas documentavam
   (a idade fora da capa, o recado em letra de leitura, a cursiva única da
   T-0035) continuam valendo e estão no bloco novo, logo abaixo.

   FICARAM, porque continuam emitidas: o link da agenda e o `Alterar
   acompanhantes` (a mesma peça), o botão de linha dos mapas e o título da etapa
   dos acompanhantes (`.convite-secao-titulo`).
   ⚠️ As regras-base fora deste bloco (`.convite-titulo`, `.convite-recado` e
   `.dresscode-lista`, da família antiga do cartão) também ficaram órfãs e NÃO
   foram tiradas nesta tarefa: são da varredura de CSS morto da auditoria.
   -------------------------------------------------------------------------- */

/* O link da agenda (T-0027): serviço da data, não segundo botão principal. A
   tinta cheia e o filete de ouro embaixo o distinguem do texto da data; nenhuma
   cor escolhida aqui — `--cor-texto` e `--ouro` vêm da pele, então ele
   acompanha Clássico e Jardim sem uma linha a mais. A altura mínima é o alvo de
   toque da casa: link discreto continua tendo de ser acertado com o polegar.
   Desde a T-0037 ele mora no bloco da data (`.cn-agenda`), com o ícone. */

/* `Alterar acompanhantes`, nas sugestões (T-0034), é a mesma peça que
   `Adicionar à minha agenda`: ação de texto com 44 px de alvo e fio de ouro.
   Entra na MESMA regra, e não numa cópia dela. Ela cai sobre `--cor-fundo`, entre
   o cabeçalho e o cartão das sugestões: `--cor-texto` mede ali 11,18:1 no
   Clássico e 9,67:1 no Jardim (TD-079). */
.tema-convite .convite-alterar {
    margin: 0 0 var(--e-4);
    text-align: center;
}

.tema-convite .convite-agenda-link,
.tema-convite .convite-alterar-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--alvo-toque);
    padding: 0 var(--e-3);
    font-size: var(--fs-2);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--cor-texto);
    text-decoration: underline;
    text-decoration-color: var(--ouro);
    text-underline-offset: 0.3em;
}

/* Botão de linha: fundo de ouro claro, tinta por cima. Medido em 10,27:1 no
   Jardim e 12,15:1 no Clássico — o ouro aqui é FUNDO, nunca a letra. Desde a
   T-0037 são os dois botões de mapa do cartão Local (`.cn-mapas`). */
.tema-convite .btn-linha {
    flex: 1 1 8rem;
    padding: 0.75rem 1rem;
    border-radius: var(--raio-pilula);
    min-height: var(--alvo-toque);
    border: 1.5px solid var(--ouro);
    color: var(--cor-texto);
    text-decoration: none;
    font-size: var(--fs-2);
    font-weight: 700;
    letter-spacing: 0.04em;
    background: var(--ouro-fundo);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
}

/* O título da etapa dos acompanhantes (T-0034), dentro do cartão de alerta. */
.tema-convite .convite-secao-titulo {
    font-family: 'Poiret One', Georgia, serif;
    font-weight: 400;
    font-size: var(--fs-5);
    margin: 0 0 var(--e-1);
    color: var(--cor-texto);
    text-align: center;
    letter-spacing: 0.04em;
}

/* =============================================================================
   O PAPEL NO ARRANJO NOVO — a parte de dentro da capa (T-0037)
   =============================================================================
   A ESPECIFICAÇÃO VISUAL É A DEMO APROVADA (`To Dentro/docs/demo-T-0037-
   convite-novo.html`, a princesa na posição B), e as medidas abaixo são as dela,
   copiadas regra a regra. O que mudou na passagem da demo para a folha:
     · TODA COR É TOKEN da pele (`.visual-*`): o mesmo arranjo veste o Jardim e o
       Clássico sem uma regra por tema. O único token novo é `--ouro-texto`
       (#7a5c26), o ouro ESCURO que a demo usava para texto e ícone sobre o
       papel: `--ouro` (#b8893f) mede 2,76:1 no papel e reprovaria como texto.
       Medido: 5,46:1 no papel do Jardim, 5,56:1 no do Clássico, 6,20:1 no
       cartão branco e 5,14:1 no `--ouro-fundo`. O branco da demo é
       `--tinta-texto` (a F8 recusa hexadecimal em propriedade normal).
     · A letra do corpo é `var(--f-corpo)` (a Nunito), e não o nome escrito de
       novo: a URL das letras do convite é conferida contra as famílias que a
       folha pede (`Cursiva_do_convite_test`).
     · O brilho do cartão escolhido é um `::after` e não o `outline` da demo: o
       `outline` é do anel de foco, e o cartão agora RECEBE o foco (`app.js`).
     · A rolagem suave sem JavaScript é preferência da página, presa a ela por
       `:has()`, e volta a `auto` no bloco de movimento reduzido.
     · Os botões redondos são `flex` centrado, não grade de quatro: festa sem
       Dress code ou sem Presentes tem dois ou três botões, e eles ficam no
       centro em vez de encostados à esquerda de uma grade com buracos.
     · O cartão ancorado para 2,75rem abaixo da borda (a demo usava 1rem): o
       ícone transborda 1,6rem acima do cartão e ficaria cortado no topo.

   CONTRASTE MEDIDO NA COR PINTADA (WCAG 2.x), Jardim · Clássico:
     `--cor-texto` no papel (nome, recado, data, rótulo) ....... 10,91 · 13,14
     `--cor-texto-suave` no papel (linha do tema, dica) .......... 5,79 ·  6,53
     `--cor-texto-suave` no cartão (endereço, manual, apoio) ..... 6,58 ·  7,29
     `--ouro-texto` no papel (idade) ............................. 5,46 ·  5,56
     `--ouro-texto` no cartão ("Confirme até") ................... 6,20 ·  6,20
     `--tinta-texto` na faixa, no ponto MAIS CLARO do gradiente .. 5,11 ·  9,61
     `--ouro-claro` na faixa, no mesmo ponto (título, separador) . 3,60 ·  6,78
       (o título é cursiva de 41,6px — texto grande, piso 3:1; os separadores
       são decoração)
     `--tinta-texto` no botão redondo e no botão cheio ........... 5,11 ·  9,61
     `--cor-texto` no `--ouro-fundo` (botões de mapa) ........... 10,27 · 12,15
   ============================================================================= */

/* Sem JavaScript, os botões redondos são âncoras: a rolagem até o cartão é
   suave para quem não pediu menos movimento (o bloco de movimento reduzido, no
   fim desta seção, devolve `auto`). Presa à página do convite pelo `:has()`. */
:root:has(.tema-convite .cn) {
    scroll-behavior: smooth;
}

/* A CAPA NÃO VOLTA A FECHAR QUANDO O DESTINO ESTÁ DENTRO DO PAPEL. O botão da
   capa é um link para ela mesma e o `:target` a esconde (o caminho sem
   JavaScript); um toque num botão redondo leva o `:target` para um cartão, e
   sem estas duas regras a capa voltaria a cobrir tudo. Com elas, qualquer
   destino dentro do convite a mantém aberta. Com JavaScript quem segura é o
   `data-aberto` (`app.js`). */
.tema-convite:has(.convite :target) .capa {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

.tema-convite:has(.convite :target) .convite {
    opacity: 1;
    transform: none;
}

.tema-convite .cn {
    position: relative;
    max-width: 30rem;
    margin: 0 auto;
    padding: 3.2rem 1.25rem 2.5rem;
    background: var(--cor-superficie);
    color: var(--cor-texto);
    font-family: var(--f-corpo);
    text-align: center;
    overflow: hidden;
}

/* O conteúdo sobe acima da moldura (florais ou guirlanda), que fica no fundo. */
.tema-convite .cn > :not(.cn-floral) {
    position: relative;
    z-index: 1;
}

.tema-convite .cn [id] {
    scroll-margin-top: 2.75rem;
}

.tema-convite .cn-ico {
    display: block;
    flex: none;
    width: 1.5rem;
    height: 1.5rem;
}

/* A MOLDURA. Os florais do Jardim pendurados nos cantos, transbordando a borda
   (o `overflow` do papel os recorta, como na capa); a guirlanda do Clássico
   pendendo do topo, com a mesma altura elástica da capa. */
.tema-convite .cn-floral {
    position: absolute;
    z-index: 0;
    width: 9.5rem;
    height: auto;
    opacity: 0.95;
    pointer-events: none;
}

.tema-convite .cn-floral-sup-dir {
    top: -0.5rem;
    right: -1.5rem;
}

.tema-convite .cn-floral-inf-esq {
    bottom: 9rem;
    left: -2rem;
}

.tema-convite .cn-guirlanda {
    display: block;
    height: clamp(72px, 17vw, 96px);
    margin: -3.2rem -1.25rem 0;
    background-image: var(--guirlanda);
    background-repeat: no-repeat;
    background-position: center top;
    background-size: auto 100%;
    pointer-events: none;
}

/* ----- A abertura ----- */

/* As duas frases do topo crescem com a largura: "O dia mais aguardado chegou!"
   cabe numa linha até 360 px (pedido do usuário, 2026-10-07). */
.tema-convite .cn-tema {
    margin: 0;
    font-size: clamp(0.86rem, 3.9vw, 1.05rem);
    font-weight: 800;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--cor-texto-suave);
}

.tema-convite .cn-rotulo {
    margin: 1.5rem 0 1.9rem;
    font-size: clamp(0.8rem, 3.6vw, 1rem);
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--cor-texto);
}

/* A FOTO EM ARCO com a moldura dourada (dois fios de ouro com o papel entre
   eles). O rosto costuma estar no alto do retrato: `object-position: 50% 6%`. */
.tema-convite .cn-foto {
    position: relative;
    width: 13.75rem;
    max-width: 100%;
    aspect-ratio: 11 / 14;
    margin: 0 auto;
    padding: 0.4rem;
    border-radius: var(--raio-pilula) var(--raio-pilula) 1.2rem 1.2rem;
    background: var(--cor-cartao);
    box-shadow:
        0 0 0 2px var(--ouro),
        0 0 0 7px var(--cor-superficie),
        0 0 0 8px var(--ouro-claro),
        0 18px 36px -18px rgb(var(--sombra-tinta) / 0.45);
}

.tema-convite .cn-retrato {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 6%;
    border-radius: var(--raio-pilula) var(--raio-pilula) 0.9rem 0.9rem;
}

/* A PRINCESA NA POSIÇÃO B, encostada no canto direito do retrato (aprovada em
   2026-10-07). A 360 px a figura termina 6 px antes da borda do papel. */
.tema-convite .cn-princesa {
    position: absolute;
    right: -29%;
    bottom: -11%;
    z-index: 2;
    width: 64%;
    height: auto;
    pointer-events: none;
    filter: drop-shadow(0 10px 10px rgb(var(--sombra-tinta) / 0.35));
}

/* O NOME É O `<h1>`, na cursiva única do convite (T-0035) e com o fator de
   tamanho que a demo aprovou. NUNCA `letter-spacing` aqui: o script é ligado. */
.tema-convite .cn-nome {
    margin: 1.6rem 0 0;
    font-family: 'Imperial Script', cursive;
    font-weight: 400;
    font-size: calc(clamp(3rem, 16vw, 4.4rem) * 1.12);
    line-height: 0.95;
    color: var(--cor-texto);
    text-wrap: balance;
    overflow-wrap: break-word;
}

/* A princesa desce abaixo do arco: o nome desce junto, para não encostar nela. */
.tema-convite .cn-foto-com-princesa + .cn-nome {
    margin-top: 2.8rem;
}

.tema-convite .cn-idade {
    margin: 0.35rem 0 0;
    font-family: 'Poiret One', Georgia, serif;
    font-size: 1.5rem;
    letter-spacing: 0.3em;
    text-transform: uppercase;
    color: var(--ouro-texto);
}

.tema-convite .cn-ornamento {
    display: block;
    width: 10rem;
    height: 1rem;
    margin: 1.4rem auto 0;
    color: var(--ouro);
}

/* O RECADO do dono, com as aspas desenhadas pela folha (o texto é dele, as
   aspas são do convite). */
.tema-convite .cn-recado {
    max-width: 23rem;
    margin: 1.3rem auto 0;
    font-family: 'Poiret One', Georgia, serif;
    font-size: 1.22rem;
    line-height: 1.55;
    color: var(--cor-texto);
}

.tema-convite .cn-recado p {
    margin: 0;
    overflow-wrap: break-word;
}

.tema-convite .cn-recado p::before {
    content: "\201C";
}

.tema-convite .cn-recado p::after {
    content: "\201D";
}

/* ----- A data em bloco ----- */

.tema-convite .cn-data {
    margin: 2rem 0 0;
}

.tema-convite .cn-data-mes,
.tema-convite .cn-data-ano {
    margin: 0;
    font-family: 'Poiret One', Georgia, serif;
    font-size: 1.15rem;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    color: var(--cor-texto);
}

.tema-convite .cn-data-linha {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 0.9rem;
    margin: 0.5rem 0;
}

.tema-convite .cn-data-lado {
    padding: 0.45rem 0;
    border-block: 1px solid var(--ouro);
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--cor-texto-suave);
}

/* Festa sem hora: o flanco fica vazio, e filete em volta de nada é ruído. */
.tema-convite .cn-data-lado:empty {
    border: 0;
}

.tema-convite .cn-data-dia {
    font-family: 'Poiret One', Georgia, serif;
    font-size: 3.6rem;
    line-height: 1;
    color: var(--cor-texto);
}

.tema-convite .cn-agenda {
    margin: 0.6rem 0 0;
}

.tema-convite .cn-agenda .convite-agenda-link {
    gap: 0.45rem;
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-underline-offset: 0.35em;
}

.tema-convite .cn-agenda .cn-ico {
    width: 1.1rem;
    height: 1.1rem;
}

/* ----- Os botões redondos ----- */

.tema-convite .cn-botoes {
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    margin: 2.2rem 0 0;
}

.tema-convite .cn-botao {
    display: flex;
    flex: 0 1 calc((100% - 1.5rem) / 4);
    flex-direction: column;
    align-items: center;
    gap: 0.55rem;
    min-width: 0;
    border-radius: var(--raio-lg);
    color: var(--cor-texto);
    text-decoration: none;
}

.tema-convite .cn-botao-circulo {
    display: grid;
    place-items: center;
    width: 4rem;
    height: 4rem;
    border-radius: 50%;
    background: var(--grad);
    color: var(--tinta-texto);
    box-shadow:
        0 0 0 3px var(--cor-superficie),
        0 0 0 4.5px var(--ouro),
        0 10px 20px -10px rgb(var(--sombra-tinta) / 0.6);
    transition: transform var(--mov-rapido) var(--curva-padrao);
}

.tema-convite .cn-botao:hover .cn-botao-circulo,
.tema-convite .cn-botao:focus-visible .cn-botao-circulo {
    transform: translateY(-2px);
}

.tema-convite .cn-botao-circulo .cn-ico {
    width: 1.6rem;
    height: 1.6rem;
}

/* O corpo desce com a largura só abaixo de 390 px: a 360, "CONFIRMAR" em
   0,72rem não cabe na coluna de um quarto do papel e encostaria no vizinho. */
.tema-convite .cn-botao-rotulo {
    font-size: min(0.72rem, 2.96vw);
    font-weight: 800;
    line-height: 1.25;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.tema-convite .cn-dica {
    margin: 1rem 0 0;
    font-size: 0.88rem;
    font-style: italic;
    color: var(--cor-texto-suave);
}

/* ----- A contagem regressiva — a faixa que sangra até a borda do papel ----- */

.tema-convite .cn-contagem {
    margin: 2.2rem -1.25rem 0;
    padding: 1.6rem 1rem 1.8rem;
    background: var(--grad);
    color: var(--tinta-texto);
}

/* `hidden` vale aqui dentro mesmo nas peças que a folha põe em `flex`: são as
   horas, os minutos e os segundos que só o JavaScript mostra. */
.tema-convite .cn-contagem [hidden] {
    display: none;
}

.tema-convite .cn-contagem-titulo {
    margin: 0 0 0.8rem;
    font-family: 'Imperial Script', cursive;
    font-weight: 400;
    font-size: 2.6rem;
    line-height: 1;
    color: var(--ouro-claro);
}

.tema-convite .cn-contagem-titulo:last-child {
    margin-bottom: 0;
}

.tema-convite .cn-contagem-numeros {
    display: flex;
    justify-content: center;
    align-items: flex-start;
    gap: 0.35rem;
}

.tema-convite .cn-contagem-caixa {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 3.6rem;
}

.tema-convite .cn-contagem-num {
    font-family: 'Poiret One', Georgia, serif;
    font-size: 2.5rem;
    line-height: 1.05;
    font-variant-numeric: tabular-nums;
}

/* Os rótulos são BRANCOS: em `--ouro-claro` mediam 3,60:1 sobre o ponto mais
   claro do verde do Jardim e são texto pequeno (piso 4,5:1). */
.tema-convite .cn-contagem-rot {
    margin-top: 0.25rem;
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--tinta-texto);
}

.tema-convite .cn-contagem-sep {
    font-family: 'Poiret One', Georgia, serif;
    font-size: 2.2rem;
    line-height: 1.1;
    color: var(--ouro-claro);
}

/* ----- Os cartões: Local, Dress code, Presentes e Confirmar ----- */

.tema-convite .cn-cartao {
    position: relative;
    margin: 2.9rem 0 0;
    padding: 2.4rem 1.25rem 1.6rem;
    border: 1px solid var(--cor-borda);
    border-radius: 1.4rem;
    background: var(--cor-cartao);
    box-shadow: 0 14px 30px -22px rgb(var(--sombra-tinta) / 0.5);
}

.tema-convite .cn-contagem + .cn-cartao {
    margin-top: 3.4rem;
}

/* O medalhão do cartão, montado na aresta de cima. */
.tema-convite .cn-cartao-icone {
    position: absolute;
    top: -1.6rem;
    left: 50%;
    display: grid;
    place-items: center;
    width: 3.2rem;
    height: 3.2rem;
    border-radius: 50%;
    background: var(--ouro-fundo);
    color: var(--ouro-texto);
    box-shadow: 0 0 0 3px var(--cor-cartao), 0 0 0 4px var(--ouro);
    transform: translateX(-50%);
}

.tema-convite .cn-cartao-icone .cn-ico {
    width: 1.45rem;
    height: 1.45rem;
}

.tema-convite .cn-cartao-titulo {
    margin: 0 0 0.6rem;
    font-family: 'Imperial Script', cursive;
    font-weight: 400;
    font-size: 2.3rem;
    line-height: 1.05;
    color: var(--cor-texto);
}

.tema-convite .cn-local-nome {
    margin: 0;
    font-size: 1.08rem;
    font-weight: 800;
    overflow-wrap: break-word;
}

.tema-convite .cn-local-endereco {
    margin: 0.3rem 0 0;
    color: var(--cor-texto-suave);
    overflow-wrap: break-word;
}

.tema-convite .cn-mapas {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.7rem;
    margin-top: 1.2rem;
}

/* O Dress code: cada linha do dono é um item; a primeira é o traje, em
   destaque, como na demo; as outras são o apoio. */
.tema-convite .cn-dress-lista {
    margin: 0;
    padding: 0;
    list-style: none;
}

.tema-convite .cn-dress-lista li {
    margin: 0.5rem 0 0;
    color: var(--cor-texto-suave);
    overflow-wrap: break-word;
}

.tema-convite .cn-dress-lista li:first-child {
    margin: 0;
    font-family: 'Poiret One', Georgia, serif;
    font-size: 1.5rem;
    letter-spacing: 0.08em;
    color: var(--cor-texto);
}

.tema-convite .cn-presentes-intro {
    max-width: 21rem;
    margin: 0 auto;
    font-style: italic;
    line-height: 1.55;
    color: var(--cor-texto-suave);
}

.tema-convite .cn-btn-cheio {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--alvo-toque);
    margin-top: 1.2rem;
    padding: 0.8rem 1.4rem;
    border-radius: var(--raio-pilula);
    background: var(--grad);
    color: var(--tinta-texto);
    font-size: 0.92rem;
    font-weight: 800;
    text-decoration: none;
}

/* ----- O manual do convidado ----- */

.tema-convite .cn-manual {
    margin: 2.4rem 0 0;
}

.tema-convite .cn-manual-titulo {
    margin: 0 0 1.1rem;
    font-family: 'Imperial Script', cursive;
    font-weight: 400;
    font-size: 2.2rem;
    line-height: 1.1;
    color: var(--cor-texto);
}

.tema-convite .cn-manual-grade {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 1.2rem 0.9rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.tema-convite .cn-manual-grade li {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.9rem;
    line-height: 1.4;
    color: var(--cor-texto-suave);
}

.tema-convite .cn-manual-grade .cn-ico {
    width: 1.9rem;
    height: 1.9rem;
    color: var(--ouro-texto);
}

/* Com número ímpar de regrinhas, a última fica centralizada na linha inteira. */
.tema-convite .cn-manual-grade li:last-child:nth-child(odd) {
    grid-column: 1 / -1;
    max-width: 12rem;
    margin: 0 auto;
}

/* ----- Confirmar ----- */

.tema-convite .cn-confirmar-ate {
    margin: 0 0 0.4rem;
    font-weight: 700;
    color: var(--ouro-texto);
}

.tema-convite .cn-confirmar-sub {
    margin: 0 0 1.2rem;
    color: var(--cor-texto-suave);
}

/* "Este evento já aconteceu…" e "As confirmações foram encerradas em…": o
   cartão diz isso e mais nada — o resto do convite continua visível. */
.tema-convite .cn-encerrado {
    margin: 0.4rem 0 0;
    font-weight: 600;
    line-height: 1.55;
    color: var(--cor-texto);
}

.tema-convite .cn-confirmar .alerta,
.tema-convite .cn-form {
    text-align: left;
}

/* A LINHA DOS TERMOS (§3.10): a caixa alinhada com a PRIMEIRA linha da frase.
   As regras de campo do convite (`.campo label` em versalete, `.campo input`
   com 48 px de altura e recuo) são zeradas aqui, que é o que fazia a caixa
   flutuar no meio de três linhas. O alvo de toque é a etiqueta inteira, com
   44 px de altura mínima mesmo quando a frase cabe numa linha (na mesa). O link
   TERMOS é menor (72×22): alvo dentro de uma frase, a exceção "inline" da
   WCAG 2.5.8, como a demo aprovou. */
.tema-convite .cn-form .cn-aceite {
    display: flex;
    align-items: flex-start;
    gap: 0.7rem;
    min-height: var(--alvo-toque);
    margin: 1rem 0 0;
    font-family: var(--f-corpo);
    font-size: 0.98rem;
    font-weight: 600;
    line-height: 1.45;
    letter-spacing: normal;
    text-transform: none;
    color: var(--cor-texto);
    cursor: pointer;
}

.tema-convite .cn-form .cn-aceite input[type="checkbox"] {
    flex: none;
    width: 1.3rem;
    height: 1.3rem;
    min-width: 0;
    min-height: 0;
    margin: 0.06rem 0 0;
    padding: 0;
    border: 0;
    background: none;
    accent-color: var(--cor-texto);
}

/* O link na palavra TERMOS. A caixa alta é daqui: no documento a palavra é
   como a constante a escreve. */
.tema-convite .cn-form .cn-aceite a {
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--cor-texto);
    text-decoration: underline;
    text-decoration-color: var(--ouro);
    text-decoration-thickness: 2px;
    text-underline-offset: 0.22em;
}

/* A etapa dos acompanhantes mantém o cartão de alerta da T-0034 inteiro. */
.tema-convite .cn-etapa {
    margin: 2.9rem 0 0;
}

/* ----- O fechamento ----- */

.tema-convite .cn-fechamento {
    margin: 2.6rem 0 0;
}

.tema-convite .cn-selo {
    display: block;
    width: 7.5rem;
    height: auto;
    margin: 0 auto;
}

/* O anel de folhinhas sobre o PAPEL: as folhas em `--ouro` (na capa elas são
   `--ouro-claro` sobre o envelope, que no papel quase sumiria) e a inicial na
   tinta do texto. Decorativo (`aria-hidden`). */
.tema-convite .cn-selo-anel {
    height: 7.5rem;
}

.tema-convite .cn-selo-anel .orn-folha { fill: var(--ouro); }
.tema-convite .cn-selo-anel .orn-ponto { fill: var(--ouro-texto); }
.tema-convite .cn-selo-anel .orn-fio   { stroke: var(--ouro); opacity: 0.6; }

.tema-convite .cn-selo-anel .capa-selo-inicial {
    fill: var(--cor-texto);
}

.tema-convite .cn-fechamento-frase {
    margin: 1rem 0 0;
    font-family: 'Poiret One', Georgia, serif;
    font-size: 1.15rem;
    letter-spacing: 0.24em;
    text-transform: uppercase;
}

.tema-convite .cn-fechamento-assina {
    margin: 0.5rem 0 0;
    font-size: 0.85rem;
    letter-spacing: 0.12em;
    color: var(--cor-texto-suave);
    overflow-wrap: break-word;
}

/* O CARTÃO ESCOLHIDO ACENDE POR UM INSTANTE, para o convidado ver onde chegou
   depois do toque num botão redondo (`app.js` põe e tira `.cn-destacado`). É um
   anel de ouro num `::after`, e não o `outline` da demo: o `outline` é do foco,
   e o cartão recebe o foco junto. Sob movimento reduzido ele não aparece. */
@keyframes cn-destaque {
    0%   { opacity: 0; }
    25%  { opacity: 1; }
    100% { opacity: 0; }
}

.tema-convite .cn-destacado::after {
    content: "";
    position: absolute;
    inset: -5px;
    border: 3px solid var(--ouro);
    border-radius: calc(1.4rem + 5px);
    opacity: 0;
    pointer-events: none;
    animation: cn-destaque 1.8s ease;
}

/* -----------------------------------------------------------------------------
   OS COMPONENTES COMPARTILHADOS, REPINTADOS POR TOKEN
   -----------------------------------------------------------------------------
   Aqui está o ganho medido da camada 2: onde `.tema-verde` gastava 71 regras com
   hexadecimal na mão, sobram estas — e nenhuma delas ESCOLHE uma cor. Botão,
   cartão com borda, filete e banner mudam de pele sozinhos, porque todos já
   liam `var(--grad)`, e `--grad` é token.
   -------------------------------------------------------------------------- */

/* O par `backdrop-filter: none` saiu daqui pelo mesmo motivo do `.topo`: nenhuma
   regra desta folha liga desfoque em cartão, então desligar era peso morto. */
.tema-convite .card,
.tema-convite .card-borda,
.tema-convite .card-presentes {
    background: var(--cor-cartao);
    border: 1px solid var(--cor-borda);
    border-radius: var(--raio-lg);
    box-shadow: var(--elev-1);
}

.tema-convite .card h1,
.tema-convite .card h2 {
    font-family: 'Poiret One', Georgia, serif;
    font-weight: 400;
    text-align: center;
    letter-spacing: 0.06em;
    color: var(--cor-texto);
}

.tema-convite .subtitulo {
    color: var(--cor-texto-suave);
}

.tema-convite .campo label {
    color: var(--cor-texto);
    text-transform: uppercase;
    letter-spacing: 0.16em;
    font-size: var(--fs-1);
    font-weight: 700;
}

/* A borda de campo usa `--limite`, e não `--cor-borda`: era o achado A3 da demo
   (1,47:1 contra o mínimo de 3:1 da WCAG 1.4.11). Com `--limite` mede 3,69:1 no
   Jardim e 3,87:1 no Clássico. A espessura é a MESMA em repouso e em foco —
   variá-la faria a caixa saltar meio pixel a cada foco. */
.tema-convite .campo input,
.tema-convite .campo textarea,
.tema-convite .campo select {
    background: var(--cor-cartao);
    border: 1.5px solid var(--limite);
    color: var(--cor-texto);
    font-size: var(--fs-3);
}

/* Placeholder NÃO é rótulo, e o piso dele é o mesmo 3:1 de componente: o
   `#9bae9b` de antes media 2,35:1 no melhor caso — e era a tela do CONVIDADO. */
.tema-convite .campo input::placeholder,
.tema-convite .campo textarea::placeholder {
    color: var(--limite);
    opacity: 1;
}

.tema-convite .campo input:focus,
.tema-convite .campo textarea:focus,
.tema-convite .campo select:focus {
    border-color: var(--foco);
    box-shadow: none;
    outline: var(--foco-largura) solid var(--foco);
    outline-offset: var(--foco-desvio);
}

.tema-convite .campo small {
    color: var(--cor-texto-suave);
}

/* ⚠️ QUATRO DECLARAÇÕES A MAIS DESDE A T-0031, E CADA UMA DESFAZ UMA DECISÃO QUE
   É DO PAINEL E NÃO DA FESTA. TD-076 tirou o gradiente, a pílula e a Nunito do
   botão do PRODUTO; a família pública fica exatamente como o usuário aprovou na
   T-0015. As três primeiras já estavam aqui; entram a forma e a família — sem
   elas o botão do convite herdaria o raio de 9px e a Space Grotesk do console.
   ⚠️ E O `:hover` PRECISA REPETIR O `background`: a regra base passou a trocar o
   preenchimento para `--acento-forte` sob o ponteiro, e sem esta linha o botão
   do convite viraria roxo do painel exatamente no gesto mais comum da tela. */
.tema-convite .btn {
    background: var(--grad);
    color: var(--tinta-texto);
    border-radius: var(--raio-pilula);
    font-family: var(--f-corpo);
    font-weight: 800;
    box-shadow: var(--elev-2);
}

.tema-convite .btn:hover,
.tema-convite .btn:active {
    background: var(--grad);
    box-shadow: var(--elev-3);
}

.tema-convite .btn-secundario {
    color: var(--cor-texto);
    background: var(--cor-cartao);
    border: 1px solid var(--limite);
}

.tema-convite .alerta-erro {
    background: var(--cor-erro-fundo);
    border: 1px solid var(--cor-erro-borda);
    color: var(--cor-erro-texto);
}

.tema-convite .alerta-sucesso {
    background: var(--cor-sucesso-fundo);
    border: 1px solid var(--cor-sucesso-borda);
    color: var(--cor-sucesso-texto);
}

/* -----------------------------------------------------------------------------
   A ETAPA DOS ACOMPANHANTES COM CARA DE ALERTA (T-0034 · TD-081)
   -----------------------------------------------------------------------------
   O pedido do usuário foi "uma aba de alerta" logo depois de nome e telefone. O
   alerta é feito SÓ com tokens que os dois visuais já declaram — nenhum
   hexadecimal e nenhum token novo —, e por isso vale no Clássico e no Jardim sem
   uma linha por visual:
     · cartão em `--ouro-fundo`, moldura `--ouro` de 2 px e `--elev-2`: é o único
       cartão creme e emoldurado da página, e é isso que o separa do dress code;
     · o selo `--envelope` montado na aresta de cima, com a figura em
       `--ouro-claro`: o par do lacre da capa, decorativo (`aria-hidden`);
     · as opções são campos BRANCOS com borda `--limite`, o mesmo "campo branco
       sobre o papel" que a T-0015 aprovou, a 16 px e com 44 px de alvo.

   CONTRASTE POR ENUMERAÇÃO (TD-079), WCAG 2.x — Clássico · Jardim:
     `--cor-texto` sobre `--ouro-fundo` (título, pergunta) ........ 12,15 · 10,27
     `--cor-texto` sobre `--cor-cartao` (nome da opção) ........... 14,66 · 12,40
     `--limite` contra `--ouro-fundo` (borda: o lado que não perdoa)  3,21 ·  3,06
     `--limite` contra `--cor-cartao` (borda, lado de dentro) ........ 3,87 ·  3,69
     `--cor-texto` contra `--ouro-fundo` (borda da opção marcada) .. 12,15 · 10,27
     `--cor-acento` contra `--cor-cartao` (caixa marcada) ............ 6,51 ·  6,51
     `--cor-erro-texto` sobre `--cor-erro-fundo` (recusa) ............ 4,96 ·  4,96
     `--ouro-claro` sobre `--envelope` (figura do selo, decorativa) .. 9,70 ·  3,20
     `--envelope` contra `--cor-superficie` (selo sobre o palco) .... 12,31 ·  3,99
     `--ouro` contra `--cor-superficie` (moldura, decorativa) ........ 2,81 ·  2,76
   A moldura e o selo NÃO carregam informação: o que dizer e onde tocar está no
   título, na pergunta e nas caixas. Nenhum estado depende deles.

   ⚠️ A CAIXA LÊ `--cor-acento`, COMO A DOS TERMOS NO PASSO ANTERIOR DO MESMO
   FLUXO (`.campo-aceite`). Os visuais ainda não declaram `--acento` (consulta
   aberta da T-0031 4a); quando declararem, as duas caixas mudam juntas.
   -------------------------------------------------------------------------- */
.tema-convite .convite-alerta-cartao {
    position: relative;
    margin: var(--e-8) 0 0;
    padding: var(--e-10) var(--e-5) var(--e-6);
    background: var(--ouro-fundo);
    border: 2px solid var(--ouro);
    box-shadow: var(--elev-2);
}

.tema-convite .convite-alerta-selo {
    position: absolute;
    top: 0;
    left: 50%;
    display: grid;
    place-items: center;
    width: 3.5rem;
    height: 3.5rem;
    border: 2px solid var(--ouro);
    border-radius: var(--raio-pilula);
    background: var(--envelope);
    color: var(--ouro-claro);
    box-shadow: var(--elev-1);
    transform: translate(-50%, -50%);
}

.tema-convite .convite-alerta-selo svg {
    width: 1.75rem;
    height: 1.75rem;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
}

/* `fieldset` e `legend` perdem o desenho do navegador, não a semântica.
   `min-width: 0` desfaz o `min-content` do fieldset: sem ele, um nome longo
   alarga o cartão para fora da coluna no celular. */
.tema-convite .convite-alerta-grupo {
    min-width: 0;
    margin: 0 0 var(--e-5);
    padding: 0;
    border: 0;
}

.tema-convite .convite-alerta-pergunta {
    width: 100%;
    margin: 0 0 var(--e-2);
    padding: 0;
    color: var(--cor-texto);
    font-size: var(--fs-4);
    font-weight: 700;
    text-align: center;
}

.tema-convite .convite-alerta-grupo .alerta {
    margin: var(--e-3) 0 var(--e-1);
    text-align: left;
}

/* A OPÇÃO INTEIRA É O ALVO: o `<label>` embrulha a caixa, então tocar no nome
   marca. Altura mínima de `--alvo-toque` e letra de 16 px (celular primeiro). */
.tema-convite .convite-alerta-opcao {
    display: flex;
    align-items: center;
    gap: var(--e-3);
    min-height: var(--alvo-toque);
    margin-top: var(--e-2);
    padding: var(--e-2) var(--e-4);
    background: var(--cor-cartao);
    border: 1.5px solid var(--limite);
    border-radius: var(--raio-md);
    color: var(--cor-texto);
    font-size: var(--fs-3);
    font-weight: 600;
    text-align: left;
    overflow-wrap: anywhere;
    cursor: pointer;
}

.tema-convite .convite-alerta-opcao input[type="checkbox"] {
    flex: none;
    width: 22px;
    height: 22px;
    margin: 0;
    accent-color: var(--cor-acento);
}

/* Marcada, a opção ganha a tinta na borda. A espessura não muda (o `inset` não
   ocupa caixa, então nada salta) e a cor não é o único sinal: o visto da caixa
   continua sendo o indicador. */
.tema-convite .convite-alerta-opcao:has(input:checked) {
    border-color: var(--cor-texto);
    box-shadow: inset 0 0 0 1px var(--cor-texto);
}

/* "Vou sem acompanhante" exclui as outras respostas: um respiro a mais a separa
   dos nomes, sem texto novo (§6 da emenda). */
.tema-convite .convite-alerta-nenhum {
    margin-top: var(--e-4);
}

/* ----- As telas irmãs (sugestões e galeria) vestem a mesma pele ----- */

.tema-convite .painel-cabecalho h1 {
    font-family: 'Poiret One', Georgia, serif;
    font-weight: 400;
    color: var(--cor-texto);
}

.tema-convite .sug-titulo {
    font-family: 'Poiret One', Georgia, serif;
    font-weight: 400;
    font-size: var(--fs-6);
    letter-spacing: 0.06em;
    color: var(--cor-texto);
    margin: 0;
}

/* O "Presentes" é cursivo, e desde a T-0035 na Imperial Script, a cursiva única
   do convite. O `* 1.08` iguala o tamanho visual de antes com a régua de
   `.capa-nome` (a LARGURA): medido no Edge por canvas, com as duas letras a
   100px, "Presentes" tem 316,1px de tinta na Great Vibes e 293,1px na
   Imperial — 1,078. */
.tema-convite .sug-titulo b {
    display: block;
    font-weight: 400;
    font-family: 'Imperial Script', cursive;
    font-size: calc(var(--fs-7) * 1.08);
    line-height: 1.05;
    margin-top: 2px;
    padding-bottom: var(--e-2);
    text-transform: none;
    letter-spacing: normal;
    background: none;
    color: var(--cor-texto);
    -webkit-text-fill-color: var(--cor-texto);
}

.tema-convite .sapo-titulo {
    display: block;
    width: 118px;
    height: auto;
    margin: 2px auto 6px;
}

.tema-convite .sug-acc {
    border: 1px solid var(--cor-borda);
    border-radius: var(--raio-lg);
    overflow: hidden;
    background: var(--cor-cartao);
}

.tema-convite .sug-acc.aberto {
    border-color: var(--ouro);
}

.tema-convite .sug-acc-ic {
    color: var(--cor-texto-suave);
    display: flex;
    flex-shrink: 0;
}

.tema-convite .sug-acc-nome {
    display: block;
    font-weight: 700;
    font-size: var(--fs-3);
    color: var(--cor-texto);
}

.tema-convite .sug-acc-count {
    display: block;
    font-size: var(--fs-1);
    color: var(--cor-texto-suave);
}

.tema-convite .presentes-cabecalho::after {
    background: linear-gradient(90deg, transparent, var(--ouro), transparent);
}

.tema-convite .confirmado-banner {
    border-top: 4px solid var(--ouro);
    border-image: none;
}

.tema-convite .convite-link {
    background: var(--ouro-fundo);
}

/* Só a COR fica. `background: none` e `-webkit-text-fill-color` existiam para
   desfazer o `background-clip: text` da regra base — que saiu na T-0016. Contra-
   medida cujo motivo morreu é ruído: quem a lesse depois procuraria um efeito
   que não existe mais. O que continua tendo motivo é a tinta: no convite este
   rótulo usa o texto FORTE (`--cor-texto`), e não o suave da regra base. */
.tema-convite .convite-link label {
    color: var(--cor-texto);
}

.tema-convite .convite-input {
    background: var(--cor-cartao);
    border: 1px solid var(--limite);
    color: var(--cor-texto);
}

/* -----------------------------------------------------------------------------
   MOVIMENTO REDUZIDO — o que SAI e o que FICA
   -----------------------------------------------------------------------------
   Sem regra global de `.001ms`: ela apagaria junto o feedback de estado que a F6
   decidiu preservar (o medidor chegando ao valor, as listras do indeterminado, o
   flash da câmera). O que sai é decoração perpétua e deslocamento; o que fica é
   tudo o que INFORMA. E um esvanecimento É movimento para quem tem sensibilidade
   vestibular: a troca de cena vira instantânea, mas ACONTECE.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .tema-convite .capa-selo::before,
    .tema-convite .capa-selo::after {
        animation: none;
    }

    /* A chegada sai; o FATO fica. O keyframe só descreve o `from`, então
       remover a animação devolve nome e linha opacos e sem transformação — que
       é a versão sem movimento DECIDIDA, não o que sobrou por acaso. */
    .tema-convite .capa-nome,
    .tema-convite .capa-linha {
        animation: none;
    }

    .tema-convite .capa-abrir:hover .capa-selo-arte,
    .tema-convite .capa-abrir:focus-visible .capa-selo-arte {
        transform: none;
    }

    .tema-convite .capa {
        transition: none;
    }

    .tema-convite .convite {
        transition: none;
        transform: none;
    }

    /* T-0037: a rolagem até o cartão salta direto, o círculo do botão
       redondo não sobe sob o ponteiro e o cartão escolhido não acende. */
    :root:has(.tema-convite .cn) {
        scroll-behavior: auto;
    }

    .tema-convite .cn-botao:hover .cn-botao-circulo,
    .tema-convite .cn-botao:focus-visible .cn-botao-circulo {
        transform: none;
    }

    .tema-convite .cn-destacado::after {
        animation: none;
    }
}


/* =============================================================================
   A VITRINE — a página inicial pública `/` (T-0017, TD-082)
   =============================================================================
   O usuário trocou a página inicial pelo desenho do arquivo do Stitch, inteiro e
   com os textos dele; do site de hoje ficou o logo. A especificação visual é a
   demo aprovada (`To Dentro/docs/demo-T-0017-pagina-inicial.html`), e cada valor
   abaixo foi lido do VALOR COMPUTADO dela no navegador, a 1280, 390, 360 e 320 px
   — não do nome da classe do Tailwind.

   COMO O ARQUIVO VIROU FOLHA DA CASA:
     · Toda classe é `vitrine-*`, e nenhuma regra sai do escopo da página: o que
       não é da vitrine é `.tema-vitrine` (o `<body>` dela), a classe que o
       `Tema::Vitrine` emite.
     · A paleta do arquivo é TOKEN, em dois blocos — `.tema-vitrine` (claro) e
       `:root.modo-escuro .tema-vitrine` (escuro) —, e o escuro é o mecanismo de
       modo do site (a classe no `<html>`, pelo cookie), não a `.dark` da demo.
       As regras de ouro do bloco escuro da casa valem aqui também, e há teste:
       só token, nenhum token só no escuro, nenhum hexadecimal repetido.
     · Onde a casa já tem token para o MESMO valor, é ele: espaço (`--e-*`),
       raio (`--raio-sm/md/lg/xl/pilula` = 8/12/16/24/pílula, exatamente os do
       arquivo), movimento (`--mov-rapido`, `--curva-padrao`, `--curva-entrada`),
       camada (`--z-cabecalho`), foco (`--foco*`) e o branco (`--branco`). O que
       não tem par na casa fica em `rem`.
     · Os ícones são a fonte do arquivo (Material Symbols), recortada em
       `Tema::hrefDosIcones()`; `.vitrine-icone` faz o que a classe do Google faz.

   ONDE A FOLHA SE AFASTA DA DEMO, E POR QUÊ (todos medidos ou proibidos):
     · O TOPO É CHAPADO na cor do papel, sem o `backdrop-blur` e sem os 85% de
       alfa da demo. O desfoque é proibido nesta folha (caixa branca fantasma no
       Chromium, bug pago) e, sem ele, o alfa só mostra o conteúdo NÍTIDO
       passando por baixo — a mesma conta que tirou os dois do `.topo` da casa.
       Em repouso a cor é a mesma: 85% de `#fdf7ff` sobre `#fdf7ff` é `#fdf7ff`.
     · O selo do herói e o "Ver demonstração" perdem o `backdrop-blur` pelo
       mesmo motivo; o vidro deles (branco a 10%) fica.
     · A 320 px a demo ACHATA a logo (85,5 × 30 px, proporção quebrada) para o
       topo caber. Aqui ela encolhe INTEIRA (`object-fit: contain`).
     · Um ponto de virada a mais, `40rem` (640 px): é onde o arquivo vira o topo,
       o herói e o rodapé, e a decisão 9 do usuário fala em "abaixo de 640 px".
       Ver o placar de larguras, mais abaixo.

   O AJUSTE DE CONTRASTE APROVADO (2026-10-06): os selos verdes usam `#006c44`
   no claro e a linha da Carla Nunes perdeu o apagado. Todo texto passa 4,5:1
   (3:1 em letra grande e ícone) na cor PINTADA, nos dois modos — medido no
   navegador, sobre a página servida.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   1. OS TOKENS — a paleta do arquivo, nos dois modos
   -----------------------------------------------------------------------------
   PIGMENTOS (não giram com o modo): as cores que pintam superfície escura em
   QUALQUER modo — o herói, o bloco do prazo, o convite final, o botão violeta.
   PAPÉIS (giram): o resto, cada um com o nome do trabalho que faz. No escuro,
   quem precisa do valor de outro lê `var(--outro)`.
   -------------------------------------------------------------------------- */
.tema-vitrine {
    /* Pigmentos */
    --vitrine-noite: #1d1335;               /* surface-dark: herói, prazo, fim do degradê */
    --vitrine-violeta: #6633ee;             /* primary-container: o botão e a marca */
    --vitrine-violeta-fundo: #4d00d3;       /* primary: o botão sob o ponteiro */
    --vitrine-verde: #006c44;               /* secondary: "Copiar Link", régua, ponto ao vivo */
    --vitrine-verde-selo: #138855;          /* badge-success-text: o ícone "verificado" do rodapé */
    --vitrine-menta: #6ffcb5;               /* secondary-fixed: destaque sobre a noite */
    --vitrine-menta-forte: #4fdf9b;         /* secondary-fixed-dim: a onda do ponto ao vivo */
    --vitrine-lilas: #e9e5f2;               /* surface-subtle: texto do herói e trilho do anel */
    --vitrine-lavanda: #f5f3fa;             /* surface-tint: itens do prazo, botão branco sob o ponteiro */
    --vitrine-lavanda-forte: #ded3ff;       /* on-primary-container: texto sobre o degradê */
    --vitrine-lavanda-forte-80: rgb(222 211 255 / 0.8);
    --vitrine-vidro: rgb(255 255 255 / 0.1);
    --vitrine-vidro-forte: rgb(255 255 255 / 0.15);
    --vitrine-vidro-leve: rgb(255 255 255 / 0.04);
    --vitrine-vidro-texto: rgb(255 255 255 / 0.9);
    --vitrine-brilho-violeta: rgb(102 51 238 / 0.3);
    --vitrine-brilho-magenta: rgb(171 0 165 / 0.2);
    --vitrine-brilho-verde: rgb(0 108 68 / 0.2);
    --vitrine-brilho-roxo: rgb(77 0 211 / 0.2);
    --vitrine-sombra-leve: 0 1px 2px rgb(0 0 0 / 0.05);
    --vitrine-sombra-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
    --vitrine-sombra-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
    --vitrine-sombra-tecla: 0 8px 20px -2px rgb(102 51 238 / 0.35);
    --vitrine-sombra-tecla-grande: 0 10px 30px -4px rgb(102 51 238 / 0.55);
    --vitrine-sombra-tecla-grande-sob: 0 12px 36px -2px rgb(102 51 238 / 0.7);
    --vitrine-sombra-tecla-rodape: 0 8px 20px -2px rgb(102 51 238 / 0.25);
    --vitrine-sombra-convite: 0 20px 50px -10px rgb(77 0 211 / 0.4);
    --vitrine-rodape-sombra: 0 1px 8px rgb(29 19 53 / 0.04);

    /* Papéis — o claro */
    --vitrine-fundo: #fdf7ff;               /* background: o papel, e a barra do navegador */
    --vitrine-topo-sombra: 0 1px 8px rgb(29 19 53 / 0.04);
    --vitrine-sup-baixa: #f7f1ff;           /* surface-container-low */
    --vitrine-sup-media: #f2ebfa;           /* surface-container */
    --vitrine-sup-alta: #ece6f4;            /* surface-container-high */
    --vitrine-cartao: var(--branco);        /* surface-container-lowest */
    --vitrine-cartao-sombra: 0 8px 24px -4px rgb(29 19 53 / 0.06);
    --vitrine-duvida-sombra: 0 2px 8px rgb(29 19 53 / 0.04);
    --vitrine-cartao-faixa: var(--vitrine-sup-baixa);
    --vitrine-quadro: var(--branco);
    --vitrine-quadro-sombra: 0 24px 50px -12px rgb(0 0 0 / 0.45);
    --vitrine-quadro-faixa: var(--vitrine-sup-baixa);
    --vitrine-quadro-placa: var(--vitrine-lavanda);
    --vitrine-quadro-chip-sombra: var(--vitrine-sombra-leve);
    --vitrine-sutil: var(--vitrine-lilas);
    --vitrine-texto-forte: #110b22;         /* text-primary-dark */
    --vitrine-texto: #1c1a24;               /* on-surface */
    --vitrine-texto-medio: #494456;         /* on-surface-variant */
    --vitrine-texto-suave: #6b647b;         /* text-muted — 4,54:1 até sobre o lilás do selo */
    --vitrine-texto-sob: var(--vitrine-texto);
    --vitrine-roxo: var(--vitrine-violeta-fundo);     /* primary como tinta */
    --vitrine-roxo-claro: var(--vitrine-violeta);     /* primary-container como tinta */
    --vitrine-pastilha-roxa: #e7deff;       /* primary-fixed */
    --vitrine-pastilha-roxa-sob: var(--vitrine-pastilha-roxa);
    --vitrine-pastilha-roxa-50: rgb(231 222 255 / 0.5);
    --vitrine-pastilha-roxa-60: rgb(231 222 255 / 0.6);
    --vitrine-tinta-roxa: #1f0060;          /* on-primary-fixed */
    --vitrine-tinta-roxa-sob: var(--vitrine-tinta-roxa);
    --vitrine-verde-texto: var(--vitrine-verde);
    --vitrine-pastilha-verde: #e8faf2;      /* badge-success-bg */
    --vitrine-selo-verde: var(--vitrine-verde);       /* o ajuste aprovado: #006c44, e não o #138855 do arquivo */
    --vitrine-selo-verde-icone: var(--vitrine-verde-selo);
    --vitrine-pastilha-menta: var(--vitrine-menta);   /* secondary-container */
    --vitrine-tinta-menta: #007349;         /* on-secondary-container */
    --vitrine-pastilha-rosa: #ffd7f3;       /* tertiary-fixed */
    --vitrine-tinta-rosa: #390036;          /* on-tertiary-fixed */
    --vitrine-rosa: #83007e;                /* tertiary */

    /* Letra, escala e medidas do arquivo (DESIGN.md) */
    --vitrine-letra: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
    --vitrine-icones: 'Material Symbols Outlined';
    --vitrine-titulo-xl: 2.5rem;            /* 40px — headline-xl */
    --vitrine-titulo-lg: 1.75rem;           /* 28px — headline-lg */
    --vitrine-titulo-md: 1.25rem;           /* 20px — headline-md */
    --vitrine-titulo-sm: 1.0625rem;         /* 17px — headline-sm */
    --vitrine-corpo-lg: 1rem;               /* 16px — body-lg */
    --vitrine-corpo-md: 0.875rem;           /* 14px — body-md */
    --vitrine-corpo-sm: 0.8125rem;          /* 13px — body-sm e label-md */
    --vitrine-miudo: 0.75rem;               /* 12px */
    --vitrine-rotulo: 0.6875rem;            /* 11px — label-sm */
    --vitrine-topo-altura: 5rem;            /* o topo fixo de 80 px */
    --vitrine-largura: 80rem;               /* a faixa mais larga do arquivo (1280 px) */
}

/* O ESCURO — a paleta de `demo-t0017-escuro.css`, valor por valor. */
:root.modo-escuro .tema-vitrine {
    --vitrine-fundo: #110b22;
    --vitrine-topo-sombra: 0 1px 0 rgb(255 255 255 / 0.07);
    --vitrine-sup-baixa: #171030;
    --vitrine-sup-media: #1a1236;
    --vitrine-sup-alta: #241a42;
    --vitrine-cartao: var(--vitrine-noite);
    --vitrine-cartao-sombra: 0 0 0 1px rgb(255 255 255 / 0.08);
    --vitrine-duvida-sombra: var(--vitrine-cartao-sombra);
    --vitrine-cartao-faixa: var(--vitrine-sup-alta);
    --vitrine-quadro: var(--vitrine-sup-alta);
    --vitrine-quadro-sombra: 0 0 0 1px rgb(255 255 255 / 0.1), 0 24px 50px -12px rgb(0 0 0 / 0.55);
    --vitrine-quadro-faixa: #2c2250;
    --vitrine-quadro-placa: var(--vitrine-quadro-faixa);
    --vitrine-quadro-chip-sombra: none;
    --vitrine-sutil: var(--vitrine-quadro-faixa);
    --vitrine-texto-forte: var(--branco);
    --vitrine-texto: #f5eefd;
    --vitrine-texto-medio: #cac3d9;
    --vitrine-texto-suave: #b9b2ca;
    --vitrine-texto-sob: var(--branco);
    --vitrine-roxo: #ccbeff;
    --vitrine-roxo-claro: var(--vitrine-roxo);
    --vitrine-pastilha-roxa: rgb(102 51 238 / 0.32);
    --vitrine-pastilha-roxa-sob: rgb(102 51 238 / 0.4);
    --vitrine-pastilha-roxa-50: rgb(102 51 238 / 0.26);
    --vitrine-pastilha-roxa-60: var(--vitrine-pastilha-roxa-50);
    --vitrine-tinta-roxa: #e7deff;
    --vitrine-tinta-roxa-sob: var(--branco);
    --vitrine-verde-texto: var(--vitrine-menta-forte);
    --vitrine-pastilha-verde: rgb(38 194 129 / 0.16);
    --vitrine-selo-verde: var(--vitrine-menta);
    --vitrine-selo-verde-icone: var(--vitrine-menta);
    --vitrine-pastilha-menta: rgb(38 194 129 / 0.2);
    --vitrine-tinta-menta: var(--vitrine-menta);
    --vitrine-pastilha-rosa: rgb(196 40 187 / 0.24);
    --vitrine-tinta-rosa: #ffd7f3;
    --vitrine-rosa: #ffabef;
}

/* -----------------------------------------------------------------------------
   2. O DOCUMENTO — letra, papel, rolagem e foco
   -------------------------------------------------------------------------- */
/* O atalho `background` zera a imagem dos campos de cor da casa (`body`): a
   vitrine não tem "sala", tem o papel liso do arquivo. */
.tema-vitrine {
    font-family: var(--vitrine-letra);
    font-size: var(--vitrine-corpo-md);
    line-height: 1.5;
    color: var(--vitrine-texto);
    background: var(--vitrine-fundo);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* O menu rola a MESMA página até a seção, suave só para quem não pediu menos
   movimento, e a seção para logo abaixo do topo fixo (decisão de 2026-10-06). */
@media (prefers-reduced-motion: no-preference) {
    :root:has(.tema-vitrine) {
        scroll-behavior: smooth;
    }
}

.vitrine-passos-secao,
.vitrine-vantagens-secao,
.vitrine-duvidas-secao {
    scroll-margin-top: var(--vitrine-topo-altura);
}

/* O `<main>` da casa tem `padding: 26px 16px 56px` (e 40px de topo a partir de
   48rem); a vitrine é de ponta a ponta e paga só a altura do topo fixo. */
.vitrine {
    padding: var(--vitrine-topo-altura) 0 0;
    background: var(--vitrine-fundo);
}

/* O anel da casa, e só ele (`outline` e `outline-offset`, nada mais). Sobre as
   superfícies escuras o anel vira branco: o `--anel` do claro mede 1,34:1 contra
   a noite e sumiria. */
.tema-vitrine :focus-visible {
    outline: var(--foco-largura) solid var(--foco);
    outline-offset: var(--foco-desvio);
}

.vitrine-heroi,
.vitrine-prazo,
.vitrine-convite {
    --foco: var(--branco);
}

/* O pulo para o conteúdo é o da casa; só a letra é a da página. */
.tema-vitrine .cabine-pular {
    font-family: var(--vitrine-letra);
}

/* O ÍCONE — o que a classe `.material-symbols-outlined` do Google faz. */
.vitrine-icone {
    display: inline-block;
    font-family: var(--vitrine-icones);
    font-weight: 400;
    font-style: normal;
    font-size: 24px;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
}

/* -----------------------------------------------------------------------------
   3. O TOPO FIXO
   -----------------------------------------------------------------------------
   Abaixo de 640 px (decisão 9, medida na demo): lado de 1.25rem, logo de 30 px,
   botão de modo de 36 px e "Criar minha conta" em 13 px, numa linha só a 390 e
   a 360 px. A 360 a conta fecha EXATA (20 + 125,5 + 12 + 36 + 8 + 138,5 + 20 =
   360), então abaixo disso quem cede é a logo — inteira, sem achatar.
   -------------------------------------------------------------------------- */
.vitrine-topo {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: var(--z-cabecalho);
    background: var(--vitrine-fundo);
    box-shadow: var(--vitrine-topo-sombra);
}

.vitrine-topo-faixa {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-3);
    height: var(--vitrine-topo-altura);
    max-width: var(--vitrine-largura);
    margin-inline: auto;
    padding-inline: 1.25rem;
}

.vitrine-marca {
    display: flex;
    align-items: center;
    min-width: 0;
}

/* `logo-img` está no mesmo `<img>` (é o gancho do `app.js`); esta regra vem
   depois na folha e vence por ordem: a altura da vitrine é a dela. */
.vitrine-marca-topo {
    display: block;
    height: 30px;
    width: auto;
    max-width: 100%;
    object-fit: contain;
    object-position: left center;
}

.vitrine-menu {
    display: none;
    align-items: center;
    gap: var(--e-8);
}

.vitrine-menu-link {
    font-size: var(--vitrine-corpo-md);
    line-height: 1.5;
    color: var(--vitrine-texto-medio);
    text-decoration: none;
    transition: color var(--mov-rapido) var(--curva-padrao);
}

a.vitrine-menu-link:hover {
    color: var(--vitrine-texto-sob);
}

/* PLANOS e PLANOS E PREÇOS: visíveis, apagados, sem clique (decisão de
   2026-10-06). `#6b647b` mede 5,34:1 sobre o papel. */
.vitrine-menu-link.vitrine-indisponivel,
.vitrine-rodape-link.vitrine-indisponivel {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    color: var(--vitrine-texto-suave);
    cursor: default;
    user-select: none;
}

.vitrine-selo-breve {
    padding: 2px var(--e-2);
    border-radius: var(--raio-pilula);
    background: var(--vitrine-pastilha-roxa);
    color: var(--vitrine-tinta-roxa);
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.04em;
}

.vitrine-topo-acoes {
    display: flex;
    align-items: center;
    gap: var(--e-2);
    flex-shrink: 0;
}

/* O ALTERNADOR DE MODO no desenho do arquivo. Os glifos (lua e sol) são os da
   casa, e quem mostra um ou outro é `.modo-glifo-*`, pela classe do `<html>`. */
.vitrine-modo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 0;
    border-radius: var(--raio-md);
    background: var(--vitrine-pastilha-roxa-50);
    color: var(--vitrine-roxo-claro);
    cursor: pointer;
    transition: background-color var(--mov-rapido) var(--curva-padrao);
}

.vitrine-modo:hover {
    background: var(--vitrine-pastilha-roxa-sob);
}

/* -----------------------------------------------------------------------------
   4. AS TECLAS — os botões do arquivo, todos `<a>` (ou o `Sair`, `<button>`)
   -------------------------------------------------------------------------- */
.vitrine-tecla {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: var(--raio-md);
    font-family: inherit;
    font-size: var(--vitrine-corpo-md);
    line-height: 1.3125rem;
    font-weight: 700;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition:
        background-color var(--mov-rapido) var(--curva-padrao),
        color var(--mov-rapido) var(--curva-padrao),
        box-shadow var(--mov-rapido) var(--curva-padrao);
}

.vitrine-tecla .vitrine-icone {
    margin-left: var(--e-2);
    font-size: 20px;
}

/* "Entrar" (e o `Sair`, para quem estiver logado): o botão claro do topo. No
   celular o desenho o esconde, porque o lugar é do botão cheio; com o cadastro
   fechado não há botão cheio, e ele volta (`-sempre`). */
.vitrine-tecla-suave {
    padding: 0.625rem var(--e-4);
    font-weight: 600;
    color: var(--vitrine-roxo-claro);
    background: var(--vitrine-pastilha-roxa-50);
}

.vitrine-tecla-suave:hover {
    background: var(--vitrine-pastilha-roxa-sob);
    color: var(--vitrine-tinta-roxa-sob);
}

.vitrine-topo-acoes .vitrine-tecla-suave {
    display: none;
}

.vitrine-topo-acoes .vitrine-tecla-sempre {
    display: inline-flex;
}

.vitrine-tecla-cheia {
    background: var(--vitrine-violeta);
    color: var(--branco);
}

.vitrine-tecla-cheia:hover {
    background: var(--vitrine-violeta-fundo);
}

.vitrine-tecla-topo {
    padding: 0.625rem 0.875rem;
    font-size: var(--vitrine-corpo-sm);
    white-space: nowrap;
    box-shadow: var(--vitrine-sombra-tecla);
}

.vitrine-tecla-grande {
    padding: var(--e-4) var(--e-8);
    font-size: var(--vitrine-corpo-lg);
    line-height: 1.5rem;
}

.vitrine-tecla-grande.vitrine-tecla-cheia {
    box-shadow: var(--vitrine-sombra-tecla-grande);
}

.vitrine-tecla-grande.vitrine-tecla-cheia:hover {
    box-shadow: var(--vitrine-sombra-tecla-grande-sob);
}

/* O botão branco do convite final: a tinta violeta não gira com o modo. */
.vitrine-tecla-branca {
    background: var(--branco);
    color: var(--vitrine-violeta);
    box-shadow: var(--vitrine-sombra-lg);
}

.vitrine-tecla-branca:hover {
    background: var(--vitrine-lavanda);
}

.vitrine-tecla-vidro {
    padding: var(--e-4) var(--e-6);
    font-size: var(--vitrine-corpo-lg);
    line-height: 1.5rem;
    font-weight: 600;
    color: var(--vitrine-vidro-texto);
    background: var(--vitrine-vidro);
}

.vitrine-tecla-vidro:hover {
    background: var(--vitrine-vidro-forte);
}

.vitrine-tecla-rodape {
    width: 100%;
    padding: var(--e-3) var(--e-4);
    font-size: var(--vitrine-corpo-sm);
    line-height: 1.125rem;
    background: var(--vitrine-violeta);
    color: var(--branco);
    box-shadow: var(--vitrine-sombra-tecla-rodape);
}

.vitrine-tecla-rodape:hover {
    background: var(--vitrine-violeta-fundo);
}

/* A AÇÃO DA PÁGINA (`inicio/_acao.php`): a mesma peça no herói e no convite. */
.vitrine-acao-heroi {
    margin-bottom: var(--e-5);
}

.vitrine-acao-convite {
    margin-bottom: var(--e-8);
}

.vitrine-acao-botoes {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--e-4);
}

.vitrine-acao-convite .vitrine-acao-botoes {
    align-items: center;
    justify-content: center;
}

.vitrine-acao-convite .vitrine-acao-principal {
    width: 100%;
}

/* As duas linhas de porta fechada (§6, CA-170). O arquivo não tem esse estado;
   elas herdam a cor de apoio da superfície em que caem. */
.vitrine-acao-apoio {
    margin-top: var(--e-3);
    font-size: var(--vitrine-corpo-sm);
    line-height: 1.125rem;
    color: var(--vitrine-lilas);
}

.vitrine-acao-convite .vitrine-acao-apoio {
    color: var(--vitrine-lavanda-forte);
}

/* -----------------------------------------------------------------------------
   5. O HERÓI — a noite com as três luzes, o texto e o quadro de exemplo
   -------------------------------------------------------------------------- */
.vitrine-heroi {
    position: relative;
    overflow: hidden;
    padding-block: 3.5rem;
    background: var(--vitrine-noite);
    color: var(--branco);
}

/* As luzes desfocadas do arquivo: `filter` na própria mancha, que é parada e
   não lê nada atrás dela — não é `backdrop-filter`, que segue proibido. */
.vitrine-luz {
    position: absolute;
    border-radius: var(--raio-pilula);
    pointer-events: none;
}

.vitrine-luz-1 {
    top: -8rem;
    left: -8rem;
    width: 24rem;
    height: 24rem;
    background: var(--vitrine-brilho-violeta);
    filter: blur(64px);
}

.vitrine-luz-2 {
    top: 50%;
    right: 0;
    width: 30rem;
    height: 30rem;
    background: var(--vitrine-brilho-magenta);
    filter: blur(110px);
}

.vitrine-luz-3 {
    bottom: 0;
    left: 33.333333%;
    width: 20rem;
    height: 20rem;
    background: var(--vitrine-brilho-verde);
    filter: blur(64px);
}

.vitrine-faixa {
    position: relative;
    max-width: var(--vitrine-largura);
    margin-inline: auto;
    padding-inline: var(--e-6);
}

.vitrine-heroi-grade {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: center;
    gap: 3rem;
}

.vitrine-heroi-texto {
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.vitrine-heroi-selo {
    display: inline-flex;
    align-items: center;
    align-self: flex-start;
    gap: var(--e-2);
    margin-bottom: var(--e-6);
    padding: 0.375rem 0.875rem;
    border-radius: var(--raio-pilula);
    background: var(--vitrine-vidro);
    box-shadow: var(--vitrine-sombra-leve);
}

.vitrine-heroi-selo-brilho {
    font-size: var(--vitrine-corpo-md);
    line-height: 1.25rem;
}

.vitrine-heroi-selo-texto {
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--vitrine-menta);
}

.vitrine-heroi-titulo {
    margin-bottom: var(--e-6);
    font-size: var(--vitrine-titulo-xl);
    line-height: 1.12;
    font-weight: 800;
    letter-spacing: -0.025em;
    color: var(--branco);
}

.vitrine-heroi-texto-apoio {
    max-width: 36rem;
    margin-bottom: var(--e-8);
    font-size: var(--vitrine-corpo-lg);
    line-height: 1.625;
    font-weight: 500;
    color: var(--vitrine-lilas);
}

.vitrine-heroi-garantia {
    display: flex;
    align-items: center;
    gap: var(--e-2);
    margin-bottom: var(--e-10);
    font-size: var(--vitrine-corpo-sm);
    line-height: 1.125rem;
    color: var(--vitrine-lilas);
}

.vitrine-heroi-garantia .vitrine-icone {
    font-size: 18px;
    color: var(--vitrine-menta);
}

.vitrine-heroi-numeros {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-3);
    padding: var(--e-6) var(--e-4) var(--e-4);
    border-radius: var(--raio-lg);
    background: var(--vitrine-vidro-leve);
    list-style: none;
}

.vitrine-heroi-numeros li {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    font-size: var(--vitrine-corpo-sm);
    line-height: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    color: var(--branco);
}

.vitrine-heroi-numero-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: var(--e-8);
    height: var(--e-8);
    border-radius: var(--raio-sm);
    background: var(--vitrine-vidro);
}

.vitrine-heroi-numero-icone .vitrine-icone {
    font-size: 18px;
    color: var(--vitrine-menta);
}

/* O QUADRO DE EXEMPLO — só informativo: nada nele é clicável, e por isso nada
   nele muda sob o ponteiro (decisão de 2026-10-06). */
.vitrine-quadro-coluna {
    width: 100%;
}

.vitrine-quadro {
    position: relative;
    padding: var(--e-6);
    border-radius: var(--raio-lg);
    background: var(--vitrine-quadro);
    color: var(--vitrine-texto);
    box-shadow: var(--vitrine-quadro-sombra);
}

/* A faixa do cabeçalho do quadro desconta SEMPRE 24 px, inclusive quando o
   quadro passa a 28 px de respiro (a partir de 640): é o recuo de 4 px que o
   arquivo tem, medido na demo. */
.vitrine-quadro-cabeca {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin: calc(-1 * var(--e-6)) calc(-1 * var(--e-6)) var(--e-6);
    padding: var(--e-6) var(--e-6) var(--e-5);
    border-radius: var(--raio-lg) var(--raio-lg) 0 0;
    background: var(--vitrine-quadro-faixa);
}

.vitrine-quadro-ao-vivo {
    display: flex;
    align-items: center;
    gap: var(--e-3);
}

.vitrine-ponto {
    position: relative;
    display: flex;
    width: var(--e-3);
    height: var(--e-3);
}

.vitrine-ponto-onda {
    position: absolute;
    display: inline-flex;
    width: 100%;
    height: 100%;
    border-radius: var(--raio-pilula);
    background: var(--vitrine-menta-forte);
    opacity: 0.75;
    animation: vitrine-pulso 1s var(--curva-entrada) infinite;
}

.vitrine-ponto-miolo {
    position: relative;
    display: inline-flex;
    width: var(--e-3);
    height: var(--e-3);
    border-radius: var(--raio-pilula);
    background: var(--vitrine-verde);
}

@keyframes vitrine-pulso {
    75%,
    100% {
        transform: scale(2);
        opacity: 0;
    }
}

.vitrine-quadro-ao-vivo-texto {
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--vitrine-verde-texto);
}

.vitrine-quadro-festa {
    display: inline-flex;
    align-items: center;
    padding: var(--e-1) var(--e-3);
    border-radius: var(--raio-pilula);
    background: var(--vitrine-pastilha-roxa);
    color: var(--vitrine-tinta-roxa);
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 600;
    letter-spacing: 0.04em;
}

.vitrine-quadro-total {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: center;
    gap: var(--e-4);
    margin-bottom: var(--e-6);
    padding: var(--e-5);
    border-radius: var(--raio-md);
    background: var(--vitrine-quadro-placa);
}

.vitrine-quadro-rotulo {
    margin-bottom: var(--e-1);
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--vitrine-texto-suave);
}

.vitrine-quadro-numero {
    display: flex;
    align-items: baseline;
    gap: var(--e-2);
}

.vitrine-quadro-numero-valor {
    font-size: var(--vitrine-titulo-xl);
    line-height: 3rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--vitrine-texto-forte);
}

.vitrine-quadro-numero-unidade {
    font-size: var(--vitrine-titulo-sm);
    line-height: 1.5rem;
    font-weight: 700;
    color: var(--vitrine-roxo-claro);
}

.vitrine-quadro-legenda {
    font-size: var(--vitrine-corpo-sm);
    line-height: 1.125rem;
    color: var(--vitrine-texto-medio);
}

.vitrine-quadro-anel-coluna {
    display: flex;
}

.vitrine-quadro-anel {
    display: flex;
    align-items: center;
    gap: var(--e-3);
    padding: 0.625rem 0.875rem;
    border-radius: var(--raio-md);
    background: var(--vitrine-cartao);
    box-shadow: var(--vitrine-quadro-chip-sombra);
}

.vitrine-quadro-anel-desenho {
    width: 3rem;
    height: 3rem;
    transform: rotate(-90deg);
}

/* O trilho do anel é lilás nos DOIS modos, como no arquivo. */
.vitrine-quadro-anel-trilho {
    color: var(--vitrine-lilas);
}

.vitrine-quadro-anel-cheio {
    color: var(--vitrine-verde-texto);
}

.vitrine-quadro-anel-valor {
    font-size: var(--vitrine-titulo-sm);
    line-height: 1.5rem;
    font-weight: 800;
    color: var(--vitrine-texto);
}

.vitrine-quadro-anel-conta {
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--vitrine-texto-suave);
}

.vitrine-quadro-meta {
    margin-bottom: var(--e-6);
}

.vitrine-quadro-meta-linha {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--e-2);
    font-size: var(--vitrine-corpo-sm);
    line-height: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.01em;
}

.vitrine-quadro-meta-nome {
    color: var(--vitrine-texto-medio);
}

.vitrine-quadro-meta-valor {
    color: var(--vitrine-verde-texto);
}

.vitrine-quadro-barra {
    width: 100%;
    height: 0.625rem;
    overflow: hidden;
    border-radius: var(--raio-pilula);
    background: var(--vitrine-sutil);
}

/* Os 80% do exemplo moram na REGRA, e não num `style=""` (a política de
   conteúdo é `self`). */
.vitrine-quadro-barra-cheia {
    width: 80%;
    height: 100%;
    border-radius: var(--raio-pilula);
    background: var(--vitrine-verde);
}

.vitrine-quadro-lista {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    margin-bottom: var(--e-6);
    list-style: none;
}

.vitrine-quadro-linha {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--e-3);
    border-radius: var(--raio-md);
    background: var(--vitrine-quadro-faixa);
}

.vitrine-quadro-pessoa {
    display: flex;
    align-items: center;
    gap: var(--e-3);
    min-width: 0;
}

.vitrine-avatar {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--raio-pilula);
    font-size: var(--vitrine-corpo-md);
    line-height: 1.25rem;
    font-weight: 700;
}

.vitrine-avatar-roxo {
    background: var(--vitrine-pastilha-roxa);
    color: var(--vitrine-tinta-roxa);
}

.vitrine-avatar-violeta {
    background: var(--vitrine-violeta);
    color: var(--branco);
}

.vitrine-avatar-rosa {
    background: var(--vitrine-pastilha-rosa);
    color: var(--vitrine-tinta-rosa);
}

.vitrine-avatar-sutil {
    background: var(--vitrine-sutil);
    color: var(--vitrine-texto-suave);
}

.vitrine-quadro-pessoa-texto {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.vitrine-quadro-nome {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: var(--vitrine-corpo-md);
    line-height: 1.25rem;
    font-weight: 700;
    color: var(--vitrine-texto);
}

.vitrine-quadro-detalhe {
    font-size: var(--vitrine-miudo);
    line-height: 1rem;
    color: var(--vitrine-texto-suave);
}

.vitrine-quadro-estado {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    gap: var(--e-2);
}

.vitrine-selo {
    display: inline-flex;
    align-items: center;
    gap: var(--e-1);
    padding: var(--e-1) 0.625rem;
    border-radius: var(--raio-pilula);
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.04em;
}

.vitrine-selo .vitrine-icone {
    font-size: 14px;
}

.vitrine-selo-confirmado {
    background: var(--vitrine-pastilha-verde);
    color: var(--vitrine-selo-verde);
}

.vitrine-selo-aguardando {
    background: var(--vitrine-sutil);
    color: var(--vitrine-texto-suave);
    font-weight: 600;
}

.vitrine-quadro-hora {
    display: none;
    font-size: var(--vitrine-miudo);
    line-height: 1rem;
    color: var(--vitrine-texto-suave);
}

.vitrine-quadro-acoes {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--e-3);
    padding-top: var(--e-2);
}

/* "+ Convidado" e "Copiar Link": a aparência dos botões do arquivo, sem botão,
   sem clique e sem a cópia do `onclick` (decisão de 2026-10-06). */
.vitrine-quadro-acao {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    width: 100%;
    padding: 0.625rem var(--e-3);
    border-radius: var(--raio-md);
    font-size: var(--vitrine-corpo-sm);
    line-height: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    cursor: default;
    user-select: none;
}

.vitrine-quadro-acao .vitrine-icone {
    font-size: 18px;
}

.vitrine-quadro-acao-convidado {
    background: var(--vitrine-quadro-placa);
    color: var(--vitrine-roxo);
}

.vitrine-quadro-acao-link {
    background: var(--vitrine-verde);
    color: var(--branco);
    box-shadow: var(--vitrine-sombra-leve);
}

/* -----------------------------------------------------------------------------
   6. A CITAÇÃO
   -------------------------------------------------------------------------- */
.vitrine-citacao {
    padding: 3rem var(--e-6);
    background: var(--vitrine-sup-media);
}

.vitrine-citacao-cartao {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--e-6);
    max-width: 56rem;
    margin-inline: auto;
    padding: var(--e-8);
    border-radius: var(--raio-lg);
    background: var(--vitrine-cartao);
    box-shadow: var(--vitrine-cartao-sombra);
}

.vitrine-citacao-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: var(--raio-lg);
    background: var(--vitrine-pastilha-roxa);
    color: var(--vitrine-tinta-roxa);
}

.vitrine-citacao-icone .vitrine-icone {
    font-size: 32px;
}

.vitrine-citacao-frase {
    margin-bottom: var(--e-3);
    font-size: var(--vitrine-titulo-md);
    line-height: 1.375;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--vitrine-texto-forte);
}

.vitrine-citacao-texto {
    font-size: var(--vitrine-corpo-md);
    line-height: 1.625;
    color: var(--vitrine-texto-medio);
}

.vitrine-citacao-texto strong {
    font-weight: 700;
    color: var(--vitrine-roxo);
}

/* -----------------------------------------------------------------------------
   7. AS SEÇÕES — cabeça centrada, passos, vantagens, prazo, dúvidas e convite
   -----------------------------------------------------------------------------
   ⚠️ A CABEÇA DE SEÇÃO É CENTRADA, e não por descuido: é o desenho do arquivo,
   aprovado pelo usuário (TD-082). A borda esquerda única da página anterior
   (a trava L5) era uma decisão DAQUELA composição; ela continua guardando
   `.coluna-leitura`, que o admin e o painel usam.
   -------------------------------------------------------------------------- */
.vitrine-secao {
    max-width: var(--vitrine-largura);
    margin-inline: auto;
    padding: 5rem var(--e-6);
}

.vitrine-secao-cabeca {
    max-width: 42rem;
    margin: 0 auto 3.5rem;
    text-align: center;
}

.vitrine-secao-cabeca-funda {
    margin-bottom: var(--e-16);
}

.vitrine-sobrancelha {
    display: inline-block;
    margin-bottom: var(--e-3);
    padding: var(--e-1) var(--e-3);
    border-radius: var(--raio-pilula);
    background: var(--vitrine-pastilha-roxa-60);
    color: var(--vitrine-roxo);
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.vitrine-secao-titulo {
    margin-bottom: var(--e-4);
    font-size: var(--vitrine-titulo-xl);
    line-height: 3rem;
    font-weight: 800;
    letter-spacing: -0.025em;
    color: var(--vitrine-texto-forte);
}

.vitrine-secao-apoio {
    font-size: var(--vitrine-corpo-lg);
    line-height: 1.5rem;
    font-weight: 500;
    color: var(--vitrine-texto-medio);
}

.vitrine-cartao {
    border-radius: var(--raio-lg);
    background: var(--vitrine-cartao);
    box-shadow: var(--vitrine-cartao-sombra);
}

.vitrine-cartao-titulo {
    margin-bottom: var(--e-3);
    font-size: var(--vitrine-titulo-md);
    line-height: 1.625rem;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--vitrine-texto-forte);
}

.vitrine-cartao-texto {
    font-size: var(--vitrine-corpo-md);
    line-height: 1.625;
    color: var(--vitrine-texto-medio);
}

/* Os tons das pastilhas e dos ícones, com os nomes do trabalho que fazem. */
.vitrine-tom-roxo {
    background: var(--vitrine-pastilha-roxa);
    color: var(--vitrine-tinta-roxa);
}

.vitrine-tom-menta {
    background: var(--vitrine-pastilha-menta);
    color: var(--vitrine-tinta-menta);
}

.vitrine-tom-rosa {
    background: var(--vitrine-pastilha-rosa);
    color: var(--vitrine-tinta-rosa);
}

.vitrine-tom-verde {
    background: var(--vitrine-pastilha-verde);
    color: var(--vitrine-verde-texto);
}

.vitrine-cor-roxo {
    color: var(--vitrine-roxo);
}

.vitrine-cor-verde {
    color: var(--vitrine-verde-texto);
}

.vitrine-cor-rosa {
    color: var(--vitrine-rosa);
}

/* Os passos */
.vitrine-passos {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-8);
    margin-bottom: var(--e-10);
    list-style: none;
}

.vitrine-passo {
    display: flex;
    flex-direction: column;
    padding: var(--e-8);
    transition: transform var(--mov-rapido) var(--curva-padrao);
}

.vitrine-passo:hover {
    transform: translateY(-0.25rem);
}

.vitrine-passo-topo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--e-6);
}

.vitrine-passo-numero {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    border-radius: var(--raio-md);
    font-size: var(--vitrine-titulo-md);
    line-height: 1.625rem;
    font-weight: 800;
    letter-spacing: -0.015em;
}

.vitrine-passo-icone {
    font-size: 28px;
}

.vitrine-aviso {
    display: flex;
    align-items: center;
    gap: var(--e-4);
    width: 100%;
    padding: var(--e-5);
    border-radius: var(--raio-md);
    background: var(--vitrine-sup-alta);
    color: var(--vitrine-texto);
}

.vitrine-aviso-icone {
    flex-shrink: 0;
    font-size: 28px;
    color: var(--vitrine-roxo);
}

.vitrine-aviso-texto {
    font-size: var(--vitrine-corpo-md);
    line-height: 1.625;
}

.vitrine-aviso-texto strong {
    font-weight: 700;
    color: var(--vitrine-texto-forte);
}

/* As vantagens */
.vitrine-vantagens-secao {
    padding: 5rem var(--e-6);
    background: var(--vitrine-sup-baixa);
}

.vitrine-faixa-larga {
    max-width: var(--vitrine-largura);
    margin-inline: auto;
}

.vitrine-vantagens {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-6);
    list-style: none;
}

.vitrine-vantagem {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: var(--e-8);
}

.vitrine-vantagem-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    margin-bottom: var(--e-6);
    border-radius: var(--raio-md);
}

.vitrine-vantagem-icone .vitrine-icone {
    font-size: 26px;
}

/* O pé do cartão sangra até as bordas dele (os -32 px do arquivo). */
.vitrine-vantagem-pe {
    display: flex;
    align-items: center;
    gap: var(--e-2);
    margin: var(--e-6) calc(-1 * var(--e-8)) calc(-1 * var(--e-8));
    padding: var(--e-4) var(--e-8) 0.875rem;
    border-radius: 0 0 var(--raio-lg) var(--raio-lg);
    background: var(--vitrine-cartao-faixa);
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--vitrine-texto-forte);
}

.vitrine-vantagem-pe .vitrine-icone {
    font-size: 18px;
}

/* O prazo — a noite de novo, numa caixa só */
.vitrine-prazo-secao,
.vitrine-duvidas-secao {
    padding-block: var(--e-16);
}

/* `isolation` fecha a camada da caixa: o `z-index` do conteúdo vale só aqui
   dentro e nunca disputa com o topo fixo. */
.vitrine-prazo {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    padding: var(--e-8);
    border-radius: var(--raio-xl);
    background: var(--vitrine-noite);
    color: var(--branco);
    box-shadow: var(--vitrine-sombra-xl);
}

.vitrine-luz-prazo {
    right: -4rem;
    bottom: -4rem;
    width: 20rem;
    height: 20rem;
    background: var(--vitrine-brilho-roxo);
    filter: blur(64px);
}

.vitrine-prazo-conteudo {
    position: relative;
    z-index: 1;
    max-width: 48rem;
}

.vitrine-prazo-selo {
    display: inline-flex;
    align-items: center;
    gap: var(--e-2);
    margin-bottom: var(--e-4);
    padding: var(--e-1) var(--e-3);
    border-radius: var(--raio-pilula);
    background: var(--vitrine-vidro);
    color: var(--vitrine-menta);
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.04em;
}

.vitrine-prazo-selo .vitrine-icone {
    font-size: 16px;
}

.vitrine-prazo-titulo {
    margin-bottom: var(--e-4);
    font-size: var(--vitrine-titulo-lg);
    line-height: 2.25rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--branco);
}

.vitrine-prazo-texto {
    margin-bottom: var(--e-6);
    font-size: var(--vitrine-corpo-lg);
    line-height: 1.625;
    font-weight: 500;
    color: var(--vitrine-lilas);
}

.vitrine-prazo-texto strong {
    font-weight: 700;
}

.vitrine-prazo-itens {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--e-6);
    font-size: var(--vitrine-corpo-md);
    line-height: 1.25rem;
    color: var(--vitrine-lavanda);
    list-style: none;
}

.vitrine-prazo-itens li {
    display: flex;
    align-items: center;
    gap: var(--e-2);
}

.vitrine-prazo-itens .vitrine-icone {
    font-size: 18px;
    color: var(--vitrine-menta);
}

/* As dúvidas: `<details open>`, e a seta gira por CSS na direção do arquivo —
   aberta aponta para baixo; fechada, girada. */
.vitrine-duvidas {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: var(--e-6);
}

.vitrine-duvidas-coluna {
    display: flex;
    flex-direction: column;
    gap: var(--e-4);
}

.vitrine-duvida {
    padding: var(--e-6);
    border-radius: var(--raio-md);
    background: var(--vitrine-cartao);
    box-shadow: var(--vitrine-duvida-sombra);
}

.vitrine-duvida-pergunta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    font-size: var(--vitrine-titulo-sm);
    line-height: 1.5rem;
    font-weight: 700;
    text-align: left;
    color: var(--vitrine-texto-forte);
    cursor: pointer;
    list-style: none;
}

.vitrine-duvida-pergunta::-webkit-details-marker {
    display: none;
}

.vitrine-duvida-seta {
    color: var(--vitrine-roxo);
    transition: transform var(--mov-rapido) var(--curva-padrao);
}

.vitrine-duvida:not([open]) .vitrine-duvida-seta {
    transform: rotate(180deg);
}

.vitrine-duvida-resposta {
    margin-top: var(--e-3);
    font-size: var(--vitrine-corpo-md);
    line-height: 1.625;
    color: var(--vitrine-texto-medio);
}

/* O convite final — o degradê do arquivo, que é o mesmo nos dois modos */
.vitrine-convite-secao {
    padding: var(--e-16) var(--e-6);
    background: var(--vitrine-sup-baixa);
}

.vitrine-convite {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    max-width: 64rem;
    margin-inline: auto;
    padding: 2.5rem;
    border-radius: var(--raio-xl);
    background-image: linear-gradient(to bottom right, var(--vitrine-violeta), var(--vitrine-violeta-fundo), var(--vitrine-noite));
    color: var(--branco);
    text-align: center;
    box-shadow: var(--vitrine-sombra-convite);
}

.vitrine-convite-conteudo {
    position: relative;
    z-index: 1;
    max-width: 42rem;
    margin-inline: auto;
}

.vitrine-convite-selo {
    display: inline-block;
    margin-bottom: var(--e-6);
    padding: var(--e-1) var(--e-3);
    border-radius: var(--raio-pilula);
    background: var(--vitrine-vidro);
    color: var(--vitrine-menta);
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.vitrine-convite-titulo {
    margin-bottom: var(--e-6);
    font-size: var(--vitrine-titulo-xl);
    line-height: 3rem;
    font-weight: 800;
    letter-spacing: -0.025em;
    color: var(--branco);
}

.vitrine-convite-texto {
    margin-bottom: var(--e-8);
    font-size: var(--vitrine-corpo-lg);
    line-height: 1.625;
    font-weight: 500;
    color: var(--vitrine-lavanda-forte);
}

.vitrine-convite-itens {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--e-6);
    font-size: var(--vitrine-corpo-md);
    line-height: 1.25rem;
    color: var(--vitrine-lavanda-forte-80);
    list-style: none;
}

.vitrine-convite-itens li {
    display: flex;
    align-items: center;
    gap: 0.375rem;
}

.vitrine-convite-itens .vitrine-icone {
    font-size: 16px;
    color: var(--vitrine-menta);
}

/* -----------------------------------------------------------------------------
   8. O RODAPÉ (`inicio/_rodape.php`)
   -------------------------------------------------------------------------- */
.vitrine-rodape {
    margin-top: var(--e-10);
    background: var(--vitrine-sup-baixa);
    box-shadow: var(--vitrine-rodape-sombra);
}

.vitrine-rodape-faixa {
    max-width: var(--vitrine-largura);
    margin-inline: auto;
    padding: var(--e-16) var(--e-6);
}

.vitrine-rodape-grade {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-10);
}

.vitrine-rodape-logo {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin-bottom: var(--e-4);
}

/* As DUAS marcas do rodapé (ver `inicio/_rodape.php`): a classe de modo do
   `<html>` mostra uma e esconde a outra. */
.vitrine-marca-rodape {
    display: block;
    height: 2rem;
    width: auto;
}

.vitrine-marca-rodape-escuro {
    display: none;
}

:root.modo-escuro .vitrine-marca-rodape-claro {
    display: none;
}

:root.modo-escuro .vitrine-marca-rodape-escuro {
    display: block;
}

.vitrine-rodape-texto {
    margin-bottom: var(--e-6);
    font-size: var(--vitrine-corpo-sm);
    line-height: 1.625;
    color: var(--vitrine-texto-medio);
}

.vitrine-rodape-texto-curto {
    margin-bottom: var(--e-4);
}

.vitrine-rodape-selo {
    display: inline-flex;
    align-items: center;
    gap: var(--e-2);
    padding: 0.375rem var(--e-3);
    border-radius: var(--raio-pilula);
    background: var(--vitrine-pastilha-verde);
    color: var(--vitrine-selo-verde);
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.04em;
}

.vitrine-rodape-selo .vitrine-icone {
    font-size: 16px;
}

.vitrine-rodape-titulo {
    margin-bottom: var(--e-4);
    font-size: var(--vitrine-titulo-sm);
    line-height: 1.5rem;
    font-weight: 700;
    color: var(--vitrine-texto);
}

.vitrine-rodape-lista {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    font-size: var(--vitrine-corpo-sm);
    line-height: 1.125rem;
    list-style: none;
}

.vitrine-rodape-link {
    color: var(--vitrine-texto-medio);
    text-decoration: none;
    transition: color var(--mov-rapido) var(--curva-padrao);
}

a.vitrine-rodape-link:hover {
    color: var(--vitrine-texto-sob);
}

.vitrine-rodape-base {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-4);
    margin-top: 3rem;
    padding-top: var(--e-8);
}

.vitrine-rodape-direitos {
    font-size: var(--vitrine-corpo-sm);
    line-height: 1.125rem;
    color: var(--vitrine-texto-suave);
}

.vitrine-rodape-base-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--e-6);
    font-size: var(--vitrine-corpo-sm);
    line-height: 1.125rem;
    color: var(--vitrine-texto-suave);
}

.vitrine-rodape-base-link {
    color: var(--vitrine-texto-suave);
    text-decoration: none;
    transition: color var(--mov-rapido) var(--curva-padrao);
}

.vitrine-rodape-base-link:hover {
    color: var(--vitrine-texto-sob);
}

.vitrine-rodape-autor {
    display: flex;
    align-items: center;
    gap: var(--e-1);
}

.vitrine-rodape-autor-nome {
    font-weight: 600;
    color: var(--vitrine-texto-forte);
    transition: color var(--mov-rapido) var(--curva-padrao);
}

.vitrine-rodape-autor-nome:hover {
    color: var(--vitrine-roxo);
}

.vitrine-rodape-seguro {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    font-size: var(--vitrine-rotulo);
    line-height: 14px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--vitrine-texto-suave);
}

.vitrine-rodape-seguro .vitrine-icone {
    font-size: 14px;
    color: var(--vitrine-selo-verde-icone);
}

/* -----------------------------------------------------------------------------
   9. SEM MOVIMENTO
   -----------------------------------------------------------------------------
   Sai o que é decoração perpétua e deslocamento — a onda do ponto ao vivo, a
   subida do cartão e o giro da seta. Fica o que informa: a seta continua no
   lugar certo (quem a gira é a regra `[open]`, não a animação) e as cores sob o
   ponteiro continuam respondendo. As luzes desfocadas não se movem nunca.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .vitrine-ponto-onda {
        animation: none;
    }

    .vitrine-passo,
    .vitrine-duvida-seta {
        transition: none;
    }

    .vitrine-passo:hover {
        transform: none;
    }
}

/* =============================================================================
   O PAINEL DO DONO NO ARQUIVO DO STITCH (T-0038)
   =============================================================================
   O usuário trocou o painel do dono pelo desenho do arquivo do Stitch — três
   telas: o painel SEM festa, o painel COM festa e "criar evento" —, só visual,
   com a LOGO DE HOJE. Cada valor abaixo é a classe do Tailwind do `code.html`
   traduzida (tamanho, peso, espaçamento, raio, sombra e cor), com o
   `screen.png` como critério de aprovação.

   COMO O ARQUIVO VIROU FOLHA DA CASA:
     · Toda classe nova é `dono-*`. O cabeçalho e o rodapé (`.dono-topo`,
       `.dono-rodape`) vestem TODA tela de `layouts/painel` — login, cadastro,
       termos e o console do admin inclusive; o conteúdo só muda dentro de
       `.dono`, o invólucro que as seis telas do dono emitem.
     · A paleta é a família `--dono-*` do `:root` (o porquê está lá). Dentro de
       `.dono` os SEMÂNTICOS DA CASA são REAPONTADOS para ela (`--cor-texto`,
       `--cor-cartao`, `--f-corpo`…), que é como as telas que o arquivo não
       desenha — convidados, sugestões, galeria e o aviso de prazo — ganham a
       mesma linguagem sem uma regra por peça e sem mudar de arranjo. É a mesma
       mecânica dos `.visual-*` do convite (camada 2 redeclarada por pele).
     · As classes que são CONTRATO DE TESTE ficaram na marcação e são vestidas
       por `.dono .classe`: `palco-info`, `palco-titulo`, `palco-meta`,
       `palco-farol-num`, `palco-destinos`, `palco-destino`, `palco-campo`,
       `evento-abas`, `escolha-visual-*`, `medidor`. As regras-base delas não
       foram tocadas (há teste lendo o corpo de várias).
     · Ícones: a fonte do arquivo (Material Symbols), recortada em
       `Tema::ICONES_DO_PAINEL`; `.dono-icone` faz o que a classe do Google faz.

   ONDE A FOLHA SE AFASTA DO ARQUIVO, E POR QUÊ (todos medidos ou proibidos):
     · O cabeçalho é `sticky` e CHAPADO, sem o `backdrop-blur` e sem o alfa do
       arquivo: o desfoque é proibido nesta folha (caixa branca fantasma no
       Chromium, bug pago). Em repouso a cor é a mesma.
     · O mesmo vale para os `backdrop-blur` da banda e as luzes `blur-3xl`: as
       luzes viram `radial-gradient`, que pinta a mesma mancha sem filtro.
     · As letras dos CAMPOS ficam em 16 px abaixo de 64rem: abaixo de 16 px o iOS
       dá zoom sozinho no foco (BUG-TD-076). Da mesa para cima são as do arquivo.
     · Alvos de toque de 44 px no celular (o botão de modo, o `Sair`, os links
       do rodapé, o copiar pequeno e o "Escolher foto" ganham área invisível).
     · O placeholder é `--dono-texto-suave` (5,08:1) e não o `outline` do
       arquivo (#7a7487, 3,96:1): placeholder é texto e o piso é 4,5:1.
     · Os selos verdes são `#006c44` (6,01:1), o mesmo ajuste aprovado na
       vitrine, e não o `#138855` do arquivo (4,16:1).
   ============================================================================= */

/* -----------------------------------------------------------------------------
   1. O DOCUMENTO — o papel, a largura, a letra e o reapontamento da casa
   -------------------------------------------------------------------------- */
/* O papel do arquivo atrás das telas do dono. Sem `:has()` o navegador fica com
   o papel da casa, e nada some. */
body:has(.dono) {
    background-color: var(--dono-fundo);
    background-image: none;
}

/* `max-w-7xl` com `px-4 sm:px-6 lg:px-12`, como as três telas do arquivo. */
main.container:has(> .dono) {
    max-width: var(--dono-largura);
    padding-inline: var(--e-4);
}

.dono {
    padding-block: var(--e-8);
    font-family: var(--dono-letra);
    font-size: var(--dono-corpo-md);
    line-height: 1.5;
    color: var(--dono-texto);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;

    /* O REAPONTAMENTO: os semânticos da casa passam a ler a paleta do arquivo
       dentro das telas do dono. Fora de `.dono` nada muda. */
    --f-corpo: var(--dono-letra);
    --f-display: var(--dono-letra);
    --cor-texto: var(--dono-texto);
    --cor-texto-medio: var(--dono-texto-medio);
    --cor-texto-suave: var(--dono-texto-suave);
    --cor-cartao: var(--dono-cartao);
    --cor-borda: var(--dono-borda-cartao-cheia);
    --cor-acento: var(--dono-roxo);
    --acento-forte: var(--dono-roxo-sob);
    --acento-fundo: var(--dono-roxo);
    --cor-roxo-claro: var(--dono-sup-baixa);
    --cor-sob-ponteiro: var(--dono-sup-media);
    --sup-campo: var(--dono-sup-baixa);
    --sup-hover: var(--dono-sup-alta);
    --sup-press: var(--dono-sup-maxima);
    --tecla-fantasma: var(--dono-sup-media);
    --tecla-fantasma-hover: var(--dono-sup-alta);
    --raio-tecla: var(--raio-md);
    --raio-peca: var(--raio-lg);
    --elev-1: var(--dono-sombra-secao);
    --elev-2: var(--dono-sombra-media);
}

/* O anel da casa — `outline` e `outline-offset`, e mais nada. */
.dono-topo :focus-visible,
.dono-rodape :focus-visible,
.dono :focus-visible {
    outline: var(--foco-largura) solid var(--foco);
    outline-offset: var(--foco-desvio);
}

/* O ÍCONE — o que a classe `.material-symbols-outlined` do Google faz. A caixa
   é presa em 1em: antes de a fonte chegar (`display=block`), a ligadura não
   empurra o vizinho com a largura do NOME do ícone. */
.dono-icone {
    display: inline-block;
    flex: none;
    width: 1em;
    overflow: hidden;
    font-family: var(--dono-icones);
    font-weight: 400;
    font-style: normal;
    font-size: 1.25rem;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
}

.dono-icone-cheio {
    font-variation-settings: 'FILL' 1;
}

/* Visualmente oculto, e ainda lido e tabulável — NÃO é `.oculto`
   (`display: none`, que some para todo mundo). */
.dono-oculto,
.dono .foto-upload-campo input.dono-foto-arquivo {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* -----------------------------------------------------------------------------
   2. O CABEÇALHO — 80 px, a marca de hoje e as três ações do arquivo
   -------------------------------------------------------------------------- */
.dono-topo {
    position: sticky;
    top: 0;
    z-index: var(--z-cabecalho);
    background: var(--dono-fundo);
    border-bottom: 1px solid var(--dono-sutil);
    box-shadow: var(--dono-sombra-topo);
    font-family: var(--dono-letra);
}

.dono-topo-faixa {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-2);
    height: var(--dono-topo-altura);
    max-width: var(--dono-largura);
    margin-inline: auto;
    padding-inline: var(--e-4);
}

/* ⚠️ NO CONSOLE DO ADMIN O CABEÇALHO E O RODAPÉ ANDAM COM O `<main>`. A T-0031
   mediu três bordas esquerdas diferentes quando o `.container` do cabeçalho não
   acompanhava o do console (ver `.painel-largo:has(.cabine-corpo) .container`),
   e o cabeçalho do arquivo tem faixa própria (`max-w-7xl`). Aqui ela volta à
   largura e ao recuo do contêiner do console: 1440px e 16px, como antes. */
.painel-largo:has(.cabine-corpo) :is(.dono-topo-faixa, .dono-rodape-faixa) {
    max-width: 1440px;
    padding-inline: var(--e-4);
}

.dono-topo .logo {
    display: flex;
    align-items: center;
    min-width: 0;
    min-height: var(--alvo-toque);
}

/* A marca de HOJE (`logo-img`, o gancho do `app.js`). 30 px no celular, como
   a vitrine decidiu (a conta da faixa de 360 px fecha com ela) e 36 px a partir
   de 40rem, que é o piso da `marca.md` §5.1. Nunca achatada. */
.dono-topo .logo-img {
    height: 30px;
    width: auto;
    max-width: 100%;
    object-fit: contain;
    object-position: left center;
}

.dono-topo-acoes {
    display: flex;
    align-items: center;
    gap: var(--e-1);
    flex-shrink: 0;
}

/* O botão de modo do arquivo: o quadrado arredondado com a lua. Os glifos (lua
   e sol) são os da casa, trocados pela classe do `<html>` (`.modo-glifo-*`). */
.dono-modo {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--alvo-toque);
    height: var(--alvo-toque);
    padding: 0;
    border: 0;
    border-radius: var(--raio-md);
    background: var(--dono-sup-media);
    color: var(--dono-texto-medio);
    box-shadow: var(--dono-sombra-leve);
    cursor: pointer;
    transition:
        background-color var(--mov-rapido) var(--curva-padrao),
        color var(--mov-rapido) var(--curva-padrao);
}

.dono-modo:hover {
    background: var(--dono-sup-alta);
    color: var(--dono-texto);
}

.dono-topo-link {
    display: inline-flex;
    align-items: center;
    min-height: var(--alvo-toque);
    padding: var(--e-2) var(--e-3);
    border-radius: var(--raio-md);
    font-size: var(--dono-corpo-md);
    line-height: 1.25rem;
    font-weight: 600;
    color: var(--dono-texto-medio);
    text-decoration: none;
    white-space: nowrap;
    transition:
        background-color var(--mov-rapido) var(--curva-padrao),
        color var(--mov-rapido) var(--curva-padrao);
}

.dono-topo-link:hover {
    color: var(--dono-roxo);
    background: var(--dono-sup-media);
}

.dono-topo-filete {
    display: none;
    width: 1px;
    height: 1.25rem;
    background: var(--dono-sup-maxima);
}

.dono-sair {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.375rem;
    min-width: var(--alvo-toque);
    min-height: var(--alvo-toque);
    padding: var(--e-2) var(--e-3);
    border: 0;
    border-radius: var(--raio-md);
    background: none;
    font-family: inherit;
    font-size: var(--dono-corpo-md);
    line-height: 1.25rem;
    font-weight: 600;
    color: var(--dono-erro);
    cursor: pointer;
    transition:
        background-color var(--mov-rapido) var(--curva-padrao),
        color var(--mov-rapido) var(--curva-padrao);
}

.dono-sair .dono-icone {
    font-size: 1.125rem;
}

.dono-sair:hover {
    background: var(--dono-erro-sob);
    color: var(--dono-erro-sob-tinta);
}

/* No celular o rótulo sai do OLHO e fica para o leitor de tela (o arquivo usa
   `hidden sm:inline`, que tiraria o nome do botão). */
.dono-sair-rotulo {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* -----------------------------------------------------------------------------
   3. O RODAPÉ — o direito autoral, os Termos (CA-133) e o crédito
   -------------------------------------------------------------------------- */
.dono-rodape {
    background: var(--dono-sup-baixa);
    border-top: 1px solid var(--dono-sutil);
    box-shadow: var(--dono-sombra-rodape);
    font-family: var(--dono-letra);
}

.dono-rodape-faixa {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-2);
    max-width: var(--dono-largura);
    margin-inline: auto;
    padding: var(--e-8) var(--e-4);
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    color: var(--dono-texto-suave);
    text-align: center;
}

.dono-rodape-faixa p {
    margin: 0;
}

.dono-rodape-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    column-gap: var(--e-6);
}

.dono-rodape a {
    display: inline-flex;
    align-items: center;
    min-height: var(--alvo-toque);
    color: inherit;
    text-decoration: none;
    transition: color var(--mov-rapido) var(--curva-padrao);
}

.dono-rodape .rodape-termos a {
    font-weight: 500;
}

.dono-rodape .desenvolvido a {
    font-weight: 700;
    color: var(--dono-texto);
}

.dono-rodape a:hover {
    color: var(--dono-roxo);
}

/* O ponto só existe com os dois links na MESMA linha (40rem): no celular eles
   se empilham, e o ponto ficaria pendurado no fim da primeira. */
.dono-rodape-ponto {
    display: none;
    color: var(--dono-tracejado);
}

/* -----------------------------------------------------------------------------
   4. AS PEÇAS QUE SE REPETEM — tecla, pastilha, rótulo, chip, cartão
   -------------------------------------------------------------------------- */
.dono-tecla {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.625rem;
    border: 0;
    border-radius: var(--raio-md);
    font-family: inherit;
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition:
        background-color var(--mov-rapido) var(--curva-padrao),
        box-shadow var(--mov-rapido) var(--curva-padrao),
        transform var(--mov-rapido) var(--curva-padrao),
        color var(--mov-rapido) var(--curva-padrao);
}

.dono-tecla-cheia {
    background: var(--dono-violeta);
    color: var(--branco);
    box-shadow: var(--dono-sombra-tecla);
}

.dono-tecla-cheia:hover {
    background: var(--dono-violeta-fundo);
    box-shadow: var(--dono-sombra-tecla-sob);
    transform: translateY(-2px);
}

.dono-tecla-cheia:active {
    transform: none;
}

.dono-tecla-criar {
    align-self: flex-start;
    min-height: var(--alvo-toque);
    padding: 0.875rem var(--e-6);
}

.dono-tecla-criar .dono-icone {
    transition: transform 300ms var(--curva-padrao);
}

.dono-tecla-criar:hover .dono-icone {
    transform: rotate(90deg);
}

.dono-tecla-grande {
    gap: var(--e-3);
    width: 100%;
    min-width: 17.5rem;
    padding: var(--e-4) var(--e-8);
    box-shadow: var(--dono-sombra-tecla-grande);
}

.dono-tecla-grande:hover {
    box-shadow: var(--dono-sombra-tecla-grande-sob);
}

.dono-tecla-suave {
    gap: 0.375rem;
    min-height: var(--alvo-toque);
    padding: 0.625rem var(--e-4);
    background: var(--dono-sup-media);
    color: var(--dono-texto-medio);
}

.dono-tecla-suave .dono-icone {
    font-size: 1.125rem;
}

/* FALAR COM SUPORTE — visível, apagado, sem clique (decisão do usuário, T-0038;
   o mesmo tratamento do "Planos" da vitrine). `--dono-texto-suave` sobre
   `--dono-sup-media` mede 4,83:1. */
.dono-indisponivel {
    cursor: default;
    user-select: none;
    color: var(--dono-texto-suave);
}

.dono-selo-breve {
    padding: 2px var(--e-2);
    border-radius: var(--raio-pilula);
    background: var(--dono-pastilha-roxa);
    color: var(--dono-tinta-roxa);
    font-size: var(--dono-rotulo);
    line-height: 0.875rem;
    font-weight: 700;
    letter-spacing: 0.04em;
}

/* O "Painel" de volta do arquivo, e o mesmo desenho para o botão secundário das
   telas que o arquivo não desenha. */
.dono-tecla-voltar,
.dono .btn-secundario {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--e-2);
    min-height: var(--alvo-toque);
    padding: 0.625rem var(--e-4);
    border: 0;
    border-radius: var(--raio-md);
    background: var(--dono-sup-media);
    color: var(--dono-texto);
    font-family: inherit;
    font-size: var(--dono-corpo-md);
    line-height: 1.25rem;
    font-weight: 600;
    text-decoration: none;
    box-shadow: var(--dono-sombra-leve);
    transition:
        background-color var(--mov-rapido) var(--curva-padrao),
        transform var(--mov-rapido) var(--curva-padrao);
}

.dono-tecla-voltar:hover,
.dono .btn-secundario:hover {
    background: var(--dono-sup-alta);
    transform: translateY(-2px);
}

.dono-tecla-voltar .dono-icone {
    font-size: 1.125rem;
}

/* O botão cheio da casa (`.btn`) dentro das telas do dono: o violeta do arquivo
   (`bg-primary`, `hover:bg-primary-container`) com tinta branca, nos DOIS modos —
   o mesmo pigmento do "Criar evento" do painel. Sem isto o reapontamento de
   `--cor-acento` o pintaria de lilás no escuro, e a tela teria dois botões cheios
   de cores diferentes. Branco sobre ele: 9,31:1 (e 6,42:1 sob o ponteiro). */
.dono .btn {
    background: var(--dono-violeta-fundo);
    color: var(--branco);
    min-height: 3rem;
    padding: 0.875rem var(--e-8);
    border-radius: var(--raio-md);
    font-family: inherit;
    font-size: var(--dono-corpo-md);
    font-weight: 700;
    box-shadow: var(--dono-sombra-salvar);
}

.dono .btn:hover {
    background: var(--dono-violeta);
    box-shadow: var(--dono-sombra-salvar-sob);
}

.dono .btn:active {
    background: var(--dono-violeta-fundo);
}

/* O "Link da galeria" (`.convite-link`) tem fundo escrito à mão na regra-base
   (um degradê claro, débito conhecido do F8). Dentro de `.dono` ele lê o papel do
   arquivo, e é isso que o faz existir no escuro: lá o degradê claro deixava o
   rótulo, que gira com o modo, claro sobre claro. */
.dono .convite-link {
    background: var(--dono-sup-baixa);
    border-radius: var(--raio-md);
}

.dono .btn .dono-icone {
    font-size: 1.125rem;
}

.dono-pastilha {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 3rem;
    height: 3rem;
    border-radius: var(--raio-md);
}

.dono-pastilha .dono-icone {
    font-size: 1.5rem;
}

.dono-pastilha .ico {
    width: 1.25rem;
    height: 1.25rem;
}

.dono-pastilha-roxa {
    background: var(--dono-pastilha-roxa);
    color: var(--dono-roxo);
}

.dono-pastilha-neutra {
    border-radius: var(--raio-lg);
    background: var(--dono-sup-alta);
    color: var(--dono-roxo);
}

.dono-tinta-roxa {
    color: var(--dono-roxo);
}

.dono-tinta-verde {
    color: var(--dono-verde);
}

.dono-tinta-rosa {
    color: var(--dono-rosa-vivo);
}

.dono-rotulo {
    font-size: var(--dono-rotulo);
    line-height: 0.875rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--dono-texto-suave);
}

.dono-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--e-1);
    padding: 0.125rem 0.625rem;
    border-radius: var(--raio-pilula);
    font-size: var(--dono-rotulo);
    line-height: 0.875rem;
    font-weight: 700;
    letter-spacing: 0.04em;
}

.dono-chip .dono-icone {
    font-size: 0.8125rem;
}

.dono-cartao {
    border-radius: var(--raio-lg);
    background: var(--dono-cartao);
}

.dono-secao-titulo {
    font-size: var(--dono-titulo-md);
    line-height: 1.625rem;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--dono-texto-forte);
}

.dono-secao-titulo-icone {
    display: flex;
    align-items: center;
    gap: var(--e-2);
}

.dono-secao-titulo-icone .dono-icone {
    font-size: 1.375rem;
}

.dono-secao-topo {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-2) var(--e-4);
}

.dono-secao-apoio {
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    color: var(--dono-texto-suave);
}

/* O cabeçalho das telas (o `.painel-cabecalho` da casa, na escala do arquivo:
   `text-3xl lg:text-4xl font-extrabold tracking-tight`). */
.dono .painel-cabecalho {
    display: flex;
    flex-direction: column;
    gap: var(--e-4);
    margin: 0 0 var(--e-8);
}

.dono .painel-cabecalho h1 {
    font-family: inherit;
    font-size: 1.875rem;
    line-height: 2.25rem;
    font-weight: 800;
    letter-spacing: -0.025em;
    color: var(--dono-texto);
}

.dono .painel-cabecalho .subtitulo {
    margin: 0;
    font-size: var(--dono-corpo-md);
    line-height: 1.25rem;
    color: var(--dono-texto-suave);
}

.dono .painel-cabecalho .btn-secundario,
.dono-tecla-voltar {
    align-self: flex-start;
}

/* "Criar evento": a pastilha do bolo AO LADO da manchete, e a linha de apoio
   embaixo das duas. */
.dono-cabecalho-texto {
    display: flex;
    flex-direction: column;
    gap: var(--e-1);
}

.dono-cabecalho-linha {
    display: flex;
    align-items: center;
    gap: var(--e-3);
}

.dono-pastilha-titulo {
    width: 2.5rem;
    height: 2.5rem;
    box-shadow: var(--dono-sombra-leve);
}

/* Os avisos da casa (erro, sucesso, aviso) no raio e na letra do arquivo. */
.dono .alerta {
    border-radius: var(--raio-lg);
    padding: var(--e-4) var(--e-5);
    font-size: var(--dono-corpo-md);
}

.dono .painel-status {
    border-radius: var(--raio-md);
}

/* -----------------------------------------------------------------------------
   5. O PAINEL — a saudação, o aviso de sucesso e a coluna
   -------------------------------------------------------------------------- */
.dono-com-festa,
.dono-sem-festa {
    display: flex;
    flex-direction: column;
    gap: var(--e-8);
}

/* SEM festa a tela é a coluna `max-w-5xl` centrada do arquivo. */
.dono-sem-festa {
    max-width: 64rem;
    margin-inline: auto;
}

.dono .dono-saudacao {
    gap: var(--e-4);
    margin: 0;
}

.dono-com-festa .dono-saudacao {
    padding-top: var(--e-2);
}

.dono-saudacao-texto {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
}

.dono .dono-saudacao h1 {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--e-2);
    font-size: var(--dono-titulo-lg);
    line-height: 2.25rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--dono-texto-forte);
}

.dono-com-festa .dono-saudacao .subtitulo {
    font-size: var(--dono-corpo-lg);
    line-height: 1.5rem;
    font-weight: 500;
}

/* O aceno da casa no lugar do 👋 (TD-076). Âmbar, a cor quente da paleta, e
   três saltos — não infinito como o `animate-bounce` do arquivo. */
.dono-aceno {
    width: 1.625rem;
    height: 1.625rem;
    color: var(--ambar);
    animation: dono-aceno 1s 3;
}

@keyframes dono-aceno {
    0%,
    100% {
        transform: translateY(-25%);
        animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
    }

    50% {
        transform: none;
        animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
    }
}

/* O AVISO DE SUCESSO (`?criado=1` e os outros três). */
.dono-aviso {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-4);
    padding: var(--e-4);
    border-radius: var(--raio-lg);
    background: var(--dono-pastilha-verde);
    box-shadow: var(--dono-sombra-leve);
}

.dono-aviso-corpo {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    min-width: 0;
}

.dono-aviso-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--raio-md);
    background: var(--dono-menta);
    color: var(--dono-menta-tinta);
    box-shadow: var(--dono-sombra-leve);
}

.dono-aviso-icone .dono-icone {
    font-size: 1.375rem;
}

/* O aviso ESTRUTURADO (T-0038, segunda passada): o título em destaque com o selo
   "Novo" ao lado, e a linha de apoio embaixo (`space-y-0.5` do arquivo). */
.dono-aviso-textos {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.dono .dono-aviso-texto {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--e-2);
    font-size: var(--dono-titulo-sm);
    line-height: 1.5rem;
    font-weight: 700;
    color: var(--dono-verde);
    overflow-wrap: anywhere;
}

/* O selo "Novo": 11 px, negrito, maiúsculas, pílula, fundo `secondary/10`. A
   tinta é `#006c44` e não o `#138855` do arquivo — o MESMO ajuste dos selos
   verdes da vitrine: o do arquivo mede 3,59:1 sobre o selo, e este 5,20:1. */
.dono-aviso-selo {
    display: inline-flex;
    align-items: center;
    padding: 0.125rem var(--e-2);
    border-radius: var(--raio-pilula);
    background: var(--dono-verde-10);
    color: var(--dono-verde);
    font-size: var(--dono-rotulo);
    line-height: 1rem;
    font-weight: 700;
    letter-spacing: 0.025em;
    text-transform: uppercase;
}

.dono .dono-aviso-linha {
    font-size: var(--dono-corpo-md);
    line-height: 1.3125rem;
    font-weight: 400;
    color: var(--dono-aviso-linha);
    overflow-wrap: anywhere;
}

.dono-aviso-fechar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: var(--alvo-toque);
    height: var(--alvo-toque);
    border: 0;
    border-radius: var(--raio-md);
    background: none;
    color: var(--dono-verde);
    cursor: pointer;
    transition: background-color var(--mov-rapido) var(--curva-padrao);
}

.dono-aviso-fechar:hover {
    background: var(--dono-verde-10);
}

.dono-aviso-fechar[hidden],
.dono-foto-escolhida[hidden],
.dono-farol-selo[hidden] {
    display: none;
}

/* -----------------------------------------------------------------------------
   6. SEM FESTA — o cartão de boas-vindas, a conta e os três passos
   -------------------------------------------------------------------------- */
/* As duas luzes do arquivo (`blur-3xl`) como gradiente radial: a mesma mancha,
   sem filtro nenhum. */
.dono-vazio {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--e-8);
    border-radius: var(--raio-lg);
    background-color: var(--dono-cartao);
    background-image:
        radial-gradient(circle at 4rem 3rem, var(--dono-luz-roxa) 0, var(--dono-luz-roxa) 5rem, transparent 13rem),
        radial-gradient(circle at calc(100% - 4rem) calc(100% - 3rem), var(--dono-luz-menta) 0, var(--dono-luz-menta) 5rem, transparent 13rem);
    box-shadow: var(--dono-sombra-cartao);
    text-align: center;
}

.dono-vazio-miolo {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    max-width: 36rem;
}

.dono-vazio-selo {
    position: relative;
    margin-bottom: var(--e-6);
}

.dono-vazio-bolo {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 5rem;
    height: 5rem;
    border-radius: var(--raio-lg);
    background: var(--dono-sup-media);
    color: var(--dono-roxo);
    box-shadow: var(--dono-sombra-leve);
}

.dono-vazio-bolo .dono-icone {
    font-size: 2.5rem;
}

.dono-vazio-selinho {
    position: absolute;
    right: -0.375rem;
    bottom: -0.375rem;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--raio-sm);
    background: var(--dono-pastilha-menta);
    color: var(--dono-tinta-menta);
    box-shadow: var(--dono-sombra-leve);
}

.dono-vazio-selinho .dono-icone {
    font-size: 1rem;
}

.dono-vazio-rotulo {
    margin-bottom: var(--e-2);
    letter-spacing: 0.1em;
    color: var(--dono-roxo);
}

.dono .dono-vazio-titulo {
    margin-bottom: var(--e-3);
    font-size: var(--dono-titulo-lg);
    line-height: 2.25rem;
    font-weight: 700;
    letter-spacing: -0.025em;
    color: var(--dono-texto-forte);
}

.dono .dono-vazio-texto {
    margin-bottom: var(--e-8);
    font-size: var(--dono-corpo-md);
    line-height: 1.625;
    color: var(--dono-texto-suave);
}

/* `mt-10 pt-8` e `py-3.5` no arquivo: o `pt-8` vence o `py-3.5` em cima, e o
   embaixo fica nos 14 px. */
.dono-vazio-garantias {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--e-3);
    width: 100%;
    margin-top: var(--e-10);
    padding: var(--e-8) var(--e-4) 0.875rem;
    border-radius: var(--raio-md);
    background: var(--dono-sup-baixa-60);
}

.dono .dono-vazio-garantia {
    display: flex;
    align-items: center;
    gap: var(--e-2);
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    font-weight: 500;
    color: var(--dono-texto);
}

.dono-vazio-garantia .dono-icone {
    font-size: 1.125rem;
}

.dono-vazio-ponto {
    display: none;
    font-weight: 700;
    color: var(--dono-tracejado);
}

.dono-conta-sem-festa {
    display: flex;
    flex-direction: column;
    gap: var(--e-3);
}

.dono .dono-conta-rotulo {
    padding-inline: var(--e-1);
}

/* O cartão da conta: a faixa violeta de 6 px na borda esquerda. */
.dono-conta-cartao {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--e-6);
    padding: var(--e-6);
    box-shadow: var(--dono-sombra-cartao);
}

.dono-conta-cartao::before {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 0.375rem;
    background: var(--dono-violeta);
}

.dono-conta-info {
    display: flex;
    align-items: flex-start;
    gap: var(--e-4);
    padding-left: var(--e-2);
}

.dono-conta-texto {
    display: flex;
    flex-direction: column;
    gap: var(--e-1);
    min-width: 0;
}

.dono .dono-conta-linha {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--e-2);
}

.dono-conta-titulo {
    font-size: var(--dono-titulo-sm);
    line-height: 1.5rem;
    font-weight: 700;
    color: var(--dono-texto-forte);
}

.dono-chip-estado {
    background: var(--dono-pastilha-verde);
    color: var(--dono-verde);
}

.dono-estado-alerta .dono-chip-estado {
    background: var(--pastilha-ambar);
    color: var(--ambar);
}

.dono-estado-encerrado .dono-chip-estado {
    background: var(--pastilha-rosa);
    color: var(--rosa);
}

.dono .dono-conta-frase {
    font-size: var(--dono-corpo-md);
    line-height: 1.3125rem;
    color: var(--dono-texto-suave);
}

.dono-conta-acoes {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--e-3);
    flex-shrink: 0;
    padding-left: var(--e-2);
}

.dono-passos {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-5);
    margin: 0;
    padding: 0;
    list-style: none;
}

.dono-passo {
    display: flex;
    flex-direction: column;
    gap: var(--e-3);
    padding: var(--e-6);
    border-radius: var(--raio-lg);
    background: var(--dono-sup-baixa);
}

.dono-passo-numero {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: var(--raio-sm);
    background: var(--dono-sup-maxima);
    color: var(--dono-roxo);
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.01em;
}

.dono .dono-passo-titulo {
    font-size: var(--dono-titulo-sm);
    line-height: 1.5rem;
    font-weight: 700;
    color: var(--dono-texto-forte);
}

.dono .dono-passo-texto {
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    color: var(--dono-texto-suave);
}

/* -----------------------------------------------------------------------------
   7. A FESTA — o canhoto do arquivo: a banda, o bilhete, o farol e o picote
   -------------------------------------------------------------------------- */
/* O degradê e as duas luzes do arquivo; o `--foco` vira branco aqui dentro,
   porque o anel da casa sumiria contra a banda. */
.dono-palco {
    position: relative;
    overflow: hidden;
    border-radius: var(--raio-xl);
    background-color: var(--dono-palco-meio);
    background-image:
        radial-gradient(circle at calc(100% - 4rem) 4rem, var(--dono-palco-luz-roxa) 0, var(--dono-palco-luz-roxa) 8rem, transparent 16rem),
        radial-gradient(circle at 4rem calc(100% - 4rem), var(--dono-palco-luz-rosa) 0, var(--dono-palco-luz-rosa) 6rem, transparent 14rem),
        linear-gradient(to bottom right, var(--dono-palco-inicio), var(--dono-palco-meio), var(--dono-palco-fim));
    box-shadow: var(--dono-sombra-palco);
    color: var(--branco);
    --foco: var(--branco);
}

.dono-palco-corpo {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-items: center;
    gap: var(--e-8);
    padding: var(--e-6);
}

.dono-palco-festa {
    display: flex;
    flex-direction: column;
    gap: var(--e-6);
    min-width: 0;
}

.dono-palco-chips {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--e-3);
}

.dono-palco-rotulo {
    padding: var(--e-1) var(--e-3);
    border-radius: 0.375rem;
    background: var(--dono-palco-vidro);
    color: var(--branco);
    font-size: var(--dono-rotulo);
    line-height: 0.875rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.dono-palco-contagem {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: var(--e-1) var(--e-3);
    border-radius: var(--raio-pilula);
    background: var(--dono-menta-20);
    color: var(--dono-menta);
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.01em;
}

.dono-palco-contagem .dono-icone {
    font-size: 1rem;
}

.dono-palco-identidade {
    display: flex;
    flex-direction: column;
    gap: var(--e-5);
}

/* O BILHETE: papel BRANCO SÓLIDO na banda escura (BUG-TD-055), nos dois modos. */
.dono .dono-bilhete {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    flex: none;
    width: 5rem;
    height: 6rem;
    padding: var(--e-2);
    border-radius: var(--raio-lg);
    background: var(--branco);
    color: var(--dono-bilhete-tinta);
    box-shadow: var(--dono-sombra-bilhete);
}

.dono-bilhete-mes {
    padding-top: var(--e-1);
    font-size: var(--dono-rotulo);
    line-height: 0.875rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--dono-violeta-fundo);
}

.dono-bilhete-dia {
    margin-top: calc(-1 * var(--e-1));
    font-size: var(--dono-titulo-xl);
    line-height: 1;
    font-weight: 800;
    letter-spacing: -0.05em;
}

.dono-bilhete-ano {
    padding-bottom: var(--e-1);
    font-size: var(--dono-rotulo);
    line-height: 0.875rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--dono-bilhete-ano);
}

.dono .palco-info {
    display: flex;
    flex-direction: column;
    gap: var(--e-2);
}

/* O título da festa: `headline-xl` no celular, 34 px a partir de 40rem. O
   recorte em três linhas da regra-base fica (é decisão da T-0016 para dado
   longo); só a letra e a cor são do arquivo. */
.dono .palco-titulo {
    font-family: inherit;
    font-size: var(--dono-titulo-xl);
    line-height: 3rem;
    font-weight: 800;
    letter-spacing: -0.025em;
    color: var(--branco);
}

.dono .palco-meta {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-3);
    margin: 0;
    padding: var(--e-2) 0 0;
    list-style: none;
    font-size: inherit;
    line-height: inherit;
    color: inherit;
}

.dono-palco-dado {
    display: flex;
    align-items: flex-start;
    gap: var(--e-3);
    min-width: 0;
    padding: 0.875rem;
    border-radius: var(--raio-md);
    background: var(--dono-palco-vidro-leve);
}

.dono-palco-dado-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 2rem;
    height: 2rem;
    border-radius: var(--raio-sm);
    background: var(--dono-palco-vidro);
    color: var(--dono-menta);
}

.dono-palco-dado-icone .dono-icone {
    font-size: 1.125rem;
}

.dono-palco-dado-texto {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.dono-palco-dado-rotulo {
    font-size: var(--dono-rotulo);
    line-height: 0.875rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--dono-palco-tinta-60);
}

.dono-palco-dado-valor {
    font-size: var(--dono-corpo-md);
    line-height: 1.3125rem;
    font-weight: 500;
    color: var(--branco);
}

/* `porExtenso()` escreve o dia da semana em minúscula ("sexta-feira"); o
   arquivo começa a linha com maiúscula. */
.dono-palco-data::first-letter {
    text-transform: uppercase;
}

.dono-palco-dado-extra {
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    color: var(--dono-palco-tinta-70);
}

/* PESSOAS NA FESTA — a caixa da direita. */
.dono-farol {
    display: flex;
    flex-direction: column;
    gap: var(--e-5);
    min-width: 0;
    padding: var(--e-6);
    border-radius: var(--raio-lg);
    background: var(--dono-farol-fundo);
    box-shadow: var(--dono-sombra-interna);
}

.dono-farol-topo {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-3);
}

.dono .dono-farol-rotulo {
    display: flex;
    align-items: center;
    gap: var(--e-2);
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--dono-palco-tinta-70);
}

.dono-farol-rotulo .dono-icone {
    font-size: 1.125rem;
    color: var(--dono-menta);
}

.dono-farol-selo {
    display: inline-flex;
    align-items: center;
    padding: 0.125rem 0.625rem;
    border-radius: var(--raio-pilula);
    background: var(--dono-menta-15);
    color: var(--dono-menta);
    font-size: var(--dono-miudo);
    line-height: 1rem;
    font-weight: 700;
}

.dono-farol-numero {
    display: flex;
    align-items: baseline;
    gap: var(--e-3);
}

.dono .palco-farol-num {
    margin: 0;
    font-family: inherit;
    font-size: 3.75rem;
    line-height: 1;
    font-weight: 800;
    letter-spacing: -0.025em;
    font-variant-numeric: tabular-nums;
    color: var(--branco);
}

.dono-farol-numero-texto {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.dono .dono-farol-frase {
    font-size: var(--dono-titulo-sm);
    line-height: 1.5rem;
    font-weight: 700;
    color: var(--branco);
}

.dono .dono-farol-obs {
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    color: var(--dono-palco-tinta-60);
}

.dono-farol-regua {
    display: flex;
    flex-direction: column;
    gap: var(--e-2);
    padding-top: var(--e-2);
}

.dono .dono-farol-conta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-3);
    font-size: var(--dono-miudo);
    line-height: 1rem;
    font-weight: 500;
    color: var(--dono-palco-tinta-80);
}

.dono-farol-percentual {
    font-weight: 700;
    color: var(--dono-menta);
}

/* A régua: `.barra` + `<span data-progresso>`, o gancho do `app.js`, na forma
   do arquivo (trilho de 12 px com 2 px de folga e o verde com brilho). */
.dono .dono-farol-barra {
    height: 0.75rem;
    padding: 0.125rem;
    border-radius: var(--raio-pilula);
    background: var(--dono-palco-vidro-forte);
}

.dono .dono-farol-barra span {
    min-width: 8px;
    background: var(--palco-menta);
    box-shadow: var(--dono-menta-brilho);
}

.dono-farol-legenda {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-2) var(--e-4);
    margin: 0;
    padding: var(--e-2) 0 0;
    list-style: none;
    font-size: var(--dono-miudo);
    line-height: 1rem;
    color: var(--dono-palco-tinta-60);
}

.dono-farol-item {
    display: flex;
    align-items: center;
    gap: 0.375rem;
}

.dono-farol-item::before {
    content: '';
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--dono-menta);
}

.dono-farol-item-pendentes::before {
    background: var(--dono-palco-ponto);
}

.dono-farol-item-recusados::before {
    background: var(--dono-erro-ponto);
}

/* O PICOTE — as duas mordidas na cor do papel e a linha tracejada. */
.dono-picote {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.dono-picote-mordida {
    flex: none;
    width: 1.75rem;
    height: 2.5rem;
    background: var(--dono-fundo);
}

.dono-picote-esquerda {
    margin-left: calc(-1 * var(--e-3));
    border-radius: 0 var(--raio-pilula) var(--raio-pilula) 0;
}

.dono-picote-direita {
    margin-right: calc(-1 * var(--e-3));
    border-radius: var(--raio-pilula) 0 0 var(--raio-pilula);
}

.dono-picote-linha {
    flex: 1;
    margin-inline: var(--e-2);
    border-bottom: 2px dashed var(--dono-palco-picote);
}

/* O PÉ DO CANHOTO — o link do convite. */
.dono-palco-pe {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--e-4);
    padding: var(--e-6);
    background: var(--dono-palco-pe);
}

.dono-palco-link-texto {
    display: flex;
    flex-direction: column;
    gap: var(--e-1);
}

.dono-palco-link-rotulo {
    display: flex;
    align-items: center;
    gap: var(--e-2);
    font-size: var(--dono-titulo-sm);
    line-height: 1.5rem;
    font-weight: 700;
    color: var(--branco);
}

.dono-palco-link-rotulo .dono-icone {
    color: var(--dono-menta);
}

.dono .dono-palco-link-apoio {
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    color: var(--dono-palco-tinta-70);
}

.dono .dono-palco-link-linha {
    display: flex;
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 0.625rem;
    width: 100%;
    max-width: 36rem;
}

.dono-palco-campo-caixa {
    position: relative;
    flex: 1;
    min-width: 0;
}

.dono .palco-campo {
    width: 100%;
    height: 3rem;
    min-height: 3rem;
    padding: 0 2.75rem 0 var(--e-4);
    border: 0;
    border-radius: var(--raio-md);
    background: var(--dono-palco-vidro);
    color: var(--branco);
    font-family: inherit;
    font-size: var(--dono-corpo-lg);
    font-weight: 400;
}

.dono .palco-campo:focus {
    background: var(--dono-palco-vidro-forte);
}

/* O copiar pequeno de dentro do campo: 32 px de desenho e 44 de alvo. */
.dono-palco-copiar-mini {
    position: absolute;
    top: var(--e-2);
    right: var(--e-2);
    display: flex;
    align-items: center;
    justify-content: center;
    height: 2rem;
    padding: 0 0.625rem;
    border: 0;
    border-radius: var(--raio-sm);
    background: var(--dono-palco-vidro-forte);
    color: var(--branco);
    cursor: pointer;
    transition: background-color var(--mov-rapido) var(--curva-padrao);
}

.dono-palco-copiar-mini::after {
    content: '';
    position: absolute;
    inset: -0.375rem;
}

.dono-palco-copiar-mini:hover {
    background: var(--dono-palco-vidro-sob);
}

.dono-palco-copiar-mini .dono-icone {
    font-size: 1rem;
}

.dono-palco-tecla {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--e-2);
    height: 3rem;
    padding: 0 var(--e-6);
    border: 0;
    border-radius: var(--raio-md);
    font-family: inherit;
    font-size: var(--dono-titulo-sm);
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition:
        background-color var(--mov-rapido) var(--curva-padrao),
        color var(--mov-rapido) var(--curva-padrao);
}

.dono-palco-tecla-clara {
    background: var(--branco);
    color: var(--dono-bilhete-tinta);
    box-shadow: var(--dono-sombra-papel);
}

.dono-palco-tecla-clara .dono-icone {
    color: var(--dono-violeta-fundo);
}

.dono-palco-tecla-clara:hover {
    background: var(--palco-papel-toque);
}

/* "Copiado!" — a classe é posta pelo `app.js` por dois segundos. */
.dono-palco-tecla-clara.copiado,
.dono-palco-tecla-clara.copiado .dono-icone {
    color: var(--dono-verde-papel);
}

.dono-palco-tecla-vazada {
    padding: 0 var(--e-5);
    background: transparent;
    color: var(--branco);
}

.dono-palco-tecla-vazada:hover {
    background: var(--dono-palco-vidro);
}

/* O olho do arquivo em `::before`: a âncora `Ver o convite` é contrato de teste
   (o texto encosta no `<a>`), então o ícone não pode ser filho dela. O texto
   alternativo vazio (`/ ''`) tira o NOME do ícone do nome acessível onde o
   navegador entende a sintaxe; onde não entende, vale a primeira declaração. */
.dono-ver-convite::before {
    content: 'visibility';
    content: 'visibility' / '';
    display: inline-block;
    width: 1em;
    overflow: hidden;
    font-family: var(--dono-icones);
    font-size: 1.25rem;
    font-weight: 400;
    line-height: 1;
    font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
}

/* -----------------------------------------------------------------------------
   8. AÇÕES DA FESTA — os quatro destinos em cartão
   -------------------------------------------------------------------------- */
.dono-acoes {
    display: flex;
    flex-direction: column;
    gap: var(--e-4);
}

.dono .palco-destinos {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-4);
    margin: 0;
}

/* Cada destino veste a tinta dele por variável: a pastilha, a chamada e o
   título sob o ponteiro leem a mesma `--destino-tinta`. */
.dono-destino {
    position: relative;
    display: flex;
    flex-direction: column;
    padding: var(--e-5);
    border-radius: var(--raio-lg);
    background: var(--dono-cartao);
    box-shadow: var(--dono-sombra-leve);
    transition:
        box-shadow var(--mov-medio) var(--curva-padrao),
        transform var(--mov-medio) var(--curva-padrao);
    --destino-tinta: var(--dono-roxo);
    --destino-icone: var(--dono-roxo);
    --destino-pastilha: var(--dono-roxo-10);
    --destino-sob: var(--tinta-viva);
}

.dono-destino:hover {
    box-shadow: var(--dono-sombra-media);
    transform: translateY(-4px);
}

.dono-destino-rosa {
    --destino-tinta: var(--dono-rosa);
    --destino-icone: var(--dono-rosa);
    --destino-pastilha: var(--dono-rosa-10);
}

.dono-destino-verde {
    --destino-tinta: var(--dono-verde);
    --destino-icone: var(--dono-verde);
    --destino-pastilha: var(--dono-menta-30);
}

.dono-destino-neutro {
    --destino-tinta: var(--dono-texto);
    --destino-icone: var(--dono-texto-medio);
    --destino-pastilha: var(--dono-sup-maxima);
    --destino-sob: var(--dono-fundo);
}

.dono-destino-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    border-radius: var(--raio-md);
    background: var(--destino-pastilha);
    color: var(--destino-icone);
    transition:
        background-color var(--mov-medio) var(--curva-padrao),
        color var(--mov-medio) var(--curva-padrao);
}

.dono-destino-icone .dono-icone {
    font-size: 1.625rem;
}

.dono-destino:hover .dono-destino-icone {
    background: var(--destino-tinta);
    color: var(--destino-sob);
}

.dono .dono-destino-titulo {
    margin-top: var(--e-4);
    font-size: var(--dono-titulo-sm);
    line-height: 1.5rem;
    font-weight: 700;
}

/* O LINK é só o título (o nome acessível do destino), e o `::after` dele cobre
   o cartão inteiro — é ele que leva o clique e desenha o anel de foco. */
.dono .palco-destino {
    display: inline;
    min-height: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    color: var(--dono-texto-forte);
    font: inherit;
    text-decoration: none;
    transition: color var(--mov-medio) var(--curva-padrao);
}

.dono .palco-destino::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: var(--raio-lg);
}

.dono .palco-destino:hover {
    transform: none;
    background: none;
    box-shadow: none;
}

.dono .palco-destino:focus-visible {
    outline: none;
}

.dono .palco-destino:focus-visible::after {
    outline: var(--foco-largura) solid var(--foco);
    outline-offset: var(--foco-desvio);
}

.dono-destino:hover .palco-destino {
    color: var(--destino-tinta);
}

.dono .dono-destino-texto {
    margin-top: var(--e-1);
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    color: var(--dono-texto-suave);
}

.dono-destino-chamada {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: auto;
    padding-top: var(--e-8);
    font-size: var(--dono-titulo-sm);
    line-height: 1.5rem;
    font-weight: 700;
    color: var(--destino-tinta);
}

.dono-destino-chamada .dono-icone {
    font-size: 1.125rem;
    transition: transform var(--mov-rapido) var(--curva-padrao);
}

.dono-destino:hover .dono-destino-chamada .dono-icone {
    transform: translateX(4px);
}

/* -----------------------------------------------------------------------------
   9. A SUA CONTA & ARMAZENAMENTO, e a ZONA DE EXCLUSÃO
   -------------------------------------------------------------------------- */
.dono-conta {
    display: flex;
    flex-direction: column;
    gap: var(--e-4);
    padding-top: var(--e-4);
}

.dono-conta-grade {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-4);
}

/* Na galeria a peça da cota vem antes de outro bloco, e o respiro é dela (a
   `.painel-status` que ela substituiu tinha o mesmo `margin-bottom`); dentro da
   grade da conta quem separa é o `gap`. */
.dono-cota {
    margin-bottom: var(--e-4);
}

.dono-conta-grade > .dono-cartao {
    margin-bottom: 0;
}

.dono-ciclo,
.dono-cota {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--e-4);
    padding: var(--e-6);
    box-shadow: var(--dono-sombra-leve);
}

.dono-cartao-linha {
    display: flex;
    align-items: flex-start;
    gap: var(--e-4);
}

.dono-cartao-texto {
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: var(--e-1);
    min-width: 0;
}

.dono .dono-cartao-destaque {
    font-size: var(--dono-corpo-lg);
    line-height: 1.5rem;
    font-weight: 600;
    color: var(--dono-texto-forte);
    overflow-wrap: anywhere;
}

.dono .dono-cartao-apoio {
    font-size: var(--dono-corpo-sm);
    line-height: 1.4;
    color: var(--dono-texto-suave);
}

/* O AVISO da cota (80 % e cheio, TD-084): a frase da §6 por extenso, embaixo
   da linha de ocupação — é o lugar dela no arranjo do arquivo. */
.dono .dono-cota-aviso {
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    font-weight: 700;
    overflow-wrap: anywhere;
}

/* O estado do ciclo e da cota pinta a FRASE — quem carrega a informação. */
.dono .dono-estado-alerta .dono-ciclo-frase,
.dono .dono-cota-alerta .dono-cota-aviso,
.dono .dono-cota-alerta .dono-cota-uso {
    color: var(--ambar);
}

.dono .dono-estado-encerrado .dono-ciclo-frase,
.dono .dono-cota-cheio .dono-cota-aviso,
.dono .dono-cota-cheio .dono-cota-uso {
    color: var(--rosa);
}

.dono .dono-cartao-nota {
    display: flex;
    align-items: center;
    gap: var(--e-2);
    padding: var(--e-3);
    border-radius: var(--raio-md);
    background: var(--dono-sup-baixa);
    font-size: var(--dono-miudo);
    line-height: 1rem;
    color: var(--dono-texto-suave);
}

.dono-cartao-nota .dono-icone {
    font-size: 1rem;
}

.dono-cota-topo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--e-3);
}

.dono .dono-cota-uso {
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    color: var(--dono-verde);
}

.dono-cota-regua {
    display: flex;
    flex-direction: column;
    gap: var(--e-2);
}

/* A régua da cota no desenho do arquivo: trilho de 12 px com folga de 2 px e o
   preenchimento roxo — sem as marcas de dez em dez da régua da casa. */
.dono .dono-cota .medidor {
    height: 0.75rem;
    padding: 0.125rem;
    border: 0;
    background-color: var(--dono-sup-maxima);
    background-image: none;
}

.dono .dono-cota .medidor::-webkit-progress-bar {
    background-color: transparent;
    background-image: none;
}

.dono .dono-cota .medidor-normal::-webkit-progress-value {
    background: var(--dono-roxo);
}

.dono .dono-cota .medidor-normal::-moz-progress-bar {
    background: var(--dono-roxo);
}

.dono .dono-cota-escala {
    display: flex;
    justify-content: space-between;
    gap: var(--e-2);
    font-size: var(--dono-miudo);
    line-height: 1rem;
    color: var(--dono-texto-suave);
}

.dono-perigo {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--e-4);
    margin: var(--e-6) 0 3rem;
    padding: var(--e-6);
    border-radius: var(--raio-lg);
    background: var(--dono-perigo-zona);
}

.dono-perigo-texto {
    display: flex;
    align-items: flex-start;
    gap: 0.875rem;
}

.dono-perigo-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--raio-md);
    background: var(--dono-erro-40);
    color: var(--dono-erro);
}

.dono .dono-perigo-titulo {
    font-size: var(--dono-titulo-sm);
    line-height: 1.5rem;
    font-weight: 700;
    color: var(--dono-texto-forte);
}

/* `max-w-2xl` (42rem) do arquivo — não é a medida de leitura da casa
   (`--medida`, 38rem), que continua declarada uma vez só. */
.dono .dono-perigo-aviso {
    max-width: 42rem;
    margin-top: var(--e-1);
    font-size: var(--dono-corpo-sm);
    line-height: 1.125rem;
    color: var(--dono-texto-suave);
}

.dono-perigo-tecla {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--e-2);
    width: 100%;
    min-height: var(--alvo-toque);
    padding: 0 var(--e-5);
    border: 0;
    border-radius: var(--raio-md);
    background: var(--dono-erro-10);
    color: var(--dono-erro);
    font-family: inherit;
    font-size: var(--dono-titulo-sm);
    font-weight: 700;
    cursor: pointer;
    transition:
        background-color var(--mov-medio) var(--curva-padrao),
        color var(--mov-medio) var(--curva-padrao);
}

.dono-perigo-tecla .dono-icone {
    font-size: 1.125rem;
}

.dono-perigo-tecla:hover {
    background: var(--dono-erro);
    color: var(--dono-erro-cheio-tinta);
}

/* -----------------------------------------------------------------------------
   10. OS FORMULÁRIOS — criar/editar evento e as telas irmãs
   -------------------------------------------------------------------------- */
.dono .evento-abas {
    gap: var(--e-2);
    margin-bottom: var(--e-8);
}

/* As abas no desenho do menu do arquivo: a ativa é o preenchimento violeta
   com sombra; as outras são texto que ganha superfície sob o ponteiro. */
.dono .evento-aba {
    display: inline-flex;
    align-items: center;
    min-height: var(--alvo-toque);
    padding: var(--e-2) var(--e-4);
    border: 0;
    border-radius: var(--raio-md);
    background: transparent;
    color: var(--dono-texto-medio);
    font-family: inherit;
    font-size: var(--dono-corpo-sm);
    font-weight: 700;
    letter-spacing: 0.01em;
}

.dono .evento-aba:hover {
    background: var(--dono-sup-media);
    color: var(--dono-texto);
}

.dono .evento-aba.ativa {
    background: var(--dono-violeta);
    color: var(--branco);
    box-shadow: var(--dono-sombra-aba);
}

/* ⚠️ O `overflow: hidden` DA REGRA-BASE FICA, e não por estética: é ele que zera o
   piso automático (`min-width: auto`) do cartão como item de grade. Medido na
   galeria a 360 px: com `overflow: visible` o cartão subia ao conteúdo mínimo
   (416 px) e a página rolava de lado. */
.dono .form-secao {
    display: flex;
    flex-direction: column;
    gap: var(--e-4);
    min-width: 0;
    padding: var(--e-6);
    border: 1px solid var(--dono-borda-cartao);
    border-radius: var(--raio-lg);
    background: var(--dono-cartao);
    box-shadow: var(--dono-sombra-secao);
}

.dono .secao-cab {
    padding: 0 0 var(--e-3);
    border-bottom: 1px solid var(--dono-sutil);
    background: none;
    text-align: left;
}

.dono .secao-cab h2 {
    font-family: inherit;
    font-size: 1.125rem;
    line-height: 1.75rem;
    font-weight: 700;
    letter-spacing: 0;
    color: var(--dono-texto);
}

.dono .secao-cab p {
    margin: 0;
    font-size: var(--dono-miudo);
    line-height: 1rem;
    color: var(--dono-texto-suave);
}

.dono .secao-corpo {
    padding: 0;
}

.dono-secao-cab {
    display: flex;
    align-items: flex-start;
    gap: var(--e-3);
}

.dono-secao-cab .dono-pastilha {
    width: 2.5rem;
    height: 2.5rem;
}

.dono-secao-cab .dono-pastilha .dono-icone {
    font-size: 1.375rem;
}

.dono-secao-cab-texto {
    flex: 1;
    min-width: 0;
}

.dono .dono-secao-cab .opcional {
    flex: none;
}

/* "Dados do evento" tem o cabeçalho maior do arquivo (`text-xl`, pastilha de
   44 px, `items-center`). */
.dono .dono-secao-dados {
    gap: var(--e-6);
}

.dono .dono-secao-dados .dono-secao-cab {
    align-items: center;
    gap: 0.875rem;
    padding-bottom: var(--e-4);
}

.dono-secao-dados .dono-secao-cab .dono-pastilha {
    width: 2.75rem;
    height: 2.75rem;
}

.dono-secao-dados .dono-pastilha .ico,
.dono-pastilha-titulo .ico {
    width: 1.5rem;
    height: 1.5rem;
}

.dono .dono-secao-dados .secao-cab h2 {
    font-size: var(--dono-titulo-md);
}

.dono-evento .secao-corpo {
    display: flex;
    flex-direction: column;
    gap: var(--e-5);
}

.dono-evento .campo {
    margin: 0;
}

.dono .campo > label:not(.campo-checkbox) {
    display: flex;
    align-items: center;
    gap: var(--e-1);
    margin-bottom: 0.375rem;
    font-size: var(--dono-corpo-md);
    line-height: 1.25rem;
    font-weight: 700;
    color: var(--dono-texto);
}

/* O chip "OPCIONAL" do arquivo, à direita do rótulo. */
.dono .opcional {
    margin-left: auto;
    padding: 0.125rem var(--e-2);
    border-radius: 0.25rem;
    background: var(--dono-sutil);
    color: var(--dono-texto-suave);
    font-size: var(--dono-rotulo);
    line-height: 1rem;
    font-weight: 600;
    letter-spacing: 0.02em;
}

.dono-obrigatorio {
    color: var(--dono-erro);
}

/* OS CAMPOS do arquivo: poço lilás sem borda, 48 px, raio de 12 px, e o anel
   roxo com o fundo branco no foco. 16 px de letra abaixo de 64rem (iOS). */
.dono .campo :is(input, select, textarea):not([type="checkbox"], [type="radio"], [type="file"]) {
    width: 100%;
    min-height: 3rem;
    padding: 0 var(--e-4);
    border: 0;
    border-radius: var(--raio-md);
    background: var(--dono-sup-baixa);
    color: var(--dono-texto);
    font-family: inherit;
    font-size: var(--dono-corpo-lg);
    font-weight: 400;
    box-shadow: var(--dono-sombra-leve);
    transition:
        background-color var(--mov-rapido) var(--curva-padrao),
        outline-color var(--mov-rapido) var(--curva-padrao);
}

.dono .campo textarea {
    padding: var(--e-4);
    line-height: 1.5;
    resize: none;
}

.dono .campo :is(input, select, textarea):not([type="checkbox"], [type="radio"], [type="file"]):focus {
    outline: 2px solid var(--dono-roxo);
    outline-offset: 0;
    border-color: transparent;
    background: var(--dono-cartao);
    box-shadow: var(--dono-sombra-leve);
}

.dono .campo :is(input, textarea)::placeholder {
    color: var(--dono-texto-suave);
    font-weight: 400;
    opacity: 1;
}

.dono .campo small,
.dono .campo-dica {
    margin-top: 0.375rem;
    font-size: var(--dono-miudo);
    line-height: 1rem;
    color: var(--dono-texto-suave);
}

.dono-campo-com-icone {
    position: relative;
    display: flex;
    align-items: center;
}

.dono-campo-com-icone .dono-icone {
    position: absolute;
    left: 0.875rem;
    color: var(--dono-texto-suave);
    pointer-events: none;
}

.dono .campo .dono-campo-com-icone input {
    padding-left: 2.75rem;
}

.dono .campo-curto input {
    max-width: none;
}

.dono-evento .campo-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-5) var(--e-4);
}

/* O PIX (`text-xs`, campos de 44 px, `grid-cols-12` com 5 + 7). */
.dono .dono-pix-grade {
    gap: var(--e-3);
}

.dono .dono-pix-grade .campo > label {
    margin-bottom: var(--e-1);
    font-size: var(--dono-miudo);
    line-height: 1rem;
}

.dono .dono-pix-grade .campo :is(input, select) {
    min-height: var(--alvo-toque);
    padding-inline: var(--e-3);
}

.dono .dono-pix-grade .campo select {
    font-weight: 500;
}

.dono .dono-dica-icone {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    margin-top: 0;
    font-size: var(--dono-rotulo);
}

.dono-dica-icone .dono-icone {
    font-size: 0.875rem;
}

.dono .dono-caixa-dica {
    display: block;
    margin-top: 0;
    padding: var(--e-3);
    border: 1px solid var(--dono-sutil);
    border-radius: var(--raio-md);
    background: var(--dono-sup-baixa);
    font-size: var(--dono-miudo);
    line-height: 1.625;
}

/* O dress code do arquivo: rótulo e campo em `text-xs`, dica em 11 px. */
.dono .dono-secao-dress .campo > label {
    font-size: var(--dono-miudo);
    line-height: 1rem;
}

.dono .dono-secao-dress .campo textarea {
    padding: 0.875rem;
    line-height: 1.625;
}

.dono .dono-secao-dress .campo small {
    font-size: var(--dono-rotulo);
}

/* O PRAZO E O MANUAL DO CONVIDADO (T-0037) — duas peças que o arquivo do
   Stitch não desenha, vestidas na mesma linguagem: o campo "Confirmar até" é
   um campo como os vizinhos (só ganhou a linha de erro ao lado dele), e o
   manual é uma lista de caixas no formato dos cartões do tema — borda de 1 px,
   o escolhido com o segundo pixel por sombra interna (o cartão não pula) e o
   ícone da casa numa pastilha lilás.
   CONTRASTE (claro · escuro): o texto da opção é `--dono-texto` sobre
   `--dono-cartao` (17,18 · 15,48); a linha de erro é `--dono-erro` sobre o
   cartão (6,46 · 10,33); o ícone na pastilha é `--dono-roxo` (decorativo). */
.dono .campo .dono-campo-erro {
    display: block;
    font-weight: 600;
    color: var(--dono-erro);
}

/* O campo recusado ganha o fio vermelho por dentro. A especificidade é a da
   regra dos campos do arquivo (0,3,1), e esta vem depois dela: vence. */
.dono .campo input[aria-invalid="true"] {
    box-shadow: inset 0 0 0 1.5px var(--dono-erro);
}

/* A grade se conta sozinha (`auto-fit`, sem breakpoint novo): uma coluna no
   celular, duas na coluna larga da mesa. */
.dono .dono-manual {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: var(--e-2);
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

/* A OPÇÃO INTEIRA É O ALVO: a etiqueta embrulha a caixa, então tocar no texto
   ou no ícone marca. Altura mínima de `--alvo-toque`. */
.dono .dono-manual-opcao {
    display: flex;
    align-items: center;
    gap: var(--e-3);
    min-height: var(--alvo-toque);
    padding: 0.625rem 0.875rem;
    border: 1px solid var(--dono-borda-cartao-cheia);
    border-radius: var(--raio-md);
    background: var(--dono-cartao);
    box-shadow: var(--dono-sombra-leve);
    color: var(--dono-texto);
    font-size: var(--dono-corpo-sm);
    line-height: 1.25rem;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
    transition:
        border-color var(--mov-rapido) var(--curva-padrao),
        box-shadow var(--mov-rapido) var(--curva-padrao);
}

.dono .dono-manual-opcao:hover {
    border-color: var(--dono-pastilha-roxa-sob);
    box-shadow: var(--dono-sombra-media);
}

/* Marcada, a opção ganha a borda roxa. A cor não é o único sinal: o visto da
   caixa continua sendo o indicador. */
.dono .dono-manual-opcao:has(input:checked) {
    border-color: var(--dono-roxo);
    box-shadow: inset 0 0 0 1px var(--dono-roxo), var(--dono-sombra-leve);
}

.dono .dono-manual-opcao input[type="checkbox"] {
    flex: none;
    width: 1.125rem;
    height: 1.125rem;
    margin: 0;
    accent-color: var(--dono-roxo);
    cursor: pointer;
}

.dono .dono-manual-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: none;
    width: 2rem;
    height: 2rem;
    border-radius: var(--raio-sm);
    background: var(--dono-pastilha-roxa);
    color: var(--dono-roxo);
}

.dono .dono-manual-icone .ico {
    width: 1.125rem;
    height: 1.125rem;
}

.dono .dono-manual-texto {
    min-width: 0;
    overflow-wrap: break-word;
}

/* O TEMA DO CONVITE — os dois cartões do arquivo. A miniatura continua sendo
   desenhada pelos tokens do VISUAL (é a cor real do convite, não a do
   exemplo); o selo "✓ Escolhido" vai para a linha do nome, como no arquivo, por
   grade — sem mudar a ordem do DOM (ele é `aria-hidden`). O escolhido ganha o
   segundo pixel de borda por sombra interna, para o cartão não pular. */
.dono .escolha-visual {
    grid-template-columns: minmax(0, 1fr);
    max-width: none;
    gap: 0.875rem;
}

.dono .escolha-visual-card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
        "miniatura miniatura"
        "nome marca"
        "pecas pecas";
    align-items: center;
    align-content: start;
    gap: 0.625rem var(--e-2);
    height: 100%;
    padding: 0.875rem;
    border: 1px solid var(--dono-borda-cartao-cheia);
    border-radius: var(--raio-md);
    background: var(--dono-cartao);
    box-shadow: var(--dono-sombra-leve);
    text-align: left;
    transition:
        border-color var(--mov-rapido) var(--curva-padrao),
        box-shadow var(--mov-rapido) var(--curva-padrao);
}

.dono .escolha-visual-opcao:hover .escolha-visual-card {
    border-color: var(--dono-pastilha-roxa-sob);
    box-shadow: var(--dono-sombra-media);
}

.dono .escolha-visual-opcao input:checked + .escolha-visual-card {
    border-color: var(--dono-roxo);
    background: var(--dono-cartao);
    box-shadow: inset 0 0 0 1px var(--dono-roxo), var(--dono-sombra-leve);
}

.dono .escolha-visual-miniatura {
    grid-area: miniatura;
    height: 5rem;
    border-radius: var(--raio-sm);
}

.dono .escolha-visual-nome {
    grid-area: nome;
    font-size: var(--dono-corpo-md);
    line-height: 1.25rem;
    font-weight: 700;
    text-align: left;
    color: var(--dono-texto);
}

/* No arquivo o selo só existe no cartão escolhido, e o nome do outro usa a
   linha inteira ("Princesa e Sapo" numa linha só). Aqui ele sai do arranjo
   (`display`) em vez de só sumir do olho (`visibility`, a regra-base): o nome
   não perde largura para um selo que não está lá. */
.dono .escolha-visual-marca {
    display: none;
    grid-area: marca;
    padding: 0.125rem var(--e-2);
    border-radius: var(--raio-pilula);
    background: var(--dono-pastilha-verde);
    color: var(--dono-verde);
    font-size: var(--dono-rotulo);
    line-height: 1rem;
    font-weight: 700;
    letter-spacing: 0;
}

.dono .escolha-visual-opcao input:checked + .escolha-visual-card .escolha-visual-marca {
    display: inline-flex;
}

.dono .escolha-visual-pecas {
    grid-area: pecas;
    gap: 0.125rem;
}

.dono .escolha-visual-peca {
    font-size: var(--dono-miudo);
    line-height: 1rem;
    font-weight: 400;
    color: var(--dono-texto-suave);
}

.dono .escolha-visual-peca::before {
    content: '• ';
    content: '• ' / '';
}

.dono .escolha-visual-peca-rotulo {
    font-weight: 400;
    color: inherit;
}

.dono .escolha-visual-apoio {
    margin: 0;
    padding: var(--e-3);
    border: 1px solid var(--dono-sutil);
    border-radius: var(--raio-md);
    background: var(--dono-sup-baixa);
    font-size: var(--dono-miudo);
    line-height: 1.625;
    color: var(--dono-texto-suave);
}

/* A FOTO — a caixa tracejada, o retrato com o "+" e o botão "Escolher foto". */
.dono .dono-foto {
    flex-direction: row;
    align-items: center;
    gap: var(--e-4);
    padding: var(--e-4);
    border: 1px dashed var(--dono-tracejado);
    border-radius: var(--raio-md);
    background: var(--dono-sup-baixa);
    text-align: left;
}

.dono-foto-avatar {
    position: relative;
    flex: none;
}

.dono .dono-foto .foto-perfil-previa {
    width: 4rem;
    height: 4rem;
    border: 2px solid var(--branco);
    box-shadow: var(--dono-sombra-papel);
}

.dono .dono-foto .foto-placeholder {
    background: var(--dono-sup-alta);
    color: var(--dono-texto-suave);
}

.dono-foto-mais {
    position: absolute;
    right: calc(-1 * var(--e-1));
    bottom: calc(-1 * var(--e-1));
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.25rem;
    height: 1.25rem;
    border-radius: 50%;
    background: var(--dono-verde-papel);
    color: var(--branco);
    box-shadow: var(--dono-sombra-papel);
}

.dono-foto-mais .dono-icone {
    font-size: 0.75rem;
}

.dono .dono-foto-campo {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.375rem;
    width: auto;
}

/* 28 px de desenho, 44 de alvo (o `::after` invisível). */
.dono-foto-escolher {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: var(--e-2);
    padding: 0.375rem 0.875rem;
    border-radius: var(--raio-sm);
    background: var(--dono-violeta-fundo);
    color: var(--branco);
    font-size: var(--dono-miudo);
    line-height: 1rem;
    font-weight: 700;
    box-shadow: var(--dono-sombra-leve);
    cursor: pointer;
    transition: background-color var(--mov-rapido) var(--curva-padrao);
}

.dono-foto-escolher::after {
    content: '';
    position: absolute;
    inset: calc(-1 * var(--e-2)) 0;
}

.dono-foto-escolher:hover {
    background: var(--dono-violeta);
}

.dono-foto-escolher .dono-icone {
    font-size: 1rem;
}

.dono-foto-arquivo:focus-visible + .dono-foto-escolher {
    outline: var(--foco-largura) solid var(--foco);
    outline-offset: var(--foco-desvio);
}

.dono-foto-formatos,
.dono-foto-escolhida {
    font-size: var(--dono-rotulo);
    line-height: 1rem;
    color: var(--dono-texto-suave);
}

.dono-foto-escolhida {
    font-weight: 600;
    color: var(--dono-texto);
    overflow-wrap: anywhere;
}

/* AS DUAS COLUNAS (64rem) e o rodapé do formulário. */
.dono .dono-grade-evento {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-8);
}

/* GRADE, e não `flex` em coluna: item de grade com `overflow: hidden` (o cartão)
   não empurra a trilha com o conteúdo mínimo dele; item de flex empurra. Medido
   na galeria a 360 px: em `flex` a coluna subia a 416 px e a página rolava de
   lado. */
.dono-coluna-principal,
.dono .coluna-lado {
    display: grid;
    align-content: start;
    gap: var(--e-6);
    min-width: 0;
}

.dono .dono-form-acoes {
    flex-direction: column-reverse;
    align-items: stretch;
    gap: var(--e-3);
    margin-top: var(--e-10);
    padding-top: var(--e-4);
    border-top: 1px solid var(--dono-sutil);
}

.dono .form-acoes .btn-secundario {
    padding: 0.875rem var(--e-6);
    background: var(--dono-sup-media);
    color: var(--dono-texto-medio);
    font-weight: 700;
    box-shadow: none;
}

.dono .form-acoes .btn-secundario:hover {
    background: var(--dono-sup-alta);
    transform: none;
}

/* -----------------------------------------------------------------------------
   11. MOVIMENTO REDUZIDO — sai o que é decorativo; o estado fica
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .dono-aceno {
        animation: none;
    }

    .dono-destino,
    .dono-destino:hover,
    .dono-tecla-cheia:hover,
    .dono-tecla-voltar:hover,
    .dono .btn-secundario:hover {
        transform: none;
    }

    .dono-tecla-criar:hover .dono-icone,
    .dono-destino:hover .dono-destino-chamada .dono-icone {
        transform: none;
    }
}


/* =============================================================================
   AS MUDANÇAS ESTRUTURAIS DE LARGURA — QUATRO, NOMEADAS, NUM LUGAR SÓ
   =============================================================================
   ANTES DESTA ETAPA: 12 media queries de `min-width` em NOVE valores distintos —
   420, 480, 560 (×3), 600, 720, 768, 820, 860, 1024 (×2) — mais uma de
   `max-width: 480px`, que era desktop-first numa folha que se declara
   mobile-first. Nove pontos de virada para cinco telas, e nenhum deles escolhido
   por um sistema: cada um nasceu do componente que o pediu.
   DEPOIS: TRÊS blocos, três valores, e cada um com uma conta atrás. A T-0017
   acrescentou o QUARTO, 40rem, e ele tem dona: só a vitrine mora lá (o motivo
   está no cabeçalho do bloco).

   O placar é conferível sem navegador, e é assim que o QA o confere:
       grep -c "^@media (min-width" style.css   →  4
       grep -c "^@media (max-width" style.css   →  0
   (os SEIS blocos de `prefers-reduced-motion: reduce` e o de `no-preference` da
   vitrine não são de largura e não entram na conta — contados em 2026-10-06.)

   ⚠️ O `^` NÃO É ENFEITE, E O COMANDO PUBLICADO SEM ELE MENTE. Todo bloco real
   começa na coluna 0; toda citação em prosa está recuada dentro de um
   comentário. Sem a âncora, o grep conta a explicação junto com a regra e o
   placar sobe sozinho na primeira vez que alguém documentar o que fez. É o mesmo
   defeito que o comentário de `--limite` resolve com `[.]`, na forma que serve
   aqui.

   COMO CINCO SUMIRAM SEM QUE NADA MUDE DE LUGAR: `.stats-fila`, `.campo-grid`,
   `.admin-stats`, `.metricas` e `.album-parte` passaram a se contar sozinhas
   (`auto-fit`/`flex-wrap`). A tese é curta — *breakpoint é palpite sobre o
   APARELHO; `auto-fit` é medição do ESPAÇO que existe.* Uma grade que se conta
   sozinha responde à caixa em que mora, inclusive quando essa caixa é uma coluna
   de 378px dentro de uma janela de 1024, que é onde toda media query de viewport
   erra e onde este produto tem quatro telas.

   ⚠️ POR QUE TRÊS E NÃO OS QUATRO DA ESPECIFICAÇÃO. `docs/painel-e-desktop.md`
   §A.2 propõe também `--bp-4` (80rem / 1280px), com dois encargos: a densidade e
   a largura da tabela do admin, e a fileira de benefícios chegando a 3 colunas.
   O segundo `auto-fit` já resolve sem breakpoint nenhum (3 colunas a partir de
   912px de caixa); o primeiro é T-0016. Um bloco de 80rem entraria vazio, e
   breakpoint sem mudança estrutural dentro é exatamente o que esta seção existe
   para não ter. Ele volta no dia em que tiver o que fazer, com o valor já
   decidido: 80rem.

   ⚠️ E POR QUE NÃO EXISTEM TOKENS `--bp-1..4`. Custom property NÃO é válida na
   condição de uma `@media` — `@media (min-width: var(--bp-3))` não casa nunca.
   Declarar os quatro no `:root` criaria quatro nomes que não podem ser usados no
   único lugar para o qual foram inventados. Os valores ficam literais, em `rem`,
   com a tabela abaixo servindo de dicionário.

   TODOS EM `rem`, E NÃO EM PX. `rem` numa media query é medido contra a fonte
   PADRÃO DO NAVEGADOR, não contra o `html` da página: quem aumenta a letra do
   sistema recebe o leiaute simples mais cedo, que é o comportamento certo — é a
   WCAG 1.4.4 saindo de graça.

   O DICIONÁRIO. Os comentários espalhados pelo arquivo dizem "migrou para o
   bloco `--bp-1`" porque `--bp-N` é o nome da ESPECIFICAÇÃO; aqui embaixo é onde
   esse nome vira um valor e um bloco.

   | Nome (spec)| Valor        | Apelido           | O que muda de ESTRUTURA      |
   |------------|--------------|-------------------|------------------------------|
   | `--bp-1`   | 30rem / 480  | o telefone deitado| o cabeçalho e a fileira de   |
   |            |              |                   | ações viram linha            |
   | (Stitch)   | 40rem / 640  | o `sm` do Stitch  | a vitrine (T-0017) e o painel|
   |            |              |                   | do dono (T-0038): os dois    |
   |            |              |                   | arquivos do Stitch viram aqui|
   | `--bp-2`   | 48rem / 768  | o tablet em pé    | o cartão ganha respiro; o    |
   |            |              |                   | menu e as grades da vitrine  |
   | `--bp-3`   | 64rem / 1024 | a mesa            | painel e admin viram DUAS    |
   |            |              |                   | COLUNAS; o herói da vitrine  |
   |            |              |                   | também                       |
   | `--bp-4`   | 80rem / 1280 | a tela grande     | NÃO EXISTE AINDA — ver acima |
   ============================================================================= */


/* =============================================================================
   A CABINE — A ARQUITETURA DA DIREÇÃO B (T-0031, etapa 2d)
   =============================================================================
   Fonte: `demos/demo-admin-B-cabine.html`, bloco `<style>` (linhas 43–1279).
   ⚠️ ESTAS REGRAS NASCEM SEM MARCAÇÃO, E ISSO É O PLANO. A marcação do console
   é reescrita na etapa 3 pelo `especialista-backend`; até lá nenhuma delas tem
   alcance, e a tela do admin continua no ar com a família `.admin-*` intacta.
   NADA foi removido daqui para trás: esta seção só ACRESCENTA.

   -----------------------------------------------------------------------------
   POR QUE TUDO TEM PREFIXO `cabine-`, e por que o prefixo é este
   -----------------------------------------------------------------------------
   O demo batiza as peças com nomes de vocabulário comum — `topo`, `selo`,
   `barra`, `campo`, `oculto` — e os CINCO já significam outra coisa nesta folha:

     · `.topo`   é o cabeçalho global, emitido por `views/layouts/painel.php`
     · `.selo`   é a pílula do convidado (`views/painel/convidados.php`)
     · `.barra`  é a régua do painel do dono, com gancho de `app.js`
       (`.barra span[data-progresso]`) — colisão de COMPORTAMENTO, não só de cor
     · `.campo`  é o INVÓLUCRO do campo de formulário, 44 emissões em `views/`;
       no demo é o `<input>`. Os dois sentidos são incompatíveis: a regra do demo
       (`padding`, `background`, `border`, `min-height`, `width:100%`) cairia em
       cima de todo rótulo e de toda dica de formulário do produto
     · `.oculto` é `display:none !important`, com leitor em `app.js`; no demo é
       o "visualmente oculto" que o leitor de tela ainda anuncia — sentidos
       OPOSTOS com o mesmo nome

   Adotar os nomes crus faria o console herdar quatro componentes alheios em
   silêncio, e a página do admin JÁ emite um `.topo`. Um prefixo resolve as cinco
   de uma vez e diz de quem é cada classe.

   `cabine-` e não outro, por quatro razões:
     1. é o nome que o usuário aprovou — "Direção B: A Cabine" —, e os DOIS demos
        (`demo-admin-B-cabine.html`, `demo-painel-B-cabine.html`) o carregam:
        "Cabine" nomeia a DIREÇÃO, não só o console;
     2. é a convenção desta folha, que namespaceia por família — `admin-*`,
        `palco-*`, `vitrine-*`, `album-*`, `sug-*`, `cam-*`, `gfoto-*`;
     3. o contêiner raiz do demo se chama `.cabine`, então o prefixo É a raiz —
        a mesma forma de `.palco` / `.palco-*`, que é o precedente vivo mais
        próximo (o canhoto, implantado na etapa 1 desta mesma tarefa);
     4. escrito por extenso, não colide com `cabeça`: nesta folha `cab`/`cabeca`
        só aparecem como SUFIXO (`.secao-cab`, `.cartao-cabeca`), nunca como
        prefixo.

   -----------------------------------------------------------------------------
   O QUE O DEMO CHAMA DE TOKEN E AQUI JÁ TEM NOME — nenhum token novo de cor
   -----------------------------------------------------------------------------
   O demo declara um `:root` próprio porque roda sozinho. Aqui ele não entra:
   todos os pigmentos, raios, sombras e curvas dele já existem nesta folha desde
   a etapa 1, com consumidor. A tradução, para quem for conferir:

     --r-1 → --raio-tecla   ·  --r-2 → --raio-peca  ·  999px → --raio-pilula
     --t-micro → --fs-1  ·  --t-peq → --fs-2  ·  --t-corpo → --fs-3
     --t-titulo → --fs-4  ·  --t-num → --fs-6
     --t-heroi clamp(2.75rem,11vw,4.25rem) → clamp(var(--fs-7),11vw,var(--fs-8))
     --dur/--toque → --mov-rapido  ·  --entra → --mov-medio
     --curva → --curva-padrao  ·  --curva-saida → --curva-entrada

   ⚠️ A ESCALA DE TIPO DO DEMO NÃO ENTRA COMO SEGUNDA ESCALA. Os seis `--t-*`
   diferem dos `--fs-*` desta casa em 0,30 a 1,20px, e a arbitragem da T-0016 já
   RECUSOU tokens novos com desvio dessa ordem, chamando-os pelo que são: renome.
   O `:root` diz a lei em uma linha — "o que entra a partir de agora usa a
   escala" — e a etapa 1 já fez essa mesma tradução no canhoto
   (`.palco-bilhete-mes` usa `--fs-1` onde o demo dizia `--t-micro`). Desvio
   máximo herdado: 1,20px no número do instrumento.

   ⚠️ UM TOKEN NOVO, E ELE NÃO É PIGMENTO: `--afundado`. O demo o declara duas
   vezes (uma por pele) com valores crus. Aqui ele é COMPOSTO dos tokens de
   sombra que já existem e que já giram com o modo, então nasce certo nas duas
   peles sem uma segunda declaração — a mesma forma de `--elev-1/2/3`.
   ============================================================================= */

:root {
    /* O poço: a sombra INTERNA de trilho e de botão pressionado. No claro
       resolve para `rgb(39 32 57 / 0.10)`, que é o valor do demo na vírgula; no
       escuro, para `rgb(0 0 0 / 0.45)` — o demo pedia 0.45 na sombra de
       elevação e 0.55 aqui, e a diferença de 0,10 de alfa não vale um degrau
       de alfa novo numa escala que só tem três. */
    --afundado: inset 0 2px 4px rgb(var(--sombra-tinta) / var(--sombra-a2));
}

/* -----------------------------------------------------------------------------
   1. UTILITÁRIOS — o pulo e o oculto de leitor de tela
   -----------------------------------------------------------------------------
   ⚠️ `.cabine-oculto` NÃO É `.oculto`, e os dois nomes não podem se encontrar:
   `.oculto` é `display:none !important` e some para TODO MUNDO, inclusive para
   o leitor de tela; este esconde só do olho e continua sendo lido e tabulável.
   Esta folha não tinha nenhum "visualmente oculto" — foi conferido. Ele nasce
   escopado na família porque é aqui que ele tem consumidor previsto; promovê-lo
   a utilitário do produto é decisão do `especialista-ui`, não minha.
   -------------------------------------------------------------------------- */
.cabine-oculto {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    white-space: nowrap;
    clip-path: inset(50%);
}

/* O pulo para o conteúdo. Ele SAI da tela pela esquerda em vez de sumir, porque
   precisa continuar na ordem de tabulação: é a primeira parada do teclado.
   `--z-capa` (20) é o degrau mais alto do sistema — o pulo não pode nascer
   atrás do cabeçalho fixo. */
.cabine-pular {
    position: absolute;
    top: 0;
    left: -9999px;
    z-index: var(--z-capa);
    padding: 10px 16px;
    border-radius: 0 0 var(--raio-tecla) 0;
    font-family: var(--f-display);
    font-weight: 700;
    background: var(--acento);
    color: var(--tinta-viva);
}

.cabine-pular:focus {
    left: 0;
}

/* -----------------------------------------------------------------------------
   2. FOCO — a família declara o seu, como as outras quatro desta folha
   -----------------------------------------------------------------------------
   Mesma forma de `.admin :focus-visible`, `.tema-vitrine :focus-visible`,
   `.painel-palco :focus-visible` e `.tema-convite :focus-visible`: `outline` e
   `outline-offset`, e MAIS NADA. `border-radius` numa regra de foco esquadra a
   peça no instante do foco de teclado, e o anel já acompanha o raio sozinho.

   ⚠️ O SEGUNDO SELETOR NÃO É REDUNDÂNCIA — É O ÚNICO ELEMENTO DA FAMÍLIA QUE O
   PRIMEIRO NÃO ALCANÇA, e ele é justamente a PRIMEIRA PARADA DO TECLADO.
   `.cabine :focus-visible` exige um ancestral `.cabine`; o pulo é filho DIRETO
   do `<body>`, porque ele precisa vir antes de tudo na ordem de tabulação.
   MEDIDO no DOM servido (T-0031 3e): 34 pulos nas telas que os têm, e ZERO
   deles dentro de um `.cabine` — a família nunca vestia nenhum. O anel dele era
   o padrão do navegador: some com `outline: none` de qualquer folha futura, não
   lê `--foco` e não gira com a pele, num elemento que só existe para quem
   navega por teclado. As cores da peça já vinham da folha nas duas peles
   (`--acento` e `--tinta-viva`); o que faltava era o ANEL.
   ⚠️ ESPECIFICIDADE IGUAL (0,2,0) nos dois seletores, então nada muda de ordem.
   E continua sendo `:focus-visible`, não `:focus`: quem faz o pulo APARECER é
   `.cabine-pular:focus { left: 0 }` acima, que é outra pergunta.
   -------------------------------------------------------------------------- */
.cabine :focus-visible,
.cabine-pular:focus-visible {
    outline: var(--foco-largura) solid var(--foco);
    outline-offset: var(--foco-desvio);
}

/* O anel DUPLO da tecla, e ele é o desta folha e não o do demo: aqui o
   `outline` fica TRANSPARENTE em vez de `none`, para que no modo de alto
   contraste do sistema — onde `box-shadow` é descartado — o anel volte a
   existir sozinho. É a mesma escolha já documentada em `.btn:focus-visible`. */
.cabine-tecla:focus-visible {
    outline: var(--foco-largura) solid transparent;
    outline-offset: var(--foco-desvio);
    box-shadow: 0 0 0 2px var(--anel-folga), 0 0 0 4px var(--anel), var(--elev-1);
}

/* O anel para DENTRO nas duas peças que são a borda do próprio cartão. É a
   correção do BUG-TD-102: um `overflow:hidden` comeu o anel de um `<summary>`
   colado na borda. */
.cabine-conta:focus-visible,
.cabine-fila-item:focus-visible {
    outline-offset: -2px;
}

/* -----------------------------------------------------------------------------
   3. A PLACA DO AMBIENTE — a listra que só o console tem
   -----------------------------------------------------------------------------
   O painel do dono não opera ambiente nenhum: gastar a listra lá diluiria o
   canal. O par de listras mede 4,01:1 entre si no claro e 4,90:1 no escuro —
   os dois tokens já existem e já giram com a pele.
   -------------------------------------------------------------------------- */
.cabine-trilho-ambiente {
    height: 3px;
}

.cabine-trilho-ambiente--local {
    background-image: repeating-linear-gradient(
        -45deg,
        var(--listra-forte) 0 8px,
        var(--listra-fraca) 8px 16px
    );
}

/* -----------------------------------------------------------------------------
   4. ESTRUTURA — o contêiner, o topo e as duas colunas
   -----------------------------------------------------------------------------
   ⚠️ PARA A ETAPA 3: `.admin-conteudo` é hoje o contêiner principal do console —
   emitido nas cinco seções, com ZERO regra nesta folha e ZERO leitor em `app.js`
   (medido). Ele é o lugar natural de `class="admin-conteudo cabine"`. NÃO dei
   regra a ele aqui de propósito: `.admin-conteudo` está VIVO na tela que está no
   ar, e uma largura máxima nova nele mudaria o console de hoje, antes de a
   marcação nova existir.
   -------------------------------------------------------------------------- */
.cabine {
    max-width: 1440px;
    margin: 0 auto;
    padding: 0 14px var(--e-16);
}

/* -----------------------------------------------------------------------------
   O TETO QUE FAZIA OS 1440px ACIMA SEREM LETRA MORTA — e por que ele é escopado
   -----------------------------------------------------------------------------
   `.cabine` declara 1440px desde a etapa 1 e NUNCA os alcançou: o console mora
   dentro de `<main class="container">`, e `.painel-largo .container` capa em
   1160px. Medido nesta etapa, a 1440 de janela: contêiner 1160, corpo 1128,
   coluna do console 892, fileira da conta 838px — a folha pedia 1440 e recebia
   838. Esta regra devolve à `.cabine` o teto que ela própria declara.

   ⚠️ E POR QUE NÃO MEXI EM `.painel-largo .container` (linha ~2828), QUE ERA O
   CAMINHO ÓBVIO: `painel-largo` NÃO É DO CONSOLE. Contei os consumidores antes
   de escrever — são SETE páginas com `larga: true`: Admin, Convidados, Evento,
   Galeria do dono, Painel do dono, Presentes e a RAIZ, que é pública. Alargar
   ali levaria 1440px para a página de apresentação do produto e para as cinco
   telas do dono, cuja composição foi fechada em 1160 na T-0015 e na T-0016 (o
   `RaizController` escreve o motivo em prosa: *"largura sem composição é pior
   que 560"*). Nenhuma delas foi medida a 1440 nesta etapa, e alargar o que não
   se mediu é o defeito que esta tarefa está justamente corrigindo.

   O GANCHO É `.cabine-corpo`, e ele é ÚNICO: `views/admin/index.php:182` é a
   única linha do sistema que o emite — conferido por varredura em `views/`. O
   seletor lê a ESTRUTURA em vez de exigir uma classe nova no `<body>`, que a
   marcação teria de me dar (e `views/**` não é meu nesta etapa).

   ⚠️ O GANCHO ESTÁ NO `<body>` E NÃO NO `<main>`, E ISSO CUSTOU UMA MEDIÇÃO.
   A primeira forma desta regra era `.container:has(> .cabine-corpo)` — só o
   `<main>`. Ela alargava o console e DEIXAVA PARA TRÁS os outros dois
   `.container` da página, que são irmãos e não ancestrais dele: o do
   `header.topo` e o do `footer.rodape`. Medido a 1440 depois daquela versão:
   conteúdo do cabeçalho começando em 132,5px, trilho do console em 16px e
   miolo do console em 325,5px — três bordas esquerdas onde a folha exige UMA
   (é a lei escrita na regra de `.coluna-leitura`, lá em cima). Cada regra
   estava certa sozinha e a PÁGINA MONTADA estava errada. Com o gancho no
   `<body>`, os três `.container` da tela do console andam juntos.

   ⚠️ DEGRADAÇÃO, na forma que esta folha já aceitou em `.admin-ato-perigo`
   (~linha 5560): navegador sem `:has()` ignora a regra e o console fica nos
   1160px de hoje. Perde-se o alargamento; não se perde tela nenhuma.
   -------------------------------------------------------------------------- */
.painel-largo:has(.cabine-corpo) .container {
    max-width: 1440px;
}

/* -----------------------------------------------------------------------------
   A OUTRA METADE, E ELA NÃO É OPCIONAL — a prosa do console presa em 66ch
   -----------------------------------------------------------------------------
   ALARGAR SOZINHO TROCA ROLAGEM POR ILEGIBILIDADE, e o console JÁ violava a
   medida ANTES desta etapa — o teto novo só tornaria a violação maior.

   O PLACAR, medido nas 5 seções × 6 larguras × 2 peles (60 telas), contando
   blocos de prosa cuja LINHA MAIS LONGA passa de 66ch:

       ANTES: 394 blocos acima de 66ch · pior linha 100,5ch (Usuários, 1280+)
       DEPOIS:  2 blocos acima de 66ch · pior linha  63,5ch (Usuários, 1280+)

   Os 2 que restam são o MESMO bloco nas duas peles, `p.cabine-heroi-linha` na
   Visão geral e SÓ a 768px, com 74,5ch antes e 74,5ch depois: ele é anterior a
   esta etapa, vive na faixa do tablet — onde o teto nem chega a valer — e não
   foi tocado. Fica nomeado aqui para o `especialista-responsividade`, não
   escondido atrás de um número redondo.

   =============================================================================
    A RÉGUA ERRADA DUAS VEZES, e é a lição desta etapa
   =============================================================================
   O número que circulou na etapa anterior — *"798px = 102,3 caracteres"* — está
   errado, e o erro é do INSTRUMENTO, não da tela. Ele errou em dois eixos:

   1. FONTE DO VIZINHO. A largura do caractere saía do PRIMEIRO parágrafo do
      documento (`.painel-status-texto`, 15,2px, caractere de 7,83px) e era
      aplicada ao parágrafo MAIS LARGO (`.admin-sub`, 12,48px, caractere de
      6,43px). 798 ÷ 7,83 dá 101,9; 798 ÷ 6,43 dá 124,1. Mesma caixa, régua de
      outro tamanho. Medir prosa exige a régua DAQUELE texto.

   2. CAIXA EM VEZ DE LINHA — e este é o pior, porque sobrevive à correção do
      primeiro. Dividir a LARGURA DA CAIXA pela largura do caractere mede a
      caixa, não a linha. Uma frase de 48 caracteres numa caixa de 75 não é uma
      linha de 75, e o alargamento cria esse caso às dúzias: a caixa cresce, o
      texto não. Com essa régua o alargamento "criava" 36 violações que não
      existiam na tela. A régua certa é `Range.getClientRects()`, que devolve um
      retângulo POR LINHA DESENHADA: a mais larga é a linha mais longa de fato.

   Os números deste bloco são todos da régua 2 corrigida: linha renderizada
   dividida pelo `ch` do próprio elemento.

   =============================================================================
    POR QUE `66ch` E NÃO `var(--medida)`
   =============================================================================
   `--medida` (38rem) é a coluna de DOCUMENTO: largura FIXA em px, calibrada
   para texto de 15,2px. Aplicada a texto de 12,48px ela entrega uma linha muito
   mais longa em caracteres, porque o número de px não sabe de que tamanho é a
   letra. `ch` é RELATIVO à fonte do próprio elemento — o mesmo `66ch` vale
   494px no texto de 12,48px e 539px no de 13,6px, e os dois dão 66 caracteres
   de largura de dígito. É a única forma de UM número servir às seis famílias
   abaixo, que têm cinco tamanhos de fonte diferentes.

   ⚠️ `66ch` NÃO SÃO 66 LETRAS MINÚSCULAS, e vale saber antes de comparar com a
   literatura: em Nunito o glifo `0` é mais largo que a minúscula média (7,49px
   contra 6,43px no corpo de 12,48px), então `66ch` desenha ~77 caracteres
   médios. Quem comparar este limite com a régua clássica de 45–75 tem de
   comparar 77, não 66.

   ⚠️ O NÚMERO NÃO É NOVO NESTA FOLHA, mas o parentesco é MENOR do que eu
   escrevi na primeira versão deste comentário e a correção fica no lugar do
   erro: quem já vivia em `66ch` era `.cabine-risco p`, e SÓ ele. Eu havia
   escrito que `.cabine-inst-nota` também vivia — não vive: ela não tem
   `max-width` nenhum. O `17ch` que eu tinha na cabeça é de OUTRO seletor,
   `.cabine-heroi-num span`. Um antecedente real, não dois.

   =============================================================================
    O ESCOPO, E AS DUAS ARMADILHAS DE CASCATA
   =============================================================================
   ⚠️ TUDO PRESO A `.cabine`, e não por gosto: `.campo-dica` e `.campo-checkbox`
   são classes do PRODUTO (`views/painel/convidados.php` e `views/painel/evento.php`
   vestem a primeira; a segunda aparece em formulário por toda parte). Sem o
   escopo, um limite pensado para o console entraria em telas do dono que
   ninguém mediu aqui — o mesmo erro que o teto acima recusou cometer.

   ⚠️ `:not(.coluna-leitura)` no aviso NÃO É ENFEITE: sem ele, `.cabine
   .cabine-aviso` (0,2,0) venceria `.coluna-leitura` (0,1,0) e passaria por cima
   de `var(--medida)` — uma segunda medida de leitura escrita por acidente, que
   é o que as travas L1–L4 de `Invariantes_do_design_system_test` existem para
   impedir. O aviso preso à coluna continua com a medida do documento.

   =============================================================================
    `label.campo-checkbox` ENTROU, E ENTROU CONTRA A MINHA PRIMEIRA LEITURA
   =============================================================================
   Eu ia deixá-lo de fora: o `<label>` inteiro é clicável, e a ressalva do
   BUG-TD-075 (~linha 4620) diz que encolher esse alvo exigiria separar
   `<input>` e `<label for>`. Eu supunha que o limite fizesse o texto quebrar e
   o ALVO CRESCER. MEDI as 25 caixas a 1440 antes de decidir, e é o contrário:

       sem limite: altura máx. 87,3px · área média 52.838px²
       com 66ch  : altura máx. 89,5px · área média 39.161px²

   A largura encolhe muito mais do que a altura cresce (+2,2px no pior caso), e
   a ÁREA CLICÁVEL CAI 26%. O borrão do BUG-TD-075 era um alvo grande e ambíguo;
   este limite anda contra o borrão, não a favor dele. O `min-height:
   var(--alvo-toque)` de 44px continua intacto, e a 320 e 375px o limite é
   INERTE — medido: os números saem idênticos com e sem ele, porque 66ch
   (557,6px) é maior que a tela. Ele só age onde a linha realmente estica. E
   ISSO IMPORTA porque estas 25 frases são as confirmações dos atos que não se
   desfazem: se alguma linha do produto precisa ser lida até o fim, é esta.

   =============================================================================
    O QUE ESTE BLOCO NÃO CAPA, E POR QUÊ
   =============================================================================
   `span.admin-conta-marcadores` apareceu como violação enquanto a régua era a
   caixa (98,7 caracteres). Com a régua da LINHA ele mede 29,1 — ele nunca foi
   prosa: é a fileira de etiquetas da conta, e cada etiqueta é curta. Não entra,
   e não entra porque foi MEDIDO de novo, não porque foi esquecido. Capá-lo
   quebraria a fileira em duas linhas para resolver um problema inexistente.
   -------------------------------------------------------------------------- */
.cabine .admin-sub,
.cabine .cabine-cartao-cabeca span,
.cabine .cabine-fila-topo,
.cabine .campo-dica,
.cabine .campo-checkbox,
.cabine .cabine-aviso:not(.coluna-leitura) {
    max-width: 66ch;
}

.cabine-topo {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--e-3);
    padding: var(--e-4) 0 18px;
}

.cabine-marca {
    display: flex;
    align-items: center;
    gap: 11px;
    margin-right: auto;
}

/* O símbolo REAL da marca, inline, com as cores do arquivo — serve às duas
   peles sem versão negativa. A palavra "Tô Dentro" é TIPO e não imagem: ela
   segue `--cor-texto` e troca de pele sozinha. */
.cabine-marca-simbolo {
    display: block;
    flex: none;
    width: auto;
    height: 36px;
}

.cabine-marca-nome {
    font-family: var(--f-display);
    font-size: var(--fs-4);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.01em;
    color: var(--cor-texto);
}

.cabine-marca-sub {
    font-family: var(--f-display);
    font-size: var(--fs-1);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--cor-texto-suave);
}

.cabine-chip {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 11px;
    border: 1px solid var(--fio-1);
    border-radius: var(--raio-pilula);
    font-family: var(--f-display);
    font-size: var(--fs-1);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    background: var(--sup-cartao);
    color: var(--cor-texto-suave);
}

.cabine-chip b {
    font-weight: 700;
}

/* A pastilha é SÓLIDA e o fio some: pastilha em alfa compõe com o que estiver
   atrás e o par deixa de ser mensurável. Mesma correção que TD-076 fez nas
   pastilhas de estado. */
.cabine-chip--ambiente {
    border-color: transparent;
    background: var(--pastilha-ambar);
    color: var(--cor-aviso-texto);
}

.cabine-chip--verde {
    border-color: transparent;
    background: var(--pastilha-verde);
    color: var(--cor-sucesso-texto);
}

/* O ponto lê a tinta de quem o hospeda (`currentColor`): um pigmento a menos
   por estado, e ele nunca diverge do rótulo ao lado. */
.cabine-ponto {
    flex: none;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
}

.cabine-corpo {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-4);
    align-items: start;
}

/* O TRILHO DE NAVEGAÇÃO. Ele QUEBRA em vez de deslizar: barra que rola na
   horizontal já foi cortada em 320/360px nesta casa. */
.cabine-rail {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: var(--e-2);
    border: 1px solid var(--fio-1);
    border-radius: var(--raio-peca);
    background: var(--sup-cartao);
    box-shadow: var(--elev-cabine);
}

.cabine-rail a {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    gap: 9px;
    min-height: 40px;
    padding: 6px 11px;
    border-radius: var(--raio-tecla);
    font-size: var(--fs-2);
    font-weight: 600;
    text-decoration: none;
    color: var(--cor-texto-medio);
    transition:
        background-color var(--mov-rapido) var(--curva-padrao),
        color var(--mov-rapido) var(--curva-padrao);
}

.cabine-rail a:hover {
    background: var(--sup-hover);
    color: var(--cor-texto);
}

.cabine-rail a:active {
    background: var(--sup-press);
}

/* A seção corrente é dita por SUPERFÍCIE e por um filete de acento à esquerda —
   nunca só por cor. Mesmo par de canais que `.admin-link.ativa` usava: esta
   regra HERDOU a solução dela, e por isso a original pôde sair na T-0031 3e. */
.cabine-rail a[aria-current="true"] {
    background: var(--sup-press);
    color: var(--cor-texto);
    box-shadow: inset 2px 0 0 var(--acento);
}

.cabine-rail svg {
    flex: none;
    opacity: 0.85;
}

.cabine-qtd {
    margin-left: auto;
    font-family: var(--f-display);
    font-size: var(--fs-1);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto-suave);
}

/* -----------------------------------------------------------------------------
   5. MÓDULOS, CARTÕES E AVISOS
   -------------------------------------------------------------------------- */
.cabine-modulo {
    display: grid;
    gap: var(--e-3);
    min-width: 0;
}

.cabine-modulo-cabeca {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--e-3);
}

.cabine-modulo-cabeca h2 {
    font-family: var(--f-display);
    font-size: var(--fs-4);
    font-weight: 600;
    letter-spacing: -0.015em;
    color: var(--cor-texto);
}

.cabine-modulo-cabeca p {
    font-size: var(--fs-2);
    color: var(--cor-texto-suave);
}

.cabine-rotulo {
    font-family: var(--f-display);
    font-size: var(--fs-1);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.13em;
    color: var(--cor-texto-suave);
}

/* SEM `overflow:hidden`. O recorte foi a causa raiz do BUG-TD-102 — ele comeu o
   anel de foco de um `<summary>` colado na borda do cartão. */
.cabine-cartao {
    border: 1px solid var(--fio-1);
    border-radius: var(--raio-peca);
    background: var(--sup-cartao);
    box-shadow: var(--elev-cabine);
}

.cabine-cartao-cabeca {
    display: grid;
    gap: 2px;
    padding: 14px var(--e-4);
}

.cabine-cartao-cabeca strong {
    font-family: var(--f-display);
    font-size: var(--fs-3);
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--cor-texto);
}

.cabine-cartao-cabeca span {
    font-size: var(--fs-2);
    color: var(--cor-texto-suave);
}

.cabine-cartao-corpo {
    padding: 14px 15px 15px;
    border-top: 1px solid var(--fio-1);
}

.cabine-avisos {
    display: grid;
    gap: 10px;
    padding: 14px var(--e-4);
    border-left: 3px solid var(--ambar);
    border-radius: var(--raio-peca);
    background: var(--fundo-aviso);
    box-shadow: var(--elev-cabine);
}

.cabine-aviso {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    font-size: var(--fs-2);
}

.cabine-aviso svg {
    flex: none;
    margin-top: 1px;
}

.cabine-aviso--forte {
    color: var(--cor-aviso-texto);
}

.cabine-aviso--forte strong {
    font-weight: 800;
    color: var(--cor-aviso-texto);
}

.cabine-aviso--calmo {
    color: var(--cor-texto-medio);
}

.cabine-aviso--calmo strong {
    font-weight: 700;
    color: var(--cor-texto);
}

.cabine-aviso code {
    padding: 1px 6px;
    border-radius: 5px;
    font-family: var(--f-display);
    font-weight: 600;
    background: var(--sup-cartao);
    color: var(--cor-texto);
}

/* -----------------------------------------------------------------------------
   6. INSTRUMENTOS — os números do console
   -----------------------------------------------------------------------------
   O destaque do número vem de TAMANHO, PESO e `tabular-nums`, nunca de cor: é a
   regra `numero_e_tinta` do design system, e é ela que mantém o único evento
   cromático da dobra onde ele foi decidido.
   -------------------------------------------------------------------------- */
.cabine-instrumentos {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-3);
}

.cabine-inst {
    display: grid;
    align-content: start;
    gap: 6px;
    min-width: 0;
    padding: 15px var(--e-4) var(--e-4);
    border: 1px solid var(--fio-1);
    border-radius: var(--raio-peca);
    background: var(--sup-cartao);
    box-shadow: var(--elev-cabine);
}

.cabine-inst-num {
    font-family: var(--f-display);
    font-size: var(--fs-6);
    font-weight: 600;
    line-height: 1;
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto);
}

.cabine-inst-num small {
    margin-left: 5px;
    font-size: var(--fs-3);
    font-weight: 500;
    color: var(--cor-texto-suave);
}

.cabine-inst-nota {
    font-size: var(--fs-2);
    color: var(--cor-texto-suave);
}

/* O herói não muda de cor: ele ganha um filete de acento e uma elevação a mais.
   Cor gasta aqui seria o segundo evento cromático da dobra. */
.cabine-inst--heroi {
    gap: 10px;
    padding: var(--e-5) var(--e-5) 22px;
    box-shadow: inset 3px 0 0 var(--acento), var(--elev-2);
}

.cabine-heroi-num {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 14px;
    font-family: var(--f-display);
    font-size: clamp(var(--fs-7), 11vw, var(--fs-8));
    font-weight: 700;
    line-height: 0.9;
    letter-spacing: -0.045em;
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto);
    animation: cabine-subir var(--mov-medio) var(--curva-entrada) both;
}

/* A frase ao lado do número volta para a fonte do CORPO: ela é texto de leitura
   e não medida. `--f-corpo` existe exatamente para essa volta. */
.cabine-heroi-num span {
    max-width: 17ch;
    font-family: var(--f-corpo);
    font-size: var(--fs-2);
    font-weight: 500;
    line-height: 1.35;
    letter-spacing: 0;
    color: var(--cor-texto-suave);
}

@keyframes cabine-subir {
    from {
        opacity: 0;
        transform: translateY(7px);
    }
}

.cabine-heroi-linhas {
    display: grid;
    gap: 7px;
    margin-top: 2px;
}

.cabine-heroi-linha {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 9px;
    font-size: var(--fs-2);
}

.cabine-heroi-linha b {
    font-family: var(--f-display);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto);
}

/* -----------------------------------------------------------------------------
   A RÉGUA DO BALDE
   -----------------------------------------------------------------------------
   ⚠️ A LARGURA VEM DO ELEMENTO, NUNCA DO FIM DE UMA ANIMAÇÃO — é o contrato que
   `.barra span` já documenta nesta folha: `app.js` escreve `style.width` a
   partir de `data-progresso` (CSSOM, que a CSP `style-src self` não bloqueia; o
   que ela bloqueia é o atributo `style=""` no HTML). O demo usa `.pct-47` porque
   é estático; uma classe por porcentagem não é mecanismo, é fotografia.
   ⚠️ FAMÍLIA PRÓPRIA — E, DESDE A ETAPA 3, PENDURADA NO GANCHO DE `.barra`.
   `views/admin/index.php` emite a régua como `.barra.cabine-barra` com o
   preenchimento em `<span>`, porque `.barra span[data-progresso]` é o único par
   que o `app.js` lê e o JS não era daquela etapa. O preço apareceu no gate
   (BUG-TD-135): `.barra span` é (0,1,1) e `.cabine-barra-fill--verde` era
   (0,1,0) — a regra antiga VENCIA por especificidade, independente da ordem, e
   a barra de Confirmações pintava o degradê aposentado nas duas peles, medido
   na engine. A correção é especificidade honesta, não ordem de origem: o
   preenchimento passa a ser declarado DENTRO da sua régua
   (`.cabine-barra .cabine-barra-fill`, 0,2,0), o mesmo desenho com que
   `.palco-conf .barra span` vence a mesma regra. Todas as declarações sobem
   juntas — inclusive a `transition`, que por isso ganhou a própria linha no
   bloco de `prefers-reduced-motion`. `.barra` continua servindo o painel do
   dono (`views/painel/index.php:294`, dentro de `.palco-conf`), agora com base
   em `--cor-acento` e não em `--grad`.
   -------------------------------------------------------------------------- */
.cabine-barra {
    position: relative;
    height: 12px;
    margin-top: var(--e-1);
    border-radius: var(--raio-pilula);
    background: var(--trilho-barra);
    box-shadow: var(--afundado);
}

.cabine-barra--alta {
    height: 18px;
}

.cabine-barra .cabine-barra-fill {
    display: block;
    width: 0;
    height: 100%;
    border-radius: var(--raio-pilula);
    background: var(--acento);
    transition: width var(--mov-medio) var(--curva-padrao);
}

.cabine-barra .cabine-barra-fill--verde {
    background: var(--verde);
}

/* As marcas de dez em dez: a barra vira RÉGUA e não mancha. Objeto gráfico,
   piso de 3:1, e `--marca-barra` já existe com esse cargo. */
.cabine-barra-marcas {
    position: absolute;
    inset: 0;
    border-radius: var(--raio-pilula);
    background-image: repeating-linear-gradient(
        90deg,
        var(--marca-barra) 0 1px,
        transparent 1px 10%
    );
}

.cabine-legenda-barra {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 2px var(--e-3);
    margin-top: 6px;
    font-family: var(--f-display);
    font-size: var(--fs-1);
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto-suave);
}

/* -----------------------------------------------------------------------------
   7. A LISTA DE CONTAS — fila ordenada por urgência, não grade
   -----------------------------------------------------------------------------
   UMA COLUNA e uma borda esquerda só, que é o que o `layout.json` manda e o que
   a T-0021 já mediu nesta mesma seção: numa grade, "a mais urgente" e "a
   segunda" ficam lado a lado e a fila deixa de ser fila.
   -------------------------------------------------------------------------- */
.cabine-contas {
    display: grid;
    gap: 10px;
    list-style: none;
}

/* O cabeçalho de colunas só existe quando as colunas existem — ele nasce
   escondido e o bloco de 64rem o liga.
   ⚠️ ELE CONTINUA SEM CONSUMIDOR NA T-0031 ETAPA 3b, E A RAZÃO É DE MARCAÇÃO E
   NÃO DE FOLHA: `Pessoa · Festa · Estado · Prazo` são QUATRO elementos que
   precisam existir no HTML, e `views/admin/index.php` não os emite. Nenhuma
   regra de CSS cria conteúdo de leitura — a alternativa (`::before` com texto)
   seria conteúdo escondido da árvore de acessibilidade e está recusada. Vai como
   consulta ao `especialista-backend`.
   ⚠️ E O RECUO DELE JÁ ESTÁ CERTO PARA O DIA EM QUE A MARCAÇÃO CHEGAR — PROVADO,
   e não conferido por leitura. Regra sem consumidor não se confere lendo: eu
   INJETEI este cabeçalho na página servida, com a marcação exata que a view
   emitiria, e comparei a abscissa dos quatro rótulos com a das quatro células,
   a 1280px:

       rótulo   351,5   586,0   798,5   984,5
       célula   351,5   585,5   797,5   983,5
       desvio     0,0     0,5     1,0     1,0     ← o 1px é a borda do cartão

   O RECUO ANTIGO ERRAVA POR 5px À ESQUERDA e por 36px à direita: a caixa do
   cabeçalho começa em 330,5 (medida), e `var(--e-4)` a punha em 346,5 contra os
   351,5 da célula — porque a linha recua `--e-5` E mora dentro de um cartão com
   1px de borda. O que entra é `--e-5 + 1px` de um lado e a MESMA pista da seta
   do outro (`--e-5 + --e-4`), senão o rótulo `Prazo` fica sobre o lugar da seta e
   não sobre a coluna. */
.cabine-contas-cabeca {
    display: none;
    /* O MESMO gabarito da linha, e o porquê dos 148/172 (em vez dos 172/150 do
       demo) está escrito UMA vez, no bloco de 64rem. Repetido aqui porque o
       cabeçalho é IRMÃO da lista e não filho dela — não há como herdar trilha. */
    grid-template-columns: minmax(0, 2fr) minmax(0, 1.8fr) 148px 172px;
    gap: 14px;
    padding: 0 calc(var(--e-5) + var(--e-4)) 2px calc(var(--e-5) + 1px);
}

.cabine-conta {
    border: 1px solid var(--fio-1);
    border-radius: var(--raio-peca);
    background: var(--sup-cartao);
    box-shadow: var(--elev-cabine);
    transition:
        background-color var(--mov-rapido) var(--curva-padrao),
        box-shadow var(--mov-rapido) var(--curva-padrao),
        transform var(--mov-rapido) var(--curva-padrao);
}

.cabine-conta:hover {
    background: var(--sup-hover);
    box-shadow: var(--elev-2);
    transform: translateY(-1px);
}

/* A conta desligada apagou a luz: a superfície AFUNDA até o nível da página e a
   sombra some. Nenhuma cor — desligado não é alarme. */
.cabine-conta--desativada {
    background: var(--cor-fundo);
    box-shadow: none;
}

.cabine-conta--desativada:hover {
    background: var(--sup-cartao);
    box-shadow: var(--elev-cabine);
}

/* -----------------------------------------------------------------------------
   A LINHA DE LEITURA — a peça com DOIS NOMES, e por que ela tem dois
   -----------------------------------------------------------------------------
   `.cabine-conta-leitura` é o nome do demo aprovado; `.admin-conta-linha` é o
   nome que a marcação emite hoje, no `<summary>` do acordeão. É a MESMA peça, e
   por isso a geometria está escrita UMA vez, aqui, para os dois seletores.

   ⚠️ POR QUE NÃO SE RESOLVEU PONDO A CLASSE DO DEMO NA MARCAÇÃO: `views/**` não
   é desta especialidade nesta etapa, e há uma razão melhor do que a de
   propriedade — `.admin-conta-linha` carrega três coisas que a peça do demo não
   tem e não pode perder (a margem de rolagem da âncora `#conta-{id}`, o marcador
   nativo apagado e a seta de "isto abre"). Enquanto as duas existirem, elas
   precisam ler a MESMA geometria, senão a folha passa a ter duas grades para uma
   lista. Quando a marcação adotar o nome do demo, nada aqui muda.

   ⚠️ O RECUO NÃO ENTRA NA REGRA COMPARTILHADA, e a diferença é deliberada: o
   demo recua 16px e a linha do produto recua `--e-5` (20px), que é o recuo de
   `.secao-corpo` — é isso que faz a linha FECHADA e a bancada ABERTA começarem
   na mesma abscissa quando a conta se abre. O demo não tem bancada.
   -------------------------------------------------------------------------- */
.cabine-conta-leitura,
.admin-conta-linha {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 11px;
}

.cabine-conta-leitura {
    padding: 14px var(--e-4);
}

.cabine-pessoa {
    display: grid;
    gap: 2px;
    min-width: 0;
}

.cabine-pessoa strong {
    font-family: var(--f-display);
    font-size: var(--fs-3);
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--cor-texto);
}

/* `anywhere` e não `break-word`: é o valor que esta folha já usa nos três
   lugares onde o dado é do usuário, e ele também baixa o `min-content` — a
   caixa passa a poder encolher em qualquer caixa em que a ponham (BUG-TD-068). */
.cabine-pessoa span {
    font-size: var(--fs-2);
    overflow-wrap: anywhere;
    color: var(--cor-texto-suave);
}

.cabine-festa {
    display: grid;
    gap: 2px;
    min-width: 0;
}

.cabine-festa strong {
    font-size: var(--fs-3);
    font-weight: 700;
    color: var(--cor-texto-medio);
}

.cabine-festa span {
    font-size: var(--fs-2);
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto-suave);
}

/* A ausência de festa é dita por PESO e por itálico, além do tom: o estado não
   depende de cor sozinha. */
.cabine-festa--vazia strong {
    font-weight: 400;
    font-style: italic;
    color: var(--cor-texto-suave);
}

.cabine-prazo {
    display: grid;
    gap: 2px;
}

.cabine-prazo b {
    font-family: var(--f-display);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto);
}

.cabine-prazo span {
    font-family: var(--f-display);
    font-size: var(--fs-1);
    text-transform: uppercase;
    letter-spacing: 0.09em;
    color: var(--cor-texto-suave);
}

/* A data muda de tinta, e o SELO ao lado diz a mesma coisa por escrito — a cor
   é reforço, nunca o único canal (`estado_nunca_so_por_cor`). */
.cabine-prazo--vencido b {
    color: var(--cor-erro-texto);
}

.cabine-prazo--perto b {
    color: var(--cor-aviso-texto);
}

/* PASTILHA SÓLIDA, e a escolha é medida: em rgba ela compunha com a linha e o
   par mudava sob o ponteiro — 4,25:1, que reprova. Sólida, mede-se uma vez e
   não depende do que está atrás. */
.cabine-selo {
    display: inline-flex;
    align-self: start;
    align-items: center;
    gap: 7px;
    padding: 6px 11px;
    border-radius: var(--raio-pilula);
    font-family: var(--f-display);
    font-size: var(--fs-1);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    white-space: nowrap;
}

.cabine-selo--noar {
    background: var(--pastilha-verde);
    color: var(--cor-sucesso-texto);
}

.cabine-selo--pode {
    background: var(--pastilha-acento);
    color: var(--cor-acento);
}

.cabine-selo--avencer {
    background: var(--pastilha-ambar);
    color: var(--cor-aviso-texto);
}

.cabine-selo--vencido {
    background: var(--pastilha-rosa);
    color: var(--cor-erro-texto);
}

.cabine-selo--desligada {
    background: var(--pastilha-neutra);
    color: var(--cor-neutro-texto);
}

.cabine-conta-acoes {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--e-2);
    padding: var(--e-3) var(--e-4);
    border-top: 1px solid var(--fio-1);
}

/* O vão que empurra o ato destrutivo para longe dos corriqueiros. Ele é
   ESTRUTURA e não enfeite: erro de clique em "Excluir conta" não tem desfazer. */
.cabine-espacador {
    margin-left: auto;
}

/* -----------------------------------------------------------------------------
   8. TECLAS — o botão em densidade de console
   -----------------------------------------------------------------------------
   ⚠️ POR QUE ELA EXISTIA TENDO `.btn` E `.admin-acao` NA FOLHA, e a pergunta
   era justa. Medido: `.btn` é o botão de FORMULÁRIO — `width:100%`, 50px de
   altura, 24px de recuo —, e `.btn-secundario`/`.btn-perigo` têm 46px;
   `.admin-acao` era o botão de linha do console de então (7px 12px, 0.82rem) e
   não tinha preenchimento vivo, nem estado de carregando, nem a variante cheia
   do destrutivo. A tecla é a terceira densidade: 40px de alvo, em linha, com as
   CINCO variantes que a tela dos seis atos destrutivos precisa.
   ⚠️ ELA NÃO INVENTA PIGMENTO: lê os MESMOS tokens que `.btn`, `.btn-secundario`
   e `.btn-perigo` já leem (`--acento`/`--acento-forte`/`--acento-fundo`,
   `--tecla-fantasma*`, `--tecla-perigo*`, `--rosa-solido`), e o anel duplo é o
   mesmo. ⚠️ ESTE PARÁGRAFO PREVIA O QUE JÁ ACONTECEU: "quando a etapa 3 trocar
   a marcação do console, `.admin-acao` fica sem consumidor e vira candidata a
   remoção — em tarefa própria, com medição, nunca junto da entrada". A tarefa
   própria foi a 3e e `.admin-acao` SAIU; agora a tecla não tem irmã de densidade
   nenhuma no console, e os 40px daqui são o único alvo dos botões de lá —
   quatro abaixo do piso de 44px da PRIMEIRA LINHA desta folha, o que está
   registrado no bloco "O ALVO DE 44px DO CONSOLE SAIU DAQUI" (§admin).
   -------------------------------------------------------------------------- */
.cabine-tecla {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--e-2);
    min-height: 40px;
    padding: 9px 15px;
    border: 1px solid transparent;
    border-radius: var(--raio-tecla);
    font-family: var(--f-display);
    font-size: var(--fs-2);
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    background: transparent;
    color: var(--cor-texto-medio);
    transition:
        background-color var(--mov-rapido) var(--curva-padrao),
        color var(--mov-rapido) var(--curva-padrao),
        box-shadow var(--mov-rapido) var(--curva-padrao),
        transform var(--mov-rapido) var(--curva-padrao);
}

.cabine-tecla svg {
    flex: none;
}

/* ⚠️ AS CLASSES `.cabine-e-*` NÃO SÃO ENFEITE DE DEMO: elas fixam na folha o
   ESTADO que só existe sob o dedo, e é assim que os seis microestados podem ser
   renderizados com a engine real numa tela de conferência. Elas viajam de graça
   — moram no mesmo seletor do estado que já é escrito. */
.cabine-tecla--fantasma {
    border-color: var(--fio-2);
    background: var(--tecla-fantasma);
}

.cabine-tecla--fantasma:hover,
.cabine-tecla--fantasma.cabine-e-hover {
    background: var(--tecla-fantasma-hover);
    color: var(--cor-texto);
}

.cabine-tecla--fantasma:active,
.cabine-tecla--fantasma.cabine-e-press {
    background: var(--sup-press);
    box-shadow: var(--afundado);
    transform: translateY(1px);
}

/* O preenchimento vivo, e a tinta em cima dele vai ao extremo do papel
   (`--tinta-viva`) — a regra (c) da direção, a mesma de `.btn`. */
.cabine-tecla--acesa {
    font-weight: 700;
    background: var(--acento);
    color: var(--tinta-viva);
    box-shadow: var(--elev-1);
}

.cabine-tecla--acesa:hover,
.cabine-tecla--acesa.cabine-e-hover {
    background: var(--acento-forte);
    box-shadow: var(--elev-2);
}

.cabine-tecla--acesa:active,
.cabine-tecla--acesa.cabine-e-press {
    background: var(--acento-fundo);
    box-shadow: var(--afundado);
    transform: translateY(1px);
}

/* DESTRUTIVO DISCRETO EM REPOUSO. A tinta também anda no hover: `--rosa-forte`
   é o vermelho que ganha presença quando o fundo escurece — sem ele a única
   coisa que se move é a superfície, e o rótulo perde contraste relativo. */
.cabine-tecla--perigo {
    border-color: transparent;
    background: var(--tecla-perigo);
    color: var(--cor-erro-texto);
}

.cabine-tecla--perigo:hover,
.cabine-tecla--perigo.cabine-e-hover {
    background: var(--tecla-perigo-hover);
    color: var(--rosa-forte);
}

.cabine-tecla--perigo:active,
.cabine-tecla--perigo.cabine-e-press {
    transform: translateY(1px);
}

/* SÓLIDO SÓ DEPOIS DA CONFIRMAÇÃO. `--rosa-solido` existe para isto e já sabe
   trocar de valor no escuro (branco sobre o rosa claro mediria 2,99:1). */
.cabine-tecla--perigo-cheia {
    border-color: transparent;
    font-weight: 700;
    background: var(--rosa-solido);
    color: var(--tinta-viva);
    box-shadow: var(--elev-1);
}

/* O DESLIGADO NÃO É `opacity` — rebaixar opacidade rebaixa contraste e o par
   deixa de ser mensurável. `--tecla-fantasma-off` é a superfície apagada
   medida, com a tinta de apoio por cima. `[aria-disabled]` entra junto porque
   `<a>` não aceita `disabled`. */
.cabine-tecla:disabled,
.cabine-tecla[disabled],
.cabine-tecla[aria-disabled="true"],
.cabine-tecla.cabine-e-desativada {
    border-color: var(--fio-1);
    background: var(--tecla-fantasma-off);
    color: var(--cor-texto-suave);
    box-shadow: none;
    transform: none;
    cursor: not-allowed;
}

/* O estado de foco desenhado como CLASSE, para a tela de conferência. Mesmo
   par de sombras da regra `:focus-visible` acima. */
.cabine-tecla.cabine-e-foco {
    box-shadow: 0 0 0 2px var(--anel-folga), 0 0 0 4px var(--anel), var(--elev-1);
}

/* O giro lê a PRÓPRIA tinta do botão (`currentColor`): serve aos dois modos e
   às cinco variantes sem um token novo. */
.cabine-girando {
    width: 14px;
    height: 14px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    opacity: 0.9;
    animation: cabine-girar 720ms linear infinite;
}

@keyframes cabine-girar {
    to {
        transform: rotate(360deg);
    }
}

/* -----------------------------------------------------------------------------
   9. O CANAL DO TRACEJADO — "ainda não é verdade"
   -----------------------------------------------------------------------------
   Tracejado = marcado, ainda não aconteceu. Fio inteiro = já aconteceu. O canal
   sobrevive a daltonismo e a impressão em preto e branco, e `--fio-pendente`
   existe nesta folha com esse cargo declarado.
   -------------------------------------------------------------------------- */
.cabine-par {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--e-3);
    align-items: start;
}

.cabine-fila {
    display: grid;
    gap: 9px;
    list-style: none;
}

.cabine-fila-item {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 9px;
    padding: 13px 15px;
    border: 1px dashed var(--fio-pendente);
    border-radius: var(--raio-tecla);
    background: var(--fundo-fila);
}

.cabine-fila-topo {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 10px;
}

.cabine-fila-topo strong {
    font-weight: 700;
    color: var(--cor-texto-medio);
}

.cabine-fila-topo span {
    margin-left: auto;
    font-size: var(--fs-2);
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto-suave);
}

.cabine-fila-estado {
    display: flex;
    align-items: center;
    gap: var(--e-2);
    font-family: var(--f-display);
    font-size: var(--fs-1);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--cor-texto-suave);
}

.cabine-fila-estado--rodando {
    color: var(--cor-acento);
}

/* O INDETERMINADO. Aqui `overflow:hidden` é obrigatório — é ele que segura a
   faixa que corre dentro do trilho — e não há foco dentro desta peça, então ele
   não reabre o BUG-TD-102. */
.cabine-trilho-progresso {
    position: relative;
    overflow: hidden;
    height: 6px;
    border-radius: var(--raio-pilula);
    background: var(--trilho-barra);
    box-shadow: var(--afundado);
}

.cabine-trilho-progresso::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image: linear-gradient(90deg, transparent, var(--acento), transparent);
    transform: translateX(-100%);
    animation: cabine-correr 1500ms var(--curva-padrao) infinite;
}

@keyframes cabine-correr {
    to {
        transform: translateX(100%);
    }
}

/* O RECIBO — o que já aconteceu, com fio inteiro. */
.cabine-recibo {
    display: grid;
    gap: 9px;
    padding: 13px 15px;
    border: 1px solid var(--fio-2);
    border-radius: var(--raio-tecla);
    background: var(--fundo-recibo);
}

.cabine-recibo-linha {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 10px;
    font-size: var(--fs-2);
}

.cabine-recibo-linha b {
    font-family: var(--f-display);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto);
}

.cabine-recibo-linha span {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto-suave);
}

.cabine-recibo-total {
    padding-top: 9px;
    border-top: 1px solid var(--fio-2);
    color: var(--cor-sucesso-texto);
}

.cabine-recibo-total b {
    color: var(--cor-sucesso-texto);
}

/* -----------------------------------------------------------------------------
   10. ZONA DE RISCO — discreta em repouso, sólida só na confirmação
   -----------------------------------------------------------------------------
   A gradação é deliberada: a seção é um cartão de tom rosado, o gatilho é um
   `<summary>` de superfície própria e SÓ o botão da confirmação digitada é
   sólido. Ato destrutivo do mesmo tamanho e na mesma fila dos caminhos é erro
   de clique esperando acontecer.
   -------------------------------------------------------------------------- */
.cabine-risco {
    display: grid;
    gap: var(--e-3);
    padding: var(--e-4);
    border: 1px solid var(--fio-2);
    border-radius: var(--raio-peca);
    background: var(--fundo-risco);
    box-shadow: var(--elev-cabine);
}

.cabine-risco h2 {
    font-family: var(--f-display);
    font-size: var(--fs-4);
    font-weight: 600;
    color: var(--cor-erro-texto);
}

.cabine-risco p {
    max-width: 66ch;
    font-size: var(--fs-2);
    color: var(--cor-texto-medio);
}

.cabine-risco p strong {
    color: var(--cor-texto);
}

.cabine-risco code {
    padding: 1px 6px;
    border-radius: 5px;
    font-family: var(--f-display);
    font-weight: 600;
    background: var(--sup-cartao);
    color: var(--cor-texto);
}

.cabine-risco-detalhes {
    padding-top: var(--e-3);
    border-top: 1px solid var(--fio-2);
}

.cabine-risco-detalhes summary {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    padding: 9px 14px;
    border-radius: var(--raio-tecla);
    list-style: none;
    font-family: var(--f-display);
    font-size: var(--fs-2);
    font-weight: 600;
    cursor: pointer;
    background: var(--fundo-risco-2);
    color: var(--cor-erro-texto);
    transition: background-color var(--mov-rapido) var(--curva-padrao);
}

.cabine-risco-detalhes summary::-webkit-details-marker {
    display: none;
}

.cabine-risco-detalhes summary:hover,
.cabine-risco-detalhes[open] summary {
    background: var(--tecla-perigo-hover);
}

.cabine-confirmacao {
    display: grid;
    gap: 11px;
    max-width: 520px;
    margin-top: 13px;
}

.cabine-confirmacao label {
    font-size: var(--fs-2);
    color: var(--cor-texto-medio);
}

.cabine-confirmacao label b {
    font-family: var(--f-display);
    letter-spacing: 0.06em;
    color: var(--cor-erro-texto);
}

/* ⚠️ ESTE É O `<input>`, E `.campo` DESTA FOLHA É O INVÓLUCRO — por isso o
   prefixo não é opcional aqui. `--fs-3` são 16px e o piso é de PLATAFORMA, não
   de estética: abaixo de 16px o iOS dá zoom sozinho ao focar. */
.cabine-campo {
    width: 100%;
    min-height: var(--alvo-toque);
    padding: 11px 13px;
    border: 1px solid var(--fio-controle);
    border-radius: var(--raio-tecla);
    font-family: var(--f-display);
    font-size: var(--fs-3);
    background: var(--sup-campo);
    color: var(--cor-texto);
}

.cabine-campo::placeholder {
    color: var(--cor-texto-suave);
}

/* O inventário do que vai sumir, ao lado de um filete: quem confirma um ato sem
   desfazer lê o número antes de digitar a palavra. */
.cabine-confirmacao-inventario {
    padding-left: var(--e-3);
    border-left: 2px solid var(--fio-2);
    font-size: var(--fs-2);
    color: var(--cor-texto-suave);
}

.cabine-confirmacao-inventario b {
    font-family: var(--f-display);
    font-variant-numeric: tabular-nums;
    color: var(--cor-texto);
}

/* A fileira de atos solta, fora de um cartão. */
.cabine-acoes-linha {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--e-2);
    margin-top: 2px;
}

/* -----------------------------------------------------------------------------
   11. MOVIMENTO REDUZIDO — a versão sem movimento é DECIDIDA, não sobrou
   -----------------------------------------------------------------------------
   ⚠️ O BLOCO GLOBAL DO DEMO (`*{animation-duration:1ms}`) NÃO ENTROU, e a
   recusa é da casa: ele apagaria o `.cam-flash-on`, que é a única confirmação
   de que a foto foi tirada, e levaria as listras do medidor indeterminado ao
   estado final em vez de pará-las visíveis. Cada família leva o próprio freio.
   O QUE FICA: toda troca de COR e de SUPERFÍCIE, porque cor de estado é
   informação. O QUE SAI: entrada em escada, deslocamento e laço perpétuo.
   A faixa que corre vira listra PARADA — o estado continua legível sem nada se
   mexer, e um medidor indeterminado sem nenhuma marca leria como "vazio".
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .cabine-heroi-num {
        animation: none;
    }

    /* T-0031 4a: a régua do balde e de confirmações ganhou especificidade própria
       (`.cabine-barra .cabine-barra-fill`, 0,2,0) para vencer `.barra span` — e
       com isso deixou de herdar o freio de `.barra span` no bloco de cima. O freio
       tem de vir DEPOIS da regra dela na folha, e é por isso que mora aqui. O FATO
       continua: a largura vem do elemento (`data-progresso`), então a barra chega
       ao valor certo — só não desliza. Medido na engine sob `reduce`. */
    .cabine-barra .cabine-barra-fill {
        transition: none;
    }

    .cabine-tecla:active,
    .cabine-tecla.cabine-e-press,
    .cabine-conta:hover {
        transform: none;
    }

    .cabine-girando {
        animation: none;
    }

    .cabine-trilho-progresso::after {
        transform: none;
        background-image: repeating-linear-gradient(
            -45deg,
            var(--acento) 0 6px,
            transparent 6px 12px
        );
        opacity: 0.75;
        animation: none;
    }
}

/* -----------------------------------------------------------------------------
   30rem (480px) — O TELEFONE DEITADO
   -----------------------------------------------------------------------------
   É a largura em que 100 % deixa de ser "alvo confortável" e vira faixa: numa
   caixa de 448px, um botão de 448px tem quase três vezes a largura do próprio
   rótulo, e botão-faixa não parece botão — parece cabeçalho.
   -------------------------------------------------------------------------- */
@media (min-width: 30rem) {
    /* -------------------------------------------------------------------------
       O PAINEL DO DONO NO ARQUIVO DO STITCH (T-0038) — nada vira aqui. O
       arquivo vira em `sm` (40rem), `md` (48rem) e `lg` (64rem); a regra da
       casa que poria o `.painel-cabecalho` em linha neste ponto é vencida, dentro
       de `.dono`, pela do arquivo (`.dono .painel-cabecalho`, 0,2,0).
       ---------------------------------------------------------------------- */
    .campo-grupo {
        flex-direction: row;
        gap: 12px;
    }

    .painel-cabecalho {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .form-acoes {
        flex-direction: row;
        justify-content: flex-end;
        align-items: center;
        flex-wrap: wrap;
    }

    .form-acoes .btn,
    .form-acoes .btn-secundario {
        width: auto;
    }

    .form-acoes .btn {
        min-width: 180px;
    }

    /* -------------------------------------------------------------------------
       ⚠️ AQUI HAVIA `.admin-conta-prazo { flex: 0 1 23rem; order: 0; flex-wrap:
       nowrap }` — A CÉLULA DO PRAZO COMO COLUNA DE UMA LINHA FLEX. A T-0031
       trocou a linha de triagem por GRADE (§7, `.cabine-conta-leitura`), e as
       TRÊS declarações passaram a não pintar nada: `flex` e `order` porque o pai
       não é mais flex, e `flex-wrap` porque o próprio elemento resolve
       `display: grid` desde a etapa 3 (é `.cabine-prazo` que vence a cascata —
       conferido no valor computado da tela servida, não deduzido).
       QUEM FAZ O TRABALHO AGORA: a trilha da grade. As `23rem` que este bloco
       reservava eram legenda (17rem) + vão + barra (5,5rem) numa ÚNICA linha; na
       grade a célula empilha legenda e barra, e a coluna do prazo é a quarta
       trilha do gabarito de 64rem.
       O bloco de 30rem fica com a âncora, que continua sendo dele. */

    /* A âncora: desde a T-0038 o cabeçalho tem 80px FIXOS em toda largura, e o
       valor é o mesmo da regra base (80 + 8). Ele continua escrito aqui porque o
       bloco de 30rem é o dono da âncora; o porquê inteiro, com as medições e com
       a dívida do `scroll-padding-top` de raiz, está na regra base de
       `.admin-conta-linha`. */
    .admin-conta-linha {
        scroll-margin-top: 88px;
    }

    /* -------------------------------------------------------------------------
       A CABINE (T-0031, etapa 2d) — só o respiro do contêiner.
       ⚠️ O DEMO TINHA CINCO PONTOS DE VIRADA (400, 560, 760, 900 e 1080px) E
       ESTA FOLHA TEM TRÊS, por decisão desta casa: "três `@media (min-width` e
       zero `@media (max-width`". Criar cinco pontos novos quebraria o contrato
       de layout do produto para vestir uma tela. A compressão declarada é:
       400 → 30rem · 560 e 760 → 48rem · 900 e 1080 → 64rem. Sempre para o ponto
       SEGUINTE, nunca para o anterior: empilhar por mais tempo é o erro barato,
       espremer duas colunas cedo demais é o caro.
       ---------------------------------------------------------------------- */
    .cabine {
        padding: 0 18px 72px;
    }
}

/* -----------------------------------------------------------------------------
   40rem (640px) — O PONTO DA VITRINE (T-0017)
   -----------------------------------------------------------------------------
   ⚠️ É O QUARTO VALOR DESTA FOLHA, E ELE TEM DONO: OS ARQUIVOS DO STITCH. Até a
   T-0038 só a vitrine morava aqui; o painel do dono (o segundo arquivo do
   Stitch, mesmo `sm` de 640px) passou a morar também.
   O desenho do arquivo do Stitch, aprovado pelo usuário (TD-082), vira em 640px
   o topo (logo de 30 → 36 px, botão de modo de 36 → 40 px, "Entrar" aparece),
   os botões do herói (empilhados → em linha), os três números do herói, o
   quadro de exemplo e o rodapé — e a decisão 9 do usuário fala em "abaixo de
   640 px". Comprimir para 48rem, como a cabine fez com os pontos dela (T-0031),
   mudaria a página aprovada entre 640 e 767px: o topo de celular apareceria num
   telefone deitado. Fica declarado para o `especialista-responsividade`, que
   valida os pontos de virada, e a tabela do placar, mais acima, ganhou a linha.
   -------------------------------------------------------------------------- */
@media (min-width: 40rem) {
    /* -------------------------------------------------------------------------
       O PAINEL DO DONO NO ARQUIVO DO STITCH (T-0038) — o `sm:` do arquivo.
       ⚠️ ESTE BLOCO DEIXOU DE SER SÓ DA VITRINE: o `sm` do Tailwind é 640px nos
       dois arquivos do Stitch, e é aqui que o painel do dono vira o topo (a
       marca de 36px e o "Sair" com rótulo), a saudação, o bilhete, as grades de
       duas colunas e os botões que deixam de ocupar a faixa inteira.
       ---------------------------------------------------------------------- */
    main.container:has(> .dono) {
        padding-inline: var(--e-6);
    }

    .dono-topo-faixa {
        gap: var(--e-3);
        padding-inline: var(--e-6);
    }

    .dono-topo .logo-img {
        height: 36px;
    }

    .dono-topo-acoes {
        gap: var(--e-2);
    }

    .dono-topo-filete {
        display: block;
    }

    .dono-sair-rotulo {
        position: static;
        width: auto;
        height: auto;
        overflow: visible;
        clip-path: none;
    }

    .dono-rodape-faixa {
        flex-direction: row;
        padding-inline: var(--e-6);
        text-align: left;
    }

    .dono-rodape-ponto {
        display: inline;
    }

    .dono .dono-saudacao {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .dono-tecla-criar {
        align-self: auto;
    }

    .dono-aviso {
        padding: var(--e-5);
    }

    .dono-vazio {
        padding: 3rem;
    }

    .dono-tecla-grande {
        width: auto;
    }

    .dono-vazio-garantias {
        gap: var(--e-6);
    }

    .dono-vazio-ponto {
        display: inline;
    }

    .dono-conta-cartao {
        padding: 1.75rem;
    }

    .dono-conta-info {
        align-items: center;
    }

    .dono-conta-acoes {
        flex-direction: row;
        align-items: center;
    }

    .dono-palco-corpo,
    .dono-palco-pe {
        padding: var(--e-8);
    }

    .dono-palco-identidade {
        flex-direction: row;
        align-items: center;
    }

    .dono .dono-bilhete {
        width: 6rem;
        height: 7rem;
    }

    .dono .palco-titulo {
        font-size: 2.125rem;
        line-height: 2.5rem;
    }

    .dono .palco-meta {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .dono .dono-palco-link-linha {
        flex-direction: row;
        align-items: center;
    }

    .dono .palco-destinos {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .dono-perigo {
        flex-direction: row;
        align-items: center;
    }

    .dono-perigo-tecla {
        width: auto;
    }

    /* O Manual do convidado (T-0037) mora na mesma coluna larga e veste o
       mesmo recuo das duas seções do arquivo acima dele. */
    .dono .dono-secao-dados,
    .dono .dono-secao-dress,
    .dono .dono-secao-manual {
        padding: var(--e-8);
    }

    .dono .dono-secao-dados .secao-cab p {
        font-size: var(--dono-corpo-md);
        line-height: 1.25rem;
    }

    .dono .escolha-visual {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .dono-evento .campo-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .dono .dono-pix-grade {
        grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    }

    .dono .campo-curto input {
        max-width: 11rem;
    }

    .dono .dono-form-acoes {
        flex-direction: row;
        justify-content: flex-end;
        align-items: center;
    }
    .vitrine-topo-faixa {
        gap: var(--e-6);
        padding-inline: var(--e-6);
    }

    .vitrine-marca-topo {
        height: 36px;
    }

    .vitrine-topo-acoes {
        gap: var(--e-4);
    }

    .vitrine-modo {
        width: 2.5rem;
        height: 2.5rem;
    }

    .vitrine-topo-acoes .vitrine-tecla-suave {
        display: inline-flex;
    }

    .vitrine-tecla-topo {
        padding-inline: var(--e-5);
        font-size: var(--vitrine-corpo-md);
    }

    .vitrine-acao-heroi .vitrine-acao-botoes {
        flex-direction: row;
        align-items: center;
    }

    .vitrine-acao-convite .vitrine-acao-botoes {
        flex-direction: row;
    }

    .vitrine-acao-convite .vitrine-acao-principal {
        width: auto;
    }

    .vitrine-heroi-numeros {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .vitrine-quadro {
        padding: 1.75rem;
    }

    /* Doze trilhas, sete e cinco: é a conta do arquivo, e ela dá os 266,3 e
       185,7 px medidos na demo; `7fr 5fr` erraria por 2,6 px. */
    .vitrine-quadro-total {
        grid-template-columns: repeat(12, minmax(0, 1fr));
    }

    .vitrine-quadro-total-texto {
        grid-column: span 7;
    }

    .vitrine-quadro-anel-coluna {
        grid-column: span 5;
        justify-content: flex-end;
    }

    .vitrine-quadro-hora {
        display: inline;
    }

    .vitrine-citacao-cartao {
        flex-direction: row;
        align-items: flex-start;
        padding: var(--e-10);
    }

    .vitrine-prazo {
        padding: 3rem;
    }

    .vitrine-convite {
        padding: 3.5rem;
    }

    .vitrine-rodape-base {
        flex-direction: row;
    }

    .vitrine-rodape-base-links {
        justify-content: flex-end;
    }
}

/* -----------------------------------------------------------------------------
   48rem (768px) — O TABLET EM PÉ
   -----------------------------------------------------------------------------
   É onde a coluna de formulário (35rem = 560px) para de encostar nas bordas:
   768 − 560 = 208px, 104 de cada lado.

   Na vitrine (T-0017) é onde o menu do topo aparece e onde os passos, as
   vantagens e o rodapé ganham colunas — o `md` do arquivo do Stitch, que cai
   exatamente neste valor.
   -------------------------------------------------------------------------- */
@media (min-width: 48rem) {
    /* -------------------------------------------------------------------------
       O PAINEL DO DONO NO ARQUIVO DO STITCH (T-0038) — o `md:` do arquivo:
       o cabeçalho das telas em linha, o cartão da conta em linha, os três
       passos, o pé do canhoto e a conta em duas colunas.
       ---------------------------------------------------------------------- */
    .dono .painel-cabecalho {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
    }

    .dono .painel-cabecalho .btn-secundario,
    .dono-tecla-voltar {
        align-self: auto;
    }

    .dono .dono-cabecalho .subtitulo {
        font-size: var(--dono-corpo-lg);
        line-height: 1.5rem;
    }

    .dono-conta-cartao {
        flex-direction: row;
        align-items: center;
    }

    .dono-conta-acoes {
        padding-left: 0;
    }

    .dono-passos {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .dono-palco-pe {
        flex-direction: row;
        align-items: center;
    }

    .dono-conta-grade {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .vitrine-menu {
        display: flex;
    }

    .vitrine-passos {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .vitrine-vantagens {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .vitrine-rodape-grade {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }

    /* ⚠️ ACHADO MEDIDO NESTA ETAPA, E ESTA REGRA NÃO FAZ NADA — nem aqui, nem
       na base do arquivo (`main { padding: 26px 16px 56px }`).
       Os dois layouts renderizam `<main class="container">`, e
       `.container { padding: 0 16px }` é UMA CLASSE (0,1,0) contra `main`, que é
       UM TIPO (0,0,1). A classe vence sempre, em qualquer ordem de arquivo: o
       `<main>` do produto inteiro tem `padding-top: 0` e `padding-bottom: 0`, em
       todas as 18 telas, em todas as larguras. O "respiro no desktop" que a
       especificação §A.2 dá por existente nunca existiu.
       NÃO CORRIGIDA AQUI de propósito: a correção é uma linha
       (`main.container { padding-top: 26px; padding-bottom: 56px }`, e 40px
       aqui), mas ela mexe no ritmo vertical das 18 telas de uma vez, na última
       etapa antes do gate. Está no relatório com o diagnóstico e a linha pronta.
       Fica VISÍVEL aqui para que ninguém volte a contar com ela. */
    main {
        padding-top: 40px;
    }

    /* O RESPIRO DO PALCO. Mesma lei que a faixa de tinta da página inicial da
       T-0015 seguia (ela saiu com a T-0017): campo de cor grande pede
       mais ar por dentro do que a distância que separa dois blocos comuns —
       senão ele lê como tarja, e não como abertura. Aqui a banda não sangra até
       a borda da janela, então o degrau é `--e-10`/`--e-8` e não `--e-16`. */
    .palco-conteudo {
        padding: var(--e-10) var(--e-10) var(--e-8);
    }

    .palco-link {
        padding: 0 var(--e-10) var(--e-8);
    }

    .card {
        padding: 32px 28px;
    }

    .card h1 {
        font-size: 1.5rem;
    }

    /* ⚠️ Também sem efeito na tela do convite: `.tema-convite .convite-titulo`
       (0,2,0) vence `.convite-titulo` (0,1,0) por especificidade, em qualquer
       ordem. Mantida porque `.convite-card`/`.convite-topo`/`.convite-titulo`
       são a família ANTIGA do cartão de convite, e provar que ela está morta é
       trabalho de varredura da F8, não de responsividade. */
    .convite-titulo {
        font-size: 1.9rem;
    }

    /* -------------------------------------------------------------------------
       A CABINE (T-0031, etapa 2d) — os pontos 560 e 760 do demo caem aqui.
       A linha da conta deixa de ser pilha e vira DUAS colunas: identidade à
       esquerda, estado e prazo à direita, alinhados pela mesma aresta.
       ---------------------------------------------------------------------- */
    .cabine-instrumentos {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .cabine-inst--heroi,
    .cabine-inst--balde {
        grid-column: span 2;
    }

    .cabine-par {
        grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    }

    /* ⚠️ A TRILHA DA DIREITA É `auto`, ENTÃO ELA VARIA DE LINHA PARA LINHA — e
       isso está certo aqui, ao contrário do que parece. Cada `<summary>` é uma
       GRADE PRÓPRIA: trilha `auto` não pode alinhar bordas ESQUERDAS entre
       linhas. Por isso as duas peças desta coluna são encostadas à DIREITA
       (`justify-self: end` no selo, `text-align: right` no prazo): a aresta que
       o olho persegue nesta faixa é a direita, e ela é comum às linhas porque a
       largura do cartão é. MEDIDO no próprio demo aprovado, a 768px: os cinco
       selos ficam em cinco abscissas esquerdas distintas e nenhuma à direita.
       O alinhamento por trilha FIXA só chega em 64rem, com as quatro colunas. */
    .cabine-conta-leitura,
    .admin-conta-linha {
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: start;
    }

    .cabine-conta-leitura .cabine-festa,
    .admin-conta-linha .cabine-festa {
        grid-column: 1;
    }

    .cabine-conta-leitura .cabine-selo,
    .admin-conta-linha .cabine-selo {
        grid-column: 2;
        grid-row: 1;
        justify-self: end;
    }

    .cabine-conta-leitura .cabine-prazo,
    .admin-conta-linha .cabine-prazo {
        grid-column: 2;
        justify-items: end;
        text-align: right;
    }
}

/* -----------------------------------------------------------------------------
   64rem (1024px) — A MESA
   -----------------------------------------------------------------------------
   É a largura em que 420 (formulário) + 20 (vão) + 560 (lista) = 1000 cabem sem
   apertar. É também onde a coluna de conteúdo do admin passa a ter 734px para
   uma tabela de sete colunas, contra os 540 que ela tinha nos 820px de antes.

   Na vitrine (T-0017) é o `lg` do arquivo do Stitch, no mesmo valor: o herói em
   duas colunas, as vantagens em três, as dúvidas em duas e o respiro maior das
   faixas de ponta a ponta.
   -------------------------------------------------------------------------- */
@media (min-width: 64rem) {
    /* -------------------------------------------------------------------------
       O PAINEL DO DONO NO ARQUIVO DO STITCH (T-0038) — o `lg:` do arquivo: a
       margem de 48px, a banda em 7 + 5, os quatro destinos numa linha, as duas
       colunas de "criar evento" e a letra dos campos do arquivo (aqui o iOS do
       telefone já não chega, e o zoom do BUG-TD-076 não acontece).
       ---------------------------------------------------------------------- */
    main.container:has(> .dono) {
        padding-inline: 3rem;
    }

    .dono-topo-faixa,
    .dono-rodape-faixa {
        padding-inline: 3rem;
    }

    .dono-modo {
        width: 2.5rem;
        height: 2.5rem;
    }

    .dono-palco-corpo {
        grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
        gap: 3rem;
        padding: var(--e-10);
    }

    .dono .palco-destinos {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }

    .dono .dono-grade-evento {
        grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    }

    .dono .painel-cabecalho:not(.dono-saudacao) h1 {
        font-size: 2.25rem;
        line-height: 2.5rem;
    }

    .dono .palco-campo,
    .dono .campo :is(input, select, textarea):not([type="checkbox"], [type="radio"], [type="file"]) {
        font-size: var(--dono-corpo-md);
    }

    .dono .dono-pix-grade .campo :is(input, select),
    .dono .dono-secao-dress .campo textarea {
        font-size: var(--dono-miudo);
    }
    .vitrine-topo-faixa,
    .vitrine-heroi-faixa,
    .vitrine-rodape-faixa {
        padding-inline: 3rem;
    }

    .vitrine-heroi {
        padding-block: 5rem;
    }

    /* Doze trilhas com seis de cada lado, no arquivo: são duas colunas iguais com
       os 56px de vão (564 + 56 + 564 = 1184 úteis a 1280, medido na demo). */
    .vitrine-heroi-grade {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 3.5rem;
    }

    .vitrine-vantagens {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }

    .vitrine-duvidas {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    /* O PALCO EM DUAS COLUNAS — a festa à esquerda, o farol à direita.
       ⚠️ O PROTÓTIPO VIRA EM 56rem, E ESSE VALOR NÃO ENTROU. Ele seria um QUARTO
       ponto de virada numa folha que acabou de sair de nove para três, e o
       dicionário desta seção já tem a linha exata para o que está acontecendo
       aqui: `--bp-3` (64rem, "a mesa") é onde "painel e admin viram DUAS
       COLUNAS". Medido na caixa: em 1024px de viewport o contêiner largo dá
       976px úteis, e com o farol em 15rem mais o vão de `--e-10` sobram 696px
       para a festa — contra os 440px que 48rem entregariam. Abaixo daqui o farol
       vai para baixo da identidade, em largura total. */
    .palco-conteudo {
        grid-template-columns: minmax(0, 1fr) auto;
        gap: var(--e-10);
        align-items: start;
    }

    .palco-farol {
        min-width: min(100%, 15rem);
    }

    .palco-titulo {
        font-size: var(--fs-7);
    }

    .grade-convidados {
        grid-template-columns: 420px minmax(0, 1fr);
    }

    .grade-convidados .card,
    .grade-convidados .form-secao {
        margin-bottom: 0;
    }

    .grade-painel {
        grid-template-columns: 420px minmax(0, 1fr);
    }

    .grade-painel.inverso {
        grid-template-columns: minmax(0, 1fr) 360px;
    }

    /* 15rem (240px) e não 230: 230 não está em escala nenhuma, e a lateral do
       admin é o único lugar do produto com uma largura fixa de navegação. */
    .admin {
        grid-template-columns: 15rem minmax(0, 1fr);
        align-items: start;
    }

    /* ⚠️ `.admin-nav nav` SAIU DAQUI (T-0031 3e — ver "O QUE SAIU DA FOLHA" na
       §admin): a lateral do admin não é mais emitida, e quem faz o papel dela é
       `.cabine-rail`, logo abaixo neste mesmo bloco.
       ⚠️ E A REGRA `.admin` ACIMA FICA, mas quem manda no gabarito de duas
       colunas hoje é `.cabine-corpo` (214px, mais abaixo): mesma
       especificidade, declarada DEPOIS, então é ela que vence. `.admin` segue
       VIVA no DOM — não é órfã, é regra sombreada, e desfazer sombra de classe
       viva é outra tarefa, com outra medição. */

    .admin-grid2 {
        grid-template-columns: 1.4fr 1fr;
    }

    /* -------------------------------------------------------------------------
       A CABINE (T-0031, etapa 2d) — os pontos 900 e 1080 do demo caem aqui.
       ⚠️ DÍVIDA DECLARADA PARA O `especialista-responsividade`: no demo a
       leitura de QUATRO colunas nascia em 900px e o trilho só virava coluna em
       1080 — 180px de folga entre as duas coisas. Comprimidas no mesmo ponto,
       em 1024px de viewport sobram ~736px para o `<main>` contra os ~870 que o
       gabarito de quatro colunas foi desenhado para ocupar. Nada estoura (todas
       as trilhas são `minmax(0, …)` e a coluna do nome tem piso zero), mas o
       nome de pessoa passa a quebrar em duas linhas antes do que quebrava no
       demo. Medir e arbitrar é da etapa de responsividade; inventar um quarto
       ponto de virada aqui, não.
       ---------------------------------------------------------------------- */
    .cabine {
        padding: 0 26px 80px;
    }

    .cabine-corpo {
        grid-template-columns: 214px minmax(0, 1fr);
        gap: 22px;
    }

    /* O trilho vira coluna e ACOMPANHA a rolagem: a lista de contas tem 1,6
       tela de altura medida, e o operador volta ao trilho o tempo todo. */
    .cabine-rail {
        position: sticky;
        top: var(--e-4);
        flex-direction: column;
        gap: 3px;
    }

    .cabine-rail a {
        flex: none;
    }

    .cabine-instrumentos {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }

    .cabine-inst--heroi {
        grid-column: span 2;
        grid-row: span 2;
    }

    .cabine-inst--balde {
        grid-column: span 2;
    }

    .cabine-contas-cabeca {
        display: grid;
    }

    /* -------------------------------------------------------------------------
       AS DUAS TRILHAS FIXAS TROCARAM DE TAMANHO — 148/172 em vez de 172/150
       -------------------------------------------------------------------------
       ⚠️ É A ÚNICA DIVERGÊNCIA NUMÉRICA DESTA GRADE EM RELAÇÃO AO DEMO, e ela
       existe porque o CONTEÚDO das duas colunas é outro. MEDIDO nesta etapa, na
       fonte da tela (`--f-display`, Space Grotesk):

         ESTADO — os cinco rótulos que `_conta.php` pode emitir medem, com a
         pastilha inteira: `Prazo vencido` 130,9 · `Desativada` 109,2 ·
         `Pode criar` 106,9 · `A vencer` 94,0 · `No ar` 72,4. O maior deles cabe
         em 148px com 17,1px de folga. Os 172px do demo vestiam selos de até
         141,9px, que são os DELE.

         PRAZO — as 14 legendas servidas medem 226,2 (×2) · 160,0 · 158,4 ·
         151,6 · 150,0 · e as oito restantes abaixo de 92. Com os 150px do demo,
         SEIS das catorze embrulhavam, e embrulhavam feio: `sem festa · faltam
         102 d` virava `sem festa · faltam 102` + `d`, com o `d` sozinho na
         segunda linha. Com 172px embrulham DUAS — as de 226,2 —, e essas duas
         embrulham no separador, que é a quebra que a célula aceita.

       O TOTAL FIXO É PRATICAMENTE O MESMO (320px contra os 322 do demo), então
       as duas trilhas elásticas não pagam a conta: a coluna do nome fica em
       222px contra os 220px de antes. Não é a coluna do nome que cede — são os
       41px que o selo tinha de sobra que mudam de dono.
       ⚠️ QUEM MEXER NESTES DOIS NÚMEROS MEXE TAMBÉM EM `.cabine-contas-cabeca`:
       o gabarito está escrito nos dois lugares porque o cabeçalho é irmão da
       lista, não filho dela, e não há como ele herdar as trilhas. */
    .cabine-conta-leitura,
    .admin-conta-linha {
        grid-template-columns: minmax(0, 2fr) minmax(0, 1.8fr) 148px 172px;
        gap: 14px;
        align-items: center;
    }

    .cabine-conta-leitura .cabine-festa,
    .admin-conta-linha .cabine-festa {
        grid-column: 2;
    }

    .cabine-conta-leitura .cabine-selo,
    .admin-conta-linha .cabine-selo {
        grid-column: 3;
        grid-row: 1;
        justify-self: start;
    }

    .cabine-conta-leitura .cabine-prazo,
    .admin-conta-linha .cabine-prazo {
        grid-column: 4;
        grid-row: 1;
        justify-items: end;
        text-align: right;
    }

    /* -------------------------------------------------------------------------
       A QUARTA TRILHA TEM OS 150px DO DEMO, E O CONTEÚDO DELA AQUI É OUTRO
       -------------------------------------------------------------------------
       No demo aquela célula é `22/08/2026` + `há 12 dias`, que cabem em 150px.
       Aqui ela é a legenda do prazo, cujo pior caso — `sem festa · venceu há
       1000 d · estendido`, montado por `legendaDoPrazo()` — MEDE 267,6px na fonte
       de hoje (Space Grotesk 13,6px/600, medido nesta etapa; os fallbacks dão
       263,8 / 251,5 / 249,5). A legenda longa ocupa DUAS linhas dentro da célula,
       que é exatamente a forma que a célula tem no demo: duas linhas empilhadas,
       encostadas à direita. A legenda curta — o caso das 14 contas das fixtures —
       continua numa linha só. Quem permite isso é a saída do `nowrap`, na regra
       base de `.admin-conta-legenda`, com a medição que a obrigou.

       ALTERNATIVA PESADA E RECUSADA: alargar a quarta trilha para `17rem`. A
       fileira media 798px quando isto foi escrito (o `.painel-largo .container`
       capava em 1160 e o trilho lateral come 236), e com 272px na quarta trilha
       sobrariam 141px para o NOME e 127px para a festa — MEDIDO, não estimado.
       Trocar uma legenda de duas linhas por um nome de três não é ganho.

       ⚠️ O 798 ACIMA É HISTÓRICO, e fica por ser o número que sustentou a
       recusa. O teto do console subiu para 1440px na etapa 3c da T-0031
       (`.painel-largo .container:has(> .cabine-corpo)`), e a fileira passou a
       medir o que está anotado lá. A ARBITRAGEM NÃO MUDA: as quatro trilhas
       continuam sendo as mesmas, e alargar a quarta segue sem ser ganho — o que
       o alargamento deu foi folga para as DUAS primeiras, que são elásticas. */
}
