/* #145 — OS TOKENS DESTE ARQUIVO VIRARAM APELIDOS DOS DE `tokens.css`.
 *
 * O SISTEMA TINHA DOIS CONJUNTOS DE TOKENS, e a #142 trocou so um. Resultado:
 * dois azuis convivendo em producao (#2563eb novo nos 16 tokens trocados,
 * #276fc6 velho em 30 usos daqui), duas famílias de borda e dois fundos.
 * NADA pegou: a suite nao ve cor, o portao de acessibilidade ve CONTRASTE e as
 * duas paletas passavam separadamente, e a bateria nao compara cores.
 *
 * O erro de raciocinio: a regra do CLAUDE.md diz "cor literal so em
 * tokens.css", e eu conclui que TODO token mora la. A regra fala de cor
 * LITERAL -- ela nao impede um segundo conjunto de tokens em outro arquivo.
 * Confiar no documento em vez de enumerar e o mesmo erro que custou a #136.
 *
 * Os nomes antigos FICAM (211 usos), agora apontando para a paleta unica. Quem
 * escrever CSS novo usa os de `tokens.css`; estes existem para nao reescrever
 * 211 lugares numa rodada de cor. */
/* Tinta e papel, nao cromo colorido.
   A barra de navegacao ocupava a maior area e a cor mais saturada da tela
   carregando a MENOR quantidade de informacao. Aqui o cromo recua para
   tinta, e o azul passa a significar uma coisa so: da para agir aqui. */
:root {
  /* #293: os OITO apelidos do #145 (--tinta, --tinta-fraca, --acao,
     --acao-escura, --realce, --fundo, --superficie, --borda) SAÍRAM daqui --
     eram 320 usos de um nome e 331 do canônico para a MESMA cor. Só o nome de
     tokens.css existe agora (--ink, --ink-3, --azul, --azul-escuro,
     --azul-fraco, --page, --surface, --line). Troca mecânica, valor idêntico. */
  /* #57-B: três azuis conviviam sem que ninguém tivesse decidido isso — o
     token do #36 (--azul #276fc6), este --acao vibrante (#1550e5) nas pílulas
     do DRE/Análise e no "+ Nova categoria", e um arroxeado (#0f3fbb) no botão
     da Conciliação. Unificados na família do --azul. Contrastes medidos sobre
     branco: #276fc6 = 5,03 (AA) e #1f5da8 = 6,55 (AA); sobre --realce
     #eaf0fe, #1f5da8 = 5,77 (AA) — o próprio #276fc6 daria 4,41 e FALHARIA,
     por isso a variante escura existe e é ela que vai em texto sobre azul-claro. */
  /* #168: `--acao-clara` saiu daqui. Ela existia "só no gradiente da barra de
     progresso", e esse gradiente tinha as duas pontas na mesma cor desde que
     o #57-B unificou os azuis -- ou seja, ela nao pintava nada distinguivel
     havia varias rodadas. Removida junto com o gradiente chapado que a usava. */
  /* Vermelho e verde mais escuros que os anteriores (#e94747 / #24ad52):
     dinheiro e lido em corpo pequeno sobre branco, e os tons claros nao
     alcancavam contraste 4.5:1. Estes alcancam, e ainda imprimem.
     #168: as tres MUDARAM DE CASA para `tokens.css`, com o valor intacto --
     a decisao #70 diz que cor literal so mora la. O texto acima fica porque
     e o registro de POR QUE elas sao escuras; o valor agora se le no
     tokens.css, junto do aviso de que --erro/--sucesso/--atencao e
     --vermelho/--verde/--amarelo sao duas familias esperando decisao. */
  /* #168 — O `--raio: 8px` QUE MOROU AQUI NUNCA PINTOU NADA, e por dois anos
     de rodadas ninguem viu, porque CSS nao reclama de token perdedor.
     `tokens.css:82` define `--raio: 10px` e carrega DEPOIS (base.html:21-23),
     entao os 54 usos de `var(--raio)` -- 34 neste arquivo, 20 em
     `componentes.css` -- sempre renderizaram 10px. Quem editasse o 8px veria
     a tela nao mudar e procuraria o defeito em qualquer outro lugar.
     E o MESMO defeito que o #145 descreve no topo deste arquivo (dois
     conjuntos de tokens, um deles morto em silencio): ele varreu COR e parou
     ali. Raio era o irmao que ficou. A guarda contra a terceira ocorrencia
     esta em `tests/test_token_sem_colisao_168.py`, que falha se QUALQUER
     token for definido nos dois arquivos com valores diferentes.
     `--raio-miudo` fica: e definido so aqui, nao colide. */
  --raio-miudo: 4px;
  --linha: 32px;
  /* #168: `--sombra` tambem foi para `tokens.css`, junto das outras cinco
     elevacoes que viviam soltas em box-shadow ao longo deste arquivo. */
}

/* A fonte reservada ao DINHEIRO, e a nada mais.
   A classe `valor` ja marcava dinheiro com exclusividade (era o alvo do
   borrao de "ocultar valores"); aqui ela vira tambem um papel tipografico.
   Condensada de proposito: deixa um saldo de sete digitos ser grande sem
   comer a largura da coluna, e da a coluna de valores a textura de um
   extrato. IBM Plex Sans Condensed, SIL OFL 1.1. */
@font-face {
  font-family: "Cifra";
  src: url("../fontes/PlexCondensed-500.25db464417d3.woff2") format("woff2");
  /* #287: descritor de @font-face não resolve `var()` -- os dois pesos
     caíam em `normal` e a segunda face vencia a primeira. Literal, como o
     `tokens.css` já faz com a Inter. */
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: "Cifra";
  src: url("../fontes/PlexCondensed-600.bac89dc82014.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
}

* { box-sizing: border-box; }

/* O `body` mora em tokens.css desde o #70 -- corpo único de 15px system-ui
   sobre --page. Declarar aqui de novo só criaria uma segunda verdade que
   perde a cascata em silêncio. */

/* `flex-wrap: wrap`, e nao `overflow-x: auto`: a barra tem submenus
   (`.submenu`) posicionados `position: absolute` por cima dela, e
   `overflow-x: auto` num container forca o `overflow-y` computado tambem
   para `auto` (regra da propria spec do CSS -- um eixo com overflow
   diferente de `visible` empurra o outro eixo para fora de `visible`
   tambem), o que transforma `.topo` num container de RECORTE: qualquer
   submenu que escape da caixa de 56px fica cortado e inalcancavel por
   mouse, mesmo com `display: block` no hover (achado da revisao final --
   `elementFromPoint` no centro do link nao alcancava o alvo; o Playwright
   `is_visible()` nao pegou o defeito porque e cego a clipping por
   ancestral).
   Com `flex-wrap: wrap` a barra nunca entra em modo de recorte: numa tela
   de 390px o nome da empresa, o menu e o lado direito quebram em linhas
   separadas em vez de estourar para o lado, sem precisar de overflow nenhum
   aqui (mesmo problema das tabelas largas, solucao diferente porque esta
   barra tem filhos que precisam escapar dela). `flex: none` nos filhos
   impede que texto como "Lançamentos" quebre linha sozinho ou se esprema
   antes da barra quebrar. */
.topo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--esp-8) var(--esp-24);
  min-height: 56px;
  padding: var(--esp-8) var(--esp-16);
  /* #145 — A BARRA CLARA da referência do dono (/root/referencia/menusup.png).
     Era `--tinta` com texto branco desde sempre; passa a ser superfície branca
     com uma linha embaixo, texto slate e o item ativo em azul sublinhado. */
  background: var(--surface);
  color: var(--ink);
  border-bottom: 1px solid var(--line);
}
.topo a, .topo span, .topo summary, .topo button { color: var(--ink-2); text-decoration: none; }
.topo-produto { font-weight: var(--peso-forte); flex: none; white-space: nowrap; }

/* #60, item 1 -- a empresa ativa.
   Antes: `.topo-empresa`, peso 600, cor de item de menu, e o `Trocar` no
   extremo oposto da barra. Numa tela multi-empresa isso deixa "em qual
   empresa estou" com o mesmo destaque de "Relatorios", e lancar na empresa
   errada e erro silencioso -- as duas empresas tem contas de nome parecido.
   Agora: pastilha propria (o unico fundo claro do lado esquerdo da barra),
   nome em 640 -- o peso do heroi (#57-E1) -- e o controle de troca DENTRO da
   pastilha, ao lado do nome que ele troca. Medido no Chromium: o nome computa
   640 contra 400 dos itens de menu (o link antigo computava 600), porque o que
   distingue tem de pesar mais que o que nao distingue.
   #163 -- O NUMERO ANTIGO EXPIROU NO #145, E A COR JUNTO COM ELE.
   Estava escrito aqui: "o branco sobre a pastilha composta (rgba .12 sobre
   #0f1a2b = #2c3544) da 12,29:1". Era verdade enquanto a barra era ESCURA. O
   #145 tornou a barra `var(--surface)`, e rgba(255,255,255,.12) sobre branco
   COMPOE BRANCO: a pastilha media 1,00:1 contra a propria barra, ou seja,
   deixou de existir visualmente. Numa tela multi-empresa ela e o sinal de
   qual empresa esta aberta -- o mesmo erro silencioso que o comentario acima
   descreve.
   Agora a pastilha ESCURECE a barra clara, que e a unica direcao que funciona
   sobre fundo claro. `--line-2` no repouso, `--line` no realce, mantendo a
   progressao de dois niveis do paragrafo abaixo. Guarda:
   tests/test_contraste_163.py. */
.empresa-ativa {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  flex: none;
  padding: 3px 3px 3px var(--esp-10);
  border-radius: var(--raio);
  background: var(--line-2);
}
.empresa-ativa-nome { font-weight: 640; white-space: nowrap; }
/* Menor que um item de menu: dentro da pastilha o `Trocar` e acao secundaria
   do nome, nao mais um item de primeiro nivel competindo com o menu. O realce
   de hover sobe de .12 para .18 porque .12 sobre .12 nao se ve.
   #163: a INTENCAO desse paragrafo continua valendo -- o realce precisa ser
   mais forte que o repouso. O que mudou e a direcao: sobre a barra clara do
   #145, "mais forte" e mais ESCURO, entao `--line` (repouso e `--line-2`).
   As duas rgba brancas anteriores davam 1,00:1 sobre a barra: hover E foco de
   teclado do `Trocar` eram invisiveis. */
.empresa-ativa .tem-submenu > summary { padding: 5px var(--esp-8); font-size: var(--corpo-nota); }
.empresa-ativa .tem-submenu:hover > summary,
.empresa-ativa .tem-submenu[open] > summary { background: var(--line); }

/* Faixa da empresa ativa: 3px no topo absoluto da pagina. Cor por empresa
   (core/models/organizacao.py explica por que por id e nao por nome). E
   REFORCO -- o nome em texto e que carrega a informacao --, entao nao ha
   requisito de contraste de texto aqui; ainda assim as seis passam de 3:1
   sobre o fundo da pagina. */
.faixa-empresa { height: 3px; }
.faixa-empresa-0 { background: var(--empresa-0); }
.faixa-empresa-1 { background: var(--empresa-1); }
.faixa-empresa-2 { background: var(--empresa-2); }
.faixa-empresa-3 { background: var(--empresa-3); }
.faixa-empresa-4 { background: var(--empresa-4); }
.faixa-empresa-5 { background: var(--empresa-5); }

/* #289: `.visualmente-oculto` saiu -- era o mesmo que `.oculto-visual` (18 usos), com outro nome. */
.topo-menu { display: flex; gap: var(--esp-4); list-style: none; margin: 0; padding: 0; flex: none; }
.topo-menu > li > a, .tem-submenu > summary {
  display: block; padding: var(--esp-8) var(--esp-12); border-radius: var(--raio); cursor: pointer; white-space: nowrap;
}
/* #287: o gatilho do submenu é um <summary> -- sem o marcador nativo, e com o
   mesmo anel de foco dos links da barra. */
.tem-submenu > summary { list-style: none; }
.tem-submenu > summary::-webkit-details-marker { display: none; }
/* Realce do cromo por CLAREZA, nao por outra cor: sobre a barra de tinta,
   um branco a 12% marca o item sem introduzir um segundo azul competindo
   com o azul de acao. */
/* #145: sobre fundo claro, o realce por clareza vira realce por SOMBRA --
   branco a 12% sobre branco é invisível. */
.topo-menu > li > a:hover, .tem-submenu > summary:hover, .tem-submenu[open] > summary { background: var(--line-2); }
/* O ITEM ATIVO, que não existia: azul com sublinhado de 2px, como na
   referência. `aria-current="page"` é o seletor DE PROPÓSITO -- é o atributo
   que um leitor de tela anuncia, então marcar por ele faz a mesma marcação
   servir aos dois. Marcar por classe deixaria o leitor de tela sem nada. */
.topo-menu a[aria-current="page"] {
  color: var(--azul); font-weight: var(--peso-forte);
  box-shadow: inset 0 -2px 0 var(--azul);
  border-radius: var(--raio) var(--raio) 0 0;
}
.topo-direita { margin-left: auto; display: flex; align-items: center; gap: var(--esp-8); flex: none; }

.tem-submenu { position: relative; }
.submenu {
  display: none; position: absolute; top: 100%; left: 0; z-index: 10;
  min-width: 200px; margin: 0; padding: var(--esp-4); list-style: none;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--raio); box-shadow: var(--sombra-suspensa);
}
/* #287: abre por clique/Enter (`open` do <details>), não por hover -- é o que
   funciona no toque. O ui.js fecha ao clicar fora e no Esc (MENUS_FLUTUANTES). */
.tem-submenu[open] .submenu { display: block; }
.submenu a { display: block; padding: var(--esp-8); color: var(--ink); border-radius: var(--raio-miudo); }
.submenu a:hover { background: var(--azul-fraco); }
/* O submenu de "Trocar" fica no extremo direito da barra (`.topo-direita`
   tem `margin-left: auto`). `left: 0` (o padrao de `.submenu`, pensado para
   "Cadastros", perto da esquerda) faz este dropdown de 200px de largura
   comecar na borda esquerda do proprio gatilho e continuar para a direita --
   passando da borda da janela e ficando com pontos fora do viewport
   (`elementFromPoint` devolve `null` ali, achado da revisao final: o mouse
   real nao alcanca coordenada nenhuma fora da tela). Ancorar pela direita
   (`right: 0`) mantem o dropdown inteiro dentro da largura visivel. */
.topo-direita .submenu { left: auto; right: 0; }

.ocultar-valores { background: transparent; border: 0; cursor: pointer; font-size: 16px; padding: var(--esp-4) var(--esp-8); position: relative; display: inline-flex; align-items: center; }
/* #288: o ícone SVG da barra (lupa, olho) alinha pela linha de base do texto. */
.gatilho-busca .icone, .ocultar-valores .icone { display: block; flex: none; }
.gatilho-busca { display: inline-flex; align-items: center; gap: var(--esp-6); }
.ocultar-valores:hover { background: var(--line-2); border-radius: var(--raio); }
/* #60, item 4: estado LIGADO do "ocultar valores". A barra diagonal e
   desenhada em CSS, nao trocando o emoji: glifo depende da fonte instalada
   (num contêiner sem fonte de emoji o proprio olho ja sai como quadrado
   vazio), e um estado que some junto com a fonte nao e estado. O fundo
   aceso repete a informacao sem depender de cor sozinha.
   #163 -- E ESSA REDUNDANCIA TINHA PARADO DE EXISTIR. Fundo aceso
   (rgba branco .18) e diagonal (#fff) eram os DOIS brancos, sobre a barra que
   o #145 tornou branca: 1,00:1 cada. O estado ligado nao tinha sinal visual
   nenhum -- so o emoji e o `aria-pressed` --, que e exatamente o defeito que
   este item existiu para corrigir. Agora usa o vocabulario de LIGADO do
   sistema (`--azul-fraco` + `--azul`), o mesmo de `.segmentado
   input:checked` e do item de menu com `aria-current`; a diagonal da 4,75:1
   sobre o fundo aceso. Guarda: tests/test_contraste_163.py. */
.ocultar-valores.ativo { background: var(--azul-fraco); border-radius: var(--raio); }
.ocultar-valores.ativo::after {
  content: "";
  position: absolute;
  left: 6px; right: 6px; top: 50%;
  height: 2px;
  background: var(--azul);  /* #163: era #fff, invisivel sobre a barra clara */
  transform: rotate(-20deg);
  pointer-events: none;
}

/* Coluna central: sem um teto de largura, numa tela de 1600px a linha de
   leitura e a grade do dashboard se esticam ate perder ritmo. A tabela de
   lancamentos e larga por natureza, mas nao precisa furar esta coluna: ela ja
   rola dentro do proprio quadro (`.rolagem-horizontal`), que e o que a mantem
   utilizavel sem quebrar o ritmo da pagina. */
/* #78 tinha erguido este teto para 1800px, com o argumento de que 640px de
   tela vazia em 1920 eram desperdicio. O #79 reverte para 1280: o argumento
   media errado, e a largura de 1800 produzia o erro mais caro num sistema
   financeiro -- uma linha tao larga que o olho atravessa a tela e le o valor
   da linha errada (o dono comparou com o Controlle; a leitura dele e a
   certa). A largura da TELA e a decisao; a largura das COLUNAS e a
   consequencia -- e quem resolve coluna larga e teto por coluna
   (`.gruda-desc`, `.col-categoria`, `.col-contato`, `.col-conta`, em
   componentes.css), nao um `main` mais largo.

   O DEFEITO DE MEDICAO do #78, encontrado no #79: a comparacao "cabe/nao
   cabe" usava `main.clientWidth`, que INCLUI os 16px de padding de cada
   lado. Os 640px "vazios" de 1920 nunca existiram como espaco util -- 32px
   deles eram o proprio padding sendo contado duas vezes. O criterio certo:

     const s = getComputedStyle(main);
     const util = main.clientWidth - parseFloat(s.paddingLeft) - parseFloat(s.paddingRight);
     const transborda = tabela.scrollWidth > util + 1;

   Com esse criterio, NENHUM teto de `main` faz o DRE caber: a tabela mede
   1357px e exige util >= 1357 (container >= 1389px) -- mas o notebook de
   1366px do dono e o proprio VIEWPORT, entao mesmo um teto de 1800px nao
   ajuda ali (o container nunca passa de 1366, util 1334, ainda menor que
   1357). Alargar o `main` das outras onze telas so para uma que continua
   sem caber onde mais importa era otimizar para a excecao. O DRE resolve
   como a Analise ja resolve desde o #71: rola dentro do proprio quadro
   (ver `.rolagem-horizontal:has(...)`, abaixo) -- nao empurra a pagina.

   `:has(.tabela)` e nao `:has(table)`: o Inicio tem `<table>` mas nao a
   classe (medido) -- e la o conteudo mede 1168px, entao esticar so
   espalharia os cartoes do painel. `:has()` em vez de uma classe por
   template: assim nao ha template para editar, nem risco de uma tela nova
   nascer com o teto errado por esquecimento -- quem manda e o CONTEUDO.
   O projeto ja usa `:has()` em varios lugares.

   O `:has(.tabela)` que existia aqui (#78) sumiu de proposito: ele so fazia
   sentido enquanto valia um numero DIFERENTE do `main` base. Com os dois
   iguais (1280px), manter a regra seria CSS morto -- se um teto por
   conteudo voltar a fazer sentido um dia, escreva-o com o numero medido
   daquela vez, nao ressuscite este. */
main { max-width: 1280px; margin: 0 auto; padding: var(--esp-16); }

/* `flex-wrap: wrap` nao e enfeite: sem ele, numa tela de 390px o titulo mais
   o navegador de mes somam mais que os 358px uteis e a PAGINA INTEIRA passa a
   rolar para o lado (medido: 398 contra 390). Com a quebra, o periodo desce
   para a propria linha e continua centrado. */
.cabecalho { display: flex; flex-wrap: wrap; align-items: center; gap: var(--esp-8) var(--esp-16); margin-bottom: var(--esp-16); }
/* #169 -- `templates/conciliacao/resultado.html:6` poe o <h1> FORA do
   `.cabecalho`, entao `.cabecalho h1` sozinho nao o alcancava e ele saia no 2em
   padrao do navegador (32px): o unico titulo do sistema maior que 24px.
   `.titulo-pagina` entra no MESMO seletor em vez de ganhar um bloco proprio --
   copiar o `24px` para um segundo lugar faria a divida de tipografia literal
   crescer (`tests/test_tipografia_166.py`, teto 70) para pintar o mesmo
   tamanho duas vezes. O `margin: 0` continua servindo: o que vem depois na
   tela e um <p>, que traz a propria margem de cima.
   #288: FEITO -- o <h1> entrou no `{% block cabecalho %}` e `.titulo-pagina`
   saiu do seletor (e do template). O parágrafo abaixo é o registro do que era:
   O conserto de RAIZ nao e este: e o <h1> entrar no `{% block cabecalho %}` do
   `base.html`, como em toda outra tela -- hoje `resultado.html` renderiza dois
   <h1>, um vazio no cabecalho e este no conteudo. Isso mexe na estrutura do
   template e na disposicao da tela, e ficou de fora desta rodada. */
.cabecalho h1 { font-size: 24px; margin: 0; }
/* #275: na lista o <h1> fica só para o leitor de tela (o menu do topo já diz
   onde a pessoa está). `display: contents` tira a caixa dele do flex sem
   tirá-lo da árvore de acessibilidade -- o span de dentro continua sendo o
   nome da página. Sem isto, o h1 "vazio" ainda ocupava um gap de 12px. */
.cabecalho h1:has(> .oculto-visual) { display: contents; }
/* #275: o período e a nota do eixo (#212) numa linha só, no cabeçalho. */
.periodo-com-eixo { display: flex; align-items: center; gap: var(--esp-10); flex-wrap: wrap; }
.cabecalho .nota-do-eixo { margin: 0; white-space: nowrap; }
.cabecalho-esquerda { display: flex; align-items: center; gap: var(--esp-12); }
/* `flex: 1` no centro mantem o periodo no MEIO da linha mesmo quando o titulo
   da esquerda e mais largo que as acoes da direita. */
.cabecalho-centro { flex: 1; display: flex; justify-content: center; }
.cabecalho-direita { display: flex; align-items: center; gap: var(--esp-8); margin-left: auto; }
/* #278 (dono, com a foto: "o campo seleção de data não ficou centralizado"):
   com `flex: 1` o centro se centralizava no ESPAÇO QUE SOBRA entre as
   laterais -- a densidade à esquerda (#277) e o lado direito vazio -- e o mês
   ficava deslocado para a direita (medido: 1047px numa página cujo centro é
   933). Numa grade `1fr auto 1fr` as duas laterais têm a MESMA largura, e o
   centro é o centro da página, seja o que for que haja nas pontas. Só acima
   de 900px: abaixo disso o cabeçalho continua flex com quebra de linha
   (`flex-wrap`), que é o que o mantém inteiro em 360px (prova 104). */
@media (min-width: 901px) {
  .cabecalho { display: grid; grid-template-columns: 1fr auto 1fr; }
  .cabecalho-centro { flex: initial; justify-self: center; }
  .cabecalho-direita { margin-left: 0; justify-self: end; }
}

/* A tabela e larga por natureza (seis colunas de dado financeiro). Sem este
   contorno, numa tela de 390px a PAGINA INTEIRA rolava para o lado: medido,
   scrollWidth 994 contra clientWidth 390. Agora quem rola e a tabela, dentro
   do proprio quadro, e o resto da tela fica no lugar. O `min-width` e o que
   faz o contorno servir para alguma coisa: sem ele a tabela se espremeria ate
   virar uma coluna de letras soltas em vez de rolar. */
/* O `overflow-x: auto` vive dentro de uma media query, e nao solto, porque um
   eixo com overflow diferente de `visible` empurra o OUTRO eixo para fora de
   `visible` tambem (mesma regra que ja mordeu os submenus da barra). Isso
   transforma este quadro num container de rolagem, e o `position: sticky` do
   cabecalho de dia passa a se ancorar NELE em vez de na pagina -- medido: ao
   rolar 400px o cabecalho ia para -12, ou seja, nao grudava.
   Acima de 900px a tabela cabe na coluna central e nao precisa do quadro;
   abaixo, precisa, e ali o sticky perde o efeito -- troca consciente, porque
   numa tela estreita a lista nao e o gesto principal. */
.rolagem-horizontal > .tabela { min-width: 520px; }
@media (max-width: 900px) {
  .rolagem-horizontal { overflow-x: auto; }
}

/* Notebook de 13" (#70, Tarefa 10): com "Mostrar variação mês a mês (AH)"
   ligado, a tabela cruzada da Análise ganha 12 colunas extras (.cruzada-ah)
   e ultrapassa 1280px -- medido: scrollWidth 1684 contra clientWidth 1280
   em 1280x800, no estado default os dois dão 1280. É pré-existente à rodada
   inteira (o checkbox e as colunas .cruzada-ah já existiam antes da
   Tarefa 1); só ficou visível porque a medição do Passo 1 mede a URL nua, e
   ninguém tinha ligado o controle e medido antes.
   Não dá para simplesmente tirar `overflow-x: auto` da media query acima
   para todo `.rolagem-horizontal`: ela também envolve a lista de
   Lançamentos, cujo cabeçalho de dia (`.linha-dia > th`) e colunas
   congeladas (`.gruda-*`) dependem do quadro NÃO ser um contexto de
   rolagem acima de 900px (ver o comentário logo acima). Medido (Tarefa 10,
   nível 1: Chromium contra o servidor real): tirar a media query faz
   `overflow-y` computar `auto` também (regra do CSS -- um eixo non-visible
   arrasta o outro), o que muda o ancestral de rolagem do `position:
   sticky` do cabeçalho de "a página" para o próprio quadro, e o cabeçalho
   PARA de grudar -- medido em `getBoundingClientRect()` a vários scrolls:
   topo vai a -341px/-741px (some da tela) em vez de grudar em 0. A
   asserção "gruda ao rolar" de `verificar_navegador.py` NÃO pega essa
   quebra (ela só testa scroll=400, onde o topo ainda dá positivo) -- quem
   prova é a medição direta acima, não aquele script; ver
   docs/medicoes/interface-70.txt. A tabela cruzada não tem nem cabeçalho
   de dia nem `.gruda-*`, então o `:has()` abre a exceção só para ela: DRE,
   Lançamentos e Cadastros medem `overflow-x: visible` (inalterado) com
   esta regra presente -- o seletor não casa neles, então "antes" e
   "depois" são o mesmo estado por construção (medido e registrado em
   docs/medicoes/interface-70.txt).

   #79: `.tabela-dre` entra na MESMA exceção, pelo MESMO motivo -- ela
   também não tem cabeçalho de dia nem `.gruda-*` (é uma grade de mês x
   linha), então nada do argumento acima muda ao somar seu seletor.
   ⚠️ #98: "sem sticky nenhum" era verdade quando esta frase foi escrita e
   DEIXOU DE SER — o DRE agora gruda rótulo, TOTAL e AV (ver "TRÊS ÂNCORAS
   GRUDADAS", adiante). O argumento acima não muda por isso: o que aquele
   texto protege é o sticky VERTICAL do cabeçalho de dia de Lançamentos, que
   `overflow-x: auto` quebraria; o do DRE é HORIZONTAL e nasce DENTRO deste
   mesmo quadro rolável -- ele existe por causa desta regra, não apesar
   dela. O motivo de precisar da exceção agora e não antes: o `main`
   voltou a ter 1280px (ver o comentário de `main:has(.tabela)`, acima), e
   nessa largura a tabela do DRE (1357px medidos, doze meses + total + AV,
   nenhuma coluna truncável) sempre transborda a caixa útil -- ela rola
   dentro do próprio quadro em vez de empurrar a página, exatamente como a
   Análise já fazia. Lançamentos e Cadastros continuam de fora: Lançamentos
   tem o cabeçalho de dia sticky que esta regra quebraria (medido acima), e
   por isso cabe por teto de COLUNA (`.celula-descricao`/`.celula-categoria`/
   `.col-conta`), não por rolagem do quadro. */
.rolagem-horizontal:has(.tabela-cruzada, .tabela-dre) { overflow-x: auto; }

/* Sem `overflow: hidden` aqui. Ele existia so para recortar os cantos
   arredondados, mas `overflow` diferente de `visible` faz do elemento um
   contexto de rolagem -- e o `position: sticky` do cabecalho de dia passava a
   se ancorar NA TABELA, que nao rola, em vez de na pagina. Medido: rolando
   400px o cabecalho ia para -12.
   O arredondamento nao se perde: fundo de elemento ja e recortado pelo
   `border-radius` sem precisar de overflow nenhum. */
/* `width` e `border-collapse` saíram (medido via CDP, #70): componentes.css
   define os dois na MESMA especificidade e carrega depois -- nunca aplicavam.
   `background`, `border-radius` e `box-shadow` continuam aqui porque
   componentes.css não os declara em `.tabela`: são a ÚNICA fonte do aspecto
   de cartão das tabelas legadas (DRE, Lançamentos), e apagá-los tirava a
   moldura de todas elas. */
.tabela { background: var(--surface); border-radius: var(--raio); box-shadow: var(--sombra); }
/* Cabecalho de coluna como rotulo, do mesmo vocabulario das sobrancelhas
   dos blocos: e nomenclatura, nao conteudo.
   `text-align`, `font-size`, `font-weight`, `color`, `padding` e
   `border-bottom` saíram (medido via CDP, #70): componentes.css redeclara
   todos com a mesma especificidade e carrega depois. `letter-spacing` e
   `text-transform` ficam -- são a ÚNICA fonte do rótulo em versalete
   rastreado; sem eles o cabeçalho das tabelas legadas vira texto comum. */
.tabela th { letter-spacing: .07em; text-transform: uppercase; }
/* O realce de hover saiu (medido via CDP + `:hover` real no navegador, #70):
   `.tabela tbody tr:hover th, .tabela tbody tr:hover td` de componentes.css
   tem a MESMA especificidade (0,2,3) e carrega depois -- o #f6f8fc daqui
   nunca aparecia; quem sempre vencia era o #fafaf8 de componentes.css. */
.direita { text-align: right; font-variant-numeric: tabular-nums; }
/* `.negativo` VIVE EM componentes.css DESDE O #98 (`var(--vermelho)`, um token
   só para valor negativo em toda tela). Esta linha ficou aqui, apagada, porque
   apagá-la em silêncio faria alguém reescrevê-la: era ELA, com `var(--erro)`
   (#b3261e), contra os três lugares que já usavam `--vermelho` (#c0392f), que
   produzia o mesmo -453.497,05 em duas cores em duas telas. Não ressuscitar. */

.positivo { color: var(--sucesso); }
/* #169: `.cat-vazio` (`templates/categorias/tela.html:55`) e mesma função que
   `.vazio` -- aba de categorias sem nenhum no --, so nao tinha regra nenhuma e
   saia como texto corrido. Entra no SELETOR em vez de ganhar copia das mesmas
   tres declaracoes: mesma funcao, mesmo componente (diretriz #77, item 6). */
.vazio, .cat-vazio { color: var(--ink-3); text-align: center; padding: var(--esp-24); }

/* Rotulo so para leitor de tela: a coluna de tipo e um ponto colorido, e
   uma coluna sem nome nenhum deixa quem usa leitor de tela sem referencia. */
/* Sem `position: absolute`, de proposito. A receita classica de "so para
   leitor de tela" usa absolute, e dentro de uma TABELA QUE ROLA isso e uma
   armadilha: sem ancestral posicionado, o bloco contenedor do span vira a
   PAGINA, ele escapa do recorte do quadro de rolagem e vai parar na posicao
   estatica dele -- a 500px, na tabela rolada. Resultado medido: a pagina
   inteira passava a rolar 114px para o lado numa tela de 390px, com todos
   os elementos visiveis dentro dos 390.
   Em fluxo, ocupando 1px e recortado, ele nao escapa de nada e continua
   invisivel e legivel por leitor de tela. */
.oculto-visual {
  display: inline-block; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* Cabecalho clicavel: o `<a>` ocupa a celula inteira para o alvo do mouse
   ser a coluna, e nao so as letras. */
.col-ordenavel > a { display: block; color: inherit; text-decoration: none; }
.col-ordenavel > a:hover { color: var(--azul); }
.col-ativa > a { color: var(--ink); }
.seta-ordem { margin-left: var(--esp-4); font-size: var(--corpo-micro); } /* #289: era 8px, o menor glifo do sistema */

.celula-tipo { width: 1%; padding-right: 0; }

/* Select que so parece select quando se chega nele. Numa lista de 50 linhas,
   50 caixas com borda e seta viram uma parede de controles e escondem o
   dado; a borda aparece no hover e no foco, quando a intencao de editar
   existe. */
.categoria-na-linha {
  border-color: transparent; background: transparent; height: 26px;
  padding: 0 var(--esp-4); max-width: 100%; color: inherit;
  appearance: none; -webkit-appearance: none;
}
.categoria-na-linha:hover, .categoria-na-linha:focus {
  border-color: var(--line); background: var(--surface);
}
.ponto-tipo { display: inline-block; width: 8px; height: 8px; border-radius: 50%; }
.ponto-entrada { background: var(--sucesso); }
.ponto-saida { background: var(--erro); }
/* #257: a terceira cor da bolinha. `--azul` é o MESMO token do valor da
   transferência (#236) e do seletor da conciliação (#249) -- três lugares
   que dizem a mesma coisa, com a mesma tinta. Elemento gráfico exige 3:1
   e este mede 5,17:1 sobre `--surface`. */
.ponto-transferencia { background: var(--azul); }

/* Marca de parcelado/recorrente: diz que a linha tem irmas. Sem ela, uma
   parcela parece um gasto avulso e a leitura do mes engana. */
.marca-repete { color: var(--ink-3); font-size: var(--corpo-nota); margin-left: var(--esp-6); white-space: nowrap; }
.marca-repete .parcela { font-size: var(--corpo-micro); margin-left: var(--esp-2); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------- extrato -- */
/* O cabecalho do dia GRUDA no topo enquanto se rola: numa lista longa,
   perder de vista em que dia se esta e o que faz a pessoa rolar de volta.
   `position: sticky` num `<tr>` nao funciona em todos os navegadores; quem
   gruda e a celula. */
/* #99: o `top` é ZERO no CSS e passa a ser ESCRITO pelo ui.js quando o dia
   está acabando (empurrão) -- ver "empurrão do cabeçalho de dia" lá. Sem JS
   o comportamento é o de antes do #99: gruda e não é empurrado. */
/* #100: o `top` deixou de ser 0 — agora é a BANDA do cabeçalho da tabela, que
   passou a grudar (`.tabela thead th`, componentes.css). Sem isso os dois
   grudariam no mesmo lugar e o de dia sumiria atrás do da tabela.
   O padrão é `--altura-linha` porque é a altura que `.tabela th` declara: sem
   JavaScript o comportamento já fica certo. O `ui.js` refina com a altura
   MEDIDA do `<thead>` (que difere quando o cabeçalho quebra linha) e é ele
   quem escreve o `top` inline no empurrão. */
/* #105: o fundo e as bordas SAÍRAM daqui. Estavam escritos (`#f2f5fa` e
   `var(--line)`) e nunca chegaram à tela: `.tabela th` (componentes.css)
   empata em especificidade e vence por vir depois na cascata do #70 — a faixa
   de dia saía branca, igual às linhas de lançamento, que é o defeito que o
   dono reportou. Reescrevê-los aqui não adiantaria; quem pinta agora é
   `.tabela .linha-dia > .dia-fundido`, em componentes.css, que ganha por
   especificidade. Não devolver cor a este seletor: ela seria descartada de
   novo, e em silêncio. */
/* #168: aqui estava `var(--banda-cabecalho, var(--altura-linha))`, e
   `--banda-cabecalho` NUNCA EXISTIU -- nao em tokens.css, nao em app.css, nao
   em componentes.css, e nenhum JS a define por setProperty (procurado nos
   tres arquivos e em static/js/). O fallback era, desde sempre, o valor real.
   Isso e o terceiro irmao do defeito desta rodada, e o unico dos tres achado
   por guarda em vez de leitura: um token perdedor (--raio), um token fora de
   casa (as 72 cores) e um token FANTASMA, que nao chegou a nascer.
   O fallback sumiu junto: enquanto ele estava ali, o dia em que alguem
   criasse `--banda-cabecalho` mudaria esta tela sem que ninguem tivesse
   pedido -- e o `var()` sem fallback quebra visivel, enquanto com fallback
   mente (a licao do #164). */
.linha-dia > th {
  position: sticky; top: var(--altura-linha); z-index: 2;
  padding: var(--esp-8); font-weight: var(--peso-forte); text-align: left;
}
.dia-data { color: var(--ink); font-size: var(--corpo-nota); letter-spacing: 0; text-transform: none; }
.dia-semana { color: var(--ink-3); font-weight: var(--peso-normal); margin-left: var(--esp-6); }
.dia-contagem { color: var(--ink-3); font-weight: var(--peso-normal); margin-left: var(--esp-12); font-size: var(--corpo-mini); }
.dia-rotulo {
  font-size: var(--corpo-micro); font-weight: var(--peso-medio); letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-3); margin-right: var(--esp-8);
}

/* Rodape do dia: os dois saldos. Fundo de papel, nao de superficie, para o
   olho ler como "fim de bloco" e nao como mais um lancamento. */
.linha-saldo > td { background: var(--saldo-fundo); border-bottom: 2px solid var(--line); padding: var(--esp-8); height: auto; }
.saldo-par { display: inline-flex; align-items: baseline; margin-left: var(--esp-24); }
/* #281: a coluna Data do modo lista (curta, dd/mm) e o pé de saldos. O saldo
   final é o número que se procura no rodapé: peso do total do dia (#87). */
.celula-data { white-space: nowrap; color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* #282 (dono: "a lista de saldos deve ser sobreposta"): a régua de saldos gruda
   no PÉ DA JANELA enquanto a tabela rola e assenta no fluxo quando a lista
   acaba -- `sticky`, não `fixed`, para não cobrir a legenda nem o fim da
   página. Quatro células iguais separadas por fio (a mesma grade do Controlle,
   que o dono usa há anos); o Saldo é o número que se procura e leva o peso.
   `z-index: 3` fica ABAIXO da barra de lote (4); com linhas marcadas a barra
   toma o pé e esta sobe a altura dela (`--altura-barra-de-lote`). */
.rodape-de-saldos {
  position: sticky; bottom: 0; z-index: 3;
  display: grid; grid-template-columns: repeat(4, 1fr);
  margin-top: var(--esp-8); padding: var(--esp-8) 0;
  background: var(--surface); border-top: 1px solid var(--line);
  box-shadow: var(--sombra-regua);
}
.saldo-celula {
  display: flex; align-items: baseline; justify-content: center; gap: var(--esp-8);
  padding: 0 var(--esp-12); font-variant-numeric: tabular-nums;
}
.saldo-celula + .saldo-celula { border-left: 1px solid var(--line); }
.saldo-celula .dia-rotulo { margin-right: 0; }
.rodape-de-saldos .saldo-final { font-weight: var(--peso-forte); font-size: var(--corpo); }
/* #298: ESTE NÚMERO NÃO MANDA -- é o retrato, não a régua. O valor vivo é
   MEDIDO no navegador pelo `lista-41.js`, que observa a `.barra-de-lote` e
   escreve a altura real desta variável no `<html>`. O declarado aqui vale só
   para o caminho SEM JavaScript, e por isso carrega a medição de HOJE
   (09/09/2026, 1366×768: a barra ocupa 700,5 -> 768, altura 67,5px).
   O 61px que estava aqui era a medição do #282 e ENVELHECEU quando o
   #289/#290 mexeram na altura dos botões: sobrou 6,5px de sobreposição, com a
   barra (`z-index: 4`) por cima da borda inferior da régua. Trocar um número
   mágico por outro só adiaria o mesmo defeito -- daí a medição. */
:root { --altura-barra-de-lote: 67.5px; }
.acao-lote:has(input[name="selecionados"]:checked) .rodape-de-saldos { bottom: var(--altura-barra-de-lote); }
@media (max-width: 900px) { .rodape-de-saldos { grid-template-columns: repeat(2, 1fr); row-gap: var(--esp-6); } }
@media print { .rodape-de-saldos { position: static; box-shadow: none; } }
.saldo-realizado { color: var(--azul); }

/* Linha vencida: faixa ambar na linha inteira, nao so na etiqueta. O que
   esta atrasado precisa ser visto ao varrer a lista, sem ler a coluna de
   situacao. Ambar, e nao vermelho, porque vermelho ja e "dinheiro que sai" e
   metade das linhas vencidas sao despesas. */
.linha-vencida > td { background: var(--vencido-fundo); }
.tabela tbody tr.linha-vencida:hover td { background: var(--vencido-fundo-forte); }

.resumo { display: flex; flex-wrap: wrap; gap: var(--esp-16); margin-bottom: var(--esp-8); color: var(--ink-3); align-items: center; }
.exportar-csv { margin-left: auto; font-size: var(--corpo-nota); color: var(--azul); text-decoration: none; }
.exportar-csv:hover { text-decoration: underline; }
/* #313b: o Excluir da linha (lista e cartao) mora dentro do `form.acao-lote` e
   casava esta regra por ser submit. Virou `type="button"` (a exclusao falha
   fechada) -- `[data-confirma-exclusao]` guarda a MESMA margem, medida igual
   ao master na tela e na impressao. */
.acao-lote button[type="submit"],
.acao-lote button[data-confirma-exclusao] { margin-bottom: var(--esp-8); }
.tabela th:first-child, .tabela td:first-child { width: 1%; padding-right: 0; }
.navegador-de-mes { display: flex; align-items: center; gap: var(--esp-12); }
.navegador-de-mes .seta {
  display: flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border-radius: var(--raio-miudo);
  color: var(--azul); text-decoration: none; font-size: 18px; line-height: 1;
}
.navegador-de-mes .seta:hover { background: var(--azul-fraco); }
/* #182 — ALVO DE CLIQUE, nao so texto. O `<summary>` nao tinha padding nenhum,
   entao a altura do alvo era a propria linha: 22,5px medidos contra os 24 do
   WCAG 2.5.8 (achado da `prova_interface_104` no #181). `min-height` mais o
   grid de centro dao os 24 sem mexer no tamanho da fonte -- e valem para as
   QUATRO telas que usam `componentes/seletor-de-periodo.html`. */
.navegador-de-mes .mes-atual {
  font-weight: var(--peso-forte); min-width: 140px; text-align: center;
  min-height: 24px; display: grid; place-items: center;
}

/* Faixa de alerta: ambar, nao vermelho. Vermelho ja significa "dinheiro que
   sai" em toda a interface; usa-lo tambem para aviso faria a faixa competir
   com os proprios valores que ela esta apontando. */
.alerta-faixa {
  display: flex; align-items: center; gap: var(--esp-12); flex-wrap: wrap;
  margin-bottom: var(--esp-12); padding: var(--esp-12) var(--esp-16);
  background: var(--alerta-fundo); border: 1px solid var(--alerta-borda); border-radius: var(--raio);
}
.alerta-icone {
  flex: none; width: 20px; height: 20px; display: grid; place-items: center;
  border-radius: 50%; background: var(--atencao); color: var(--branco);
  font-size: var(--corpo-nota); font-weight: var(--peso-maximo);
}
.alerta-faixa .valor { color: var(--atencao); }
.alerta-acao {
  margin-left: auto; padding: 0 var(--esp-14); height: 28px; line-height: 28px;
  border-radius: var(--raio); background: var(--atencao); color: var(--branco);
  font-size: var(--corpo-nota); text-decoration: none; white-space: nowrap;
}
.alerta-acao:hover { background: var(--atencao-escuro); }

.filtros { margin-bottom: var(--esp-8); }
.filtros > summary {
  display: inline-block; cursor: pointer; list-style: none;
  padding: 0 var(--esp-16); height: var(--linha); line-height: var(--linha);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--raio); color: var(--azul); font-size: var(--corpo-nota);
}
.filtros > summary::-webkit-details-marker { display: none; }
.filtros > summary:hover { background: var(--azul-fraco); }
.filtros[open] > summary { margin-bottom: var(--esp-8); }

.painel-filtros { display: flex; flex-wrap: wrap; gap: var(--esp-12); align-items: end; margin-bottom: var(--esp-8); background: var(--surface); padding: var(--esp-12) var(--esp-16); border-radius: var(--raio); box-shadow: var(--sombra); }
/* #98/B8b: dentro da barra da lista o painel perde a moldura própria (a barra
   já é o cartão) e, ABERTO, toma a linha inteira em vez de esticar uma célula
   no meio da barra. `order: 9` o joga para o fim da linha flex, então ele
   quebra para baixo de tudo — sem isso o painel aberto empurraria os totais e
   as ações para uma terceira linha. */
.barra-da-lista .filtros { margin-bottom: 0; }
/* #185, relato do dono: "ao clicar em Filtrar o botão pula uma linha, gerando
   um grande espaçamento". MEDIDO na foto local, viewport 1366: fechado o botão
   ficava em (325, 451), entre o Localizar e as ações; aberto ia para (369, 73)
   — 44px abaixo e 378px à esquerda. Ele sumia de onde a pessoa acabou de
   clicar, e a barra ia de 57px para 173px de altura.
   A CAUSA não era a intenção do #98/B8b (que segue valendo: aberto, o painel
   toma a linha inteira) — era ela ser aplicada ao `<details>` INTEIRO, que
   carrega o `<summary>` junto. `display: contents` faz o `<details>` deixar de
   gerar caixa: o summary e o painel viram itens flex diretos da barra, o botão
   fica onde sempre esteve, e só o PAINEL recebe a linha cheia. O `open` do
   details continua mandando na exibição do painel, como antes. */
.barra-da-lista .filtros[open] > summary { margin-bottom: 0; }
.barra-da-lista .painel-filtros { display: none; }
.barra-da-lista .filtros[open] ~ .painel-filtros { display: flex; flex: 0 0 100%; order: 9; }
.barra-da-lista .painel-filtros {
  background: none; box-shadow: none; padding: var(--esp-10) 0 0; margin-bottom: 0;
}
/* #280: base de 120px (era 160) para os oito campos caberem numa linha só em
   1366px -- medido no mock sobre a tela real: painel 130 -> 120px, e a
   primeira linha de dado sobe 50px. */
.painel-filtros label { display: flex; flex-direction: column; gap: var(--esp-4); flex: 1 1 120px; min-width: 0; }
.painel-filtros input, .painel-filtros select { min-width: 0; }
/* #280, desenho do dono: o rodapé do painel toma a linha inteira -- Filtrar
   GRANDE e Limpar à esquerda (primário à esquerda, secundário à direita, como
   todo `.acoes-do-formulario`), Salvar filtro à direita. A altura é explícita
   nos DOIS porque `button` e `a.btn` não herdam a mesma (#192): o `<a>` saía
   7px mais alto ao lado do botão. */
.rodape-do-painel { display: flex; flex: 0 0 100%; align-items: center; justify-content: space-between; gap: var(--esp-12); }
.acoes-do-painel { display: flex; align-items: center; gap: var(--esp-8); }
.acoes-do-painel .btn { height: 36px; margin: 0; padding: 0 var(--esp-24); font-size: var(--corpo); }
/* MEDIDO: o painel mora dentro do `form.acao-lote`, e `.acao-lote button[type=
   "submit"]` (acima) dá 8px de margem embaixo ao Filtrar -- o Limpar (um <a>)
   não a tem, e saía 4px mais baixo no centro da linha. Mesma especificidade,
   declarado depois: vence. */
.acoes-do-painel button[type="submit"] { margin-bottom: 0; }
/* #280: as fichas do filtro aplicado moram na barra, ao lado do Filtrar. */
.fichas-da-barra { margin: 0; }

.fichas { display: flex; flex-wrap: wrap; gap: var(--esp-8); margin-bottom: var(--esp-8); align-items: center; }
/* #289: pílula, como o `.chip` -- é o mesmo componente (filtro aplicado); era o único raio de 4px entre 13 pílulas. */
.ficha { background: var(--azul-fraco); color: var(--azul-escuro); padding: var(--esp-2) var(--esp-10); border-radius: 999px; font-size: var(--corpo-nota); }
.ficha-limpar { font-size: var(--corpo-nota); color: var(--azul); }
/* #289: 10px → 11px. É o chip de situação da lista (clicável desde o #274):
   o menor texto interativo do sistema não pode ser o menor texto do sistema. */
.marca { font-size: var(--corpo-mini); font-weight: var(--peso-medio); letter-spacing: .03em; padding: var(--esp-2) var(--esp-8); border-radius: 999px; white-space: nowrap; }
.marca-pago { background: var(--sucesso-fraco); color: var(--sucesso); }
.marca-aberto { background: var(--atencao-fraco); color: var(--atencao); }
/* #212: a frase que diz por qual data a lista agrupa. Discreta de propósito:
   é contexto permanente da tela, não um filtro nem um aviso. */
.nota-do-eixo { font-size: var(--corpo-nota); color: var(--ink-3); margin: 0 0 var(--esp-8); }
/* #212: a data de vencimento ao lado da marca "Pago", quando o dia do grupo
   é o do PAGAMENTO. Texto seco, sem pílula: é contexto, não estado -- duas
   pílulas lado a lado dariam à data o mesmo peso visual da situação. */
.dica-venc { font-size: var(--corpo-micro); color: var(--ink-3); margin-left: var(--esp-4); white-space: nowrap; }
.paginacao { display: flex; gap: var(--esp-16); align-items: center; margin-top: var(--esp-16); }

/* `min(200px, 100%)` e nao `200px`: com o `main` tendo 16px de padding de
   cada lado, uma tela de 390px deixa 358px de conteudo -- menos que 200px
   * 2, entao dois cartoes por linha ainda cabem, mas um minimo fixo maior
   que a largura disponivel estouraria a pagina. */
.cartoes { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr)); gap: var(--esp-16); margin-bottom: var(--esp-16); }
/* NÃO é o `.cartao` da fundação (contêiner branco de componentes.css): este
   aqui é uma célula de número, com estado na borda. Renomeado no #70 para
   que a fundação possa valer em todas as telas sem apagar a barra colorida. */
.cartao-kpi { display: flex; flex-direction: column; gap: var(--esp-4); padding: var(--esp-16); background: var(--surface); border-radius: var(--raio); border-left: 3px solid var(--line); text-decoration: none; color: inherit; }
.cartao-kpi:hover { background: var(--azul-fraco); }
.cartao-kpi-valor { font-family: "Cifra", system-ui, sans-serif; font-weight: var(--peso-forte); font-size: 26px; font-variant-numeric: tabular-nums; }
.cartao-kpi-quantidade { font-size: var(--corpo-nota); color: var(--ink-3); }
/* #288: o nome da empresa na tela de escolha -- texto, não dinheiro. */
.cartao-empresa-nome { font-size: var(--corpo-heroi); font-weight: var(--peso-forte); line-height: 1.2; }
.cartao-kpi-erro { border-left-color: var(--erro); }
.cartao-kpi-sucesso { border-left-color: var(--sucesso); }
.cartao-kpi-atencao { border-left-color: var(--atencao); }
.painel { background: var(--surface); border-radius: var(--raio); padding: var(--esp-16); display: flex; flex-wrap: wrap; gap: var(--esp-24); align-items: center; }
.rotulo { font-size: var(--corpo-nota); color: var(--ink-3); }
.alerta { color: var(--erro); }

.formulario { background: var(--surface); border-radius: var(--raio); padding: var(--esp-16); margin-top: var(--esp-16); max-width: 480px; }
.formulario p { margin: 0 0 var(--esp-8); display: flex; flex-direction: column; gap: var(--esp-4); }
.formulario label { font-size: var(--corpo-nota); color: var(--ink-3); }
input, select, textarea { font: inherit; height: var(--linha); padding: 0 var(--esp-8); border: 1px solid var(--line); border-radius: var(--raio); background: var(--surface); color: var(--ink); }
/* A regra acima e pensada para campo de texto/select; aplicada a um
   checkbox ela infla a caixinha para 32px de altura com borda e fundo,
   estourando a linha da tabela. Um checkbox usa o tamanho nativo. */
input[type="checkbox"] { height: auto; width: auto; padding: 0; border: 0; background: none; vertical-align: middle; }
/* #290: o <button> sem classe nascia AZUL sólido (32px) enquanto a ação
   primária do sistema é `.btn-primario` (--ink) -- duas cores de primário e
   três alturas para o mesmo botão. Agora ele nasce com a cara do `.btn`
   (componentes.css): quem quer primário pede a classe. As regras de contexto
   (menu da linha, submenu do nome, calendário, chip) continuam por cima. */
button {
  display: inline-flex; align-items: center; gap: var(--esp-6);
  padding: 7px var(--esp-14); border: 1px solid var(--line); border-radius: var(--raio);
  background: var(--surface); color: var(--ink); font: inherit; font-weight: var(--peso-medio); cursor: pointer;
}
button:hover { background: var(--line-2); }
/* Acao secundaria: contorno em vez de bloco cheio. O azul solido e da
   navegacao e da acao primaria de uma tela; quando tudo e primario, nada e. */
/* #289: `.botao-secundario` e `.botao` saíram -- eram o `.btn` com 2px a
   menos de altura e outra cor de borda; os templates usam `.btn`. */
.errorlist { color: var(--erro); font-size: var(--corpo-nota); margin: 0; padding-left: var(--esp-16); }

/* Contas em linha dupla: o nome de uma conta bancaria e um codigo, e codigo
   sozinho nao diz o que a conta e. */
.conta-marca {
  flex: none; width: 26px; height: 26px; display: grid; place-items: center;
  border-radius: 50%; background: var(--azul-fraco); color: var(--azul-escuro);
  font-size: var(--corpo-nota); font-weight: var(--peso-forte); text-transform: uppercase;
}
.lista-contas li { gap: var(--esp-10); flex-wrap: wrap; }
.conta-identidade { display: flex; flex-direction: column; gap: 1px; min-width: 0; margin-right: auto; }
.conta-nome { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conta-tipo { font-size: var(--corpo-mini); color: var(--ink-3); }

/* Saldo conferido contra o BANCO (#48). Segunda linha da propria conta, nunca
   um alarme: o numero divergente CONTINUA na tela (esconde-lo criaria dinheiro
   invisivel, o caso da RSB-PART) e ganha o valor do banco escrito ao lado.
   As duas cores saem dos tokens medidos no #42 -- --amarelo 4,51:1 e --ink-3
   4,54:1 sobre --surface, ambos AA. */
.conta-nao-conferida,
.conta-conferida {
  flex-basis: 100%;
  padding-left: 36px;   /* 26px da marca redonda + 10px do gap: alinha ao nome */
  font-size: var(--corpo-mini);
  margin-top: -2px;
}
.conta-nao-conferida { color: var(--amarelo); }
.conta-conferida { color: var(--ink-3); }

/* Balanco do mes. As barras se comparam ENTRE SI (a maior enche a linha),
   porque e a relacao entre entrada e saida que se le -- nao a distancia ate
   um teto arbitrario. */
.balanco { display: flex; flex-direction: column; gap: var(--esp-4); }
.balanco-linha { display: flex; justify-content: space-between; align-items: baseline; gap: var(--esp-12); }
.balanco-rotulo { font-size: var(--corpo-nota); color: var(--ink-3); }
.barra { height: 8px; border-radius: 999px; background: var(--page); overflow: hidden; margin-bottom: var(--esp-10); }
.barra > span { display: block; height: 100%; border-radius: 999px; }
.barra-entrada { background: var(--sucesso); }
.barra-saida { background: var(--erro); }
.balanco-resultado { display: flex; justify-content: space-between; align-items: baseline; gap: var(--esp-12); padding-top: var(--esp-10); border-top: 1px solid var(--line); }
.balanco-resultado .valor { font-size: 18px; }

.grafico { width: 100%; height: auto; display: block; }
/* Grade e rotulos do eixo: o `paint-order` evita que a linha da grade
   atravesse o texto do rotulo. */
.grafico-grade { stroke: var(--line); stroke-width: 1; }
/* Barras de movimento: pano de fundo da linha de saldo, e por isso mais
   claras que o verde e o vermelho do dinheiro em texto. */
.grafico-barra-entrada { fill: var(--sucesso); opacity: .45; }
.grafico-barra-saida { fill: var(--erro); opacity: .45; }
.grafico-rotulo-y, .grafico-rotulo-x {
  fill: var(--ink-3); font-size: var(--corpo-micro); font-family: inherit;
  font-variant-numeric: tabular-nums;
}
/* O rótulo do eixo fica LEGÍVEL mesmo quando a linha do saldo cruza por
   cima dele: um contorno da cor do papel separa os dois sem caixa e sem
   mover o rótulo para fora da área (#70/E4). */
.grafico-rotulo-y { paint-order: stroke; stroke: var(--surface); stroke-width: 3px; }
.grafico-linha { fill: none; stroke: var(--azul); stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }
/* Os pontos so aparecem no hover: com 30 dias de serie, 30 circulos
   permanentes viram ruido e escondem a forma da curva, que e o que a
   pessoa esta lendo. O alvo do mouse continua sempre la. */
.grafico-ponto { fill: var(--surface); stroke: var(--azul); stroke-width: 2; opacity: 0; }
.grafico:hover .grafico-ponto, .grafico-ponto:hover { opacity: 1; }
.grafico-zero { stroke: var(--line); stroke-width: 1; stroke-dasharray: 4 4; }
/* Legenda das barras: vermelho e verde não dizem sozinhos o que são (#70/E4). */
.grafico-legenda { display: flex; gap: var(--esp-12); align-items: center; font-size: var(--corpo-miudo); color: var(--ink-3); margin: var(--esp-6) 0 0; }
.grafico-chave { display: inline-block; width: 10px; height: 10px; border-radius: 2px; vertical-align: -1px; }
.grafico-chave-entrada { background: var(--verde); }
.grafico-chave-saida { background: var(--vermelho); }
.grafico-chave-linha { background: var(--azul); height: 3px; border-radius: 2px; }

/* #55, item 3: conteúdo largo à ESQUERDA, lateral (Precisa de você + Contas) à
   direita — como a referência. Antes as contas ficavam à esquerda e sobrava
   vazio do outro lado. */
/* #104: largura FIXA na lateral, como a referência (`.g-inicio`, v3 linha 79:
   `minmax(0,1fr) 344px`). Com `2fr minmax(280px,1fr)` a coluna das contas
   crescia junto com a janela — em 1920px ela passava de 500px e os nomes de
   conta nadavam num vão à direita, enquanto o gráfico, que é quem ganha com
   largura, ficava com o resto. Fixa em 344px, todo pixel a mais da janela vai
   para o conteúdo largo. O `minmax(0,1fr)` na primeira coluna é o que impede
   uma tabela larga de empurrar a grade (`1fr` sozinho tem mínimo `auto`). */
.painel-dashboard { display: grid; grid-template-columns: minmax(0, 1fr) 344px; gap: var(--esp-16); align-items: start; }
/* ⭐ #151 -- O VAZIO ENTRE OS CARTOES E O FLUXO DE CAIXA (relatado pelo dono
 * com `/root/referencia/err.png`).
 *
 * CAUSA, e ela nao estava no bloco do grafico: as duas linhas da grade eram
 * `auto`, e a `.coluna-lateral` ATRAVESSA as duas (`grid-row: 1 / span 2`).
 * Quando um item faz span sobre linhas `auto`, o CSS Grid distribui a altura
 * dele ENTRE elas -- entao metade da coluna da direita virava altura da linha
 * 1, e o herói, que e curto, ficava com o resto em branco embaixo.
 *
 * POR QUE APARECEU AGORA: a #150 pos as 5 contas zeradas de volta na lista.
 * A coluna da direita cresceu, e o vazio cresceu junto -- o defeito e antigo,
 * o gatilho e novo. O grafico nunca teve espacamento nenhum a mais.
 *
 * `auto 1fr` prega a linha 1 no tamanho do proprio herói e joga TODA a sobra
 * da lateral para a linha 2, onde o conteudo da esquerda cresce de baixo para
 * cima sem empurrar nada. `1fr` e `minmax(auto, 1fr)`: nunca encolhe abaixo do
 * conteudo dos blocos. */
.painel-dashboard { grid-template-rows: auto 1fr; }
/* #70/E2: gap igual ao da `.blocos` e da `.painel-dashboard` (16px) -- eram
   três gaps diferentes na mesma tela. `.bloco` estica para acompanhar a
   altura da linha do grid (que já estica por padrão; quem não acompanhava
   era esta coluna, que é flex). */
/* #104: as três células são posicionadas explicitamente, porque a ordem do
   DOM (herói, lateral, blocos) não é a ordem visual (herói e blocos na
   esquerda, lateral atravessando as duas linhas à direita). `order` de flex
   não resolveria: aqui é grid de duas dimensões. */
.cartao-heroi { grid-column: 1; grid-row: 1; margin-bottom: 0; }
.coluna-lateral { grid-column: 2; grid-row: 1 / span 2; display: flex; flex-direction: column; gap: var(--esp-16); }
.painel-dashboard > .blocos { grid-column: 1; grid-row: 2; }
.coluna-lateral > .cartao { margin-bottom: 0 !important; }
/* Grade DECLARADA, no lugar de `auto-fit`: com `repeat(auto-fit, minmax(220px,
   1fr))` uma tela larga empacotava quatro blocos numa fileira e deixava o
   ultimo orfao numa segunda linha. Aqui o grafico ocupa a largura inteira, os
   dois blocos de vencimento ficam lado a lado, e ranking e cartoes fecham a
   grade -- sem sobra. */
/* #104: a coluna esquerda passou a começar pelo HERÓI, que era largura total
   acima do painel — na referência ele mora aqui e a lateral sobe até o topo
   da tela (v3, linhas 416-524). Com o herói fora, a lateral começava 150px
   abaixo e aquele vão à direita era o primeiro pixel da tela.
   A grade nomeada de duas colunas virou empilhamento: só a última fileira
   (Top despesas | Balanço) tem duas colunas, e ela é a `.blocos-par`. */
.blocos {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--esp-16);
}
.blocos-par { display: grid; grid-template-columns: 1fr 1fr; gap: var(--esp-16); align-items: start; }
.area-grafico { min-width: 0; }
.blocos > .bloco { height: 100%; }
.bloco { display: flex; flex-direction: column; gap: var(--esp-8); padding: 20px; background: var(--surface); border-radius: var(--raio); box-shadow: var(--sombra); text-decoration: none; color: inherit; }
/* Sobrancelha: pequena, espacada, caixa alta. O titulo de um bloco e um
   ROTULO -- ele nomeia o que esta abaixo e sai da frente. Quem tem que ser
   grande e o numero. */
.bloco-titulo {
  font-size: var(--corpo-mini); font-weight: var(--peso-medio); letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-3);
}
/* #70 (Tarefa 10): `.bloco-numero`/`.bloco-valor`/`.bloco-acao` (e, acima,
   `.bloco-erro`/`.bloco-sucesso`) apagadas -- CSS morto. As cinco so
   existiam para `templates/componentes/cartao-numero.html`, um componente
   ORFAO (zero `{% include %}` em qualquer template -- achado da Tarefa 3,
   "verificar na revisao final", fechado aqui): o card `.bloco.bloco-{{tom}}`
   de "Vencidas a pagar/receber" que ele desenhava foi substituido pela fila
   compacta de `<a><span class="etiqueta">` em "Abertura do comprometido"
   (templates/home.html), e o template velho nunca foi apagado. Achado ao
   vivo: `verificar_navegador.py` (a checagem de "ocultar valores") batia
   num `document.querySelector('.bloco-valor.valor')` que nao existia em
   lugar nenhum e travava com TypeError -- e foi essa checagem quebrando que
   trouxe a cadeia inteira a tona. `.bloco-titulo` continua viva (Contas,
   Fluxo de caixa, Top despesas, Balanco, Cartoes de credito, Precisa de
   voce) -- so as classes exclusivas do componente orfao saíram. */

/* O saldo geral e o evento tipografico da pagina: e a resposta a primeira
   pergunta que alguem faz ao abrir o sistema. Estava num `style` inline de
   32px, do tamanho de um titulo qualquer. */
.saldo-geral { font-size: 46px; line-height: 1.05; letter-spacing: -.015em; }

/* Foco visivel: nao havia nenhum estilo de foco no projeto, entao quem
   navega por teclado dependia do anel padrao do navegador -- que some sob
   `background` proprio em varios elementos. Um anel unico, na cor de acao,
   em tudo que recebe foco. */
:focus-visible {
  outline: 2px solid var(--azul);
  outline-offset: 2px;
  border-radius: var(--raio-miudo);
}
/* #163: aqui morava `.topo :focus-visible { outline-color: #fff; }`.
   Ele existia para a barra ESCURA do pre-#145, onde o anel branco era o unico
   visivel. Com a barra em `var(--surface)` o anel ficou branco sobre branco --
   1,00:1 -- e o foco de teclado sumiu da barra INTEIRA: menu, `Trocar`
   empresa, `Buscar` (Ctrl+K) e `+ Lancar`. Sem esta regra vale o
   `:focus-visible` global acima (`var(--azul)`), que da 5,17:1 sobre a barra.
   Nao reintroduzir cor de anel por barra: se a barra mudar de fundo de novo, o
   global acompanha e esta regressao nao volta. Guarda:
   tests/test_contraste_163.py. */

/* Movimento com moderacao: numa ferramenta de uso diario, animacao e
   ruido. So a transicao de realce, e nem ela para quem pediu menos
   movimento no sistema operacional. */
a, button, summary, .bloco, .tabela tbody tr { transition: background-color .12s ease, color .12s ease; }
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

.lista-contas { list-style: none; margin: 0; padding: 0; }
/* A lista de contas e um razao: nome a esquerda, cifra a direita, pauta
   entre as linhas. Sem a ultima pauta -- regra que fecha lista pendura no
   vazio. */
.lista-contas li { display: flex; justify-content: space-between; align-items: baseline; gap: var(--esp-12); padding: 9px 0; border-bottom: 1px solid var(--page); }
.lista-contas li:last-child { border-bottom: 0; padding-bottom: 0; }
/* O `li` do estado vazio NAO e uma linha de razao: sendo flex com
   `space-between`, o texto, o link e o ponto final viravam tres itens
   espalhados pela largura ("Nenhum cartao.    Cadastrar um cartao    ."). */
.lista-contas li.vazio { display: block; }
.ranking { list-style: none; margin: 0; padding: 0; counter-reset: posicao; }
.ranking li { display: flex; align-items: baseline; gap: var(--esp-10); padding: var(--esp-8) 0; border-bottom: 1px solid var(--page); }
.ranking li:last-child { border-bottom: 0; }
.ranking li::before { counter-increment: posicao; content: counter(posicao); flex: none; width: 18px; height: 18px; display: grid; place-items: center; border-radius: 50%; background: var(--page); color: var(--ink-3); font-size: var(--corpo-micro); font-weight: var(--peso-forte); align-self: center; }
/* O valor encosta na direita e o percentual fecha a linha, com largura fixa
   para que os percentuais alinhem entre si em vez de dancarem conforme o
   numero de digitos. */
.ranking .valor { margin-left: auto; }
.ranking .percentual { flex: none; width: 52px; text-align: right; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* #289: era 860px, o único breakpoint fora do 900/901 do resto do sistema
   (entre 861 e 900 o dashboard já era uma coluna e o cabeçalho ainda era grid). */
@media (max-width: 900px) {
  .painel-dashboard { grid-template-columns: 1fr; }
  /* #104: numa coluna só, o posicionamento explícito da grade some e vale o
     empilhamento — herói primeiro (é o número que a pessoa abriu a tela para
     ver), depois a lateral com as pendências, e o conteúdo largo por último. */
  .cartao-heroi, .coluna-lateral, .painel-dashboard > .blocos {
    grid-column: 1; grid-row: auto;
  }
  .cartao-heroi { order: 0; }
  .coluna-lateral { order: 1; }
  .painel-dashboard > .blocos { order: 2; }
  /* Numa tela estreita a grade nomeada viraria duas colunas de 1fr
     espremidas; empilhar em uma coluna so e o comportamento certo. */
  .blocos { grid-template-columns: 1fr; grid-template-areas: none; }
  .blocos > * { grid-area: auto; }
  /* #104: Top despesas e Balanço lado a lado em 360px dariam ~160px cada —
     o valor `368.625,21` não cabe e quebra a linha em duas. */
  .blocos-par { grid-template-columns: 1fr; }
}

/* `tabular-nums` em TODA a classe `valor`, nao so nas colunas alinhadas a
   direita: sem largura fixa de algarismo, uma coluna de dinheiro nao alinha
   e o olho nao consegue comparar duas linhas. */
/* O papel tipografico do dinheiro. Sem `color` aqui de proposito: a cor do
   valor vem do contexto (`.negativo`, `.positivo`, ou a tinta herdada). */
.valor {
  font-family: "Cifra", system-ui, sans-serif;
  font-weight: var(--peso-forte);
  font-variant-numeric: tabular-nums;
  letter-spacing: .01em;
}
/* #71: `.heroi-num` entra aqui porque estava de fora. Os tres numeros do topo
   da home -- Disponivel, Comprometido, Folga -- usam `.heroi-num`, nunca
   `.valor`, entao o olho borrava os cartoes de baixo e deixava LEGIVEL o maior
   numero da tela. Achado na prova da Tarefa 4 (#71) com clique real no
   navegador. Meia privacidade e pior que nenhuma: quem clica no olho conclui
   que escondeu tudo e vira a tela para o lado. */
.valores-ocultos .valor,
.valores-ocultos .heroi-num { filter: blur(6px); user-select: none; }

/* Impressao: o papel nao tem navegacao nem paginacao, e um recorte impresso
   sem o periodo no topo nao serve para conferir nada -- por isso o cabecalho
   FICA. `break-inside: avoid` impede que uma linha de lancamento seja cortada
   ao meio pela quebra de pagina. */
@media print {
  .topo, .filtros, .paginacao, .acao-lote button[type="submit"],
  .acao-lote button[data-confirma-exclusao],
  .ocultar-valores, .exportar-csv, .acoes-do-relatorio { display: none; }

  /* `html body`, e não `body`: `tokens.css` declara `background: var(--page)`
     num `body` sem condição de mídia, com a MESMA especificidade (0,0,1), e
     carrega depois -- então a regra de impressão perdia em silêncio e o papel
     saía com o cinza da tela. Um degrau a mais resolve, e o comentário fica
     para que ninguém "simplifique" isto de volta. (#70) */
  html body { background: var(--branco); }
  main { max-width: none; padding: 0; }
  .tabela, .bloco, .painel { box-shadow: none; }
  .rolagem-horizontal { overflow-x: visible; }
  .tabela tr { break-inside: avoid; }
  .tabela th { color: var(--ink); }

  /* O borrao de "ocultar valores" e um recurso de tela; no papel ele
     produziria um relatorio ilegivel sem que ninguem percebesse. */
  .valores-ocultos .valor,
  .valores-ocultos .heroi-num { filter: none; }
}

/* ------------------------------------------------------------- analise -- */
/* Controles como LINKS e nao `<select>`: cada estado da analise tem endereco
   proprio, entao um recorte e compartilhavel e o botao voltar funciona. */
.controles-da-analise {
  display: flex; flex-wrap: wrap; gap: var(--esp-24); align-items: flex-start;
  margin-bottom: var(--esp-16); padding: var(--esp-14) var(--esp-16);
  background: var(--surface); border-radius: var(--raio); box-shadow: var(--sombra);
}
.grupo-de-controle { display: flex; flex-direction: column; gap: var(--esp-6); }
.controle-rotulo {
  font-size: var(--corpo-micro); font-weight: var(--peso-medio); letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-3);
}
.opcoes { display: flex; flex-wrap: wrap; gap: var(--esp-4); }
.opcao {
  padding: var(--esp-4) var(--esp-12); border-radius: 999px; font-size: var(--corpo-nota);
  color: var(--ink-3); text-decoration: none; border: 1px solid var(--line);
  white-space: nowrap;
}
.opcao:hover { background: var(--azul-fraco); color: var(--azul-escuro); }
.opcao-ativa { background: var(--azul); border-color: var(--azul); color: var(--branco); }
.opcao-ativa:hover { background: var(--azul-escuro); color: var(--branco); }

/* O filtro de categoria e conta dos relatorios (#191). Mora junto dos outros
   controles porque E um deles: mesmo cartao, mesmo rotulo em caixa alta. O que
   muda e que este abre um painel -- marcar VARIAS categorias num menu suspenso
   nao existe, e 221 categorias (Link ce, medido em 19/08/2026) num select
   viram uma lista que ninguem varre. A indentacao segue o idioma que a arvore
   da analise ja usa (`.nivel-N`), so que escopada neste painel. */
.filtro-do-relatorio { min-width: 220px; }
/* O resumo segue o desenho dos vizinhos: rotulo em caixa alta em cima, o
   valor como pilula clicavel embaixo -- e o painel inteiro e o `<details>`.
   O marcador nativo sai porque ele quebraria o alinhamento da coluna; quem
   anuncia que abre e o `▾` dentro da pilula. */
.resumo-do-filtro { display: flex; flex-direction: column; gap: var(--esp-6); cursor: pointer; list-style: none; }
.resumo-do-filtro::-webkit-details-marker { display: none; }
.resumo-do-filtro-valor { max-width: 320px; overflow: hidden; text-overflow: ellipsis; }
.filtro-do-relatorio[open] .resumo-do-filtro-valor { background: var(--azul-fraco); color: var(--azul-escuro); }
.painel-de-filtro {
  display: flex; flex-wrap: wrap; gap: var(--esp-24); align-items: flex-start;
  margin-top: var(--esp-8); padding: var(--esp-12);
  background: var(--page); border: 1px solid var(--line); border-radius: var(--raio);
}
.coluna-do-filtro { display: flex; flex-direction: column; gap: var(--esp-6); min-width: 240px; }
.marcacao-em-arvore {
  list-style: none; margin: 0; padding: 0;
  /* Teto em px, nao em vh (R40): altura de controle e ergonomica. 320px cabe
     ~16 linhas e sobra tela em 1366x768 com o painel aberto. */
  max-height: 320px; overflow-y: auto;
}
.item-de-marcacao { display: flex; align-items: center; gap: var(--esp-6); padding: var(--esp-2) 0; font-size: var(--corpo-denso); }
.item-de-marcacao label { display: flex; align-items: center; gap: var(--esp-6); cursor: pointer; min-width: 0; }
.nome-para-marcar { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.marcacao-em-arvore .nivel-1 { padding-left: var(--esp-16); }
.marcacao-em-arvore .nivel-2 { padding-left: calc(2 * var(--esp-16)); }
.marcacao-em-arvore .nivel-3 { padding-left: calc(3 * var(--esp-16)); }
.marcacao-em-arvore .nivel-4 { padding-left: calc(4 * var(--esp-16)); }
.marca-herdada {
  font-size: var(--corpo-micro); letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-3); white-space: nowrap;
}
.nota-do-filtro, .vazio-do-filtro { margin: 0; font-size: var(--corpo-micro); color: var(--ink-3); }
/* As acoes fecham o painel embaixo, largura cheia: no topo elas competiam com
   os titulos das duas colunas (visto na foto local). */
.acoes-do-filtro { display: flex; align-items: center; gap: var(--esp-8); flex-basis: 100%; }

.cabecalho-do-relatorio { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--esp-16); flex-wrap: wrap; }
.titulo-do-relatorio { font-size: 16px; margin: 0; }
.recorte-do-relatorio { margin: var(--esp-4) 0 0; font-size: var(--corpo-nota); color: var(--ink-3); }
/* #169 -- o aviso de que a tabela NAO mostra o periodo inteiro (`dre.html:51`,
   pendencia registrada em RELATORIO-154-M2) vinha sem regra: herdava a cor do
   metadado que o cerca e desaparecia dentro dele -- justo a frase que diz que
   falta dado na tela (diretriz #77, item 8). Medido sobre o fundo real, que e
   o `.bloco` (--superficie #ffffff): --atencao #ad5f05 = 4,76:1, AA; sobre
   --fundo #f8fafc = 4,55:1, tambem AA. O PESO entra porque matiz sozinho nao
   basta: --tinta-fraca #64748b da os MESMOS 4,76:1, ou seja, mesma luminancia. */
.recorte-limitado { color: var(--atencao); font-weight: var(--peso-medio); }

/* A análise em escada (#172): a forma do relatório do Controlle, que é a
   referência aprovada pelo dono — seções EMPILHADAS de largura cheia
   (entradas primeiro), hierarquia completa por <details> nativo (teclado e
   leitor de tela ganham o abre/fecha de graça, sem JavaScript). Cada linha é
   um grid com as DUAS colunas da direita fixas: é isso que mantém percentual
   e valor alinhados em qualquer profundidade — a indentação come só a coluna
   do nome. (As barras proporcionais saíram com o redesenho: o percentual
   carrega o número, e a referência não tem barra.) */
.arvore-da-analise { margin-top: 20px; }
.arvore-da-analise + .arvore-da-analise { margin-top: 28px; }

.lado-cabecalho { display: flex; justify-content: space-between; align-items: baseline; padding-bottom: var(--esp-8); border-bottom: 1px solid var(--line); }
.lado-total { font-size: 20px; }

.linha-da-arvore {
  display: grid;
  grid-template-columns: var(--esp-16) minmax(0, 1fr) 72px 150px;
  align-items: center;
  column-gap: var(--esp-6);
  padding: var(--esp-6);
  border-bottom: 1px solid var(--page);
  font-size: var(--corpo-denso);
}
.cabecalho-da-arvore {
  font-size: var(--corpo-micro); font-weight: var(--peso-forte); letter-spacing: .07em;
  text-transform: uppercase; color: var(--ink-3);
  border-bottom: 1px solid var(--line);
}
.nome-da-arvore { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nivel-0 > .linha-da-arvore > .nome-da-arvore { font-weight: var(--peso-medio); }
.valor-da-arvore { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.percentual-da-fatia { color: var(--ink-3); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.amostra-de-cor { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: var(--esp-6); }

/* A escada: recuo ABSOLUTO por nível (os nós são aninhados no DOM, mas o
   recuo não acumula — cada classe diz a distância da margem). */
.nivel-1 > .linha-da-arvore { padding-left: var(--esp-24); }
.nivel-2 > .linha-da-arvore { padding-left: calc(2 * var(--esp-24)); }
.nivel-3 > .linha-da-arvore { padding-left: calc(3 * var(--esp-24)); }
.nivel-4 > .linha-da-arvore { padding-left: calc(4 * var(--esp-24)); }

.haste-da-arvore { text-align: center; color: var(--ink-3); }
/* #173: cabeçalho que ordena — o link herda a cor do cabeçalho e só se
   anuncia no hover; a seta marca a coluna ativa. */
.th-ordenavel a { color: inherit; text-decoration: none; }
.th-ordenavel a:hover { color: var(--azul); text-decoration: underline; }
.seta-de-ordem { color: var(--azul); }
.cabecalho-da-arvore .th-ordenavel { text-transform: inherit; }
.no-da-analise > summary { list-style: none; cursor: pointer; }
.no-da-analise > summary::-webkit-details-marker { display: none; }
.no-da-analise > summary:hover { background: var(--page); }
.seta-da-arvore::before { content: "▸"; color: var(--ink-3); }
details[open] > summary > .seta-da-arvore::before { content: "▾"; }
.no-da-analise > .conteudo-da-gaveta { padding: var(--esp-4) var(--esp-12) var(--esp-8); }

.resultado-total {
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--esp-16);
  margin-top: 20px; padding-top: var(--esp-14); border-top: 2px solid var(--line);
}
.resultado-total .valor { font-size: 24px; }

/* ----------------------------------------------------------------- DRE -- */
.tabela-dre { font-size: var(--corpo-nota); }
.tabela-dre th, .tabela-dre td { padding: 5px var(--esp-8); height: auto; white-space: nowrap; }
.tabela-dre .dre-rotulo { text-align: left; text-transform: none; letter-spacing: 0; font-size: var(--corpo-nota); white-space: normal; min-width: 200px; }
.tabela-dre tbody .dre-rotulo { font-weight: var(--peso-normal); color: var(--ink); }
.tabela-dre .dre-rotulo a { color: inherit; text-decoration: none; }
.tabela-dre .dre-rotulo a:hover { color: var(--azul); text-decoration: underline; }
.dre-total { border-left: 1px solid var(--line); font-weight: var(--peso-forte); }
.dre-av { color: var(--ink-3); font-variant-numeric: tabular-nums; width: 1%; }

/* ⭐ TRÊS ÂNCORAS GRUDADAS NO DRE: RÓTULO À ESQUERDA, TOTAL + AV À DIREITA
 * (#98, B2 — decisão do dono).
 *
 * O DEFEITO QUE OBRIGA, e ele é maior que o que o prompt descrevia. Medido no
 * navegador sobre o HTML de produção da Link ce (`main` útil 1248px, quadro
 * visível 1208px, tabela 1357px em 2026 e 1570px em 2025):
 *   - da coluna TOTAL só 20 dos 100px estavam visíveis (80% cortados) em
 *     2026, e ZERO dos 104px em 2025;
 *   - da AV, 0 de 70px — inteiramente fora;
 *   - e o RÓTULO DA LINHA não era fixo (`position: static`): rolando o quadro
 *     até o fim sobravam 91px dos 240px em 2026 e **0px** no ano cheio. Quem
 *     rolava para ler dezembro lia um número sem saber de que linha ele era.
 *   O rótulo é por isso OBRIGATÓRIO, não conforto.
 *
 * POR QUE NÃO COLAPSAR OS MESES VAZIOS, que era a outra opção: em 2026 quatro
 * meses estão 100% vazios (set/out/nov/dez: 134 células `—` de 134 linhas) e
 * escondê-los devolveria 149px; em 2025 **nenhum** mês está vazio (as células
 * `—` por mês vão de 39 a 51 em 140 linhas) e a mesma ideia devolveria ZERO.
 * Ela resolve o problema de hoje e desaparece exatamente quando o relatório
 * fica mais largo — é o erro do #78 com outra roupa. O sticky devolve os
 * 100px do TOTAL em 100% das posições de rolagem, nos dois anos.
 *
 * A AV VAI JUNTO DO TOTAL por decisão do dono: percentual só significa alguma
 * coisa ao lado do número que ele descreve. Custo: ~70px permanentemente
 * ocupados; sobram ~798px para os meses (≈8 meses por vez), e os outros se
 * alcançam rolando o quadro — o mecanismo que a tela JÁ tem
 * (`.rolagem-horizontal:has(.tabela-dre)`, acima). A alternativa proibida é
 * alargar a tela (#78/#79): `main` tem teto de 1280px em toda tela.
 *
 * PAR AMARRADO, como `.gruda-valor`/`.gruda-acoes` em componentes.css: a AV
 * mede 70px e o TOTAL gruda em `right: 70px`. Mudou um, muda o outro. Os 70px
 * NÃO são escolha minha — é a largura NATURAL medida com o dado real nos dois
 * anos (o conteúdo mais largo da coluna é `115,0%`, 6 caracteres). `min-width`
 * e não `width` fixo de propósito: se um dia um percentual exigir mais, a
 * coluna cresce e o pior caso é uma fresta atrás do TOTAL — nunca texto
 * cortado. E a prova de navegador afirma a igualdade `largura da AV == right
 * do TOTAL`, então o dia em que ela deixar de valer alguém fica sabendo.
 *
 * Fundo: não precisa ser declarado aqui. `.tabela th, .tabela td`
 * (componentes.css) já pinta `var(--surface)` em toda célula, e as faixas da
 * cascata (`.dre-secao > *`, `.dre-subtotal > *`, `.dre-sem_grupo > *`, o
 * hover) vêm DEPOIS nesta folha e continuam vencendo — a célula grudada
 * mantém a cor da própria linha, em vez de virar uma tira branca. */
.tabela-dre .dre-rotulo { position: sticky; left: 0; z-index: 3; }
.tabela-dre .dre-total { position: sticky; right: 70px; z-index: 2; }
.tabela-dre .dre-av { position: sticky; right: 0; z-index: 2; min-width: 70px; }

/* A hierarquia da cascata, do mais forte ao mais fraco: subtotal, seção,
   grupo, categoria. Sem essa escada, 40 linhas de numero viram uma parede.

   As faixas abaixo tinham (0,1,0) (o `> *` nao acrescenta especificidade) e
   sumiam atras de dois seletores da fundacao: `.tabela th, .tabela td`
   (componentes.css) e (0,1,1), que ja bastava para vencer; e
   `.tabela tbody tr:hover th, .tabela tbody tr:hover td`, que e (0,2,3) --
   subir so um degrau devolvia a faixa em repouso e a perdia de novo sob o
   mouse. A dupla `.tabela-dre .dre-X` / `.tabela-dre .dre-X:hover` soma
   DUAS classes em repouso -- (0,2,0), maior que (0,1,1) so no digito das
   classes, o suficiente para vencer OS DOIS tipos contados na regra base --
   e TRES sob o mouse -- (0,3,0), maior que (0,2,3) no MESMO digito, entao
   vence sem depender de quantos tipos o outro lado tem. Nada de
   `!important`: e so contar direito.

   Decisao sobre o hover: estas linhas (subtotal/secao/sem_grupo) nunca tem
   `linha.url` (core/views/dre.py so poe url em CATEGORIA) -- nao sao
   clicaveis, entao o destaque cinza que marca "isto responde ao clique" e
   enganoso aqui. A faixa sobrevive ao hover de proposito: continua dizendo
   "isto e estrutura", com ou sem o mouse em cima. As linhas GRUPO e
   CATEGORIA (essas sim, com link) NAO tem regra propria de fundo e
   continuam recebendo o cinza padrao do componentes.css normalmente. */
.tabela-dre .dre-subtotal > *,
.tabela-dre .dre-subtotal:hover > * { background: var(--azul-fraco); font-weight: var(--peso-forte); border-top: 1px solid var(--line); }
.dre-subtotal .dre-rotulo { font-weight: var(--peso-maximo); }
.tabela-dre .dre-secao > *,
.tabela-dre .dre-secao:hover > * { background: var(--secao-hover); }
.dre-secao .dre-rotulo { font-weight: var(--peso-forte); }
.dre-grupo .dre-rotulo { padding-left: var(--esp-24); }
.dre-categoria .dre-rotulo { padding-left: 44px; color: var(--ink-3); }
.dre-nivel-3 .dre-rotulo { padding-left: 60px; }
.dre-nivel-4 .dre-rotulo { padding-left: 76px; }
/* #174b: com a arvore completa (mae presente em todo ramo com movimento) a
   escada pode chegar ao 5o degrau — 92px, em passos da escala. */
.dre-nivel-5 .dre-rotulo { padding-left: calc(5 * var(--esp-16) + var(--esp-12)); }
.tabela-dre .dre-sem_grupo > *,
.tabela-dre .dre-sem_grupo:hover > * { background: var(--alerta-fundo); }
.dre-sem_grupo .dre-rotulo { font-weight: var(--peso-forte); color: var(--atencao); }

/* Categorias escondidas por padrao: a cascata e a leitura principal, e
   abrir e um clique. Elas ficam NO HTML -- quem esconde e o CSS --, entao a
   impressao e o leitor de tela continuam alcancando tudo. */
.tabela-dre .dre-categoria { display: none; }
.tabela-dre.com-categorias .dre-categoria { display: table-row; }
@media print { .tabela-dre .dre-categoria { display: table-row; } }

.opcao-interruptor { display: inline-flex; align-items: center; gap: var(--esp-6); cursor: pointer; }
.aviso-do-relatorio { margin: var(--esp-16) 0 0; font-size: var(--corpo-nota); color: var(--ink-3); }
.aviso-do-relatorio .valor { color: var(--atencao); }

/* ------------------------------------------------------ tabela cruzada -- */
.controles-secundarios { margin: var(--esp-16) 0 var(--esp-8); }
.tabela-cruzada { font-size: var(--corpo-nota); }
.tabela-cruzada th, .tabela-cruzada td { padding: 5px var(--esp-8); height: auto; white-space: nowrap; }
.tabela-cruzada .cruzada-rotulo { text-align: left; text-transform: none; letter-spacing: 0; font-size: var(--corpo-nota); white-space: normal; min-width: 200px; position: sticky; left: 0; z-index: 3; }
.tabela-cruzada tbody .cruzada-rotulo { font-weight: var(--peso-normal); }
.tabela-cruzada .cruzada-rotulo a { color: inherit; text-decoration: none; }
.tabela-cruzada .cruzada-rotulo a:hover { color: var(--azul); text-decoration: underline; }
/* #172: o sticky que o DRE já tinha (#98/B2), no mesmo desenho — TOTAL e AV
   grudados à direita, com o `right` do TOTAL igual ao `min-width` do AV; o
   fundo vem do `.tabela th/td` do componentes.css, e as faixas de seção/saldo
   vêm DEPOIS nesta folha e continuam vencendo. */
.cruzada-total { border-left: 1px solid var(--line); font-weight: var(--peso-forte); position: sticky; right: 70px; z-index: 2; }
.cruzada-av { color: var(--ink-3); font-variant-numeric: tabular-nums; position: sticky; right: 0; z-index: 2; min-width: 70px; }

/* As linhas de saldo abrem e fecham a leitura -- sao elas que fazem disto um
   fluxo de caixa e nao um agrupamento com colunas.

   Mesma mecanica e mesma decisao do DRE (ver o comentario junto de
   `.dre-subtotal`, acima): `.tabela-cruzada .cruzada-X` empata as classes em
   (0,2,0) e a variante `:hover` em (0,3,0), o suficiente para vencer a base
   da fundacao (0,1,1) e o hover dela (0,2,3) sem `!important`. Nenhuma
   destas linhas (saldo/secao/resultado) tem `linha.url`
   (core/views/analise.py so poe url em GRUPO) -- a faixa fica igual sob o
   mouse de proposito, porque nao ha clique para anunciar aqui. */
.tabela-cruzada .cruzada-resultado > *,
.tabela-cruzada .cruzada-resultado:hover > * { background: var(--azul-fraco); font-weight: var(--peso-forte); }
.cruzada-resultado > * { border-top: 2px solid var(--line); }
.tabela-cruzada .cruzada-secao > *,
.tabela-cruzada .cruzada-secao:hover > * { background: var(--secao-hover); }
.cruzada-secao .cruzada-rotulo { font-weight: var(--peso-forte); }
.cruzada-grupo .cruzada-rotulo { padding-left: var(--esp-24); color: var(--ink-3); }

/* #172: linhas de categoria/subcategoria da cruzada — mesmo mecanismo do DRE
   (`.dre-categoria`, acima): vêm no HTML, o CSS esconde, o interruptor
   "Mostrar categorias" revela, e a impressão mostra tudo. O recuo por nível
   soma o degrau do grupo (--esp-24) mais --esp-16 por profundidade. */
.tabela-cruzada .cruzada-categoria { display: none; }
.tabela-cruzada.com-categorias .cruzada-categoria { display: table-row; }
@media print { .tabela-cruzada .cruzada-categoria { display: table-row; } }
.cruzada-categoria .cruzada-rotulo { color: var(--ink-3); }
.cruzada-nivel-1 .cruzada-rotulo { padding-left: calc(var(--esp-24) + var(--esp-16)); }
.cruzada-nivel-2 .cruzada-rotulo { padding-left: calc(var(--esp-24) + 2 * var(--esp-16)); }
.cruzada-nivel-3 .cruzada-rotulo { padding-left: calc(var(--esp-24) + 3 * var(--esp-16)); }
.cruzada-nivel-4 .cruzada-rotulo { padding-left: calc(var(--esp-24) + 4 * var(--esp-16)); }

/* AH atras de interruptor: doze meses com variacao ao lado sao 24 colunas de
   numero, e a comparacao com o mes anterior e a SEGUNDA pergunta. */
.tabela-cruzada .cruzada-ah { display: none; font-size: var(--corpo-micro); font-variant-numeric: tabular-nums; }
.tabela-cruzada.com-ah .cruzada-ah { display: table-cell; }

/* #172 — as DUAS tabelas de meses (cruzada da Análise e DRE) no mesmo corpo
   e no mesmo respiro. O prefixo `.tabela` existe para VENCER o
   `.tabela-densa` do componentes.css: aquela folha carrega DEPOIS desta
   (app → tokens → componentes, #70) e empatava a especificidade — o corpo
   e o padding declarados aqui não chegavam à tela. Meses em --corpo-mini é
   o que aproxima 12 colunas + Total da largura útil (1232px em 1366);
   rótulo e cabeçalhos ficam em --corpo-nota, e o que não couber rola DENTRO
   do quadro com rótulo/TOTAL/AV grudados. */
.tabela.tabela-cruzada, .tabela.tabela-dre { font-size: var(--corpo-nota); }
/* O RÓTULO fica FORA do shorthand de padding: com (0,2,1) ele vencia as
   regras de recuo da escada (.dre-grupo/.cruzada-nivel-*, (0,2,0)) e
   achatava a indentação das duas tabelas — medido: todo rótulo indentado
   computava padding-left 6px (#172c). O rótulo recebe só o respiro
   vertical; o padding-left dele vem da base e das regras de recuo. */
.tabela.tabela-cruzada th:not(.cruzada-rotulo), .tabela.tabela-cruzada td:not(.cruzada-rotulo),
.tabela.tabela-dre th:not(.dre-rotulo), .tabela.tabela-dre td:not(.dre-rotulo) { padding: var(--esp-4) var(--esp-6); height: auto; }
.tabela.tabela-cruzada .cruzada-rotulo,
.tabela.tabela-dre .dre-rotulo { padding-top: var(--esp-4); padding-bottom: var(--esp-4); height: auto; }
.tabela.tabela-cruzada td.valor, .tabela.tabela-dre td.valor { font-size: var(--corpo-mini); }

/* ---------------------------------------------------------------- paleta -- */
.paleta {
  position: fixed; inset: 0; z-index: 100;
  background: var(--veu-paleta);
  display: flex; justify-content: center;
  padding: 12vh var(--esp-16) var(--esp-16);
}
.paleta[hidden] { display: none; }
.paleta-painel {
  width: 100%; max-width: 560px; max-height: 70vh;
  display: flex; flex-direction: column;
  background: var(--surface); border-radius: 12px;
  box-shadow: var(--sombra-paleta);
  overflow: hidden;
}
.paleta-campo {
  border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  height: 52px; padding: 0 18px; font-size: var(--corpo);
}
/* #287: era `outline: none` sem substituto -- o primeiro campo focado da
   paleta ficava sem nenhum sinal de foco. */
.paleta-campo:focus { outline: none; border-bottom-color: var(--azul); box-shadow: inset 0 -1px 0 var(--azul); }
.paleta-resultados { overflow-y: auto; padding: var(--esp-6); }
.paleta-secao {
  margin: var(--esp-8) var(--esp-12) var(--esp-4); font-size: var(--corpo-micro); font-weight: var(--peso-medio);
  letter-spacing: .07em; text-transform: uppercase; color: var(--ink-3);
}
.paleta-item {
  display: flex; align-items: baseline; gap: var(--esp-10);
  padding: var(--esp-8) var(--esp-12); border-radius: var(--raio);
  color: var(--ink); text-decoration: none;
}
.paleta-rotulo { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.paleta-detalhe { font-size: var(--corpo-mini); color: var(--ink-3); white-space: nowrap; }
/* Realce da SELECAO, nao do hover: quem manda aqui e o teclado, e duas
   marcas competindo confundem qual acao o Enter vai executar. */
.paleta-item.paleta-ativo { background: var(--azul-fraco); }
.paleta-vencido .paleta-detalhe { color: var(--atencao); }
.paleta-vazio, .paleta-rodape { margin: var(--esp-12); font-size: var(--corpo-nota); color: var(--ink-3); }
.paleta-rodape { margin: 0; padding: var(--esp-8) var(--esp-16); border-top: 1px solid var(--line); }
/* #294: a lista de atalhos (modal aberto por "?"). */
.atalhos-grupo { margin: var(--esp-14) 0 var(--esp-6); font-size: var(--corpo-rotulo); font-weight: var(--peso-forte); color: var(--ink-3); }
.atalhos-grupo:first-child { margin-top: 0; }
.tabela-de-atalhos { display: grid; grid-template-columns: max-content 1fr; gap: var(--esp-6) var(--esp-16); margin: 0; align-items: center; }
.tabela-de-atalhos dt { margin: 0; }
.tabela-de-atalhos dd { margin: 0; font-size: var(--corpo-miudo); color: var(--ink-2); }
.tabela-de-atalhos kbd, .paleta-rodape kbd {
  display: inline-block; padding: 1px 5px; margin-right: var(--esp-2);
  border: 1px solid var(--line); border-radius: var(--raio-miudo);
  font-family: inherit; font-size: var(--corpo-micro); background: var(--page);
}

/* Faixa de escopo de serie: aparece DEPOIS da edicao, oferecendo escalar. */
.faixa-escopo {
  display: flex; align-items: center; gap: var(--esp-12); flex-wrap: wrap;
  margin: var(--esp-8) 0; padding: var(--esp-10) var(--esp-14);
  background: var(--azul-fraco); border-radius: var(--raio); font-size: var(--corpo-nota);
}
.faixa-escopo button { height: 26px; padding-top: 0; padding-bottom: 0; font-size: var(--corpo-nota); }
.faixa-escopo-feita { background: var(--sucesso-fraco); color: var(--sucesso); }
/* #203: a faixa que PEDE confirmacao antes de mexer em dinheiro em massa.
   Amarelo e nao vermelho: nada quebrou, e uma decisao a tomar. */
.faixa-escopo-perigo { background: var(--alerta-fundo); color: var(--atencao); }

/* Menu de acao da linha: `<details>` nativo, sem JavaScript. */
.celula-acoes { width: 1%; padding-left: 0; }
.menu-da-linha { position: relative; display: inline-block; }
.menu-da-linha > summary {
  list-style: none; cursor: pointer; padding: var(--esp-2) var(--esp-6); border-radius: var(--raio-miudo);
  color: var(--ink-3); line-height: 1;
  /* #306: alvo de clique >= 24x24 (WCAG 2.5.8). Media 27x19; a altura vinha
     só do texto. `inline-flex` centraliza o ⋯ na caixa maior sem mexer na
     altura da linha (a célula já tem mais de 24px). */
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 24px; min-height: 24px; box-sizing: border-box;
}
.menu-da-linha > summary::-webkit-details-marker { display: none; }
.menu-da-linha > summary:hover { background: var(--page); color: var(--ink); }
.menu-itens {
  position: absolute; right: 0; top: 100%; z-index: 20; min-width: 150px;
  padding: var(--esp-4); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--raio);
  box-shadow: var(--sombra-menu);
}
.menu-itens button {
  display: block; width: 100%; height: 30px; padding: 0 var(--esp-10); border: 0; font-weight: var(--peso-normal);
  background: transparent; color: var(--ink); text-align: left; font-size: var(--corpo-nota);
}
.menu-itens button:hover { background: var(--azul-fraco); }
.menu-itens .menu-perigo { color: var(--erro); }
.menu-itens .menu-perigo:hover { background: var(--erro-fraco); }

/* Barra de ferramentas dentro do card da lista.
   A barra e o quadro de rolagem sao IRMAOS, e nao aninhados num wrapper: com
   um `<div>` a mais em volta do `.rolagem-horizontal`, a pagina passava a
   rolar 114px para o lado numa tela de 390px (medido) -- o quadro deixava de
   conter a tabela. O cartao aqui e costurado pelo CSS: topo arredondado na
   barra, base arredondada na tabela, mesma sombra. */
.barra-da-lista {
  background: var(--surface);
  border-radius: var(--raio) var(--raio) 0 0;
  box-shadow: var(--sombra);
  display: flex; align-items: center; gap: var(--esp-16); flex-wrap: wrap;
  padding: var(--esp-12) var(--esp-14); border-bottom: 1px solid var(--line);
}
/* #284: a barra dentro do cartão da fatura -- o cartão já é a moldura. */
.cartao > .barra-da-lista { box-shadow: none; }
.contagem-da-lista { font-size: var(--corpo); font-weight: var(--peso-forte); }
.localizar input { height: 28px; min-width: 200px; }
.totais-da-lista { display: flex; gap: var(--esp-14); font-size: var(--corpo-nota); }
.acoes-da-lista { margin-left: auto; display: flex; align-items: center; gap: var(--esp-14); font-size: var(--corpo-nota); }
.acoes-da-lista a, .ligacao {
  color: var(--azul); text-decoration: none; background: none; border: 0;
  height: auto; padding: 0; font: inherit; cursor: pointer;
}
.acoes-da-lista a:hover, .ligacao:hover { text-decoration: underline; background: none; }
/* #98/B4: qual das ordens está valendo. Peso e tinta normal (não a cor de
   ação): um link que descreve o ESTADO atual não é um convite a clicar, e
   pintá-lo de azul junto dos outros dois faria três convites iguais para
   três coisas diferentes. `--tinta` tem contraste medido no #42. */
/* #275: os dois menus da barra (Ordem e ⋯). O gatilho parece o link que ele
   substitui (mesma cor de ação, mesmo corpo); o painel é o `.menu-itens` da
   linha -- mesma função, mesmo componente (diretriz 6). */
.menu-da-barra { position: relative; display: inline-block; }
.menu-da-barra > summary {
  list-style: none; cursor: pointer; color: var(--azul); font-size: var(--corpo-nota);
  padding: var(--esp-2) var(--esp-4); border-radius: var(--raio-miudo); white-space: nowrap;
}
.menu-da-barra > summary::-webkit-details-marker { display: none; }
.menu-da-barra > summary:hover { text-decoration: underline; }
.menu-da-barra > summary:focus-visible { outline: 2px solid var(--azul); outline-offset: 1px; }
.menu-mais > summary { font-size: var(--corpo); line-height: 1; padding: 0 var(--esp-6); }
.menu-da-barra .menu-itens { min-width: 190px; }
.menu-da-barra .menu-itens a[aria-current="true"] { color: var(--ink); font-weight: var(--peso-forte); }
.menu-da-barra .menu-itens a[aria-current="true"]::after { content: " ✓"; color: var(--ink-3); }
/* A tabela completa o cartao: sem raio no topo, que a barra ja fez. */
.tabela { border-radius: 0 0 var(--raio) var(--raio); }

/* -------------------------------------------------- Pagamento parcial --- */

/* Terceira situação, e por isso terceira cor. Reaproveitar o âmbar de "Em
   aberto" com outro texto obrigaria a LER a etiqueta para distinguir as duas,
   e a coluna de situação existe justamente para ser varrida sem leitura. Azul
   porque é a cor de ação do sistema: parcial é um título em andamento, não um
   alerta. */
.marca-parcial { background: var(--azul-fraco); color: var(--azul-escuro); }
/* #274: o vencido em aberto diz há quantos dias. Vermelho é a cor de estado
   do "faltou" no sistema (--erro = --vermelho desde o #169); o par
   tinta/fundo é o mesmo já medido para `.negativo` sobre `--vermelho-fraco`. */
.marca-vencido { background: var(--erro-fraco); color: var(--erro); }

/* #274 -- A BAIXA NO CHIP DE SITUAÇÃO. Mesma receita do menu da linha
   (`<details>` + caixa `position: absolute`): o chip é a penúltima coluna,
   então a caixa abre ANCORADA À DIREITA (`right: 0`), senão sairia pela
   borda do cartão. Acima de 900px o quadro da tabela não recorta (decisão
   travada: sem `overflow-x: auto` ali), e é nessa largura que a caixa é
   medida pela prova de navegador. */
.celula-situacao { white-space: nowrap; }
.baixa-no-chip { position: relative; display: inline-block; }
.baixa-no-chip > summary { list-style: none; cursor: pointer; display: inline-block; border-radius: 999px; }
.baixa-no-chip > summary::-webkit-details-marker { display: none; }
.baixa-no-chip > summary:hover .marca,
.baixa-no-chip[open] > summary .marca { box-shadow: 0 0 0 2px var(--azul-fraco); }
.baixa-no-chip > summary:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }
.baixa-corpo {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 20; width: 272px;
  display: flex; flex-direction: column; gap: var(--esp-8);
  padding: var(--esp-12); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--raio);
  box-shadow: var(--sombra-menu);
  text-align: left; white-space: normal; font-size: var(--corpo-miudo);
  font-weight: var(--peso-normal); letter-spacing: 0;
}
.baixa-corpo.baixa-carregando { color: var(--ink-3); font-size: var(--corpo-nota); }
.baixa-titulo {
  margin: 0; font-weight: var(--peso-medio); color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.baixa-titulo .ponto-tipo { margin-right: var(--esp-4); }
.baixa-fato { margin: 0; color: var(--ink); }
.baixa-corpo .miudo { color: var(--ink-3); font-size: var(--corpo-nota); }
/* Quando a linha está no pé da janela a caixa abre PARA CIMA (`lista-41.js`
   mede e põe a classe): medido em 1366×768, a caixa de 272×~270 aberta numa
   linha a 576px do topo saía 120px por baixo, com o botão Pagar fora da tela. */
.baixa-no-chip.para-cima .baixa-corpo { top: auto; bottom: calc(100% + 4px); }
.baixa-campos { display: flex; gap: var(--esp-8); }
.baixa-campos > label { flex: 1 1 0; min-width: 0; }
.baixa-corpo label { display: flex; flex-direction: column; gap: 3px; font-size: var(--corpo-nota); color: var(--ink-3); }
.baixa-corpo input, .baixa-corpo select { width: 100%; font-size: var(--corpo-miudo); color: var(--ink); }
.baixa-corpo input[name="valor"] { text-align: right; font-variant-numeric: tabular-nums; }
.baixa-corpo .btn { align-self: flex-start; }
/* #295: o Dar baixa é a única ação da caixa -- ocupa a largura toda e tem a
   altura do `.btn` cheio (36px), centrado; o Estornar da cara "pago" segue
   mini. */
.baixa-corpo [data-pagar] { align-self: stretch; justify-content: center; margin-top: var(--esp-4); }
.baixa-corpo .erro-campo { margin: 0; }
/* O chip do tipo (Pago/Recebido) segue o vocabulário por tipo do modal (#88):
   um span de cada vez, decidido pelo `data-tipo` da linha. */
.baixa-corpo .rotulo-receita { display: none; }
tr[data-tipo="RECEITA"] .baixa-corpo .rotulo-despesa { display: none; }
tr[data-tipo="RECEITA"] .baixa-corpo .rotulo-receita { display: inline; }

/* O link do menu tem que parecer os botões vizinhos: no menu, "Pagar parcial"
   e "Duplicar" são a mesma coisa para quem clica, e um sublinhado azul no
   meio de dois itens neutros diria que é outra categoria de ação. */
.menu-itens a {
  display: block; width: 100%; padding: 0 var(--esp-10); line-height: 30px;
  color: var(--ink); text-align: left; font-size: var(--corpo-nota); text-decoration: none;
}
.menu-itens a:hover { background: var(--azul-fraco); }

.cartao-kpi-estreito {
  max-width: 460px; gap: var(--esp-16); padding: var(--esp-24);
  border-left: 1px solid var(--line); box-shadow: var(--sombra);
}
.cartao-kpi-estreito:hover { background: var(--surface); }

.titulo-em-baixa { display: flex; align-items: center; gap: var(--esp-8); flex-wrap: wrap; }
.titulo-em-baixa .miudo { color: var(--ink-3); font-size: var(--corpo-nota); }

/* O saldo é o número que a decisão depende; ele manda na tela. */
.saldo-em-aberto {
  display: flex; align-items: baseline; gap: var(--esp-8); flex-wrap: wrap;
  padding: var(--esp-12) 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.saldo-em-aberto .rotulo { font-size: var(--corpo-nota); color: var(--ink-3); }
.saldo-em-aberto .valor {
  font-family: "Cifra", system-ui, sans-serif; font-weight: var(--peso-forte); font-size: 24px;
  font-variant-numeric: tabular-nums;
}
.saldo-em-aberto .miudo { font-size: var(--corpo-nota); color: var(--ink-3); }

.formulario-de-baixa { display: flex; flex-direction: column; gap: var(--esp-12); }
.formulario-de-baixa label {
  display: flex; flex-direction: column; gap: var(--esp-4);
  font-size: var(--corpo-nota); color: var(--ink-3);
}
.formulario-de-baixa input, .formulario-de-baixa select {
  height: 34px; font-size: 14px; color: var(--ink);
}
.acoes-do-formulario { display: flex; align-items: center; gap: var(--esp-12); margin-top: var(--esp-4); }

.nota { font-size: var(--corpo-nota); color: var(--ink-3); margin: 0; }

.baixas-anteriores h2 { font-size: var(--corpo-nota); color: var(--ink-3); margin: 0 0 var(--esp-6); }
.baixas-anteriores ul { list-style: none; margin: 0; padding: 0; }
.baixas-anteriores li {
  display: flex; align-items: baseline; gap: var(--esp-12); padding: var(--esp-4) 0;
  border-top: 1px solid var(--line); font-size: var(--corpo-miudo);
}
.baixas-anteriores .valor { font-variant-numeric: tabular-nums; margin-left: auto; }
.baixas-anteriores .miudo { color: var(--ink-3); font-size: var(--corpo-nota); }

/* ------------------------------------------------- Editar lançamento ---- */

/* A descrição vira link sem virar azul: numa tabela de cinquenta linhas,
   cinquenta links azuis sublinhados apagam a hierarquia da tela inteira. O
   sublinhado aparece no hover, que é quando a pergunta "isso clica?" é
   feita. */
.ligacao-da-linha { color: inherit; text-decoration: none; }
.ligacao-da-linha:hover { color: var(--azul); text-decoration: underline; }

.cartao-kpi-formulario {
  max-width: 720px; gap: var(--esp-16); padding: var(--esp-24);
  border-left: 1px solid var(--line); box-shadow: var(--sombra);
}
.cartao-kpi-formulario:hover { background: var(--surface); }

.formulario-de-edicao { display: flex; flex-direction: column; gap: var(--esp-14); }
.formulario-de-edicao label {
  display: flex; flex-direction: column; gap: var(--esp-4);
  font-size: var(--corpo-nota); color: var(--ink-3);
}
.formulario-de-edicao input, .formulario-de-edicao select {
  height: 34px; font-size: 14px; color: var(--ink);
}
.campos-lado-a-lado { display: flex; gap: var(--esp-12); flex-wrap: wrap; }
/* `min-width: 0` não é enfeite: o padrão de um item flex é `min-width: auto`,
   que o proíbe de encolher abaixo do próprio conteúdo mínimo -- e o conteúdo
   mínimo de um `<input>` é a largura padrão dele, perto de 220px. Com três
   campos de data numa faixa de 672px isso bastava para o terceiro quebrar
   linha sozinho, apesar de 3 × 150px caberem folgados. */
.campos-lado-a-lado > label { flex: 1 1 150px; min-width: 0; }
.campos-lado-a-lado > .cresce { flex: 1 1 180px; min-width: 0; }
/* O valor alinhado à direita e tabular: é assim que ele aparece na lista, e
   o campo que se confere de volta tem que ter a mesma forma do número que se
   veio conferir. */
.campos-lado-a-lado > .campo-valor { flex: 0 0 140px; min-width: 0; }
.campos-lado-a-lado > .campo-valor input { text-align: right; font-variant-numeric: tabular-nums; }

/* #289: o `.grupo-de-radio` (e o `.radio` dele) morreu -- nenhum template o
   usa. O `.rotulo-do-grupo` das tags vive por conta própria, abaixo. */
.rotulo-do-grupo { font-size: var(--corpo-nota); color: var(--ink-3); }

.escopo-na-edicao {
  display: flex; flex-direction: column; gap: var(--esp-6);
  padding: var(--esp-12); background: var(--azul-fraco); border-radius: var(--raio);
}
.escopo-na-edicao .nota { color: var(--azul-escuro); }

.avisos { margin-bottom: var(--esp-16); }
.aviso {
  margin: 0; padding: var(--esp-10) var(--esp-14); font-size: var(--corpo-miudo);
  background: var(--sucesso-fraco); color: var(--sucesso);
  border-radius: var(--raio); border-left: 3px solid var(--sucesso);
}
/* #287: o nível da mensagem (`messages.error/warning/info`) tem cor própria --
   as mesmas três famílias de estado do sistema (`--erro`, `--atencao`,
   `--azul`), cada par fraco/forte já medido no #142 sobre o próprio fundo. */
.aviso-error   { background: var(--erro-fraco);    color: var(--erro);    border-left-color: var(--erro); }
.aviso-warning { background: var(--atencao-fraco); color: var(--atencao); border-left-color: var(--atencao); }
.aviso-info    { background: var(--azul-fraco);    color: var(--azul);    border-left-color: var(--azul); }
.avisos .aviso + .aviso { margin-top: var(--esp-6); }

/* #288: sinal de que um envio (anexo, extrato OFX) está em curso -- a classe
   `enviando` entra no form no `onchange`, antes do POST partir. Enquanto a
   prévia da fusão recarrega (`hx-indicator`), ela esmaece. */
.aviso-de-envio { display: none; font-size: var(--corpo-miudo); color: var(--ink-3); }
.enviando .aviso-de-envio { display: inline-block; margin-top: var(--esp-6); }
.enviando .btn { pointer-events: none; opacity: .6; }
#previa-fusao.htmx-request { opacity: .55; cursor: progress; }
.painel-carregando { padding: var(--esp-16); }

/* #291: a linha do teto do grupo "Depois" no A pagar -- respiro maior que a
   linha de grupo vazio, porque ela carrega um link. */
.ap-teto td { padding-top: var(--esp-12); padding-bottom: var(--esp-12); }

/* ------------------------------------------------------------ Anexos --- */

/* O clipe herda a cor fraca do texto ao lado: ele é um sinal, não uma
   chamada. Vira azul no hover, que é quando a pergunta "isso abre?" é
   feita. */
.marca-anexo {
  display: inline-flex; align-items: center; gap: 1px; margin-left: var(--esp-6);
  color: var(--ink-3); text-decoration: none; vertical-align: -2px;
}
.marca-anexo:hover { color: var(--azul); }
.marca-anexo .quantos { font-size: var(--corpo-micro); font-variant-numeric: tabular-nums; }

/* ⭐ #100 — A COLUNA DE SINAIS (v3).
   Os sinais deixaram de morar ao lado do nome e ganharam coluna própria. O
   argumento contrário do #79 ("uma coluna quase toda vazia custa mais espaço
   do que informa") valia para UM sinal; medido em produção com os cinco:
   98,0% das linhas do recorte padrão têm algum sinal, 88,0% no total da
   empresa. Vazia em 2% do que o dono abre.

   `white-space: nowrap` e não quebra: os sinais são uma fileira, e uma fileira
   que quebra em duas linhas muda a altura da linha da tabela -- que é o que a
   densidade alta (diretriz 4) não pode perder.
   Sem largura fixa: quem manda é o conteúdo, e a medição da largura já provou
   que a tabela inteira cabe em 1248px úteis com esta coluna. */
.col-sinais { white-space: nowrap; }
.col-sinais > * + * { margin-left: var(--esp-6); }
/* A primeira marca não herda o `margin-left: 6px` de `.marca-anexo`, que
   existia para separá-la do NOME -- aqui não há nome à esquerda. */
.col-sinais .marca-anexo { margin-left: 0; }

/* Conciliado: verde, porque é confirmação -- a mesma cor que o sistema usa
   para "deu certo" em toda etiqueta. A dica diz QUANDO e por QUAL extrato;
   o ícone sozinho repetiria o próprio nome. */
.marca-conciliado {
  display: inline-flex; align-items: center;
  color: var(--verde); font-weight: var(--peso-forte); vertical-align: -1px;
}

/* Anexo PERDIDO: o MESMO clipe, em vermelho. "Sem anexo" e "anexo que sumiu"
   são estados diferentes e precisam ser distinguíveis -- mas por FORMA e
   posição, não só por cor: ele é o único clipe que aparece sem ser link,
   e o `title`/texto oculto dizem o que é. Cor sozinha não informa quem não
   distingue vermelho de cinza. */
.marca-anexo-perdido {
  display: inline-flex; align-items: center;
  color: var(--vermelho); vertical-align: -2px;
}

/* Transferência: AZUL, nunca verde nem vermelho. Não é receita nem despesa --
   é dinheiro andando entre contas próprias, e pintá-lo com a cor de um dos
   dois faria a linha mentir sobre o que aconteceu. */
.marca-transferencia {
  display: inline-flex; align-items: center;
  color: var(--azul); vertical-align: -1px;
}

/* Legenda ao pé da tabela: ícone sem legenda é adivinhação, e o custo dela é
   uma linha (v3). Peso de contexto, nunca de dado. */
.legenda-sinais {
  display: flex; flex-wrap: wrap; gap: var(--esp-4) var(--esp-16);
  margin-top: var(--esp-10); font-size: var(--corpo-rotulo); color: var(--ink-3);
}
.legenda-sinais span { display: inline-flex; align-items: center; gap: 5px; }

/* Os arquivos são o que se clica aqui, mas dez linhas azuis sublinhadas
   pesam mais que o formulário inteiro acima delas. Sublinhado no hover, e
   `:visited` normalizado -- o roxo padrão do navegador é a única cor da tela
   que não sai da paleta. */
.anexos a { color: var(--azul); text-decoration: none; }
.anexos a:visited { color: var(--azul); }
.anexos a:hover { text-decoration: underline; }

.anexos { border-top: 1px solid var(--line); padding-top: var(--esp-12); }
.anexos h2 { font-size: var(--corpo-nota); color: var(--ink-3); margin: 0 0 var(--esp-6); }
.anexos ul { list-style: none; margin: 0; padding: 0; }
.anexos li {
  display: flex; align-items: baseline; gap: var(--esp-8); flex-wrap: wrap;
  padding: var(--esp-4) 0; font-size: var(--corpo-miudo);
}
.anexos .miudo { font-size: var(--corpo-mini); color: var(--ink-3); }
.anexos .pendente { color: var(--ink-3); }

/* #188: o painel lateral lista os mesmos anexos sem o container `.anexos`
   (o desenho dele é outro -- marcador, e não a lista chapada do formulário).
   Sem estes dois seletores, "não baixado" sairia com a cor do texto normal e
   se leria como parte do nome do arquivo. */
.painel-lancamento .miudo { font-size: var(--corpo-mini); color: var(--ink-3); }
.painel-lancamento .pendente { color: var(--ink-3); }

/* ------------------------------------------------------ Tela de entrada -- */

/* A única tela do sistema sem barra superior, sem empresa e sem menu -- e por
   isso a única centrada. Aqui não há nada para navegar: há uma coisa para
   fazer, e ela fica no meio. */
.tela-de-entrada {
  display: flex; align-items: center; justify-content: center;
  min-height: 100vh; padding: var(--esp-24); background: var(--page);
}
.caixa-de-entrada {
  width: 100%; max-width: 340px; padding: 32px;
  background: var(--surface); border-radius: var(--raio);
  box-shadow: var(--sombra-caixa);
}
.caixa-de-entrada h1 { margin: 0 0 20px; font-size: 22px; }
.caixa-de-entrada .erro { margin: 0 0 var(--esp-16); }

.formulario-de-entrada { display: flex; flex-direction: column; gap: var(--esp-14); }
.formulario-de-entrada label {
  display: flex; flex-direction: column; gap: var(--esp-4);
  font-size: var(--corpo-nota); color: var(--ink-3);
}
.formulario-de-entrada input { height: 36px; font-size: 14px; color: var(--ink); }
.formulario-de-entrada button { margin-top: var(--esp-4); height: 36px; }

/* Conta e saída na barra superior. Segue o mesmo desenho do "Trocar" ao lado
   -- são vizinhos, e dois estilos de submenu lado a lado leriam como dois
   tipos diferentes de controle. */
.conta-do-usuario .submenu form { margin: 0; }
.conta-do-usuario .submenu button {
  display: block; width: 100%; padding: var(--esp-6) var(--esp-12); border: 0; font-weight: var(--peso-normal);
  background: transparent; color: inherit; text-align: left; font-size: var(--corpo-miudo);
}

/* ------------------------------------------------------- Ação em lote --- */

/* Escondida por padrão; aparece quando alguma caixa da lista está marcada.
   `:has()` faz isso sem uma linha de JavaScript -- a condição é o estado
   real do formulário, não uma cópia dele mantida à mão. */
.barra-de-lote { display: none; }
/* ⭐ #100: A BARRA DE LOTE VIVE NO RODAPÉ, GRUDADA — não acima da lista.
   Motivo da referência v3, e ele é operacional, não estético: as linhas se
   escolhem ROLANDO, e com a barra em cima a ação fica fora da vista
   justamente quando se terminou de escolher. Grudada embaixo, ela está onde
   o olho já está.
   Não rouba altura permanente porque continua saindo do fluxo enquanto não
   há seleção (`display: none` acima) -- a condição segue sendo o estado real
   do formulário, via `:has()`, sem cópia mantida à mão.
   No DOM ela mudou de posição DENTRO do mesmo `<form class="acao-lote">`:
   nenhum campo trocou de dono, e o vínculo `form=` dos campos externos não
   foi tocado (é o ponto que já produziu um POST sem `selecionados`, em
   silêncio, e por isso está escrito aqui). */
.acao-lote:has(input[name="selecionados"]:checked) .barra-de-lote {
  display: flex; align-items: center; gap: var(--esp-12);
  position: sticky; bottom: 0; z-index: 4;
  margin-top: var(--esp-12); padding: var(--esp-10);
  background: var(--surface);
  border-top: 1px solid var(--line);
}

/* Envio de anexo. Na mesma linha do resto do bloco: o campo de arquivo é
   largo por natureza e empurrar o botão para baixo dele criaria uma terceira
   coluna de leitura numa caixa que já tem duas. */
.enviar-anexo {
  display: flex; align-items: flex-end; gap: var(--esp-12); flex-wrap: wrap;
  margin-top: var(--esp-12); padding-top: var(--esp-12); border-top: 1px solid var(--line);
}
.enviar-anexo label {
  display: flex; flex-direction: column; gap: var(--esp-4); flex: 1 1 220px;
  min-width: 0; font-size: var(--corpo-nota); color: var(--ink-3);
}
.enviar-anexo input[type="file"] { font-size: var(--corpo-nota); color: var(--ink); }
/* "Remover" fica NEUTRO até o hover. Num lançamento com dez anexos, dez
   palavras vermelhas empilhadas viram uma coluna de alarme sobre uma lista
   que não tem nada de errado -- e o vermelho, gasto assim, para de significar
   perigo onde ele de fato existe. O aviso de verdade está no confirm(). */
.anexos li .menu-perigo {
  padding: 0; font-size: var(--corpo-mini); color: var(--ink-3); background: transparent;
}
.anexos li .menu-perigo:hover { color: var(--erro); text-decoration: underline; }

/* Direção da transferência: as duas contas na mesma linha, com a seta entre
   elas. Empilhadas, com rótulos parecidos, "de" e "para" trocam de lugar na
   leitura -- e é a única informação da tela que não pode ser lida errada. */
.direcao-da-transferencia {
  display: flex; align-items: flex-end; gap: var(--esp-10); flex-wrap: wrap;
}
.direcao-da-transferencia > .cresce { flex: 1 1 140px; min-width: 0; }
.seta-da-transferencia {
  padding-bottom: var(--esp-8); font-size: 18px; color: var(--ink-3);
}

/* ------------------------------------------- Análise: abrir a fatia ----- */
/* (#172: as gavetas antigas — .gaveta-da-fatia, .gaveta-de-lancamentos,
   .tabela-subcategorias, .linha-da-gaveta — morreram com o redesenho da
   árvore; a lista de lançamentos que o htmx injeta continua a mesma.) */

.lancamentos-da-fatia { list-style: none; margin: var(--esp-4) 0; padding: 0 0 0 var(--esp-12); }
.lancamentos-da-fatia li {
  display: flex; align-items: baseline; gap: var(--esp-10);
  padding: 3px 0; font-size: var(--corpo-nota); border-bottom: 1px solid var(--line);
}
.lancamentos-da-fatia .data { flex: 0 0 74px; color: var(--ink-3); }
.lancamentos-da-fatia .descricao {
  flex: 1 1 auto; min-width: 0; color: inherit; text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lancamentos-da-fatia .descricao:hover { color: var(--azul); text-decoration: underline; }
.lancamentos-da-fatia .conta { flex: 0 0 auto; }
.lancamentos-da-fatia .valor { flex: 0 0 auto; font-variant-numeric: tabular-nums; }

/* ===== Tela de categorias (classificacao para o DRE) ===== */
.cat-tela { max-width: 1100px; }
.cat-busca {
  height: var(--linha); min-width: 220px; padding: 0 .6rem;
  border: 1px solid var(--line); border-radius: var(--raio-miudo);
  background: var(--surface); color: var(--ink);
}

.cat-progresso { margin: .25rem 0 1rem; }
.cat-barra {
  height: 10px; background: var(--azul-fraco); border-radius: 999px; overflow: hidden;
  border: 1px solid var(--line);
}
/* #168: aqui havia `linear-gradient(90deg, var(--acao-clara), var(--azul))`,
   e as DUAS pontas resolviam para #2563eb -- o gradiente ja renderizava chapado.
   Nasceu no #57-B: `--acao-clara` era um azul vibrante proprio (#1550e5) e, ao
   unificar os tres azuis na familia do --azul, as pontas encostaram uma na
   outra. O comentario da linha 32 ("so no gradiente da barra de progresso")
   sobreviveu descrevendo um gradiente que ja nao existia.
   Trocado por cor solida: e exatamente o que a tela pinta hoje, com menos
   codigo. Se a barra dever voltar a ter degrade, isso e escolha de cor -- e
   cor e decisao do dono (#142), nao efeito colateral de limpeza. */
.cat-barra-cheia {
  height: 100%; background: var(--azul);
  transition: width .3s ease;
}
.cat-progresso-texto { margin: .35rem 0 0; color: var(--ink-3); font-size: .9rem; }
.cat-progresso-texto strong { color: var(--ink); }
.cat-fora-total { color: var(--atencao); }

.cat-legenda { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; margin: 0 0 .75rem; font-size: .82rem; }
/* #70 (Tarefa 6): .cat-chip / .cat-chip-ok / -pendente / -fora saíram daqui --
   viraram .etiqueta / .etiqueta.ok / .etiqueta.falta na fundação (grep em
   templates/ deu zero usos das quatro antes de apagar). */
.cat-dica { color: var(--ink-3); margin-left: auto; }

.cat-abas { display: flex; gap: .25rem; border-bottom: 1px solid var(--line); margin-bottom: .5rem; }
.cat-aba {
  border: none; background: none; padding: .5rem .9rem; cursor: pointer;
  color: var(--ink-3); border-bottom: 2px solid transparent; font-size: .95rem;
}
.cat-aba.ativa { color: var(--azul); border-bottom-color: var(--azul); font-weight: var(--peso-forte); }
.cat-aba-conta { color: var(--ink-3); font-size: .8rem; }

.cat-sem-resultado { padding: 1rem; color: var(--ink-3); }

.cat-raizes, .cat-filhos { list-style: none; margin: 0; padding: 0; }
.cat-no { border-bottom: 1px solid var(--page); }
.cat-linha {
  display: flex; align-items: center; gap: .5rem; min-height: var(--linha);
  padding: .15rem .3rem .15rem calc(.3rem + var(--nivel, 0) * 18px);
  border-left: 3px solid transparent;
}
.cat-linha:hover { background: var(--azul-fraco); }
/* Fundo NEUTRO por padrao: tudo comeca sem linha, entao pintar pendencia
   acenderia a tela inteira. So o que pesa e esta sem linha recebe destaque. */
.cat-ok > .cat-linha { border-left-color: var(--sucesso); }
.cat-fora > .cat-linha { border-left-color: var(--ink-3); opacity: .72; }
.cat-atencao > .cat-linha { border-left-color: var(--atencao); background: var(--atencao-realce); }
.cat-atencao > .cat-linha .cat-movimento { color: var(--atencao); font-weight: var(--peso-forte); }

.cat-toggle {
  border: none; background: none; cursor: pointer; color: var(--ink-3);
  width: 1.2rem; padding: 0; font-size: .8rem; line-height: 1;
}
.cat-toggle-vazio { width: 1.2rem; display: inline-block; }
.cat-nome { flex: 1 1 auto; min-width: 8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Largura FIXA e tabular para o olho comparar magnitude coluna abaixo:
   "R$ 0,00" e "R$ 75.959.128,98" alinham a virgula na mesma posicao. */
.cat-movimento {
  flex: 0 0 auto; width: 11rem; text-align: right; color: var(--ink-3);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.cat-destino { flex: 0 0 auto; display: flex; align-items: center; gap: .4rem; }
.cat-pendente-total { color: var(--atencao); }

.cat-grupo-controle { display: inline-flex; align-items: center; gap: .35rem; }
.cat-select-grupo {
  height: 26px; max-width: 15rem; border: 1px solid var(--line);
  border-radius: var(--raio-miudo); background: var(--surface); color: var(--ink);
}
.cat-pendente .cat-select-grupo { border-color: var(--atencao); }
.cat-herda { color: var(--sucesso); font-size: .82rem; font-style: italic; }
.cat-definir {
  height: auto; padding: 1px var(--esp-8); font-size: .78rem; background: none;
  color: var(--azul); border: 1px solid var(--line); border-radius: 999px;
}
.cat-definir:hover { background: var(--azul-fraco); }
.cat-fora-toggle { color: var(--ink-3); font-size: .82rem; white-space: nowrap; cursor: pointer; }
/* #287: em 390px a linha da categoria (nome + valor + select + fora do DRE +
   editar/excluir) media 705px e estourava a página. Abaixo de 760px o
   destino desce para uma segunda fileira, alinhado ao nome. */
@media (max-width: 760px) {
  .cat-linha { flex-wrap: wrap; }
  .cat-destino { flex: 1 1 100%; flex-wrap: wrap; }
}

.cat-tag { font-size: .82rem; padding: .05rem .45rem; border-radius: 999px; background: var(--page); color: var(--ink-3); }
.cat-tag-fora em { font-style: normal; opacity: .8; }

.cat-status { font-size: .8rem; min-width: 1rem; }
.cat-status-erro { color: var(--erro); font-weight: var(--peso-forte); }
.htmx-request.cat-status::after, .htmx-request .cat-status::after { content: "…"; color: var(--ink-3); }

/* Link estilizado como acao primaria (o <a> "+ Nova categoria" no cabecalho). */
.cat-editar { color: var(--ink-3); font-size: .8rem; text-decoration: none; }
.cat-editar:hover { color: var(--azul); text-decoration: underline; }

/* Tela de resultado da conciliação (#53). Três colunas com o estado no meio —
   o desenho do Controlle, que é bom: o olho compara banco e sistema na mesma
   linha e o estado fica onde a decisão é tomada. */
.barra-lote {
  position: sticky; top: 0; z-index: 5;
  display: flex; flex-wrap: wrap; gap: var(--esp-8); align-items: center;
  background: var(--surface); border-bottom: 1px solid var(--line);
  padding: var(--esp-10) 0; margin-bottom: var(--esp-10);
}
.barra-espaco { margin-left: auto; }
/* #231: o `<select>` de categoria esticava e empurrava o botão da ação primária
   para uma segunda linha da barra -- com o "Aceitar N sugestões" ao lado ficou
   pior. 260px cabem os nomes de categoria mais longos da Link ce sem quebrar a
   barra em 1366px. */
.barra-lote select { max-width: 260px; }
.filtro-linhas { display: flex; gap: var(--esp-8); margin-bottom: var(--esp-10); }

/* #258 -- ABAS POR ESTADO. Elas herdam o vocabulário do `.segmentado` (o
   "escolha um entre N" da casa, componentes.css): mesma moldura, mesma
   divisória, mesmo azul-fraco no escolhido. Um controle novo com desenho
   próprio ensinaria uma segunda gramática para dizer a mesma coisa.

   A diferença é o CONTADOR, e ele é o argumento da aba: diz quanto há antes
   do clique, como o "Aceitar N sugestões" do #231. Fica em `tabular-nums`
   porque o número muda ao aplicar e o rótulo não pode dançar.

   Aba de contador zero vem `disabled` do servidor -- clicar levaria a uma
   tabela vazia, e o vazio precisaria de uma frase para se explicar. */
.abas-de-estado { display: inline-flex; border: 1px solid var(--linha-campo); border-radius: var(--raio); overflow: hidden; }
.abas-de-estado .aba {
  display: inline-flex; align-items: center; gap: var(--esp-6);
  padding: 7px var(--esp-14); font-size: var(--corpo-miudo); color: var(--ink-2);
  background: none; border: none; border-left: 1px solid var(--line); cursor: pointer;
}
.abas-de-estado .aba:first-child { border-left: none; }
.abas-de-estado .aba:hover:not(:disabled) { background: var(--line-2); }
.abas-de-estado .aba[aria-selected="true"] { background: var(--azul-fraco); color: var(--azul); font-weight: var(--peso-forte); }
.abas-de-estado .aba:focus-visible { outline: 2px solid var(--azul); outline-offset: -2px; }
.abas-de-estado .aba:disabled { color: var(--ink-3); cursor: not-allowed; }
.aba-contador { font-variant-numeric: tabular-nums; color: var(--ink-3); }
.abas-de-estado .aba[aria-selected="true"] .aba-contador { color: inherit; }

.filtro-linhas input { flex: 1 1 180px; min-width: 0; }
/* #258: as abas não esticam -- elas têm a largura do seu texto, e são os campos
   de filtro que tomam a sobra. */
.filtro-linhas .abas-de-estado { flex: 0 0 auto; }

/* 🔴 #229 -- `display: flex` NUM `<td>` DESTRÓI A CÉLULA DE TABELA, e foi isso
   que empilhou as três colunas uma embaixo da outra em toda a tela de
   resultado. O elemento deixa de ser `table-cell`, o navegador gera célula
   anônima e a linha perde o alinhamento em coluna -- o `<thead>` continuava em
   colunas (o `th` não tinha a regra), o que fazia a tela parecer "quase certa"
   e escondia a causa. O empilhamento era o desejado DENTRO da célula (data,
   valor, descrição), e é o que a `.pilha-celula` faz agora, sem tocar no
   modelo de tabela. NÃO devolver `display: flex` ao `td`.
   Medido no navegador (#229): antes, as três células nasciam em x=113 nas três
   linhas; depois, em x=113 / x=624 / x=880, na mesma linha. */
/* #293: TENTADO e REVERTIDO na mesma rodada -- fazer esta tabela herdar
   `.tabela` (componentes.css). A base traz `nowrap`, altura de 48px,
   `box-sizing: border-box` e cabeçalho em caixa alta, e as fotos mostraram o
   preço: a caixa de seleção invadindo a data, a descrição do banco em três
   linhas (perdeu a reticência) e "CATEGORIA E DIVERGÊNCIAS" quebrando em
   duas. O que a herança traria de bom -- cabeçalho grudado e hover de linha
   -- entra por duas regras próprias, logo abaixo, sem mexer no desenho
   medido do #229/#249. */
.tabela-conciliacao { width: 100%; border-collapse: collapse; table-layout: fixed; }
.tabela-conciliacao thead th { position: sticky; top: 0; z-index: 3; background: var(--surface); }
.tabela-conciliacao tbody tr:hover td { background: var(--linha-hover); }
.tabela-conciliacao th { text-align: left; font-size: var(--corpo-nota); color: var(--ink-3);
  padding: var(--esp-6) var(--esp-8); border-bottom: 1px solid var(--line); }
/* #252: o cabeçalho que ordena é um `<button>` -- alcançável por teclado --,
   com a aparência do rótulo que ele substituiu: nada de altura de botão nem de
   moldura numa linha que é cabeçalho de tabela. */
.tabela-conciliacao th .ordena {
  all: unset;
  cursor: pointer; font: inherit; color: inherit;
  display: inline-flex; align-items: center; gap: var(--esp-4);
}
.tabela-conciliacao th .ordena:hover { color: var(--ink); }
.tabela-conciliacao th .ordena:focus-visible {
  outline: 2px solid var(--azul); outline-offset: 2px; border-radius: var(--raio);
}
/* A SETA é o mesmo estado que o `aria-sort` carrega, para quem enxerga. Só a
   coluna ordenada tem seta: uma seta cinza em toda coluna vira ruído (R12). */
.tabela-conciliacao th[aria-sort] .ordena { color: var(--ink); font-weight: var(--peso-forte); }
.tabela-conciliacao th[aria-sort="ascending"] .ordena::after { content: "↑"; font-size: var(--corpo-mini); }
.tabela-conciliacao th[aria-sort="descending"] .ordena::after { content: "↓"; font-size: var(--corpo-mini); }
/* A coluna de dinheiro alinha à direita, e o cabeçalho dela também. */
.tabela-conciliacao th.col-valor .ordena { justify-content: flex-end; width: 100%; }
.tabela-conciliacao td { padding: var(--pad-linha) var(--esp-8); border-bottom: 1px solid var(--line-2);
  vertical-align: top; }
/* Teto por coluna (R40): a descrição do banco tem 57 caracteres na pior linha
   medida em produção, e sem teto ela empurra "No sistema" para fora da tela.
   Banco e sistema com o mesmo peso -- são os dois lados que se comparam; o
   estado fica no meio, estreito, porque só carrega etiqueta e motivo. */
/* ============ #249c: AS SETE COLUNAS, ditas pelo dono ============
 * ☐ · Data · No banco · Valor · Estado · No sistema · Categoria e divergências
 *
 * As duas colunas de TEXTO (banco e sistema) dividem o que sobra e têm o MESMO
 * peso: são os dois lados que se comparam, e comparar em colunas vizinhas é o
 * trabalho desta tela. Cada uma corta com reticências e leva o texto inteiro no
 * `title` -- teto por COLUNA, nunca rolagem horizontal (R40).
 *
 * `table-layout: fixed` faz o `<thead>` mandar na largura: a classe tem de
 * estar no `<th>` E no `<td>`, senão a regra da célula não tem efeito nenhum
 * (a lição do #229).
 */
/* MEDIDO NO NAVEGADOR (1248 px de tabela), e a medição mudou o desenho: com
 * `26%` em cada lado, "No banco" saía com **447 px** e "No sistema" com 239 --
 * os dois lados que se comparam, com pesos diferentes. A culpa era de um
 * `max-width: 0; min-width: 100%` que eu tinha posto no `<td>` para truncar:
 * dentro de `table-layout: fixed` ele atropela a largura declarada. Truncar em
 * célula de tabela fixa não precisa disso -- as três propriedades de overflow
 * bastam.
 *
 * As larguras fixas foram ajustadas ao que o conteúdo MEDIDO usa (sobra de
 * 21 px na caixa, 16 px em estado, sistema e classificação): o que se recupera
 * vai para as duas colunas de TEXTO, que é onde o conteúdo é longo. */
.tabela-conciliacao .col-escolha { width: 28px; }
.tabela-conciliacao .col-data { width: 88px; }
.tabela-conciliacao .col-banco { width: 27.7%; }
.tabela-conciliacao .col-valor { width: 116px; text-align: right; }
/* 132 px, e o número saiu da MEDIÇÃO, não do olho: com 112 a etiqueta e o
   "Desfazer" deixavam de caber lado a lado, quebravam em duas linhas e a linha
   inteira subia de 51 para 81 px. Trinta pixels a mais aqui valem mais que
   trinta a mais nas colunas de texto, que já cortam com reticências. */
.tabela-conciliacao .col-estado { width: 132px; }
.tabela-conciliacao .col-sistema { width: 27.7%; }
.tabela-conciliacao .col-classificacao { width: 188px; }
/* As colunas de texto cortam em vez de empurrar a tabela (R40: teto por
   coluna, nunca rolagem horizontal). */
.tabela-conciliacao .col-banco,
.tabela-conciliacao .col-sistema .linha-memo {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tabela-conciliacao .col-data { color: var(--ink-3); font-size: var(--corpo-nota); }

.pilha-celula { display: flex; flex-direction: column; gap: var(--esp-2); }
/* #229: o recorte do histórico por conta -- rótulo e campo na mesma linha, com
   o respiro do bloco. Mesmo desenho da busca de Cadastros (`.cadastro-busca`),
   que é o outro "filtro curto no topo de uma lista" do sistema. */
/* #230 -- EXTRATOS POR CONTA: o que falta subir, antes do que já entrou.
   Tabela densa e sem cor de fundo: quem chama a atenção é a ORDEM (o que falta
   está no topo) e o contador acima dela, não um realce por linha. Uma tela de
   trabalho não precisa de semáforo em toda linha para ser lida.
   Os três estados da prova reusam os MESMOS tokens da pílula da prévia (#70):
   mesma pergunta, mesma cor, em qualquer lugar do sistema. */
.tabela-extratos { width: 100%; border-collapse: collapse; margin-top: var(--esp-8); }
.tabela-extratos th { text-align: left; font-size: var(--corpo-nota); color: var(--ink-3);
  padding: var(--esp-6) var(--esp-8); border-bottom: 1px solid var(--line); }
.tabela-extratos td { padding: var(--esp-6) var(--esp-8);
  border-bottom: 1px solid var(--line-2); }
.tabela-extratos .linha-sem-extrato td:first-child { font-weight: var(--peso-forte); }
/* Sem largura, três colunas curtas numa tabela de 1280px abrem um vão morto
   entre a data e a prova -- o mesmo defeito que o #187 tirou da lista. A prova
   é DINHEIRO, então ela encosta na direita, como toda coluna de dinheiro do
   sistema (#98, item 5), e o vão vira alinhamento. */
.tabela-extratos .col-conta-nome { width: 45%; }
.tabela-extratos .col-extrato-ate { width: 20%; }
.tabela-extratos .col-prova { width: 35%; text-align: right; }
.sem-extrato { color: var(--ink-2); font-weight: var(--peso-forte); }
.prova-fecha { color: var(--verde); }
.prova-diverge { color: var(--amarelo); font-weight: var(--peso-forte); }
.prova-neutra { color: var(--ink-3); }

.filtro-historico { display: flex; align-items: center; gap: var(--esp-8);
  margin-bottom: var(--esp-10); }
.filtro-historico label { font-size: var(--corpo-nota); color: var(--ink-2); }
/* Com a coluna limitada, memo sem espaço (PROT. 000000000001946207) estouraria
   a célula em vez de quebrar. */
.tabela-conciliacao .linha-memo { overflow-wrap: anywhere; }
/* ===================== #249: A LINHA DO EXTRATO =====================
 * Data à esquerda, descrição no meio, VALOR À DIREITA. Antes eram três
 * elementos empilhados (`.pilha-celula`), e a pilha era a causa dos 109,5 px
 * por linha medidos no navegador em 01/09/2026 -- oito linhas por tela onde a
 * referência do dono mostra dezenove.
 *
 * O valor encosta na direita porque é DINHEIRO (#98, item 5) e porque é assim
 * que uma coluna de valores vira régua: o olho varre a borda direita
 * procurando o que não bate, que é o trabalho desta tela. Sem
 * `tabular-nums` isso não funciona -- ver o token em `tokens.css`.
 *
 * A descrição é a única coisa que pode ser longa, então é ela que recebe o
 * `flex: 1` e o corte com reticências; data e valor nunca quebram.
 */
.tabela-conciliacao .valor,
.tabela-conciliacao .linha-data,
.regua-de-conciliacao .valor {
  font-variant-numeric: var(--num-tabular);
  white-space: nowrap;
}
.tabela-conciliacao .valor { font-weight: var(--peso-forte); }
/* Verde entra · vermelho sai · AZUL muda de bolso (pedido do dono, #249).
   O azul não é enfeite: transferência não soma no resultado, e pintá-la de
   vermelho a faria parecer despesa em toda leitura rápida da coluna. Mesma
   decisão que o #236 tomou para a transferência exibida em uma linha. */
.tabela-conciliacao .valor-entrada { color: var(--verde); }
.tabela-conciliacao .valor-saida { color: var(--vermelho); }
.tabela-conciliacao .valor-transferencia { color: var(--azul); }
/* 🔴 AS DUAS REGRAS DE LARGURA POR VISTA SAÍRAM AQUI (#249c).
   Elas vinham do primeiro desenho, quando a vista simples ESCONDIA o lado do
   sistema e a coluna da direita só classificava -- 56% para o banco, 30% para
   o resto. Quando as colunas passaram a ser as que o dono nomeou, elas
   continuaram valendo: seletor com atributo tem especificidade MAIOR que o de
   classe, então os `28.5%` novos nunca chegaram a valer.
   Medido antes de achar: "No banco" com 466 px e "No sistema" com 250 -- os
   dois lados que se comparam, com pesos diferentes, e a coluna que trunca era
   justamente a do sistema, onde as descrições são longas. */
/* NA VISTA SIMPLES A LINHA É UMA LINHA -- nas TRÊS colunas.
   Medido no navegador: com a célula do banco horizontal a linha caiu de 109,5
   para 75,5 px, e os 30 px que sobravam eram as outras duas colunas ainda
   empilhando. Etiqueta de estado e "Desfazer" cabem lado a lado; categoria e
   divergência também. Na vista DETALHADO a pilha continua, porque lá o espelho
   tem três campos e a comparação é vertical.
   `align-items: baseline` alinha o texto das três colunas na MESMA linha de
   base -- sem isso, a etiqueta arredondada empurra o resto e a linha fica
   torta. */
.tabela-conciliacao[data-vista="simples"] .pilha-celula {
  flex-direction: row; align-items: baseline; gap: var(--esp-8); flex-wrap: wrap;
}
.tabela-conciliacao[data-vista="simples"] td { vertical-align: middle; }

/* O que DIFERE, quando difere -- o rótulo em negrito porque um valor solto na
   coluna parece o valor da linha. */
/* #249: "Desfazer" aparece em TODA linha, e em azul sublinhado ele disputava
   atenção com o valor -- que é o que a pessoa veio ler. Ação secundária tem
   peso menor (diretriz 5): fica cinza, e o sublinhado só no ponteiro e no
   foco, onde ele confirma que é clicável. `--ink-3` sobre `--surface` = 4,76:1,
   medido. */
/* #289: era `.botao-link`; é o `.ligacao` do sistema no corpo miúdo da tabela
   -- em 15px a linha subia de 60 para 72px (prova 249). */
.tabela-conciliacao .ligacao { color: var(--ink-3); text-decoration: none; font-size: var(--corpo-mini); }
.tabela-conciliacao .ligacao:hover,
.tabela-conciliacao .ligacao:focus-visible { color: var(--azul-escuro); text-decoration: underline; }

/* ============ #249b: A COLUNA DA DIREITA, VISTA CHEIA ============
 * Foto de PRODUÇÃO, com as linhas casadas: a descrição do lançamento abria
 * cada uma com "no sistema ..." e ocupava três alturas de texto, empurrando a
 * etiqueta de categoria -- que é a AÇÃO -- para baixo. Duas correções:
 *
 * 1. A CATEGORIA VEM PRIMEIRO (a ordem está no template). É o que a pessoa
 *    vem fazer nesta coluna.
 * 2. A DESCRIÇÃO É CONTEXTO: uma linha, cortada, com o texto inteiro no
 *    `title`. Sem rótulo -- o cabeçalho da coluna já diz o que ela é, e "no
 *    sistema" repetido em toda linha é a mesma repetição sem informação que
 *    esta rodada foi tirar do outro lado (R12).
 *
 * E divergência de VALOR ou DATA não é a mesma notícia que a de descrição:
 * ali a linha pode ter casado com o lançamento ERRADO. Essa se vê.
 */
.espelho-descricao {
  display: block;
  font-size: var(--corpo-nota); color: var(--ink-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  max-width: 100%;
}
/* `--amarelo` sobre `--amarelo-fraco` é o par que o #142 mediu para este uso:
   4,51:1, e aqui o corpo é pequeno, então vale o mínimo de 4,5. */
.divergencia-grave {
  display: inline-block;
  font-size: var(--corpo-mini); font-weight: var(--peso-forte);
  padding: var(--esp-2) var(--esp-8); border-radius: 999px; /* #289: uma pílula só */
  background: var(--amarelo-fraco); color: var(--amarelo);
  border: 1px solid var(--marca-ignorar-borda);
  font-variant-numeric: var(--num-tabular);
}

.linha-data { font-size: var(--corpo-nota); color: var(--ink-3); }
.linha-memo { font-size: var(--corpo-miudo); }
.linha-motivo { font-size: var(--corpo-mini); color: var(--ink-3); }
/* Verde crédito, vermelho débito — os tokens medidos no #42 (AA). */
.tabela-conciliacao .positivo { color: var(--verde); font-weight: var(--peso-forte); }
.tabela-conciliacao .negativo { color: var(--vermelho); font-weight: var(--peso-forte); }

.marca-estado { display: inline-block; font-size: var(--corpo-mini); padding: var(--esp-2) var(--esp-8);
  border-radius: 999px; border: 1px solid var(--line); width: fit-content; }
.marca-conciliar { background: var(--verde-fraco); color: var(--verde); border-color: var(--marca-conciliar-borda); }
.marca-criar { background: var(--azul-fraco); color: var(--azul); border-color: var(--marca-criar-borda); }
.marca-ignorar { background: var(--amarelo-fraco); color: var(--amarelo); border-color: var(--marca-ignorar-borda); }
/* #109: mesmo par de tokens da `.conta-marca.neutra` — mesma razão, mesma
   correção. O portão não cobre esta tela; achada por busca dos irmãos. */
.marca-ja_importada { background: var(--line-2); color: var(--ink-2); }

.etiqueta-categoria { display: inline-block; font-size: var(--corpo-mini); padding: var(--esp-2) var(--esp-8);
  border-radius: 999px; background: var(--line-2); width: fit-content; }
/* #233: a categoria da linha virou CONTROLE. O `<details>` é o gatilho sem
   JavaScript nenhum -- clicar na etiqueta abre o combobox de busca do sistema
   e o "Editar lançamento". Sem o marcador nativo do `<summary>`, que aqui só
   somaria ruído: a etiqueta já parece clicável e tem `cursor: pointer`. */
.cat-editor > summary { cursor: pointer; list-style: none; }
.cat-editor > summary::-webkit-details-marker { display: none; }
.cat-editor[open] > summary { margin-bottom: var(--esp-4); }
.cat-editor select { max-width: 100%; }
/* A linha que ninguém classificou: tracejado e apagado, para se distinguir de
   uma categoria de verdade sem gritar. */
.etiqueta-vazia { border: 1px dashed var(--line); background: none; color: var(--ink-3); }

/* #235: a linha que ficou sem lançamento volta ao fluxo. Os dois caminhos ficam
   lado a lado e miúdos -- é uma exceção na tela (uma linha em dez), não a ação
   principal dela. */
/* #236: a transferência em UMA linha, azul. Ela não é entrada nem saída -- o
   dinheiro mudou de bolso --, e o azul é o que o dono pediu para distinguir isso
   do verde/vermelho de quem soma no resultado. `--azul` sobre `--surface` é o
   mesmo par já medido do `.etiqueta-sugerida`. */
.valor-transferencia { color: var(--azul); font-weight: var(--peso-forte); }
.linha-transferencia .celula-descricao a { color: var(--azul); }

.acoes-da-linha { display: flex; gap: var(--esp-6); flex-wrap: wrap; }
.busca-de-lancamento { margin-top: var(--esp-6); }
.busca-de-lancamento input { width: 100%; }
/* A lista de candidatos tem teto: 20 resultados não podem empurrar as linhas de
   baixo para fora da tela. */
.lista-candidatos { list-style: none; margin: var(--esp-6) 0 0; padding: 0;
  max-height: 220px; overflow-y: auto; }
.lista-candidatos li { display: flex; gap: var(--esp-6); align-items: baseline;
  padding: var(--esp-4) 0; border-bottom: 1px solid var(--line-2); }
.lista-candidatos .linha-memo { flex: 1; min-width: 0; overflow-wrap: anywhere; }
/* #327: o candidato é para LER antes de casar -- a descrição quebra em vez de
   virar "Lançamento …" (a reticência da coluna, acima, vale para a linha da
   tabela, não para a lista de escolha), e o aviso de por que não casa desce
   para a linha de baixo, inteiro. */
.lista-candidatos li { flex-wrap: wrap; }
.col-sistema .lista-candidatos .linha-memo { white-space: normal; overflow: visible; flex-basis: 8em; }
.lista-candidatos li > .linha-motivo { flex-basis: 100%; }

.etiqueta-sugerida { background: var(--azul-fraco); color: var(--azul);
  border: 1px dashed var(--etiqueta-sugerida-borda); }
/* #289: `.botao-link` virou `.ligacao` (o link-botão do sistema, sublinhado no hover). */
/* #169 -- A PREVIA E A LISTA DA CONCILIACAO NUNCA TIVERAM REGRA.
   O #70 escreveu `.previa-saldo*` (logo abaixo) e parou ali: as sete classes
   que embrulham o resto do <li> -- `.previa`, `.previa-parada`,
   `.previa-arquivo`, `.previa-erro`, `.previa-conta`, `.previa-destinos`,
   `.previa-aviso` -- e os dois <ul> (`.lista-previa` :55, `.lista-historico`
   :145) ficaram sem uma linha de CSS. Efeito: sete <span> em linha, emendados,
   dentro de um <ul> com marcador e recuo de 40px do navegador, no meio de um
   `.bloco`. Padrao copiado de `.lista-contas` (:824/:828/:829), que e a mesma
   forma -- inclusive o `.conta-identidade` que o historico ja reusa. */
.lista-previa, .lista-historico { list-style: none; margin: 0; padding: 0; }
.lista-historico > li { display: flex; justify-content: space-between; align-items: baseline;
  gap: var(--esp-12); padding: var(--esp-8) 0; border-bottom: 1px solid var(--page); }
.lista-historico > li:last-child { border-bottom: 0; padding-bottom: 0; }

.previa { padding: var(--esp-8) 0; border-bottom: 1px solid var(--page); }
.previa:last-child { border-bottom: 0; padding-bottom: 0; }
/* Arquivo PARADO (erro de leitura ou conta nao reconhecida) nao entra no
   Aplicar, e o <li> inteiro precisa dizer isso antes de a pessoa ler o texto.
   Barra a esquerda, como `.cat-ok`/`.cat-atencao` marcam a linha da arvore de
   categorias -- o mesmo recurso ja usado no sistema para "esta linha e outra
   coisa". Vem DEPOIS de `.previa` de proposito: e o `padding-left` daqui que
   tem de vencer o `padding: ... 0` do atalho de cima. */
.previa-parada { border-left: 3px solid var(--erro); padding-left: var(--esp-8); }

/* `display: block` e nao `flex` no <li>: assim `.previa-saldo` continua sendo a
   pilula `inline-block` que o #70 desenhou. Num flex column o `align-items`
   padrao (stretch) a esticaria de ponta a ponta e a pilula viraria faixa. */
.previa-arquivo, .previa-erro, .previa-conta, .previa-destinos, .previa-aviso { display: block; }
.previa-arquivo { font-weight: var(--peso-medio); }
.previa-conta, .previa-destinos { font-size: var(--corpo-nota); color: var(--ink-3); }
/* Contraste medido sobre o fundo real do `.bloco` (--superficie #ffffff):
   --erro #d92323 = 4,98:1 e --atencao #ad5f05 = 4,76:1. Os dois passam em AA
   para texto normal (>= 4,5:1, diretriz #77 item 7). */
.previa-erro { color: var(--erro); }
.previa-aviso { color: var(--atencao); }

/* A prova de saldo é a razão desta tela existir (#50): toda conciliação termina
   comparando o LEDGERBAL do arquivo com o saldo que o sistema terá depois de
   aplicar. O HTML distingue "fecha" de "não fecha" desde o #50, mas nenhum CSS
   pintava a diferença -- os dois estados saíam idênticos, e a marca que separa
   um do outro era invisível. Âmbar, e não vermelho, porque diferença NÃO
   bloqueia o Aplicar: ela fica registrada (decisão do #50). (#70) */
.previa-saldo {
  display: inline-block;
  margin-top: var(--esp-6);
  padding: 3px var(--esp-10);
  border-radius: calc(var(--raio) - 3px);
  background: var(--verde-fraco);
  color: var(--verde);
  font-weight: var(--peso-medio);
}
.previa-saldo-diverge { background: var(--amarelo-fraco); color: var(--amarelo); }

/* No resultado a prova é o rodapé do lote -- um `.bloco`, não uma pílula:
   quem recebe a cor é o cartão inteiro. */
/* Terceiro estado da PRÉVIA (`conciliacao.html`), e não uma variação dos
   outros dois: quando o extrato não traz LEDGERBAL não há prova a fazer -- e
   "sem prova" não pode sair pintado de verde como "fecha". Neutro, porque o
   veredito não existe. (#70)
   ⚠️ Esta classe é de OUTRA TELA. Ela morava colada no `.rodape-prova` e caiu
   junto quando o #249 reescreveu o rodapé -- a mesma armadilha do "procure os
   irmãos": corte por vizinhança de arquivo, não por dono. */
.previa-saldo-sem-prova { background: var(--line-2); color: var(--ink-2); }

/* ============== #249: A RÉGUA DE CONCILIAÇÃO (era `.rodape-prova`) ==========
 * Gruda no rodapé porque a pergunta que ela responde -- "quanto ainda falta?"
 * -- é a razão da tela existir, e antes ela ficava depois de 218 linhas, com
 * o peso de uma nota. `sticky`, e não `fixed`: fica no fluxo, então não tapa a
 * última linha nem exige compensar padding em lugar nenhum.
 *
 * A COR MORA NO NÚMERO. A faixa inteira colorida (o que havia antes) pinta
 * 1280 px para dizer o que um valor já diz, e uma barra permanente colorida
 * cansa a leitura das linhas logo acima. Medidos sobre `--surface`:
 * `--verde` 4,78:1, `--amarelo` 4,76:1.
 */
.regua-de-conciliacao {
  position: sticky; bottom: 0;
  display: flex; align-items: baseline; gap: var(--esp-24);
  margin-top: var(--esp-12);
  padding: var(--esp-10) var(--esp-16);
  background: var(--surface);
  border-top: 2px solid var(--line);
  border-radius: var(--raio) var(--raio) 0 0;
  box-shadow: var(--sombra-regua);
}
.regua-bloco { display: flex; flex-direction: column; gap: var(--esp-2); }
.regua-rotulo {
  font-size: var(--corpo-mini); color: var(--ink-3);
  text-transform: uppercase; letter-spacing: 0.04em;
}
.regua-bloco .valor { font-size: var(--corpo); font-weight: var(--peso-forte); }
/* O ÚNICO número grande da tela: é ele que diz se o trabalho acabou. */
.regua-diferenca .valor { font-size: var(--corpo-heroi); line-height: 1.1; }
.regua-fecha .regua-diferenca .valor { color: var(--verde); }
.regua-diverge .regua-diferenca .valor { color: var(--amarelo); }
.regua-sem-prova { border-top-color: var(--line); }
.regua-aviso { margin: 0; font-size: var(--corpo-nota); color: var(--ink-2); max-width: 46ch; }
.regua-volta { margin-left: auto; font-size: var(--corpo-nota); color: var(--azul-escuro); }

/* A2/A3 (#54): a coluna de contas mostra as maiores e agrupa o resto; a fila de
   pendências se lê em diagonal (uma linha por item), não em parágrafo. */
.contas-agrupadas { margin-top: var(--esp-6); }
.contas-agrupadas > summary { font-size: var(--corpo-nota); color: var(--ink-3); cursor: pointer;
  padding: var(--esp-4) 0; }
.contas-agrupadas > summary:hover { color: var(--ink); }

.fila-pendencias { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--esp-4); }
.fila-pendencias > li { display: flex; align-items: center; gap: var(--esp-8); font-size: 13.5px;
  padding: var(--esp-4) 0; border-bottom: 1px solid var(--line-2); }
.fila-pendencias > li:last-child { border-bottom: 0; }
.pendencia-texto { margin-right: auto; }
.pendencia-detalhe > summary { font-size: var(--corpo-nota); color: var(--azul); cursor: pointer; }
.pendencia-detalhe ul { margin: var(--esp-6) 0 0; padding-left: 18px; font-size: var(--corpo-rotulo); }
.pendencia-detalhe p { margin: var(--esp-6) 0 0; font-size: var(--corpo-rotulo); color: var(--ink-2); }

/* #98/B7: as notas de ESTADO, no mesmo cartão e fora da fila de ação. Sem
   etiqueta de contagem (a etiqueta é o convite a agir) e com a tinta de
   contexto do sistema — `--ink-2`, contraste já medido no #42. A divisória
   acima é o que separa "faça isto" de "saiba disto" sem precisar de dois
   cartões, que custariam a altura de outro título. */
.fila-notas { list-style: none; margin: var(--esp-10) 0 0; padding: var(--esp-10) 0 0;
  border-top: 1px solid var(--line); display: grid; gap: var(--esp-4); }
.fila-notas > li { display: flex; align-items: center; gap: var(--esp-8); font-size: var(--corpo-rotulo);
  color: var(--ink-2); }
.nota-de-estado-titulo { font-size: var(--corpo-mini); text-transform: uppercase;
  letter-spacing: .06em; color: var(--ink-3); }

/* #149 -- "Precisa de voce" na forma da referencia aprovada em 13/08/2026:
 * cada pendencia deixa de ser uma linha com divisoria e vira uma CAIXA com o
 * tom do alerta. Nada saiu: a etiqueta continua carregando a CONTAGEM (a
 * referencia poe um icone generico ali; o numero informa mais e ja existia),
 * o texto continua o mesmo e o `Ver` continua sendo `<details>` de verdade.
 *
 * A cor entra por `:has()` sobre a etiqueta que o proprio item ja traz --
 * nenhuma classe nova no template, nenhum token novo. `:has()` ja e usado
 * nesta base (`.form-lancamento:has(...)`, `.rolagem-horizontal:has(...)`).
 *
 * Contraste CALCULADO sobre tokens.css, no fundo REAL de cada caixa:
 *   --ink   #0f172a sobre --vermelho-fraco #fef2f2 -> 16,1:1
 *   --ink-2 #475569 sobre --vermelho-fraco        ->  6,93:1
 *   --ink-2 #475569 sobre --amarelo-fraco #fffbeb ->  7,08:1
 *   --vermelho #d92323 sobre --surface (a pastilha) -> 4,98:1
 *   --amarelo  #ad5f05 sobre --surface              -> 4,51:1
 *   --verde    #12843c sobre --verde-fraco #f0fdf4  -> 4,57:1 */
.fila-pendencias { gap: var(--esp-8); }
.fila-pendencias > li {
  align-items: flex-start;
  padding: var(--esp-10) var(--esp-12);
  border: 1px solid var(--line); border-bottom: 1px solid var(--line);
  border-radius: var(--raio);
  background: var(--surface);
}
.fila-pendencias > li:last-child { border-bottom: 1px solid var(--line); }
.fila-pendencias > li:has(.etiqueta.vencido) { background: var(--vermelho-fraco); }
.fila-pendencias > li:has(.etiqueta.falta)   { background: var(--amarelo-fraco); }
/* A pastilha precisa do fundo CLARO de volta: dentro de uma caixa que ja e
   `--vermelho-fraco`, uma etiqueta `--vermelho-fraco` desaparece. */
.fila-pendencias > li .etiqueta {
  background: var(--surface);
  width: 24px; height: 24px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto; padding: 0;
}
.fila-pendencias .pendencia-texto { color: var(--ink); font-weight: var(--peso-forte); }
/* O chevron da referencia, SEM tirar a palavra: `Ver` sozinho e um alvo
   nomeado, um `›` sozinho nao e. */
.fila-pendencias .pendencia-detalhe > summary::after { content: " ›"; }

/* O cartao verde "ESTADO CONHECIDO" da referencia. Era divisoria + titulo
   solto; vira caixa, que e o que separa "saiba disto" de "faca isto" sem
   depender de o olho notar uma linha de 1px. */
.fila-notas {
  border-top: 0; padding: var(--esp-10) var(--esp-12);
  background: var(--verde-fraco); border: 1px solid var(--line);
  border-radius: var(--raio);
}
.nota-de-estado-titulo { color: var(--verde); }

/* CONTAS: valor e status empilhados a DIREITA, como na referencia. Hoje o
   `conferido` cai na linha de baixo A ESQUERDA, por `flex-wrap`, e a coluna
   do dinheiro perde o alinhamento. Grade de tres colunas resolve sem tocar no
   template. Escopado a `.coluna-lateral` porque `.lista-contas` serve outras
   duas listas na mesma tela. */
.coluna-lateral .lista-contas li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  column-gap: var(--esp-10); row-gap: 0;
  flex-wrap: nowrap;
}
.coluna-lateral .lista-contas .conta-marca { grid-column: 1; grid-row: 1 / span 2; }
/* #182 — `margin-right: auto` MATA o stretch aqui, e o ellipsis nunca corta.
   A regra base (`.conta-identidade`, ~linha 663) nasceu para o layout FLEX do
   #104, onde `auto` era o que empurrava o saldo para a direita. Desde o #149
   esta lista e GRID, e ali a margem automatica troca o `stretch` do item por
   `fit-content` -- cujo piso e o min-content do `.conta-nome`, que tem
   `white-space: nowrap`. Resultado medido em 18/08/2026 (#181, prova
   `prova_interface_104`): uma conta de nome longo ocupava 589px numa faixa de
   229px, `main` sobrava 285px e `document.scrollWidth` dava 1565 contra 1280.
   A coluna do saldo ja e posicionada pelo proprio grid (`grid-column: 3`), entao
   aqui a margem nao empurra nada -- so estraga. */
.coluna-lateral .lista-contas .conta-identidade {
  grid-column: 2; grid-row: 1 / span 2; margin-right: 0;
}
.coluna-lateral .lista-contas .valor { grid-column: 3; grid-row: 1; text-align: right; }

/* #98/B7c: o travessão do que ainda não foi lançado. Tinta de contexto, nunca
   verde nem vermelho — o ponto é justamente que ainda não há veredito. */
.balanco-sem-dado { color: var(--ink-3); font-weight: var(--peso-normal); }
.balanco-ressalva { font-size: 11.5px; }

/* A4 (#54): os dois pares de saldo numa célula só, alinhados à direita e com
   QUEBRA — cortar um valor de dinheiro é pior que descer uma linha. */
.saldo-par { margin-left: 0; }

/* #55, item 5: os atalhos ficam VISÍVEIS. Ctrl+K e N existem desde o #36 sem
   que nada na tela contasse — atalho que ninguém descobre não existe. */
.gatilho-busca, .gatilho-lancar {
  display: inline-flex; align-items: center; gap: var(--esp-6);
  background: none; border: 1px solid var(--line); border-radius: var(--raio);
  padding: var(--esp-4) var(--esp-10); font-size: var(--corpo-miudo); color: var(--ink-2); cursor: pointer;
  text-decoration: none; white-space: nowrap;
}
.gatilho-busca:hover, .gatilho-lancar:hover { background: var(--line-2); color: var(--ink); }
.gatilho-busca kbd, .gatilho-lancar kbd {
  font-size: 10.5px; padding: 1px var(--esp-4); border: 1px solid var(--line);
  border-bottom-width: 2px; border-radius: 4px; background: var(--surface);
  color: var(--ink-3); font-family: inherit;
}
/* Numa tela estreita o rótulo sai e ficam o ícone e a tecla. */
@media (max-width: 760px) { .gatilho-texto { display: none; } }
/* #287: num celular o menu (nove itens, ~770px) não cabe numa linha e, com
   `flex: none`, estourava a página inteira para o lado (medido: 790px de
   rolagem numa tela de 390px, em TODAS as telas). Abaixo de 760px ele ocupa a
   linha inteira e quebra em duas ou três fileiras de abas; a empresa e as
   ações ficam na primeira linha. Sem `overflow-x: auto` de propósito -- o
   comentário de `.topo` explica que ele recortaria os submenus. */
@media (max-width: 760px) {
  .topo { gap: var(--esp-4) var(--esp-12); padding: var(--esp-6) var(--esp-10); }
  /* #288: numa tela de 360px a linha Buscar + Lançar + olho + nome media 370
     (prova 121); as teclas dos gatilhos (Ctrl K, N) são dica de teclado --
     que num celular não existe. */
  .gatilho-busca kbd, .gatilho-lancar kbd { display: none; }
  .topo-menu { flex: 1 1 100%; flex-wrap: wrap; order: 3; gap: 0 var(--esp-2); }
  .topo-menu > li > a, .tem-submenu > summary { padding: var(--esp-6) var(--esp-10); }
}

/* #55: ficha de filtro aplicado, removível uma a uma. */
.chip-removivel { display: inline-flex; align-items: center; gap: var(--esp-6); }
.chip-x { color: var(--ink-3); text-decoration: none; font-size: 14px; line-height: 1; }
.chip-x:hover { color: var(--vermelho); }
.densidade { display: inline-flex; gap: var(--esp-4); }
/* #275/#277: o botão de densidade ATIVO se vê -- até aqui os três eram iguais e
   ninguém sabia qual valia. O estado vem do `data-densidade` do <html>
   (ui.js), não de classe. (#277: os botões moram à esquerda do cabeçalho.) */
/* #276: os filtros salvos (#41) moram no painel Filtrar, na linha inteira,
   depois que a fila de atalhos saiu por decisão do dono. */
.filtros-salvos { display: flex; flex-direction: column; gap: var(--esp-4); flex: 1 1 100%; }
.filtros-salvos .fichas { margin: 0; }
/* #281: o par Extrato/Lista, irmão da densidade e com o mesmo ATIVO -- aqui o
   estado é `aria-pressed`, porque quem sabe o modo é o servidor. */
.modo-da-lista { display: inline-flex; gap: var(--esp-4); margin: 0; }
.modo-da-lista .btn[aria-pressed="true"],
:root[data-densidade="compacto"] .densidade [data-densidade="compacto"],
:root[data-densidade="normal"] .densidade [data-densidade="normal"],
:root[data-densidade="relaxado"] .densidade [data-densidade="relaxado"] {
  background: var(--azul-fraco); border-color: var(--azul); color: var(--azul-escuro);
}
/* #249: o par Simples/Detalhado. O ESCOLHIDO precisa se ver -- `aria-pressed`
   sozinho é estado que só o leitor de tela enxerga, e este mesmo arquivo já
   registra esse defeito (linha 247). Os dois botões encostam num par só, como
   um seletor de segmento. */
.vista-da-tela { display: inline-flex; }
.vista-da-tela .btn { border-radius: 0; margin-left: -1px; }
.vista-da-tela .btn:first-child { border-radius: var(--raio) 0 0 var(--raio); margin-left: 0; }
.vista-da-tela .btn:last-child { border-radius: 0 var(--raio) var(--raio) 0; }
.vista-da-tela .btn[aria-pressed="true"] {
  /* `--acao-escura` sobre `--realce`: 5,77:1, medido e registrado no topo
     deste arquivo. `--acao` sobre `--realce` daria 4,41 e reprovaria. */
  background: var(--azul-fraco); border-color: var(--azul); color: var(--azul-escuro);
  font-weight: var(--peso-forte); position: relative; z-index: 1;
}


/* #57-D/E1: o herói ganha cor semântica e a escala tipográfica escolhida.
   Vermelho é o que SAI, verde o que sobra; o disponível fica neutro porque é o
   que se TEM, não um veredito. Os operadores são gramática, não conteúdo. */
.heroi-rotulo { display: block; font-size: var(--corpo-nota); color: var(--ink-3); }
.heroi-num { font-size: 24px; font-weight: 640; letter-spacing: -.025em; }
.heroi-num.heroi-principal { font-size: 30px; }
.heroi-saida { color: var(--vermelho); }   /* 5,43 sobre branco — AA */
.heroi-sobra { color: var(--verde); }      /* 5,98 sobre branco — AA */
.heroi-operador { font-size: 20px; color: var(--ink-3); }  /* 4,88 — AA */

/* #98/B5: o grupo que o `−` subtrai. Sem ele a linha leria
   `Disponível − Vencido + Vence em 7 dias = Folga`, que é outra conta — e
   errada. As duas barras finas são o parêntese: não somam peso visual (é uma
   linha de 1px na cor de divisória), e são o que torna a aritmética legível
   sem escrever um parêntese literal no meio de números de 24px.
   `align-items: baseline` porque os vizinhos do herói também se alinham pela
   base — sem isso os dois termos flutuariam em relação ao Disponível. */
.heroi-grupo {
  display: flex; gap: 20px; align-items: baseline;
  padding: 0 var(--esp-16);
  border-left: 1px solid var(--line);
  border-right: 1px solid var(--line);
}
/* A contagem ao lado do vencido. Fica em linha PRÓPRIA (block) para não
   empurrar a largura do termo — a etiqueta ao lado do número esticava o grupo
   e a linha do herói tem `flex-wrap`. */
.heroi-etiqueta { display: block; margin-top: var(--esp-2); }

/* E3: card vazio não ocupa espaço nobre para dizer que não há nada. */
.bloco-vazio { display: none; }

/* #57-A2: os cinco Cadastros nunca passaram por rodada de interface. Abas com
   estado, cabeçalho com busca/contagem/criar, e a tabela do #36. Nada de
   redesenho: só os componentes que as outras telas já usam.
   #70 (Tarefa 6): as três regras `.aba-cadastro*` saíram daqui -- viraram
   `.aba`/`.abas` em core/static/css/componentes.css. Não era chip de estado
   (aquele virou `.etiqueta`, acima); era navegação por abas, e a fundação
   não tinha esse componente -- só mudou de arquivo e de nome, os valores são
   os mesmos. */

.cabecalho-cadastro { display: flex; align-items: center; gap: var(--esp-12);
  flex-wrap: wrap; margin-bottom: var(--esp-12); }
.cadastro-busca { display: flex; gap: var(--esp-8); flex: 1 1 260px; min-width: 0; }
.cadastro-busca input { flex: 1 1 auto; min-width: 0; }
.cadastro-contagem { font-size: var(--corpo-miudo); color: var(--ink-3); }
.cabecalho-cadastro > .btn { margin-left: auto; }
/* #186: o "Destravar acessos" mora num `<form>` (é POST — ação que muda estado
   não acontece por GET), e um form é bloco: sem isto ele quebraria a linha do
   cabeçalho e empurraria o botão primário. A regra do `margin-left: auto`
   acima passa para ELE quando existe, para o primário continuar encostado à
   direita e o secundário ficar ao lado. */
.cabecalho-cadastro > .formulario-em-linha { display: flex; }
.cabecalho-cadastro:has(.formulario-em-linha) > .btn { margin-left: auto; }
.cabecalho-cadastro > .formulario-em-linha + * { margin-left: 0; }
/* O nome quebrava em três linhas ("18.572.970 CARLA DAMASCENO DE OLIVEIRA"). */
.tabela td { overflow-wrap: anywhere; }

/* #57-C: área de soltar arquivo. O input nativo some da vista mas continua
   sendo o alvo do <label> — foco por teclado e leitor de tela intactos. */
.area-solta { display: flex; flex-direction: column; align-items: center;
  gap: var(--esp-8); padding: 32px var(--esp-16); border: 2px dashed var(--line);
  border-radius: var(--raio); text-align: center; cursor: pointer; }
.area-solta:hover, .area-solta:focus-within { border-color: var(--azul);
  background: var(--azul-fraco); }
.area-solta-icone { font-size: 28px; color: var(--ink-3); line-height: 1; }
.area-solta .ajuda { max-width: 52ch; font-size: var(--corpo-miudo); color: var(--ink-3); }
/* #199: a variante do MODAL. A original (acima) tem 32px de padding e foi
   feita para ocupar uma tela inteira -- na conciliação ela é o assunto da
   página. No modal de lançar ela divide espaço com dez campos, e densidade é
   requisito (diretriz 4 do dono), então encolhe: o ícone vira inline, o texto
   fica numa linha e o botão acompanha. Mesmo componente, mesma cor, mesmo
   gesto -- só o volume muda. */
.area-solta.compacta { flex-direction: row; flex-wrap: wrap; justify-content: flex-start;
  gap: var(--esp-8); padding: var(--esp-12) var(--esp-14); text-align: left; }
.area-solta.compacta strong { font-size: var(--corpo-miudo); font-weight: var(--peso-forte); }
.area-solta.compacta .ajuda { flex-basis: 100%; margin: 0; }
.area-solta.compacta .btn { margin-left: auto; }

/* A lista do que foi escolhido: com o input escondido, o navegador não conta
   mais os arquivos -- quem conta é a tela (diretriz 8). */
.anexos-escolhidos { list-style: none; margin: var(--esp-8) 0 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--esp-4); }
.anexos-escolhidos li { display: flex; align-items: baseline; gap: var(--esp-8);
  font-size: var(--corpo-miudo); color: var(--ink-2); }
.anexos-escolhidos .tamanho { margin-left: auto; color: var(--ink-3);
  font-variant-numeric: tabular-nums; }

.entrada-arquivo-oculta { position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); border: 0; }
/* #287: `.campo-anexos input[type="file"]` (componentes.css, 0,2,1) vencia a
   regra acima (0,1,0) e o input escondido ganhava 100% de largura em
   `position: absolute` -- a tela do Lançar rolava 136px para o lado em
   QUALQUER largura (medido em 1440, 1280, 820 e 390). Especificidade 0,3,1. */
.campo-anexos input[type="file"].entrada-arquivo-oculta { width: 1px; margin: -1px; }
/* O foco do input escondido tem de aparecer no container, senão o teclado
   navega às cegas. */
.area-solta:focus-within { outline: 2px solid var(--azul); outline-offset: 2px; }

/* ============================================================================
   #104 — o Início contra `docs/referencia/referencia-visual1.png`
   Nenhum token novo, nenhuma cor literal: tudo daqui sai de `tokens.css`, e os
   pares de cor são os que o portão do #103 já mediu (`--azul` sobre
   `--azul-fraco` no segmentado, `--vermelho` sobre `--vermelho-fraco` na
   etiqueta vencida).
   ========================================================================= */

/* A sublinha de contexto de cada número do herói (v3, linhas 432/445/458/470).
   11,5px é o mesmo tamanho da `.conta-tipo`, que é a outra sublinha do
   sistema — duas escalas para a mesma função seriam duas decisões onde cabe
   uma. */
.heroi-sub { display: block; margin-top: 3px; font-size: 11.5px; color: var(--ink-3); }

/* A frase-veredito passou a carregar o selo e o botão (v3, linhas 473-477). O
   botão morava no alto do cartão, longe da frase que explica por que clicar
   nele. */

/* Seletor segmentado de LINKS — irmão de `.segmentado`, que é de rádio.
   Mesma moldura, mesmo padding, mesmo par de cor no ativo: a diferença é que
   este navega (querystring) em vez de submeter formulário, e por isso são
   `<a>`, alcançáveis por teclado sem JS nenhum. */
.segmentado-links { display: inline-flex; border: 1px solid var(--linha-campo);
  border-radius: var(--raio); overflow: hidden; }
.segmentado-links a { display: inline-flex; align-items: center; min-height: 32px;
  padding: var(--esp-6) var(--esp-14); font-size: var(--corpo-miudo); color: var(--ink-2);
  text-decoration: none; border-left: 1px solid var(--line); }
.segmentado-links a:first-child { border-left: none; }
.segmentado-links a:hover { background: var(--line-2); color: var(--ink); }
.segmentado-links a[aria-current="page"] { background: var(--azul-fraco);
  color: var(--azul); font-weight: var(--peso-forte); }
.segmentado-links a:focus-visible { outline: 2px solid var(--azul); outline-offset: -2px; }

/* Cabeçalho de bloco com ação à direita: `Contas … Todas as 21`,
   `Top despesas do mês … Ver todas` (v3, linhas 505 e 542). */
.bloco-cab { display: flex; align-items: baseline; gap: var(--esp-10); }
.bloco-cab > .bloco-titulo { margin-right: auto; }
/* Ação textual à direita de um cabeçalho ou de uma linha de fila. `min-height`
   de 24px é a WCAG 2.5.8, a mesma correção que o #103 fez no `.definir`. */
.lnk { font-size: var(--corpo-rotulo); color: var(--azul); text-decoration: none;
  display: inline-flex; align-items: center; min-height: 24px; }
.lnk:hover { text-decoration: underline; }
.lnk:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

/* A pastilha da conta negativa (v3, linha 556). Mesmo par de cor da etiqueta
   `vencido`, que já é o "isto está no vermelho" do sistema. */
.conta-marca.negativa { background: var(--vermelho-fraco); color: var(--vermelho); }
/* #109: era `--ink-3`, que o token declara calibrado "4,54:1 sobre --surface".
   Sobre `--line-2`, que é mais escuro, a razão cai para 4,28:1 (medido pelo
   `portao_a11y_103.py` no "+15" do Início) e o portão reprova. */
.conta-marca.neutra { background: var(--line-2); color: var(--ink-2); }

/* `+16 Outras 16 contas` deixou de ser um `<details>` e virou linha da lista
   (v3, linha 562): o resumo já dizia tudo o que o expansível escondia, e um
   clique a menos para ver 16 contas é a diretriz 1 (eficiência) em prática. */

/* O resumo do gráfico ("2026, mês a mês · resultado …") empurrado para a
   direita da legenda, como na referência. */
.grafico-resumo { margin-left: auto; }

/* O `+N outras contas` com a MESMA geometria das linhas de conta acima dele:
   antes era um `<summary>` de 12px, visivelmente de outra família, e o olho
   lia a lista como se ela terminasse na linha anterior. */
.contas-agrupadas > summary { display: flex; align-items: baseline; gap: var(--esp-10);
  padding: 9px 0; font-size: inherit; color: inherit; list-style: none; }
.contas-agrupadas > summary::-webkit-details-marker { display: none; }
.contas-agrupadas > summary .valor { margin-left: auto; }
.contas-agrupadas > summary:hover .conta-nome { color: var(--ink); }
.contas-agrupadas > summary:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

/* #143 — OS QUATRO CARTÕES DO TOPO DA HOME (referência: /root/referencia/ref.png).
   Substituem o herói-equação do #98/B5. A célula da grade continua sendo
   `.cartao-heroi` (grid-column 1, row 1); ela deixou de ser um cartão e passou
   a ser o CONTÊINER de quatro, mais a faixa do veredito.
   Nenhum token novo: tudo sai de `tokens.css`, que a #142 já modernizou. */
.bloco-do-topo { display: flex; flex-direction: column; gap: var(--esp-16); }
.cartoes-do-topo {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--esp-16);
}
.cartoes-do-topo > .kpi { margin-bottom: 0; }
.kpi .cartao-corpo { display: flex; flex-direction: column; gap: var(--esp-4); }
/* #149 -- a referencia `/root/referencia/ok.jpg`, aprovada pelo dono em
   13/08/2026, centraliza o conteudo do cartao. As tres linhas do #144
   (icone+descricao / valor / quantidade) CONTINUAM as mesmas: muda o eixo,
   nao a estrutura. Sem PIL nem ImageMagick nesta maquina, o alinhamento saiu
   de leitura visual da imagem -- MEDIDO POR PROXY, nao por pixel. */
.kpi .cartao-corpo { align-items: center; text-align: center; }
/* O círculo colorido usa GLIFO EXISTENTE (↑ ↓ ⚠ ✓) — família de ícone nova é
   proibida por iniciativa do agente (§12). */
/* #144, pedido do dono: "diminua o tamanho do card, colocando o ícone mais
   descrição na MESMA LINHA". O padrão do cartão passa a ser três linhas:
     ícone + descrição
     valor
     quantidade
   O círculo encolheu de 34px para 22px: em linha com um rótulo de 13px, 34px
   dominava a linha e empurrava o cartão para baixo -- o oposto de diminuir. */
.kpi-linha-rotulo { display: flex; align-items: center; gap: 7px; }
/* #149: 22px -> 26px. O #144 encolheu de 34 para 22 porque 34 "dominava a
   linha"; 26 e o meio-termo que a referencia mostra -- o circulo le como
   marca, nao como ilustracao, e a linha do rotulo continua com 26px de
   altura, a mesma do texto de 15px com entrelinha. */
.kpi-marca {
  width: 26px; height: 26px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px; line-height: 1; flex: 0 0 auto;
}
.kpi-marca-entrada { background: var(--verde-fraco); color: var(--verde); }
.kpi-marca-saida   { background: var(--vermelho-fraco); color: var(--vermelho); }
.kpi-marca-atencao { background: var(--amarelo-fraco); color: var(--amarelo); }
.kpi-marca-caixa   { background: var(--azul-fraco); color: var(--azul); }
/* A HIERARQUIA que o dono pediu: rótulo pequeno, valor dominante, e a
   QUANTIDADE em destaque de verdade -- "21 contas" e "22 títulos" não podem
   parecer texto auxiliar (item 5 do prompt dele). 15px/700 contra os 13px
   normais de `.heroi-sub`, que continua existindo para o resto da tela. */
.kpi .heroi-rotulo { font-size: var(--corpo-miudo); color: var(--ink-3); }
.kpi-detalhe { font-size: var(--corpo); font-weight: var(--peso-maximo); color: var(--verde); }
.kpi-detalhe-saida { color: var(--vermelho); }
.kpi-detalhe-atencao { color: var(--amarelo); }
.kpi-nota { font-size: var(--corpo-miudo); color: var(--ink-3); }

/* #149 -- a hierarquia da referencia aprovada em 13/08/2026.
 *
 * ⚠ ISTO CONTRARIA O #144 NUM PONTO, e o registro fica aqui para quem vier
 * depois nao "consertar" de volta: no #144 o dono pediu a quantidade em
 * DESTAQUE (15px/700, colorida) para nao parecer texto auxiliar. Na ok.jpg a
 * quantidade e cinza e de peso normal -- quem carrega a cor e o VALOR. A
 * imagem e posterior e foi aprovada nominalmente, entao ela vence; se o dono
 * quiser o destaque de volta, o caminho e reverter estas quatro linhas.
 *
 * Contraste CALCULADO sobre os valores de tokens.css, contra --surface
 * (#ffffff), que e o fundo real do cartao -- nao renderizado:
 *   --ink-2  #475569 -> 7,58:1  (rotulo e quantidade; AA texto normal)
 *   --ink-3  #64748b -> 4,54:1  (nota do mais antigo; ja registrado no #42)
 *   --verde  #12843c -> 4,78:1  (valor positivo)
 *   --vermelho #d92323 -> 4,98:1 (valor negativo e vencido)
 *   --amarelo  #ad5f05 -> 4,51:1 (vence em 7 dias; ja registrado no #42) */
.kpi .heroi-rotulo { font-size: var(--corpo); color: var(--ink-2); }
/* ⭐ #149 -- DUAS REVOGACOES DO DONO em 13/08/2026, com a ok.jpg na mesa e as
 * duas regras anteriores nomeadas na pergunta. NAO "CONSERTAR" ISTO COMO SE
 * FOSSE DESVIO:
 *
 * (a) O DISPONIVEL POSITIVO E VERDE. Revoga o #57-D ("a cor e veredito, o
 *     positivo fica neutro"). O negativo continua vermelho -- o que muda e
 *     que o positivo tambem passa a ter cor, nao que a cor deixou de
 *     significar. `--verde` sobre `--surface`: 4,78:1, AA.
 * (b) OS QUATRO VALORES TEM O MESMO CORPO. Revoga o 30px exclusivo do
 *     Disponivel (#98). A hierarquia passa a ser dada pela ORDEM e pela cor,
 *     nao pelo tamanho.
 *
 * A quantidade ("21 contas", "36 titulos") FICA no destaque do #144 --
 * 15px/700 colorida, como ele decidiu la e reafirmou aqui. A referencia a
 * mostra cinza; ele escolheu manter o destaque. */
.kpi .heroi-num { font-size: 30px; }
.kpi .heroi-principal { color: var(--verde); }
.kpi .heroi-principal.negativo { color: var(--vermelho); }
.kpi .heroi-atencao { color: var(--amarelo); }
/* A quantidade e a nota deixam de disputar a MESMA linha: no Vencido elas
   viravam "177.975,07 36 titulos o mais antigo, ha 86" numa massa so. */
.kpi .kpi-linha-detalhe { flex-direction: column; align-items: center; gap: 1px; }
.kpi .explica-alvo { align-items: center; }
.kpi .kpi-linha-rotulo { justify-content: center; }
/* 1366 é o notebook espremido: quatro cartões de 1fr num container de ~900px
   dariam ~210px cada, e "R$ 1.070.982,34" em 24px não cabe. Duas colunas. */
@media (max-width: 1200px) {
  .cartoes-do-topo { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .cartoes-do-topo { grid-template-columns: minmax(0, 1fr); }
}

/* #144 — a linha de resultado do fluxo de caixa. `fill:none` não é detalhe:
   sem ele o SVG fecha o polígono e pinta a área inteira, escondendo as barras. */
.grafico-resultado { fill: none; stroke: var(--azul); stroke-width: 2; stroke-linejoin: round; }
.grafico-zero { stroke: var(--ink-3); stroke-width: 1; stroke-dasharray: 3 3; }
.grafico-chave-resultado { background: var(--azul); }

/* #145 — O `+ Lançar` VIRA BOTÃO PRIMÁRIO AZUL SÓLIDO.
 *
 * ⚠️ ISTO REVOGA A DECISÃO #D3, e por decisão NOMINAL do dono em 13/08/2026,
 * com a referência dele na mesa (/root/referencia/menusup.png). A #D3 dizia:
 * "`.gatilho-lancar` é um botão-fantasma da barra escura do topo, não o botão
 * primário do sistema. Fora da barra ele seria invisível." Com a barra CLARA a
 * premissa caiu: fantasma sobre branco é que fica invisível.
 *
 * NÃO "CONSERTAR" ISTO COMO SE FOSSE DESVIO.
 *
 * Consequência conhecida e aceita: telas com ação própria (o Salvar do modal, o
 * Registrar pagamento da fatura) passam a exibir DOIS azuis. A diretriz nº 5
 * pede uma ação primária por tela -- o dono decide se o Lançar cede peso
 * quando a tela tem ação própria; medido e relatado na entrega. */
/* `.topo a` VENCE `.gatilho-lancar` por ESPECIFICIDADE (0,1,1 contra 0,1,0),
   nao por ordem -- pôr no fim do arquivo nao bastou. O portao mediu o
   resultado: fundo azul com texto slate, 1,47:1, um botao primario ilegivel
   que meus olhos nao pegariam. Daí o `.topo` na frente. */
.topo .gatilho-lancar {
  background: var(--azul);
  border-color: var(--azul);
  color: var(--surface);
  font-weight: var(--peso-forte);
  padding: var(--esp-6) var(--esp-14);
}
.topo .gatilho-lancar:hover { background: var(--azul-escuro); border-color: var(--azul-escuro); color: var(--surface); }
/* A tecla dentro do botao: branco sobre azul CLAREADO dava 3,51:1 (medido).
   Escurecer o fundo da tecla resolve sem mexer na cor do texto. */
.topo .gatilho-lancar kbd { background: var(--azul-escuro); border-color: var(--azul-escuro); color: var(--surface); }
/* A busca da referência é uma caixa arredondada e mais larga, não um botão. */
.gatilho-busca { border-radius: 999px; padding: 5px var(--esp-12); background: var(--page); }

/* #145 — O `+ Lançar` CEDE PESO ONDE A TELA TEM AÇÃO PRÓPRIA.
 *
 * Decisão do dono em 13/08/2026, com o número na mesa: 15 templates usam
 * `btn-primario`, e com o Lançar sólido essas telas passariam a exibir DOIS
 * azuis — contra a diretriz nº 5, que pede uma ação primária por tela.
 *
 * `:has()` e não classe no template porque a condição é do CONTEÚDO, não da
 * rota: o modal injeta o `Salvar` por htmx DEPOIS da carga, e nesse instante
 * a ação primária passa a ser dele. Com `:has()` a cessão acontece ao vivo;
 * com classe no `<body>` por rota, o modal ficaria de fora.
 *
 * Conteúdo dentro de `<template>` (o `#molde-lote`) é inerte para o `:has()` —
 * senão toda tela que carrega o molde acharia que tem ação própria. */
body:has(.btn-primario) .topo .gatilho-lancar {
  background: var(--surface);
  color: var(--azul);
  border-color: var(--azul);
}
body:has(.btn-primario) .topo .gatilho-lancar:hover {
  background: var(--azul-fraco);
  color: var(--azul-escuro);
  border-color: var(--azul-escuro);
}
body:has(.btn-primario) .topo .gatilho-lancar kbd {
  background: var(--azul-fraco); border-color: var(--azul); color: var(--azul);
}

/* #146, achado do dono: "a quebra de linha nos cards ainda está errada".
 * Estava: eu pus rótulo, valor e quantidade dentro do `.explica-alvo`, e SÓ o
 * `.cartao-corpo` era coluna -- então os três fluíam EM LINHA. O padrão que o
 * dono definiu é de três linhas:
 *     ícone + descrição
 *     valor
 *     quantidade (e, no Vencido, a nota do mais antigo JUNTO dela) */
.kpi .explica-alvo { display: flex; flex-direction: column; gap: var(--esp-2); }
.kpi-linha-detalhe { display: flex; align-items: baseline; gap: var(--esp-6); flex-wrap: wrap; }

/* #146: a seta dos submenus, que faltava. `▾` é o glifo que o sistema já usa
 * no combobox -- não é família de ícone nova. Escopado a `.topo-menu` porque
 * foi o que o dono nomeou (Relatórios e Cadastros); o "Trocar" da empresa
 * também abre submenu e ficaria coerente com a mesma seta, mas isso é escolha
 * dele e não minha. */
.topo-menu .tem-submenu > summary::after {
  content: "▾"; font-size: var(--corpo-micro); margin-left: 5px; color: var(--ink-3);
}

/* #147 — a dica do fluxo de caixa. O alvo é invisível mas PRECISA capturar o
   ponteiro: `fill: transparent` captura, `fill: none` NÃO -- e a diferença
   entre as duas é exatamente um gráfico que não responde ao mouse. */
.grafico-alvo { fill: transparent; cursor: default; }
.grafico-alvo:focus-visible { outline: 2px solid var(--azul); outline-offset: -2px; }
.grafico-dica {
  position: absolute; z-index: 45; pointer-events: none;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--raio);
  box-shadow: var(--sombra-dica);
  padding: var(--esp-8) var(--esp-10); font-size: var(--corpo-miudo); min-width: 168px;
}
.grafico-dica[hidden] { display: none; }
.grafico-dica b { display: block; margin-bottom: var(--esp-4); color: var(--ink); }
.grafico-dica .linha { display: flex; justify-content: space-between; gap: var(--esp-12); }
.grafico-dica .linha span:last-child { font-variant-numeric: tabular-nums; }
.grafico-dica .pct { margin-top: var(--esp-4); color: var(--ink-3); }

/* #149 -- o resultado operacional na dica, como na referencia aprovada.
 *
 * A COR E A REGRA, e ela vem de token: `--verde` quando o mes sobrou,
 * `--vermelho` quando faltou. O prompt pedia #16A34A e #DC2626 -- as duas
 * foram MEDIDAS e REPROVADAS no #142 (3,15:1 e 4,41:1 sobre o fundo fraco) e
 * por isso viraram #12843c e #d92323. Sobre o fundo real desta caixa, que e
 * `--surface` (#ffffff), o par calculado agora da:
 *   --verde    #12843c -> 4,78:1  (AA texto normal)
 *   --vermelho #d92323 -> 4,98:1  (AA texto normal)
 * Ou seja: mesma leitura, contraste que passa. Nao ha cor literal aqui. */
.grafico-dica .pct-resultado {
  margin-top: var(--esp-6); padding-top: var(--esp-6); border-top: 1px solid var(--line-2);
  display: flex; flex-direction: column; gap: 1px;
}
.grafico-dica .pct-rotulo { color: var(--ink-3); }
.grafico-dica .pct-num { font-size: 20px; font-weight: 640; letter-spacing: -.02em; }
.grafico-dica .pct-resultado.positivo .pct-num { color: var(--verde); }
.grafico-dica .pct-resultado.negativo .pct-num { color: var(--vermelho); }

/* A seta da referencia. Fica na BASE da caixa apontando para baixo, porque a
   dica e posicionada ACIMA do topo da coluna (`top = r.top + 8`). Dois
   triangulos sobrepostos: o de tras faz a borda, o da frente o preenchimento
   -- e o truque de sempre para dar borda a um triangulo de CSS. */
.grafico-dica::before,
.grafico-dica::after {
  content: ""; position: absolute; left: 50%; width: 0; height: 0;
  border-left: 7px solid transparent; border-right: 7px solid transparent;
}
.grafico-dica::before {
  bottom: -8px; margin-left: -7px; border-top: 8px solid var(--line);
}
.grafico-dica::after {
  bottom: -6px; margin-left: -7px; border-top: 8px solid var(--surface);
}
