/* ══════════════════════════════════════════════════════════════
   COMPONENTES · botão, chip, campo, paginação
   Passo 5 da ordem de aplicação de docs/design/especificacao-visual.html.

   Um arquivo só, carregado em todas as telas. Antes disto o botão e o
   campo estavam espalhados entre shell.css e login.css — componente
   partido em dois arquivos diverge na terceira semana.

   Todos os estados de uma vez, inclusive os que só existem no :hover e
   no :focus: estado que não está escrito não pode ser conferido.

   Nenhum valor cru: tudo de tokens.css.
   ══════════════════════════════════════════════════════════════ */

/* ══ HIDDEN VENCE SEMPRE ═══════════════════════════════════════
   O atributo `hidden` esconde pelo estilo do NAVEGADOR, e qualquer
   `display` de classe nossa (.campo é flex, .botao é inline-flex)
   passa por cima dele — o elemento fica "escondido" no HTML e
   visível na tela. Foi assim que o formulário de lançamento mostrou
   o bloco de série com Ocorrência = Única e os DOIS seletores de
   categoria ao mesmo tempo, por dois checkpoints, sem nenhum erro
   em lugar nenhum (achado em 22/08/2026, pela tela de Recorrências).

   O !important é o uso legítimo: `hidden` é semântica do documento,
   não estilo — quando o HTML diz escondido, nenhuma classe pode
   discordar. */
[hidden] { display: none !important; }

/* ══ FOCO ══════════════════════════════════════════════════════
   Anel rosa de 2px com 2px de folga, em TUDO que é operável.
   Nunca o azul do navegador — está no checklist do documento.

   :focus-visible e não :focus: quem clica com o mouse não precisa do
   anel, quem chega por teclado precisa. O navegador sabe a diferença. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: var(--e-1) solid var(--foco);
  outline-offset: var(--e-1);
}

/* ══ 7.1 · BOTÃO ═══════════════════════════════════════════════
   Um primário por tela, e só ele é preenchido. 38px de altura,
   pílula, texto 14px peso 500. */
/* PÍLULA desde 19/09/2026 — é a gramática de BOTÃO do desenho,
   medida: <button> e <a> aparecem 32 vezes com altura 38 e raio 19.
   Ver o bloco do raio em tokens.css.

   A folga lateral subiu de 16 para 20 junto com o raio, e não é
   estética: numa pílula o texto precisa de folga MAIOR OU IGUAL ao
   raio, senão a primeira letra encosta na curva. Com 38px de altura o
   raio é 19, e 20 é o primeiro degrau da escala que o cobre. */
.botao {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 8 e não 4, desde 19/09/2026. O desenho escreve `gap:8px` em TODO
     botão que leva ícone — o primário de Contatos, o Salvar, o Estornar.
     Só aparece em botão com ícone E texto: com um filho só, gap não
     pinta nada. Anda junto com o ícone de 16 (item F): 16 de ícone com
     4 de folga encosta o desenho no texto. */
  gap: var(--e-3);
  height: var(--botao-h);                /* 38px (era 34) */
  padding: 0 calc(var(--e-5) + var(--e-2));
  border: 1px solid var(--campo-borda);
  border-radius: var(--r-botao);
  background: var(--papel);
  color: var(--tinta);
  font-family: inherit;
  font-size: var(--fs-dado);
  font-weight: var(--peso-medio);
  white-space: nowrap;
  cursor: pointer;
  text-decoration: none;
}

/* secundário é o padrão: fundo de papel, borda discreta */
.botao:hover { background: var(--papel-2); border-color: var(--regua); }

/* primário — o único preenchido.

   NEGRITO E FOLGA DE 18, desde 19/09/2026 (item A da comparação). O
   desenho escreve o primário em peso 700 e com 18px de folga lateral —
   medido nos 15 arquivos: `font-weight:700; padding:0 18px; border:0`
   no de Contatos, no Salvar do formulário e no Salvar do modal.

   DUAS COISAS QUE EU DEVO DECLARAR:

   1. O CONTORNO JÁ ERA INVISÍVEL. O desenho diz `border:0` e nós dizemos
      `border-color: var(--marca)` — a MESMA cor do fundo. Na tela não há
      diferença nenhuma; a única consequência é o texto começar 1px mais
      para dentro. A borda FICA, e de propósito: ela é o que mantém o
      primário e o secundário com a mesma caixa, lado a lado, na mesma
      barra de ação. Tirá-la encolheria só um dos dois.
   2. 18 NÃO ESTÁ NA ESCALA, e por isso é escrito como conta dela
      (16 + 2), do mesmo jeito que os 20 de antes eram 16 + 4. Com a
      borda de 1px o texto começa em 19, contra os 18 do desenho.

   A folga desce de 20 para 18 e passa a ser MENOR que o raio (19), o que
   contraria a regra que escrevi no alto deste bloco em setembro. A regra
   estava conservadora, e a conta mostra por quê: a pílula de 38px tem o
   centro da curva em (19,19) e raio 19, e a letra ocupa da altura 14 à
   24. No pior ponto dela — y=14 — a curva avança 19 − √(19²−5²) = 0,67px
   sobre a borda. Menos de um pixel, contra os 2 que a folga cedeu.

   A conta importa porque quase todo primário do sistema é TEXTO PURO —
   "Salvar", "Entrar", "Criar usuário", "Exportar agora". QUATRO levam
   ícone, e são estes: "Novo lançamento" (Shell.php:601), "Novo contato"
   (contatos.php:148), "Salvar contato" (contatos.php:580) e o "Salvar"
   do lançamento (lancamento.php:669).
   Eu escrevi "dois" aqui na primeira versão, e a comparação
   independente contou. Contados de novo, um por um: são quatro. */
.botao.primario {
  background: var(--marca);
  border-color: var(--marca);
  color: var(--papel);
  padding: 0 calc(var(--e-5) + var(--e-1));   /* 18 */
  font-weight: var(--peso-negrito);
}
.botao.primario:hover  { background: var(--marca-forte); border-color: var(--marca-forte); }
.botao.primario:active { background: var(--marca-press); border-color: var(--marca-press); }

/* fantasma — ação secundária dentro de um bloco, sem moldura */
.botao.fantasma {
  background: transparent;
  border-color: transparent;
  color: var(--marca-forte);
  padding: 0 var(--e-4);
}
.botao.fantasma:hover { background: var(--marca-fraca); border-color: transparent; }

/* escolhido — a pílula de recorte escolhida (Categorias, Contatos, Extrato,
   Excluídos, o DRE e o tema em Configurações). Não é o primário: aqui não
   há ação, há um recorte, e a marca fica para o primário. O :hover vem
   junto para o escolhido não perder a cor quando o mouse passa. A borda
   --regua é a do limite conhecido da seção "A leva de peças" do
   CLAUDE.md. */
.botao.escolhido,
.botao.escolhido:hover {
  background: var(--papel-3);
  border-color: var(--regua);
  color: var(--tinta);
  font-weight: var(--peso-forte);
}

/* marcado — o convite com a cor da marca no contorno, sem preencher: é o
   segundo passo de uma escolha (dividir uma série entre categorias), e o
   preenchido continua sendo só o primário. O contorno é --marca, e não o
   --marca-linha do desenho: aquele é cor de preenchimento e mede 1,36
   contra o branco, abaixo dos 3,0 de uma peça. */
.botao.marcado {
  color: var(--marca-forte);
  border-color: var(--marca);
  background: var(--papel);
  font-weight: var(--peso-negrito);
}
.botao.marcado:hover { background: var(--marca-fraca); border-color: var(--marca); }

/* destrutivo — contorno, nunca preenchido. Estornar não pode ser o
   botão mais fácil de acertar da tela. */
.botao.destrutivo {
  color: var(--vencido);
  border-color: var(--vencido);
  background: var(--papel);
  padding: 0 var(--e-4);
}
.botao.destrutivo:hover { background: var(--vencido-fraca); }

.botao:disabled,
.botao[aria-disabled="true"] { opacity: .4; cursor: not-allowed; }
.botao:disabled:hover { background: var(--papel); border-color: var(--campo-borda); }
.botao.primario:disabled:hover { background: var(--marca); border-color: var(--marca); }

/* salvando — o botão vira relato do que está acontecendo. A palavra
   muda junto com o giro: animação sozinha não informa, e some para
   quem desliga movimento. */
.botao.salvando { pointer-events: none; opacity: .8; }
.botao-giro {
  width: var(--e-4); height: var(--e-4);
  flex: none;
  border: var(--e-1) solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: girar .7s linear infinite;
}
@keyframes girar { to { transform: rotate(360deg); } }

/* CÍRCULO desde 19/09/2026: é o que o desenho faz com todo botão que
   só tem ícone — 18 declarações de `50%` nos 15 arquivos. */
/* A FONTE É HERDADA, e não a do navegador. Quase todo botão de ícone tem um
   SVG dentro e não se importa — mas o "×" de tirar linha da grade de
   rateio é um CARACTERE, e sem esta linha ele saía em Arial 13,33px, a
   fonte de fábrica do <button>, no meio de uma tela em Nunito.
   Achado pela comparação independente de 20/09/2026. */
.botao-icone {
  display: inline-grid;
  place-items: center;
  font-family: inherit;
  font-size: var(--fs-corpo);
  width: var(--botao-h);
  height: var(--botao-h);
  padding: 0;
  border: 1px solid var(--campo-borda);
  border-radius: 50%;
  background: var(--papel);
  color: var(--tinta-2);
  cursor: pointer;
}
.botao-icone:hover { background: var(--papel-2); color: var(--tinta); }

/* ══ 7.2 · AS DUAS ETIQUETAS ═══════════════════════════════════
   São duas peças declaradas lado a lado, e não uma com exceções
   escopadas por tela: o SELO, em caixa alta e sem ponto, e o CHIP DE
   SITUAÇÃO, em caixa normal e com o ponto da cor na frente.

   O que cada peça carrega e em que telas entra está na seção
   "As duas etiquetas" do CLAUDE.md.

   Os dois têm COR E PALAVRA juntas — tire a cor da tela e ainda dá
   para operar, porque a palavra continua lá.

   As quatro classes de cor ficam no fim deste bloco e servem às duas
   peças. */

/* ── O selo: 20px, 12px de letra, caixa alta, pílula ─────────────── */
.selo {
  display: inline-flex;
  align-items: center;
  gap: var(--e-1);
  height: calc(var(--e-5) + var(--e-2));   /* 20px */
  padding: 0 var(--e-3);
  border-radius: var(--r-botao);
  font-size: var(--fs-rotulo);
  font-weight: var(--peso-forte);
  letter-spacing: .05em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ── O chip de situação: 26px, ponto de 6px, caixa normal, pílula ──
   Estas declarações vinham de `.v3-tabela .chip`, em lancamentos-v3.css,
   e de `.pnl-hoje-cabeca .chip`, em painel.css, onde eram exceções
   escopadas ao chip de 20px. O contorno é o que separa o chip do fundo
   do quadro, que também é claro. */
.chip-situacao {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--e-2) + var(--e-1));       /* 6px entre o ponto e a palavra */
  height: calc(var(--e-6) + var(--e-1));    /* 26px */
  padding: 0 calc(var(--e-3) + var(--e-1)) 0 var(--e-3);   /* 8 antes do ponto, 10 depois da palavra */
  border: 1px solid transparent;
  border-radius: var(--r-botao);
  font-size: var(--fs-rotulo);
  font-weight: var(--peso-forte);
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
}
/* O PONTO DE 6px, UMA VEZ SÓ. Ele existia em quatro lugares: aqui, em
   `.v3-tabela .chip` e em `.pnl-hoje-cabeca .chip` — que sumiram em 22/09 —,
   e em `.bx-devendo-chip::before`, na tela de baixa, que só apareceu em
   23/09 porque a busca por `.chip` não acha quem se chama `.bx-`.

   Os dois nomes na mesma declaração, e não uma cópia em cada folha: é o
   mesmo arranjo de `.aud-sistema, .autor-sistema`, algumas linhas abaixo.
   Ver "Um nome, um dono" no CLAUDE.md.

   O `.bx-devendo-chip` NÃO é um chip de situação, e por isso leva só o
   ponto e não a peça inteira. */
.chip-situacao::before,
.bx-devendo-chip::before {
  content: "";
  width: 6px; height: 6px; flex: 0 0 6px;
  border-radius: 50%;
  background: currentColor;
}
.chip-situacao.chip-liquidado { border-color: var(--liquidado-borda); }
.chip-situacao.chip-hoje      { border-color: var(--hoje-borda); }
.chip-situacao.chip-vencido   { border-color: var(--vencido-borda); }
.chip-situacao.chip-aberto    { border-color: var(--aberto-borda); }
/* O Ativo de um cadastro: o chip na paleta do aberto, com o ponto no verde do
   pago. Ver "A regra de cor" e "As duas etiquetas" no CLAUDE.md. */
.chip-situacao.chip-ativo::before { background: var(--liquidado); }

/* ── A paleta, compartilhada pelas duas peças ────────────────────── */
.chip-liquidado { background: var(--liquidado-fraca); color: var(--liquidado); }
.chip-aberto    { background: var(--aberto-fraca);    color: var(--aberto);    }
.chip-hoje      { background: var(--hoje-fraca);      color: var(--hoje);      }
.chip-vencido   { background: var(--vencido-fraca);   color: var(--vencido);   }

/* Variantes do SELO. Rateio não é situação, e por isso não parece uma:
   sem cor de estado, peso menor, número tabular. Um selo colorido a mais
   daria à tela cinco "situações", e são quatro.

   "DO SISTEMA" (Categorias, 17/09/2026) usa a MESMA declaração, e não uma
   cópia dela: é a mesma ideia — um estado do cadastro, não do dinheiro. Ele
   ocupa a coluna Situação sozinho, porque categoria de sistema nunca é
   inativa (o B12 reprova quem tentar), então "do sistema" já diz que a
   categoria está ativa. */
.chip-rateio,
.chip-sistema {
  background: var(--papel-2);
  color: var(--tinta-2);
  border: 1px solid var(--campo-borda);
  font-weight: var(--peso-medio);
  letter-spacing: 0;
  text-transform: none;
  font-variant-numeric: tabular-nums;
}

/* O selo de contorno, sem preenchimento: o perfil e o "Você" de Usuários, e a
   ação que não é do financeiro na Auditoria. Ver "As duas etiquetas" no
   CLAUDE.md. */
.selo-contorno {
  background: transparent;
  border: 1px solid var(--linha-2);
  color: var(--tinta-2);
}

/* Baixa estornada: borda tracejada, sem preenchimento. É o registro de uma
   baixa desfeita, e não um cadastro — o tracejado diz isso sem cor. */
.chip-inativa {
  background: transparent;
  color: var(--tinta-3);
  border: 1px dashed var(--linha-2);
}

/* ── A SIGLA DO CONTATO (avatar de duas letras) ─────────────────────────
   Nasceu em Contatos, em 19/09/2026, e subiu para cá em 21/09, quando o
   Painel passou a usar a mesma peça na lista de quem deve. As duas letras
   saem de `App\Core\Texto::sigla()` — uma regra só, no Core, como a
   chaveBusca; já houve DUAS regras de iniciais no sistema, e elas davam
   respostas diferentes para o mesmo nome (um nome de cinco palavras dava
   uma sigla num lugar e outra no outro).

   `aria-hidden` sempre: a sigla é a abreviação do nome que está ao lado, e
   um leitor de tela que a lesse anunciaria as duas letras antes do nome. */
.sigla,
.con-sigla {
  display: grid;
  place-items: center;
  flex: 0 0 var(--e-7);
  width: var(--e-7);
  height: var(--e-7);
  border-radius: var(--r-1);
  background: var(--avatar);
  color: var(--avatar-tinta);
  font-size: var(--fs-rotulo);
  /* peso MÉDIO, não forte: a sigla é apoio e o nome é quem manda na
     linha. Os dois estavam trocados — as duas letras do avatar pesavam
     mais que o nome do contato, que é por onde ela se localiza. */
  font-weight: var(--peso-medio);
}

/* ══ 7.3 · CAMPO ═══════════════════════════════════════════════
   40px de altura, canto de 12px, fundo claro, texto 16px, rótulo em
   caixa alta acima. */
.campo { display: flex; flex-direction: column; gap: calc(var(--e-2) + var(--e-1)); }

/* O RÓTULO DE CAMPO SAIU DA CAIXA ALTA em 19/09/2026: em caixa alta
   fica pesado de ler. No desenho é "Razão social ou nome", com só a
   primeira letra — 12px, peso 600, tom secundário.

   ISTO É GLOBAL: o rótulo aparece em 19 views. Uma regra aqui muda
   todos os formulários do sistema de uma vez, e nenhuma tela precisa
   ser tocada.

   O `.rotulo` do tokens.css NÃO muda: aquele é o rótulo ESTRUTURAL —
   cabeçalho de coluna, nome de seção —, e é outro trabalho. São duas
   coisas com nomes parecidos e trabalhos diferentes. */
.campo-rotulo {
  font-size: var(--fs-rotulo);
  font-weight: var(--peso-forte);
  color: var(--tinta-2);
}

/* O CAMPO, refeito em 19/09/2026 — é a outra gramática do desenho:
   40px de altura, canto de 12, e FUNDO CLARO em vez de branco. Os três
   juntos: o campo passa a ter fundo rosado claro em vez de branco.

   O fundo é o --papel-2, que já existia: o desenho preenche o campo
   com #F7F7FA, que é exatamente o valor desse token. Não houve cor
   nova; havia uma cor que o campo não estava usando.

   A BORDA NÃO É A DO DESENHO, e isto é decisão declarada. O desenho
   contorna o campo com a divisória dele, que mede 1,24 sobre o branco;
   o conferidor exige 3,0 de contorno de controle e o nosso
   --campo-borda mede 3,76. Copiado ao pé da letra, o campo ficaria com
   a borda quase invisível e o conferidor reprovaria. Vale a regra da
   casa: onde o desenho reprova, o valor se ajusta até passar. Fica o
   preenchimento do desenho, e a borda que se enxerga. */
.campo-caixa {
  height: var(--campo-h);                /* 40px (era 38) */
  padding: 0 var(--e-4);
  border: 1px solid var(--campo-borda);
  border-radius: var(--r-1);
  background: var(--papel-2);
  color: var(--tinta);
  font-family: inherit;
  font-size: var(--fs-corpo);
  width: 100%;
  min-width: 0;
}
.campo-caixa::placeholder { color: var(--tinta-3); }
.campo-caixa:hover { border-color: var(--regua); }
.campo-caixa:focus { border-color: var(--marca); }

.campo-caixa:disabled,
.campo-caixa[readonly] {
  background: var(--papel-3);
  border-color: var(--linha);
  color: var(--tinta-3);
  cursor: not-allowed;
}

/* Inválido: borda vermelha E mensagem escrita. A borda sozinha não diz
   O QUE está errado, e some para quem não distingue vermelho. */
.campo-caixa[aria-invalid="true"] { border-color: var(--vencido); }
.campo-erro {
  display: flex;
  align-items: center;
  gap: var(--e-2);
  font-size: var(--fs-meta);
  color: var(--vencido);
}

/* O ÍCONE DA MENSAGEM DE ERRO PRECISA DE TAMANHO — defeito antigo, achado
   em 19/09/2026 na tela /componentes.

   O svg escrito nas views não leva a classe `.ic`, que é quem dá 16px a
   todo ícone do sistema, e esta regra não dizia nada sobre ele. Um svg com
   viewBox e sem largura, dentro de um flex, ocupa o que sobrar: medi 208px
   de altura na tela de componentes — um ponto de exclamação do tamanho de
   um prato ao lado de uma frase de 13px.

   Não é novo. A regra nunca existiu, e o defeito está nas DEZ telas que
   mostram erro de campo; ele só ficou grande de ver agora, porque a
   moldura devolveu 333px de largura à página e o ícone cresceu junto.

   Quem deu a pista foi a própria /componentes, que existe para isso. */
.campo-erro svg { width: var(--e-5); height: var(--e-5); flex: none; }

.campo-ajuda { font-size: var(--fs-meta); color: var(--tinta-3); }
/* SOBRE O FUNDO DA TELA, O METADADO SOBE UM DEGRAU — é a regra 1 do
   tokens.css, e ela passou a alcançar mais lugares em 19/09/2026: o fundo
   --tela deixou de ser pintado por sete telas e passou a valer para as 22.
   Uma ajuda de campo SOLTA no miolo não tem quadro branco por baixo, e ali
   --tinta-3 mede 4,14 contra os 8,50 do --tinta-2. Dois casos vivos: a nota
   "Para trocar a SUA senha" em Usuários e a de encerrar conta em Contas
   correntes. Dentro de um quadro nada muda — lá o fundo é --bloco. */
.conteudo > .campo-ajuda,
.conteudo > * > .campo-ajuda { color: var(--tinta-2); }

/* ══ 7.3.1 · CAMPO DE SENHA COM O OLHO ═════════════════════════
   Do desenho da V5, e em três telas: a de entrada, Minha senha e a
   redefinição em Usuários. Mora aqui porque é componente — nasceu
   copiado em duas folhas e a terceira cópia seria a que diverge.

   O botão fica DENTRO da caixa, e o padding à direita do campo abre
   o lugar dele: assim o olho nunca cobre o que está escrito. Quem o
   faz funcionar é assets/js/senha.js. */
.campo-senha { position: relative; display: flex; }
.campo-senha .campo-caixa { flex: 1; min-width: 0; padding-right: var(--e-8); }
.campo-olho {
  position: absolute;
  right: var(--e-2);
  top: 50%;
  transform: translateY(-50%);
  display: inline-grid;
  place-items: center;
  width: var(--e-7);
  height: var(--e-7);
  padding: 0;
  border: 0;
  border-radius: var(--r-1);
  background: transparent;
  color: var(--tinta-3);
  cursor: pointer;
}
.campo-olho:hover { color: var(--tinta); background: var(--papel-2); }
/* O risco só aparece quando a senha está visível — o mesmo olho, com a
   barra em cima, como no desenho. */
.campo-olho-risco { display: none; }
.campo-olho[aria-pressed="true"] .campo-olho-risco { display: inline; }
.campo-olho[aria-pressed="true"] { color: var(--tinta); }

@media (max-width: 900px) {
  .campo-olho {
    width: calc(var(--e-8) - var(--e-2));
    height: calc(var(--e-8) - var(--e-2));
  }
  .campo-senha .campo-caixa { padding-right: calc(var(--e-8) + var(--e-2)); }
}

/* ══ 7.6 · CAMPO COM AFIXO — UMA CAIXA SÓ ══════════════════════
   Refeito em 19/09/2026, e é o conserto que fecha a leva.

   ANTES ERAM DUAS CAIXAS COLADAS: uma caixinha com o "R$", com borda e
   meio-raio, encostada num campo com o outro meio-raio. Funcionava
   enquanto o canto era pequeno; com a gramática nova do botão, a
   emenda entre as duas metades ficaria à vista — foi o que fez a
   pílula ser recusada em 15/09: na tela era "um R$ retangular colado
   num campo em pílula".

   O DESENHO NÃO COLA NADA. Ele monta o campo de dinheiro como UM
   contêiner — borda, canto e fundo no contêiner, foco no contêiner —
   com o "R$" e o número lado a lado DENTRO. O mesmo com o "%" da
   grade de rateio, que fica dentro da caixa do campo.

   Então é isso que o sistema passa a fazer. A emenda deixa de existir
   porque a junção deixa de existir, e são 15 lugares de uma vez: 12
   com "R$", 2 com "%" e 1 com o "+" do cadastro rápido.

   E O QUE 28/08 GANHOU CONTINUA DE PÉ: o "%" segue colado no campo que
   ele qualifica, não no cabeçalho da coluna. Só mudou de que lado da
   borda ele mora. */
.campo-valor {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  height: var(--campo-h);
  padding: 0 var(--e-4);
  border: 1px solid var(--campo-borda);
  border-radius: var(--r-1);
  background: var(--papel-2);
}
/* O foco mora na CAIXA, como no desenho: quem recebe o cursor é o
   campo de dentro, e quem muda de cor é a borda que a pessoa vê. O
   anel de foco do teclado continua sendo desenhado pelo navegador em
   volta do campo — não foi suprimido. */
.campo-valor:focus-within { border-color: var(--marca); }
.campo-valor:hover { border-color: var(--regua); }
.campo-valor:focus-within:hover { border-color: var(--marca); }

/* INVÁLIDO: quem tem a borda agora é o pai, então é o pai que fica
   vermelho. A regra do `.campo-caixa[aria-invalid]` continua existindo e
   continua certa para todo campo comum — só que aqui o filho não tem
   borda nenhuma para pintar, e o alerta sumia da tela. As views não mudam:
   elas já escrevem o `aria-invalid` no campo, que é onde o leitor de tela
   o procura. */
.campo-valor:has(.campo-caixa[aria-invalid="true"]) { border-color: var(--vencido); }

/* O ANEL DE FOCO MUDA DE DONO, pela mesma razão: quem tem borda, canto e
   fundo é o pai. Desenhado no filho, o anel nascia dentro da caixa, com
   canto vivo por cima do canto de 12, deixando o "R$" de fora e vazando
   1px em cima e embaixo. Eu tinha escrito aqui que ele "continua sendo
   desenhado pelo navegador em volta do campo" — era verdade e não era o
   que se via.
   O anel é o do sistema, não um desenho novo: mesma cor, mesma espessura
   e mesma folga da regra global do tokens.css. */
.campo-valor .campo-caixa:focus-visible { outline: none; }
.campo-valor:has(.campo-caixa:focus-visible) {
  outline: 2px solid var(--foco);
  outline-offset: 2px;
}

.campo-valor-moeda {
  flex: none;
  font-size: var(--fs-meta);
  color: var(--tinta-2);
}

/* O campo de dentro não tem caixa nenhuma: a caixa é o pai. */
.campo-valor .campo-caixa {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  text-align: right;
  font-variant-numeric: tabular-nums lining-nums;
}
.campo-valor .campo-caixa:hover { border-color: transparent; }

/* SUFIXO — o "%" da grade de rateio. Com a caixa única, a única
   diferença entre prefixo e sufixo é a ORDEM dos filhos no HTML; não
   há mais meio-raio de um lado nem borda suprimida do outro. A classe
   fica porque as views a escrevem, e porque ela diz qual dos dois é. */
.campo-valor.sufixo .campo-caixa { text-align: right; }

/* Valor secundário — multa, desconto, taxas. Raros, menores, cinzas:
   se tivessem o mesmo peso do principal, a tela sugeriria que preencher
   os quatro é o normal, e não é. */
.campo-valor.secundario {
  height: var(--botao-h);
  border-color: var(--linha);
}
.campo-valor.secundario .campo-caixa {
  font-size: var(--fs-dado);
  color: var(--tinta-2);
}

/* Campo com botão ao lado (cadastro rápido de contato). Descolado em
   19/09/2026, pelo mesmo motivo dos afixos — e porque no desenho esse
   botão é um controle inteiro, com o canto dele, ao lado do campo. */
.campo-com-acao { display: flex; align-items: center; gap: var(--e-3); }
.campo-com-acao .campo-caixa { flex: 1; min-width: 0; }
.campo-com-acao-botao {
  width: var(--campo-h);
  height: var(--campo-h);
  flex: none;
  display: grid;
  place-items: center;
  border: 1px solid var(--campo-borda);
  border-radius: var(--r-1);
  background: var(--papel-2);
  color: var(--marca-forte);
  cursor: pointer;
}
.campo-com-acao-botao:hover { background: var(--marca-fraca); }

/* ══ 7.6.1 · O CAMPO TRAVADO ══════════════════════════════════
   Caixa TRACEJADA no lugar do controle, com o valor dentro: o que a tela
   mostra mas não deixa mudar. Tracejado diz "isto não é um campo agora";
   cinza sozinho diria só "desligado", que é o que um campo opcional
   também parece.

   PEÇA DO SISTEMA: o formulário de lançamento, Editar série e Categorias
   escrevem `.campo-travado`. A altura é o token do campo: a caixa é
   desenhada no lugar exato dele. */
.campo-travado {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  min-height: var(--campo-h);
  padding: var(--e-2) var(--e-4);
  background: var(--banda);
  border: 1px dashed var(--linha-2);
  border-radius: var(--r-1);
  font-size: var(--fs-corpo);
  color: var(--tinta-2);
}
/* O texto quebra em linhas; a categoria rateada tem duas e passa de 70
   caracteres. Truncar esconderia justamente o que desambigua. */
.campo-travado-valor { flex: 1; min-width: 0; line-height: var(--lh-dado); }
/* O cadeado é ÍCONE, não metadado: a régua dele é a de 3:1 dos elementos
   gráficos, não a de 4,5 do texto. Medido: --tinta-3 sobre --banda dá 4,09
   no claro e 4,04 no escuro — passa com folga na régua que vale para ele.
   Fica um degrau abaixo do texto de propósito: o valor é que se lê, o
   cadeado só diz por que ele não é um campo. */
.campo-travado-cadeado { flex: 0 0 auto; color: var(--tinta-3); }

/* ══ 7.7 · AVISO DE ATRASO ═════════════════════════════════════
   Fica ao lado do campo de juros. É o empurrão que faz alguém preencher
   — sem ele o usuário passa direto, que foi exatamente o que aconteceu
   no Simplific. */
.aviso-atraso {
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  font-size: var(--fs-meta);
  font-weight: var(--peso-medio);
  color: var(--vencido);
}
.aviso-atraso svg { width: var(--e-4); height: var(--e-4); flex: none; }

/* ══ FAIXA DE PRAZO (Painel) ═══════════════════════════════════ */
.faixa-prazo { display: flex; flex-direction: column; border: 1px solid var(--campo-borda); border-radius: var(--r-1); }
.faixa-prazo-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--e-4);
  padding: var(--e-3) var(--e-4);
  border-bottom: 1px solid var(--linha);
  font-size: var(--fs-dado);
}
.faixa-prazo-item:last-child { border-bottom: 0; }
.faixa-prazo-rotulo { display: flex; align-items: center; gap: var(--e-2); color: var(--tinta-2); }
.faixa-prazo-valor { font-variant-numeric: tabular-nums; font-weight: var(--peso-medio); }

/* ══ 7.7 · PAGINAÇÃO ═══════════════════════════════════════════
   30px de altura, tabular. A página atual é a única preenchida — mesma
   regra do botão primário: um preenchido por bloco. */
.paginacao { display: flex; flex-direction: column; gap: var(--e-3); }
.paginacao-paginas { display: flex; align-items: center; gap: var(--e-2); flex-wrap: wrap; }

.pagina {
  display: inline-grid;
  place-items: center;
  min-width: calc(var(--e-7) - var(--e-1));   /* 30px */
  height: calc(var(--e-7) - var(--e-1));
  padding: 0 var(--e-3);
  border: 1px solid var(--campo-borda);
  border-radius: var(--r-1);
  background: var(--papel);
  color: var(--tinta);
  font-size: var(--fs-dado);
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  cursor: pointer;
}
.pagina:hover { background: var(--papel-2); border-color: var(--regua); }

.pagina[aria-current="page"] {
  background: var(--marca);
  border-color: var(--marca);
  color: var(--papel);
  font-weight: var(--peso-forte);
}
.pagina[aria-current="page"]:hover { background: var(--marca); border-color: var(--marca); }

/* O "…" não é botão: não tem borda, não recebe foco, não é clicável. */
.pagina-salto {
  display: inline-grid;
  place-items: center;
  min-width: var(--e-5);
  height: calc(var(--e-7) - var(--e-1));
  /* --tinta-2, e não --tinta-3: a paginação mora sobre --tela, e esse par
     é PROIBIDO pela regra 1 do tokens.css (4,14 contra o mínimo de 4,5).
     A contagem ao lado foi corrigida por isto em 15/09 e o "…" ficou de
     fora — ele não aparecia porque a Auditoria é a única tela com páginas
     suficientes para ele nascer, e ela não tinha sido olhada. */
  color: var(--tinta-2);
  font-size: var(--fs-dado);
}

/* "1–44 de 44 · 50 por página".
   A tinta é --tinta-2, não --tinta-3, e isto NÃO é preferência: a paginação
   das duas listagens mora sobre --tela, e --tinta-3 sobre --tela é um par
   PROIBIDO desde 17/08/2026 (mede 3,53 — abaixo dos 4,5). Estava assim desde
   que a regra existe, e o conferidor não pegava porque ele compara os TOKENS
   declarados, não o que a tela de fato pinta sobre o quê. Achado medindo as
   22 telas em 15/09/2026: era a única violação viva, em duas telas. */
.paginacao-conta {
  font-size: var(--fs-meta);
  color: var(--tinta-2);
  font-variant-numeric: tabular-nums;
}

/* ══ Tecla, usada nas dicas de teclado ═════════════════════════ */
kbd {
  display: inline-grid;
  place-items: center;
  min-width: var(--e-5);
  height: var(--e-5);
  padding: 0 var(--e-1);
  border: 1px solid var(--campo-borda);
  border-radius: var(--r-1);
  background: var(--papel);
  font-family: inherit;
  font-size: var(--fs-rotulo);
  color: var(--tinta-2);
}

/* ══ Página /componentes ═══════════════════════════════════════
   Só a moldura da demonstração. Nada aqui é componente do sistema. */
.comp-indice {
  display: flex; flex-wrap: wrap; gap: var(--e-2);
  margin-bottom: var(--e-6);
  padding-bottom: var(--e-4);
  border-bottom: 1px solid var(--linha);
}

.comp-secao { margin-bottom: var(--e-8); max-width: 110ch; }

.comp-titulo {
  margin: 0 0 var(--e-2);
  font-size: var(--fs-titulo);
  font-weight: var(--peso-forte);
  line-height: var(--lh-titulo);
}

.comp-nota {
  margin: 0 0 var(--e-5);
  font-size: var(--fs-meta);
  line-height: var(--lh-corpo);
  color: var(--tinta-2);
  max-width: 78ch;
}
.comp-nota strong { color: var(--tinta); font-weight: var(--peso-medio); }
.comp-secao .comp-nota:last-child { margin: var(--e-5) 0 0; }

.comp-linha {
  display: flex; flex-wrap: wrap; gap: var(--e-6);
  align-items: flex-start;
  padding: var(--e-5);
  border: 1px solid var(--campo-borda);
  border-radius: var(--r-1);
  background: var(--papel);
}
.comp-linha-separada { margin-top: var(--e-4); }

.comp-item { display: flex; flex-direction: column; align-items: flex-start; gap: var(--e-2); }
.comp-marca {
  font-size: var(--fs-rotulo);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--tinta-3);
  font-weight: var(--peso-forte);
}
.comp-item .selo + .selo,
.comp-item .chip-situacao + .chip-situacao { margin-top: var(--e-1); }

.comp-grade {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(30ch, 100%), 1fr));
  gap: var(--e-5);
  align-items: start;
  padding: var(--e-5);
  border: 1px solid var(--campo-borda);
  border-radius: var(--r-1);
  background: var(--papel);
}
/* As células da vitrine, em pares, um par embaixo do outro. No celular cada
   par empilha, como as células do Painel gerencial a 390. */
.comp-celulas { display: grid; gap: var(--e-4); max-width: calc(var(--e-8) * 12); }
@media (max-width: 640px) {
  .comp-celulas .celula { flex: 1 1 100%; }
}

/* ── A lupa, dentro do campo de busca ─────────────────────────
   A lupa fica DENTRO da caixa, à esquerda do texto: 14px, a 12 da borda,
   com o texto começando a 36. Está nas buscas de Categorias, Contatos,
   do seletor de categoria, do Cartão, do Extrato e das listagens. O
   ícone vem ANTES da caixa, como irmão dela, num pai
   posicionado. Ele não recebe o clique (pointer-events: none), senão
   clicar nele não colocaria o cursor no campo. */
.campo-com-icone { position: relative; display: block; }
.campo-icone {
  position: absolute;
  left: var(--e-4);
  top: 50%;
  transform: translateY(-50%);
  width: calc(var(--e-4) + var(--e-1));    /* 14px, o do desenho */
  height: calc(var(--e-4) + var(--e-1));
  color: var(--tinta-3);
  pointer-events: none;
}
.campo-icone ~ .campo-caixa { padding-left: calc(var(--e-4) + var(--e-5) + var(--e-3)); }   /* 36px */
.campo-com-icone .campo-caixa { width: 100%; }

/* ══════════════════════════════════════════════════════════════════════
   FORMULÁRIO · o padrão das telas que gravam
   Nasceu em Configurações › Empresa (18/08/2026) e vale daqui em diante
   para Usuários, para a tela de baixa e para o Novo lançamento.

   Nada de padrão visual novo: é o MESMO quadro da v3 — fundo --bloco,
   contorno --linha-2, raio --r-2 —, os MESMOS campos de componentes.css
   e os MESMOS botões. O que o formulário acrescenta é só arranjo:
   seções com título, grade de campos e uma barra de ação embaixo.
   ══════════════════════════════════════════════════════════════════════ */

.form-bloco {
  max-width: calc(var(--e-8) * 18);        /* 864px: coluna de leitura de formulário */
  background: var(--bloco);
  border: 1px solid var(--linha-2);
  border-radius: var(--r-2);
  box-shadow: var(--sh-quadro);
  /* SEM overflow:hidden: cortava o painel do seletor de categoria na
     borda do quadro (achado de 28/08/2026). O canto redondo vem dos
     filhos das pontas, logo abaixo. */
}
/* Cantos individuais, não o atalho: um filho ÚNICO é first E last ao
   mesmo tempo, e com o atalho a segunda regra apagava o raio da
   primeira — ele precisa dos quatro cantos.

   E O FILHO DA PONTA PODE SER INVISÍVEL — conserto de 15/09/2026.
   Todo .form-bloco que é <form> começa com o campo escondido do token
   CSRF (o lançamento emite dois seguidos). Campo escondido não é
   desenhado, mas CONTA como filho para o :first-child do CSS — a regra
   caía nele e o canto de cima nunca recebia raio. Invisível hoje,
   porque o filho visível seguinte não pinta fundo; armadilha no dia em
   que pintar, e das que ninguém entende seis meses depois.
   Em português, o que os três seletores dizem: o canto de cima é do
   primeiro filho que NÃO é campo escondido (dá-se a todos e tira-se de
   quem vem depois de um visível), e o de baixo é do último que não é. */
.form-bloco > :not(input[type="hidden"]) {
  border-top-left-radius: var(--r-2); border-top-right-radius: var(--r-2);
}
.form-bloco > :not(input[type="hidden"]) ~ :not(input[type="hidden"]) {
  border-top-left-radius: 0; border-top-right-radius: 0;
}
.form-bloco > :not(input[type="hidden"]):not(:has(~ :not(input[type="hidden"]))) {
  border-bottom-left-radius: var(--r-2); border-bottom-right-radius: var(--r-2);
}

/* ── Seção ────────────────────────────────────────────────────────────
   Divide o formulário em blocos com nome. A régua entre seções é a mesma
   divisória da tabela: --linha. Sem preenchimento e sem cor de fundo, que
   é a convenção do balancete já adotada no DRE. */
/* 18 NOS QUATRO LADOS, e o número não é novo: é o mesmo inset lateral que
   as faixas da tabela ganharam em 19/09/2026. Era 16 em cima e 24 dos
   lados — o desenho usa 18 em volta, e com 24 o quadro tinha uma margem
   interna maior que a da tabela ao lado. */
.form-secao { padding: calc(var(--e-5) + var(--e-1)); }
.form-secao + .form-secao { border-top: 1px solid var(--linha); }

/* O TÍTULO DE BLOCO SAIU DA CAIXA ALTA JUNTO COM O RÓTULO, em
   19/09/2026 — e sem ele o conserto do rótulo ficaria pela metade.

   Com os dois em caixa alta a hierarquia existia; com o rótulo em caixa
   normal e o título em maiúscula, o título passava a ser o mesmo
   tamanho, o mesmo peso e a mesma cor dos rótulos logo abaixo dele, e
   nada anunciava o bloco. No desenho ele é maior, na tinta cheia e com
   só a primeira letra.

   GLOBAL: o título de bloco aparece em 9 telas. */
.form-secao-titulo {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--e-3);
  margin: 0 0 var(--e-4);
  font-size: var(--fs-corpo);
  font-weight: var(--peso-forte);
  color: var(--tinta);
}

/* A NOTA AO LADO DO TÍTULO DO BLOCO — "só o nome é obrigatório", em
   Contatos. É do desenho, que a põe ao lado do título com 10px de folga e
   um tom mais fraco. Nasce aqui, e não em contatos.css, porque a frase
   que diz o que um formulário exige serve a qualquer formulário: a
   primeira vez que outra tela precisar dela, já existe.

   O tamanho é 13 (--fs-meta) e não os 12 do desenho, que está abaixo do
   piso de fonte que ela fixou em 28/08. `baseline` no pai é o que faz a
   nota assentar na mesma linha do texto do título, e não no meio dele. */
.form-secao-nota {
  font-size: var(--fs-meta);
  font-weight: var(--peso-normal);
  color: var(--tinta-2);
}

/* ── Grade de campos ──────────────────────────────────────────────────
   Doze colunas. Cada campo diz quantas ocupa, para que "UF" não fique do
   mesmo tamanho de "Logradouro" — campo largo demais para o conteúdo
   sugere que falta texto a escrever. */
.form-grade {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  /* 16, e não 12: é o gap do desenho, medido no arquivo dele.

     A primeira versão deste comentário dizia que com 12 o vão entre dois
     campos ficava menor que a distância entre o rótulo e o campo — e isso
     é FALSO: essa distância é o gap do .campo, que vale 6px. É o dobro,
     não menor. Corrigido pela auditoria independente de 20/09/2026, e
     registrado porque num projeto em que o comentário é a memória um
     porquê errado é pior que nenhum.

     O atalho vale para os DOIS eixos: o vão entre LINHAS também subiu de
     12 para 16, e os formulários das sete telas ficaram um pouco mais
     altos. Medido que nenhuma coluna estoura: a seção devolveu 12px de
     largura (padding 24→18 dos dois lados) quase na conta do que os vãos
     comeram — c-3 dá 194,5px antes e depois. */
  gap: var(--e-5);
}
.c-2  { grid-column: span 2; }
.c-3  { grid-column: span 3; }
.c-4  { grid-column: span 4; }
.c-5  { grid-column: span 5; }
.c-6  { grid-column: span 6; }
.c-7  { grid-column: span 7; }
.c-8  { grid-column: span 8; }
.c-12 { grid-column: span 12; }

@media (max-width: 760px) {
  .form-grade > * { grid-column: span 12; }
}

/* AQUI MORAVA O ASTERISCO DE CAMPO OBRIGATÓRIO, e ele saiu de todas as dez
   telas em 24/09/2026, com a regra que o pintava. Ver "O obrigatório se diz
   pelo erro" no CLAUDE.md.

   Fica registrado onde ele estava, porque a classe `.obrigatorio` some do CSS
   e do HTML no mesmo dia: quem procurar por ela daqui a seis meses não acha
   nada, e esta linha responde. */

/* ── Barra de ação ────────────────────────────────────────────────────
   Embaixo, dentro do quadro, sobre --banda. Um primário só, à direita, e
   nada preenchido além dele. */
/* A FAIXA DE SALVAR/CANCELAR clareou em 19/09/2026 (item C). Ela estava
   em --banda (#E7E7EF) com régua --regua (#8E8AA3) — a banda é a cor da
   LINHA DE RESULTADO do DRE e a régua é a estrutural, e as duas juntas
   no pé de um formulário faziam o quadro parecer dois quadros colados.
   O desenho põe `background:var(--card-2); border-top:1px solid
   var(--line)`, e o --card-2 dele é #F7F7FA, que é exatamente o nosso
   --papel-2. Mesma mudança no pé do modal, que o desenho desenha igual. */
.form-acoes,
.modal-acoes {
  display: flex;
  gap: var(--e-4);
  padding: calc(var(--e-4) + var(--e-1)) calc(var(--e-5) + var(--e-1));
  background: var(--faixa-acao);
  border-top: 1px solid var(--linha);
}
/* No formulário os botões ficam no meio da faixa, na vertical; na janela, à
   direita. */
.form-acoes { align-items: center; }
.modal-acoes { justify-content: flex-end; }

/* O HOVER DO SECUNDÁRIO DENTRO DA FAIXA muda borda e tinta, nunca o
   preenchimento — e é o que o desenho faz: o Cancelar dele tem
   `style-hover="color:var(--ink); border-color:var(--ink-3)"`, sem tocar
   no fundo.

   Aqui isso deixou de ser preferência e virou necessidade: o hover geral
   do botão preenche com --papel-2, que no claro passou a ser a cor da
   PRÓPRIA FAIXA. Passar o mouse no Cancelar pintava o botão exatamente
   da cor do fundo em que ele está — em vez de acender, ele DESBOTAVA,
   porque a borda também clareava de --campo-borda para --regua.
   Achado pela comparação independente de 19/09/2026. */
.form-acoes .botao:not(.primario):not(.destrutivo):not(.fantasma):hover,
.modal-acoes .botao:not(.primario):not(.destrutivo):not(.fantasma):hover {
  background: var(--papel);
  border-color: var(--tinta-3);
  color: var(--tinta);
}
/* O BOTÃO DA FAIXA DE AÇÃO TEM A ALTURA DO CAMPO, não a do botão de
   barra de ferramentas. São dois tamanhos no desenho, e os dois têm
   função: 38 é o botão que acompanha um filtro ou um título; 40 é o que
   fecha um formulário, e ele fica lado a lado com campos de 40. Dois
   pixels de diferença ali aparecem, porque o Salvar encosta na coluna
   dos campos. */
.form-acoes .botao,
.modal-acoes .botao { height: var(--campo-h); }

.form-acoes-nota {
  font-size: var(--fs-meta);
  color: var(--tinta-2);
  margin-right: auto;
  /* Teto de leitura, como no desenho: sem ele a frase corre a faixa
     inteira numa linha só e some ao lado dos botões. */
  max-width: calc(var(--e-8) * 10);
}

/* O tratamento de celular da barra de ação está no bloco @media único,
   no fim deste arquivo. */

/* ══ AVISO · o retorno de uma ação que já aconteceu ════════════════════
   Neutro, sem prefixo de tela: serve a qualquer formulário. A palavra
   carrega o significado; a régua lateral só reforça. */
.aviso {
  display: flex;
  align-items: flex-start;
  gap: var(--e-3);
  max-width: calc(var(--e-8) * 18);
  margin: 0 0 var(--e-5);
  padding: var(--e-4);
  border-radius: var(--r-1);
  font-size: var(--fs-corpo);
  background: var(--papel-2);
  color: var(--tinta);
  box-shadow: inset 3px 0 0 var(--regua);
}
.aviso-ok   { background: var(--liquidado-fraca); box-shadow: inset 3px 0 0 var(--liquidado); }
.aviso-erro { background: var(--vencido-fraca);   box-shadow: inset 3px 0 0 var(--vencido); }
.aviso .ic  { flex: none; margin-top: 1px; }
.aviso-ok   .ic { color: var(--liquidado); }
.aviso-erro .ic { color: var(--vencido); }

/* ── QUEM FEZ, quando não foi gente ────────────────────────────────────
   A palavra é "Sistema", nunca um traço: traço faz parecer que o dado se
   perdeu, e ele nunca existiu — importação e linha de comando não têm
   usuário. Nasceu na Auditoria e mora aqui desde 11/09/2026, quando a
   lista de baixas passou a mostrar o autor: três telas falando a mesma
   coisa pedem uma declaração só, num arquivo que todas carregam. */
.aud-sistema,
.autor-sistema { font-style: italic; color: var(--tinta-2); }

/* ══ TABELA SIMPLES · listas de configuração ═══════════════════════════
   A mesma caixa da tabela da v3: sem raio, contorno --linha-2. Não é um
   padrão novo — é o mesmo, sem as oito colunas fixas da listagem de
   lançamentos. O cabeçalho é o da v3: os dois usam a --faixa-acao.

   DUAS MUDANÇAS DE 19/09/2026 (itens B e D da comparação), e as duas
   valem para as telas que usam esta classe — Auditoria, Baixa,
   Categorias, Contas, Contatos, Exportação e Extrato:

   B · A RÉGUA SOB O CABEÇALHO deixa de ser --regua. O desenho usa ali
       `border-bottom:1px solid var(--line-2)`, e o --line-2 dele
       (#DAD9E4) é o tom de CONTORNO DE COMPONENTE — o mesmo papel do
       nosso --linha-2. O --regua (#8E8AA3) é a régua estrutural do DRE,
       três degraus mais escura: dentro de uma tabela de cadastro ela
       vira um risco atravessando a tela.
       NÃO alcança o DRE, o Fluxo nem o Cartão, que usam 2px de --regua
       por outra razão, escrita no dre.css: lá a régua separa ETAPA de
       componente, e é a convenção do balancete. Essas três telas têm
       leva própria.

   D · O RECUO LATERAL vai de 12 para 18. É o valor do desenho em toda
       tira — cabeçalho, linha e faixa de letra — e aparece 119 vezes
       nos 15 arquivos. Escrito como conta da escala (16 + 2), porque 18
       não é degrau. */
.tabela-simples {
  width: 100%;
  background: var(--bloco);
  border: 1px solid var(--linha-2);
  border-collapse: collapse;
}
.tabela-simples caption { text-align: left; }
/* CAIXA NORMAL desde 21/09/2026 — ver "O cabeçalho de coluna" no
   CLAUDE.md. Esta regra é o cabeçalho de coluna de seis telas —
   Contatos, Auditoria, Categorias, Exportação, Extrato e a tela de
   baixa — e era ela que punha em CAIXA ALTA um texto que as views
   escrevem em caixa normal. Os quinze arquivos do desenho da V5 não usam
   `text-transform` em lugar nenhum, e as duas listagens nunca estiveram
   em caixa alta.

   O FUNDO é a --faixa-acao: no claro ela vale --papel-2, e no escuro sobe
   para --banda, um tom ACIMA do quadro. Com --papel-2 cru, no escuro o
   cabeçalho ficava mais fundo que o quadro (1,03).

   O `letter-spacing` saiu JUNTO, e não é mudança à parte: ele existe
   para abrir a caixa alta, onde as letras se colam; sobre caixa normal
   ele estica a palavra. O `.v3-cabeca` das listagens tem
   letter-spacing zero. */
.tabela-simples thead th {
  height: var(--linha-h-cabeca);
  padding-block: 0;
  text-align: left;
  background: var(--faixa-acao);
  border-bottom: 1px solid var(--linha-2);    /* item B */
  font-size: var(--fs-rotulo);
  font-weight: var(--peso-forte);
  color: var(--tinta-2);
  white-space: nowrap;
}
.tabela-simples tbody td {
  height: var(--linha-h-lista);
  padding-block: var(--e-2);
  border-bottom: 1px solid var(--linha);
  font-size: var(--fs-dado);
  color: var(--tinta);
  vertical-align: middle;
}

/* ── O RECUO DE 18 É DA TIRA, NÃO DE CADA CÉLULA (item D, corrigido) ──
   Eu tinha lido o desenho errado na primeira aplicação, e o erro custou
   132px de largura em nove telas.

   O desenho não usa tabela: usa grade, e escreve
   `grid-template-columns: …; gap: 14px; padding: 10px 18px`. Os 18 são
   a folga da TIRA INTEIRA contra a borda do cartão, uma vez de cada
   lado; entre duas colunas o que existe é o `gap`, de 14. Idêntico em
   Categorias.dc.html e Extrato.dc.html; em Contas a receber v3 o gap é 12.

   Eu tinha posto 18 de cada lado de CADA célula, o que deixa 36 entre
   colunas onde o desenho deixa 14. Conta refeita sobre as sete colunas
   de Contatos: 7×36 = 252 de recuo, contra 36 + 6×14 = 120 no desenho.

   Agora: 8 de cada lado no miolo (16 entre colunas, contra os 14 do
   desenho — 8 é o degrau da escala e 7 não é), e 18 nas duas pontas.
   Dá 36 + 6×16 = 132.

   (O 18 é mesmo o valor da casa do desenho: 108 declarações de `padding`
   nos 15 arquivos o contêm. Eu tinha escrito "119 vezes" aqui, que era a
   contagem de OCORRÊNCIAS do número — `padding: 18px 18px` conta duas —,
   não de declarações. A comparação independente pegou a diferença.)

   E o valor ANTERIOR à leva também estava largo: 12 de cada lado são 24
   entre colunas, 1,7× o desenho. Ou seja, o item D não era só "12 vira
   18" — era "o recuo está no lugar errado". */
.tabela-simples thead th,
.tabela-simples tbody td { padding-inline: var(--e-3); }
.tabela-simples thead th:first-child,
.tabela-simples tbody td:first-child { padding-inline-start: calc(var(--e-5) + var(--e-1)); }
.tabela-simples thead th:last-child,
.tabela-simples tbody td:last-child { padding-inline-end: calc(var(--e-5) + var(--e-1)); }
.tabela-simples tbody tr:last-child td { border-bottom: 0; }
.tabela-simples tbody tr:hover td { background: var(--papel-2); }
.tabela-simples .num { font-variant-numeric: tabular-nums; text-align: right; }
/* O `nowrap` mora nos FILHOS, não na célula — mesmo arranjo que a coluna
   de papel de Contatos. Na célula ele impedia o texto de explicação
   ("você não desativa a si mesmo") de quebrar, e era esse texto, não os
   botões, que fixava a largura da coluna.

   Medido em Usuários a 1.366, os dois estados no mesmo instante:
     na célula   coluna 199px · tabela rolando 80px · 2 botões cortados
     nos filhos  coluna 121px · tabela rolando  2px · 0 botões cortados
   A altura das linhas não muda (87px nos dois), porque o texto que passa
   a quebrar é mais baixo que os botões ao lado dele. */
.tabela-simples .acoes { text-align: right; }
.tabela-simples .acoes .botao,
.tabela-simples .acoes .botao-icone,
.tabela-simples .acoes a,
.tabela-simples .acoes button { white-space: nowrap; }


.tabela-simples .inativa td { color: var(--tinta-2); }
.tabela-simples .eu td { background: var(--marca-fraca); }
/* E o metadado sobe um degrau aqui dentro — é a regra 1 do tokens.css
   ("a tinta mais fraca vive na superfície mais clara") aplicada a uma
   superfície que não é o bloco. Sobre --marca-fraca, --tinta-3 mede 4,27 e
   --tinta-2 mede 7,57. Achado medindo as 18 telas em 15/09/2026: era o único
   --tinta-3 que sobrava abaixo de 4,5 depois da leva. */
.tabela-simples .eu td .campo-ajuda { color: var(--tinta-2); }

/* position:relative NÃO é cosmético: um .so-leitor (absolute) dentro da
   tabela ancora no ancestral POSICIONADO mais próximo — sem este, ele
   escapa do rolo, ancora no documento e cria rolagem horizontal de
   página (achado na tela de Excluídos, 29/08/2026: o th "Ação" da
   última coluna estourava 308px de body). */
.tabela-rolagem { overflow-x: auto; position: relative; }

/* ══ RODAPÉ DE TABELA · a faixa que fecha o quadro ══════════════════════
   Extrato e Fluxo; a nota e o total, também no Cartão (que guarda a caixa
   dele). A régua de cima separa da última linha; o fundo é o --faixa-acao,
   o da faixa dentro do quadro. */
.tabela-rodape {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--e-3) calc(var(--e-5) + var(--e-2));                        /* 8 · 20 */
  padding: calc(var(--e-4) + var(--e-1)) calc(var(--e-5) + var(--e-1)); /* 14 · 18 */
  background: var(--faixa-acao);
  border-top: 1px solid var(--linha);
}
.tabela-rodape-nota {
  margin: 0;
  flex: 1 1 calc(var(--e-8) * 9);
  font-size: var(--fs-meta);
  line-height: var(--lh-corpo);
  color: var(--tinta-2);
  text-wrap: pretty;
}
.tabela-rodape-nota strong { color: var(--tinta); }
.tabela-rodape-total {
  margin: 0 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: var(--e-4);
  font-size: var(--fs-meta);
  color: var(--tinta-2);
}
.tabela-rodape-total strong {
  font-family: var(--fonte-num);
  font-size: var(--fs-titulo);
  font-weight: var(--peso-forte);
  color: var(--tinta);
  font-variant-numeric: tabular-nums lining-nums;
}

/* ══ PASTILHA DE CATEGORIA · "Grupo › Categoria" e a fatia do rateio ════
   As duas listagens e a Baixa. O nome longo quebra em linhas: o corte
   comeria justamente a categoria, que é o que separa os nomes repetidos
   entre grupos. A fatia só aparece com mais de uma categoria; o número
   dela vem pronto da view, escrito como manda a seção "A leva de peças"
   do CLAUDE.md. */
.pastilha-categoria {
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  max-width: 100%;
  min-height: calc(var(--e-5) + var(--e-2) + var(--e-1));   /* 22px */
  padding: var(--e-1) var(--e-3);
  border-radius: var(--r-1);
  background: var(--banda);
  font-size: var(--fs-rotulo);
  color: var(--tinta-2);
}
.pastilha-categoria-nome { min-width: 0; }
/* --tinta-2, e não --tinta-3: a pastilha pinta --banda, e --tinta-3 sobre
   --banda é o par que a regra 1 de tokens.css proíbe. */
.pastilha-categoria-fatia {
  flex: 0 0 auto;
  color: var(--tinta-2);
  white-space: nowrap;
}
.pastilha-categoria-vazia {
  padding-block: calc(var(--e-1) - 1px);   /* a borda leva 1px de cada lado: 22, como a cheia */
  background: transparent;
  border: 1px dashed var(--linha-2);
  color: var(--tinta-3);
}

/* ══ FILTRO ATIVO · a faixa que diz o que está recortado ════════════════
   Duas formas. A INTERNA mora dentro do quadro (as listagens). A SOLTA
   mora fora dele, com contorno, canto e o botão de voltar: é a do DRE por
   cliente, embaixo do título. O texto quebra em linhas: filtro longo é
   contato e categoria por extenso. */
.filtro-ativo {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  padding: var(--e-3) var(--e-4);
  background: var(--marca-fraca);
  border-bottom: 1px solid var(--marca);
}
.filtro-ativo-rotulo {
  flex: none;
  font-size: var(--fs-rotulo);
  font-weight: var(--peso-forte);
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--marca-forte);
}
.filtro-ativo-texto { min-width: 0; font-size: var(--fs-meta); color: var(--tinta-2); }
.filtro-ativo-texto strong { color: var(--tinta); font-weight: var(--peso-forte); }
.filtro-ativo.solta {
  gap: var(--e-4);
  min-height: calc(var(--e-8) - var(--e-2));                              /* 44 */
  margin-top: var(--e-4);
  padding: calc(var(--e-2) + var(--e-1)) var(--e-3) calc(var(--e-2) + var(--e-1)) calc(var(--e-4) + var(--e-1));
  border: 1px solid var(--marca-linha);
  border-bottom-color: var(--marca);
  border-radius: var(--r-1);
}
.filtro-ativo-voltar {
  flex: none;
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  height: var(--e-7);                                                      /* 32 */
  padding: 0 calc(var(--e-4) + var(--e-1));
  border: 1px solid var(--campo-borda);
  border-radius: var(--r-botao);
  background: var(--bloco);
  font-size: var(--fs-meta);
  font-weight: var(--peso-forte);
  color: var(--tinta-2);
  text-decoration: none;
  white-space: nowrap;
}
.filtro-ativo-voltar:hover { color: var(--tinta); border-color: var(--regua); }

/* ══ CARTÃO VAZIO · o lugar do conteúdo que não existe ══════════════════
   O DRE de um cliente sem lançamento no ano e o Painel gerencial de um mês
   sem movimento: um quadro só, com a frase centrada e o caminho de volta.
   48 · 24 · 52, do desenho, e 28 · 18 sem sombra abaixo de 900. O título
   e o texto também são daqui; a largura do texto e o caminho de volta são
   de cada tela. */
.dre-vazio,
.ger-vazio {
  padding: var(--e-8) var(--e-6) calc(var(--e-8) + var(--e-2));
  background: var(--bloco);
  border: 1px solid var(--bloco-borda);
  border-radius: var(--r-2);
  box-shadow: var(--sh-quadro);
  text-align: center;
}
.dre-vazio-titulo,
.ger-vazio-titulo {
  margin: 0;
  font-size: var(--fs-corpo);
  font-weight: var(--peso-forte);
  color: var(--tinta);
}
.dre-vazio-texto,
.ger-vazio-texto {
  margin: calc(var(--e-2) + var(--e-1)) auto 0;
  font-size: var(--fs-dado);
  line-height: var(--lh-corpo);
  color: var(--tinta-2);
}
@media (max-width: 900px) {
  .dre-vazio,
  .ger-vazio { padding: calc(var(--e-6) + var(--e-2)) calc(var(--e-5) + var(--e-1)); box-shadow: none; }
}

/* ══ COMPARAÇÃO · meta × realizado ═══════════════════════════════════════
   O número da célula é o do DRE (Dinheiro::emParenteses). Estas quatro
   são o que vem ao lado dele: a meta com a marca "parcial" do mês em
   curso, o "sem meta" escrito e o traço da diferença que não existe. */
.comparacao-meta {
  display: flex;
  justify-content: flex-end;
  align-items: baseline;
  gap: calc(var(--e-2) + var(--e-1));
}
.comparacao-nota { font-family: var(--fonte); font-size: var(--fs-meta); color: var(--tinta-2); }
.comparacao-parcial { font-family: var(--fonte); font-size: var(--fs-rotulo); color: var(--tinta-2); }
.comparacao-traco { color: var(--tinta-2); }

/* ══ GRADE DE DOZE MESES · DRE e Fluxo ══════════════════════════════════
   A tabela de uma coluna de rótulo, doze meses e o total do ano. Aqui mora o
   esqueleto que as duas telas dividem: a raiz, o cabeçalho grudado, o canto,
   o mês e o mês corrente, a marca da segunda linha, a coluna do ano, a coluna
   do rótulo grudada e as quatro linhas do balancete do DRE (as classes
   tr.l-*, que só o DRE escreve). O corpo do Fluxo — seção, grupo, categoria
   e as linhas finais no preto — fica em `fluxo.css`. As larguras vêm de
   --col-rotulo, --col-mes e --col-total.

   O CABEÇALHO segue "O cabeçalho de coluna": a altura de uma linha é a do
   --linha-h-cabeca (40), e o padding é o que sobra dela em cima e embaixo da
   palavra, com a régua de 2px dentro da sobra de baixo. Com a marca embaixo
   ("proj.", "atual", "acumulado") a banda cresce a linha da marca e dá 52, e
   os meses de uma linha ficam no meio dela.

   A COLUNA DO RÓTULO é escrita em duas regras, uma para o canto (thead) e
   outra para o corpo (tbody e tfoot). Uma regra só para as duas, com a
   especificidade do corpo, vencia o cabeçalho no canto e o deixava em
   --papel e peso 400. */
.grade-meses {
  border-collapse: separate;   /* separate: sticky não perde a borda */
  border-spacing: 0;
  font-size: var(--fs-dado);
  line-height: var(--lh-dado);
  width: max-content;          /* a tabela tem a largura que precisa */
  min-width: 100%;
}

.grade-meses thead th {
  position: sticky;
  top: 0;
  z-index: 3;
  padding: calc((var(--linha-h-cabeca) - var(--e-5)) / 2) var(--e-4)
           calc((var(--linha-h-cabeca) - var(--e-5)) / 2 - var(--e-1));
  line-height: var(--e-5);
  /* A --faixa-acao, como os outros cabeçalhos de coluna: no claro é o
     --papel-2; no escuro sobe um tom acima do quadro. */
  background: var(--faixa-acao);
  /* 2px: a régua de etapa é 1px na mesma cor, e o cabeçalho é sticky —
     rolando, ele encosta em qualquer linha. Se fossem iguais, num quadro
     intermediário o cabeçalho pareceria uma linha de resultado. */
  border-bottom: var(--e-1) solid var(--regua);
  font-size: var(--fs-rotulo);
  font-weight: var(--peso-medio);
  color: var(--tinta-2);
  text-align: right;
  white-space: nowrap;
}
.grade-meses thead th.grade-meses-rotulo {
  left: 0;
  z-index: 4;                  /* o canto fica acima dos dois eixos */
  width: var(--col-rotulo);
  min-width: var(--col-rotulo);
  max-width: var(--col-rotulo);
  padding-inline: var(--e-5);
  background: var(--faixa-acao);
  font-weight: var(--peso-forte);
  text-align: left;
  box-shadow: var(--sh-coluna);
}
.grade-meses thead th.grade-meses-mes { width: var(--col-mes); }
/* o mês corrente: o sublinhado na cor da marca não toca em número nenhum */
.grade-meses thead th[data-corrente] {
  color: var(--tinta);
  font-weight: var(--peso-forte);
  box-shadow: inset 0 calc(var(--e-1) * -1) 0 var(--marca);
}
/* A segunda linha do cabeçalho. --tinta-2 e não --tinta-3: ela vive também
   sobre --banda (a coluna do ano e a projeção do Fluxo), par que a regra 1
   de tokens.css proíbe para a --tinta-3. */
.grade-meses-marca {
  display: block;
  font-family: var(--fonte);
  font-size: var(--fs-rotulo);
  font-weight: var(--peso-normal);
  line-height: var(--e-4);
  color: var(--tinta-2);
}

.grade-meses .grade-meses-ano {
  width: var(--col-total);
  background: var(--banda);
  border-left: 1px solid var(--linha-2);
}
.grade-meses thead th.grade-meses-ano { color: var(--tinta); font-weight: var(--peso-forte); }

/* A coluna do rótulo no corpo. Fundo OPACO: ela gruda, e fundo transparente
   deixaria o miolo passar por baixo dela na rolagem. */
.grade-meses :is(tbody, tfoot) th.grade-meses-rotulo {
  position: sticky;
  left: 0;
  z-index: 2;
  width: var(--col-rotulo);
  min-width: var(--col-rotulo);
  max-width: var(--col-rotulo);
  padding-inline: var(--e-5);
  background: var(--papel);
  font-weight: var(--peso-normal);
  text-align: left;
  box-shadow: var(--sh-coluna);
}

/* As quatro linhas do balancete, na grade do DRE e na tabela do DRE
   resumido do Painel gerencial (.ger-tabela). A base da célula (altura de
   28, régua de 1px --linha em cima, padding e fundo) é da folha de cada
   tela; aqui fica o que distingue as quatro. O peso vai só nos números
   (td): o rótulo tem o peso no nome, e o sinal "(=)" fica em 400. */
:is(.grade-meses, .ger-tabela) tr.l-componente > td { font-weight: var(--peso-normal); }
:is(.grade-meses, .ger-tabela) tr.l-subtotal > td { font-weight: var(--peso-medio); }
.grade-meses tr.l-etapa,
.grade-meses tr.l-final { height: var(--linha-h-resultado); }
:is(.grade-meses, .ger-tabela) tr.l-etapa > th,
:is(.grade-meses, .ger-tabela) tr.l-etapa > td {
  height: var(--linha-h-resultado);
  border-top: 1px solid var(--regua);
  padding-top: var(--e-2);          /* o ar entre a régua e o texto */
}
/* A linha final vai no <tfoot>, que gruda embaixo: sem isso a resposta do
   relatório nasce abaixo da dobra. O sticky vai no tfoot e não nas células,
   que não grudam dentro da própria linha. A régua dupla é de 4px: a 125% de
   escala do Windows, 3px viram 2,4 e os dois fios se fecham. Ela é `border`,
   e não `box-shadow`: o vão entre os dois fios fica transparente e mostra o
   fundo da célula, e por isso acerta sobre o papel, sobre a coluna do ano e
   no tema escuro. Uma sombra precisaria pintar o vão de uma cor fixa. */
.grade-meses tfoot {
  position: sticky;
  bottom: 0;
  z-index: 5;
}
:is(.grade-meses, .ger-tabela) tr.l-final > th,
:is(.grade-meses, .ger-tabela) tr.l-final > td {
  height: var(--linha-h-resultado);
  border-top: var(--e-2) double var(--regua);
  padding-top: var(--e-2);
  color: var(--tinta);
}
:is(.grade-meses, .ger-tabela) :is(tr.l-etapa, tr.l-final) > td { font-weight: var(--peso-forte); }
/* a coluna de rótulo da linha final cruza os dois eixos grudados */
.grade-meses tfoot th.grade-meses-rotulo { z-index: 6; }

/* O total do ano, um degrau acima dos meses da própria linha. */
.grade-meses tr.l-componente > td.grade-meses-ano { font-weight: var(--peso-medio); }
.grade-meses :is(tr.l-subtotal, tr.l-etapa, tr.l-final) > td.grade-meses-ano { font-weight: var(--peso-forte); }

/* O zero recua para não competir. Escrito depois das linhas e com a
   especificidade delas, para valer também na categoria e na linha final.
   Na coluna do ano ele fica em --tinta-2: --tinta-3 sobre --banda é o par
   que a regra 1 de tokens.css proíbe. */
.grade-meses :is(tbody, tfoot) td.zero { color: var(--tinta-3); }
.grade-meses td.grade-meses-ano.zero { color: var(--tinta-2); }

/* No celular a coluna do rótulo encolhe para 192: com os 340 do computador
   ela cobriria a moldura inteira, e a 390 nenhum mês apareceria. Na coluna
   estreita o nome quebra em linhas, e o respiro lateral é 12. */
@media (max-width: 900px) {
  .grade-meses :is(thead, tbody, tfoot) th.grade-meses-rotulo {
    width: calc(var(--e-8) * 4);
    min-width: calc(var(--e-8) * 4);
    max-width: calc(var(--e-8) * 4);
    padding-inline: var(--e-4);
    white-space: normal;
  }
}

/* ══ FAIXA PRETA · o número grande sobre o preto do menu ════════════════
   Painel, Cartão, Contas correntes, Extrato e Fluxo. O preto é o --rail:
   superfície que flutua sobre a tela e carrega números, não uma zona da
   página. Aqui mora o que as cinco têm igual; o arranjo de cada uma — a
   grade do Painel, a linha do Extrato, o limite do Cartão, o vão entre as
   colunas da legenda — fica na folha dela. A folga de 22·24 é a do Cartão,
   das Contas e do Fluxo; o Painel e o Extrato escrevem a deles.

   O SINAL DO NEGATIVO VAI ESCRITO junto do R$ ("−R$ 10.046,62"), e o R$
   não é escondido do leitor de tela: com ele escondido, o leitor lia o
   número sem o sinal. */
.faixa-preta {
  padding: calc(var(--e-5) + var(--e-2) + var(--e-1)) var(--e-6);
  background: var(--rail);
  border-radius: var(--r-2);
}
.faixa-preta-linha {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: var(--e-6) var(--e-7);
}
.faixa-preta-bloco { min-width: 0; }

/* O rótulo sobre o número. É flex porque no Cartão ele leva o selo da
   fatura ao lado da palavra. */
.faixa-preta-rotulo {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  margin: 0;
  font-size: var(--fs-meta);
  font-weight: var(--peso-normal);
  color: var(--rail-ink-2);
}
/* A linha do número mede o próprio número: com a altura de linha 1, o R$,
   menor, fica dentro da caixa dele pela linha de base. */
.faixa-preta-numero {
  display: flex;
  align-items: baseline;
  gap: var(--e-3);
  margin: calc(var(--e-2) + var(--e-1)) 0 0;
  line-height: 1;
}
.faixa-preta-moeda {
  font-family: var(--fonte-num);
  font-size: var(--fs-titulo);
  font-weight: var(--peso-normal);
  color: var(--rail-ink-2);
}
.faixa-preta-valor {
  font-family: var(--fonte-num);
  font-size: var(--fs-destaque);            /* 42px — o degrau do saldo */
  font-weight: var(--peso-medio);
  letter-spacing: -.035em;
  line-height: 1;
  color: var(--rail-ink);
  font-variant-numeric: tabular-nums lining-nums;
}
/* O número de 26: a projeção do Painel e o saldo inicial do Extrato. */
.faixa-preta-moeda.menor { font-size: var(--fs-dado); }
.faixa-preta-valor.menor { font-size: var(--fs-tela); letter-spacing: -.03em; }
/* O número de 32, para o saldo final do Extrato. */
.faixa-preta-moeda.medio { font-size: var(--fs-corpo); }
.faixa-preta-valor.medio { font-size: var(--fs-numerao); }
.faixa-preta-sub { margin: calc(var(--e-2) + var(--e-1)) 0 0; font-size: var(--fs-rotulo); color: var(--rail-ink-2); }

/* Os fatos de 19px, à direita do número grande. O vão entre eles é de cada
   tela. */
.faixa-preta-fatos {
  margin-left: auto;
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
}
.faixa-preta-fato { display: flex; flex-direction: column; gap: var(--e-2); }
.faixa-preta-fato-rotulo {
  display: flex;
  align-items: center;
  gap: calc(var(--e-2) + var(--e-1));
  font-size: var(--fs-rotulo);
  color: var(--rail-ink-2);
  white-space: nowrap;
}
.faixa-preta-fato-valor {
  font-family: var(--fonte-num);
  font-size: var(--fs-titulo);
  font-weight: var(--peso-normal);
  color: var(--rail-ink);
  font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap;
}

/* A fita de proporção e a legenda dela: UMA fita, contínua, e a legenda
   escrita embaixo, para a cor nunca ser a única portadora. A margem acima
   da fita e o vão entre as colunas da legenda são de cada tela. */
.faixa-preta-fita {
  display: flex;
  height: calc(var(--e-2) + var(--e-1));
  border-radius: var(--r-1);
  overflow: hidden;
  background: var(--rail-linha);
}
.faixa-preta-fatia { display: block; height: 100%; }
.faixa-preta-fatia-1 { background: var(--rail-fatia-1); }
.faixa-preta-fatia-2 { background: var(--rail-fatia-2); }
.faixa-preta-fatia-3 { background: var(--rail-fatia-3); }
.faixa-preta-fatia-4 { background: var(--rail-fatia-4); }
.faixa-preta-legenda {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  row-gap: var(--e-3);
  margin: calc(var(--e-3) + var(--e-1)) 0 0;
  padding: 0;
}
.faixa-preta-legenda-item { display: flex; align-items: center; gap: calc(var(--e-2) + var(--e-1)); white-space: nowrap; }
.faixa-preta-legenda-cor { width: 9px; height: 9px; border-radius: var(--r-1); }
.faixa-preta-legenda-nome { font-size: var(--fs-rotulo); color: var(--rail-ink-2); }
.faixa-preta-legenda-valor {
  font-family: var(--fonte-num);
  font-size: var(--fs-rotulo);
  color: var(--rail-ink);
  font-variant-numeric: tabular-nums lining-nums;
}

/* A coluna separada por régua (a projeção do Painel). No celular a régua
   deita: sem isto a borda esquerda ficaria pendurada no nada. */
.faixa-preta-coluna {
  min-width: 0;
  padding-left: var(--e-6);
  border-left: 1px solid var(--rail-linha);
}

@media (max-width: 900px) {
  .faixa-preta { padding: var(--e-5); }
  .faixa-preta-fatos { margin-left: 0; }
  .faixa-preta-coluna {
    padding-left: 0;
    padding-top: var(--e-5);
    border-left: 0;
    border-top: 1px solid var(--rail-linha);
  }
}

/* No celular o número grande cai para o degrau de 32. O de 26 e o de 32 das
   variantes ficam como estão, pela especificidade. */
@media (max-width: 640px) {
  .faixa-preta-valor { font-size: var(--fs-numerao); }
}

/* ══ CÉLULA DE NÚMERO · o número de 32 num quadro dividido ══════════════
   O "O que vence hoje" e os vencidos do Painel, os números da Baixa e das
   Contas correntes, e o Painel gerencial. `.celulas` é o contêiner: as
   divisórias de 1px são o fundo dele aparecendo pelo vão, sem borda em cada
   célula. A largura-base de cada célula é da tela.

   O SINAL VAI NO R$ ("+R$", "−R$"), como na faixa preta, e o zero sai sem
   sinal. */
.celulas { display: flex; flex-wrap: wrap; gap: 1px; background: var(--linha); }
.celula {
  flex: 1 1 0;
  min-width: 0;
  padding: var(--e-5) calc(var(--e-5) + var(--e-1)) calc(var(--e-5) + var(--e-1));
  background: var(--bloco);
}
.celula-rotulo {
  display: block;
  margin: 0;
  font-size: var(--fs-meta);
  font-weight: var(--peso-forte);
  line-height: var(--lh-dado);
  color: var(--tinta);
}
/* A linha do número mede o próprio número: com a altura de linha 1, o R$,
   menor, fica dentro da caixa dele pela linha de base. */
.celula-numero {
  display: flex;
  align-items: baseline;
  gap: calc(var(--e-2) + var(--e-1));
  margin: calc(var(--e-3) + var(--e-1)) 0 0;
  line-height: 1;
}
.celula-moeda {
  font-family: var(--fonte-num);
  font-size: var(--fs-meta);
  font-weight: var(--peso-normal);
  color: var(--tinta-2);
}
.celula-valor {
  font-family: var(--fonte-num);
  font-size: var(--fs-numerao);
  font-weight: var(--peso-medio);
  letter-spacing: -.03em;
  line-height: 1;
  color: var(--tinta);
  font-variant-numeric: tabular-nums lining-nums;
}
/* O zero apaga o número e o R$ juntos, para o R$ não ficar mais escuro que
   o número ao lado dele. */
.celula-numero.vazio > * { color: var(--tinta-3); }
/* O "—" de quando não há valor (a margem de um mês sem receita) não é zero:
   fica em --tinta-2. */
.celula-valor.sem-valor { color: var(--tinta-2); }
.celula-sub {
  margin: var(--e-3) 0 0;
  font-size: var(--fs-rotulo);
  line-height: var(--lh-corpo);
  color: var(--tinta-2);
}
/* A variação contra o mês anterior, com a seta de 12 centrada na primeira
   linha do texto. O texto vem de App\Core\Variacao. */
.celula-variacao {
  display: flex;
  align-items: flex-start;
  gap: calc(var(--e-2) + var(--e-1));
  margin: var(--e-3) 0 0;
  font-size: var(--fs-rotulo);
  line-height: var(--lh-corpo);
  color: var(--tinta-2);
}
.celula-seta {
  flex: none;
  width: var(--e-4);
  height: var(--e-4);
  margin-top: calc((var(--fs-rotulo) * var(--lh-corpo) - var(--e-4)) / 2);
}

/* No celular o número da célula vai a 26. O total do vencido do Painel usa a
   linha do número fora de uma célula, e fica em 32. */
@media (max-width: 640px) {
  .celula .celula-valor { font-size: var(--fs-tela); }
}

/* ══ SELETOR DE PERÍODO · o mês ou o ano, com as setas dos lados ═══════
   As duas listagens (o mês), o DRE e o Fluxo (o ano), no topo; e o mês da
   lista do celular do DRE, dentro do quadro dela (o lugar e a largura ali
   são do dre.css). A seta aceita `<button>` além de `<a>`, para a peça poder
   ir para dentro de um quadro. A caixa é controle: contorno em
   --campo-borda, fundo --bloco. As réguas entre as setas e o rótulo são
   divisória, em --linha-2. O lugar da caixa no topo é do shell.css. */
.periodo {
  display: inline-flex;
  align-items: center;
  height: var(--campo-h);
  border: 1px solid var(--campo-borda);
  border-radius: var(--r-1);
  background: var(--bloco);
  overflow: hidden;
}
.periodo-rotulo {
  padding: 0 calc(var(--e-4) + var(--e-1));
  font-size: var(--fs-dado);
  font-weight: var(--peso-medio);
  color: var(--tinta);
  text-align: center;
  white-space: nowrap;
}
/* O mês tem largura mínima, para a seta da direita não andar de um mês para
   o outro: 152 cobrem "novembro de 2026", o mais largo. O ano é `.num`, de
   algarismos da mesma largura. */
.periodo-mes { min-width: calc(var(--e-8) * 3 + var(--e-3)); }
.periodo-seta {
  display: grid;
  place-items: center;
  width: var(--e-7);
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--tinta-2);
  font: inherit;
  text-decoration: none;
  cursor: pointer;
}
.periodo-seta:first-child { border-right: 1px solid var(--linha-2); }
.periodo-seta:last-child  { border-left: 1px solid var(--linha-2); }
.periodo-seta .ic {
  width: calc(var(--e-4) + var(--e-1));
  height: calc(var(--e-4) + var(--e-1));
  stroke-width: 2;
}
.periodo-seta:not(.desativada):hover { background: var(--faixa-acao); color: var(--tinta); }
.periodo-seta.desativada { color: var(--linha-2); cursor: default; }
/* O anel de foco fica por dentro da seta: por fora, a caixa o cortaria. */
.periodo-seta:focus-visible { outline-offset: calc(var(--e-1) * -1); }

/* No celular a caixa vai a 46, para as setas terem 44 de toque por dentro
   da borda. */
@media (max-width: 900px) {
  .periodo { height: calc(var(--e-8) - var(--e-1)); }
  .periodo-seta { flex: none; width: calc(var(--e-8) - var(--e-2)); }
  .periodo-seta .ic { width: var(--e-5); height: var(--e-5); }
  .periodo-rotulo { flex: 1 1 auto; }
}

/* Abaixo de 375 o mês perde parte da folga, para a caixa caber sem as setas
   encolherem: 130, com 4 de cada lado, ainda cobrem "novembro de 2026". */
@media (max-width: 374px) {
  .periodo-mes {
    min-width: calc(var(--e-8) * 2 + var(--e-7) + var(--e-1));
    padding-inline: var(--e-2);
  }
}

/* ══════════════════════════════════════════════════════════════════════
   MODAL · o padrão v3 de diálogo
   Nasceu no cadastro rápido de contato (spec 5.4) e vale daqui em diante.
   É o quadro da v3 — --bloco, contorno --linha-2, raio --r-2 — flutuando
   sobre um escurecimento; nada visual novo além do véu.

   Regras do padrão:
   · <dialog> nativo, aberto com showModal(): o foco fica preso dentro e
     Esc fecha de graça — sem reimplementar o que o navegador já faz.
   · UM primário, o da ação que dá nome ao modal; Cancelar é botão comum.
   · Erro aparece DENTRO do modal, no campo, e nada do que está por trás
     é recarregado — o que a pessoa estava fazendo não pode ser perdido.
   As janelas de excluir lançamentos (as listagens) e de estornar baixa
   (a Baixa) também são este modal.
   ══════════════════════════════════════════════════════════════════════ */
.modal {
  width: min(calc(var(--e-8) * 11), calc(100vw - var(--e-6) * 2));   /* 528px */
  padding: 0;
  border: 1px solid var(--linha-2);
  border-radius: var(--r-2);
  box-shadow: var(--sh-modal);
  background: var(--bloco);
  color: var(--tinta);
}
.modal::backdrop { background: var(--veu); }

/* O CORPO E O PÉ DO MODAL TÊM O MESMO INSET LATERAL, e é por isso que este
   valor mudou junto com o do `.modal-acoes`: eram 24 nos dois, o pé foi a
   18 com a leva do formulário e o corpo ficou em 24 — os botões do pé
   começavam 6px mais para fora que o texto logo acima, nos cinco modais do
   sistema, um deles o aviso de sessão que aparece nas 22 telas.
   Achado pela auditoria independente de 20/09/2026. */
.modal-corpo { padding: calc(var(--e-5) + var(--e-1)); }

.modal-titulo {
  margin: 0 0 var(--e-4);
  font-size: var(--fs-corpo);
  font-weight: var(--peso-forte);
  color: var(--tinta);
}

.modal-nota { margin: 0 0 var(--e-4); font-size: var(--fs-meta); color: var(--tinta-2); }


/* ══════════════════════════════════════════════════════════════════════
   CELULAR — o que é COMUM a várias telas (29/08/2026)

   UM bloco só neste arquivo, na régua única de 900px (a mesma do
   menu-faixa do shell). Dois blocos @media com a mesma largura na mesma
   folha é a armadilha do --r-1 declarado duas vezes: vale o último, e
   quem lê o primeiro trecho acredita no valor errado.

   O desktop não lê NADA daqui — a prova da leva é o retrato de medidas a
   1366×768, que tem de sair idêntico.
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {

  /* ── Barra de ação ──────────────────────────────────────────────────
     Nota e botões lado a lado não cabem em ~318px de largura útil. Era o
     que estourava a página em Novo lançamento (545px), Editar série
     (477), Baixa (421) e Exportação (460) — quatro telas, um defeito só.
     `overflow-wrap: anywhere` no <code> não é enfeite: o caminho da
     pasta em Exportação é uma palavra só, e só o `anywhere` reduz o
     min-content do item flex, que é a medida que estoura. */
  .form-acoes { flex-wrap: wrap; padding: var(--e-4); }
  .form-acoes-nota { flex: 1 0 100%; margin-right: 0; }
  .form-acoes-nota code { overflow-wrap: anywhere; }
  .form-acoes .botao {
    flex: 1 1 auto;
    height: auto;
    min-height: calc(var(--e-8) - var(--e-2));   /* 44px, o mínimo de toque */
  }

  /* ── Respiro da seção ───────────────────────────────────────────────
     Os 18px do computador ainda gastam mais de 10% da tela de um celular
     — logo depois de o shell ter cortado o PRÓPRIO padding de 24 para 12
     pelo mesmo motivo. Aqui caem para 12. O canto arredondado não se
     perde: o raio vem dos filhos das pontas do .form-bloco, não daqui. */
  .form-secao { padding: var(--e-5) var(--e-4); }

  /* ── Alvo de toque: botão de formulário e de modal ─────────────────
     No computador o botão tem 38, e 40 quando está na faixa de ação de
     um formulário ou de um modal; no toque o mínimo é 44, venha de onde
     vier. */
  .form-bloco .botao, .modal .botao {
    height: auto;
    min-height: calc(var(--e-8) - var(--e-2));
  }

  /* O total do rodapé de tabela desce para a linha dele, à esquerda. */
  .tabela-rodape-total { margin-left: 0; }

  /* A faixa "Filtro ativo" solta empilha, e o botão de voltar vira a linha
     inteira, com o alvo de toque de 44. */
  .filtro-ativo.solta {
    display: block;
    padding: calc(var(--e-3) + var(--e-1)) var(--e-4);
  }
  .filtro-ativo.solta .filtro-ativo-texto { display: block; margin-top: var(--e-1); }
  .filtro-ativo.solta .filtro-ativo-voltar {
    display: flex;
    justify-content: center;
    width: 100%;
    height: auto;
    min-height: calc(var(--e-8) - var(--e-2));
    margin-top: var(--e-3);
    font-size: var(--fs-dado);
  }

  /* ── Paginação ──────────────────────────────────────────────────────
     30×30 com 4px de separação: 32% abaixo do mínimo, e os alvos quase
     se tocando. */
  .paginacao-paginas { gap: var(--e-3); }
  .pagina, .pagina-salto {
    min-width: calc(var(--e-8) - var(--e-2));
    height: calc(var(--e-8) - var(--e-2));
  }

  /* ── TABELA VIRA CARTÃO — o reset, uma vez só ───────────────────────
     As tabelas desta lista precisam exatamente do mesmo reset. O que
     impede o cartão é `tbody td { height: 44px; border-bottom }` e o que
     fixa o piso de largura é `thead th { white-space: nowrap }`.

     A LISTA É EXPLÍCITA, NUNCA `.tabela-simples` SOLTO: a tela de Baixa
     usa a mesma classe e foi aprovada em 27/08 sem estouro — varrê-la
     junto seria regressão numa tela pronta. Cada nome aqui é uma tela
     que EU medi estourando.

     `width: auto` é indispensável: .aud-quando e .aud-ip têm `width: 1%`
     (truque de tabela), que como item de grade vira ~3px e faz o texto
     vazar por cima do vizinho. */
  .cat-arvore, .con-tabela, .cta-ultimas, .ext-tabela,
  .aud-tabela, .exp-tabela, .ct-tabela, .lanc-grade-tabela {
    display: block;
    min-width: 0;
    border: 0;
  }
  .cat-arvore thead, .con-tabela thead, .cta-ultimas thead, .ext-tabela thead,
  .aud-tabela thead, .exp-tabela thead, .ct-tabela thead, .lanc-grade-tabela thead {
    display: none;
  }
  .cat-arvore tbody, .con-tabela tbody, .cta-ultimas tbody, .ext-tabela tbody,
  .aud-tabela tbody, .exp-tabela tbody, .ct-tabela tbody, .lanc-grade-tabela tbody,
  .cat-arvore tfoot, .ext-tabela tfoot, .ct-tabela tfoot,
  .lanc-grade-tabela tfoot {
    display: block;
  }
  .cat-arvore tbody tr, .con-tabela tbody tr, .cta-ultimas tbody tr,
  .ext-tabela tbody tr, .aud-tabela tbody tr, .exp-tabela tbody tr,
  .ct-tabela tbody tr, .lanc-grade-tabela tbody tr,
  .cat-arvore tfoot tr, .ext-tabela tfoot tr,
  .ct-tabela tfoot tr, .lanc-grade-tabela tfoot tr {
    display: grid;
    gap: var(--e-1) var(--e-3);
    padding: var(--e-4);
    border: 1px solid var(--linha-2);
    border-top: 0;
  }
  .cat-arvore tbody tr:first-child, .con-tabela tbody tr:first-child,
  .cta-ultimas tbody tr:first-child, .ext-tabela tbody tr:first-child,
  .aud-tabela tbody tr:first-child, .exp-tabela tbody tr:first-child,
  .ct-tabela tbody tr:first-child, .lanc-grade-tabela tbody tr:first-child {
    border-top: 1px solid var(--linha-2);
  }
  /* `tbody td`, não `td`: a regra que fixa a altura em 44px é
     `.tabela-simples tbody td` (0,1,2), e um `.con-tabela td` (0,1,1)
     perde para ela — nem dentro de @media, nem vindo depois. Empatar a
     especificidade e vir depois no arquivo é o que faz valer. */
  .cat-arvore tbody td, .con-tabela tbody td, .cta-ultimas tbody td,
  .ext-tabela tbody td, .aud-tabela tbody td, .exp-tabela tbody td,
  .ct-tabela tbody td, .lanc-grade-tabela tbody td,
  .cat-arvore tfoot td, .ext-tabela tfoot td,
  .ct-tabela tfoot td, .lanc-grade-tabela tfoot td {
    display: block;
    height: auto;
    width: auto;
    min-width: 0;
    max-width: none;
    padding: 0;
    border: 0;
    text-align: left;
  }
}
