/* =====================================================================================
   Atendimento Web — TEMA VISUAL (o clone da FloSeller Smart)  ·  E8
   CONTRATOS §5 · docs/API-V1.md §12 · dossie/04-IDENTIDADE-VISUAL.md

   O que este arquivo é: a PRIMEIRA folha da página. Ele define a paleta, a fonte e os
   componentes da plataforma nova, e re-veste a casca herdada do Financeiro Pro (app.css)
   no escuro da Smart. O objetivo é a equipe abrir e NÃO estranhar.

   ┌──────────────────────────────────────────────────────────────────────────────────┐
   │ 1. COMO ESTE ARQUIVO GANHA — leia antes de editar                                │
   └──────────────────────────────────────────────────────────────────────────────────┘
   tema.css é incluído ANTES de app.css (docs/API-V1.md §13.2). Em CSS, com a mesma
   especificidade, quem vem DEPOIS vence — ou seja, o :root do app.css venceria o :root
   daqui e o tema não pintaria nada. Por isso:

     · os tokens moram em  html:root        (0,1,1)  e vencem o  :root  (0,1,0) do app.css;
     · toda regra de componente HERDADO leva o prefixo  :root   (ex.: :root .toast),
       que sobe a especificidade de (0,1,0) para (0,2,0) e vence sem !important;
     · os componentes NOVOS (§12) não existem no app.css: vão sem prefixo.

   ⛔ Nada de !important aqui. ⛔ Nada de @layer: regra sem camada vence QUALQUER camada,
   e o app.css inteiro é sem camada — uma camada só perderia.

   ┌──────────────────────────────────────────────────────────────────────────────────┐
   │ 2. MODOS                                                                          │
   └──────────────────────────────────────────────────────────────────────────────────┘
   O ESCURO é o padrão — é como a equipe usa. Regra de decisão, nesta ordem:
     html sem data-tema            -> ESCURO   (padrão da casa; não depende do integrador)
     sistema em escuro, sem data-tema="claro" -> ESCURO
     html data-tema="escuro"       -> ESCURO
     html data-tema="claro"        -> CLARO    ("tudo branco": §7 e §17)
   Os NEUTROS ficam nos BANCOS (§5), escritos UMA vez; cada modo só mapeia. Marca, estado,
   etiquetas e sombras são literais de cada bloco de modo (§6 e §7), medidos par a par.
   ⭐ 18/09/2026 — QUEM TROCA é a chave sol/lua do cabeçalho (static/js/comp/tema.js): grava a
   escolha em localStorage "fp.tema" e escreve o data-tema no <html>. Um script inline no <head>
   do index.html aplica o atributo ANTES desta folha carregar, para não piscar escuro->claro.
   ⛔ prefers-color-scheme NÃO decide: sem escolha gravada é escuro, em qualquer sistema.
   O CLARO é conferido por tools/checar_contraste_tema.py, nos DOIS modos — ver §7 e §17.

   ┌──────────────────────────────────────────────────────────────────────────────────┐
   │ 3. CATÁLOGO DE CLASSES — o que existe e quando usar                              │
   └──────────────────────────────────────────────────────────────────────────────────┘
   ⛔ Classe CSS fantasma não estoura erro no console e já escondeu um rompimento inteiro.
   Se o nome não está aqui embaixo, ele NÃO EXISTE. Peça a E8 em vez de inventar.

   ESTADO POR ATRIBUTO (não por classe — o valor vem cru da API e um enum novo cai em
   neutro em vez de sumir):
     [data-estado="…"]   estado da fibra (docs/API-V1.md §3.1). Publica --e-cor / --e-tinta /
                         --e-texto para quem estiver dentro. Valores: fibra_ok · sinal_ruim ·
                         caindo_fibra · caindo_energia · evento_pon · so_ele_caiu ·
                         porta_olt_down · ont_trocada · voltou_pior · sem_ont · ont_removida ·
                         nao_sei_dizer. ⛔ Sem valor / valor desconhecido = CINZA neutro.
     [data-nivel="…"]    idade da espera: ok · atencao · critico · indefinido.
                         ⛔ indefinido (limiar [confirmar]) fica NEUTRO — nunca vermelho.
     [data-frescor="…"]  ao_vivo · dado_antigo · sem_espelho (docs/API-V1.md §3.2).
     ⛔ Cor sozinha não serve: #C10015 como texto sobre #090E11 mede 3,03 e reprova.
        O emoji anda junto, sempre — é ele que carrega o estado.

   CAIXA DE ENTRADA (§12.1)   .caixa (grid 344 · flex · 320) · .caixa-lista · .caixa-conversa ·
     .caixa-ficha · .caixa-lista-topo · .caixa-lista-itens · .caixa-ficha-corpo · .caixa-voltar
     .caixa.sem-ficha (2 colunas) · .caixa[data-ficha="aberta"] (ficha como gaveta, < 1024)
     .caixa[data-painel="lista|conversa"] (celular: qual painel está na frente)
   LINHA DA LISTA (§12.2)     .linha-conversa (2 andares, 48 px, borda esquerda 3 px = estado)
     .lc-emoji · .lc-corpo (os dois andares) · .lc-topo · .lc-nome · .lc-id ·
     .lc-espera (tabular-nums, direita) · .lc-base · .lc-trecho · .lc-fila · .lc-etiqueta ·
     .lc-nao-lidas · .linha-conversa.ativa
     .lc-alerta (a ⏳ de quem espera; âmbar acima do limiar por [data-alerta="1"]) ·
     .lc-puxar (a palavra "puxar", que entra no lugar do nome da fila reservada — a única informação
     redundante do 2º andar) — §12.2, ordem 1 do dono de 11/09 à noite. ⛔ A ⏳ NÃO substitui o marcador
     do assunto: os dois aparecem juntos. 12/09: .lc-emoji virou o MARCADOR da lista fechada do dono
     (📉 🔌 ⚡) e pode vir vazio ([data-vazio="1"]) — sem dado é sem ícone.
     ⭐⭐ 12/09 (equipe 2) — ONDE CADA UM MORA, e por que eles NÃO viram duas manchas coladas. Esta
     linha dizia "a ⏳ AO LADO do marcador", e isso ⛔ deixou de ser verdade quando o cartão virou a
     cópia da Smart (dossie/13): no .cx-cartao os dois ficam em ANDARES DIFERENTES do mesmo cartão —
     o marcador (.lc-emoji, 18 px) no 1º andar, colado ao nome (.cx-c-nome-l), e a ⏳ (.lc-alerta,
     11 px) no RODAPÉ, dentro do chip do contador (.cx-c-chip), a dois andares de distância. É por
     isso que a O2 ("todos, absolutamente todos, têm ampulheta") convive com o marcador do assunto
     sem disputar o mesmo slot: ⛔ eles nunca competem, porque nunca estão na mesma fileira.
     Eles também ⛔ não se confundem à vista: tamanho diferente (18 × 11), origem diferente (o
     marcador é EMOJI colorido, a ⏳ é SVG monocromático que obedece a color) e papel diferente (um
     é O QUE É, o outro é HÁ QUANTO TEMPO). Medido em tools/prova_icone_suporte_vermelho.py.
     ⛔ Quem for reaproveitar .lc-emoji e .lc-alerta numa fileira só (o desenho antigo e plano de
     .linha-conversa, hoje sem nenhum render em produção) tem de medir a distância de novo: o halo
     vermelho do marcador é um anel que cresce para FORA da caixa de 18 px.
     A bolinha da etiqueta lê --etiqueta-cor, que E4 põe no style da própria .lc-etiqueta a
     partir de etiquetas[].cor. Sem ela a bolinha fica cinza — nunca some.
   TARJA (§12.3)              .tarja (+ [data-nivel]) · .tarja-texto · .tarja-acao
     UMA por lista (coleta atrasada). ⛔ Nunca um aviso por card.
   PLACAR AO VIVO (§12.4)     .placar · .placar-celula (+ .ativa) · .pc-emoji ·
     .pc-texto (empilha os dois de baixo) · .pc-n · .pc-rotulo
   FAIXA DE DIAGNÓSTICO (§12.5) .faixa-diag (44 px, borda 4 px, fundo 12 %) · .fd-emoji ·
     .fd-texto (13,5/600) · .fd-frescor (12,5) · .linha-acao · .linha-identidade · .li-item
     .regua · .regua-item · .regua-rotulo · .regua-valor (tabular-nums)
   SELOS E CHIPS (§12.6)      .selo-estado · .selo-frescor · .chips-gaveta · .chip-gaveta
   LINHA-MÃE DE EVENTO (§12.7) .linha-evento · .le-emoji · .le-grau · .le-n · .le-acoes
   SEM ESPELHO (§12.8)        .sem-espelho · .se-texto · .se-link
   ESCOLHA EM GRADE (§12.9)   .grade-opcoes · .opcao (+ .ativa) · .opcao-nome · .opcao-nota
     (motivos de fechamento, escolha de contrato, seletor de fila)
   DADOS DE EXEMPLO (§12.10)  .faixa-exemplo · .faixa-exemplo-texto (uma linha, abaixo do cabeçalho;
     a altura vai em --faixa-exemplo-a, que a caixa desconta)

   HERDADOS que este arquivo re-veste (nomes do app.css, não mudam):
     .sidebar .header .conteudo .nav-item .btn .chip .badge .avatar .card .kpi .tabela
     .input .select .textarea .interruptor .modal .popover .gaveta .toast .alerta .esqueleto
     .progresso .abas/.aba .passos/.passo .vazio .separador .codigo-copiar

   ┌──────────────────────────────────────────────────────────────────────────────────┐
   │ 4. REGRAS DA CASA QUE VENCEM O CLONE                                             │
   └──────────────────────────────────────────────────────────────────────────────────┘
   · Uma fonte só: Roboto. ⛔ Nunca mono + sans na mesma tela.
   · tabular-nums em todo número que se compara (régua, placar, idade da espera).
   · Sem caixa alta em rótulo. 13,5 semibold / 12,5 normal.
   · ⛔ Sem mascote, sem ilustração.
   · Azul primário SÓ para o que é clicável. Cor de estado NUNCA pinta a linha inteira —
     ela pinta 3–4 px de borda e o emoji.
   · Contraste mínimo 4,5. Medido par a par (§5): o vermelho e o roxo do Quasar só entram
     como BORDA e FUNDO; para texto existem --negative-texto e --accent-texto.
   · Densidade: a Smart desperdiça altura. Linha de conversa em 48 px, não 64.
   · ⛔ Esconder é el.hidden (o app.css já tem [hidden] com display:none). Nenhum
     componente daqui aparece ou some por classe.
   · ⛔ Crase dentro de comentário CSS fecha template literal quando o CSS mora em JS —
     já quebrou 4 vezes. Neste arquivo não existe uma única crase.
   · ⛔ Comentário solto dentro de bloco de tokens já engoliu uma variável e derrubou o
     grid da caixa em produção. Todo comentário aqui abre e fecha na mesma linha ou
     entre regras.
   ===================================================================================== */


/* ══════════════════════════════════════════════ 5. BANCOS DE COR (valores literais, uma vez)
   Contraste conferido par a par (script em tools/, saída na entrega), fundo #090E11 e
   superfície #1E1E1E:
     #FFFFFF sobre #090E11 = 19,40  ·  #9E9E9E sobre #090E11 = 7,24  ·  sobre #1E1E1E = 6,22
     #FFFFFF sobre #1976D2 = 4,60 (botão)  ·  #1976D2 como TEXTO sobre #090E11 = 4,22 REPROVA
     #C10015 como TEXTO = 3,03 REPROVA  ·  #9C27B0 como TEXTO = 3,08 REPROVA
     por isso existem: --primary-texto #64B5F6 = 8,76 · --negative-texto #FF6A6A = 6,95 ·
     --accent-texto #CE93D8 = 8,12 · --positive-texto #4ADE80 = 11,13
     #FFFFFF sobre #21BA45 = 2,57 REPROVA -> sobre verde cheio o texto é escuro (6,99) */
html:root {
  /* ---- banco ESCURO — a paleta da Smart (tema padrão do Quasar em dark) ---- */
  --c-esc-bg: #090E11;
  --c-esc-surface: #1E1E1E;
  --c-esc-surface-2: #26292B;
  --c-esc-surface-3: #2E3235;
  --c-esc-linha: #2C3134;
  --c-esc-linha-forte: #3B4146;
  --c-esc-texto: #FFFFFF;
  --c-esc-texto-corpo: #EDEFF0;
  --c-esc-texto-fraco: #9E9E9E;
  --c-esc-texto-apagado: #8A9296;

  /* ---- banco CLARO — "tudo branco" (só com data-tema="claro") ----
     ⭐ 18/09/2026, ordem do dono: "o claro tem que ficar perfeito, com tudo branco e contrastes dos
     botões". Antes era a paleta cinza do Financeiro Pro (bg #f6f7f9, o "lavado"), nunca medida.
     Medido antes (tools/checar_contraste_tema.py, sobre #ffffff salvo indicação):
       apagado #9aa3af = 2,55 REPROVA (hora, contagem, placeholder)  ·  fraco #6b7280 = 4,83 mas
       4,27 sobre --surface-3 (placeholder dentro do campo REPROVA)  ·  linha-forte #d6dbe2 como
       borda de campo/chip/trilho = 1,39 (borda que importa some).
     Agora: página E painel são #ffffff — a separação vira o fio --linha (#e5e7eb = 1,24, sutil de
     propósito) e dois degraus quase-brancos só onde precisa de degrau (surface-2 #f7f8fa para
     hover/zebra/thead/balão de entrada, surface-3 #eef0f3 para campo/toast/esqueleto).
     Os cinzas de texto DESCEM mantendo a ordem texto > corpo > fraco > apagado:
       fraco #545f6d = 6,13 · 5,37 sobre surface-3   ·   apagado #616b78 = 5,41 · 4,74 sobre surface-3
     ⛔ A borda de CONTROLE não sai daqui: é --borda-controle (§7), para não virar grade na tabela. */
  --c-cla-bg: #ffffff;
  --c-cla-surface: #ffffff;
  --c-cla-surface-2: #f7f8fa;
  --c-cla-surface-3: #eef0f3;
  --c-cla-linha: #e5e7eb;
  --c-cla-linha-forte: #d1d5db;
  --c-cla-texto: #111827;
  --c-cla-texto-corpo: #374151;
  --c-cla-texto-fraco: #545f6d;
  --c-cla-texto-apagado: #616b78;
}

/* ══════════════════════════════════════════════ 6. MODO ESCURO (o padrão da casa)
   Vale quando o html não tem data-tema nenhum e quando ele diz data-tema="escuro".
   ⛔ Não depende de o integrador lembrar do atributo: sem atributo, é escuro. */
html:root:not([data-tema]),
html:root[data-tema="escuro"] {
  color-scheme: dark;

  /* superfícies e fios */
  --bg: var(--c-esc-bg);
  --surface: var(--c-esc-surface);
  --surface-2: var(--c-esc-surface-2);
  --surface-3: var(--c-esc-surface-3);
  --linha: var(--c-esc-linha);
  --linha-forte: var(--c-esc-linha-forte);

  /* texto */
  --texto: var(--c-esc-texto);
  --texto-corpo: var(--c-esc-texto-corpo);
  --texto-fraco: var(--c-esc-texto-fraco);
  --texto-apagado: var(--c-esc-texto-apagado);
  --text-2: var(--c-esc-texto-fraco);

  /* marca — azul só para o que é clicável */
  --primary: #1976D2;
  --primary-rgb: 25, 118, 210;
  --primary-cheio-hover: #1565C0;
  --primary-texto: #64B5F6;
  --primary-escuro: #64B5F6;
  --primary-suave: rgba(25, 118, 210, .18);
  --primary-linha: rgba(25, 118, 210, .45);

  /* estado — cheio (fundo/borda) · -texto (legível) · -suave (tinta 16 %) */
  --positive: #21BA45;   --positive-rgb: 33, 186, 69;    --positive-texto: #4ADE80;
  --negative: #C10015;   --negative-rgb: 193, 0, 21;     --negative-texto: #FF6A6A;
  --warning: #F2C037;    --warning-rgb: 242, 192, 55;    --warning-texto: #F2C037;
  --info: #31CCEC;       --info-rgb: 49, 204, 236;       --info-texto: #31CCEC;
  --secondary: #26A69A;  --secondary-rgb: 38, 166, 154;  --secondary-texto: #4DD0C4;
  --accent: #9C27B0;     --accent-rgb: 156, 39, 176;     --accent-texto: #CE93D8;
  --brand-wa: #25D366;   --brand-wa-rgb: 37, 211, 102;
  --neutro-rgb: 158, 158, 158;

  /* ⭐ o AMARELO DO MONITOR (12/09, ordem do dono: "mesma cor ... igual no monitor"). É a variável
     --at do painel do Monitor Óptico, medida no CSS publicado dele — ⛔ não é escolha de gosto e
     ⛔ não se ajusta "para ficar mais bonito": os dois painéis têm de falar a mesma língua de cor. */
  --sinal-destaque: #f5a524;
  --sinal-destaque-rotulo: #d8952a;
  --sinal-destaque-bg: rgba(245, 165, 36, .10);

  /* apelidos do app.css: -suave = tinta de FUNDO · -escuro/-texto = cor de TEXTO */
  --verde: var(--positive);    --verde-suave: rgba(33, 186, 69, .16);   --verde-escuro: var(--positive-texto);
  --ambar: var(--warning);     --ambar-suave: rgba(242, 192, 55, .16);  --ambar-texto: var(--warning-texto);
  --vermelho: var(--negative); --vermelho-suave: rgba(193, 0, 21, .18); --vermelho-texto: var(--negative-texto);
  --roxo: var(--accent-texto); --roxo-suave: rgba(156, 39, 176, .18);

  /* trilho da cobrança (telas herdadas ainda usam; aqui só re-tonalizado) */
  --trilho-azul: #42A5F5;      --trilho-azul-txt: #64B5F6;     --trilho-azul-bg: rgba(25, 118, 210, .16);
  --trilho-ambar: #F2C037;     --trilho-ambar-txt: #F2C037;    --trilho-ambar-bg: rgba(242, 192, 55, .14);
  --trilho-laranja: #FB8C00;   --trilho-laranja-txt: #FFB74D;  --trilho-laranja-bg: rgba(251, 140, 0, .14);
  --trilho-vermelho: #C10015;  --trilho-vermelho-txt: #FF6A6A; --trilho-vermelho-bg: rgba(193, 0, 21, .16);
  --trilho-verde: #21BA45;     --trilho-verde-txt: #4ADE80;    --trilho-verde-bg: rgba(33, 186, 69, .14);

  /* ⭐ etiqueta de FILA do Ao Vivo (Financeiro · Suporte · Planos · Outros Assuntos).
     ⛔ Não é escolha de gosto: a cor foi MEDIDA pixel a pixel na captura real da Smart
     (referencia/smart/smart-aovivo-1440.png, 12/09/2026) — fundo #EF9A9A e texto #383838,
     os dois lidos direto dos chips "Financeiro" e "Suporte". Contraste do par: 5,4:1
     (acima do mínimo 4,5 da casa). Fica ao lado do trilho porque a etiqueta de CANAL,
     a irmã laranja dela na mesma linha, é --trilho-laranja-txt (#FFB74D). */
  --etiq-fila: #EF9A9A;
  --etiq-fila-texto: #383838;

  /* ⭐ 12/09 — AS OUTRAS DUAS ETIQUETAS DO CARTÃO, medidas no mesmo passe da fila logo acima
     (dossie/13 §3 · getComputedStyle dentro da Smart logada · referencia/smart/smart-etiquetas-css.json).
     As três têm a MESMA forma (10px/500, padding 1px 5px, raio 4px, altura 16px): só o fundo muda, e é
     o fundo que diz O QUE a etiqueta é. ⛔ Departamento nunca sai em outra cor que não o rosa
     --etiq-fila (é ele que mostra o que o cliente escolheu no bot) e ⛔ atendente nunca sai em rosa.
     O laranja é o mesmo #FFB74D que a casa já tinha em --trilho-laranja-txt; o azul é o mesmo
     #64B5F6 de --primary-texto. Contraste do par, superfície #1E1E1E:
       texto #383838 sobre #FFB74D = 6,77  ·  chip #FFB74D sobre a superfície = 9,63
       texto #383838 sobre #64B5F6 = 5,29  ·  chip #64B5F6 sobre a superfície = 7,53 */
  --etiq-canal: #FFB74D;
  --etiq-canal-texto: #383838;
  --etiq-atendente: #64B5F6;
  --etiq-atendente-texto: #383838;

  /* ⭐ 12/09 — as quatro tintas de TEXTO do cartão da lista (dossie/13 §2 e §4), todas MEDIDAS.
     A hierarquia abaixo veio da medição, sobre a superfície #1E1E1E:
       tempo    #BDBDBD = 8,87   (o contador do rodapé é o mais aceso dos cinzas)
       ticket   #A8A8A8 = 7,01
       prévia   #999999 = 5,85   (a linha da última mensagem, o cinza mais apagado)
     e o vermelho de "Fora da janela de tempo" #EF9B94 = 7,77, que OCUPA o lugar do tempo em vez de
     somar com ele. ⛔ Estes quatro não se ajustam a gosto: são a cópia do tema escuro da Smart. */
  --cartao-tempo: #BDBDBD;
  --cartao-tempo-expirado: #EF9B94;
  --cartao-previa: #999999;
  --cartao-ticket: #A8A8A8;

  /* ⭐ 12/09 — o VERMELHO QUE SOBREVIVE EM CIMA DE TINTA VERMELHA. --negative-texto (#FF6A6A) tem
     6,95 sobre a superfície e é o certo em quase tudo; sobre um fundo que JÁ é avermelhado ele cai.
     Medido na pastilha de Pendentes do Ao Vivo (#463134, o valor amostrado pixel a pixel na captura
     da Smart): #FF6A6A dá 4,30 e o piso da casa é 4,5 — este par dá 5,29. ⛔ Não é "um vermelho mais
     bonito": é o único jeito de manter o FUNDO medido e continuar legível. Só para TEXTO sobre tinta
     vermelha; em fundo de superfície continua valendo --negative-texto. */
  --negative-texto-tinta: #FF8A8A;

  /* sombra: no escuro a sombra é preta de verdade, senão o modal não descola do fundo */
  --sombra-menu: 0 6px 18px rgba(0, 0, 0, .55), 0 1px 2px rgba(0, 0, 0, .45);
  --sombra-modal: 0 24px 56px rgba(0, 0, 0, .68);
  --sombra: none;
  --sombra-flutuante: var(--sombra-menu);
  --veu: rgba(0, 0, 0, .62);
  --realce-fraco: rgba(255, 255, 255, .04);
  --realce-medio: rgba(255, 255, 255, .08);

  /* ⭐ 18/09 — quatro tokens que nasceram com o modo claro (§7). No ESCURO eles valem EXATAMENTE o
     que as regras já cravavam em literal, então nada muda de cor aqui: existem para o claro ter um
     valor próprio sem a regra precisar saber em que tema está. ⛔ Todo token de um modo existe no
     outro (tools/checar_contraste_tema.py cobra a paridade): token que só existe num modo cai no
     :root do app.css — a paleta clara do Financeiro Pro — sem erro nenhum no console. */
  --borda-controle: var(--c-esc-linha-forte);      /* borda de campo, .btn de contorno, chip, trilho */
  --positive-cheio-hover: #1CA93D;                  /* era o literal de :root .btn-verde:hover */
  --negative-cheio-hover: #9E0011;                  /* era o literal de :root .btn-perigo:hover */
  --selecao-texto: #fff;                            /* era o literal de :root ::selection */
}

/* O mesmo escuro quando o sistema está em escuro e ninguém pediu claro — exigido pelo
   contrato (docs/API-V1.md §12.1) e serve de rede se alguém apagar o data-tema. */
@media (prefers-color-scheme: dark) {
  html:root:not([data-tema="claro"]) {
    color-scheme: dark;
    --bg: var(--c-esc-bg);
    --surface: var(--c-esc-surface);
    --surface-2: var(--c-esc-surface-2);
    --surface-3: var(--c-esc-surface-3);
    --linha: var(--c-esc-linha);
    --linha-forte: var(--c-esc-linha-forte);
    --texto: var(--c-esc-texto);
    --texto-corpo: var(--c-esc-texto-corpo);
    --texto-fraco: var(--c-esc-texto-fraco);
    --texto-apagado: var(--c-esc-texto-apagado);
    --text-2: var(--c-esc-texto-fraco);
    --primary-escuro: #64B5F6;
    --primary-texto: #64B5F6;
    --primary-suave: rgba(25, 118, 210, .18);
    --primary-linha: rgba(25, 118, 210, .45);
    --verde-suave: rgba(33, 186, 69, .16);
    --verde-escuro: #4ADE80;
    --ambar-suave: rgba(242, 192, 55, .16);
    --ambar-texto: #F2C037;
    --vermelho-suave: rgba(193, 0, 21, .18);
    --vermelho-texto: #FF6A6A;
    --roxo: #CE93D8;
    --roxo-suave: rgba(156, 39, 176, .18);
    --sombra-menu: 0 6px 18px rgba(0, 0, 0, .55), 0 1px 2px rgba(0, 0, 0, .45);
    --sombra-modal: 0 24px 56px rgba(0, 0, 0, .68);
    --veu: rgba(0, 0, 0, .62);
    --realce-fraco: rgba(255, 255, 255, .04);
    --realce-medio: rgba(255, 255, 255, .08);
  }
}

/* ══════════════════════════════════════════════ 7. MODO CLARO ("tudo branco" — ordem do dono, 18/09/2026)
   O dono, literal, mostrando o cabeçalho: "já está no modo noturno, quero uma chave de sol e lua.
   modo claro — o claro tem que ficar perfeito, com tudo branco e contrastes dos botões".
   Vem DEPOIS de todos os blocos escuros de propósito: quem escreve data-tema="claro" ganha, mesmo
   com o sistema em escuro. Os neutros vêm do banco --c-cla-* (§5, onde está a medição); o resto é
   literal deste bloco e cada par abaixo foi medido em tools/checar_contraste_tema.py (WCAG 2.x:
   texto ≥ 4,5 · borda/ícone/pastilha ≥ 3). Sobre #ffffff, salvo indicação. */
html:root[data-tema="claro"] {
  color-scheme: light;
  --bg: var(--c-cla-bg);
  --surface: var(--c-cla-surface);
  --surface-2: var(--c-cla-surface-2);
  --surface-3: var(--c-cla-surface-3);
  --linha: var(--c-cla-linha);
  --linha-forte: var(--c-cla-linha-forte);
  --texto: var(--c-cla-texto);
  --texto-corpo: var(--c-cla-texto-corpo);
  --texto-fraco: var(--c-cla-texto-fraco);
  --texto-apagado: var(--c-cla-texto-apagado);
  --text-2: var(--c-cla-texto-fraco);

  /* ⭐ BORDA DE CONTROLE — o que estava errado: --linha-forte (#d6dbe2 = 1,39) era a borda do campo,
     do .chip-gaveta, do .btn de contorno e o trilho do interruptor; sobre branco, a borda "que
     importa" não existia. ⛔ Escurecer --linha-forte inteiro viraria grade na tabela e na caixa:
     por isso um token SÓ para controle. #7b8794 = 3,66 sobre branco · 3,21 sobre o campo (surface-3)
     · e o botão branco do interruptor DESLIGADO sobre ele = 3,66 (era 1,39: sumia). */
  --borda-controle: #7b8794;

  /* marca: o mesmo azul cheio do escuro (branco sobre ele = 4,60; hover #1565C0 = 5,75). Como TEXTO
     o cheio raspa (4,60): links, nav ativo e chips usam --primary-texto #0B5ED7 = 5,84.
     --primary-suave era #ebf2fe (1,13 sobre branco — o fundo do .btn.ativo, do nav ativo e do balão
     de SAÍDA "lavado", indistinguível do balão de entrada). Agora #e4eefc: #0B5ED7 sobre ele = 4,99,
     #111827 = 15,2, e o balão de saída (azulado) se separa do de entrada (surface-2, cinza). */
  --primary: #1976D2;
  --primary-rgb: 25, 118, 210;
  --primary-cheio-hover: #1565C0;
  --primary-texto: #0B5ED7;
  --primary-escuro: #0B5ED7;
  --primary-suave: #e4eefc;
  --primary-linha: #bcd3f5;

  /* estado — cheio (fundo/borda ≥ 3 sobre branco: verde 3,37 · vermelho 6,41 · âmbar 3,19) e
     -texto (≥ 4,5 sobre branco E sobre a própria tinta suave: verde #0B6B36 = 6,0 · vermelho
     #991B1B = 7,29 · âmbar #92400E = 6,6 · info #0E6F8A = 4,85 sobre a tinta 12 % · roxo #6B21A8 =
     7,67). ⛔ --warning e --positive cheios NUNCA pintam texto sobre branco (3,19 / 3,37): quem
     nasceu no escuro pintando com o cheio é consertado na §17 com o -texto. */
  --positive: #12a150;   --positive-rgb: 18, 161, 80;    --positive-texto: #0B6B36;
  --negative: #C10015;   --negative-rgb: 193, 0, 21;     --negative-texto: #991B1B;
  --warning: #d97706;    --warning-rgb: 217, 119, 6;     --warning-texto: #92400E;
  --info: #0E6F8A;       --info-rgb: 14, 111, 138;       --info-texto: #0E6F8A;
  --secondary: #0f766e;  --secondary-rgb: 15, 118, 110;  --secondary-texto: #0f766e;
  --accent: #7c3aed;     --accent-rgb: 124, 58, 237;     --accent-texto: #6B21A8;
  --brand-wa: #128C4A;   --brand-wa-rgb: 18, 140, 74;
  --neutro-rgb: 107, 114, 128;

  /* hover dos botões cheios: o primário ESCURECE (#1565C0); o verde fazia o contrário — #1CA93D é
     mais CLARO que a base #12a150, o botão clareava ao passar o mouse ("lavado"). Aqui o hover
     escurece como o primário: #08170D sobre #10984c = 4,93. O do perigo já escurecia (#9E0011 = 8,53). */
  --positive-cheio-hover: #10984c;
  --negative-cheio-hover: #9E0011;
  /* ::selection era branco cravado: sobre 40 % de azul em branco (#a3c8ed) media 1,74 — texto
     selecionado ilegível. Com --texto: 10,17. */
  --selecao-texto: var(--texto);

  /* ⭐ o amarelo do Monitor no CLARO é o mesmo que o painel dele usa no claro (--at: #b45309):
     laranja queimado, porque #f5a524 sobre branco não alcança contraste de leitura.
     #b45309 sobre #fff6e8 = 4,69 — passa por pouco e ⛔ o fundo não se "aquece" (cai abaixo de 4,5). */
  --sinal-destaque: #b45309;
  --sinal-destaque-rotulo: #92400e;
  --sinal-destaque-bg: #fff6e8;

  /* apelidos do app.css. ⛔ Um vermelho só: --vermelho era #dc2626 enquanto --negative é #C10015 —
     .btn-perigo, .selo-nao-enviar e .alerta-erro saíam em dois tons na mesma tela. Agora é o mesmo
     (#C10015: branco sobre ele 6,41 · como texto sobre branco 6,41). --roxo como TEXTO segue o
     escuro e aponta para -texto (#6B21A8 sobre --roxo-suave = 7,67); ninguém o usa como fundo. */
  --verde: var(--positive);   --verde-suave: #e9f7ef;    --verde-escuro: var(--positive-texto);
  --ambar: var(--warning);    --ambar-suave: #fef6e7;    --ambar-texto: var(--warning-texto);
  --vermelho: var(--negative); --vermelho-suave: #feecec; --vermelho-texto: var(--negative-texto);
  --roxo: var(--accent-texto); --roxo-suave: #f3eefe;

  --trilho-azul: #3b82f6;      --trilho-azul-txt: #1d4ed8;     --trilho-azul-bg: #eff6ff;
  --trilho-ambar: #d97706;     --trilho-ambar-txt: #92400e;    --trilho-ambar-bg: #fef6e7;
  --trilho-laranja: #ea580c;   --trilho-laranja-txt: #9a3412;  --trilho-laranja-bg: #fff1e7;
  --trilho-vermelho: #dc2626;  --trilho-vermelho-txt: #991b1b; --trilho-vermelho-bg: #feecec;
  --trilho-verde: #12a150;     --trilho-verde-txt: #0b6b36;    --trilho-verde-bg: #e9f7ef;

  /* ⭐ etiqueta de FILA do Ao Vivo — o par do bloco escuro, INVERTIDO, como o resto desta paleta.
     O #EF9A9A MEDIDO na captura da Smart é o certo no escuro e some no claro: rosa claro sobre
     cartão #ffffff dá 1,5:1, ou seja, o chip deixaria de existir. Aqui a mesma família de cor vira
     o vermelho escuro cheio, com texto branco por cima — 6,5:1 nos dois sentidos (texto sobre a
     etiqueta E etiqueta sobre o cartão). ⛔ Quem pinta o chip usa SEMPRE o par junto
     (background: var(--etiq-fila); color: var(--etiq-fila-texto)): é ele que atravessa os dois temas. */
  --etiq-fila: #b3261e;
  --etiq-fila-texto: #ffffff;

  /* ⭐ As outras duas etiquetas no CLARO, pelo mesmo critério da fila logo acima: o valor MEDIDO é do
     tema escuro da Smart e no claro ele desaparece, então a mesma família de cor vira o tom cheio e
     escuro desta paleta, com texto branco por cima. Canal fica no laranja queimado de
     --trilho-laranja-txt e atendente no azul de --trilho-azul-txt, para o cartão não inventar uma
     terceira paleta. Por que o medido reprova aqui e quanto dá o par novo (cartão #ffffff):
       #FFB74D sobre #ffffff = 1,73 REPROVA  ->  #9a3412 com texto #ffffff = 7,31 nos dois sentidos
       #64B5F6 sobre #ffffff = 2,21 REPROVA  ->  #1d4ed8 com texto #ffffff = 6,70 nos dois sentidos
     ⛔ Quem pinta o chip usa SEMPRE o par junto (background + color): é ele que atravessa os temas. */
  --etiq-canal: #9a3412;
  --etiq-canal-texto: #ffffff;
  --etiq-atendente: #1d4ed8;
  --etiq-atendente-texto: #ffffff;

  /* ⭐ As quatro tintas de texto do cartão no CLARO. Os cinzas medidos nasceram para fundo escuro e
     apagam aqui (sobre #ffffff: #BDBDBD = 1,88 · #A8A8A8 = 2,38 · #999999 = 2,85 · #EF9B94 = 2,15 —
     os quatro REPROVAM no piso 4,5 da casa), então cada um desce um degrau MANTENDO A ORDEM medida:
     tempo mais aceso que ticket, ticket mais aceso que prévia. Conferido no cartão (#ffffff) e também
     no fundo da lista (#f6f7f9), que é o pior caso:
       tempo    #4b5563 = 7,56 · 7,05
       ticket   #576070 = 6,34 · 5,91
       prévia   #626b78 = 5,39 · 5,03   (--c-cla-texto-fraco #6b7280 daria 4,51 no fundo, colado no piso)
       expirado #b3261e = 6,54 · 6,10   (mesmo vermelho da etiqueta de fila deste tema: mesma família,
                                         papéis diferentes — aqui é TEXTO sobre o cartão, lá é FUNDO) */
  --cartao-tempo: #4b5563;
  --cartao-tempo-expirado: #b3261e;
  --cartao-previa: #626b78;
  --cartao-ticket: #576070;

  /* no CLARO a tinta de fundo é clara (--vermelho-suave #feecec) e o --negative-texto #991B1B já dá
     7,29 em cima dela: ⛔ não existe motivo para uma segunda cor aqui. O apelido existe só para quem
     escreve a regra não precisar saber em que tema está. */
  --negative-texto-tinta: var(--negative-texto);

  --sombra-menu: 0 6px 16px rgba(17, 24, 39, .10), 0 1px 2px rgba(17, 24, 39, .06);
  --sombra-modal: 0 24px 48px rgba(17, 24, 39, .18);
  --sombra: none;
  --sombra-flutuante: var(--sombra-menu);
  --veu: rgba(17, 24, 39, .45);
  /* realces: .03/.06 sobre branco mediam 1,06/1,13 — o hover do nav-item, da aba, do recolher e da
     .linha-conversa e o fundo da .tarja e do .sem-espelho não existiam. Agora .05/.10 (1,11/1,23):
     visível como hover, ainda longe de ser uma cor. */
  --realce-fraco: rgba(17, 24, 39, .05);
  --realce-medio: rgba(17, 24, 39, .10);
}

/* ══════════════════════════════════════════════ 8. TOKENS QUE NÃO MUDAM COM O MODO */
html:root {
  /* ---- fonte: UMA só (dossie/04). A pilha é a mesma do Quasar. ---- */
  --fonte: Roboto, -apple-system, "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* ---- escala do clone: 10 · 11 · 12 · 13 · 14 · 16 · 18 · 20 ---- */
  --fs-2xs: 10px;
  --fs-xs: 11px;
  --fs-sm: 12px;
  --fs-base: 13px;
  --fs-md: 14px;
  --fs-lg: 16px;
  --fs-xl: 18px;
  --fs-2xl: 20px;
  /* ⛔ --fs-2xs e --fs-xs só em pastilha de contagem; texto que se LÊ começa em 12. */

  /* os dois tamanhos escritos no contrato: 13,5 semibold e 12,5 normal */
  --fs-faixa: 13.5px;
  --fs-selo: 12.5px;

  /* apelidos do app.css, agora na escala do clone */
  --fs-corpo: var(--fs-base);
  --fs-sec: var(--fs-sm);
  --fs-micro: var(--fs-sm);
  --fs-titulo-pagina: var(--fs-2xl);
  --fs-titulo-secao: var(--fs-base);
  /* a ÚNICA exceção acima de 20 na escala: o número grande dos cartões (indicadores, "quem não respondeu") */
  --fs-num-grande: 24px;

  /* ---- movimento ---- */
  --transicao: .12s ease;
  --transicao-suave: .3s cubic-bezier(.215, .61, .355, 1);
  /* --transicao: cor e fundo, entra na hora. --transicao-suave: painel e gaveta (dossie/04). */

  /* ---- caixa de entrada: 344 · flex · 320 (CONTRATOS §6) ---- */
  --caixa-lista-l: 344px;
  /* … a MESMA coluna com o MENU RECOLHIDO (§15): os 168 px que a barra devolve não viram vão na
     conversa, engordam a lista — que é onde o nome do cliente vinha cortado. É o "ele fecha e
     aumenta um pouco para poder ler" da ordem 3 do dono (11/09), igual ao Financeiro Pro. */
  --caixa-lista-l-max: 408px;
  --caixa-ficha-l: 320px;
  --caixa-linha-a: 48px;
  --faixa-a: 44px;
  /* --caixa-linha-a: linha de 2 andares (44–48 px). --faixa-a: faixa de diagnóstico. */
}

/* ══════════════════════════════════════════════ 9. BASE */
:root body {
  font-family: var(--fonte);
  font-size: var(--fs-base);
  color: var(--texto-corpo);
  background: var(--bg);
  font-variant-numeric: tabular-nums;
}
/* a cor do texto selecionado é por modo (§6/§7): branco no escuro (10,5 sobre #1c4166); no claro o
   branco media 1,74 sobre #a3c8ed e o texto sumia ao selecionar — lá é --texto (10,17). */
:root ::selection { background: rgba(var(--primary-rgb), .40); color: var(--selecao-texto); }
:root :focus-visible { outline: 2px solid var(--primary-texto); outline-offset: 2px; }

/* barra de rolagem discreta — no escuro a barra clara do sistema salta na tela */
:root * { scrollbar-width: thin; scrollbar-color: var(--linha-forte) transparent; }
:root ::-webkit-scrollbar { width: 10px; height: 10px; }
:root ::-webkit-scrollbar-track { background: transparent; }
:root ::-webkit-scrollbar-thumb { background: var(--linha-forte); border-radius: 999px; border: 2px solid transparent; background-clip: content-box; }
:root ::-webkit-scrollbar-thumb:hover { background: var(--texto-apagado); background-clip: content-box; }

/* ══════════════════════════════════════════════ 10. CASCA re-vestida (sidebar e header em #1E1E1E)
   Na Smart a barra lateral E o cabeçalho são #1E1E1E sobre a página #090E11. No app.css a
   barra usa --bg e o cabeçalho usa --surface: aqui a barra passa a usar --surface também. */
:root .sidebar { background: var(--surface); border-right: 1px solid var(--linha); }
:root .header { background: var(--surface); border-bottom: 1px solid var(--linha); }
:root .sidebar-overlay { background: var(--veu); }
/* 11/09 (revisão): a zebra do menu no computador saiu — o drawer da Smart não tem zebra. [confirmar] com o
   dono: a alternância continua SÓ na gaveta do celular (app.css ≤ 900), que foi o pedido dele de 06/09. */
:root .sidebar-nav > .nav-item:nth-of-type(even):not(.ativo),
:root .nav-grupo > .nav-item:nth-of-type(even):not(.ativo) { background: transparent; }
:root .sidebar-nav .nav-item:not(.ativo):hover,
:root .nav-grupo .nav-item:not(.ativo):hover { background: var(--realce-medio); color: var(--texto); }
/* o item ATIVO é texto sobre a tinta azul: --primary (#1976D2) media 3,02:1 — reprova. --primary-texto = 7,5. */
:root .sidebar-nav .nav-item.ativo, :root .nav-grupo .nav-item.ativo { color: var(--primary-texto); }
:root .sidebar-recolher:hover { background: var(--realce-medio); color: var(--texto); }
/* a marca não é clicável: sem azul cheio (azul só no que se clica). O avatar do header é botão e continua azul. */
:root .marca-icone { background: var(--surface-3); color: var(--texto); }
:root .nav-badge { background: var(--primary); color: #fff; }
/* link de texto: --primary-texto (o app.css usa --primary, 3,6:1 sobre #1E1E1E) */
:root a { color: var(--primary-texto); }
/* Branco somente sobre azul cheio. As abas da Caixa usam fundo suave e texto do tema. */
:root .btn-primary, :root .btn-primary:hover, :root .aba.ativa { color: #fff; }

/* ══════════════════════════════════════════════ 11. HERDADOS que precisam de conserto no escuro
   São os pontos onde o app.css cravou um hexadecimal claro ou usou --texto como FUNDO. */

/* botões: o azul cheio continua o #1976D2; o hover escurece (branco sobre #1565C0 = 5,75) */
:root .btn-primary { background: var(--primary); border-color: var(--primary); color: #fff; }
:root .btn-primary:hover { background: var(--primary-cheio-hover); border-color: var(--primary-cheio-hover); color: #fff; }
:root .btn-perigo, :root .btn-danger { background: var(--negative); border-color: var(--negative); color: #fff; }
:root .btn-perigo:hover, :root .btn-danger:hover { background: var(--negative-cheio-hover); border-color: var(--negative-cheio-hover); color: #fff; }
:root .btn-contorno-danger { color: var(--negative-texto); border-color: rgba(var(--negative-rgb), .55); background: transparent; }
:root .btn-contorno-danger:hover { background: rgba(var(--negative-rgb), .16); border-color: var(--negative); color: var(--negative-texto); }
/* ⛔ branco sobre #21BA45 mede 2,57 e reprova: sobre verde cheio o texto é escuro.
   18/09: o hover virou token (--positive-cheio-hover) porque no claro o literal #1CA93D CLAREAVA o
   botão em vez de escurecer — ver §7. No escuro o token vale o mesmo #1CA93D de sempre. */
:root .btn-verde { background: var(--positive); border-color: var(--positive); color: #08170D; }
:root .btn-verde:hover { background: var(--positive-cheio-hover); border-color: var(--positive-cheio-hover); color: #08170D; }
:root .btn.ativo { background: var(--primary-suave); border-color: var(--primary-linha); color: var(--primary-texto); }

/* vermelho como TEXTO: --vermelho é o cheio (#C10015, 2,6:1 sobre #1E1E1E). Sete regras herdadas pintam
   texto com ele; aqui elas passam para --negative-texto (#FF6A6A, 6:1). Fundo e borda continuam cheios. */
:root .popover .popover-sair, :root .popover .popover-sair:hover,
:root .menu-item.perigo, :root .kpi .delta.neg, :root .card-metrica .delta.neg,
:root .campo .erro-campo, :root .balao .meta .ticks.falhou, :root .balao .erro, :root .vermelho { color: var(--negative-texto); }
/* 18/09 — três folhas embutidas fazem a mesma coisa (color: var(--vermelho), o cheio) e o grep desta
   rodada as achou: acionadores.js .ac-fluxo .aviso, erros.js .er-cel.alerta-kpi .valor e o hover do
   ícone de apagar em contatos.js. Sobre #1E1E1E o cheio mede 2,6; sobre a tinta vermelha do hover,
   menos ainda. Mesmo conserto, vale nos dois modos; a especificidade (:root + o seletor deles) vence. */
:root .ac-fluxo .aviso, :root .er-cel.alerta-kpi .valor, :root .ct-cond .ct-ico-btn:hover { color: var(--negative-texto); }

/* badge/chip com hexadecimal cravado */
:root .badge-lido { background: rgba(var(--positive-rgb), .26); color: var(--positive-texto); }
:root .badge-cinza, :root .badge-pendente, :root .badge-rascunho,
:root .badge-arquivada, :root .badge-inativo, :root .badge-pulado {
  background: rgba(var(--neutro-rgb), .18); color: var(--texto-corpo);
}

/* entrada: no escuro o campo precisa de fundo próprio, senão some dentro do painel.
   ⛔⛔ 12/09 — "background-color", NUNCA o atalho "background". O atalho REINICIA background-image,
   e o app.css desenha a setinha ▾ de todo <select> exatamente ali (app.css §11, um data:image/svg+xml).
   Com o atalho, esta regra (0,2,0) ganhava daquela (0,1,0) e apagava a seta do aplicativo INTEIRO,
   nos dois temas: medido no #av-agrupar do Ao Vivo — backgroundImage 'none', appearance 'none' e os
   30 px de padding-right continuavam reservados e vazios, uma caixa "Usuários" sem seta nenhuma. */
:root .input, :root .select, :root .textarea,
:root input[type=text], :root input[type=search], :root input[type=password],
:root input[type=number], :root input[type=email], :root input[type=tel],
:root input[type=date], :root input[type=time], :root select, :root textarea {
  background-color: var(--surface-3);
  /* 18/09: a borda do campo é --borda-controle (escuro = --linha-forte de sempre; claro = #7b8794,
     porque #d6dbe2 sobre branco media 1,39 e o campo não tinha contorno) */
  border-color: var(--borda-controle);
  color: var(--texto);
}
:root .input:focus, :root .select:focus, :root .textarea:focus,
:root input:focus, :root select:focus, :root textarea:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(var(--primary-rgb), .28);
}
/* trilho DESLIGADO = --borda-controle: no escuro é o #3B4146 de sempre (botão branco = 10,3); no claro
   era --linha-forte #d6dbe2 e o botão branco sobre ele media 1,39 — o interruptor desligado sumia.
   Com #7b8794: 3,66. Ligado continua azul (branco sobre --primary = 4,60). */
:root .interruptor .trilho { background: var(--borda-controle); }
:root .interruptor .trilho::after { background: #fff; }
:root .codigo-copiar { background: var(--surface-3); border-color: var(--linha); }

/* sobreposição: véu preto de verdade */
:root .modal-fundo, :root .gaveta-fundo { background: var(--veu); }
:root .modal, :root .popover, :root .gaveta { background: var(--surface); border: 1px solid var(--linha); }
:root .gaveta { border-right: 0; }

/* toast: o app.css usa --texto como FUNDO com texto branco. No escuro --texto É branco,
   e o toast virava branco no branco. Aqui ele ganha fundo próprio. */
:root .toast { background: var(--surface-3); color: var(--texto); border: 1px solid var(--linha-forte); }
:root .toast.ok { background: rgba(var(--positive-rgb), .22); border-color: rgba(var(--positive-rgb), .55); color: var(--positive-texto); }
:root .toast.erro { background: rgba(var(--negative-rgb), .22); border-color: rgba(var(--negative-rgb), .70); color: var(--negative-texto); }
:root .toast.aviso { background: rgba(var(--warning-rgb), .18); border-color: rgba(var(--warning-rgb), .55); color: var(--warning-texto); }

/* alerta: as cores de texto estavam cravadas em hexadecimal claro */
:root .alerta-info { background: var(--primary-suave); color: var(--primary-texto); border-color: var(--primary-linha); }
:root .alerta-aviso { background: var(--ambar-suave); color: var(--warning-texto); border-color: rgba(var(--warning-rgb), .45); }
:root .alerta-erro { background: var(--vermelho-suave); color: var(--negative-texto); border-color: rgba(var(--negative-rgb), .55); }
:root .alerta-ok { background: var(--verde-suave); color: var(--positive-texto); border-color: rgba(var(--positive-rgb), .45); }

/* carregando e progresso: cinza claro cravado */
:root .esqueleto { background: var(--surface-3); }
:root .progresso { background: var(--surface-3); }

/* tabela: cabeçalho colado, linha de 44, números à direita com tabular-nums */
:root .tabela thead th, :root .tablewrap > table thead th, :root .tabela-wrap > table thead th {
  background: var(--surface-2); color: var(--texto-fraco); font-weight: 500; text-transform: none;
}
:root .tabela td.num, :root .tabela th.num, :root .num, :root .valor-grande, :root .kpi .valor {
  font-variant-numeric: tabular-nums;
}

/* abas: a ativa é azul cheio com texto branco (4,60) */
:root .aba.ativa { color: #fff; background: var(--primary); border-color: var(--primary); }
:root .aba.ativa:hover { color: #fff; background: var(--primary-cheio-hover); border-color: var(--primary-cheio-hover); }
:root .aba:hover { background: var(--realce-medio); color: var(--texto); }
:root .passo.feito .n { background: var(--positive); border-color: var(--positive); color: #08170D; }

/* ══════════════════════════════════════════════ 12. COMPONENTES NOVOS DO ATENDIMENTO */

/* ---- 12.0 ESTADO POR ATRIBUTO ----
   Cada valor publica três variáveis para quem estiver dentro:
     --e-cor    borda de 3–4 px e bolinha
     --e-tinta  fundo a 12 % da mesma cor
     --e-texto  cor legível para texto sobre fundo escuro
   Quem consome usa var(--e-cor, <neutro>): estado desconhecido cai em NEUTRO, nunca some. */
[data-estado="fibra_ok"]      { --e-cor: var(--positive); --e-tinta: rgba(var(--positive-rgb), .12); --e-texto: var(--positive-texto); }
[data-estado="sinal_ruim"]    { --e-cor: var(--warning);  --e-tinta: rgba(var(--warning-rgb), .12);  --e-texto: var(--warning-texto); }
[data-estado="caindo_fibra"]  { --e-cor: var(--negative); --e-tinta: rgba(var(--negative-rgb), .12); --e-texto: var(--negative-texto); }
[data-estado="so_ele_caiu"]   { --e-cor: var(--negative); --e-tinta: rgba(var(--negative-rgb), .12); --e-texto: var(--negative-texto); }
[data-estado="evento_pon"]    { --e-cor: var(--negative); --e-tinta: rgba(var(--negative-rgb), .12); --e-texto: var(--negative-texto); }
[data-estado="caindo_energia"]{ --e-cor: var(--warning);  --e-tinta: rgba(var(--warning-rgb), .12);  --e-texto: var(--warning-texto); }
[data-estado="porta_olt_down"]{ --e-cor: var(--info);     --e-tinta: rgba(var(--info-rgb), .12);     --e-texto: var(--info-texto); }
[data-estado="ont_trocada"]   { --e-cor: var(--info);     --e-tinta: rgba(var(--info-rgb), .12);     --e-texto: var(--info-texto); }
[data-estado="voltou_pior"]   { --e-cor: var(--accent);   --e-tinta: rgba(var(--accent-rgb), .12);   --e-texto: var(--accent-texto); }
[data-estado="sem_ont"]       { --e-cor: var(--text-2);   --e-tinta: rgba(var(--neutro-rgb), .12);   --e-texto: var(--texto-fraco); }
[data-estado="ont_removida"]  { --e-cor: var(--text-2);   --e-tinta: rgba(var(--neutro-rgb), .12);   --e-texto: var(--texto-fraco); }
[data-estado="nao_sei_dizer"] { --e-cor: var(--text-2);   --e-tinta: rgba(var(--neutro-rgb), .12);   --e-texto: var(--texto-fraco); }

/* idade da espera. ⛔ indefinido = limiar [confirmar] = NEUTRO. Nunca vermelho inventado. */
[data-nivel="ok"]         { --n-cor: var(--texto-fraco); --n-peso: 400; }
[data-nivel="atencao"]    { --n-cor: var(--warning-texto); --n-peso: 500; }
[data-nivel="critico"]    { --n-cor: var(--negative-texto); --n-peso: 700; }
[data-nivel="indefinido"] { --n-cor: var(--texto-fraco); --n-peso: 400; }

/* frescor do espelho (docs/API-V1.md §3.2) */
[data-frescor="ao_vivo"]     { --f-cor: var(--positive-texto); --f-num: var(--texto); }
[data-frescor="dado_antigo"] { --f-cor: var(--texto-fraco); --f-num: var(--texto-fraco); }
[data-frescor="sem_espelho"] { --f-cor: var(--texto-apagado); --f-num: var(--texto-apagado); }

/* ---- 12.1 CAIXA DE ENTRADA: 344 px lista · flex conversa · 320 px ficha ----
   ⛔ Só px nas larguras. Um comentário solto dentro deste bloco já engoliu a variável da
   coluna e a caixa inteira virou uma coluna empilhada em produção. */
.caixa {
  display: grid;
  grid-template-columns: var(--caixa-lista-l) minmax(0, 1fr) var(--caixa-ficha-l);
  height: calc(100vh - var(--header-a, 52px) - var(--faixa-exemplo-a, 0px));
  background: var(--surface);
  min-width: 0;
}
.caixa.sem-ficha { grid-template-columns: var(--caixa-lista-l) minmax(0, 1fr); }
.caixa-lista {
  display: flex; flex-direction: column; min-width: 0; min-height: 0;
  background: var(--surface); border-right: 1px solid var(--linha);
}
.caixa-lista-topo { flex: none; padding: var(--e3, 12px); border-bottom: 1px solid var(--linha); display: flex; flex-direction: column; gap: var(--e2, 8px); }
.caixa-lista-itens { flex: 1; overflow-y: auto; min-height: 0; }
.caixa-conversa { display: flex; flex-direction: column; min-width: 0; min-height: 0; background: var(--bg); }
.caixa-ficha {
  display: flex; flex-direction: column; min-width: 0; min-height: 0;
  background: var(--surface); border-left: 1px solid var(--linha); overflow: hidden;
}
.caixa-ficha-corpo { flex: 1; overflow-y: auto; min-height: 0; padding: var(--e3, 12px); display: flex; flex-direction: column; gap: var(--e3, 12px); }
.caixa-voltar { display: none; }

/* ---- 12.2 LINHA DA LISTA: 2 andares, 48 px, borda esquerda de 3 px = estado da fibra ----
   ⛔ A cor do estado pinta a BORDA e o emoji. Nunca o fundo da linha inteira. */
.linha-conversa {
  display: flex; gap: 10px; align-items: flex-start;
  min-height: var(--caixa-linha-a);
  padding: 5px 12px 5px 9px;
  border-bottom: 1px solid var(--linha);
  border-left: 3px solid var(--e-cor, transparent);
  cursor: pointer; min-width: 0;
  background: transparent;
  line-height: 1.3;
  /* ⭐⭐ 19/09/2026 — O "SECO" DO DONO: *"Tenho identificado a forma de clicar um tanto amador...
     nao sei se ta seco demais ou apenas mais devagar"*. ⛔ MEDIDO: nao era lentidao — o alvo mais
     clicado da plataforma NAO ACUSAVA O TOQUE. A linha tinha cursor e :hover e mais nada: nem
     :active, nem transicao, nem realce de toque. No computador o hover ja estava aceso ANTES do
     clique, entao apertar nao mudava UM pixel; no celular nao existe hover, e o dedo batia numa
     tela imovel ate a resposta voltar (54,8 a 60,8 ms medidos na bancada, ~105-160 ms na VPS).
     O irmao que ele considera bom tem isso ha tempos (FinanceiroPro/static/css/app.css:440,
     .btn:active com translateY). ⛔ Custo de rede: zero. ⛔ Nada de comportamento muda aqui. */
  transition: background-color .12s ease;
  -webkit-tap-highlight-color: transparent;   /* o realce cinza do Android tapa o cartao inteiro: o :active abaixo e melhor */
}
/* o dedo (ou o mouse) apertado: a linha escurece NO MESMO QUADRO do toque, antes de qualquer pedido.
   ⛔ Fica entre o hover e a .ativa de propósito — apertar nao pode parecer "ja abriu". */
/* ⛔ 19/09: na Caixa esta regra NAO pinta — o cartao de la tem duas classes (linha-conversa +
   cx-cartao) e a folha da propria tela vence por ordem; o :active de verdade mora em
   static/js/telas/caixa.js. Aqui ela vale para a linha crua do Ao Vivo, e por isso precisa vir
   DEPOIS do :hover desta mesma folha. */
/* quem chega pelo teclado (Tab) tambem ve onde esta: a linha e role="button" e recebe foco */
.linha-conversa:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
/* ⛔ A entrelinha aqui é travada de propósito. Com o 1,5 do corpo a linha media 53 px e
   estourava os 44–48 px do contrato — a Smart desperdiça altura e é justamente isso que
   não se copia. Com 1,3 o conteúdo fecha em ~45 px e o min-height manda: 48 px cravados. */
.linha-conversa:hover { background: var(--realce-fraco); }
.linha-conversa:active { background: var(--realce-medio); transition-duration: 0s; }
.linha-conversa.ativa { background: rgba(var(--primary-rgb), .16); }
.linha-conversa.ativa .lc-nome { color: var(--primary-texto); }
.lc-emoji { flex: none; font-size: var(--fs-md); line-height: 20px; width: 18px; text-align: center; }
.linha-conversa > .lc-corpo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.lc-topo { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.lc-nome { font-size: var(--fs-base); font-weight: 500; color: var(--texto); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; line-height: 1.3; }
.lc-id { font-size: var(--fs-sm); color: var(--texto-fraco); font-variant-numeric: tabular-nums; flex: none; }
.lc-espera {
  margin-left: auto; flex: none;
  font-size: var(--fs-sm); font-variant-numeric: tabular-nums;
  color: var(--n-cor, var(--texto-fraco)); font-weight: var(--n-peso, 400);
}
/* ---- A POTENCIA DE QUEM ESTA BOM, na propria linha (ordem do dono, 11/09 21:50) ----
   Literal: "mesmo quem esta BOM, a pessoa possa aparecer ali a POTENCIA dela, mesmo que sejam
   menos vinte e seis, menos vinte e sete."
   TEXTO, nunca icone: a lista de icones e FECHADA e ninguem inventa um quinto simbolo.
   tabular-nums porque numero em lista tem de alinhar (feedback_tipografia_paineis).
   O margin-left:auto daqui empurra o par (sinal + tempo) para a direita; a regra seguinte tira o
   o auto do tempo para os dois ficarem GRUDADOS no canto, em vez de a sobra se dividir entre eles.
   Cor: cinza por padrao. So a faixa RUIM ganha o ambar de leitura -- e o vermelho continua sendo
   assunto do halo do icone de suporte, ⛔ nunca de um numero solto. */
.lc-sinal {
  margin-left: auto; flex: none;
  font-size: var(--fs-sm); font-variant-numeric: tabular-nums;
  color: var(--texto-fraco); letter-spacing: .01em;
}
.lc-sinal + .lc-espera { margin-left: 0; }
.lc-sinal[data-faixa="ruim"] { color: var(--warning-texto); }
/* ---- SINAL DE ATENÇÃO NA LINHA (ordem 1 do dono, 11/09 à noite) ----
   Literal: "a linha da Maria está com símbolo verde; ela deveria ter TAMBÉM o símbolo de atenção
   (âmbar), para o colaborador identificar e JÁ PUXAR, tirando da fila."
   Então o âmbar entra AO LADO do emoji da fibra (que continua verde / o que for), ⛔ nunca no lugar
   dele: são duas informações diferentes — a fibra do cliente e o tempo que ele está esperando.
   ⛔ Cor sozinha não serve: vão juntos o ÍCONE ⏳ (âmbar), o TEXTO do tempo em âmbar e a palavra "puxar".
   O âmbar é --warning-texto (#F2C037 sobre #1E1E1E = 9,9:1 no escuro; #92400E no claro = 7,4:1). */
/* ---- 12/09: a LISTA FECHADA DE ÍCONES do dono (dossie/ORDEM-AOVIVO, "a lista DEFINITIVA") ----
   📉 financeiro · 🔌 suporte · ⚡ energia · ⏳ esperando. ⛔ Saíram o ❔, o ✅ e o 🔥.
   .lc-emoji deixou de ser "o emoji da fibra" e passou a ser o MARCADOR da linha — e ele pode vir
   VAZIO, porque sem dado não há ícone. O slot continua ocupando os 18 px de propósito: sem ele os
   nomes da lista deixariam de alinhar e a coluna viraria um zigue-zague.
   .lc-alerta deixou de ser o ⚠️ "acima do limiar" e passou a ser a ⏳ "está esperando para ser
   puxada", em qualquer assunto. O que muda com o limiar é só o TOM: âmbar quando passou, apagado
   enquanto está dentro. ⛔ O símbolo nunca muda — símbolo que troca sozinho ninguém aprende. */
.lc-emoji[data-vazio="1"] { color: transparent; }

/* ⭐ 12/09 — ORDEM DO DONO: "o ícone de suporte vai tá lá SEMPRE que identificar suporte, até mesmo
   clicando. Mas se já identificar −28..−29 ou assim por diante, o emoji fica IGUAL porém AVERMELHADO.
   Isso para identificar logo que é problema de conexão ou sem sinal."
   ⛔ O SÍMBOLO NÃO MUDA — muda a cor. Emoji não aceita "color", então o vermelho vem de fora: um
   halo circular vermelho atrás dele, mais um filtro leve que puxa a própria tomada para o quente.
   O halo é quem garante o recado: se o navegador ignorar o filtro (e alguns ignoram), o anel
   vermelho continua lá. ⛔ Nunca confiar só no filter para dizer uma coisa que importa. */
.lc-emoji[data-tom="alerta"] {
  border-radius: 50%;
  background: rgba(var(--negative-rgb), .22);
  box-shadow: 0 0 0 1.5px var(--negative-texto);
  filter: saturate(1.7) hue-rotate(-22deg) contrast(1.05);
}
@media (prefers-reduced-motion: reduce) { .lc-emoji[data-tom="alerta"] { filter: none; } }
.lc-alerta { flex: none; font-size: var(--fs-sm); line-height: 20px; width: 16px; text-align: center; color: var(--texto-apagado); }
.lc-alerta[data-alerta="1"] { color: var(--warning-texto); }
.lc-base { display: flex; align-items: center; gap: 6px; min-width: 0; }
/* "puxar" só aparece em conversa SEM dono acima do limiar: é a ação que tira o cliente da fila */
.lc-puxar {
  flex: none; font-size: var(--fs-sm); font-weight: 600; line-height: 1.25;
  color: var(--warning-texto); background: var(--ambar-suave);
  border-radius: 4px; padding: 0 5px; white-space: nowrap;
}
.lc-trecho { flex: 1; min-width: 0; font-size: var(--fs-sm); color: var(--texto-fraco); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ⛔ 11/09 (equipe C): a fila era flex:none e "Aguardando atendimento" (135 px) comia o 2º andar inteiro —
   MEDIDO na coluna de 289 px: o trecho da mensagem ficava com 0 px de largura, ou seja, sumia da tela.
   O nome da fila é uma lista fechada e curta: cortar com reticências custa quase nada. O trecho, não —
   é ele que diz o ASSUNTO da conversa. Então quem encolhe primeiro é a fila. */
.lc-fila { flex: 0 1 auto; min-width: 0; max-width: 42%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-sm); color: var(--texto-apagado); }
.lc-etiqueta {
  flex: none; display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-sm); color: var(--texto-fraco); max-width: 120px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lc-etiqueta::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--etiqueta-cor, var(--text-2)); flex: none; }
.lc-nao-lidas {
  flex: none; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  background: var(--primary); color: #fff; font-size: var(--fs-xs); font-weight: 500;
  line-height: 18px; text-align: center; font-variant-numeric: tabular-nums;
}

/* ---- 12.3 TARJA: UMA por lista (coleta atrasada) ----
   ⛔ Nunca um aviso por card: o aviso é do espelho inteiro, não do cliente. */
.tarja {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 12px;
  font-size: var(--fs-selo); line-height: 1.35;
  color: var(--n-cor, var(--texto-fraco));
  background: var(--realce-fraco);
  border-bottom: 1px solid var(--linha);
  border-left: 3px solid var(--n-cor, var(--linha-forte));
}
.tarja-texto { flex: 1; min-width: 0; }
.tarja-acao { flex: none; color: var(--primary-texto); text-decoration: none; font-weight: 500; }
.tarja-acao:hover { text-decoration: underline; }

/* ---- 12.4 PLACAR DO AO VIVO: as nove células, cada uma FILTRA a lista ----
   É clicável, então o realce da célula ativa é azul (regra do azul só no clicável). */
/* 112 px é medido, não chutado. São NOVE células; num 1440 com a barra lateral aberta
   sobram 1160 px de conteúdo (1440 − 232 da barra − 48 de respiro). Nove por 112 mais os
   oito vãos de 8 dão 1072 e cabem; com 132 a nona pulava sozinha para a fileira de baixo
   e o placar deixava de ser UM placar. As células esticam com 1fr, então em tela maior
   elas crescem juntas. */
.placar {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: var(--e2, 8px);
}
.placar-celula {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; min-height: 52px;
  background: var(--surface); border: 1px solid var(--linha); border-radius: 8px;
  cursor: pointer; text-align: left; color: var(--texto-corpo); font: inherit;
  transition: border-color var(--transicao), background var(--transicao);
}
.placar-celula:hover { border-color: var(--linha-forte); background: var(--surface-2); }
.placar-celula.ativa { border-color: var(--primary); background: rgba(var(--primary-rgb), .16); }
.pc-emoji { flex: none; font-size: var(--fs-lg); line-height: 1; }
.pc-n { font-size: var(--fs-xl); font-weight: 500; color: var(--texto); font-variant-numeric: tabular-nums; line-height: 1.1; }
.pc-rotulo { font-size: var(--fs-selo); color: var(--texto-fraco); line-height: 1.25; }
.placar-celula > .pc-texto { display: flex; flex-direction: column; gap: 1px; min-width: 0; }

/* ---- 12.5 FAIXA DE DIAGNÓSTICO + AÇÃO + IDENTIDADE + RÉGUA (dossie/05 §5.1) ----
   44 px · borda esquerda de 4 px na cor do estado · fundo da mesma cor a 12 % ·
   texto 13,5/600 · UM emoji só · selo de frescor 12,5 à direita. */
.faixa-diag {
  display: flex; align-items: center; gap: 8px;
  min-height: var(--faixa-a); padding: 8px 12px;
  border-left: 4px solid var(--e-cor, var(--text-2));
  background: var(--e-tinta, rgba(var(--neutro-rgb), .12));
  border-radius: 0 8px 8px 0;
}
.fd-emoji { flex: none; font-size: var(--fs-lg); line-height: 1.2; }
.fd-texto { flex: 1; min-width: 0; font-size: var(--fs-faixa); font-weight: 600; line-height: 1.35; color: var(--texto-corpo); }
.fd-frescor { flex: none; font-size: var(--fs-selo); font-weight: 400; color: var(--f-cor, var(--texto-fraco)); white-space: nowrap; }
.linha-acao { font-size: var(--fs-base); line-height: 1.45; color: var(--texto-corpo); padding: 0 2px; }
.linha-identidade { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: var(--fs-sm); color: var(--texto-fraco); padding: 0 2px; }
.li-item { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.li-item strong { font-weight: 500; color: var(--texto); }

/* régua de quatro números frios — o número é o que se compara, então tabular-nums sempre */
.regua { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; background: var(--linha); border: 1px solid var(--linha); border-radius: 8px; overflow: hidden; }
.regua-item { background: var(--surface); padding: 7px 8px; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
/* ⛔ O rótulo QUEBRA em duas linhas; não corta com reticências. Na coluna de 320 px
   "quedas em 5 dias" virava "quedas …" e o número perdia o nome — um número frio sem
   nome é pior do que número nenhum. As quatro células esticam juntas pelo grid. */
.regua-rotulo { font-size: var(--fs-selo); color: var(--texto-fraco); line-height: 1.2; overflow-wrap: break-word; }
.regua-valor { font-size: var(--fs-lg); font-weight: 500; color: var(--f-num, var(--texto)); font-variant-numeric: tabular-nums; line-height: 1.2; }

/* ⭐ 12/09 — ORDEM DO DONO, literal: "a parte que aparece o SINAL da pessoa tem que ficar AMARELO
   ou LARANJA, mesma cor do card mais destacado, igual no MONITOR". O amarelo é o do próprio
   Monitor Óptico (a variável --at do painel dele: #f5a524 no escuro, #b45309 no claro) — medido no
   CSS publicado, não escolhido por gosto.
   ⛔ Este destaque é de LEITURA (achar o número na tela), não é veredito: quem diz se está bom ou
   ruim continua sendo o selo de estado e a frase do Monitor logo abaixo. Por isso o amarelo vale
   para o quadro do sinal SEMPRE, em qualquer estado — se mudasse de cor conforme o valor, viraria
   um segundo semáforo, disputando com o primeiro.
   ⛔⛔ 12/09, SEGUNDA VOLTA — eu tinha escrito aqui uma exceção que devolvia o quadro ao CINZA
   quando o dado não estava "ao vivo". Só que o caso de TODO DIA é justamente esse: a ficha abre
   antes de o Monitor ser consultado, e o quadro nascia cinza — o dono viu e disse "ainda não tá
   amarelo ou laranja". A exceção CAIU: o quadro do sinal é amarelo SEMPRE, com dado ou sem dado.
   O envelhecimento continua sendo dito, mas por opacidade (o número apaga), não por troca de cor:
   assim o quadro continua achável na tela e ninguém confunde "velho" com "outro estado". */
.regua-item[data-destaque="sinal"] { background: var(--sinal-destaque-bg); box-shadow: inset 3px 0 0 var(--sinal-destaque); }
.regua-item[data-destaque="sinal"] .regua-valor { color: var(--sinal-destaque); font-weight: 600; }
.regua-item[data-destaque="sinal"] .regua-rotulo { color: var(--sinal-destaque-rotulo); }
.regua-item[data-destaque="sinal"][data-frescor] .regua-valor { opacity: .68; }

/* ---- 12.6 SELOS E CHIPS DA GAVETA ---- */
.selo-estado {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 6px;
  font-size: var(--fs-selo); font-weight: 500; line-height: 1.4; white-space: nowrap;
  background: var(--e-tinta, rgba(var(--neutro-rgb), .12));
  color: var(--e-texto, var(--texto-fraco));
}
.selo-frescor { font-size: var(--fs-selo); color: var(--f-cor, var(--texto-fraco)); white-space: nowrap; }
.chips-gaveta { display: flex; flex-wrap: wrap; gap: 6px; }
.chip-gaveta {
  display: inline-flex; align-items: center; gap: 5px;
  height: 26px; padding: 0 10px; border-radius: 6px;
  background: transparent; border: 1px solid var(--borda-controle);
  color: var(--primary-texto); font: inherit; font-size: var(--fs-sm); font-weight: 500;
  cursor: pointer; white-space: nowrap;
  transition: background var(--transicao), border-color var(--transicao);
}
.chip-gaveta:hover { background: rgba(var(--primary-rgb), .16); border-color: var(--primary); }
.chip-gaveta[aria-expanded="true"] { background: rgba(var(--primary-rgb), .16); border-color: var(--primary); }
.chip-gaveta[disabled] { color: var(--texto-apagado); border-color: var(--linha); cursor: default; background: transparent; }

/* ---- 12.7 LINHA-MÃE DE EVENTO (N conversas da mesma ocorrência) ----
   Sem isto um rompimento de 23 clientes vira 23 O.S. */
.linha-evento {
  display: flex; align-items: center; gap: 8px 10px; flex-wrap: wrap;
  padding: 9px 12px 9px 9px;
  border-bottom: 1px solid var(--linha);
  border-left: 3px solid var(--e-cor, var(--negative));
  background: var(--e-tinta, rgba(var(--negative-rgb), .12));
}
.le-emoji { flex: none; font-size: var(--fs-md); line-height: 1.2; }
/* o GRAU do laudo nunca é cortado: "ROMPIMENTO PROVÁVEL" cortado em "ROMPIMENTO …" muda
   o que a atendente pode dizer ao cliente. Na coluna estreita a contagem desce de linha. */
.le-grau { flex: 1 1 60%; min-width: 0; font-size: var(--fs-base); font-weight: 500; color: var(--texto); line-height: 1.3; }
.le-n { flex: none; font-size: var(--fs-sm); color: var(--texto-fraco); font-variant-numeric: tabular-nums; }
.le-acoes { flex: none; display: flex; gap: 6px; }

/* ---- 12.8 SEM ESPELHO ----
   O bloco inteiro vira frase. ⛔ Nunca "sem sinal", nunca número velho fingindo de novo. */
.sem-espelho {
  display: flex; flex-direction: column; gap: 6px;
  padding: 12px; border: 1px dashed var(--linha-forte); border-radius: 8px;
  background: var(--realce-fraco);
}
.se-texto { font-size: var(--fs-base); line-height: 1.45; color: var(--texto-fraco); }
.se-link { font-size: var(--fs-sm); color: var(--primary-texto); text-decoration: none; font-weight: 500; }
.se-link:hover { text-decoration: underline; }

/* ---- 12.9 ESCOLHA EM GRADE (motivo de fechamento, contrato, fila) ---- */
.grade-opcoes { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px; }
.opcao {
  display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  padding: 9px 11px; min-height: 46px;
  background: var(--surface); border: 1px solid var(--linha); border-radius: 8px;
  cursor: pointer; text-align: left; font: inherit; color: var(--texto-corpo);
  transition: border-color var(--transicao), background var(--transicao);
}
.opcao:hover { border-color: var(--linha-forte); background: var(--surface-2); }
.opcao.ativa { border-color: var(--primary); background: rgba(var(--primary-rgb), .16); }
.opcao-nome { font-size: var(--fs-base); font-weight: 500; color: var(--texto); }
.opcao-nota { font-size: var(--fs-sm); color: var(--texto-fraco); line-height: 1.3; }

/* ---- 12.10 FAIXA DE DADOS DE EXEMPLO (app.js, quando o /health traz exemplo: true) ----
   Uma linha, logo abaixo do cabeçalho, grudada nele ao rolar. Fundo âmbar suave e texto --warning-texto
   (legível nos dois modos). A altura é publicada em --faixa-exemplo-a pelo app.js só quando a faixa
   aparece, e a caixa desconta essa altura: sem isso a página ganharia uma rolagem de 28 px. */
.faixa-exemplo {
  position: sticky; top: var(--header-a, 52px); z-index: 39;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  height: var(--faixa-exemplo-a, 28px); box-sizing: border-box; padding: 0 12px;
  background: var(--ambar-suave); color: var(--warning-texto);
  border-bottom: 1px solid rgba(var(--warning-rgb), .35);
  font-size: var(--fs-selo); font-weight: 500; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.faixa-exemplo-texto { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* ══════════════════════════════════════════════ 13. RESPONSIVO — 1440 / 1280 / 1024 / 600
   A caixa de 3 colunas vira 2 no notebook (a ficha abre como gaveta) e 1 no celular.

   Por que existe um degrau em 1280 que não está na lista de breakpoints do dossie/04:
   a regra da casa é que a COLUNA DO MEIO é sempre a maior. Com 344 + 320 de laterais
   sobram 360 px para a conversa num 1024 — medido no navegador, a do meio caiu para
   122 px e a caixa ficou impossível de ler. Então as três colunas só valem a partir de
   1280; de 1024 para baixo a ficha vira gaveta. Os degraus nomeados (1440 · 1024 · 600)
   continuam todos lá, este é um degrau A MAIS, não um no lugar de outro. */

/* até 1439: as colunas laterais encolhem, a do meio continua sendo a maior */
@media (max-width: 1439px) {
  html:root { --caixa-lista-l: 320px; --caixa-lista-l-max: 384px; --caixa-ficha-l: 300px; }
}

/* até 1279 o placar de nove células deixa de ser auto-fit (que dava 6 + 3): grade fixa de 3 × 3 */
@media (max-width: 1279px) {
  .placar { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* até 1279 (o notebook de 1024 entra aqui): duas colunas, a ficha vira folha lateral.
   ⛔ Não sai do DOM e não é escondida por classe: ela desliza e só volta a ser focável
   quando está aberta (visibility). Esconder de verdade continua sendo el.hidden. */
@media (max-width: 1279px) {
  html:root { --caixa-lista-l: 300px; --caixa-lista-l-max: 364px; }
  /* min(…, 38%) trava a lista em pouco mais de um terço: medido no navegador, com a largura
     fixa em px a coluna do meio caía para 210 px num tablet e a conversa ficava ilegível.
     A regra da casa é que a conversa é SEMPRE a maior — aqui ela tem 62 % garantidos. */
  .caixa, .caixa.sem-ficha { grid-template-columns: min(var(--caixa-lista-l), 38%) minmax(0, 1fr); }
  .caixa-ficha {
    position: fixed; top: calc(var(--header-a, 52px) + var(--faixa-exemplo-a, 0px)); right: 0; bottom: 0;
    width: var(--caixa-ficha-l); max-width: 92vw; z-index: 92;
    box-shadow: var(--sombra-modal);
    transform: translateX(100%); visibility: hidden;
    transition: transform var(--transicao-suave), visibility var(--transicao-suave);
  }
  .caixa[data-ficha="aberta"] .caixa-ficha { transform: none; visibility: visible; }
  .caixa-ficha[hidden] { display: none; }
}

/* até 1023 (degrau do dossiê): a lista encolhe para a conversa continuar sendo a maior. */
@media (max-width: 1023px) {
  html:root { --caixa-lista-l: 264px; --caixa-lista-l-max: 328px; }
}

/* até 600 (o degrau sm do dossiê, inclusive): uma coluna. data-painel diz qual está na frente. */
@media (max-width: 600px) {
  /* a linha fica nos 48 px do contrato também no celular (era 52): o dedo tem 44 no mínimo, e 48 cabe */
  html:root { --caixa-lista-l: 100%; --caixa-linha-a: 48px; }
  .caixa, .caixa.sem-ficha { grid-template-columns: minmax(0, 1fr); }
  .caixa-lista { border-right: 0; }
  .caixa-conversa {
    position: fixed; inset: calc(var(--header-a, 52px) + var(--faixa-exemplo-a, 0px)) 0 0 0; z-index: 88;
    transform: translateX(100%); visibility: hidden;
    transition: transform var(--transicao-suave), visibility var(--transicao-suave);
  }
  .caixa[data-painel="conversa"] .caixa-conversa { transform: none; visibility: visible; }
  .caixa-voltar { display: inline-flex; }
  .caixa-ficha { top: 0; width: 100%; max-width: 100%; }
  .placar { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .regua { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* ⛔ No celular a lista ocupa a largura inteira, então a fila e a etiqueta CONTINUAM na
     tela: o que encolhe é o trecho da mensagem. Esconder a fila economizaria 60 px e
     custaria a informação de quem é a conversa. */
  .lc-etiqueta { max-width: 92px; }
  /* ⛔ o alvo de toque cresce no celular: 44 px é o mínimo do dedo */
  .placar-celula, .opcao, .chip-gaveta { min-height: 44px; }
}

/* a partir de 1920 a coluna do meio já é larga demais: a leitura fica melhor com limite */
@media (min-width: 1920px) {
  html:root { --caixa-lista-l: 360px; --caixa-lista-l-max: 424px; --caixa-ficha-l: 340px; }
}

/* ══════════════════════════════════════════════ 14. MOVIMENTO REDUZIDO E IMPRESSÃO */
@media (prefers-reduced-motion: reduce) {
  html:root { --transicao-suave: 0s; }
  .caixa-ficha, .caixa-conversa { transition: none; }
}
@media print {
  html:root { color-scheme: light; }
  .sidebar, .header, .placar, .chips-gaveta, .caixa-voltar { display: none; }
  .caixa, .caixa.sem-ficha { grid-template-columns: minmax(0, 1fr); height: auto; }
}

/* ══════════════════════════════════════════════ 15. MENU RECOLHIDO × CAIXA (ordem 3 do dono, 11/09)
   O dono, literal: "menu recolhível, encolhendo para a esquerda, EXATAMENTE idêntico ao do Financeiro
   Pro — onde ele fecha e AUMENTA UM POUCO para poder ler."

   A sanfona em si (232 ↔ 64 px, memória em localStorage "fp.menu.encolhido", botão com a seta bem
   transparente no rodapé da barra) já é a MESMA do Financeiro Pro — app.css §20 e app.js
   aplicarMenuEncolhido(), copiados linha a linha. O que faltava era a segunda metade da frase: lá os
   168 px que a barra devolve engordam a LISTA da caixa (app.css publica --ib-lista-l-max), e aqui a
   caixa nova usa outro token (--caixa-lista-l, tema §12.1) — então o "aumenta um pouco para poder ler"
   não acontecia. Esta regra liga os dois.

   ⛔ Sem transição, pelo mesmo motivo medido no Financeiro Pro (app.css §20): animar a largura da barra
   e a margem do conteúdo anima LAYOUT e pega qualquer mudança de viewport, não só o clique.
   ⛔ Só a partir de 901 px: abaixo disso a barra é a gaveta de sempre e a lista já ocupa a largura toda. */
@media (min-width: 901px) {
  body.menu-encolhido { --caixa-lista-l: var(--caixa-lista-l-max); }
}

/* ══════════════════════════════════════════════ 16. CELULAR "ESTILO APLICATIVO" (ordem 4 do dono, 11/09)
   O dono, literal: "tentei entrar estilo aplicativo no celular e não está bem responsivo — tem que ajeitar."

   O que "estilo aplicativo" exige, e onde cada coisa é resolvida:
     uma coluna e folhas (lista → conversa → ficha)  ... §13, já existia
     cabeçalho em UMA linha                          ... app.css ≤ 900 + os apertos daqui
     alvo mínimo de 44 px                            ... aqui
     ⛔ nenhuma rolagem horizontal                   ... aqui (min-width: 0 e quebra de palavra)
     recorte do iPhone (notch e barra de gestos)     ... aqui, pelos tokens --safe-*
     o teclado não pode cobrir o campo de escrever   ... aqui (--teclado-a) + caixa.js (visualViewport)

   ⛔ 100vh no celular é MAIOR que a tela (a barra do navegador entra na conta): o campo de escrever some
   embaixo da barra de endereço. Por isso 100dvh, com 100vh como recuo para navegador velho. */
html:root {
  /* env() com recuo 0px: navegador sem notch e desktop ficam em zero, e a conta nunca vira inválida */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  /* altura que o teclado virtual está comendo da tela; quem escreve é caixa.js, pelo visualViewport */
  --teclado-a: 0px;
}

@media (max-width: 900px) {
  /* O recorte de cima entra no PRÓPRIO --header-a: assim tudo que já calculava "abaixo do cabeçalho"
     (a altura da caixa, o topo das folhas da conversa e da ficha) acerta sozinho, sem uma segunda conta
     espalhada por cinco arquivos. O conteúdo do cabeçalho desce pelo padding. */
  html:root { --header-a: calc(52px + var(--safe-t)); }
  :root .header { padding-top: var(--safe-t); padding-left: calc(var(--e3) + var(--safe-l)); padding-right: calc(var(--e3) + var(--safe-r)); }
  /* a gaveta do menu começa no alto da tela: a marca também precisa descer do notch */
  :root .sidebar { padding-left: var(--safe-l); }
  :root .sidebar-marca { height: var(--header-a); padding-top: var(--safe-t); }
  :root .sidebar-nav { padding-bottom: calc(var(--e4) + var(--safe-b)); }

  /* cabeçalho em UMA linha em 360 px: ☰ · Atendimento Web · SOMBRA · avatar.
     ⛔ O selo do modo NÃO some — é ele que diz que nada sai para o cliente. Quem encolhe é o título. */
  :root .header-titulo { font-size: var(--fs-sm); }
  :root .header-conta { flex: 1 1 auto; min-width: 0; }
  :root .selo-modo { flex: none; max-width: 46%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* ⛔⛔ 12/09: ALVO DO DEDO na CASCA — aqui, e não em ≤600 px, porque é aqui que a gaveta existe.
     Medido no DOM em 390 e 360 com a gaveta ABERTA: o ☰ do cabeçalho tinha 36 px e os 11 itens
     de submenu (Ferramentas e Definições) tinham 40 px. Quatro pixels parecem nada até o dedo
     abrir "Etiquetas" querendo "Campos" — e são justamente os itens mais juntos da tela.
     ⛔ Vale para o ☰ e para o X de fechar a gaveta, que são o mesmo .btn-icone.
     (app.css é a casca e é do lead — a correção mora aqui, que já é a casa dos 44 px.) */
  :root .header .btn-icone, :root .sidebar .btn-icone { min-height: 44px; min-width: 44px; }
  :root .sidebar .nav-item.sub { height: 44px; min-height: 44px; }

  /* ⛔ rolagem horizontal: qualquer palavra comprida (um wamid, um e-mail, um Pix) empurrava a página */
  :root body { overflow-x: hidden; }
  :root .conteudo { overflow-x: clip; }

  /* ⛔⛔ A GAVETA DO MENU FICAVA POR BAIXO DA CONVERSA — medido em 390 px (equipe C, 11/09): com uma
     conversa aberta, tocar no ☰ abria a gaveta e só se via uma tira dela no alto; o resto ficava atrás
     da folha da conversa e do painel do cliente. A casca herdada põe a gaveta em 60 (e o véu em 55),
     números de quando não existia folha em cima da tela; a caixa nova usa 88 (conversa) e 92 (ficha).
     Aqui a gaveta volta para cima dos dois — e continua ABAIXO do modal (100) e dos avisos (200),
     que são o que precisa ganhar dela. Só no celular: em ≥ 901 px a barra não é gaveta e não sobrepõe. */
  :root .sidebar-overlay { z-index: 96; }
  :root .sidebar { z-index: 97; }
}

@media (max-width: 600px) {
  /* altura real da tela (⛔ nunca 100vh): recuo primeiro, dvh depois — quem entende dvh usa a 2ª linha */
  .caixa { height: calc(100vh - var(--header-a) - var(--faixa-exemplo-a, 0px)); }
  .caixa { height: calc(100dvh - var(--header-a) - var(--faixa-exemplo-a, 0px)); }

  /* O TECLADO. No celular o teclado não encolhe a janela — encolhe a visualViewport. Sem isto a folha da
     conversa continua indo até o fim da tela e o campo de escrever fica EMBAIXO do teclado (o defeito que
     o dono viu). caixa.js mede a sobra e publica --teclado-a; aqui a folha para em cima do teclado. */
  .caixa-conversa {
    inset: calc(var(--header-a) + var(--faixa-exemplo-a, 0px)) var(--safe-r) var(--teclado-a) var(--safe-l);
  }
  .caixa-ficha { top: 0; bottom: var(--teclado-a); width: 100%; max-width: 100%; }
  /* a barra de gestos do iPhone fica POR CIMA do que estiver no rodapé: o respiro é do composer,
     ⛔ não da altura da caixa (tirar altura deixaria uma faixa morta no fim da lista). */
  .caixa-conversa .composer { padding: var(--e3) var(--e3) calc(var(--e3) + var(--safe-b)); }
  .caixa-lista-itens { padding-bottom: var(--safe-b); overscroll-behavior: contain; }

  /* ⛔ alvo do dedo: 44 px é o mínimo. Vale para tudo que se toca na caixa e na casca.
     (as classes .cx-* são da tela — o alvo delas mora no CSS da caixa.js, uma casa só por classe) */
  .caixa-voltar, .chip-gaveta, .placar-celula, .opcao { min-height: 44px; }
  :root .caixa .btn-icone, :root .caixa .btn { min-height: 44px; }
  /* a linha da lista continua nos 48 px do contrato — já é alvo de sobra e é o que mantém a densidade */

  /* ⛔⛔ 12/09 (verificação): as duas regras acima PROMETIAM 44 px e não alcançavam metade do que se
     toca. Medido no DOM em 390 e em 360, só o que estava visível dentro da tela:
       · caixa: ☰ 36 px · buscar 36 px · etiqueta 30 px · ordem 30 px · 8× o ⋯ da linha 32 px;
       · gaveta: 11 itens de submenu 40 px;
       · Indicadores: "Atualizar" 36 px · 6 abas de período 30 px · 2 datas 36 px · 2 filtros 36 px;
       · Ao Vivo: 3 .btn-sm 30 px;   · Definições: 2 <select> 36 px.
     O motivo é sempre o mesmo: a regra falava de CLASSE (".caixa .btn") num lugar onde o que o dedo
     encosta é ELEMENTO (<input>, <select>) ou mora fora da .caixa. Regra que existe e não alcança é
     pior que regra que falta — alguém lê e acredita.
     A ordem 4 do dono é sobre o APLICATIVO no celular, não sobre uma tela: então a regra passa a ser
     por elemento e vale na casa inteira. ⛔ Só a ALTURA cresce; nada muda de largura. */
  :root .btn:not(.login-mostrar) { min-height: 44px; }
  :root .abas .aba { min-height: 44px; }
  :root select, :root textarea,
  :root input:not([type="checkbox"]):not([type="radio"]):not([type="range"]) {
    min-height: 44px; font-size: 16px;
  }
  /* ⛔ o 16px junto não é enfeite e nem gosto: abaixo disso o Safari do iPhone DÁ ZOOM ao focar o
     campo e a tela inteira sai do lugar. É a mesma razão já escrita no composer da conversa.
     ⛔ caixa, rádio e range ficam de fora: quem ganha o alvo de 44 px ali é o <label> em volta
     (.interruptor, .opcao), senão o quadradinho cresceria e o desenho do interruptor quebraria.
     ⛔ .login-mostrar fica de fora porque ela é ABSOLUTA dentro do campo de senha (top/bottom: 3px):
     44 px ali estouraria o próprio campo em vez de virar alvo. */

  /* ⛔⛔ 12/09 (corretor): o CARTÃO DE DOCUMENTO da conversa é um <a> — e nenhuma das regras acima
     alcança <a>. Medido em 390 px, com uma semente que TEM anexo ("[Documento] boleto.pdf"), ele
     saía com 38 px, três vezes na mesma tela. É o alvo que BAIXA o arquivo do cliente: errar o
     toque aqui abre a conversa em vez de abrir o boleto.
     ⚠️ Ele só aparece quando a semente traz anexo — por isso passou tanto tempo invisível: quem
     rodava o conferidor de 44 px com a semente sem anexo nunca via este elemento na tela. */
  :root .balao .anexo-doc { min-height: 44px; }
}

/* 390 e 360 px em RETRATO: as duas larguras que o dono testou. Aqui não se muda o desenho, só se tira
   o que não cabe — e ⛔ nada que seja informação. */
@media (max-width: 400px) {
  /* o nome do cliente é o que importa na linha: a etiqueta encolhe antes dele */
  .lc-etiqueta { max-width: 76px; }
  /* a régua de quatro números vira 2 × 2 (já é o padrão ≤ 600) e o rótulo continua quebrando, não cortando */
  .fd-texto { font-size: var(--fs-base); }
}

/* ══════════════════════════════════════════════ 17. MODO CLARO — OS CONSERTOS DE QUEM NASCEU NO ESCURO
   (18/09/2026, ordem do dono: "o claro tem que ficar perfeito, com tudo branco e contrastes dos botões")

   Os TOKENS do claro moram na §7. Esta seção é o que os tokens sozinhos não alcançam: regras que
   cravaram uma cor pensando no fundo escuro (no app.css e nas folhas EMBUTIDAS das telas — caixa.js,
   aovivo.js, contatos.js, broadcasts.js, respostas.js) e que, no claro, pintam errado.
   Foram 238 cores fixas classificadas uma a uma (scratchpad/cores_fixas.txt): 205 são neutras nos
   dois modos ou recuo de var() que nunca pinta; as que sobraram estão aqui.

   ⛔ COMO ESTAS REGRAS GANHAM. As folhas embutidas entram no documento DEPOIS desta, então ordem não
   serve: cada override vence por ESPECIFICIDADE — html:root[data-tema="claro"] .x é (0,2,1) e passa
   de qualquer (0,1,0)/(0,2,0) de folha embutida. Onde a regra original é mais funda (0,3,0), o
   seletor daqui a repete inteira e soma o (0,1,1) do prefixo.
   ⛔ Os arquivos das telas NÃO se editam nesta frente (outra equipe está neles): o conserto é
   sempre daqui. ⛔ Nada aqui vale no escuro, exceto a 17.1, que é dos dois modos de propósito. */

/* ---- 17.1 NOS DOIS MODOS: folha embutida pintando branco sobre verde/âmbar cheio ----
   broadcasts.js .bc-passo.feito .n: #fff sobre --verde = 3,37 no claro (#12a150) e 2,57 no escuro
   (#21BA45) — o mesmo defeito que a §11 já conserta em .passo.feito .n. #08170D = 5,48 / 6,99.
   contatos.js .ct-bot-todos: #fff sobre --ambar = 3,19 no claro (#d97706) e 1,70 no escuro
   (#F2C037). #1b1205 = 5,81 / > 10 — a mesma tinta que nota.js já usa no botão âmbar. */
html:root .bc-passo.feito .n { color: #08170D; }
html:root .ct-bot-todos, html:root .ct-bot-todos:hover:not(:disabled) { color: #1b1205; }
/* caixa.js .cx-achado mark (o trecho achado na busca): herdava --texto-fraco por cima de 45 % de âmbar.
   A classificação dizia que no escuro passava; MEDIDO no conferidor: #9E9E9E sobre #7d6729 = 2,04 no
   escuro e #6b7280 sobre #eec28f = 3,29 no claro — reprova nos dois. Com --texto: 5,46 / 10,75.
   (0,2,2) vence o (0,1,1) da folha embutida. */
html:root .cx-achado mark { color: var(--texto); }

/* ---- 17.2 BORDA DE CONTROLE nos herdados do app.css ----
   .btn (contorno) e .composer-caixa escrevem border-color: var(--linha-forte) e o app.css não se
   edita. Em vez de brigar por border-color (o :hover do .btn e o :focus-within do composer, ambos
   (0,2,0), PERDERIAM para um (0,2,1) daqui), o que muda é a VARIÁVEL que eles leem, só dentro deles:
   --linha-forte passa a valer --borda-controle no elemento. O :hover (--texto-apagado) e o foco
   (--primary) continuam ganhando como sempre. .btn-primary/-ghost/-perigo/-verde/.ativo não leem
   --linha-forte e ficam como estão. */
html:root[data-tema="claro"] .btn,
html:root[data-tema="claro"] .composer-caixa { --linha-forte: var(--borda-controle); }

/* ---- 17.3 HOVER que usava --bg: com página e painel ambos #ffffff, "fundo --bg" virou invisível ----
   app.css: .btn-ghost:hover, .header-usuario:hover/[aria-expanded], .menu-item:hover.
   contatos.js .ct-menu-lista button:hover · respostas.js .rr-vars-lista button:hover.
   Todos passam para --surface-3 (#eef0f3, 1,14 sobre branco): é o degrau de "estou em cima". */
html:root[data-tema="claro"] .btn-ghost:hover,
html:root[data-tema="claro"] .header-usuario:hover,
html:root[data-tema="claro"] .header-usuario[aria-expanded="true"],
html:root[data-tema="claro"] .menu-item:hover,
html:root[data-tema="claro"] .ct-menu-lista button:hover,
html:root[data-tema="claro"] .ct-menu-lista button:focus-visible,
html:root[data-tema="claro"] .rr-vars-lista button:hover,
html:root[data-tema="claro"] .rr-vars-lista button:focus-visible { background: var(--surface-3); }

/* ---- 17.4 BOTÃO DE CONTORNO PERIGOSO: a borda da §11 (rgba(193,0,21,.55) sobre branco = #dd737e)
   mede 3,08 — na risca do 3, e a ordem é "contorno com borda visível". Borda cheia: 6,41. ---- */
html:root[data-tema="claro"] .btn-contorno-danger { border-color: var(--negative); background: var(--surface); color: var(--negative-texto); }
html:root[data-tema="claro"] .btn-contorno-danger:hover { background: var(--vermelho-suave); border-color: var(--negative); color: var(--negative-texto); }

/* ---- 17.5 CHIP DA JANELA (aovivo.js .av-janela, caixa.js .cx-c-janela): pinta o texto com --warning
   CHEIO sobre a tinta de 16 % — no escuro --warning == --warning-texto (#F2C037, 6,85) e nada muda;
   no claro #d97706 sobre #f9e9d7 = 2,68 em texto de 10-11 px. --warning-texto #92400E = 5,96.
   Seletor (0,3,1) vence o (0,2,0) da folha embutida. ---- */
html:root[data-tema="claro"] .av-janela[data-cor="warning"],
html:root[data-tema="claro"] .cx-c-janela[data-cor="warning"] { color: var(--warning-texto); }

/* 19/09: texto pequeno sobre fundos suaves precisa da tinta de texto, não do azul de botão. */
html:root[data-tema="claro"] .ct-var:hover,
html:root[data-tema="claro"] .ct-var:focus-visible,
html:root[data-tema="claro"] .cp-var:hover,
html:root[data-tema="claro"] .cp-var:focus-visible,
html:root[data-tema="claro"] .rr-item.sel .rr-atalho,
html:root[data-tema="claro"] .rr-rodape button,
html:root[data-tema="claro"] .bc-etq.ativo .q,
html:root[data-tema="claro"] .agora-tag { color: var(--primary-texto); }
/* A citação e o recado enviado acumulam fundos translúcidos; a tinta escura preserva a leitura. */
html:root[data-tema="claro"] .cx-citado-autor,
html:root[data-tema="claro"] .chat-bolha.minha .qd { color: var(--texto-corpo); }
html:root[data-tema="claro"] .nt-sistema-hora { opacity: 1; }
/* O visor de fotos tem fundo escuro nos dois temas; não herda o azul dos links da página clara. */
html:root .cx-visor-link { color: #cfcfcf; }
html:root .cx-visor-link:hover { color: #fff; }
