@charset "UTF-8";
/* ==========================================================================
   sgm-components.css — peças reutilizáveis
   Card de quadro, indicador, grid HTML, chip, aviso, estados de carga,
   vazio e erro. Todo componente traz os estados; nada sai daqui pela metade.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Grade do painel
   Os cards têm tamanhos diferentes de propósito — um quadro de 12 meses não
   ocupa o mesmo espaço que um medidor. O span é decidido pelo conteúdo.
   -------------------------------------------------------------------------- */

.sgm-grade {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--sgm-4);
  align-items: start;
}

.sgm-col-3  { grid-column: span 3; }
.sgm-col-4  { grid-column: span 4; }
.sgm-col-6  { grid-column: span 6; }
.sgm-col-8  { grid-column: span 8; }
.sgm-col-12 { grid-column: span 12; }

/* --------------------------------------------------------------------------
   1a. O CORAÇÃO — REGRA DE OURO 12

   Favorita o quadro para o "Meu painel". Vazado e discreto por padrão, cheio
   e vermelho quando marcado — o mesmo par do legado (`far fa-heart` preto ×
   `fas fa-heart` vermelho, uContabilidade.pas:299-306).

   ⚠️ O vermelho é o da paleta validada (#e34948), e não um vermelho qualquer:
   ele divide a tela com as barras dos gráficos, e duas famílias de vermelho
   lado a lado é o tipo de coisa que ninguém sabe nomear mas todo mundo vê.
   -------------------------------------------------------------------------- */

.sgm-fav {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--color-on-surface-muted);
  cursor: pointer;
  font-size: 15px;
  transition: color .15s ease, background-color .15s ease;
}

.sgm-fav:hover { background: var(--color-surface-sunken); }

.sgm-fav[aria-pressed="true"] { color: #e34948; }

/* --------------------------------------------------------------------------
   1b. O CARD DE NÚMERO — a simetria é de ALTURA, não de largura

   Os cinco cards de número da Contabilidade (Disponibilidade, Restos,
   Pagamentos, Receita×Dívida, Conta Corrente) têm conteúdo desigual: o Conta
   Corrente mostra só o destaque, o Pagamentos mostra três auxiliares. Cada um
   parando na sua altura deixa os botões Ajuda/Detalhes em linhas diferentes,
   e a fileira fica desalinhada.

   ⚠️ A CORREÇÃO É `align-self`, E NÃO `align-items`. A grade do painel tem
   `align-items: start` de propósito — sem ele, um card curto ao lado de um
   gráfico de 300px esticaria e ficaria com um vazio enorme. Mudar o container
   afetaria TODOS os quadros de TODOS os módulos. Mudando o item, só quem pede
   estica, e cada card vai à altura DA SUA LINHA:

     linha 1   Disponibilidade · Restos · Pagamentos · Receita×Dívida
               -> todos na altura do maior, que é o Receita×Dívida
     linha 2   Conta Corrente + os medidores
               -> o Conta Corrente na altura do gauge, que é o vizinho dele

   É o que o Rodrigo pediu em 2026-08-12, e sai de uma linha só: a altura da
   linha do grid já é a do item mais alto, e o `stretch` faz o resto.

   🥇 A versão anterior disto era uma faixa de cinco trilhas, copiando o
   `mcontainer` do legado. Cinco cards numa linha ficaram ESTREITOS DEMAIS e o
   Rodrigo derrubou na hora. A lição: copiar a ESTRUTURA do legado não é o
   mesmo que copiar o resultado — lá a fileira de cinco cabe porque o card
   legado é mais apertado; aqui o mesmo agrupamento espremeu o conteúdo.
   -------------------------------------------------------------------------- */

.sgm-card--num {
  align-self: stretch;
  display: flex;
  flex-direction: column;
}

/* O corpo ocupa a sobra e centra o número nela — assim o rodapé desce sozinho
   para o fim do card, e os botões alinham entre os vizinhos da linha. */
.sgm-card--num > .sgm-card__corpo {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

@media (max-width: 1279px) {
  .sgm-col-3 { grid-column: span 6; }
  .sgm-col-4 { grid-column: span 6; }
  .sgm-col-8 { grid-column: span 12; }
}

@media (max-width: 767px) {
  .sgm-grade { gap: var(--sgm-3); }
  .sgm-col-3, .sgm-col-4, .sgm-col-6, .sgm-col-8 { grid-column: span 12; }
}

/* --------------------------------------------------------------------------
   2. Card
   -------------------------------------------------------------------------- */

.sgm-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--color-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-lg);
  box-shadow: var(--sgm-sh-2);
  overflow: hidden;
  transition: box-shadow var(--sgm-normal) var(--sgm-ease),
              border-color var(--sgm-normal) var(--sgm-ease);
}

.sgm-card:hover { box-shadow: var(--sgm-sh-3); border-color: var(--color-outline-strong); }

/* destaque ao chegar pelo submenu: o clique precisa ter efeito visível mesmo
   quando o quadro já estava na tela */
.sgm-card[data-destaque="true"] {
  border-color: var(--color-primary-500);
  box-shadow: var(--sgm-sh-3), 0 0 0 3px rgba(15, 118, 110, .16);
}

/* --------------------------------------------------------------------------
   Diálogo — ajuda do quadro
   -------------------------------------------------------------------------- */

.sgm-dialog {
  width: min(560px, calc(100vw - 32px));
  padding: 0;
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-lg);
  box-shadow: var(--sgm-sh-4);
  color: var(--color-on-surface);
  background: var(--color-surface);
}

/* A ficha precisa caber uma grid de dez colunas; 560px espremeria o item a
   item a ponto de a tela não responder o que existe para responder.

   ALTURA: o corpo do diálogo comum para em 60vh, e na ficha isso punha o
   cabeçalho inteiro em rolagem — apontado pelo Rodrigo em 2026-08-10, com o
   print. Aqui vai a 88vh, para a ficha caber sem barra. Junto com os campos
   mais baixos, é o que faz o pedido inteiro aparecer de uma vez.

   ⚠️ POPUP QUE ROLA É POPUP QUE NÃO SINTETIZOU. A regra desta tela é caber:
   ao acrescentar campo, veja se algum outro pode sair. */
.sgm-dialog--largo { width: min(1100px, calc(100vw - 32px)); }
.sgm-dialog--largo .sgm-dialog__corpo { max-height: 88vh; }

.sgm-dialog::backdrop {
  background: rgba(11, 25, 33, .42);
  backdrop-filter: blur(2px);
}

.sgm-dialog__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sgm-3);
  padding: var(--sgm-4) var(--sgm-5) var(--sgm-3);
  border-bottom: 1px solid var(--color-outline);
}

.sgm-dialog__titulo { font-size: var(--sgm-t-md); font-weight: 650; }
.sgm-dialog__sub    { margin-top: 2px; font-size: var(--sgm-t-sm); color: var(--color-on-surface-variant); }

.sgm-dialog__corpo {
  padding: var(--sgm-4) var(--sgm-5);
  font-size: var(--sgm-t-base);
  line-height: 1.62;
  color: var(--color-on-surface-variant);
  max-height: 60vh;
  overflow: auto;
}

/* A linha escolhível do diálogo de busca (Cat./Gru./Mod./Ele.). É um
   <button> e não uma <li> com clique: assim o Tab chega nela, o Enter
   escolhe e o leitor de tela a anuncia como ação — de graça. */
.sgm-lista-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: var(--sgm-2) var(--sgm-3);
  border: 0;
  border-radius: var(--sgm-r-2);
  background: transparent;
  color: var(--color-on-surface);
  font: inherit;
  cursor: pointer;
}
.sgm-lista-item:hover { background: var(--color-surface-sunken); }
.sgm-lista-item:focus-visible {
  outline: 2px solid var(--color-primary-500);
  outline-offset: -2px;
}
.sgm-lista-item b { color: var(--color-on-surface-variant); margin-right: var(--sgm-2); }
.sgm-dialog__corpo p { margin-bottom: var(--sgm-3); }
.sgm-dialog__corpo p:last-child { margin-bottom: 0; }
.sgm-dialog__corpo dt { font-weight: 650; color: var(--color-on-surface); margin-top: var(--sgm-3); }
.sgm-dialog__corpo dd { margin: 2px 0 0; }

/* --------------------------------------------------------------------------
   O botão de fechar do diálogo

   Era um ícone fantasma, do mesmo cinza do resto do cabeçalho, e o Rodrigo
   apontou com o print: num popup que se abre por cima de outro, e que às
   vezes é o terceiro da pilha, sair TEM de ser óbvio. Um X apagado no canto
   obriga a procurar a saída de uma tela que se está tentando deixar.

   Vermelho e sólido, na forma que ele mandou de referência. É o único botão
   destrutivo-por-acidente da tela — e a cor diz o que ele faz.
   -------------------------------------------------------------------------- */

.sgm-dialog__fechar {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  font-size: 15px;
  border: 0;
  border-radius: var(--sgm-r-sm);
  cursor: pointer;
  color: #fff;
  background: #e34948;
  box-shadow: var(--sgm-sh-1);
  transition: background var(--sgm-fast) var(--sgm-ease),
              transform var(--sgm-fast) var(--sgm-ease);
}

.sgm-dialog__fechar:hover  { background: #c9302f; transform: scale(1.05); }
.sgm-dialog__fechar:active { transform: scale(.96); }
.sgm-dialog__fechar:focus-visible {
  outline: 2px solid #e34948;
  outline-offset: 2px;
}

.sgm-dialog__pe {
  display: flex;
  justify-content: flex-end;
  gap: var(--sgm-2);
  padding: var(--sgm-3) var(--sgm-5);
  border-top: 1px solid var(--color-outline);
  background: var(--color-surface-sunken);
}

/* --------------------------------------------------------------------------
   Meu perfil — o bloco de leitura

   Login e perfil de acesso não são campos: são fatos. Ficam num painel
   afundado, sem borda de input, justamente para não parecerem editáveis e
   depois frustrar quem tentar clicar.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   🥇 O PERFIL NO FORMATO DO ModeloPadrao (2026-08-14)

   Porte de `modules/admin/paginas/perfil/perfil.component.ts`: faixa colorida,
   avatar redondo com as iniciais MONTADO SOBRE ela, nome grande e a linha de
   apoio embaixo. É, nas palavras do próprio modelo, "o arranjo de tela mais
   reaproveitável do sistema" — o mesmo que serve a ficha de servidor e a
   cadastro de contribuinte.

   ⚠️ `.sgm-perfil__fixos`, `__rot` e `__val` SAÍRAM: eram o par Login /
   Perfil de acesso numa caixa afundada, e os dois subiram para o cabeçalho.
   Duas formas de mostrar a mesma coisa, na mesma tela, seria a divergência
   esperando acontecer.
   -------------------------------------------------------------------------- */

.sgm-perfil__capa {
  height: 84px;
  background: linear-gradient(90deg, var(--color-primary-700), var(--color-primary-500));
}

.sgm-perfil__cab {
  display: flex;
  align-items: flex-end;
  gap: var(--sgm-4);
  padding: 0 var(--sgm-5) var(--sgm-4);
}

/* o avatar sobe sobre a faixa — é o que dá a profundidade do modelo, e o
   valor de -40px é metade da altura dele */
.sgm-perfil__avatar {
  flex: 0 0 auto;
  margin-top: -40px;
  display: grid;
  place-items: center;
  width: 80px; height: 80px;
  border-radius: 50%;
  border: 4px solid var(--color-surface);
  background: var(--color-primary-500);
  color: #fff;
  font-size: var(--sgm-t-xl);
  font-weight: 650;
  letter-spacing: .02em;
}

.sgm-perfil__id { min-width: 0; padding-bottom: 2px; }

.sgm-perfil__sub {
  margin: 2px 0 0;
  display: flex;
  align-items: center;
  gap: var(--sgm-2);
  font-size: var(--sgm-t-sm);
  color: var(--color-on-surface-variant);
  overflow-wrap: anywhere;
}
.sgm-perfil__sub strong { color: var(--color-on-surface); font-weight: 650; }

/* O rótulo de seção do modelo: caixa-alta pequena e um traço que corre até a
   borda. Fica fora de `.sgm-perfil__` porque não é do perfil — é o separador
   de assunto que qualquer formulário longo vai querer. */
.sgm-secao {
  display: flex;
  align-items: center;
  gap: var(--sgm-2);
  margin: 0 0 var(--sgm-3);
  font-size: var(--sgm-t-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--color-on-surface-variant);
}

.sgm-secao::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--color-outline);
}

/* A grade de 12 colunas dos formulários do modelo. No telefone tudo vira
   uma coluna — um campo de CPF com 3/12 de 360px não recebe o dedo. */
.sgm-grade-form {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--sgm-3) var(--sgm-3);
}

.sgm-grade-form .sgm-col-3  { grid-column: span 3; }
.sgm-grade-form .sgm-col-4  { grid-column: span 4; }
.sgm-grade-form .sgm-col-6  { grid-column: span 6; }
.sgm-grade-form .sgm-col-12 { grid-column: span 12; }

@media (max-width: 767px) {
  .sgm-grade-form > * { grid-column: 1 / -1 !important; }
  .sgm-perfil__cab { flex-direction: column; align-items: flex-start; gap: var(--sgm-2); }
}

.sgm-perfil__nota {
  display: flex;
  align-items: center;
  gap: var(--sgm-2);
  margin: var(--sgm-2) 0 var(--sgm-4);
  font-size: var(--sgm-t-sm);
  color: var(--color-on-surface-variant);
}
.sgm-perfil__nota i { font-size: 11px; }

.sgm-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sgm-3);
  padding: var(--sgm-4) var(--sgm-4) var(--sgm-3);
}

.sgm-card__titulo {
  font-size: var(--sgm-t-md);
  font-weight: 650;
  color: var(--color-on-surface);
  letter-spacing: -.01em;
  min-width: 0;
}

.sgm-card__meta {
  margin-top: 3px;
  font-size: var(--sgm-t-sm);
  color: var(--color-on-surface-variant);
}

/* 🥇 O SELO DA ENTIDADE ENCOSTA NA ESQUERDA E TRUNCA — 2026-08-14

   *"nos cards que mostram o meu painel está estourando o nome da entidade; há
   um certo espaço em branco ainda à esquerda, nesse caso se deslocar esse
   badge mais à esquerda já resolveria"* — Rodrigo, com "PREFEITURA DA ESTÂNCIA
   BALNEARIA DE MO" cortado no meio.

   Duas coisas, na ordem em que ele sugeriu:

   1. o selo recua até a margem do card, ganhando a faixa que o coração deixa
      vazia — são uns 30px, e num nome de entidade isso é uma palavra;
   2. o que ainda não couber vira reticências, e não corte cru. Não se perde
      nada: o nome inteiro já está no `title` do próprio selo. */
.sgm-card__meta .sgm-chip {
  display: inline-block;
  max-width: 100%;
  /* 28px do coração (.sgm-fav) + o gap do head — o selo volta exatamente à
     margem interna do card, sem chutar o valor */
  margin-left: calc(-1 * (28px + var(--sgm-3)));
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
}

/* no telefone o card é a largura da tela: o recuo tiraria o selo para fora */
@media (max-width: 767px) {
  .sgm-card__meta .sgm-chip { margin-left: 0; }
}

.sgm-card__ferramentas {
  display: flex;
  align-items: center;
  gap: var(--sgm-1);
  flex: 0 0 auto;
  opacity: 0;
  transform: translateX(4px);
  transition: opacity var(--sgm-normal) var(--sgm-ease),
              transform var(--sgm-normal) var(--sgm-ease);
}
.sgm-card:hover  .sgm-card__ferramentas,
.sgm-card:focus-within .sgm-card__ferramentas { opacity: 1; transform: translateX(0); }

/* em toque não há hover: as ferramentas ficam sempre visíveis */
@media (hover: none) {
  .sgm-card__ferramentas { opacity: 1; transform: none; }
}

.sgm-card__corpo { flex: 1 1 auto; padding: 0 var(--sgm-3) var(--sgm-2); min-width: 0; }

/* --------------------------------------------------------------------------
   1c. Controles do próprio quadro

   Os filtros que são DAQUELE quadro — a secretaria e o exercício de "Despesas
   por Secretaria", os quatro níveis da despesa, a base do percentual. Ficam
   entre o cabeçalho e o gráfico, que é onde o legado os põe, e não na barra
   do módulo: ali estariam prometendo valer para os catorze cards.

   Quebram em várias linhas quando o card é estreito — nunca em rolagem
   lateral, que esconderia filtro ativo.
   -------------------------------------------------------------------------- */

.sgm-card__controles {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--sgm-2);
  padding: 0 var(--sgm-3) var(--sgm-2);
  min-width: 0;
}

/* o campo do controle é mais estreito que o da barra de filtros: são vários
   lado a lado dentro de um card, não a largura da tela */
.sgm-card__controles .sgm-field--ctl { flex: 0 1 190px; min-width: 0; }
/* nome de secretaria é longo — "SECRETARIA MUNICIPAL DE ADMINISTRAÇÃO" */
.sgm-card__controles .sgm-field--ctl.sgm-field--largo { flex: 1 1 260px; }

.sgm-card__controles .sgm-input { width: 100%; }

/* A mesma barra, na TELA DE DETALHAMENTO — os seis checkboxes de agrupamento
   da Disponibilidade Comprometida. Herda o layout do card e troca só o
   espaçamento: ali ela vive dentro do padding do cartão, aqui é a largura da
   página, e o alinhamento tem de ser o dos cartões de resumo e da busca —
   senão a fileira de botões nasce recuada em relação a tudo o que está em
   volta.

   ⚠️ `[hidden]` explícito pela REGRA DE OURO 5: `display:flex` de autor vence
   o `hidden` do navegador, e a barra vazia deixaria uma faixa de ar. */
.sgm-det-controles { padding: 0 0 var(--sgm-3); }
.sgm-det-controles[hidden] { display: none; }

/* O cartão ABAIXO da grade — o `htmlFooter` do legado, que a tela de
   Pagamentos usa para "Pagamentos nesta data". Mesmos cartões do topo, com a
   margem trocada de lado: aqui o ar tem de ficar ENTRE a grade e ele.

   ⚠️ `[hidden]` explícito pela REGRA DE OURO 5 — `.sgm-resumo` já traz o seu,
   e esta classe anda junto dela; a repetição é barata e a falta dela custou
   três cobranças. */
.sgm-det-rodape { margin: var(--sgm-3) 0 0; }
.sgm-det-rodape[hidden] { display: none; }

/* o par botão + X anda junto e não se separa na quebra de linha */
.sgm-ctl-busca { display: flex; align-items: center; gap: 2px; }

/* O botão do controle de múltipla escolha tem cara de campo, não de botão: é
   o que o operador reconhece como "combo" — e é o que o legado desenha ali,
   um <select> com caixas por dentro. */
.sgm-ctl-multi {
  justify-content: space-between;
  text-align: left;
  font-weight: 400;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A linha marcável do diálogo de múltipla escolha. É um <label> com a caixa
   dentro: assim clicar no texto marca, que é o alvo grande que o dedo acha. */
.sgm-check {
  display: flex;
  align-items: center;
  gap: var(--sgm-2);
  padding: var(--sgm-2) var(--sgm-1);
  border-radius: var(--sgm-r-2);
  cursor: pointer;
  min-width: 0;
}
.sgm-check:hover { background: var(--color-surface-sunken); }
.sgm-check span { min-width: 0; overflow-wrap: anywhere; }

.sgm-card__pe {
  display: flex;
  align-items: center;
  gap: var(--sgm-2);
  flex-wrap: wrap;
  padding: var(--sgm-3) var(--sgm-4);
  border-top: 1px solid var(--color-outline);
  background: var(--color-surface-sunken);
}
.sgm-card__pe .sgm-card__meta { margin: 0; margin-right: auto; }

/* --------------------------------------------------------------------------
   2a-bis. 🥇 O RODAPÉ TEM TETO — e é ele que dá SIMETRIA à fileira

   Medido em 2026-09-17, no painel do PPA: quatro cards da mesma linha com
   640, 712, 694 e 658px. A diferença inteira vinha daqui — o rodapé de um
   deles ocupava 126px e o do vizinho, 198.

   ⚠️ NUMA GRADE DE DASHBOARD A ALTURA NÃO PODE SER GOVERNADA PELO TEXTO. O
   olho varre a fileira pela linha de base dos botões; com quatro alturas
   diferentes, cada card termina num lugar e a varredura se perde. É o mesmo
   problema que `.sgm-card--num` resolveu em 2026-08-12 pelo outro lado.

   🥇 E NADA SE PERDE: o texto inteiro continua no `title` e, sobretudo, na
   AJUDA daquele quadro — que é onde ele já estava, estruturado em parágrafos.
   O rodapé é o resumo de leitura rápida, não o documento.

   Três linhas é a conta do que se lê sem parar de varrer. Quem quiser o resto
   clica, e o cursor avisa que há mais. */
.sgm-card__pe .sgm-card__meta {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  /* ⚠️ O `min-width: 0` É O QUE DEIXA O CLAMP ACONTECER num flex container:
     sem ele o span assume min-content e a caixa cresce em vez de cortar. */
  min-width: 0;
  max-width: 100%;
}

/* Quando o texto foi cortado, o card diz isso — e o clique abre a Ajuda. */
.sgm-card__pe .sgm-card__meta[data-cortado] { cursor: help; }
.sgm-card__pe .sgm-card__meta[data-cortado]:hover { color: var(--color-on-surface-variant); }

.sgm-grafico { width: 100%; height: 300px; }
.sgm-grafico--alto  { height: 380px; }
.sgm-grafico--baixo { height: 210px; }

/* 🥇 O MEDIDOR TEM ALTURA PRÓPRIA, e ela veio de uma medição, não de gosto.

   Os 300px de `.sgm-grafico` foram dimensionados para o gauge do legado: arco
   de 270°, ponteiro, número no canto. O desenho de hoje é um arco de 220°, e
   num container de 300px ele ocupa 189 — 38px de vazio em cima e 73 embaixo,
   111 no total, mais de um terço do card gasto em nada.

   ⚠️ O VAZIO NÃO ERA SIMÉTRICO, e isso importa mais que o tamanho: com o dobro
   de folga embaixo, o gauge ficava colado no título e solto da faixa de
   valores — a figura não pertencia a nenhum dos dois. Com a altura certa e o
   `center` recalculado (sgm-charts.js), os dois vãos ficam iguais.

   200px é a conta: o desenho mede `R × (1 + sen 20°)` mais a espessura do
   trilho, e com `radius: 78%` de metade do lado menor isso dá ~112px, que
   respira dentro de 200. */
.sgm-grafico--medidor { height: 200px; }

/* --------------------------------------------------------------------------
   2b. Quadro de indicadores — o número é o conteúdo
   --------------------------------------------------------------------------
   A posição de estoque não é série nem proporção: são quatro totais. Não
   recebe a altura fixa de .sgm-grafico, que deixaria dois terços de vazio;
   a altura sai do conteúdo.
   -------------------------------------------------------------------------- */

/* 🥇 MAIS DELICADOS, e a delicadeza é de PROPORÇÃO, não de tamanho: o rótulo
   ganhou tracking e o número perdeu peso, de 24px/700 para 20px/650. Um número
   de 24px em negrito dentro de uma caixa de 81px de altura pede a atenção que
   o quadro inteiro deveria pedir — e há quatro deles lado a lado, competindo
   entre si.

   ⚠️ O QUE ENCOLHEU FOI O CONTINENTE, NÃO O CONTEÚDO. `minmax(160px, …)` no
   lugar de 190 deixa caber quatro colunas onde cabiam três, e é isso que faz a
   fileira parecer um painel em vez de quatro cartões. O número continua o
   maior texto da caixa. */
.sgm-indicadores {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
  gap: var(--sgm-2);
  padding: var(--sgm-1) 0 var(--sgm-2);
}

/* --------------------------------------------------------------------------
   2c. O DESTAQUE — um número que é a resposta do quadro

   Cinco quadros da Contabilidade do legado (Disponibilidade Comprometida,
   Restos a Pagar, Pagamentos, Conta Corrente, Receita Tributária × Dívida
   Ativa) respondem com UM valor grande e um rótulo que muda com o sinal:
   "Saldo Total" em verde, "Saldo Insuficiente" em vermelho.

   A cor está no rótulo E no valor de propósito — no legado é assim
   (udmSGM.pas:4571), e quem opera lê a cor antes de ler o número. Não é
   decoração: é a informação chegando primeiro pelo canal mais rápido.
   -------------------------------------------------------------------------- */

.sgm-destaque {
  padding: var(--sgm-5) var(--sgm-4) var(--sgm-3);
  text-align: center;
}

.sgm-destaque__rot {
  font-size: var(--sgm-t-lg);
  font-weight: 650;
  letter-spacing: -.01em;
}

.sgm-destaque__val {
  margin-top: 2px;
  font-size: var(--sgm-t-2xl);
  font-weight: 700;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: var(--color-on-surface);
}

/* Neutro é o padrão: quadro que não declara tom não ganha cor nenhuma, em vez
   de herdar a do vizinho. */
.sgm-destaque[data-tom="neutro"]   .sgm-destaque__rot { color: var(--color-on-surface); }
.sgm-destaque[data-tom="positivo"] .sgm-destaque__rot { color: var(--color-success); }
.sgm-destaque[data-tom="negativo"] .sgm-destaque__rot { color: var(--color-error); }
.sgm-destaque[data-tom="negativo"] .sgm-destaque__val { color: var(--color-error); }

/* --------------------------------------------------------------------------
   2b-bis. A FAIXA SOB O MEDIDOR — os denominadores do percentual

   Os dois valores que o legado escreve sob cada gauge ("Permitida (15%)" e
   "Realizada"), pedidos pelo Rodrigo em 2026-08-14.

   ⚠️ DUAS COLUNAS FIXAS, e não o `auto-fit` da faixa geral: o medidor mora num
   card de um quarto de tela (`sgm-col-3`), e ali o `minmax(190px, 1fr)` não
   cabe duas vezes — os dois valores empilhariam, e o par deixaria de se ler
   como par. No legado eles são duas células de 50% lado a lado.

   O corpo menor é pela mesma razão: R$ 18.048.214,38 em `--sgm-t-xl` dentro de
   meia coluna quebra a linha no meio do número. */
/* 💎 `minmax(0, 1fr)` E NÃO `1fr` — foi isto que fez a abreviação não
   acontecer, e o Rodrigo apontou duas vezes ("os valores ainda estão
   estourando").

   `1fr` é atalho de `minmax(auto, 1fr)`, e `auto` no mínimo significa
   min-content: com o valor em `nowrap`, o min-content é a LARGURA DO NÚMERO
   INTEIRO. As colunas então se recusam a encolher, a faixa empurra o card, e
   dentro do `<span>` sobra espaço de sobra — `scrollWidth` igual a
   `clientWidth`, e o `SGM.valorQueCabe` concluindo que cabia. O texto não
   estourava a caixa; a caixa é que estourava o card.

   Com `minmax(0, …)` a coluna pode encolher abaixo do conteúdo, o `<span>`
   passa a ter de fato menos largura que o texto, e aí sim a medida acusa. */
.sgm-indicadores--medidor {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--sgm-2);
  padding-top: 0;
}

.sgm-indicadores--medidor .sgm-indicador {
  padding: var(--sgm-2) var(--sgm-3);
  text-align: center;
}

/* ⚠️ O NÚMERO NÃO PODE QUEBRAR NO MEIO, e quebrava: o print de 2026-08-14
   mostra "R$ 14.181.935,3" numa linha e o "8" na seguinte — o `overflow-wrap:
   anywhere` da faixa geral, que existe para nome comprido de secretaria, aqui
   parte o valor no meio do algarismo. Um número partido é pior do que um
   número pequeno: ele muda de grandeza aos olhos de quem passa.

   `normal` deixa quebrar só no espaço depois do "R$"; o `clamp` encolhe de
   15px para 13px quando a coluna aperta, que é o caso de meia largura de um
   card de um quarto de tela. */
/* ⚠️ `nowrap` + `overflow: hidden` são o que dá a MEDIDA ao JS: com o texto
   podendo quebrar, `scrollWidth` nunca passa de `clientWidth` e o
   `SGM.valorQueCabe` acharia que tudo cabe — a abreviação nunca aconteceria.
   Aqui o número ou cabe numa linha, ou é encolhido para "R$ 23,3 mi" com o
   valor inteiro no hover. */
.sgm-indicadores--medidor .sgm-indicador__val {
  font-size: clamp(0.8125rem, 1.6vw, var(--sgm-t-md));
  overflow-wrap: normal;
  white-space: nowrap;
  overflow: hidden;
}

/* o valor abreviado tem o número por extenso no title — o cursor de ajuda
   avisa que há mais ali do que o que se lê */
.sgm-indicador__val[title],
.sgm-resumo__valor[title] { cursor: help; }

/* 🥇 A CAIXA DO NÚMERO — 2026-09-17, mais delicada por PROPORÇÃO.

   Ela tinha 12/16 de padding e o número em 24px/700 dentro de 81px de altura.
   Quatro dessas lado a lado competem entre si e com o resto do painel: cada
   uma pedia a atenção que o QUADRO deveria pedir.

   ⚠️ O QUE MUDOU FOI O PESO, NÃO A LEGIBILIDADE. O número continua sendo o
   maior texto da caixa e o primeiro que o olho encontra — 20px contra os 11px
   do rótulo é a mesma razão de antes. O que saiu foi o excesso de tinta: 700
   vira 650, e a borda de 1px substitui parte do contraste que o fundo cheio
   fazia sozinho.

   ⚠️ E A BORDA É `--color-outline`, NÃO UMA SOMBRA: numa fileira de quatro
   caixas encostadas, sombra vira sujeira; a linha de 1px separa sem pesar. */
.sgm-indicador {
  padding: var(--sgm-2) var(--sgm-3);
  border-radius: var(--sgm-r);
  border: 1px solid var(--color-outline);
  background: var(--color-surface-sunken);
}

.sgm-indicador__rot {
  display: block;
  font-size: var(--sgm-t-xs);
  text-transform: uppercase;
  /* ⚠️ MAIÚSCULA PEDE MAIS RESPIRO: as caixas altas não têm ascendente nem
     descendente para separar as palavras, e .04em era apertado no rótulo de
     duas palavras ("PROGRAMAS MONITORADOS"). */
  letter-spacing: .06em;
  /* 🛑 `--color-on-surface-variant`, E NÃO O `muted` — 2026-09-17.
     Ao tornar o indicador mais delicado eu troquei um pelo outro, e o
     `confere-contraste.js` reprovou na hora: 4,06:1 contra o piso de 4,5 que
     texto pequeno pede. Delicadeza aqui é ESPAÇO e PESO, não texto mais
     claro — clarear o rótulo de 11px é tirar a legibilidade e chamar de
     refinamento. */
  color: var(--color-on-surface-variant);
}

/* 🥇 CÉLULA COM FUNDO DE COR: A FONTE É BRANCA — 2026-09-09.

   Quem pinta o fundo é o servidor (a cor é DADO, e no RELCON ela vem do
   legado), e o texto do `.sgm-indicador` tem cor própria, pensada para o fundo
   claro do componente. Sem esta regra o mês fica escuro sobre teal e sobre
   vermelho — foi o que o print mostrou.

   ⚠️ AS TRÊS LINHAS VALEM PELA ARITMÉTICA DA CASCATA, e não por `!important`:
      `.sgm-indicador--cor .sgm-indicador__rot` é 0,2,0 contra os 0,1,0 de
      `.sgm-indicador__rot` logo acima. Empate de especificidade já custou
      quatro defeitos neste projeto; aqui não há empate. */
.sgm-indicador--cor .sgm-indicador__rot,
.sgm-indicador--cor .sgm-indicador__val,
.sgm-indicador--cor .sgm-indicador__val i {
  color: #fff;
}

.sgm-indicador__val {
  display: block;
  margin-top: 2px;
  /* 🥇 20px/650, e não 24px/700 — 2026-09-17. Ver a nota de `.sgm-indicador`:
     numa fileira de quatro, o peso 700 em 24px faz cada caixa pedir a atenção
     que o quadro inteiro deveria pedir. A razão contra o rótulo de 11px
     continua a mesma; o que saiu foi tinta, não hierarquia. */
  font-size: var(--sgm-t-lg);
  font-weight: 650;
  color: var(--color-on-surface);
  letter-spacing: -.02em;
  /* tabular-nums: quatro valores empilhados alinham na vírgula */
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   2b-bis. A fileira `--lado`: a forma do LEGADO — 2026-09-22
   --------------------------------------------------------------------------
   Pedido do Rodrigo, com os dois prints lado a lado: *"o web2 deve seguir o
   legado nesses quadros"*.

   No Dashboard do SAMP o card é uma `<table>` de duas células
   (`udmSAMP.pas:4029-4070`): à esquerda o texto em DUAS linhas — a categoria
   pequena em cima ("Programas") e o nome em `<h4>` embaixo ("Monitorados") —,
   à direita o número em `<h1>`.

   🛑 ELA É UMA VARIANTE, E NÃO O PADRÃO. `.sgm-indicador` serve 18 quadros em
      6 módulos; trocar a forma de todos mudaria a cara de Contabilidade,
      Saúde, Tributos, Protocolo e Controle Interno sem que ninguém pedisse.
      O Rodrigo escolheu aplicar só ao PPA, e quem liga a variante é o servidor
      (`"faixa"` no JSON). Ver a nota de 17/09 em `.sgm-indicador__val`: os
      indicadores foram DELIBERADAMENTE afinados para não competir com o
      quadro, e esta variante anda na direção contrária — de propósito, e só
      onde foi pedida.

   ⚠️ O GRID TEM DUAS LINHAS NOMEADAS, e é isso que mantém as três caixas da
      MESMA ALTURA. O terceiro card do legado ("Alt.Realizadas") não tem
      categoria e o legado escreve `&nbsp` no lugar; aqui o servidor manda um
      espaço, a linha existe vazia, e a fileira não desalinha. Altura desigual
      numa fileira de cards já foi defeito relatado neste projeto. */
.sgm-indicadores--lado .sgm-indicador {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "cat val"
    "rot val";
  align-items: center;
  column-gap: var(--sgm-3);
  padding: var(--sgm-3);
}

.sgm-indicadores--lado .sgm-indicador__cat {
  grid-area: cat;
  display: block;
  font-size: var(--sgm-t-xs);
  line-height: 1.3;
  /* ⚠️ SEM MAIÚSCULA E SEM TRACKING, ao contrário do `__rot` padrão: no legado
     a categoria é texto corrente, e ela é a MENOR das duas linhas. O contraste
     entre as duas vem do TAMANHO e da cor, não de caixa alta. */
  color: var(--color-on-surface-variant);
  overflow-wrap: anywhere;
}

/* 🛑 O RÓTULO PERDE A CAIXA ALTA AQUI — e as três propriedades vêm juntas.
   `.sgm-indicadores--lado .sgm-indicador__rot` é 0,2,0 contra os 0,1,0 da
   regra base, então vence pela aritmética da cascata, sem `!important`.
   Empate de especificidade já custou quatro defeitos neste projeto. */
.sgm-indicadores--lado .sgm-indicador__rot {
  grid-area: rot;
  font-size: var(--sgm-t-md);
  text-transform: none;
  letter-spacing: normal;
  line-height: 1.3;
  color: var(--color-on-surface);
}

.sgm-indicadores--lado .sgm-indicador__val {
  grid-area: val;
  margin-top: 0;
  /* O `<h1>` do legado. 32px é o token de número em destaque, e aqui ele NÃO
     compete com os vizinhos: há um número por card e ele é a resposta. */
  font-size: var(--sgm-t-2xl);
  font-weight: 600;
  text-align: right;
  /* ⚠️ O NÚMERO NÃO QUEBRA: ele está numa coluna `auto`, que cresce com o
     conteúdo, e quebrar "153" em duas linhas desmontaria a altura da fileira
     — o mesmo defeito do print de 14/08 no medidor. */
  overflow-wrap: normal;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   3. Indicador (o número é o gráfico)
   -------------------------------------------------------------------------- */

.sgm-kpi {
  display: flex;
  flex-direction: column;
  gap: var(--sgm-1);
  padding: var(--sgm-4);
  background: var(--color-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-lg);
  box-shadow: var(--sgm-sh-1);
  min-width: 0;
  transition: box-shadow var(--sgm-normal) var(--sgm-ease);
}
.sgm-kpi:hover { box-shadow: var(--sgm-sh-2); }

.sgm-kpi__topo { display: flex; align-items: center; justify-content: space-between; gap: var(--sgm-2); }

.sgm-kpi__rotulo {
  font-size: var(--sgm-t-sm);
  font-weight: 600;
  color: var(--color-on-surface-variant);
  min-width: 0;
}

.sgm-kpi__ico {
  flex: 0 0 auto;
  display: grid; place-items: center;
  width: 30px; height: 30px;
  border-radius: var(--sgm-r-sm);
  background: var(--color-primary-50);
  color: var(--color-primary-500);
  font-size: 13px;
}

.sgm-kpi__valor {
  font-size: var(--sgm-t-2xl);
  font-weight: 680;
  letter-spacing: -.03em;
  color: var(--color-on-surface);
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}

.sgm-kpi__delta {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--sgm-t-sm);
  font-weight: 600;
}
.sgm-kpi__delta[data-dir="bom"]  { color: var(--color-success); }
.sgm-kpi__delta[data-dir="ruim"] { color: var(--color-error); }
.sgm-kpi__delta[data-dir="neutro"] { color: var(--color-on-surface-variant); }
.sgm-kpi__delta small { color: var(--color-on-surface-variant); font-weight: 500; }

/* --------------------------------------------------------------------------
   4. Chip e etiqueta de estado
   -------------------------------------------------------------------------- */

.sgm-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: var(--sgm-r-pill);
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-outline);
  color: var(--color-on-surface-variant);
  font-size: var(--sgm-t-xs);
  font-weight: 650;
  white-space: nowrap;
}

.sgm-chip[data-tom="accent"]  { background: var(--color-primary-50);  border-color: var(--color-primary-100);  color: var(--color-primary-600); }
.sgm-chip[data-tom="ok"]      { background: var(--color-success-container); border-color: var(--color-success-outline); color: var(--color-success); }
.sgm-chip[data-tom="alerta"]  { background: var(--color-warning-container); border-color: var(--color-warning-outline); color: var(--color-warning); }
.sgm-chip[data-tom="risco"]   { background: var(--color-error-container);  border-color: var(--color-error-outline);  color: var(--color-error); }
.sgm-chip[data-tom="info"]    { background: var(--color-info-container);    border-color: var(--color-info-outline);    color: var(--color-info); }

/* estado nunca é só cor: vem sempre com ícone e palavra */
.sgm-chip i { font-size: 10px; }

/* --------------------------------------------------------------------------
   5. Aviso
   -------------------------------------------------------------------------- */

.sgm-aviso {
  display: flex;
  align-items: flex-start;
  gap: var(--sgm-3);
  padding: var(--sgm-3) var(--sgm-4);
  border: 1px solid var(--color-info-outline);
  background: var(--color-info-container);
  border-radius: var(--sgm-r);
  /* 💎 TOKEN, E NÃO HEXADECIMAL SOLTO — 2026-08-20.

     Os quatro tons deste bloco pintavam com `#14418f`, `#8a3a06`, `#8c1c14` e
     `#045c37`: quatro cores à mão, cada uma vizinha de um token que existe
     (`--color-info` #175cd3, `--color-warning` #b54708, `--color-error`
     #b42318, `--color-success` #027a48). É letra por letra o defeito que o
     `<head>` do contribuinte-demo.html descreve e comemora ter tirado da
     própria página: "cor solta que quase acerta o token é pior do que cor
     solta que erra: no dia em que a paleta mudar, esta página passa a mostrar
     um fundo que o sistema já não usa".

     E a peça é justamente a FAIXA DE INDISPONIBILIDADE da tela do
     contribuinte, que o cabeçalho do bloco CONTRIBUINTE promete livre de cor
     solta — promessa que valia só a partir daquele bloco.

     ⚠️ O CONTRASTE FOI MEDIDO ANTES DE TROCAR, e os quatro continuam em AA
     sobre o próprio container: info 5,50:1, alerta 5,20:1, risco 6,05:1, ok
     5,13:1. São menores do que os das cores à mão (8,84 / 7,49 / 8,43 / 7,68)
     porque as cores à mão eram MAIS ESCURAS que o token — e é isso que
     "quase acerta" quer dizer. Um vocabulário, não dois. */
  color: var(--color-info);
  font-size: var(--sgm-t-base);
}
.sgm-aviso i { margin-top: 2px; flex: 0 0 auto; }
.sgm-aviso strong { font-weight: 650; }

/* A FAIXA EM FLUXO, com ar embaixo. Nasceu porque duas telas escreviam
   `style="margin-bottom:16px"` no JS — token por extenso, onde nenhum
   verificador de CSS o alcança, e que ficaria para trás calado no dia em que a
   escala mudar. 16px é `--sgm-4`. REGRA DE OURO 1 pelo espírito: estilo é do
   CSS.
   Sem regra de `display` aqui, então nada a fazer pela REGRA DE OURO 5. */
.sgm-aviso--bloco { margin-bottom: var(--sgm-4); }

.sgm-aviso[data-tom="alerta"] { border-color: var(--color-warning-outline); background: var(--color-warning-container); color: var(--color-warning); }
.sgm-aviso[data-tom="risco"]  { border-color: var(--color-error-outline);  background: var(--color-error-container);  color: var(--color-error); }
.sgm-aviso[data-tom="ok"]     { border-color: var(--color-success-outline); background: var(--color-success-container); color: var(--color-success); }

/* --------------------------------------------------------------------------
   6. Carregando — esqueleto, nunca giro no meio do conteúdo
   -------------------------------------------------------------------------- */

/* 🥇 O SHIMMER PRECISA SER VISTO — 2026-08-17.

   Cobrado pelo Rodrigo, com o print do Inventário por unidade/setor: *"os
   gráficos quando estão carregando, não tem como colocar um loading neles para
   que o usuário entenda que está sendo carregado?"*

   O esqueleto JÁ existia (REGRA DE OURO 17) e JÁ animava. O problema era que
   ninguém via: o gradiente ia de `#eef2f7` para `#e2e9f1` — três por cento de
   luminosidade — e o resultado lia como um gráfico cinza parado, não como
   espera. Esqueleto que não se anuncia não cumpre o que a regra 17 promete.

   A faixa clara subiu para `#f7fafd` e a escura desceu para `#d4dfea`: agora há
   contraste suficiente para a onda aparecer sem virar pisca-pisca. */
/* 🥇 `display: block` NÃO É ENFEITE — sem ele metade do esqueleto não existe.

   As peças do esqueleto são escritas como `<span>`, e span é INLINE: `height`
   e `width` não se aplicam a caixa inline, e um span vazio e inline mede zero
   por zero. Quem está dentro de um contêiner `flex` escapa — o pai blocifica o
   filho —, e é por isso que `--cel`, que só vive dentro de
   `.sgm-skeleton-grade__linha` e de `.sgm-cnt-linha`, sempre apareceu. Já
   `--titulo` e `--txt`, pendurados direto em `.sgm-cnt-cabeca` e em
   `.sgm-cnt-painel`, que são blocos comuns, NUNCA apareceram: a espera do
   resumo do contribuinte mostrava a fita azul e três barrinhas por painel, sem
   uma única barra de título, e a página saltava quando o título real entrava.
   É a REGRA DE OURO 17 falhando — o esqueleto tem de ter a FORMA do que vem, e
   o que vem tem título. Corrigido em 2026-08-19.

   ⚠️ Blocificar aqui não muda nada nos usos antigos: dentro de um `flex` o
   `display` do filho já era ignorado. */
.sgm-skeleton {
  display: block;
  background: linear-gradient(90deg, #eef2f7 25%, #d4dfea 37%, #f7fafd 50%, #d4dfea 63%, #eef2f7 75%);
  background-size: 400% 100%;
  border-radius: var(--sgm-r-sm);
  animation: sgm-shimmer 1.3s ease-in-out infinite;
}
/* REGRA DE OURO 5: `display` de autor vence o `hidden` do navegador. */
.sgm-skeleton[hidden] { display: none; }

@keyframes sgm-shimmer {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

@media (prefers-reduced-motion: reduce) {
  .sgm-skeleton { animation: none; background: #eef2f7; }
}

.sgm-skeleton--txt   { height: 11px; margin-bottom: 7px; }
.sgm-skeleton--titulo{ height: 15px; width: 45%; margin-bottom: var(--sgm-3); }

/* 💎 A ARITMÉTICA DA REGRA 17, ESCRITA — 2026-08-20.

   `--titulo` mede 15 + 12 = 27px. Isso serve para um título de card, e NÃO
   serve para o título de painel do resumo do contribuinte:

     alvo                                 conta                  total
     .sgm-cnt-painel__titulo (<button>)   min-height 38 + 8      46px

   Com `--titulo`, o painel saltava 19px quando o dado chegava — oito vezes —,
   que é exatamente o que a regra 17 existe para impedir. Este modificador
   carrega a altura do alvo real.

   ⚠️ O DO PAINEL DEPENDE DO `min-height: 38px` DE `.sgm-cnt-painel__titulo`
   (§4 deste arquivo), que é o alvo de toque da WCAG 2.5.8. Mexeu num, mexe
   no outro — e é por isso que o número está escrito, e não só usado.

   ⚠️ E HAVIA UM `--titulo-nome`, de 22px, para `.sgm-cnt-cabeca__nome`. Os
   dois saíram em 2026-08-20, na segunda volta: o cartão do cabeçalho deixou
   de repetir o nome da pessoa, que agora vive só no `<h1>` da aba. Esqueleto
   com barra a mais é salto para cima quando o dado chega, e salto para cima é
   pior do que salto para baixo — leva embora o que o operador já está lendo. */
.sgm-skeleton--titulo-botao { height: 38px; margin-bottom: var(--sgm-2); }

/* E a LINHA do painel: `.sgm-cnt-linha` real mede 4 + 13px×1,25 + 4 + 1 de
   filete = 25,25px; com a célula de 11px do esqueleto media 20px. Dentro de
   uma `.sgm-cnt-linha` a barrinha ganha a altura da caixa de texto que ela
   substitui. (0,2,0) contra (0,1,0) da regra base — vence por b. */
.sgm-cnt-linha .sgm-skeleton--cel { height: 16px; }

/* 💎 E A LINHA DO CABEÇALHO DA PESSOA — 2026-08-20, segunda volta.

   As quatro linhas do cartão da pessoa são `--junta`: 12px × 1,25 = 15px de
   caixa, mais 2 + 2 de recuo, 19px cada (a última sem recuo de baixo, 17px —
   `.sgm-cnt-linha:last-child`). O esqueleto delas eram quatro
   `.sgm-skeleton--txt` SOLTAS, 11 + 7 = 18px cada: 72px contra 74px, mais o
   meio pixel do título. O topo da aba saltava ~4,5px quando o dado chegava,
   e a tabela de aritmética acima media os títulos e NÃO media estas quatro.

   O conserto não é somar 2px: é o esqueleto ter a MESMA ESTRUTURA do que vem.
   Agora cada barrinha nasce dentro de uma `.sgm-cnt-linha--junta` de verdade,
   e o recuo, o filete e o `:last-child` são os mesmos objetos — não há conta a
   manter em dia. À barrinha resta a altura da caixa de texto que ela
   substitui: 15px, e não os 16px da linha do painel, que é 13px.

   (0,3,0) pela classe repetida, contra os (0,2,0) da regra do painel logo
   acima — vence por b, sem depender da ordem do arquivo. */
.sgm-cnt-linha.sgm-cnt-linha--junta .sgm-skeleton--cel { height: 15px; }

/* 🥇 O ESQUELETO DA GRADE — REGRA DE OURO 17, 2026-08-15.

   Cobrado pelo Rodrigo: o detalhamento do inventário demora, e até aqui quem
   esperava por uma TABELA via o esqueleto de BARRAS. Esqueleto que promete a
   coisa errada é pior que nenhum — a tela pisca de gráfico para grade quando
   o dado chega.

   A silhueta é a da tabela: uma faixa de cabeçalho e linhas de células com
   larguras diferentes. Larguras iguais pareceriam um bloco só. */
.sgm-skeleton-grade {
  position: relative;
  padding: var(--sgm-3);
}

/* O MESMO SELO NA GRADE — a peça é a mesma (`.sgm-carregando`), e só a posição
   muda.

   ⚠️ AQUI ELE FICA NO TOPO, e não no meio: a grade tem rolagem própria e o
   esqueleto é mais alto que a área visível — centrado verticalmente, o selo
   cairia fora da tela numa lista longa. */
.sgm-skeleton-grade .sgm-carregando {
  top: 96px;
  transform: translateX(-50%);
}

.sgm-skeleton-grade__cab,
.sgm-skeleton-grade__linha {
  display: flex;
  gap: var(--sgm-3);
  align-items: center;
}

.sgm-skeleton-grade__cab {
  padding-bottom: var(--sgm-3);
  margin-bottom: var(--sgm-2);
  border-bottom: 1px solid var(--color-outline);
}

.sgm-skeleton-grade__cab .sgm-skeleton--cel { height: 13px; width: 16%; opacity: .75; }

.sgm-skeleton-grade__linha { padding: 7px 0; }

.sgm-skeleton--cel { height: 11px; }

/* o esqueleto do gráfico imita a silhueta de barras, para que a troca pelo
   conteúdo real não desloque a página */
.sgm-skeleton-grafico {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 3%;
  height: 300px;
  padding: var(--sgm-5) var(--sgm-3) var(--sgm-6);
}
/* ⚠️⚠️ O `>` NÃO É ESTILO — ELE É O QUE FAZ O DISCO GIRAR. 2026-08-17.

   Esta regra era `.sgm-skeleton-grafico span`, sem combinador, e o selo de
   carregamento nasce DENTRO do esqueleto: os dois `<span>` dele — o disco e o
   texto — casavam aqui. E casavam GANHANDO, por aritmética:

       .sgm-skeleton-grafico span   (0,1,1)   <- vencia
       .sgm-carregando__giro        (0,1,0)

   O disco recebia `border-radius: 4px 4px 0 0` e virava um quadradinho, e
   recebia `animation: sgm-shimmer`, que SUBSTITUÍA o `sgm-girar`. Ele não
   girava — foi o print do Rodrigo, *"o spin do loading nao apareceu"*.

   O `>` resolve por construção, e não por `!important`: as barras são filhas
   DIRETAS do esqueleto, e os spans do selo são netos (o pai deles é o
   `div.sgm-carregando`). Um combinador separa os dois conjuntos sem disputar
   especificidade com ninguém.

   🥇 É o empate de especificidade da nota de memória acontecendo pela quinta
   vez neste projeto. A lição que já estava escrita e que eu repeti mesmo
   assim: ao pôr elemento novo DENTRO de um contêiner que já estiliza
   descendentes por TAG, confira a cascata por aritmética ANTES de olhar a
   tela — o sintoma aparece longe da causa. */
.sgm-skeleton-grafico > span {
  flex: 1 1 0;
  border-radius: 4px 4px 0 0;
  background: linear-gradient(90deg, #eef2f7 25%, #d4dfea 37%, #f7fafd 50%, #d4dfea 63%, #eef2f7 75%);
  background-size: 400% 100%;
  animation: sgm-shimmer 1.3s ease-in-out infinite;
}

/* 🥇 A ONDA ATRAVESSA AS BARRAS, uma depois da outra.

   Antes as doze animavam EM FASE: todas clareavam e escureciam juntas, e um
   pulso sincronizado a essa amplitude o olho lê como parado. Escalonando o
   início, o brilho caminha da esquerda para a direita — e movimento que se
   desloca é o sinal universal de "está trabalhando".

   Os 90ms são deliberados: doze barras × 90ms = 1,08s, um pouco menos que o
   ciclo de 1,3s, então a onda emenda no começo do ciclo seguinte sem pausa. */
.sgm-skeleton-grafico > span:nth-child(1)  { animation-delay: 0ms; }
.sgm-skeleton-grafico > span:nth-child(2)  { animation-delay: 90ms; }
.sgm-skeleton-grafico > span:nth-child(3)  { animation-delay: 180ms; }
.sgm-skeleton-grafico > span:nth-child(4)  { animation-delay: 270ms; }
.sgm-skeleton-grafico > span:nth-child(5)  { animation-delay: 360ms; }
.sgm-skeleton-grafico > span:nth-child(6)  { animation-delay: 450ms; }
.sgm-skeleton-grafico > span:nth-child(7)  { animation-delay: 540ms; }
.sgm-skeleton-grafico > span:nth-child(8)  { animation-delay: 630ms; }
.sgm-skeleton-grafico > span:nth-child(9)  { animation-delay: 720ms; }
.sgm-skeleton-grafico > span:nth-child(10) { animation-delay: 810ms; }
.sgm-skeleton-grafico > span:nth-child(11) { animation-delay: 900ms; }
.sgm-skeleton-grafico > span:nth-child(12) { animation-delay: 990ms; }

/* ⚠️ E AS BARRAS TAMBÉM PULSAM, EM VEZ DE MORRER. Mesma razão da nota longa do
   selo, logo abaixo: `animation: none` deixava o esqueleto inteiro mudo em
   máquina com movimento reduzido. Aqui a onda que ATRAVESSA sai — ela é
   deslocamento, e é isso que a preferência pede para tirar — e entra um pulso
   de opacidade, que acontece no lugar.

   ⚠️ SEM ESCALONAMENTO AQUI: as doze pulsam juntas, de propósito. Escalonar
   devolveria a sensação de onda correndo, que é justamente o que se está
   evitando. */
@media (prefers-reduced-motion: reduce) {
  .sgm-skeleton-grafico > span {
    background: #e2e9f1;
    animation: sgm-pulsar 1.6s ease-in-out infinite;
    animation-delay: 0ms !important;
  }
}

/* 🥇 O SELO DE CARREGAMENTO — o disco girando ao lado da palavra.

   Duas cobranças do Rodrigo no mesmo dia, 2026-08-17. A primeira: o esqueleto
   animava e ninguém via, e o `Carregando…` só existia para leitor de tela. A
   segunda, depois de a palavra aparecer: *"o carregando ficou legal, mas
   coloque uma animação junto"*.

   ⚠️ A PRIMEIRA VERSÃO ERA `::after` COM `content:`, E NÃO SERVIA para a
   segunda: pseudo-elemento tem UM nó de texto e nenhum filho, então não há
   onde pendurar o disco. Compor duas peças pede dois elementos — o selo virou
   markup (`SGM._selo`, sgm-core.js), e é por isso que ESTA mudança leva BUILD
   e a anterior não levava.

   ⚠️ NÃO É "giro no meio do conteúdo", que o título desta seção proíbe. O que
   aquela regra veta é o disco NO LUGAR do conteúdo — ele não diz o que vem, e
   a tela pula quando o dado chega. Aqui a silhueta continua sendo a forma do
   que vem (REGRA DE OURO 17); o disco é um detalhe dentro do selo.

   ⚠️ O SELO NÃO É ANUNCIADO: ele nasce dentro do contêiner do esqueleto, que é
   `aria-hidden="true"`, e quem fala com o leitor de tela é o `sgm-sr` irmão.
   Um mostra, o outro anuncia. */
.sgm-carregando {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 15px 7px 12px;
  border-radius: 999px;
  background: var(--color-surface, #fff);
  border: 1px solid var(--color-outline);
  color: var(--color-on-surface-variant);
  font-size: .8125rem;
  font-weight: 500;
  white-space: nowrap;
  box-shadow: 0 1px 3px rgb(16 32 48 / .08);
}

/* O disco: um anel com um quarto aceso. `border-top-color` na cor do sistema e
   o resto na cor da divisa - é o giro clássico, e ele não precisa de imagem
   nem de fonte, o que importa numa prefeitura sem internet (decisão 12). */
.sgm-carregando__giro {
  width: 14px;
  height: 14px;
  flex: none;
  border-radius: 50%;
  border: 2px solid var(--color-outline-strong);
  /* ⚠️ `--color-primary-500`, e não `--color-primary`: este projeto NÃO tem o
     token sem número - só a escala 50/100/500/600/700 (sgm-tokens.css:46-50).
     O 500 é o que os outros 37 usos do arquivo chamam de "cor do sistema".
     Escrever `var(--color-primary, #0d9488)` compilava e caía no fallback, com
     um teal PARECIDO e não igual - divergência de cor que ninguém notaria. */
  border-top-color: var(--color-primary-500);
  animation: sgm-girar .7s linear infinite;
}

@keyframes sgm-girar {
  to { transform: rotate(360deg); }
}

/* 🥇 COM MOVIMENTO REDUZIDO O SINAL TROCA DE FORMA — NÃO DESAPARECE.

   ⚠️ ESTA REGRA JÁ ESTEVE ERRADA, E O ERRO FOI MEU. Ela era
   `animation: none`, com a justificativa de que "parado, o anel continua sendo
   um sinal visual ao lado da palavra". Não continua: o Rodrigo tem movimento
   reduzido ligado, e o que ele viu foi *"apareceu mais ficou estatico"* — um
   anel morto que lê como enfeite, ou como tela travada.

   E o mesmo bloco irmão (`.sgm-skeleton-grafico > span`) já apagava a onda das
   barras, então NAS MÁQUINAS COM MOVIMENTO REDUZIDO o carregamento inteiro
   ficava mudo — as duas animações mortas de uma vez. O print mostrava as duas
   coisas, e eu só tinha olhado para uma.

   `prefers-reduced-motion` pede para não DISPARAR VERTIGEM — movimento amplo,
   parallax, zoom, coisa que atravessa a tela. Ele não pede para tirar a
   informação. A troca certa é por uma animação SEM DESLOCAMENTO: a opacidade
   pulsa, nada anda, e o operador continua vendo que o sistema trabalha.

   O ciclo é mais lento de propósito (1,6s contra 0,7s do giro): pulso lento
   lê como respiração, pulso rápido lê como alarme. */
@media (prefers-reduced-motion: reduce) {
  .sgm-carregando__giro {
    animation: sgm-pulsar 1.6s ease-in-out infinite;
  }
}

@keyframes sgm-pulsar {
  0%, 100% { opacity: 1; }
  50%      { opacity: .3; }
}

/* 🥇 O PAINEL DE ESPERA DO DETALHAMENTO — 2026-09-23 (ver `SGM._painelEspera`,
   sgm-core.js). O selo em pílula virou um cartão: disco, título, uma linha
   com o que está acontecendo e há quantos segundos, e uma barra de progresso
   indeterminada embaixo. É o selo de sempre — `.sgm-carregando` — com um
   modificador; o esqueleto de gráfico continua com a pílula. */
.sgm-carregando--painel {
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 4px 12px;
  width: min(360px, calc(100% - 32px));
  padding: 14px 18px 12px;
  border-radius: 12px;
  white-space: normal;
  box-shadow: 0 8px 24px rgb(16 32 48 / .12), 0 1px 3px rgb(16 32 48 / .08);
}
.sgm-carregando--painel .sgm-carregando__giro {
  width: 20px;
  height: 20px;
  border-width: 3px;
  margin-top: 1px;
}
.sgm-carregando__corpo {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}
.sgm-carregando--painel .sgm-carregando__txt {
  color: var(--color-on-surface);
  font-size: .875rem;
  font-weight: 600;
}
.sgm-carregando__sub {
  font-size: .75rem;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}

/* A barra ocupa a largura toda do cartão, na linha de baixo (`flex-basis`).
   O trecho aceso atravessa o trilho da esquerda para a direita, sem fim. */
.sgm-carregando__barra {
  flex-basis: 100%;
  height: 4px;
  margin-top: 10px;
  border-radius: 999px;
  background: var(--color-surface-sunken, #f7f9fc);
  overflow: hidden;
}
.sgm-carregando__barra > span {
  display: block;
  width: 35%;
  height: 100%;
  border-radius: 999px;
  background: var(--color-primary-500);
  animation: sgm-barra-espera 1.4s ease-in-out infinite;
}
@keyframes sgm-barra-espera {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(300%); }
}

/* ⚠️ COM MOVIMENTO REDUZIDO NADA SE DESLOCA, E NADA FICA PARADO — a mesma
   regra do disco, logo acima. A barra enche por inteiro e pulsa; o esqueleto
   atrás, que antes ficava cinza e morto, pulsa também. E o contador de
   segundos do painel continua mudando, que é o sinal que não depende de
   animação nenhuma. */
@media (prefers-reduced-motion: reduce) {
  .sgm-carregando__barra > span {
    width: 100%;
    animation: sgm-pulsar 1.6s ease-in-out infinite;
  }
  .sgm-skeleton-grade .sgm-skeleton {
    animation: sgm-pulsar 1.6s ease-in-out infinite;
  }
}

/* --------------------------------------------------------------------------
   7. Vazio e erro
   -------------------------------------------------------------------------- */

.sgm-estado {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sgm-2);
  padding: var(--sgm-10) var(--sgm-5);
  text-align: center;
  min-height: 220px;
}

.sgm-estado__ico {
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border-radius: 50%;
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-outline);
  color: var(--color-on-surface-muted);
  font-size: 17px;
  margin-bottom: var(--sgm-1);
}

.sgm-estado__titulo { font-size: var(--sgm-t-md); font-weight: 650; color: var(--color-on-surface); }
/* 💎 A TINTA DA PROSA DO ESTADO VAZIO PASSOU A SER `variant` — 2026-08-20,
   terceira volta. Era `--color-on-surface-muted`: 4,28:1 sobre a superfície,
   abaixo dos 4,5:1 que a WCAG 1.4.3 pede para texto. `variant` dá 7,32:1.

   ⚠️ E ISTO NÃO É ENFEITE, É O CORPO DE TODO ESTADO VAZIO E DE ERRO DESTA
      TELA: a instrução de partida ("Informe o nome ou o CPF/CNPJ acima e
      clique em Localizar…"), o convite ("Clique no título de um painel…"), a
      resposta ao painel sem lista, o "O servidor não devolveu nenhum painel…"
      e a mensagem de `SGM.cardErro` (sgm-core.js:225). É a prosa mais
      importante da tela, e era a que estava na lista de exceção.

   ⚠️ O ARGUMENTO QUE SEGURAVA A TROCA — "é anterior a esta rodada e mudar
      muda o aspecto da aplicação inteira" — não sobrevivia ao próprio
      precedente: `.sgm-page-head__sub` (sgm-shell.css), que é o subtítulo de
      TODA tela do sistema, foi trocada nesta mesma entrega, junto com
      `.sgm-hint` e `.sgm-error`. `.sgm-estado__txt` é tão geral quanto ela.

   A régua fica: as duas classes entraram na lista `PROSA` de
   `scripts\confere-contraste.js` §2, e desfazer isto REPROVA. */
.sgm-estado__txt    { font-size: var(--sgm-t-base); color: var(--color-on-surface-variant); max-width: 46ch; }

/* ⚠️ DENTRO DA FICHA O VAZIO É COMPACTO.

   Os 220px de altura mínima e o disco do ícone existem para uma tela cheia,
   onde o vazio precisa preencher. Numa ficha em popup isso tomou meia janela
   para dizer "nenhum fornecedor cadastrado" — o Rodrigo mandou o print. Aqui
   é uma linha discreta, que é o peso que a informação tem. */
.sgm-ficha .sgm-estado {
  min-height: 0;
  flex-direction: row;
  justify-content: flex-start;
  gap: var(--sgm-2);
  padding: var(--sgm-3) var(--sgm-4);
  text-align: left;
  border: 1px dashed var(--color-outline);
  border-radius: var(--sgm-r-sm);
  background: var(--color-surface-sunken);
}
.sgm-ficha .sgm-estado__ico { display: none; }
.sgm-ficha .sgm-estado__titulo { font-size: var(--sgm-t-base); }
.sgm-ficha .sgm-estado__txt { font-size: var(--sgm-t-sm); }
/* 🥇 O SEGUNDO NÍVEL DO ERRO — sugestão do Pedro Neto, 2026-09-22.

   A frase curta fica no `__txt`; isto aqui é o que o operador abre para
   consertar: onde mexer no SGM ADMIN, a configuração atual e o texto cru do
   banco.

   ⚠️ NASCE FECHADO, e a altura só cresce quando alguém pede. O card tem três
   linhas úteis — era exatamente por despejar o `[FireDAC][Phys][FB]...` nelas
   que a mensagem útil ficava de fora. */
.sgm-estado__det    { margin-top: var(--sgm-3); width: 100%; max-width: 46ch; text-align: left; }
.sgm-estado__det > summary {
  cursor: pointer;
  font-size: var(--sgm-t-sm);
  color: var(--color-on-surface-variant);
  /* o triângulo nativo fica; ele é a affordance que diz "isto abre" */
}
/* ⚠️ `pre-wrap` E `break-word`, os dois. O detalhe TEM quebra de linha própria
   (as três partes), e `pre` sozinho não reparte
   `D:\Fiorilli\SAS\DADOS\SAS.FDB` — num card estreito o caminho vazaria para
   fora da caixa em vez de dobrar. */
.sgm-estado__pre {
  margin: var(--sgm-2) 0 0;
  padding: var(--sgm-2) var(--sgm-3);
  font-size: var(--sgm-t-sm);
  line-height: 1.45;
  color: var(--color-on-surface-variant);
  background: var(--color-surface-sunken);
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-sm);
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

.sgm-estado__acoes  { margin-top: var(--sgm-3); display: flex; gap: var(--sgm-2); flex-wrap: wrap; justify-content: center; }

.sgm-estado[data-tom="erro"] .sgm-estado__ico {
  background: var(--color-error-container);
  border-color: var(--color-error-outline);
  color: var(--color-error);
}

/* --------------------------------------------------------------------------
   7b. Resumo do detalhamento — o htmlCabecalho do legado

   Os cartões coloridos acima da grid, com o total do que foi carregado. No
   legado cada tela uVis* monta isso em HTML com classes do w3.css
   (w3-blue / w3-red / w3-teal); aqui é um componente só, e as cores saem da
   paleta de séries do §4 — assim o cartão e a barra do gráfico que ele
   resume falam a mesma cor.

   Fica FORA da rolagem da grade (§6i.3): é a primeira coisa que se lê, e um
   resumo que sobe com o scroll não resume nada.
   -------------------------------------------------------------------------- */

.sgm-resumo {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sgm-3);
  margin-bottom: var(--sgm-4);
}

.sgm-resumo[hidden] { display: none; }

.sgm-resumo__cartao {
  flex: 1 1 200px;
  /* minmax(0) pela mão: sem isto um valor longo (R$ 3.276.411,03) empurra o
     cartão além da faixa e a página ganha rolagem horizontal — a mesma
     armadilha do `1fr` já registrada no §6. */
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--sgm-3);
  padding: var(--sgm-3) var(--sgm-4);
  border-radius: var(--sgm-r);
  color: #fff;
  box-shadow: var(--sgm-sh-1);
}

.sgm-resumo__ico {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  font-size: 1.25rem;
  border-radius: var(--sgm-r-sm);
  /* Vidro sobre a própria cor: um branco translúcido funciona nas três sem
     precisar de uma segunda cor declarada por tom. */
  background: rgba(255, 255, 255, .18);
}

.sgm-resumo__texto {
  min-width: 0;
  display: flex;
  flex-direction: column;
  line-height: 1.25;
}

.sgm-resumo__rotulo {
  font-size: var(--sgm-t-sm);
  font-weight: 600;
  opacity: .92;
}

.sgm-resumo__valor {
  font-size: var(--sgm-t-lg);
  font-weight: 700;
  /* tabular-nums: com dois cartões lado a lado, dígitos de larguras
     diferentes fazem os valores dançarem a cada recarga */
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   🥇 AS DUAS MEDIDAS NA MESMA LINHA, CADA UMA COM O SEU SINAL — 2026-08-15

   Pedido do Rodrigo, com o print do cartão "Móveis": o valor em R$ vinha
   embaixo, menor e esmaecido, porque a régua era o legado (só o R$ leva
   `w3-xlarge` lá). Mas numa prestação de contas o valor é o que se lê
   primeiro, e o desenho o empurrava para o pé do cartão.

   Agora os dois têm o mesmo corpo e dividem a linha, com um filete entre
   eles. O arranjo é o dos denominadores sob o ponteiro do medidor
   (`.sgm-indicador`), que resolve a mesma pergunta: dois números que só se
   entendem quando nomeados.

   ⚠️ `.sgm-resumo__valor--sec` SAIU. Era ela que encolhia a segunda medida, e
   manter a classe sem uso deixaria o próximo a mexer aqui achando que ainda
   existe uma "medida de apoio" no desenho.
   -------------------------------------------------------------------------- */

.sgm-resumo__medidas {
  display: flex;
  align-items: flex-start;
  gap: var(--sgm-3);
  flex-wrap: wrap;
  margin-top: 2px;
}

.sgm-resumo__medida {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* O filete que separa as duas. Fica no elemento seguinte e não como borda do
   primeiro, senão ele apareceria também quando a linha quebra no telefone —
   um traço vertical sobrando à esquerda de um número sozinho. */
.sgm-resumo__medida + .sgm-resumo__medida {
  padding-left: var(--sgm-3);
  border-left: 1px solid rgba(255, 255, 255, .28);
}

.sgm-resumo__sinal {
  font-size: var(--sgm-t-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  /* ⚠️ opacidade, e não uma cor: o cartão troca de fundo por `data-cor`
     (azul, teal, vermelho, laranja), e cor fixa aqui brigaria com um deles. */
  opacity: .78;
  white-space: nowrap;
}

.sgm-resumo__cartao[data-cor="azul"]     { background: #2a78d6; }
.sgm-resumo__cartao[data-cor="teal"]     { background: #0d9488; }
.sgm-resumo__cartao[data-cor="vermelho"] { background: #e34948; }
.sgm-resumo__cartao[data-cor="laranja"]  { background: #eb6834; }

/* VIOLETA — o slot 7 da paleta validada (§4).

   Entrou para "A pagar" ficar distinto de "A liquidar", que é o laranja ao
   lado. O pedido original era um laranja pastel; medido, não dava:

     #eb6834 (o laranja de hoje)      branco 3,20:1   já é o mínimo
     #f7b98f (o pastel)               branco 1,71:1   ilegível
     #4a3aa7 (violeta, slot 7 do §4)  branco 8,56:1   o melhor dos cinco

   O Rodrigo abriu para qualquer cor que contraste com branco, e aí a escolha
   deixou de ser de gosto: sai de dentro da paleta que já passou pelos testes
   de croma e de daltonismo, em vez de um tom inventado. */
.sgm-resumo__cartao[data-cor="violeta"]  { background: #4a3aa7; }

/* 🥇 O CARTÃO QUE FILTRA — 2026-09-23 (ver `aoFiltrar` em `SGM.resumo`,
   sgm-grid.js). Três estados, e os três se leem sem cor nova:

     · clicável      — cursor de mão e um leve erguer no hover;
     · aplicado      — anel branco por dentro e um tique no canto;
     · os demais, quando há filtro — recuam (opacidade), para o aplicado se
       ler de longe.

   ⚠️ O ANEL É `inset` e não `outline`: `outline` fora do cartão encosta no
   vizinho e some no espaço de 8px entre eles. */
.sgm-resumo__cartao--filtro {
  cursor: pointer;
  position: relative;
  transition: transform .12s ease, box-shadow .12s ease, opacity .12s ease;
}
.sgm-resumo__cartao--filtro:hover {
  transform: translateY(-1px);
  box-shadow: var(--sgm-sh-2, 0 4px 12px rgb(16 32 48 / .18));
}
.sgm-resumo__cartao--filtro:focus-visible {
  outline: 3px solid var(--color-primary-500);
  outline-offset: 2px;
}
.sgm-resumo__cartao--filtro[aria-pressed="true"] {
  box-shadow: inset 0 0 0 3px rgba(255, 255, 255, .9), var(--sgm-sh-1);
}
.sgm-resumo__cartao--filtro[aria-pressed="true"]::after {
  content: "\f00c";                /* fa-check */
  font-family: "Font Awesome 7 Free";
  font-weight: 900;
  position: absolute;
  top: 6px;
  right: 10px;
  font-size: .75rem;
}
.sgm-resumo--filtrado .sgm-resumo__cartao--filtro[aria-pressed="false"] {
  opacity: .55;
}
.sgm-resumo--filtrado .sgm-resumo__cartao--filtro[aria-pressed="false"]:hover {
  opacity: .85;
}
@media (prefers-reduced-motion: reduce) {
  .sgm-resumo__cartao--filtro,
  .sgm-resumo__cartao--filtro:hover { transition: none; transform: none; }
}

/* --------------------------------------------------------------------------
   O RESUMO DENTRO DE UMA ABA DE FICHA — a versão compacta

   ⚠️ ALTURA É O RECURSO ESCASSO AQUI, como já está escrito acima sobre os
   campos. Na aba Situação do empenho os cinco cartões no tamanho do
   dashboard ocupavam MAIS ALTURA QUE A GRID que eles resumem: 200px de base
   com a coluna estreita das duas colunas dá dois por linha, e cinco cartões
   viravam três fileiras. O Rodrigo mandou o print.

   Aqui eles são cabeçalho de uma lista, não o painel principal da tela.
   Base menor para caber três ou quatro por linha, ícone menor, valor no
   corpo do texto comum.
   -------------------------------------------------------------------------- */
.sgm-ficha-aba .sgm-resumo { gap: var(--sgm-2); margin-bottom: var(--sgm-2); }

.sgm-ficha-aba .sgm-resumo__cartao {
  flex: 1 1 120px;
  gap: var(--sgm-2);
  padding: var(--sgm-1) var(--sgm-2);
  border-radius: var(--sgm-r-sm);
  box-shadow: none;
}

.sgm-ficha-aba .sgm-resumo__ico {
  width: 22px;
  height: 22px;
  font-size: .8rem;
  border-radius: 6px;
}

/* Dentro da ficha o cartão é menor: ele divide a aba com os campos, e não
   encabeça a tela. */
.sgm-ficha-aba .sgm-resumo__rotulo { font-size: 11px; }
.sgm-ficha-aba .sgm-resumo__valor  { font-size: var(--sgm-t-base); }
/* ⚠️ `--sec` SAIU daqui junto com a regra principal (2026-08-15). O que
   encolhe aqui é o sinal, para a linha de duas medidas caber na aba. */
.sgm-ficha-aba .sgm-resumo__sinal  { font-size: 10px; }
.sgm-ficha-aba .sgm-resumo__medidas { gap: var(--sgm-2); }
.sgm-ficha-aba .sgm-resumo__medida + .sgm-resumo__medida { padding-left: var(--sgm-2); }

/* No telefone os cartões empilham: dois de 200px lado a lado numa tela de
   342px espremem o valor até quebrar no meio do número. */
@media (max-width: 560px) {
  .sgm-resumo__cartao { flex-basis: 100%; }
}

/* --------------------------------------------------------------------------
   8. Grid HTML — substitui o TUniDBGrid
   -------------------------------------------------------------------------- */

.sgm-grid-wrap {
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r);
  background: var(--color-surface);
  overflow: hidden;
  box-shadow: var(--sgm-sh-1);
}

.sgm-grid-scroll { overflow: auto; max-height: 62vh; }

/* --------------------------------------------------------------------------
   A NAVEGAÇÃO DE PÁGINAS — 2026-08-15

   Nasceu com a paginação no servidor: o detalhamento do Inventário
   Patrimonial Geral tem 96.581 linhas, e mandá-las de uma vez travava o
   navegador. Fica FORA da área de rolagem e depois do rodapé de totais — é
   navegação da grade inteira, não uma linha dela.

   O aviso ao lado não é enfeite: com página, a busca e os filtros de coluna
   valem só sobre o que está na mão, e quem procura uma chapa e não acha
   conclui que o bem não existe. Ele encolhe primeiro quando falta espaço,
   porque os botões é que precisam continuar alcançáveis no telefone.
   -------------------------------------------------------------------------- */

.sgm-grid-paginas {
  display: flex;
  align-items: center;
  gap: var(--sgm-2);
  flex-wrap: wrap;
  padding: var(--sgm-2) var(--sgm-3);
  border-top: 1px solid var(--color-outline);
  background: var(--color-surface-sunken);
}

.sgm-grid-paginas__conta {
  font-size: var(--sgm-t-sm);
  font-weight: 600;
  color: var(--color-on-surface);
  white-space: nowrap;
}

.sgm-grid-paginas__aviso {
  flex: 1 1 240px;
  min-width: 0;
  font-size: var(--sgm-t-xs);
  color: var(--color-on-surface-variant);
}

.sgm-grid {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--sgm-t-base);
}

.sgm-grid thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: 10px var(--sgm-3);
  background: var(--color-surface-sunken);
  border-bottom: 1px solid var(--color-outline);
  color: var(--color-on-surface-variant);
  font-size: var(--sgm-t-xs);
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: left;
  white-space: nowrap;
}

/* Quem ordena é o botão do título, não o <th>: com o filtro da coluna
   dentro da mesma célula, clicar para digitar reordenaria a tabela debaixo
   do dedo. */
.sgm-grid-ord {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  text-align: inherit;
  cursor: pointer;
  user-select: none;
}
.sgm-grid-ord:hover { color: var(--color-primary-500); }
.sgm-grid-ord::after {
  content: "\f0dc";
  font-family: "Font Awesome 7 Free";
  font-weight: 900;
  margin-left: 6px;
  opacity: .3;
  font-size: 9px;
}
.sgm-grid-ord[data-ord="asc"]::after  { content: "\f0de"; opacity: 1; color: var(--color-primary-500); }
.sgm-grid-ord[data-ord="desc"]::after { content: "\f0dd"; opacity: 1; color: var(--color-primary-500); }

/* .num alinha o conteúdo à direita; o botão precisa acompanhar */
.sgm-grid th.num { text-align: right; }
.sgm-grid th.num .sgm-grid-ord { justify-content: flex-end; }

/* --- filtro por coluna ---------------------------------------------------
   Mora no mesmo <th> do título — o cabeçalho é sticky, e uma segunda linha
   precisaria de um `top` em pixels casado com a altura da primeira.
   ------------------------------------------------------------------------- */

/* Coluna de valor ou quantidade: SELETOR DE OPERADOR + valor.
   Pedido do Rodrigo em 2026-08-07 — ele digitou 1000 esperando "maiores ou
   iguais a mil" e recebeu só os iguais. Com o operador à vista, não há o que
   adivinhar: escolhe-se com o mouse. Data ganha duas caixas, de e até. */
/* ⚠️ O OPERADOR E O VALOR FICAM SEMPRE NA MESMA LINHA.

   `flex-wrap: wrap` sozinho não basta: o campo herda `width: 100%` de
   `.sgm-grid-filtro` e nasce com base automática, então em coluna estreita
   ele não cabe ao lado do combo e **desce para a linha de baixo** — foi o
   que o Rodrigo viu. A correção é o campo poder ENCOLHER em vez de quebrar:
   `flex-basis: 0` com `width: auto`.

   O `wrap` fica porque é ele que joga o SEGUNDO campo do "entre" para
   baixo — e esse é o único que deve quebrar, por ter base 100%. */
.sgm-grid-filtro-grupo {
  /* As três medidas do filtro moram AQUI, e são usadas tanto no modo normal
     (flex) quanto no do "entre" (grade). É o que garante que a coluna da
     tabela não mude de largura ao trocar de operador — ver o `min-width`
     logo abaixo. */
  --sgm-op-w: 3.9rem;        /* o combo de operador */
  --sgm-filtro-min: 3.2rem;  /* o mínimo de uma caixa, para ainda dar para digitar */
  --sgm-filtro-gap: 4px;

  display: flex;
  align-items: stretch;
  flex-wrap: wrap;
  gap: var(--sgm-filtro-gap);
  margin-top: 6px;

  /* ⚠️ O QUE IMPEDE A COLUNA DE ENCOLHER NO "ENTRE".

     A largura de uma coluna de tabela sai do conteúdo. Sem este mínimo, a
     grade do "entre" tem largura mínima igual à do combo — a segunda trilha
     é `1fr`, que aceita zero — e a coluna encolhia junto, deixando as
     caixas espremidas. No modo flex isso não acontecia porque o
     `min-width` da caixa entrava na conta.

     Fixando o mínimo NO GRUPO, os dois modos declaram a mesma largura
     mínima e a coluna não se mexe ao trocar de operador. */
  min-width: calc(var(--sgm-op-w) + var(--sgm-filtro-gap) + var(--sgm-filtro-min));
}

/* 🥇 FILTRO DE TEXTO EM COLUNA DE LARGURA DECLARADA: sem o mínimo acima —
   2026-09-22, lista de programas do PPA.

   O `min-width` do grupo é o combo de operador mais uma caixa digitável, e
   existe para o filtro NUMÉRICO. O de texto não tem combo, mas herdava o
   mesmo mínimo — e segurava em 142px um Código que pediu 80. Quem liga esta
   classe é o `sgm-grid.js`, e só onde a coluna declara `largura`: nas outras
   grades nada muda, porque lá o campo de texto continua com a largura natural
   dele, maior que este mínimo.

   ⚠️ 0,2,0 contra os 0,1,0 da regra do grupo: vence pela aritmética da
      cascata, e não por vir depois. */
.sgm-grid-filtro-grupo.sgm-grid-filtro-grupo--estreito { min-width: 0; }

/* base zero: encolhe até o mínimo em vez de descer de linha */
.sgm-grid-filtro-grupo .sgm-grid-filtro {
  flex: 1 1 0;
  width: auto;
  /* mas não a ponto de não dar para digitar; a coluna cresce se precisar */
  min-width: var(--sgm-filtro-min);
}

/* O segundo campo do "entre" é o ÚNICO que ocupa a linha inteira: três
   caixas lado a lado numa coluna de tabela não caberiam em nenhuma delas.

   ⚠️ O seletor precisa dos DOIS níveis. `.sgm-grid-filtro--2` sozinho é
   (0,1,0) e perderia para `.sgm-grid-filtro-grupo .sgm-grid-filtro`, que é
   (0,2,0) — o `flex: 1 1 0` de cima ganharia e o campo ficaria ao lado em
   vez de descer. Empatando em (0,2,0) e vindo depois, este vence. */
.sgm-grid-filtro-caixas .sgm-grid-filtro--2[hidden] { display: none; }

/* --------------------------------------------------------------------------
   O "entre": combo à esquerda, as duas caixas empilhadas à direita
   --------------------------------------------------------------------------
       ┌─────────┐  ┌──────────────┐
       │  entre ▾│  │      de      │
       └─────────┘  ├──────────────┤
                    │     até      │
                    └──────────────┘

   Desenho pedido pelo Rodrigo em 2026-08-07. Antes, o combo ficava preso à
   primeira linha e o "até" descia sozinho por baixo dele — o combo parecia
   pertencer só ao "de", quando ele manda nos dois.

   Aqui a caixa vira GRADE em vez de flex: o combo ocupa as duas linhas da
   primeira coluna e as caixas se acomodam sozinhas na segunda. Sem `<div>`
   embrulhando nada — a estrutura do HTML não muda por causa de um layout.

   A classe entra e sai pelo JS, junto com o operador (sgm-grid.js). */
/* A coluna das caixas. Ela existe SEMPRE — com uma caixa ou com duas —, e é
   isso que impede a coluna da tabela de mudar de largura ao escolher o
   "entre": a estrutura horizontal do grupo é sempre `combo + esta coluna`.
   Ver o comentário no sgm-grid.js, em montarFiltro. */
.sgm-grid-filtro-caixas {
  flex: 1 1 0;
  min-width: var(--sgm-filtro-min);
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.sgm-grid-filtro-caixas .sgm-grid-filtro { width: 100%; flex: 0 0 auto; }

/* com duas caixas, o combo manda nas duas — então fica no meio delas */
.sgm-grid-filtro-grupo--entre { align-items: center; }

.sgm-grid-op {
  flex: 0 0 auto;
  /* cabe "entre", que é o único rótulo em palavra. A medida vem do grupo
     porque a grade do "entre" usa a mesma — ver o min-width de lá. */
  width: var(--sgm-op-w, 3.9rem);
  padding: 3px 2px 3px 5px;
  background: var(--color-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-sm);
  color: var(--color-on-surface);
  font: inherit;
  font-size: var(--sgm-t-xs);
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  text-align: center;
  cursor: pointer;
}
.sgm-grid-op:focus {
  outline: none;
  border-color: var(--color-primary-500);
  box-shadow: 0 0 0 3px rgba(15, 118, 110, .18);
}
/* operador diferente de "=" com filtro ligado: é ele que explica o
   resultado, e tem de saltar aos olhos */
.sgm-grid-op[data-ativo="true"] {
  border-color: var(--color-primary-500);
  background: var(--color-primary-50);
  color: var(--color-primary-500);
}

.sgm-grid-filtro-grupo .sgm-grid-filtro { margin-top: 0; }

/* de … até, uma sobre a outra: em coluna de tabela não cabem lado a lado */
.sgm-grid-filtro-grupo--data { flex-direction: column; gap: 3px; }
.sgm-grid-filtro-grupo--data .sgm-grid-filtro { flex: 0 0 auto; width: 100%; }

.sgm-grid-filtro {
  display: block;
  width: 100%;
  margin-top: 6px;
  padding: 3px 6px;
  background: var(--color-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-sm);
  color: var(--color-on-surface);
  font: inherit;
  font-size: var(--sgm-t-xs);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  min-width: 0;
}
.sgm-grid-filtro:focus {
  outline: none;
  border-color: var(--color-primary-500);
  box-shadow: 0 0 0 3px rgba(15, 118, 110, .18);
}
/* Filtro ligado tem de ser visível de longe: é ele que explica um total
   menor do que o usuário esperava. */
.sgm-grid-filtro[data-ativo="true"] {
  border-color: var(--color-primary-500);
  background: var(--color-primary-50);
  font-weight: 650;
}

/* Texto que a coluna numérica não entendeu: a coluna NÃO filtra, e o campo
   diz isso. Sem a marca, "mil" digitado em Valor não muda nada na tela e o
   usuário fica achando que o filtro está quebrado. */
.sgm-grid-filtro[data-erro="true"] {
  border-color: var(--color-error, #b42318);
  background: #fef3f2;
  font-weight: 650;
}
select.sgm-grid-filtro { cursor: pointer; }
.sgm-grid th.num .sgm-grid-filtro { text-align: right; }

.sgm-grid tbody td {
  padding: 9px var(--sgm-3);
  border-bottom: 1px solid #f0f4f8;
  color: var(--color-on-surface);
  vertical-align: middle;
}

.sgm-grid tbody tr { transition: background-color var(--sgm-fast) var(--sgm-ease); }
.sgm-grid tbody tr:hover { background: var(--color-primary-50); }
.sgm-grid tbody tr[aria-selected="true"] { background: var(--color-primary-50); box-shadow: inset 2px 0 0 var(--color-primary-500); }
.sgm-grid tbody tr:last-child td { border-bottom: 0; }

.sgm-grid .num  { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sgm-grid .cent { text-align: center; }

/* 🥇 NÚMERO CENTRALIZADO — `num cent` juntas, 2026-09-22.

   Pedido do Rodrigo com o print da lista de programas do PPA: os percentuais
   no centro da coluna. A coluna manda `"classe":"num cent"` (`ComForma`, em
   `uSgmFicha.pas`): o `num` continua dando o que o número precisa — dígitos
   tabulares e nada de quebra —, e o `cent` muda só o alinhamento.

   ⚠️ AS REGRAS VÃO COM AS DUAS CLASSES, E NÃO SÓ COM `.cent`. `.sgm-grid .num`
      e `.sgm-grid .cent` empatam em 0,2,0 e hoje a `.cent` vence só por vir
      depois — empate de especificidade já custou quatro defeitos neste
      projeto. Aqui `.num.cent` é 0,3,0 contra 0,2,0, e o cabeçalho, que o
      `num` empurra para a direita em duas regras (o texto e o botão de
      ordenar, que é flex), ganha as duas de volta pela mesma aritmética. */
.sgm-grid .num.cent { text-align: center; }
.sgm-grid th.num.cent .sgm-grid-ord { justify-content: center; }
.sgm-grid th.num.cent .sgm-grid-filtro { text-align: center; }

/* TEXTO CENTRALIZADO — só `cent`, 2026-09-22, a Unidade da Execução dos
   programas ("%", "UN"). O texto da célula já centralizava por
   `.sgm-grid .cent`; faltava o CABEÇALHO, cujo botão de ordenar é flex e
   ficava à esquerda. 0,3,1 — o mesmo peso de `.sgm-grid th.num .sgm-grid-ord`,
   mas as duas nunca disputam a mesma coluna: coluna com `num` e `cent` cai
   na regra de cima, que é 0,4,1. */
.sgm-grid th.cent .sgm-grid-ord { justify-content: center; }

.sgm-grid tfoot td {
  position: sticky;
  bottom: 0;
  padding: 10px var(--sgm-3);
  background: var(--color-surface-sunken);
  border-top: 1px solid var(--color-outline-strong);
  font-weight: 700;
  color: var(--color-on-surface);
}

/* Total que acompanha o filtro muda de cor: o número passa a responder outra
   pergunta, e quem olhar de relance precisa saber disso sem ler o rótulo. */
.sgm-grid tfoot[data-filtrado="true"] td {
  background: var(--color-primary-50);
  border-top-color: var(--color-primary-500);
  box-shadow: inset 0 2px 0 var(--color-primary-500);
}

/* --------------------------------------------------------------------------
   A CÉLULA DE ROTULAGEM DO TOTAL — e por que ela virou três coisas

   Desde 2026-08-14 ela carrega, na ordem em que se lê: o "Limpar filtros"
   (só com filtro ligado), a CONTAGEM de registros e o rótulo do total.
   Pedido do Rodrigo: a barra que ficava sob a grade sumiu, e o que ela dizia
   ("123 registros") entrou aqui, antes do TOTAL. Uma faixa horizontal a menos
   numa tela cuja matéria-prima é altura de lista.
   -------------------------------------------------------------------------- */
/* ⚠️ SEM `display: flex` NESTE `<td>` — e isto custou um defeito em
   2026-08-14, apontado pelo Rodrigo com o print: *"a parte que fica o total de
   registros e o TOTAL particionou; só quando rolo o scroll para o final que
   ela aparece"*.

   A célula tem `position: sticky` (a linha de total fica grudada no rodapé da
   área que rola). Trocar o `display` de um `<td>` o TIRA do layout de tabela —
   ele deixa de ser célula, o sticky perde a referência e a linha volta a ser
   uma linha comum no fim da lista, que só aparece quando a rolagem chega lá.

   O alinhamento das três peças (Limpar filtros · contagem · rótulo) vive num
   `<span>` interno, que pode ser flex à vontade. */
.sgm-grid-total__rot {
  font-size: var(--sgm-t-xs);
  text-transform: uppercase;
  letter-spacing: .04em;
  white-space: nowrap;
}

.sgm-grid-total__cx {
  display: flex;
  align-items: center;
  gap: var(--sgm-3);
}

/* a contagem é apoio, não título: some do caixa-alta e fica mais leve que o
   rótulo do total, que é o que a linha vem dizer */
.sgm-grid-total__conta {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  color: var(--color-on-surface-variant);
}

/* O botão dentro da célula não pode herdar o caixa-alta nem esticar a linha:
   ele só aparece com filtro, e a linha não pode pular de altura quando ele
   entra — isso deslocaria a grade inteira a cada filtro digitado. */
.sgm-grid-total__rot .sgm-btn {
  text-transform: none;
  letter-spacing: 0;
  margin: -4px 0;
}

/* grid sem totais: a linha existe só para a contagem, e não deve parecer um
   total que não há */
.sgm-grid tfoot[data-so-conta="true"] td {
  font-weight: 400;
  box-shadow: none;
  border-top: 1px solid var(--color-outline);
}

/* ⚠️ AQUI NÃO ENTRA CSS DE MENU — e isto é o registro de um erro de 2026-08-14.

   O "Exportar" do detalhamento nasceu com `.sgm-menu` e `.sgm-menu__item`
   escritos AQUI, sem eu ver que o sistema já tinha os dois na §10 deste mesmo
   arquivo (o menu suspenso do cabeçalho). As duas regras coexistiram, a de
   baixo venceu o empate, e o menu abria com `opacity: 0`: o Rodrigo clicava e
   NADA ACONTECIA — nem erro no console, porque erro não havia.

   É o quarto empate de especificidade a custar um defeito neste projeto. A
   regra que sobra: antes de escrever uma classe nova, procure o nome no CSS.
   O menu de exportação usa a §10, com `data-open` e `SGM.popover`. */

.sgm-grid-pe {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sgm-3);
  flex-wrap: wrap;
  padding: var(--sgm-2) var(--sgm-3);
  border-top: 1px solid var(--color-outline);
  background: var(--color-surface-sunken);
  font-size: var(--sgm-t-sm);
  color: var(--color-on-surface-variant);
}

/* no telefone a linha vira cartão: o cabeçalho de coluna acompanha o valor */
@media (max-width: 767px) {
  .sgm-grid thead { display: none; }
  .sgm-grid, .sgm-grid tbody, .sgm-grid tr, .sgm-grid td { display: block; width: 100%; }
  .sgm-grid-scroll { max-height: none; }

  .sgm-grid tbody tr {
    padding: var(--sgm-2) var(--sgm-3);
    border-bottom: 1px solid var(--color-outline);
  }
  .sgm-grid tbody td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sgm-3);
    padding: 4px 0;
    border: 0;
    text-align: right;
  }
  .sgm-grid tbody td::before {
    content: attr(data-col);
    flex: 0 0 auto;
    font-size: var(--sgm-t-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--color-on-surface-variant);
    text-align: left;
  }
  .sgm-grid tfoot { display: block; }
  .sgm-grid tfoot tr { display: block; }
  .sgm-grid tfoot td { display: flex; justify-content: space-between; }
}

/* --------------------------------------------------------------------------
   9. Aviso flutuante
   -------------------------------------------------------------------------- */

.sgm-toasts {
  position: fixed;
  right: var(--sgm-4);
  bottom: var(--sgm-4);
  z-index: var(--sgm-z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--sgm-2);
  pointer-events: none;
}

.sgm-toast {
  display: flex;
  align-items: flex-start;
  gap: var(--sgm-3);
  min-width: 260px;
  max-width: 380px;
  padding: var(--sgm-3) var(--sgm-4);
  background: var(--color-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r);
  box-shadow: var(--sgm-sh-3);
  pointer-events: auto;
  animation: sgm-toast-in var(--sgm-slow) var(--sgm-ease);
}

@keyframes sgm-toast-in {
  from { opacity: 0; transform: translateY(10px) scale(.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.sgm-toast__ico { flex: 0 0 auto; margin-top: 1px; }
.sgm-toast[data-tom="ok"]     .sgm-toast__ico { color: var(--color-success); }
.sgm-toast[data-tom="risco"]  .sgm-toast__ico { color: var(--color-error); }
.sgm-toast[data-tom="alerta"] .sgm-toast__ico { color: var(--color-warning); }
.sgm-toast[data-tom="info"]   .sgm-toast__ico { color: var(--color-info); }

.sgm-toast__txt    { flex: 1 1 auto; min-width: 0; }
.sgm-toast__titulo { font-weight: 650; font-size: var(--sgm-t-base); }
/* 💎 O CORPO DO AVISO FLUTUANTE TAMBÉM PASSOU A `variant` — 2026-08-20,
   terceira volta, pela mesma medida: 4,28:1 -> 7,32:1. É ele que carrega as
   respostas que esta entrega reescreveu para virarem voz de gente — "Esta
   pessoa não tem registro neste sistema.", "Faça uma pesquisa primeiro." —,
   e um aviso que some em quatro segundos é o texto que menos pode custar
   esforço de leitura. Está na lista `PROSA` de confere-contraste.js §2. */
.sgm-toast__msg    { font-size: var(--sgm-t-sm); color: var(--color-on-surface-variant); margin-top: 1px; }

@media (max-width: 767px) {
  .sgm-toasts { left: var(--sgm-3); right: var(--sgm-3); bottom: var(--sgm-3); }
  .sgm-toast  { max-width: none; }
}

/* --------------------------------------------------------------------------
   10. Menu suspenso — sai do container para não ser recortado
   -------------------------------------------------------------------------- */

/* Sombra e raio do header-dropdown do modelo Angular: a borda entra como
   segunda camada do box-shadow, não como border — assim o painel não ganha
   1px de largura e alinha certo com o botão que o abriu. */
.sgm-menu {
  position: fixed;
  z-index: var(--sgm-z-popover);
  min-width: 190px;
  padding: var(--sgm-1);
  background: var(--color-surface);
  color: var(--color-on-surface);
  border: 0;
  border-radius: 0.75rem;
  overflow: hidden;
  box-shadow: 0 20px 40px -12px rgb(0 0 0 / .35), 0 0 0 1px var(--color-outline);
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  transition: opacity var(--sgm-fast) var(--sgm-ease),
              transform var(--sgm-fast) var(--sgm-ease);
}
.sgm-menu[data-open="true"] { opacity: 1; transform: translateY(0); pointer-events: auto; }

.sgm-menu__item {
  display: flex;
  align-items: center;
  gap: var(--sgm-3);
  width: 100%;
  padding: 8px var(--sgm-3);
  background: transparent;
  border: 0;
  border-radius: var(--sgm-r-sm);
  color: var(--color-on-surface);
  font: inherit;
  font-size: var(--sgm-t-base);
  text-align: left;
  cursor: pointer;
  transition: background-color var(--sgm-fast) var(--sgm-ease);
}
.sgm-menu__item:hover { background: var(--color-primary-50); color: var(--color-primary-600); }
.sgm-menu__item i { width: 15px; text-align: center; color: var(--color-on-surface-muted); font-size: 12px; }
.sgm-menu__item:hover i { color: var(--color-primary-500); }
.sgm-menu__sep { height: 1px; margin: var(--sgm-1) 0; background: var(--color-outline); }
.sgm-menu__item[data-tom="risco"] { color: var(--color-error); }
.sgm-menu__item[data-tom="risco"]:hover { background: var(--color-error-container); color: var(--color-error); }
.sgm-menu__item[data-tom="risco"] i,
.sgm-menu__item[data-tom="risco"]:hover i { color: var(--color-error); }

/* --------------------------------------------------------------------------
   9. Abas — o TUniPageControl do legado
   --------------------------------------------------------------------------
   Clicar em Detalhes não troca a tela: abre uma aba ao lado, e o dashboard
   fica montado atrás (sgm-shell.js §4b). A tira só aparece a partir da
   segunda aba.

   Ela gruda no topo do miolo — e não da janela — porque quem rola agora é o
   .sgm-main (sgm-shell.css §0). Sem isso, descer numa grid de trezentas
   linhas levaria as abas embora.
   -------------------------------------------------------------------------- */

/* ⚠️ SEM `position: sticky` E SEM RECUO NEGATIVO NO TOPO.

   As duas coisas vieram de quando o `.sgm-main` rolava: o sticky segurava a
   tira no alto, e o `margin-top` negativo a fazia sangrar para dentro do
   padding, encostando na topbar.

   Desde que o miolo virou coluna flex que NÃO rola (sgm-shell.css §0), as
   duas viraram defeito: o recuo negativo puxa a tira para fora da área do
   flex e o topo dela é recortado, deixando a faixa branca que o Rodrigo viu
   por cima das abas. O sticky, sem ancestral que role, só não faz nada.

   O sangramento lateral fica — ali ele é o que dá a linha de base de ponta a
   ponta, e não puxa nada para fora. */
.sgm-abas {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-end;
  gap: var(--sgm-1);
  margin: 0 calc(var(--sgm-5) * -1) var(--sgm-4);
  padding: 0 var(--sgm-5);
  background: var(--color-background);
  border-bottom: 1px solid var(--color-outline);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: thin;
}

.sgm-abas[hidden] { display: none; }

/* A TIRA DE DENTRO — o PageControl aninhado do legado.

   A ficha do contrato tem `pg1` dentro de `pg`: a aba Contábil agrupa
   Extrato, Empenhos, Liquidações, Receitas, Dotações e Itens Licitação
   (uVisSCPIFichaContratos.dfm).

   ⚠️ A tira de fora sangra para as laterais de propósito — é o que dá a linha
   de base de ponta a ponta. A de dentro NÃO PODE: ela vive dentro de um
   painel, e o mesmo sangramento a jogaria para fora dele. É primo do recuo
   negativo que recortou o topo das abas em 2026-08-07 (§6h) — margem negativa
   em elemento aninhado é sempre a mesma armadilha.

   Ela também é menor que a de fora. Duas tiras idênticas não diriam qual
   está dentro de qual, e a hierarquia é a informação. */
.sgm-abas--interna {
  margin: 0 0 var(--sgm-3);
  padding: 0;
  background: transparent;
}

.sgm-abas--interna .sgm-aba {
  padding: 5px var(--sgm-3);
  font-size: var(--sgm-t-xs);
}

.sgm-aba {
  display: inline-flex;
  align-items: center;
  gap: var(--sgm-2);
  flex: 0 0 auto;
  max-width: 260px;
  padding: 8px var(--sgm-3);
  background: transparent;
  border: 1px solid transparent;
  border-bottom: 0;
  border-radius: var(--sgm-r-sm) var(--sgm-r-sm) 0 0;
  color: var(--color-on-surface-variant);
  font: inherit;
  font-size: var(--sgm-t-sm);
  font-weight: 600;
  cursor: pointer;
  /* a aba desce 1px para cobrir a borda da tira quando está ativa */
  margin-bottom: -1px;
  transition: background-color var(--sgm-fast) var(--sgm-ease),
              color var(--sgm-fast) var(--sgm-ease);
}

.sgm-aba:hover { background: var(--color-surface-sunken); color: var(--color-on-surface); }

.sgm-aba[aria-selected="true"] {
  background: var(--color-surface);
  border-color: var(--color-outline);
  color: var(--color-on-surface);
}

/* sombra do acento no topo: a aba ativa não depende só da cor de fundo,
   que sozinha tem contraste baixo demais para marcar seleção */
.sgm-aba[aria-selected="true"] {
  box-shadow: inset 0 2px 0 var(--color-primary-500);
}

.sgm-aba__txt {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sgm-aba__fechar {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 18px; height: 18px;
  border-radius: 50%;
  font-size: 10px;
  color: var(--color-on-surface-muted);
  cursor: pointer;
}
.sgm-aba__fechar:hover { background: var(--color-outline); color: var(--color-on-surface); }

/* o sangramento lateral tem de casar com o padding do .sgm-main, que encolhe
   no telefone (sgm-shell.css §6) — senão a tira flutua deslocada */
@media (max-width: 767px) {
  .sgm-abas {
    margin: 0 calc(var(--sgm-3) * -1) var(--sgm-3);
    padding: 0 var(--sgm-3);
  }
}

.sgm-painel[hidden] { display: none; }

/* Cada aba rola por conta própria — e guarda onde estava, como um
   PageControl. A tira de abas fica fora, então não vai embora ao rolar. */
.sgm-shell-fixo .sgm-painel {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  scrollbar-gutter: stable;
}

/* --------------------------------------------------------------------------
   Tela que PREENCHE a altura em vez de rolar
   --------------------------------------------------------------------------
   O detalhamento é assim: cabeçalho e busca parados em cima, a grade tomando
   o que sobra, e o rodapé de totais e exportação encostado embaixo — sempre
   à vista.

   Antes, a grade tinha `max-height: 62vh` fixo, o que somado ao cabeçalho e
   à barra de busca passava da tela: aparecia uma SEGUNDA barra de rolagem, a
   da página, e era ela que levava embora as abas e escondia o rodapé.
   Pedido do Rodrigo em 2026-08-07: "o certo é não precisar rolar a página e
   rolar somente o grid".
   -------------------------------------------------------------------------- */

/* ⚠️ `:not([hidden])` NÃO É ENFEITE — sem ele a aba não fecha.

   `.sgm-painel[hidden] { display: none }` e `.sgm-shell-fixo .sgm-painel--cheio
   { display: flex }` têm a MESMA especificidade (0,2,0). Empate se desempata
   pela ordem do arquivo, e esta regra vem depois: o `display: flex` ganhava
   do `display: none`, e o painel do detalhamento continuava desenhado por
   baixo do dashboard ao voltar ao quadro.

   É o mesmo defeito do realce de foco no login (§6a) — empate resolvido pela
   ordem de carga. Ali custou uma cobrança do Rodrigo, aqui outra.

   Regra: toda regra que mexer em `display` de um `.sgm-painel` tem de sair
   de cena quando o atributo `hidden` está posto. Há uma conferência disso em
   `scripts\testa-abas.js`. */
.sgm-shell-fixo .sgm-painel--cheio:not([hidden]) {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.sgm-painel--cheio > * { flex: 0 0 auto; }

/* --------------------------------------------------------------------------
   "Busca dinâmica" — o botão que abre e fecha a faixa de busca

   A faixa "Buscar" ocupava uma linha inteira em toda tela de detalhamento, o
   tempo todo, para uma coisa que se usa de vez em quando. Oculta, aquela
   altura vai para a grade — pedido do Rodrigo em 2026-08-10.

   ⚠️ A PRIMEIRA VERSÃO ERA UM DISCO FLUTUANTE no canto inferior direito, e o
   Rodrigo derrubou na hora: ele cobria linha de dado, ou seja, tomava de
   volta exatamente o espaço que a mudança queria liberar. Um botão na fileira
   de ações não disputa espaço com nada, e ainda leva rótulo — um disco com
   lupa depende de o usuário adivinhar o que faz.

   Fica só o realce de "está filtrando", abaixo. Não há mais nenhuma regra de
   flutuação, e o painel voltou a não precisar de `position: relative`.
   -------------------------------------------------------------------------- */

/* ⚠️ Filtrando com a faixa FECHADA é o estado perigoso: a lista está menor e
   o total é o do filtro, sem nada na tela dizendo por quê. O ponto é o aviso
   — some assim que a busca é limpa. */
.sgm-btn[data-filtrando] {
  position: relative;
  border-color: var(--color-primary-500);
  color: var(--color-primary-500);
}

.sgm-btn[data-filtrando]::after {
  content: '';
  position: absolute;
  top: -3px;
  right: -3px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #e34948;
  box-shadow: 0 0 0 2px var(--color-surface);
}

/* --------------------------------------------------------------------------
   Lista de séries do diálogo de seleção
   -------------------------------------------------------------------------- */

.sgm-series {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sgm-series__item {
  display: flex;
  align-items: center;
  gap: var(--sgm-2);
  padding: 6px 8px;
  border-radius: var(--sgm-r-sm);
  cursor: pointer;
}

.sgm-series__item:hover { background: var(--color-surface-sunken); }
.sgm-series__item > span { min-width: 0; overflow-wrap: anywhere; }

/* --------------------------------------------------------------------------
   A FICHA — o terceiro nível, atrás da lupa da grid

   Porte de uVisComprasFichaPedido, e genérico: serve ficha de pedido, de
   requisição, de produto e o que vier. Cabeçalho de campos, marcas e abas.
   -------------------------------------------------------------------------- */

/* MALHA DE 12 COLUNAS, o mesmo vocabulário do `col` dos quadros.

   A ficha do legado não é uma lista de campos iguais: é um formulário denso,
   com o número e o total nas pontas e as linhas em larguras diferentes. Sem
   as 12 colunas não dá para reproduzir aquilo, e o operador teria de
   reaprender uma tela que já sabia. */
.sgm-ficha-campos {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  /* 3px e não var(--sgm-2): com três linhas de campos, cada 5px de gap a mais
     são 15px que o cabeçalho cresce — e é aí que a ficha deixa de caber */
  gap: 3px;
  margin-bottom: var(--sgm-2);
}

/* --------------------------------------------------------------------------
   A FICHA EM DUAS COLUNAS — a divisão da tela de empenho

   Só vale com "layout":"duas-colunas" vindo do servidor: a ficha do
   fornecedor é de uma coluna e já foi conferida assim.

   A proporção é a do legado: ScrollVisEmpenho 579px à esquerda e PG 463px à
   direita (uVisSCPIEmpenho.dfm) — 55/45.

   ⚠️ minmax(0, ...) NAS DUAS, e não 1fr puro: item de grade tem min-width
   auto, e uma grid larga dentro da coluna da direita empurraria a coluna
   além do diálogo em vez de rolar dentro dela.
   -------------------------------------------------------------------------- */
.sgm-ficha-colunas {
  display: grid;
  grid-template-columns: minmax(0, 55fr) minmax(0, 45fr);
  gap: var(--sgm-3);
  align-items: start;
}

.sgm-ficha-col { min-width: 0; }

/* Sem largura para duas, viram uma — e a ordem da marcação já é a certa:
   informação primeiro, abas depois. */
@media (max-width: 1023px) {
  .sgm-ficha-colunas { grid-template-columns: minmax(0, 1fr); }
}

/* O título de grupo do cabeçalho — os quatro painéis titulados do empenho
   (Empenho, Ficha, Fornecedor, Licitação). Ocupa a linha inteira da grade de
   12, com um filete embaixo em vez de moldura em volta: caixa dentro de caixa
   gastaria a altura que a ficha não tem (ver o aviso logo abaixo). */
.sgm-ficha-grupo {
  grid-column: 1 / -1;
  margin-top: var(--sgm-2);
  padding-bottom: 2px;
  border-bottom: 1px solid var(--color-primary-500);
  font-size: var(--sgm-t-sm);
  font-weight: 700;
  color: var(--color-primary-500);
  text-transform: uppercase;
  letter-spacing: .02em;
}

/* o primeiro grupo encosta no topo do bloco */
.sgm-ficha-campos > .sgm-ficha-grupo:first-child { margin-top: 0; }

/* ⚠️ ALTURA É O RECURSO ESCASSO AQUI.

   O primeiro desenho usava padding de 4px e gap de 1px, e ainda assim o
   cabeçalho do pedido não cabia sem rolagem. O Rodrigo pediu mais síntese, e
   está certo: numa janela que abre por cima de outra, cada pixel de moldura é
   pixel que não é dado. Rótulo colado no valor, moldura mínima. */
.sgm-ficha-campo {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 0;
  padding: 2px var(--sgm-2) 3px;
  line-height: 1.25;
  border-radius: var(--sgm-r-sm);
  background: var(--color-surface-sunken);
  grid-column: span 3;
}

.sgm-ficha-campo[data-col="1"]  { grid-column: span 1; }
.sgm-ficha-campo[data-col="2"]  { grid-column: span 2; }
.sgm-ficha-campo[data-col="3"]  { grid-column: span 3; }
.sgm-ficha-campo[data-col="4"]  { grid-column: span 4; }
.sgm-ficha-campo[data-col="5"]  { grid-column: span 5; }
.sgm-ficha-campo[data-col="6"]  { grid-column: span 6; }
/* ⚠️ A ESCALA TEM DE SER COMPLETA, DE 1 A 12.
   Faltavam 7, 9, 10 e 11 — e `col` sem regra não é erro: o campo cai para
   UMA coluna de doze. Foi o que espremeu o nome do fornecedor da ficha do
   empenho em três linhas (col 9). Conferido por scripts\testa-ficha.js. */
.sgm-ficha-campo[data-col="7"]  { grid-column: span 7; }
.sgm-ficha-campo[data-col="8"]  { grid-column: span 8; }
.sgm-ficha-campo[data-col="9"]  { grid-column: span 9; }
.sgm-ficha-campo[data-col="10"] { grid-column: span 10; }
.sgm-ficha-campo[data-col="11"] { grid-column: span 11; }
.sgm-ficha-campo[data-col="12"] { grid-column: span 12; }

.sgm-ficha-campo__rot {
  font-size: var(--sgm-t-xs);
  color: var(--color-on-surface-variant);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* valor e lupa na mesma linha, como o edCodif + botão do legado */
.sgm-ficha-campo__linha {
  display: flex;
  align-items: center;
  gap: var(--sgm-1);
  min-width: 0;
}

.sgm-ficha-campo__val {
  flex: 1 1 auto;
  min-width: 0;
  font-weight: 600;
  color: var(--color-on-surface);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

/* Número do pedido e total: é o que o operador procura primeiro, e no legado
   os dois vêm em azul e maiores que o resto (DBText1 / DBText2). */
.sgm-ficha-campo[data-destaque] {
  background: var(--color-primary-50);
  border: 1px solid var(--color-primary-100);
}
/* destaque não pode crescer a linha: --sgm-t-md em vez de --sgm-t-lg mantém
   a altura do campo e ainda separa do resto pela cor e pelo fundo */
.sgm-ficha-campo[data-destaque] .sgm-ficha-campo__val {
  font-size: var(--sgm-t-md);
  color: var(--color-primary-600);
}

/* --------------------------------------------------------------------------
   MEMO DENTRO DA MALHA — o Objeto da licitação

   No legado o memo do Objeto tem 548px e os três valores começam em 578
   (uVisLicitacaoFichaProcesso.dfm): o texto à esquerda, os números à direita.
   Reproduzir isso na grade de 12 pede as DUAS coisas — largura (o `data-col`,
   que já existe) e ALTURA.

   É o `grid-row: span` que abre a coluna da direita. Sem ele o memo vale uma
   linha, os valores vão para as linhas de baixo e sobra meia tela vazia ao
   lado do texto — foi o que o Rodrigo circulou de vermelho em 2026-08-10.

   ⚠️ `overflow: auto` e não `hidden`: objeto de licitação chega a dez linhas,
   e cortar o texto sem dizer que cortou é pior do que uma barra de rolagem
   pequena. `min-height: 0` porque item de grade não encolhe por padrão, e sem
   ele o `overflow` nunca chega a valer.
   -------------------------------------------------------------------------- */

.sgm-ficha-campo[data-memo] {
  min-height: 0;
}
.sgm-ficha-campo[data-memo][data-linhas="2"] { grid-row: span 2; }
.sgm-ficha-campo[data-memo][data-linhas="3"] { grid-row: span 3; }

.sgm-ficha-campo[data-memo][data-linhas="4"] { grid-row: span 4; }
.sgm-ficha-campo[data-memo][data-linhas="5"] { grid-row: span 5; }

/* O valor deixa de ser uma linha só: quebra, respeita as quebras que vieram
   do SCPI, e rola dentro da própria caixa. */
.sgm-ficha-campo[data-memo] .sgm-ficha-campo__linha {
  align-items: flex-start;
  min-height: 0;
  overflow: auto;
}
.sgm-ficha-campo[data-memo] .sgm-ficha-campo__val {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  font-weight: 400;
}

/* --------------------------------------------------------------------------
   Campo de uma linha — as caixas Entradas / Saídas / Estoque

   No legado são três painéis com o rótulo à esquerda e o valor à direita,
   amarelo nos dois primeiros e verde no terceiro
   (uVisComprasFichaProduto.dfm, UniFiorilliPanel17/18/19). Rótulo em cima
   gastaria o dobro da altura para dizer a mesma coisa.
   -------------------------------------------------------------------------- */

.sgm-ficha-campo[data-linha] {
  flex-direction: row;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sgm-2);
}

.sgm-ficha-campo[data-linha] .sgm-ficha-campo__rot { flex: 0 0 auto; }
.sgm-ficha-campo[data-linha] .sgm-ficha-campo__linha { flex: 0 1 auto; }
.sgm-ficha-campo[data-linha] .sgm-ficha-campo__val {
  font-weight: 700;
  text-align: right;
}

.sgm-ficha-campo[data-tom="ambar"] {
  background: var(--color-warning-container);
  border: 1px solid var(--color-warning-outline);
}
.sgm-ficha-campo[data-tom="ambar"] .sgm-ficha-campo__val { color: var(--color-warning); }

.sgm-ficha-campo[data-tom="ok"] {
  background: var(--color-success-container);
  border: 1px solid var(--color-success-outline);
}
.sgm-ficha-campo[data-tom="ok"] .sgm-ficha-campo__val { color: var(--color-success); }

/* AS CORES DO CABEÇALHO DO CONTRATO — e elas são do legado, não de gosto.

   uVisSCPIFichaContratos.dfm pinta o valor de cada UniDBText:

     VIGENI · VIGENF · ADTFIM · DTENCERRAMENTO   clRed
     VALCON                                       clNavy
     ADITAMENTOS                                  clTeal
     TOTALGERAL                                   clBlack, e é o único em negrito

   O vermelho ali não é erro: é prazo. Quem opera esse sistema procura a
   vigência pela cor antes de ler o rótulo, e foi por isso que o Rodrigo
   cobrou o destaque nesses cinco — sem cor, viravam cinco campos iguais no
   meio de vinte.

   Só a COR do valor muda; o fundo continua o comum. Fundo colorido em cinco
   campos de uma linha só faria o cabeçalho competir com o resto da ficha. */
.sgm-ficha-campo[data-tom="prazo"] .sgm-ficha-campo__val {
  color: var(--color-error);
  font-weight: 600;
}

.sgm-ficha-campo[data-tom="valor"] .sgm-ficha-campo__val {
  color: var(--color-info);
  font-weight: 600;
}

.sgm-ficha-campo[data-tom="aditado"] .sgm-ficha-campo__val {
  color: var(--color-primary-600);
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   A FOTO 3x4 — o retrato dentro do cabeçalho da ficha

   Vem das fichas do Ensino: `pnlFoto`, 88 x 118 px em (7, 4), com um
   TUniDBImage de 86 x 116 dentro (uVisSIEFichaAluno.dfm:24-47 e
   uVisSIEFichaProfessor.dfm:24-47, idênticos). É 3x4 — a foto de documento —,
   e é essa proporção que faz o retrato ser reconhecível como retrato.

   ⚠️ NÃO É `.sgm-ficha-arquivo`. Aquele é o anexo do Portal e ocupa 70vh:
   sozinho no diálogo, no lugar dos campos. Este divide a linha com o nome, o
   RA e a idade.

   ⚠️ `grid-row: span 3` — a mesma peça do memo, e pela mesma razão. Sem ela o
   retrato valeria UMA linha da malha e esticaria essa linha para 118px, com
   os campos vizinhos boiando no meio de uma faixa alta e o cabeçalho crescendo
   o dobro. Com ela, três campos caem ao lado da foto e a ficha não cresce —
   que é o pedido: popup que rola é popup que não sintetizou.

   ⚠️ A MOLDURA TEM TAMANHO FIXO, e é o do .dfm. Deixá-la elástica faria a
   foto esticar junto com a coluna e a proporção 3x4 morrer na primeira tela
   larga — rosto achatado, que é exatamente o que o `Stretch = True` do legado
   causava e ninguém escolheu.
   -------------------------------------------------------------------------- */
.sgm-ficha-foto {
  grid-row: span 3;
  align-items: flex-start;
  background: transparent;
  padding-left: 0;
}

.sgm-ficha-foto__moldura {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 88px;
  height: 118px;
  max-width: 100%;
  overflow: hidden;
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-sm);
  background: var(--color-surface-sunken);
}

/* cabe INTEIRA: `contain` e não `cover` — cortar o queixo de um retrato de
   documento é perder o documento */
.sgm-ficha-foto__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Sem foto: silhueta e a palavra. O vazio aqui é informação — "este aluno não
   tem foto cadastrada" —, e o quadrado branco pareceria imagem que não
   terminou de baixar. */
.sgm-ficha-foto__moldura[data-vazia] {
  border-style: dashed;
}

.sgm-ficha-foto__sem {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sgm-1);
  font-size: var(--sgm-t-xs);
  color: var(--color-on-surface-variant);
  text-align: center;
}

.sgm-ficha-foto__sem i {
  font-size: 26px;
  line-height: 1;
  opacity: .55;
}

/* Numa coluna só, a malha inteira vira 12 colunas (ver o media query lá
   embaixo) e o `grid-row: span 3` deixaria três faixas vazias abaixo da
   foto. */
@media (max-width: 1023px) {
  .sgm-ficha-foto { grid-row: span 1; }
}

/* As marcas são um item da malha, inline na primeira linha — é onde o legado
   as põe, entre a data de entrega e o total. */
/* ⚠️ SEM `background: transparent`, E A RETIRADA É UM CONSERTO DE CASCATA.

   `.sgm-ficha-campo` declara `background: var(--color-surface-sunken)` na
   linha ~1969; esta regra declarava `transparent`. As duas têm a MESMA
   especificidade (0-1-0) e o elemento carrega as DUAS classes
   (`sgm-ficha-campo sgm-ficha-marcas`, sgm-telas.js), então vencia a de
   baixo no arquivo — por ORDEM, não por intenção. Resultado na tela: o
   grupo de marcas era o único bloco sem fundo da linha, um buraco entre dois
   vizinhos afundados.

   É a família de defeito que já custou quatro correções neste projeto:
   empate de especificidade resolvido por ordem de arquivo.

   O `transparent` nasceu quando o grupo era só chips soltos, ANTES de ele
   ganhar rótulo e virar um campo como os outros (ver a regra do rótulo, mais
   abaixo). Ganhando rótulo, ele é um campo — e campo tem fundo. */
.sgm-ficha-marcas {
  flex-direction: row;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sgm-2);
}

/* O DOCUMENTO DO PORTAL — o painel de visualização do legado.

   A ficha abre num diálogo de altura limitada (`--largo` tem max-height 88vh),
   e o visualizador tem de PREENCHER o que sobra, não crescer sem fim: um
   <iframe> sem altura declarada vira 150px por padrão do navegador, e o PDF
   sai numa fresta. Daí a altura em vh, com um piso para telas baixas. */
.sgm-ficha-arquivo {
  display: flex;
  flex-direction: column;
  gap: var(--sgm-3);
  min-height: 0;
}

.sgm-ficha-arquivo__vis {
  width: 100%;
  height: min(70vh, 760px);
  min-height: 320px;
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-sm);
  background: var(--color-surface-sunken);
}

/* a imagem cabe inteira, sem cortar e sem estourar o diálogo */
.sgm-ficha-arquivo__img {
  display: block;
  max-width: 100%;
  max-height: min(70vh, 760px);
  margin: 0 auto;
  object-fit: contain;
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-sm);
  background: var(--color-surface-sunken);
}

.sgm-ficha-arquivo__pe {
  display: flex;
  align-items: center;
  gap: var(--sgm-2);
  flex-wrap: wrap;
}

/* a descrição empurra os botões para a direita */
.sgm-ficha-arquivo__nome {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--sgm-t-sm);
  color: var(--color-on-surface-variant);
}

/* 🥇 REGRA DE OURO 8 — o botão que mostra os filtros, no canto do cabeçalho.

   ⚠️ CLASSE PRÓPRIA, E ISSO NÃO É DETALHE. Ele mora na mesma célula da lupa,
   e a primeira versão reusou `.sgm-grid-lupa__btn` — que troca o glifo pela
   imagem PNG da lupa e mata a fonte com `font-size: 0` (§6n). O botão de
   filtro teria saído desenhando uma lupa. Peça diferente, classe diferente.

   Só o funil, sem rótulo: o canto do cabeçalho tem a largura de um ícone, e
   é o único lugar da grade que não disputa espaço com dado nenhum — a lição
   do disco flutuante que cobria linha (§6m). */
.sgm-grid-filtros__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  padding: 0;
  background: var(--color-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-sm);
  color: var(--color-on-surface-muted);
  cursor: pointer;
  transition: border-color var(--sgm-fast) var(--sgm-ease),
              color var(--sgm-fast) var(--sgm-ease);
}

.sgm-grid-filtros__btn:hover {
  border-color: var(--color-primary-500);
  color: var(--color-primary-600);
}

/* aberto: o botão fica marcado, porque é ele que explica a linha a mais no
   cabeçalho */
.sgm-grid-filtros__btn[aria-expanded="true"] {
  background: var(--color-primary-50);
  border-color: var(--color-primary-500);
  color: var(--color-primary-600);
}

/* O RÓTULO do grupo de marcas ocupa a linha toda, e as caixas descem para
   baixo dele — exatamente como rótulo e valor nos outros campos. Deixá-lo
   inline com as caixas faria "Fonte de recurso" parecer mais uma delas. */
.sgm-ficha-marcas .sgm-ficha-campo__rot { flex: 0 0 100%; }

/* Marca desligada continua à vista, apagada: "não é aditamento" é
   informação, e sumir com ela faria o operador não saber que o campo existe.

   ⚠️ E "APAGADA" NÃO PODE SIGNIFICAR ILEGÍVEL — 2026-08-20, quarta volta.

   Esta regra era `opacity: .45` no CHIP INTEIRO, e opacidade não escolhe o
   que apaga: ela desenha o elemento e compõe o resultado todo contra o
   fundo. O rótulo saía #a7b1bb sobre o #f7f9fc do campo — 2,06:1, menos da
   metade dos 4,5:1 que a WCAG 1.4.3 pede para texto. A marca continuava na
   tela e deixava de ser LEGÍVEL, que para quem enxerga pouco é a mesma coisa
   que tirá-la — exatamente o que o parágrafo acima existe para impedir.

   O apagado passa a ser DE TINTA, e cada camada com a régua que lhe cabe:

   · o RÓTULO fica na tinta que o chip já tem, `--color-on-surface-variant`
     — 6,94:1 sobre o fundo afundado. É a tinta da prosa apagada do projeto,
     e ela passa em AA (é o que `confere-contraste.js` §2 fixa);
   · o ÍCONE, e SÓ ele, cai para `--color-on-surface-muted` — 4,06:1. Ícone é
     não-texto: a régua é a 1.4.11, que pede 3:1, e o muted a cumpre. Ele é o
     `fa-square` da caixa vazia, e é ali que o "apagado" fica visível;
   · a diferença entre ligada e desligada continua a mesma de antes — fundo,
     borda e tinta verdes contra o chip neutro do resto da aplicação, mais o
     glifo de caixa MARCADA contra o de caixa vazia.

   ⚠️ E O ESTADO TAMBÉM É DITO, não só pintado: `sgm-telas.js` escreve
      "Sim"/"Não" dentro do chip para o leitor de tela. Cor e forma sozinhas
      não chegam a quem não vê a tela. */
.sgm-ficha-marcas .sgm-chip:not([data-ligado]) > i {
  color: var(--color-on-surface-muted);
}
.sgm-ficha-marcas .sgm-chip[data-ligado] {
  background: var(--color-success-container);
  border-color: var(--color-success-outline);
  color: var(--color-success);
}

/* No telefone a malha de 12 vira uma coluna: 2 de 12 num aparelho de 342px
   daria 57px, e nenhum rótulo cabe. */
@media (max-width: 767px) {
  .sgm-ficha-campo,
  .sgm-ficha-campo[data-col] { grid-column: span 12; }
}

.sgm-ficha-aba[hidden] { display: none; }

/* --------------------------------------------------------------------------
   O AVISO — o que NÓS explicamos, e não o que o operador digitou

   ⚠️ MESMA POSIÇÃO DO MEMO, OUTRA LEITURA. `.sgm-ficha-texto` é a caixa
   afundada com rótulo cinza dos memos de DADO (Observações, Objeto,
   Cláusulas). Os avisos em prosa — "Como ler os valores", "Sobre esta aba",
   o exercício único da ficha do contrato — entravam pela MESMA peça e saíam
   indistinguíveis do dado, na mesma tela em que o dado aparece.

   É o argumento que criou o `AbaVazia` nesta etapa, aplicado ao que ficou de
   fora. Filete à esquerda em --color-info, ícone, tipografia menor: lê-se
   como nota de rodapé, que é o que é.

   ⚠️ E ELE É MAIS BAIXO QUE O MEMO de propósito — sem a caixa cheia, com
   --sgm-t-sm e padding menor. Num notebook de 768px o corpo do diálogo tem
   ~676px, e cada aviso que se comporta como memo é altura que a aba com
   grade não recebe. "Popup que rola é popup que não sintetizou".
   -------------------------------------------------------------------------- */
.sgm-ficha-aviso {
  display: flex;
  align-items: flex-start;
  gap: var(--sgm-2);
  margin-top: var(--sgm-3);
  padding: var(--sgm-2) var(--sgm-3);
  border-left: 3px solid var(--color-info);
  border-radius: 0 var(--sgm-r-sm) var(--sgm-r-sm) 0;
  background: var(--color-info-container);
  font-size: var(--sgm-t-sm);
  line-height: 1.35;
  color: var(--color-on-surface);
}

.sgm-ficha-aviso > i {
  flex: 0 0 auto;
  margin-top: 1px;
  color: var(--color-info);
}

/* min-width 0 porque item flex não encolhe por padrão, e sem ele um aviso
   longo empurra a largura do bloco em vez de quebrar dentro dele */
.sgm-ficha-aviso__corpo { min-width: 0; }

.sgm-ficha-aviso__rot {
  display: block;
  font-weight: 700;
  color: var(--color-info);
}

.sgm-ficha-aviso p { margin: 0; overflow-wrap: anywhere; }

.sgm-ficha-texto { margin-top: var(--sgm-3); }
.sgm-ficha-texto p {
  margin-top: 2px;
  padding: var(--sgm-3);
  border-radius: var(--sgm-r-sm);
  background: var(--color-surface-sunken);
  white-space: pre-wrap;          /* observação vem com quebras do SCPI */
  overflow-wrap: anywhere;
}

/* 💎 DENTRO DA FICHA A GRADE NÃO ROLA SOZINHA — §3.6, corrigido em 2026-08-16.

   O comentário anterior já dizia a intenção certa — "o corpo já rola" — e a
   regra ao lado dele fazia o contrário: `max-height: 42vh` dá à grade uma
   rolagem PRÓPRIA, dentro de um corpo que tem a dele em 88vh. Duas rolagens
   aninhadas, que é o pior caso: o operador rola o diálogo, chega na grade, e a
   rolagem passa a ser de outra coisa sem aviso.

   A conta que fecha o caso (§3.6, e está no scripts\testa-ficha.js): com a
   grade fixa em 42vh, tudo o que está acima dela precisa caber em 46vh — em
   768px de altura, 353px para cabeçalho, abas, cartões, avisos e chassi. OITO
   fichas do projeto passavam disso. Encolher as oito seria tratar o sintoma
   oito vezes; o defeito era esta linha.

   ⚠️ SEM TETO, E NÃO COM UM TETO MAIOR. A grade cresce e quem rola é o corpo
   do diálogo — uma barra só, a do §3.6. Grade grande dentro de ficha continua
   sendo assunto de PAGINAÇÃO (as três do Patrimônio já paginam), e não de
   caixa com rolagem dentro de caixa com rolagem. */
.sgm-ficha .sgm-grid-scroll { max-height: none; }

/* --------------------------------------------------------------------------
   A lupa da primeira coluna — o ColumnActionClick do legado
   -------------------------------------------------------------------------- */

.sgm-grid-lupa { width: 44px; text-align: center; padding: 0 !important; }

.sgm-grid-lupa__btn {
  /* flex, e nao grid: no telefone entram DOIS filhos (o icone e o rotulo
     'Ver ficha' do ::after). Em grid eles empilham em duas linhas, e o
     margin-left do rotulo nao faz nada. Em flex ficam lado a lado.
     Para o caso de um filho so - o desktop - o resultado e identico. */
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  /* ⚠️ NAO TIRAR. A lupa do CAMPO (uJsTelas.pas:396) fica dentro de
     .sgm-ficha-campo__linha, que e display:flex - la o botao e ITEM FLEX e,
     sem isto, encolhe quando o valor ao lado e longo. O icone tem tamanho
     fixo, entao ele transborda da caixa espremida. Enquanto o botao era
     transparente ninguem via; com borda e fundo, vira uma caixa quebrada.
     Na grid o botao nao e item flex e a declaracao fica inerte. */
  flex: 0 0 auto;
  margin: 0 auto;
  /* A borda e o fundo sao o destaque pedido: sem eles a lupa era um glifo
     solto, e nada dizia que aquilo se clica. */
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-sm);
  cursor: pointer;
  color: var(--color-primary-500);
  background: var(--color-surface);
}

.sgm-grid-lupa__btn:hover {
  background: var(--color-primary-50);
  border-color: var(--color-primary-500);
}
.sgm-grid-lupa__btn:focus-visible {
  outline: 2px solid var(--color-primary-500);
  outline-offset: 1px;
}

/* --------------------------------------------------------------------------
   O DESENHO DA LUPA — a mesma imagem do legado

   O legado desenha a lupa com <img src="imgs/button/search.png"> (16x16), e
   e essa a lupa que o usuario reconhece. Aqui ela entra por CSS, no lugar do
   glifo do FontAwesome que o <i class="fas fa-search"> carrega - o <i> e
   montado em uJsGrid.pas (grid) e uJsTelas.pas (campo), que vivem DENTRO do
   executavel. Trocando por CSS, o icone muda sem BUILD e num lugar so, valendo
   para as duas chamadas.

   ⚠️ NAO DISPUTAR O `content` COM O FONTAWESOME. A primeira versao punha a
   imagem no ::before e zerava o `content` para apagar o glifo. Perdeu: o
   Rodrigo viu **as duas coisas na tela**, a lupa em PNG com o glifo por cima.
   Disputa de cascata por `content` depende de especificidade E de ordem de
   folha, e basta uma das duas virar para o glifo voltar - sem erro nenhum.

   O jeito que nao disputa: a imagem vai no PROPRIO <i>, e o glifo morre por
   `font-size: 0`. Seja qual for o `content` que o FontAwesome injete no
   ::before, em corpo zero ele desenha nada. Nao ha o que ganhar ou perder.
   Conferido por scripts\confere-cascata-lupa.js.

   As tres resolucoes que o Rodrigo forneceu se usam assim:
     16 -> tamanho logico do desktop         32 -> o mesmo, em tela 2x
     24 -> tamanho logico do telefone, onde o alvo de toque e maior
   -------------------------------------------------------------------------- */

.sgm-grid-lupa__btn .fa-search {
  display: block;
  width: 16px;
  height: 16px;
  /* ⚠️ E ISTO que apaga o glifo. Nao trocar por content:'' - ver acima. */
  font-size: 0;
  line-height: 0;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 16px 16px;
  /* as tres linhas sao a MESMA declaracao, da mais velha para a mais nova:
     quem nao entender image-set fica na primeira e ainda ve a lupa */
  background-image: url('../imgs/icons8-lupa-16.png');
  background-image: -webkit-image-set(
    url('../imgs/icons8-lupa-16.png') 1x,
    url('../imgs/icons8-lupa-32.png') 2x);
  background-image: image-set(
    url('../imgs/icons8-lupa-16.png') 1x,
    url('../imgs/icons8-lupa-32.png') 2x);
}

/* No telefone a linha vira cartão e o <thead> some (§6i): a lupa passa a ser
   a primeira coisa do cartão, com rótulo, senão fica um ícone solto. */
@media (max-width: 767px) {
  .sgm-grid-lupa { width: auto; text-align: left; }
  .sgm-grid-lupa__btn {
    width: auto;
    height: 34px;
    margin: 0;
    padding: 0 var(--sgm-2);
    gap: var(--sgm-2);    /* no lugar do margin-left do rotulo */
  }
  .sgm-grid-lupa__btn::after {
    content: 'Ver ficha';
    font-size: var(--sgm-t-sm);
    font-weight: 600;
  }
  /* dedo, e nao ponteiro: 24 logicos, no arquivo de 24 */
  .sgm-grid-lupa__btn .fa-search {
    width: 24px;
    height: 24px;
    background-size: 24px 24px;
    background-image: url('../imgs/icons8-lupa-24.png');
  }
}

/* --------------------------------------------------------------------------
   Formatos de exportação — a lista do diálogo

   🥇 REGRA DE OURO: todo gráfico se exporta em PNG, JPG, SVG, PDF e CSV.
   Cada linha traz o formato e PARA QUE ELE SERVE: "SVG" sozinho não diz nada
   a quem só precisa colar a figura num ofício.
   -------------------------------------------------------------------------- */

.sgm-formatos {
  display: flex;
  flex-direction: column;
  gap: var(--sgm-2);
}

.sgm-formato {
  display: flex;
  align-items: center;
  gap: var(--sgm-3);
  width: 100%;
  padding: var(--sgm-3);
  text-align: left;
  font: inherit;
  color: var(--color-on-surface);
  background: var(--color-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r);
  cursor: pointer;
}

.sgm-formato:hover:not(:disabled) {
  border-color: var(--color-primary-500);
  background: var(--color-surface-sunken);
}

.sgm-formato:focus-visible {
  outline: 2px solid var(--color-primary-500);
  outline-offset: 2px;
}

.sgm-formato:disabled { opacity: .5; cursor: not-allowed; }

.sgm-formato > i {
  flex: none;
  width: 28px;
  font-size: 1.1rem;
  text-align: center;
  color: var(--color-primary-500);
}

.sgm-formato__texto { display: flex; flex-direction: column; min-width: 0; }
.sgm-formato__rotulo { font-weight: 650; }
.sgm-formato__dica {
  font-size: var(--sgm-t-sm);
  color: var(--color-on-surface-variant);
}

/* pelo mesmo motivo da regra acima: um filho de painel oculto não pode
   reacender o display do ancestral por conta própria */
.sgm-painel--cheio:not([hidden]) > .sgm-det-corpo {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.sgm-det-corpo > .sgm-grid-wrap {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.sgm-det-corpo .sgm-grid-scroll {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
}

/* o estado de carga e o de erro também preenchem, para a barra de baixo não
   pular de lugar quando o dado chega */
.sgm-det-corpo > .sgm-estado,
.sgm-det-corpo > .sgm-skeleton-grafico { flex: 1 1 auto; min-height: 0; }

/* --------------------------------------------------------------------------
   10. Ajuda do quadro — o realce do sistema-produto
   --------------------------------------------------------------------------
   No legado o nome do sistema vem em <font color=#FF0000>, que na nossa
   caixa de diálogo leria como erro. A ênfase fica, no acento do sistema de
   design — ver modules\uHelpSCPI.pas.
   -------------------------------------------------------------------------- */

.sgm-ajuda-sistema {
  color: var(--color-primary-500);
  font-weight: 700;
}

/* --------------------------------------------------------------------------
   11. Impressão — o PDF do detalhamento
   --------------------------------------------------------------------------
   O botão PDF monta uma folha (`#sgm-impressao`) e chama a impressão do
   navegador; "Salvar como PDF" gera o arquivo. Não entra biblioteca: o
   navegador já repete o cabeçalho da tabela em cada página e quebra onde
   cabe, que é justamente a parte difícil. Ver SGM.exportarPDF.

   A folha fica fora da tela enquanto não se imprime — e não `display: none`,
   porque o navegador precisa medi-la para paginar.
   -------------------------------------------------------------------------- */

.sgm-impressao {
  position: absolute;
  left: -10000px;
  top: 0;
  width: 1000px;
}

@media print {
  /* some com a moldura: topo, menu, abas, botões. Sobra a folha. */
  .sgm-imprimindo body > *:not(#sgm-impressao) { display: none !important; }

  .sgm-imprimindo,
  .sgm-imprimindo body {
    height: auto !important;
    overflow: visible !important;
    background: #fff !important;
  }

  .sgm-impressao {
    position: static !important;
    left: auto !important;
    width: auto !important;
    color: #000;
    font-size: 9pt;
  }

  .sgm-impressao__cab { margin-bottom: 10pt; }
  .sgm-impressao__cab h1 { font-size: 14pt; margin: 0 0 2pt; }
  .sgm-impressao__ent    { font-size: 10pt; font-weight: 600; margin: 0 0 2pt; }
  .sgm-impressao__sub    { font-size: 9pt; color: #444; margin: 0 0 2pt; }
  .sgm-impressao__filtro { font-size: 8pt; color: #444; margin: 0; }

  .sgm-impressao table { width: 100%; border-collapse: collapse; }

  /* o cabeçalho se repete em cada página — é o que uma biblioteca de PDF
     custaria caro para fazer, e o navegador faz de graça */
  .sgm-impressao thead { display: table-header-group; }
  .sgm-impressao tfoot { display: table-footer-group; }
  .sgm-impressao tr    { page-break-inside: avoid; break-inside: avoid; }

  .sgm-impressao th, .sgm-impressao td {
    padding: 3pt 4pt;
    border-bottom: 0.5pt solid #999;
    text-align: left;
    vertical-align: top;
  }
  .sgm-impressao th { border-bottom-width: 1pt; font-size: 8pt; text-transform: uppercase; }
  .sgm-impressao .num { text-align: right; white-space: nowrap; }
  .sgm-impressao tfoot td { border-top: 1pt solid #000; font-weight: 700; }

  /* ⚠️ A FOLHA A4 EM RETRATO TEM MENOS DE 767px DE LARGURA, e na impressão o
     `@media (max-width: 767px)` da grade (o cartão do telefone, seção 8)
     também vale: tabela, linha e célula viravam bloco, e cada valor saía numa
     linha própria, alinhado à direita, longe do título da coluna (relatado em
     2026-10-05, em todo PDF de grade). Aqui a tabela volta a ser tabela. Os
     seletores têm `.sgm-impressao .sgm-grid tbody td` (0,2,2), acima do
     `.sgm-grid tbody td` (0,1,2) do cartão - media query não muda
     especificidade, e o celular continua com o cartão. */
  .sgm-impressao .sgm-grid { display: table; width: 100%; }
  .sgm-impressao .sgm-grid thead { display: table-header-group; }
  .sgm-impressao .sgm-grid tbody { display: table-row-group; }
  .sgm-impressao .sgm-grid tfoot { display: table-footer-group; }
  .sgm-impressao .sgm-grid thead tr,
  .sgm-impressao .sgm-grid tbody tr,
  .sgm-impressao .sgm-grid tfoot tr { display: table-row; width: auto; padding: 0; border: 0; }
  .sgm-impressao .sgm-grid tbody td,
  .sgm-impressao .sgm-grid tfoot td {
    display: table-cell;
    width: auto;
    padding: 3pt 4pt;
    border-bottom: 0.5pt solid #999;
    text-align: left;
  }
  .sgm-impressao .sgm-grid tbody td.num,
  .sgm-impressao .sgm-grid tfoot td.num { text-align: right; }
  .sgm-impressao .sgm-grid tfoot td { border-top: 1pt solid #000; }
  .sgm-impressao .sgm-grid tbody td::before { content: none; }

  @page { margin: 12mm 10mm; }
}

/* --------------------------------------------------------------------------
   Configurações do dashboard — a linha da lista

   Caixa à esquerda, setas à direita: o alvo de clique é grande e o Tab passa
   pelos três controles na ordem em que se lê a linha.
   -------------------------------------------------------------------------- */

.sgm-config-item {
  display: flex;
  align-items: center;
  gap: var(--sgm-2);
  padding: var(--sgm-1) 0;
  border-bottom: 1px solid var(--color-outline);
  min-width: 0;
}
.sgm-config-item:last-child { border-bottom: 0; }
.sgm-config-item .sgm-btn[disabled] { opacity: .35; cursor: default; }

/* --------------------------------------------------------------------------
   O VALOR QUE ABRE A SUA LISTA — .sgm-cel-link

   Cobrado pelo Rodrigo em 2026-08-12, com os prints da Disponibilidade
   Comprometida: "cada valor é um link que mostra o detalhamento desse item".

   No legado é um `cursor:pointer;text-decoration:underline` pintado pelo
   DrawColumnCell — sublinhado azul de link, que numa coluna de dinheiro
   compete com o próprio número. Aqui o número continua sendo o assunto: mesma
   fonte, mesmo alinhamento, e o sinal de que se clica é o sublinhado
   PONTILHADO e a cor do primário no hover.

   ⚠️ É um <button> herdando `font: inherit` e `text-align: inherit` — sem
   isso ele volta à fonte do sistema e a coluna de moeda perde o alinhamento à
   direita, que é o que faz uma coluna de números ser lida de relance.
   -------------------------------------------------------------------------- */
.sgm-cel-link {
  font: inherit;
  color: inherit;
  text-align: inherit;
  background: none;
  border: 0;
  padding: 0;
  width: 100%;
  cursor: pointer;
  text-decoration: underline dotted var(--color-outline);
  text-underline-offset: 3px;
}

.sgm-cel-link:hover {
  color: var(--color-primary-600);
  text-decoration-color: var(--color-primary-500);
}

.sgm-cel-link:focus-visible {
  outline: 2px solid var(--color-primary-500);
  outline-offset: 1px;
  border-radius: var(--sgm-r-sm);
}

/* ==========================================================================
   Filtro de LISTA e AGRUPAMENTO da grid
   --------------------------------------------------------------------------
   Pedido do Rodrigo em 2026-08-13, no detalhamento da Conta Corrente: o filtro
   de uma coluna que é um seletor de marcar/desmarcar, e as linhas reunidas por
   aquela coluna com os subtotais no cabeçalho do grupo.

   ⚠️ TUDO AQUI É CLASSE NOVA — `sgm-grid-lista*` e `sgm-grid-grupo*`. Nenhuma
   regra existente é redefinida, então não há empate de especificidade a
   resolver (a lição das quatro vezes em que houve).
   ========================================================================== */

/* O BOTÃO que abre o popup. Parece com as caixas de filtro das outras colunas
   — senão a linha de filtros fica com um elemento estranho no meio —, mas é um
   <button>: quem escolhe é o diálogo, não ele. */
.sgm-grid-lista__botao {
  cursor: pointer;
  width: 100%;
  text-align: left;
  padding: 2px 6px;
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-sm);
  background: var(--color-surface);
  color: var(--color-on-surface-variant);
  font: inherit;
  white-space: nowrap;
}

.sgm-grid-lista__botao::after {
  content: " ▾";
  opacity: 0.6;
}

.sgm-grid-lista__botao:hover { border-color: var(--color-primary-500); }

.sgm-grid-lista__botao:focus-visible {
  outline: 2px solid var(--color-primary-500);
  outline-offset: 1px;
}

/* Filtrando: o mesmo realce das caixas de texto, para o olho achar de onde
   veio o corte sem ler coluna por coluna. */
/* ⚠️ `--color-primary-600`, e não 700: a paleta vai até o 600 (o 700 não
   existe, e uma variável inexistente sem reserva simplesmente perde a
   declaração — o realce sumiria sem erro nenhum no console). */
.sgm-grid-lista__botao[data-ativo="true"] {
  border-color: var(--color-primary-500);
  color: var(--color-primary-600);
  font-weight: 600;
}

/* Os atalhos dentro do popup. */
.sgm-grid-lista__atalhos {
  display: flex;
  gap: 6px;
  padding-bottom: 8px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--color-outline);
}

/* A linha de marcar do popup — o `sgm-lista-item` do resto do sistema, que é
   `display:block`, com a caixa ao lado do texto. Modificador próprio para NÃO
   redefinir a regra que as outras listas usam. */
.sgm-lista-item--marcar {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

/* ---- a linha de cabeçalho do grupo ----------------------------------------
   ⚠️ ELA TEM DE SE DESTACAR DAS LINHAS DE DADOS, e não só ser "mais uma linha
   cinza": é o que separa um grupo do outro quando a lista é longa. Pedido do
   Rodrigo em 2026-08-13, olhando a primeira versão. */

.sgm-grid-grupo > td {
  background: var(--color-primary-50, #e8f2f0);
  border-top: 2px solid var(--color-primary-500);
  border-bottom: 1px solid var(--color-outline);
  color: var(--color-on-surface);
  padding-top: var(--sgm-2);
  padding-bottom: var(--sgm-2);
}

.sgm-grid-grupo__rotulo { text-align: left; }

/* O DESCRITIVO EM NEGRITO — é o nome do grupo que se procura ao rolar. */
.sgm-grid-grupo__nome {
  font-weight: 700;
  letter-spacing: 0.01em;
}

/* A contagem acompanha, e não compete: peso normal e mais clara. */
.sgm-grid-grupo__conta {
  margin-left: 8px;
  font-weight: 400;
  opacity: 0.7;
}

/* Os subtotais em negrito também: são o motivo de a faixa existir. */
.sgm-grid-grupo > td.num { font-weight: 700; }

/* ==========================================================================
   CONTRIBUINTE — o selo da grade, o cabeçalho da pessoa e os oito painéis
   --------------------------------------------------------------------------
   Tarefa 0.2 do 00-PLANO.md (§8 ETAPA 0). Quatro blocos, e só eles:

       .sgm-cel-selo     a célula do selo de sistema na grade (§2.6)
       .sgm-cnt-cabeca   o cabeçalho da pessoa no resumo      (§3.2)
       .sgm-cnt-painel   cada um dos oito painéis             (§3.3, §3.4)
       .sgm-cnt-linha    a linha rótulo/valor dentro do painel

   ⚠️ TODOS OS NOMES SÃO NOVOS. Antes de escrever, procurei `sgm-cel-selo` e
   `sgm-cnt` em TODO o Web2 (.css, .js, .pas): zero ocorrências. Então entre
   estas regras e as que já existem só há uma disputa real, a do selo com as
   regras da grid — e ela está resolvida por aritmética logo abaixo, seletor
   por seletor. É a lição das quatro vezes em que um empate custou defeito
   (a última está registrada acima, no menu de exportação da §8).

   💎 E HAVIA DISPUTA DENTRO DO PRÓPRIO BLOCO — 2026-08-20, a quinta vez.
   `.sgm-cnt-painel:hover` (0,2,0) empatava com `[data-estado="fora"]` e com
   `[data-marcado="true"]`, os dois também (0,2,0), e os três disputam
   `box-shadow`. Vencia quem viesse depois. Um empate por ordem NÃO É uma
   decisão: é uma decisão que a próxima reordenação desfaz, calada — painel
   fora do ar voltando a levantar no hover (prometendo clique num botão
   `:disabled`), e painel escolhido perdendo o anel ao passar o mouse.
   Os dois seletores subiram para (0,3,0) repetindo a classe. A promessa da
   linha acima — "resolvida por aritmética, seletor por seletor" — agora vale
   para o bloco inteiro, e não só para o selo.

   O CONTRATO DE MARKUP — é o que a tarefa 1.2 escreve em `sgm-telas.js`:

     <div class="sgm-cnt-cabeca">
       <span class="sgm-cnt-fita"><i class="fas fa-address-card"></i></span>
       <div class="sgm-cnt-linha sgm-cnt-linha--junta">
         <span class="sgm-cnt-linha__rot">CPF/CNPJ</span>
         <span class="sgm-cnt-linha__val">111.444.777-35</span>
       </div>
       ... (Endereço, Idade, Telefone)
     </div>

     <div class="sgm-cnt-painel" data-estado="ok">
       <span class="sgm-cnt-fita"><i class="fas fa-chart-bar"></i></span>
       <button type="button" class="sgm-cnt-painel__titulo">Dados contábeis</button>
       <div class="sgm-cnt-linha">
         <span class="sgm-cnt-linha__rot">Empenhos</span>
         <span class="sgm-cnt-linha__val">12</span>
       </div>
       ...
     </div>

   `data-estado` tem QUATRO valores, e eles vêm de §3.4 e §7.1:
     "ok"         — há contagem; o painel abre a grid do sistema
     "vazio"      — soma zero; o clique só dá o aviso do legado
     "naoapurado" — o sistema respondeu, mas nenhum cadastro achou a pessoa:
                    os contadores não foram apurados e saem em travessão
                    (2026-08-20, terceira volta — ver a regra lá embaixo)
     "fora"       — o sistema não respondeu (§7.1); não é clicável
   `data-marcado="true"` marca o painel cujo detalhamento está na área abaixo.
   `data-zero="true"` na linha apaga um contador zerado — zero não é número
   que se leia de relance, é ausência.

   O QUE VEIO DO LEGADO E O QUE NÃO VEIO
   O painel do legado (`RIA\Web\Win32\Debug\css\card-cnt.css`, `.painelcnt` +
   `.faixaiconcnt`) tem uma FAIXA DE ÍCONE saindo pelo canto superior esquerdo,
   com a dobra desenhada no `::before` do `<span>`. A IDEIA é boa e fica: é ela
   que diz de que sistema é o painel antes de se ler o título. O que não fica é
   o hex — `rgb(0,96,96)` é a cor do legado, não a nossa; aqui a fita é
   `--color-primary-500`, e a identidade de cada um dos oito é o ÍCONE, que o
   plano já define um a um (§3.3). Não gasto a paleta de 8 do padrão, que é de
   SÉRIE DE GRÁFICO, para pintar moldura — e ainda evito o branco sobre
   `--chart-4` (#eda100), que não tem contraste para um glifo de 14px.

   TEMA — o projeto NÃO tem tema escuro hoje. Li `sgm-tokens.css` inteiro e
   varri as sete folhas: não há `prefers-color-scheme`, não há `[data-theme]`,
   não há segundo conjunto de valores. Então "respeitar os dois temas" aqui só
   pode significar uma coisa: NENHUMA COR SOLTA. Toda cor abaixo é token, e a
   única exceção declarada é o `brightness()` da dobra, que é derivado — ele
   escurece o que quer que a fita seja, inclusive num tema que ainda não
   existe. No dia em que `sgm-tokens.css` ganhar o bloco escuro, esta seção
   acompanha sem uma linha de alteração.

   ⚠️ ESTA AFIRMAÇÃO JÁ FOI FALSA. Até 2026-08-19 o anel do painel marcado
   trazia `rgba(15, 118, 110, .16)` escrito à mão, enquanto `--sgm-ring` existe
   em sgm-tokens.css com o MESMO anel e alfa .18 — dois anéis divergindo em
   0,02 por acidente, não por decisão, num bloco cujo cabeçalho garantia que
   isso não acontecia. Está corrigido, e o registro fica: comentário que
   inventaria errado é a próxima pessoa confiando no inventário.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. .sgm-cel-selo — o ✓ das oito colunas de sistema (§2.6)

   O valor é '✓' (U+2713) ou string vazia; quem manda é o servidor. A célula
   não recebe `innerHTML` (`html\uJsCore.pas:286`), então não há `<img>` nem
   `<i>` aqui — o glifo é o selo, e é ele que sai no CSV e no PDF, que levam o
   que está à vista (`html\uJsGrid.pas:1675-1677`).

   ⚠️ A CLASSE CAI NO `<th>` E NO `<td>`, e por atribuição.
   `sgm-grid.js:916` faz `th.className = c.classe` e `:1455` faz
   `td.className = c.classe` — ATRIBUIÇÃO, não `add`. Duas consequências que
   mudam o que se escreve aqui:
     a) a coluna do selo NUNCA acumula `num` (nem precisa: `tipo` é texto);
     b) o CABEÇALHO também é `.sgm-cel-selo`, e se eu só tratasse o `<td>` a
        sigla ficaria à esquerda sobre uma coluna centrada.

   A ARITMÉTICA, na notação do `scripts\confere-cascata-lupa.js`
   (ids, classes+pseudoclasses+atributos, elementos+pseudoelementos):

     .sgm-grid thead th              (0,1,2)  text-align: left   — :1356
     .sgm-grid thead th.sgm-cel-selo (0,2,2)  VENCE por b (2 > 1)

     .sgm-grid tbody td              (0,1,2)  color, padding     — :1582
     .sgm-grid tbody td.sgm-cel-selo (0,2,2)  VENCE por b (2 > 1)

     .sgm-grid .num                  (0,2,0)  text-align: right  — :1592
     .sgm-grid tbody td.sgm-cel-selo (0,2,2)  VENCE por c — e, de todo modo,
       as duas classes não coexistem, pela atribuição acima

   Escolhi de propósito o seletor de TRÊS níveis (`.sgm-grid tbody td.x`) e não
   o de dois (`.sgm-grid td.x`, que seria (0,2,1)). Os dois venceriam hoje; o
   de três vence com folga em `b` E em `c`, e continua vencendo se alguém
   acrescentar um elemento ao seletor da regra base.

   ⚠️ O `@media (max-width: 767px)` da grid (:1701) redeclara
   `.sgm-grid tbody td` — e media query NÃO muda especificidade, só ordem.
   (0,2,2) continua ganhando de (0,1,2), então o `text-align: center` vale lá
   também. O `display: flex` do telefone eu NÃO desfaço: no cartão do celular a
   linha é rótulo à esquerda e valor à direita, e o selo é o valor. Deixar como
   está é o certo, e é também o que a REGRA DE OURO 5 pede — não mexer em
   `display` de fora.

   ⚠️ O FILTRO DE LISTA DA COLUNA NÃO SE DESALINHA. `filtro: 'lista'` põe um
   `.sgm-grid-lista__botao` dentro do mesmo `<th>`, e ele traz o próprio
   `text-align: left`. Declaração no ELEMENTO ganha de valor HERDADO, qualquer
   que seja a especificidade de quem herdou — o botão com o ▾ fica alinhado à
   esquerda, como nas outras colunas. Não há nada a resolver aqui, e é por isso
   que não escrevo regra para ele.
   -------------------------------------------------------------------------- */

.sgm-grid thead th.sgm-cel-selo {
  text-align: center;
  /* oito colunas de três letras não podem comer a largura do Nome: o recuo
     lateral cai de --sgm-3 para --sgm-2 */
  padding-left: var(--sgm-2);
  padding-right: var(--sgm-2);
}

/* O botão de ordenar é `display: inline-flex` (:1375) — nível de linha. Logo o
   `text-align: center` do `<th>` já o centra, e não é preciso um
   `justify-content` como o de `.sgm-grid th.num .sgm-grid-ord` (:1404), que
   existe porque lá o alinhamento à direita foi feito em duas frentes. Uma
   regra a menos é uma disputa a menos. */

/* 🥇 A COLUNA DO SISTEMA QUE NÃO RESPONDEU — a outra metade da divergência T-E.

   No legado, "fora do ar" e "não tem cadastro" produzem exatamente a mesma
   tela: célula em branco nas duas. O resumo já resolvia isso nos painéis
   (`data-estado="fora"`, borda tracejada e frase); a GRADE continuava com a
   confusão, porque a coluna do sistema fora do ar mostra o mesmo travessão de
   `:empty::after` que significa "esta pessoa não tem cadastro aqui". A faixa
   de aviso era o único portador da diferença — e ela fica acima da grade, fora
   de vista assim que se rola.

   Quem põe o atributo é a tela (`cntTraduzirColunas`, em sgm-telas.js), a
   partir de `sistemas[].no_ar`, que já vinha na resposta e não era lido.

   O sinal é o MESMO do painel fora do ar: tinta apagada e traço tracejado —
   para o operador não ter de aprender um segundo vocabulário. E o motivo em
   texto continua no `title` do `<th>` e na faixa.

   Especificidade: (0,3,2) contra os (0,2,2) da regra acima. Vence por b, sem
   depender de ordem.

   ⚠️ E A TINTA É `--color-on-surface-variant`, E NÃO O MUTED — 2026-08-20,
   segunda volta, pela mesma régua do título do painel fora do ar. O muted
   (#6b7c8f) sobre a superfície dá 4,28:1 e reprova no AA; o variant (#46586b)
   dá 7,32:1. Esta é a SIGLA do sistema que não respondeu, num `<th>` de 12px:
   é texto que o operador precisa ler, e apagado não quer dizer ilegível. Quem
   diz "desabilitado" aqui é o traço tracejado, o `title` e a faixa de aviso.

   Esta regra escapava da varredura de `scripts\confere-contraste.js` porque
   ela não declara `font-size` — o script só media quem declarasse cor E
   tamanho no mesmo bloco, e foi consertado na mesma volta. */
.sgm-grid thead th.sgm-cel-selo[data-fora] {
  color: var(--color-on-surface-variant);
  border-bottom: 2px dashed var(--color-outline-strong);
}

.sgm-grid tbody td.sgm-cel-selo {
  text-align: center;
  padding-left: var(--sgm-2);
  padding-right: var(--sgm-2);
  color: var(--color-success);
  font-weight: 600;
  /* o ✓ é um símbolo, não texto de leitura: um corpo acima do da célula para
     ele ser visto de relance ao varrer oito colunas */
  font-size: var(--sgm-t-md);
  line-height: 1;
  white-space: nowrap;
}

/* ⚠️ O SELO DESLIGADO CONTINUA À VISTA, APAGADO — e isto não é enfeite.

   O servidor manda string vazia quando o sistema não tem a pessoa (§2.6), e
   `td.textContent = ''` deixa o `<td>` SEM FILHOS: `:empty` casa. Uma célula
   em branco numa linha de oito colunas é ambígua — não se sabe se é "não tem"
   ou "a coluna não veio". O travessão diz "não tem", que é o que o dado diz.

   Especificidade: `.sgm-grid tbody td.sgm-cel-selo:empty::after` é (0,3,3) —
   `:empty` conta como classe, `::after` conta como elemento. Nenhuma regra do
   projeto disputa `content` neste ponto; a única disputa de `content` que já
   houve foi a do glifo da lupa, e ela é de outro seletor.

   ⚠️ E O TRAVESSÃO NÃO VAI PARA O CSV. `::after` é conteúdo gerado, e a
   exportação lê `textContent` (`html\uJsGrid.pas:1675-1677`): a planilha sai
   com a célula vazia, exatamente como o servidor mandou. É a divergência, e
   ela é a desejável — na tela o operador precisa da marca de ausência, na
   planilha ele precisa do campo vazio para filtrar. */
.sgm-grid tbody td.sgm-cel-selo:empty::after {
  content: "—";
  /* mesmo argumento do travessão da linha: ele diz "esta pessoa não tem
     cadastro neste sistema", e 4,28:1 do muted reprova no AA */
  color: var(--color-on-surface-variant);
  font-weight: 400;
}

/* --------------------------------------------------------------------------
   2. A FITA DE ÍCONE — .sgm-cnt-fita

   É a `.faixaiconcnt` do legado relida no vocabulário do Web2: a lingueta que
   sai pelo canto superior esquerdo do painel, com a dobra por baixo. Serve ao
   cabeçalho e aos oito painéis — um só desenho, um só nome.

   ⚠️ NENHUM DOS DOIS BLOCOS PODE TER `overflow: hidden`. `.sgm-card` (:120)
   tem, e é por isso que a fita NÃO se pendura num `.sgm-card`: ela seria
   cortada rente à borda e viraria um quadradinho. É a diferença entre portar a
   ideia e portar o hex.

   O `--cnt-fita-saida` é o quanto ela avança para fora da borda. Fica em
   variável porque no telefone ele vai a zero: com a largura toda ocupada, 8px
   para fora do cartão é 8px em cima da margem da tela.
   -------------------------------------------------------------------------- */

/* 💎 E A GRADE PRECISA ABRIR O ESPAÇO POR ONDE ELA AVANÇA — print do Rodrigo em
   2026-08-20: no detalhamento do contribuinte, os painéis da PRIMEIRA COLUNA
   saíam com o ícone cortado rente à borda esquerda.

   O bloco acima cuidou do que corta DE PERTO — nem o painel nem o cabeçalho
   podem ter `overflow: hidden`. Faltava o que corta DE LONGE: a fita avança
   `--cnt-fita-saida` para fora da coluna, e na primeira coluna esses pixels
   caem fora da grade, dentro do painel que ROLA. E painel que rola num eixo
   não deixa o outro transbordar: `overflow-y: auto` faz o navegador tratar o
   `overflow-x` como `auto` também — a regra do CSS, não uma peculiaridade
   deste projeto. O que passa da borda ou é cortado ou vira barra horizontal.

   ⚠️ O RECUO NÃO PODE DESLOCAR OS CARTÕES. A grade dos painéis fica lado a
   lado com o cabeçalho da pessoa e com a grade do detalhe, e um recuo simples
   empurraria só ela — desalinhando as três por 8px.

   Por isso o par: a caixa CRESCE para a esquerda (`margin-left` negativo) e
   devolve o mesmo tanto em `padding-left`. O conteúdo fica exatamente onde
   estava, e a fita passa a ter chão dentro da própria grade.

   ⚠️ Só à ESQUERDA, e de propósito: a fita não avança para a direita, e um
   `margin-right` negativo comeria a margem do painel sem nada para pôr ali. */
/* A saída da fita, num escopo que a FITA e a GRADE enxergam. O telefone a zera
   logo abaixo, no mesmo `:root`, e as duas acompanham juntas. */
:root { --cnt-fita-saida: 8px; }

.sgm-grade--fita {
  margin-left: calc(var(--cnt-fita-saida) * -1);
  padding-left: var(--cnt-fita-saida);
} .sgm-shell-fixo .sgm-painel:has(.sgm-cnt-fita) { padding-left: var(--cnt-fita-saida); } /* 29/09: a ABA é quem rola (`overflow-y: auto`, .sgm-shell-fixo .sgm-painel) e começava rente ao conteúdo - a fita e a dobra dela, 8px para fora do cartão, eram cortadas na borda da aba (print do Rodrigo, primeira coluna e cabeçalho da pessoa). A folga vai na própria aba, só na que tem fita: cabeçalho, painéis e detalhe andam juntos e continuam alinhados entre si. Numa linha só para não deslocar os ponteiros desta folha. */

/* ⚠️ A SAÍDA MORA NO `:root`, E NÃO AQUI DENTRO — 2026-08-20.

   Ela era uma variável local da própria fita, e isso bastava enquanto só a
   fita a lia. Passou a não bastar no dia em que a grade precisou abrir o
   espaço por onde a fita avança: variável declarada no filho não é visível no
   pai, e o `var(--cnt-fita-saida, 8px)` da grade teria de repetir o valor —
   duas verdades, com a segunda envelhecendo calada no primeiro ajuste.

   O telefone é a prova de que isso morderia: lá a saída vai a ZERO, e a grade
   continuaria recuando 8px por um avanço que não existe mais. */
.sgm-cnt-fita {
  --cnt-fita-cor: var(--color-primary-500);

  position: absolute;
  top: var(--sgm-4);
  left: calc(var(--cnt-fita-saida) * -1);
  z-index: 1;

  display: grid;
  place-items: center;
  /* --sgm-8 nos dois lados: 34x30 estavam escritos à mão e não saíam de token
     nenhum. Com 32x32 a lingueta vai de -8px a 24px, e o texto do painel
     continua começando em --sgm-10 (40px), que é o recuo do bloco. */
  width: var(--sgm-8);
  height: var(--sgm-8);

  background: var(--cnt-fita-cor);
  color: var(--color-on-primary);
  /* --sgm-t-md, e não os 14px de antes: é a mesma escala do título do painel */
  font-size: var(--sgm-t-md);
  line-height: 1;
  border-radius: 0 var(--sgm-r-sm) var(--sgm-r-sm) 0;
  box-shadow: var(--sgm-sh-1);
}
/* o par do `display` acima, no molde de `.sgm-det-controles[hidden]` (:491).
   `[hidden] { display: none !important }` do sgm-base.css:41 já resolveria
   sozinho — mas (0,2,0) contra (0,1,0) é a resposta que não depende do
   `!important` de outra folha, e a REGRA DE OURO 5 pede as duas. */
.sgm-cnt-fita[hidden] { display: none; }

/* A DOBRA. No legado é um `::before` de quatro bordas que finge uma sombra de
   laço; aqui é o triângulo que fica DEBAIXO da saliência, na mesma cor da fita
   escurecida. `filter: brightness()` em vez de um segundo hex: o tom é
   DERIVADO, então acompanha a fita em qualquer tema e em qualquer estado — o
   painel de sistema fora do ar troca `--cnt-fita-cor` e a dobra vai junto,
   sem uma linha a mais. */
.sgm-cnt-fita::before {
  content: "";
  position: absolute;
  left: 0;
  top: 100%;
  width: 0;
  height: 0;
  border-left: var(--cnt-fita-saida) solid transparent;
  /* --sgm-2 é exatamente a saliência, então a dobra fica a 45° */
  border-top: var(--sgm-2) solid var(--cnt-fita-cor);
  filter: brightness(.68);
}

@media (max-width: 767px) {
  /* sem saliência no telefone; a dobra some junto, porque a borda esquerda
     dela mede exatamente a saliência */
  /* no `:root`, para a GRADE acompanhar: se ficasse na fita, ela recuaria
     8px no telefone por um avanço que ali não acontece */
  :root { --cnt-fita-saida: 0px; }
}

/* --------------------------------------------------------------------------
   3. .sgm-cnt-cabeca — o cabeçalho da pessoa (§3.2)

   Nome, CPF/CNPJ, Endereço, Idade e Telefone, nessa ordem, com os rótulos do
   plano. Vem de `DadosContribuinte` e é o primeiro bloco da aba.

   ⚠️ Idade nula não é idade zero (§3.2): o valor chega vazio e vira travessão
   pela regra de `.sgm-cnt-linha__val:empty` mais abaixo. Nada some.
   -------------------------------------------------------------------------- */

.sgm-cnt-cabeca {
  position: relative;
  margin-bottom: var(--sgm-4);
  padding: var(--sgm-4) var(--sgm-4) var(--sgm-4) var(--sgm-10);
  background: var(--color-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-lg);
  box-shadow: var(--sgm-sh-2);
  /* o recuo à esquerda (--sgm-10, 40px) é o que abre passagem para a fita:
     ela vai de -8px a 26px, e o texto começa depois disso */
}

/* ⚠️ `.sgm-cnt-cabeca__nome` SAIU EM 2026-08-20, e a ausência é o ponto. O
   nome da pessoa era escrito TRÊS vezes na mesma aba — no rótulo da aba, no
   `<h1>` do `.sgm-page-head` e aqui, a 18px peso 700, colado embaixo do `<h1>`
   —, e as duas últimas fontes podiam divergir: o `<h1>` recebia o nome da
   linha da grade e este cartão usava o `pessoa.nome` do resumo. Hoje o nome
   vive só no `<h1>`, e é ele que se corrige quando o servidor manda a grafia
   canônica (`cntNomeCanonico`, sgm-telas.js). O cartão ficou com a carga útil
   dele: CPF/CNPJ, endereço, idade e telefone. */

/* --------------------------------------------------------------------------
   4. .sgm-cnt-painel — cada um dos oito painéis (§3.3, §3.4)
   -------------------------------------------------------------------------- */

.sgm-cnt-painel {
  position: relative;
  padding: var(--sgm-4) var(--sgm-4) var(--sgm-3) var(--sgm-10);
  background: var(--color-surface);
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-lg);
  box-shadow: var(--sgm-sh-1);
  transition: box-shadow var(--sgm-normal) var(--sgm-ease),
              border-color var(--sgm-normal) var(--sgm-ease);
}

.sgm-cnt-painel:hover { box-shadow: var(--sgm-sh-2); }

/* O TÍTULO É UM `<button>`, e não uma `<div onclick>` como no legado
   (`.titulocnt`, com `cursor: pointer` e mais nada). Assim o Tab chega nele, o
   Enter abre e o leitor de tela o anuncia como ação — de graça, e é o mesmo
   argumento que já está registrado em `.sgm-cel-link` e em `.sgm-lista-item`.

   `font: inherit` e `text-align: inherit` pelo motivo de sempre: sem eles o
   botão volta à fonte do sistema e o painel fica com um título de outra
   família no meio. */
.sgm-cnt-painel__titulo {
  display: flex;
  align-items: center;
  gap: var(--sgm-2);
  width: 100%;
  margin-bottom: var(--sgm-2);
  /* 🥇 ALVO DE TOQUE. Este é o único caminho para a lista de cada um dos oito
     sistemas, e no telefone (`.sgm-col-3` vira `span 12`) ele atravessa a
     largura do aparelho. Com `padding: 0` a altura era 15px x 1,25 = 18,75px:
     reprova no mínimo de 24x24 da WCAG 2.2 (2.5.8) e contraria a régua que
     este projeto já escreveu — `.sgm-btn--icon { width:38px; min-height:38px }`
     com o comentário "alvo de toque nunca menor que 38px" (sgm-base.css:339).
     O recuo lateral continua zero: o texto tinha de encostar na borda do
     painel, e é só a área vertical que faltava. */
  padding: var(--sgm-1) 0;
  min-height: 38px;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--sgm-t-md);
  font-weight: 650;
  line-height: var(--sgm-lh-tight);
  text-align: inherit;
  color: var(--color-on-surface);
  cursor: pointer;
}
.sgm-cnt-painel__titulo[hidden] { display: none; }

.sgm-cnt-painel__titulo:hover { color: var(--color-primary-600); } .sgm-cnt-painel[data-estado="ok"] .sgm-cnt-painel__titulo { color: var(--color-info); text-decoration: underline; text-underline-offset: 3px; } .sgm-cnt-painel[data-estado="ok"] .sgm-cnt-painel__titulo:hover { text-decoration-thickness: 2px; } /* 29/09, pedido do Rodrigo: no painel COM dados (data-estado ok) o título parece link - azul e sublinhado -, para o usuário saber que é ali que se clica. Os vazios, não apurados e fora do ar continuam sem, porque ali o clique só responde um aviso. Numa linha só para não deslocar os ponteiros desta folha. */

.sgm-cnt-painel__titulo:focus-visible {
  outline: 2px solid var(--color-primary-500);
  outline-offset: 2px;
  border-radius: var(--sgm-r-sm);
}

/* A SETA QUE DIZ "ISTO ABRE". No legado é `.icone-vermelho`: um
   `fa-angle-right` vermelho de 30px, `float: left`, do lado do título. Aqui é
   o mesmo glifo (`fa-angle-right`, \f105 no `fontawesome.min.css` que o
   ServerModule serve), mas no FIM da linha, na cor do primário e do tamanho do
   texto — a seta é a promessa, não o assunto. Ela anda um pouco à direita no
   hover, que é o jeito mais barato de um alvo dizer que responde.

   ⚠️ ELA É `::after` DO NOSSO BOTÃO, e não um `<i class="fa">` no markup: um
   `<i>` traria o `content` do FontAwesome para dentro do botão e eu teria de
   ganhar uma disputa de `content` com uma folha que não é nossa. A lição da
   lupa (`scripts\confere-cascata-lupa.js`) é não CRIAR a disputa. Como não há
   `<i>`, não há o que disputar — e por isso o `scripts\confere-icones.js`, que
   lê `.pas` e `.js`, não tem nada a conferir aqui. Conferi o codepoint à mão,
   na própria folha. */
.sgm-cnt-painel__titulo::after {
  content: "\f105";
  font-family: "Font Awesome 7 Free";
  font-weight: 900;
  margin-left: auto;
  color: var(--color-primary-500);
  transition: transform var(--sgm-fast) var(--sgm-ease);
}

.sgm-cnt-painel__titulo:hover::after { transform: translateX(var(--sgm-1)); }

/* ---- os três estados do painel (§3.4 e §7.1) ---------------------------- */

/* SOMA ZERO. O painel continua legível — os contadores em zero são resposta,
   e escondê-los faria a pessoa parecer não cadastrada. O que sai é a promessa
   de abertura: a seta. Clicar ainda dá o "Sem informação" do legado, e é a
   tela que decide isso, não o CSS.
   (0,2,0) contra (0,1,0) do bloco: vence sem depender de ordem. */
.sgm-cnt-painel[data-estado="vazio"] {
  background: var(--color-surface-sunken);
}
/* (0,3,1): o atributo, a classe do botão e o ::after. Nenhum concorrente. */
.sgm-cnt-painel[data-estado="vazio"] .sgm-cnt-painel__titulo::after,
.sgm-cnt-painel[data-estado="naoapurado"] .sgm-cnt-painel__titulo::after,
.sgm-cnt-painel[data-estado="fora"]  .sgm-cnt-painel__titulo::after {
  content: none;
}

/* 💎 NÃO APURADO — o QUARTO estado, 2026-08-20, terceira volta.

   O sistema RESPONDEU, mas nenhum dos oito cadastros achou a pessoa: os
   contadores não chegaram a ser apurados e saem em travessão, que é o que o
   servidor escreve na faixa acima da grade (uModContribuinte.pas:2380-2382).

   ⚠️ O QUE ESTE ESTADO NÃO PODE TER É O FUNDO DE "ZERADO". Até esta volta a
      tela não lia `encontrado:false` e os oito painéis caíam em
      `data-estado="vazio"`: `--color-surface-sunken`, contadores apagados, e
      um clique respondendo "Esta pessoa não tem registro neste sistema." — uma
      afirmação sobre o dado, contradizendo palavra por palavra a faixa logo
      acima. "Não foi possível apurar" não é "tem zero".

   Então o painel fica com a MOLDURA NORMAL - ele não afirma nada, e não há por
   que apagá-lo. O que sai é só a PROMESSA de abertura: a seta (regra acima) e
   o cursor de mão. O clique continua respondendo, com o fato sobre a BUSCA.

   ⚠️ E NÃO É TRACEJADO. O tracejado é do `fora`, e é o sinal de "o sistema não
      respondeu" — o estado que fez esta tela ser preferida na comparação cega.
      Dar o tracejado a um sistema que RESPONDEU juntaria de novo dois dos
      quatro estados. (0,2,0) contra (0,1,0) do bloco: vence sem depender de
      ordem. */
.sgm-cnt-painel[data-estado="naoapurado"] .sgm-cnt-painel__titulo {
  cursor: default;
}

/* SISTEMA QUE NÃO RESPONDEU (§7.1). Este é o caso que o legado engolia: o
   `TRY…EXCEPT` vazio fazia "fora do ar" parecer "não tem". Aqui o painel fica
   apagado, a fita perde a cor do primário e o título deixa de ser alvo — o
   motivo, em texto, está no `.sgm-aviso` acima da grade, que é da tarefa 1.2.
   (0,3,0) para a fita, contra (0,1,0) da regra base dela: vence por b.

   🏅 ESTE É O TERCEIRO ESTADO, E ELE É A RAZÃO DE A TELA NOVA TER SIDO
   PREFERIDA na comparação cega de 2026-08-20. O julgamento foi que "só um dos
   lados distingue as três coisas que o balcão precisa separar: tem zero, não
   há esse dado (travessão) e o sistema não respondeu (painel tracejado, não
   clicável, com o motivo escrito e a faixa de aviso)". Juntar dois desses três
   estados — dar sombra ao `fora`, deixá-lo clicável, ou pintá-lo igual ao
   `vazio` — devolve a tela ao lado que perdeu. O motivo inteiro está
   transcrito no cabeçalho do bloco CONTRIBUINTE de sgm-telas.js. */
/* 💎 (0,3,0) PELA CLASSE REPETIDA, E NÃO (0,2,0) — 2026-08-20.

   `.sgm-cnt-painel:hover { box-shadow: var(--sgm-sh-2) }` é (0,2,0), e esta
   regra era (0,2,0) também: o `fora` só vencia porque vem depois no arquivo.
   O cabeçalho deste bloco promete que "só há uma disputa real, resolvida por
   aritmética, seletor por seletor" — e este empate não estava declarado.

   A consequência de alguém reordenar o arquivo era concreta e silenciosa:
   painel de sistema fora do ar voltava a LEVANTAR no hover, prometendo clique
   num botão que está `:disabled`. Repetir a classe no seletor sobe para
   (0,3,0) sem mudar o que ele casa, e o empate deixa de existir — a ordem do
   arquivo passa a não importar. É o defeito de cascata que este projeto já
   registrou cinco vezes. */
.sgm-cnt-painel.sgm-cnt-painel[data-estado="fora"] {
  background: var(--color-surface-sunken);
  border-style: dashed;
  border-color: var(--color-outline-strong);
  box-shadow: none;
}
.sgm-cnt-painel[data-estado="fora"] .sgm-cnt-fita {
  --cnt-fita-cor: var(--color-on-surface-muted);
}
/* 🥇 O DESABILITADO SE ESTILIZA PELO ESTADO DO CONTROLE, e não pelo atributo
   do PAI. Quem põe `bt.disabled = true` é o JS, no estado `fora`; se o aspecto
   apagado viesse só de `[data-estado="fora"]`, qualquer outro caminho que
   desabilitasse este botão o deixaria com cara de habilitado. A regra
   `:disabled` vale sozinha, e é ela que traz o cursor — `not-allowed`, que é o
   vocabulário da folha base para controle desabilitado (sgm-base.css:212).
   Dois jeitos de dizer "não dá" na mesma aplicação é um a mais. */
/* ⚠️ `--color-on-surface-variant`, E NÃO `--color-on-surface-muted` — a mesma
   régua do `.sgm-cnt-linha__rot` deste bloco, que rejeita o muted por escrito
   citando 4,28:1. Aqui o número era pior: este título é 15px peso 650 sobre
   `--color-surface-sunken` (#f7f9fc), e o muted (#6b7c8f) ali dá 4,06:1 —
   reprova no AA da WCAG 1.4.3, que pede 4,5:1 (15px/650 não alcança o limiar
   de texto grande, 18,66px em negrito). O variant (#46586b) dá 6,94:1 sobre o
   mesmo sunken.

   E ISTO NÃO É DETALHE DE PALETA: este `<button>` é o ÚNICO texto dentro do
   painel que nomeia QUAL dos oito sistemas caiu — o terceiro estado, que é a
   razão declarada de esta tela ter vencido a comparação cega. Apagado e
   ilegível são coisas diferentes; o desabilitado se lê pelo cursor, pela
   moldura tracejada e pela linha "Situação: não respondeu", não por apagar a
   tinta abaixo do mínimo. */
.sgm-cnt-painel__titulo:disabled {
  color: var(--color-on-surface-variant);
  cursor: not-allowed;
}

/* O PAINEL ZERADO CONTINUA CLICÁVEL — o 00-PLANO.md §3.4 fixa o "Sem
   informação" do legado como a resposta dele —, mas não continua PROMETENDO:
   a seta já saiu (regra acima) e aqui sai o cursor de mão. O que ele faz é
   responder, não abrir. */
.sgm-cnt-painel[data-estado="vazio"] .sgm-cnt-painel__titulo {
  cursor: default;
}

/* as duas seguem a régua da regra `:disabled` acima — variant, e não muted */
.sgm-cnt-painel[data-estado="fora"] .sgm-cnt-painel__titulo {
  color: var(--color-on-surface-variant);
}
.sgm-cnt-painel[data-estado="fora"] .sgm-cnt-painel__titulo:hover {
  color: var(--color-on-surface-variant);
}

/* O PAINEL ESCOLHIDO. §3.4: "o painel escolhido fica marcado" enquanto a grid
   dele está na área de detalhe. O realce é o mesmo par que o sistema já usa em
   `.sgm-card[data-destaque]` (:137) — borda do primário e anel —, para o
   operador não ter de aprender um segundo sinal de "é este".
   💎 (0,3,0) PELA CLASSE REPETIDA — 2026-08-20. Era (0,2,0), e vencia
   `[data-estado="vazio"]`, `[data-estado="fora"]` e `:hover` — todos (0,2,0)
   — só pela ORDEM do arquivo. Dois desses empates estavam declarados aqui; o
   do `:hover` não estava, e a consequência de reordenar era o painel escolhido
   PERDER o anel ao passar o mouse. Agora os três estão resolvidos por
   aritmética: esta regra é (0,3,0) e ganha de todos, venha antes ou depois.

   A intenção continua a mesma que já estava escrita: um painel fora do ar não
   chega a ser escolhido, mas se a tela errar, o que se vê é a marcação, e não
   um cartão tracejado mudo. */
.sgm-cnt-painel.sgm-cnt-painel[data-marcado="true"] {
  border-color: var(--color-primary-500);
  box-shadow: var(--sgm-sh-2), var(--sgm-ring);
}

.sgm-cnt-painel[hidden] { display: none; }

/* --------------------------------------------------------------------------
   5. .sgm-cnt-linha — a linha rótulo/valor

   Duas formas, uma primitiva:
     .sgm-cnt-linha              rótulo à esquerda, número à direita — o painel
     .sgm-cnt-linha--junta       "Rótulo: valor" colado — o cabeçalho

   No legado as linhas do painel são uma `<table>` de duas `<td>` com
   `table-layout: fixed`, o que dá meia largura ao número. Aqui o número vai
   para a direita e o rótulo fica com a folga que sobrar: numa coluna estreita
   é o rótulo que precisa do espaço, o número tem quatro dígitos.
   -------------------------------------------------------------------------- */

.sgm-cnt-linha {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sgm-3);
  /* --sgm-1, e não os 5px que estavam escritos à mão: a escala do projeto é
     4/8/12/16/20/24, e 5px não sai de nenhum token */
  padding: var(--sgm-1) 0;
  border-bottom: 1px dotted var(--color-outline);
  font-size: var(--sgm-t-base);
  line-height: var(--sgm-lh-tight);
  min-width: 0;
}
.sgm-cnt-linha[hidden] { display: none; }

.sgm-cnt-linha:last-child { border-bottom: 0; padding-bottom: 0; }

/* ⚠️ `--color-on-surface-variant`, E NÃO `--color-on-surface-muted`. O muted
   (#6b7c8f) sobre a superfície branca dá 4,28:1 — reprova no AA da WCAG, que
   pede 4,5:1 para texto normal —, e no cabeçalho da pessoa este mesmo rótulo
   ainda cai para 12px pela regra `--junta`. O variant (#46586b) dá 7,32:1, que
   passa no AAA. E o lado do legado ganhava a comparação com folga: lá o
   `.container-subtitle` é `color: black` a 15px, 21:1. Marca apagada continua
   apagada — apagada e legível são coisas diferentes. */
.sgm-cnt-linha__rot {
  min-width: 0;
  color: var(--color-on-surface-variant);
  overflow-wrap: anywhere;
}

.sgm-cnt-linha__val {
  flex: 0 0 auto;
  font-weight: 600;
  color: var(--color-on-surface);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* CAMPO VAZIO VIRA TRAVESSÃO, NUNCA SOME — a mesma regra do selo, pelo mesmo
   motivo, e aqui ela tem um caso concreto no plano: idade nula NÃO é idade
   zero (§3.2). O `<span>` chega sem filhos e `:empty` casa.
   (0,3,2): as duas classes mais `:empty`, e o span mais o ::after. */
.sgm-cnt-linha__val:empty::after {
  content: "—";
  /* ⚠️ O TRAVESSÃO CARREGA SIGNIFICADO: ele é a afirmação "não há este dado".
     Desenhá-lo no tom mais fraco da folha era desenhar a afirmação mais
     importante da linha com o pior contraste dela. Mesmo variant do rótulo. */
  color: var(--color-on-surface-variant);
  font-weight: 400;
}

/* CONTADOR ZERADO É AUSÊNCIA, NÃO NÚMERO. Um "0" em negrito ao lado de um "12"
   em negrito pesa igual ao olho, e não é igual: um diz "não há". Continua à
   vista — apagado, que é a regra da marca desligada. Opcional: sem o atributo
   nada muda. (0,3,0). */
.sgm-cnt-linha[data-zero="true"] .sgm-cnt-linha__val {
  font-weight: 400;
  color: var(--color-on-surface-variant);
}

/* A FORMA DO CABEÇALHO: "Rótulo: valor", sem afastar um do outro e sem risco
   embaixo. São cinco fatos sobre a mesma pessoa, não uma tabela de contagens —
   espalhá-los pela largura de um cartão inteiro faria o olho viajar por 60
   caracteres de nada.

   ⚠️ ESPECIFICIDADE: `.sgm-cnt-linha--junta` é (0,1,0), IGUAL a
   `.sgm-cnt-linha`. Empate. Quem vence empate é a ordem, então esta regra vem
   DEPOIS — e é o único jeito honesto: subir a especificidade do modificador
   com um seletor artificial (`.sgm-cnt-cabeca .sgm-cnt-linha--junta`) o
   prenderia ao cabeçalho, e ele é uma FORMA, não um lugar. */
.sgm-cnt-linha--junta {
  justify-content: flex-start;
  gap: var(--sgm-1);
  /* metade de --sgm-1, derivada em vez de escrita: as cinco linhas do
     cabeçalho são uma lista colada, e 4px já as afastaria demais */
  padding: calc(var(--sgm-1) / 2) 0;
  border-bottom: 0;
  font-size: var(--sgm-t-sm);
}

/* o dois-pontos é do desenho, não do dado: o rótulo chega "Endereço" e a tela
   não precisa carregar pontuação em string */
.sgm-cnt-linha--junta .sgm-cnt-linha__rot::after { content: ":"; }

/* e aqui o valor não se cola na direita: ele segue o rótulo.
   (0,2,0) contra (0,1,0) de `.sgm-cnt-linha__val` — vence por b, sem depender
   de ordem. */
.sgm-cnt-linha--junta .sgm-cnt-linha__val {
  flex: 0 1 auto;
  min-width: 0;
  text-align: left;
  overflow-wrap: anywhere;
}

/* 🥇 MUITOS CARTÕES, UMA LINHA SÓ — 2026-09-23.

   Pedido do Rodrigo, com o print dos oito cartões dos Indicadores de Tributos
   (seis numa linha, dois esticados na de baixo): *"ajuste para que fiquem em
   uma única linha"*. Com base de 200px, oito cartões não cabem em 1.300px, e
   os dois que sobram ocupam a largura toda embaixo — parecendo mais
   importantes que os outros seis.

   A regra vale para QUALQUER faixa de sete ou mais cartões (as fichas de
   atendimento e a farmácia da Saúde também têm oito): todos dividem a linha
   por igual (`flex: 1 1 0`), com ícone, espaço e rótulo mais compactos, e o
   rótulo que não couber termina em reticências — o nome inteiro fica no
   `title` que o cartão clicável já leva, e o número nunca é cortado.

   ⚠️ `:has()` E NÃO UMA CLASSE POSTA PELO JS: dentro do `SGM.resumo` só se
   mudam linhas que já existem (há ponteiros `sgm-grid.js:NNN` em units
   Pascal). Navegador sem `:has()` continua como antes, quebrando em duas
   linhas — que é o comportamento de hoje, e não um defeito novo.

   ⚠️ SÓ DE 1024px PARA CIMA: no tablet oito cartões numa linha dariam 90px
   cada, e o valor de moeda não caberia. Abaixo disso, a regra de sempre. */
@media (min-width: 1024px) {
  .sgm-resumo:has(> .sgm-resumo__cartao:nth-child(7)) {
    flex-wrap: nowrap;
    gap: var(--sgm-2);
  }
  .sgm-resumo:has(> .sgm-resumo__cartao:nth-child(7)) > .sgm-resumo__cartao {
    flex: 1 1 0;
    gap: var(--sgm-2);
    padding: var(--sgm-2) var(--sgm-3);
  }
  .sgm-resumo:has(> .sgm-resumo__cartao:nth-child(7)) .sgm-resumo__ico {
    width: 32px;
    height: 32px;
    font-size: 1rem;
  }
  .sgm-resumo:has(> .sgm-resumo__cartao:nth-child(7)) .sgm-resumo__rotulo {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* --------------------------------------------------------------------------
   O aviso do módulo ao abrir (2026-09-30) — a faixa que barraFiltros põe
   entre a barra e os quadros; hoje, os prazos do SICONFI na Contabilidade
   (modules\uObsPrazosSiconfi.pas). Tom e cor vêm do .sgm-aviso; aqui só o
   miolo: título, lista curta e a linha de onde veio o dado.
   -------------------------------------------------------------------------- */
.sgm-aviso-modulo__corpo { display: flex; flex-direction: column; gap: var(--sgm-1); min-width: 0; }
.sgm-aviso-modulo__itens { margin: 0; padding-left: 1.25em; }
.sgm-aviso-modulo__itens li { margin: 2px 0; }
.sgm-aviso-modulo__rodape { font-size: var(--sgm-t-sm); opacity: 0.85; }

/* --------------------------------------------------------------------------
   A situação das coletas na barra (2026-10-01) — no Recursos federais ela
   toma o lugar da apuração, do exercício e das travas (pintarSituacaoDoModulo,
   sgm-telas.js). Selos baixos, em fileira que quebra: a barra continua uma
   barra, e não vira um quadro.
   -------------------------------------------------------------------------- */
.sgm-filtros__situacao { display: flex; flex-direction: column; gap: var(--sgm-1); flex: 1 1 100%; min-width: 0; }
.sgm-filtros__selos { display: flex; flex-wrap: wrap; gap: var(--sgm-2); }
.sgm-selo-coleta {
  display: flex; flex-direction: column; gap: 1px;
  padding: 4px var(--sgm-3);
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r);
  background: var(--color-surface-sunken);
  line-height: 1.25;
}
.sgm-selo-coleta__fonte { font-size: var(--sgm-t-sm); font-weight: 600; color: var(--color-on-surface); display: flex; align-items: center; gap: 4px; }
.sgm-selo-coleta__fonte i { font-size: 11px; }
.sgm-selo-coleta__quando { font-size: var(--sgm-t-xs); color: var(--color-on-surface-variant); font-variant-numeric: tabular-nums; }
.sgm-selo-coleta[data-tom="risco"] { background: var(--color-error-container); border-color: var(--color-error-outline); }
.sgm-selo-coleta[data-tom="risco"] .sgm-selo-coleta__fonte,
.sgm-selo-coleta[data-tom="risco"] .sgm-selo-coleta__quando { color: var(--color-error); }
.sgm-selo-coleta__texto { font-size: var(--sgm-t-sm); color: var(--color-on-surface-variant); }

/* --------------------------------------------------------------------------
   Texto longo na célula da grade — 01/10/2026 (SGM._gridTextoLongo, sgm-grid.js)

   Até três linhas e "…"; o clique abre o texto inteiro. Pedido do Rodrigo
   com a Ocorrência e o Parecer da Ouvidoria, que esticavam a linha a dez.
   -------------------------------------------------------------------------- */
.sgm-cel-longa {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
  min-width: 16rem;
  cursor: pointer;
}
.sgm-cel-longa:hover { color: var(--color-primary-500); }
.sgm-cel-longa:focus-visible {
  outline: 2px solid var(--color-primary-500);
  outline-offset: 2px;
  border-radius: var(--sgm-r-2);
}
.sgm-dialog__texto {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  color: var(--color-on-surface);
}

/* --------------------------------------------------------------------------
   Modo apresentação do Meu painel (07/10/2026) — sgm-telas.js, "Modo
   apresentação". O body ganha .sgm-apresentando e data-apres-modo; a faixa
   de cima (.sgm-apres) é fixa e o resto da casca some.

   O visual é o das telas do SGM: fundo da aplicação, faixa branca como a
   barra superior. A primeira versão tinha um palco escuro, de TV; o Rodrigo
   preferiu o nosso layout (07/10).
   -------------------------------------------------------------------------- */

.sgm-apresentando {
  --apres-faixa-h: 64px;
  --apres-palco: var(--color-background);
  --apres-palco-2: var(--app-header-bg);
  --apres-tinta: var(--app-header-fg);
  --apres-tinta-2: var(--color-on-surface-muted);
}

/* a casca some: menu, topo, cabeçalho da tela, filtros, abas */
.sgm-apresentando .sgm-aside,
.sgm-apresentando .sgm-topbar,
.sgm-apresentando #sgm-conteudo .sgm-page-head,
.sgm-apresentando #sgm-conteudo .sgm-filtros,
.sgm-apresentando #sgm-conteudo .sgm-abas,
.sgm-apresentando .sgm-overlay { display: none !important; }

.sgm-apresentando .sgm-app {
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  grid-template-areas: "main";
  background: var(--apres-palco);
}
.sgm-apresentando .sgm-main {
  padding: calc(var(--apres-faixa-h) + var(--sgm-4)) var(--sgm-5) var(--sgm-4);
  background: var(--apres-palco);
}
/* quem rola é o painel da aba; aqui a rolagem é só do modo, sem barra */
.sgm-apresentando #sgm-conteudo .sgm-painel[data-aba="base"] {
  overflow: hidden !important;
  scrollbar-width: none;
  transition: opacity 350ms var(--sgm-ease, ease);
}
.sgm-apresentando #sgm-conteudo .sgm-painel.sgm-apres-troca { opacity: 0; }

/* na TV não há o que clicar: coração, ferramentas e botões do rodapé saem */
.sgm-apresentando .sgm-card .sgm-fav,
.sgm-apresentando .sgm-card .sgm-card__ferramentas,
.sgm-apresentando .sgm-card .sgm-card__controles,
.sgm-apresentando .sgm-card .sgm-card__pe .sgm-btn { display: none !important; }
/* o selo da entidade recua sobre a faixa do coração (margem negativa); sem o
   coração, ele vazaria pela esquerda do card */
.sgm-apresentando .sgm-card__meta .sgm-chip { margin-left: 0; }

/* páginas: um respiro do tamanho da tela no fim, para a última página também
   começar numa linha de cards, e não repetir o fim da anterior */
.sgm-apresentando[data-apres-modo="paginas"] #sgm-conteudo .sgm-painel[data-aba="base"]:not([hidden])::after {
  content: ""; display: block; height: 100vh;
}

/* ---- a faixa de cima ---- */
.sgm-apres {
  position: fixed;
  inset: 0 0 auto 0;
  height: var(--apres-faixa-h);
  z-index: 900;
  display: flex;
  align-items: center;
  gap: var(--sgm-4);
  padding: 0 var(--sgm-5);
  background: var(--apres-palco-2);
  color: var(--apres-tinta);
  border-bottom: 1px solid var(--color-outline);
  box-shadow: var(--sgm-sh-1);
}
.sgm-apres__esq { display: flex; align-items: center; gap: var(--sgm-3); min-width: 0; flex: 1 1 0; }
.sgm-apres__logo {
  display: grid; place-items: center; width: 40px; height: 40px; flex: none;
  border-radius: var(--sgm-r); background: var(--color-primary-500); color: #fff; font-size: 18px;
}
.sgm-apres__tit { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.sgm-apres__tit strong { font-size: var(--sgm-t-lg); }
.sgm-apres__tit span {
  font-size: var(--sgm-t-sm); color: var(--apres-tinta-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sgm-apres__meio {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  flex: 1 1 0; min-width: 0; text-align: center;
}
.sgm-apres__modo {
  font-size: var(--sgm-t-xs); letter-spacing: .08em; text-transform: uppercase;
  color: var(--apres-tinta-2);
}
.sgm-apres__ind {
  font-size: var(--sgm-t-md); font-weight: 600;
  max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sgm-apres__dir { display: flex; align-items: center; justify-content: flex-end; gap: var(--sgm-4); flex: 1 1 0; }
.sgm-apres__ctl { display: flex; gap: var(--sgm-1); transition: opacity var(--sgm-normal, 200ms) ease; }
.sgm-apres__bt {
  width: 36px; height: 36px; border: 0; border-radius: var(--sgm-r-sm);
  background: transparent; color: var(--apres-tinta-2); cursor: pointer; font-size: 14px;
}
.sgm-apres__bt:hover { background: var(--app-header-hover); color: var(--apres-tinta); }
.sgm-apres__bt:focus-visible { box-shadow: var(--sgm-ring); color: var(--apres-tinta); outline: none; }
.sgm-apres__hora { display: flex; flex-direction: column; align-items: flex-end; line-height: 1.1; }
.sgm-apres__hora strong {
  font-size: 1.75rem; font-weight: 700; font-variant-numeric: tabular-nums; letter-spacing: .02em;
}
.sgm-apres__quando { font-size: var(--sgm-t-xs); color: var(--apres-tinta-2); }
.sgm-apres__barra {
  position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: var(--color-primary-500); transform: scaleX(0); transform-origin: left center;
}

/* mouse parado: os controles somem, e o cursor também */
.sgm-apresentando[data-apres-ocioso] .sgm-apres__ctl { opacity: 0; pointer-events: none; }
.sgm-apresentando[data-apres-ocioso] { cursor: none; }
.sgm-apresentando[data-apres-pausado] .sgm-apres__modo::after { content: " · pausado"; }

/* ---- carrossel: um quadro, grande ---- */
.sgm-apresentando[data-apres-modo="carrossel"] #sgm-conteudo .sgm-grade > * { display: none; }
.sgm-apresentando[data-apres-modo="carrossel"] #sgm-conteudo .sgm-grade > .sgm-card[data-apres-ativo] {
  display: flex;
  grid-column: 1 / -1;
  height: calc(100vh - var(--apres-faixa-h) - var(--sgm-8));
  height: calc(100dvh - var(--apres-faixa-h) - var(--sgm-8));
  max-width: 1400px;
  width: 100%;
  justify-self: center;
  animation: sgm-apres-entra 500ms var(--sgm-ease, ease) both;
}
.sgm-apresentando[data-apres-modo="carrossel"] .sgm-card[data-apres-ativo] .sgm-card__corpo {
  display: flex; flex-direction: column; min-height: 0;
}
.sgm-apresentando[data-apres-modo="carrossel"] .sgm-card[data-apres-ativo] .sgm-grafico {
  flex: 1 1 auto; height: auto !important; min-height: 240px;
}
.sgm-apresentando[data-apres-modo="carrossel"] .sgm-card[data-apres-ativo] .sgm-card__titulo {
  font-size: var(--sgm-t-xl);
}
/* a faixa de KPIs não entra no carrossel */
.sgm-apresentando[data-apres-modo="carrossel"] #sgm-conteudo .sgm-grade:not(:has(> .sgm-card)) { display: none; }

@keyframes sgm-apres-entra {
  from { opacity: 0; transform: translateX(32px); }
  to   { opacity: 1; transform: none; }
}

/* ---- mosaico: tudo numa tela, o foco passando ---- */
.sgm-apresentando[data-apres-modo="mosaico"] .sgm-apres-palco {
  width: var(--apres-largura, 100%);
  transform: scale(var(--apres-escala, 1));
  transform-origin: top left;
}
.sgm-apresentando[data-apres-modo="mosaico"] #sgm-conteudo .sgm-grade > .sgm-card {
  transition: opacity 400ms ease, transform 400ms ease, box-shadow 400ms ease;
  opacity: .45;
}
.sgm-apresentando[data-apres-modo="mosaico"] #sgm-conteudo .sgm-grade > .sgm-card[data-apres-ativo] {
  opacity: 1;
  transform: scale(1.03);
  box-shadow: 0 0 0 3px var(--color-primary-500), var(--sgm-sh-4);
  position: relative;
  z-index: 2;
}

@media (prefers-reduced-motion: reduce) {
  .sgm-apresentando[data-apres-modo="carrossel"] #sgm-conteudo .sgm-grade > .sgm-card[data-apres-ativo] { animation: none; }
  .sgm-apresentando #sgm-conteudo .sgm-painel[data-aba="base"],
  .sgm-apresentando[data-apres-modo="mosaico"] #sgm-conteudo .sgm-grade > .sgm-card { transition: none; }
}

/* ---- o diálogo de opções ---- */
.sgm-apres-modos { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sgm-2); margin-bottom: var(--sgm-4); }
.sgm-apres-modo {
  position: relative; display: flex; gap: var(--sgm-3); align-items: flex-start;
  padding: var(--sgm-3); border: 1px solid var(--color-outline); border-radius: var(--sgm-r);
  cursor: pointer; background: var(--color-surface);
}
.sgm-apres-modo:hover { border-color: var(--color-outline-strong); }
.sgm-apres-modo input { position: absolute; opacity: 0; pointer-events: none; }
.sgm-apres-modo:has(input:checked) { border-color: var(--color-primary-500); box-shadow: var(--sgm-ring); }
.sgm-apres-modo:has(input:focus-visible) { box-shadow: var(--sgm-ring); }
.sgm-apres-modo__ico {
  display: grid; place-items: center; width: 36px; height: 36px; flex: none;
  border-radius: var(--sgm-r-sm); background: var(--color-primary-50); color: var(--color-primary-600);
}
.sgm-apres-modo__tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sgm-apres-modo__tx strong { font-size: var(--sgm-t-base); color: var(--color-on-surface); }
.sgm-apres-modo__tx span { font-size: var(--sgm-t-sm); color: var(--color-on-surface-variant); line-height: 1.4; }
.sgm-apres-check { display: inline-flex; align-items: center; gap: var(--sgm-2); margin-top: var(--sgm-3); font-size: var(--sgm-t-base); }
@media (max-width: 600px) { .sgm-apres-modos { grid-template-columns: minmax(0, 1fr); } }

/* Personalizar o Meu painel (sgm-telas.js, abrirPersonalizarMeuPainel) */
.sgm-meupainel-lista { display: flex; flex-direction: column; gap: var(--sgm-1); margin-bottom: var(--sgm-3); }
.sgm-meupainel-item {
  display: flex; align-items: center; gap: var(--sgm-2);
  padding: var(--sgm-2) var(--sgm-3); border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-sm); cursor: pointer; font-size: var(--sgm-t-base);
}
.sgm-meupainel-item:hover { background: var(--color-surface-sunken); }
.sgm-meupainel-item:has(input:not(:checked)) { color: var(--color-on-surface-variant); text-decoration: line-through; }

/* --------------------------------------------------------------------------
   11b. Impressão de grade larga (13/10/2026)
   --------------------------------------------------------------------------
   A grade da Folha passa de vinte colunas, e em A4 retrato com 9pt tudo o
   que passava da largura da folha sumia do PDF - o Rodrigo viu o relatório
   parar no IGTI. O SGM.exportarPDF marca a folha:

     mais de 8 colunas    --larga      A4 paisagem (um @page injetado só
                                       enquanto imprime), 8pt
     mais de 14 colunas   --compacta   além disso 6,5pt e menos respiro

   O texto pode quebrar em qualquer ponto (nome, cargo, unidade); o valor
   não (.num continua nowrap), porque um R$ partido em duas linhas lê errado.
   -------------------------------------------------------------------------- */
@media print {
  .sgm-impressao--larga,
  .sgm-impressao--larga .sgm-grid tbody td,
  .sgm-impressao--larga .sgm-grid tfoot td { font-size: 8pt; }
  /* o título da coluna na tela é nowrap, com 10px de respiro e (0,1,2) de peso: sem igualar o
     peso, o cabeçalho não quebrava e empurrava a tabela para fora da folha */
  .sgm-impressao .sgm-grid thead th { position: static; white-space: normal; letter-spacing: 0; padding: 3pt 4pt; }
  .sgm-impressao--larga .sgm-grid thead th { font-size: 7pt; }
  .sgm-impressao--larga td { overflow-wrap: anywhere; }

  .sgm-impressao--compacta,
  .sgm-impressao--compacta .sgm-grid tbody td,
  .sgm-impressao--compacta .sgm-grid tfoot td { font-size: 6.5pt; padding: 2pt 2pt; }
  .sgm-impressao--compacta .sgm-grid thead th { font-size: 6pt; padding: 2pt 2pt; }
}

/* --------------------------------------------------------------------------
   11c. O valor do cartão não quebra no meio (13/10/2026)
   --------------------------------------------------------------------------
   Print do Rodrigo, Comparativo entre meses da Folha: seis cartões na linha,
   cada um com duas medidas (2025 e 2026), e o valor saía partido -
   "R$ 3.395.80" numa linha e "6,22" na outra. Era o overflow-wrap: anywhere
   do .sgm-resumo__valor: o número quebrava em vez de transbordar, e sem
   transbordar o SGM.valorQueCabe nunca abreviava (ele mede scrollWidth contra
   clientWidth, e o span inline nem tem clientWidth).

   Agora o valor é bloco de uma linha só. Se não couber, transborda, e o
   valorQueCabe troca pela forma curta (R$ 3,4 mi) com o número inteiro no
   title - o mesmo trato dos cards do painel. A medida e o texto podem
   encolher até a largura do cartão (sem isso o bloco largo empurraria o
   cartão, e o transbordo não aconteceria).
   -------------------------------------------------------------------------- */
.sgm-resumo__texto { flex: 1 1 auto; }
.sgm-resumo__medida { max-width: 100%; }
.sgm-resumo__valor {
  display: block;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  overflow-wrap: normal;
}

/* Sete ou mais cartões numa linha até 1.600px (o print: 7 x 143px a 1.366px):
   mesmo abreviado, "R$ 939,5 mil" não cabia ao lado do ícone. O ícone sai e
   o número fica no tamanho de sempre - diminuir a fonte para 1rem ainda
   cortava, e para 13px o valor perdia o destaque que o Rodrigo pediu em
   2026-08-15. Acima de 1.600px os cartões têm largura e o ícone volta. */
@media (min-width: 1024px) and (max-width: 1599px) {
  .sgm-resumo:has(> .sgm-resumo__cartao:nth-child(7)) .sgm-resumo__ico { display: none; }
}

/* --------------------------------------------------------------------------
   11d. PDF da grade: o total aparece, e a folha cabe no papel (13/10/2026)
   --------------------------------------------------------------------------
   Print do Rodrigo, Acompanhamento Mensal da Folha: o Excel trazia a linha de
   total e o PDF não. A linha estava lá (o SGM.exportarPDF monta o tfoot), mas
   a célula herdava da tela o position: sticky; bottom: 0 do .sgm-grid tfoot
   td, e na impressão sobrava só uma faixa vazia ao pé de cada página.

   Na folha o total é static e em preto, e o tfoot vira um grupo de linhas
   comum: aparece UMA vez, depois da última linha. Como table-footer-group, o
   navegador o repetiria em toda página, e o total geral ao pé da página 1
   lê como se fosse o total dela.

   O Empenhado cortava à direita: a folha mede a largura do body, e o body da
   tela pode ser mais largo que o papel (com 1.500px de body a tabela saía com
   1.495px numa A4 paisagem de 1.047px). Na impressão o body volta à largura
   da página. A data (.dt) não quebra - com o overflow-wrap: anywhere da
   grade larga, 01/02/1997 saía "01/02/199" numa linha e "7" na outra.
   -------------------------------------------------------------------------- */
@media print {
  .sgm-imprimindo,
  .sgm-imprimindo body { width: auto !important; min-width: 0 !important; max-width: none !important; }
  .sgm-impressao { max-width: 100% !important; }
  .sgm-impressao .sgm-grid tfoot { display: table-row-group; }
  .sgm-impressao .sgm-grid tfoot td {
    position: static;
    color: #000;
    background: none;
    box-shadow: none;
    font-weight: 700;
  }
  .sgm-impressao .sgm-grid tfoot tr { break-inside: avoid; page-break-inside: avoid; }
  .sgm-impressao .sgm-grid td.dt { white-space: nowrap; overflow-wrap: normal; }
}

/* --------------------------------------------------------------------------
   11e. Tabela dinâmica e envio por e-mail (15/10/2026)
   --------------------------------------------------------------------------
   Os dois diálogos novos do detalhamento (SGM.tabelaDinamica e
   SGM.relatorioPorEmail, no fim do sgm-grid.js). A moldura é o sgm-dialog de
   sempre; aqui só o que é deles.

   A tabela do pivô usa a classe da grade (.sgm-grid) para ter o mesmo
   cabeçalho, as mesmas linhas e o mesmo rodapé de total. ⚠️ No celular a
   grade vira cartão (seção 8, max-width 767px); o pivô é um cruzamento, e
   cartão desmancharia o cruzamento - lá ele continua tabela, com rolagem
   lateral. Os seletores têm .sgm-pivo na frente para vencer os da seção 8.
   -------------------------------------------------------------------------- */
.sgm-pivo__ctl {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--sgm-3);
  margin-bottom: var(--sgm-3);
}
.sgm-pivo__abas { display: flex; gap: var(--sgm-2); margin-bottom: var(--sgm-3); }
.sgm-pivo__abas .sgm-btn[aria-pressed="true"] {
  background: var(--color-primary-50);
  border-color: var(--color-primary-500);
  color: var(--color-primary-600);
}
.sgm-pivo__aviso {
  padding: var(--sgm-3);
  border: 1px solid var(--color-warning-outline);
  border-radius: var(--sgm-r-sm);
  background: var(--color-warning-container);
  color: var(--color-warning);
}
.sgm-pivo__rolo {
  max-height: 56vh;
  overflow: auto;
  border: 1px solid var(--color-outline);
  border-radius: var(--sgm-r-sm);
}
.sgm-pivo__tab { width: 100%; }
.sgm-pivo__tab th:first-child,
.sgm-pivo__tab td:first-child { text-align: left; }
.sgm-pivo__tab td.sgm-pivo__tot { font-weight: 650; }
.sgm-pivo__graf { height: 380px; }

@media (max-width: 767px) {
  .sgm-pivo .sgm-grid { display: table; width: 100%; }
  .sgm-pivo .sgm-grid thead { display: table-header-group; }
  .sgm-pivo .sgm-grid tbody { display: table-row-group; }
  .sgm-pivo .sgm-grid tfoot { display: table-footer-group; }
  .sgm-pivo .sgm-grid tr,
  .sgm-pivo .sgm-grid tbody tr,
  .sgm-pivo .sgm-grid tfoot tr { display: table-row; width: auto; padding: 0; margin: 0; border: 0; box-shadow: none; }
  .sgm-pivo .sgm-grid td,
  .sgm-pivo .sgm-grid tbody td,
  .sgm-pivo .sgm-grid tfoot td { display: table-cell; width: auto; padding: 6px 10px; }
  .sgm-pivo .sgm-grid tbody td::before { content: none; }
  .sgm-pivo__graf { height: 300px; }
}

.sgm-email .sgm-dialog__corpo { display: flex; flex-direction: column; gap: var(--sgm-3); }
.sgm-email__ajuda { margin: 0; font-size: var(--sgm-t-sm); color: var(--color-on-surface-variant); }
.sgm-email__anexo {
  margin: 0;
  padding: var(--sgm-2) var(--sgm-3);
  border-radius: var(--sgm-r-sm);
  background: var(--color-surface-sunken);
  font-size: var(--sgm-t-sm);
  color: var(--color-on-surface-variant);
}

/* --------------------------------------------------------------------------
   11f. Ver como (15/10/2026)
   --------------------------------------------------------------------------
   O menu do ícone de quatro quadrados na lateral dos gráficos (§ver-como no
   fim do sgm-charts.js): o mesmo .sgm-menu do Exportar, com um título, a
   forma que está na tela marcada e a de origem com a nota padrão.
   -------------------------------------------------------------------------- */
.sgm-menu__titulo {
  margin: 0;
  padding: 6px var(--sgm-3) 4px;
  font-size: var(--sgm-t-xs);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--color-on-surface-variant);
}
.sgm-menu__nota {
  margin-left: auto;
  padding-left: var(--sgm-3);
  font-size: var(--sgm-t-xs);
  color: var(--color-on-surface-variant);
}
.sgm-menu--vercomo .sgm-menu__item[aria-checked="true"] {
  background: var(--color-primary-50);
  color: var(--color-primary-600);
  font-weight: 650;
}
.sgm-menu--vercomo .sgm-menu__item[aria-checked="true"] i { color: var(--color-primary-500); }

/* ==========================================================================
   11g. 🥇 O NÚMERO CABE NO CARD — 2026-10-15
   --------------------------------------------------------------------------
   Print do Rodrigo com quatro cards da Contabilidade de Mongaguá circulados:
   "R$ 38.118.592,|", "R$ 11.719.990,|", "R$ 163.408.70|" — o DESTAQUE cortado
   na borda do card. Pedido: *"reveja a responsividade dos cards,
   principalmente os que tem valores pois estouram e nao cabem no card, pode
   até diminuir um pouco a fonte"*.

   A CAUSA: o destaque era 32px/700 fixo (`--sgm-t-2xl`). Num card de um
   quarto de tela sobram ~200px, e "R$ 38.118.592,25" em 32px pede ~280. O
   card tem `overflow: hidden`, então o número não quebrava a página — só
   perdia os centavos, e às vezes a casa do milhar, sem aviso nenhum.

   🥇 O CORPO SAI DA LARGURA DO CARD, NÃO DA JANELA. `container-type` faz do
      bloco um contêiner, e `cqi` é 1% da largura dele: o mesmo quadro fica
      grande num card de meia tela e menor num de um quarto, e o menu
      recolhido ou aberto já entra na conta sem JavaScript. A unidade de
      janela (`vw`) que a faixa do medidor usava errava justamente aí — a
      janela não muda quando a barra lateral muda.

   ⚠️ A CONTA DO TAMANHO: um valor em reais com milhões ("R$ 120.064.971,86",
      17 caracteres) mede ~9,3 vezes o corpo da fonte em algarismos tabulares.
      10,5cqi no destaque e 9,5cqi na caixa pequena deixam caber até a casa
      das centenas de milhões; acima disso (bilhões) a medida acusa e o
      `SGM.valorQueCabe` abrevia para "R$ 1,16 bi", com o número inteiro no
      hover. Encolher sem fim deixaria o número ilegível; abreviar sem tentar
      encolher, que era o que acontecia nas caixas, trocava centavos por
      "mi" num card que tinha espaço para eles.

   ⚠️ O TETO DESCEU (32 → 28px no destaque, 18 → 17px nas caixas): é o "pode
      até diminuir um pouco a fonte". Os cards da mesma fileira têm a mesma
      largura e por isso o MESMO corpo — o tamanho deixa de depender do
      comprimento de cada número, e a fileira lê como um painel só.
   ========================================================================== */

.sgm-destaque {
  container-type: inline-size;
  padding: var(--sgm-4) var(--sgm-3) var(--sgm-3);
}

.sgm-destaque__rot {
  font-size: clamp(0.875rem, 7.5cqi, 1.0625rem);
  line-height: 1.3;
}

.sgm-destaque__val {
  font-size: clamp(1.125rem, 10.5cqi, 1.75rem);
  font-weight: 650;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
}

/* ⚠️ SÓ A FILEIRA PADRÃO E A DO MEDIDOR. A `--lado` (o PPA) é a forma do
   legado, com o número em `<h1>` numa coluna `auto` — foi pedida assim e fica
   assim (ver 2b-bis). E `container-type` só entra em filho de GRADE: num item
   cuja largura viesse do conteúdo, a contenção o zeraria. */
.sgm-indicadores:not(.sgm-indicadores--lado) > .sgm-indicador {
  container-type: inline-size;
  min-width: 0;
}

/* `[data-num]` é posto pelo `SGM.valorQueCabe` só em valor numérico: o texto
   (nome de secretaria, situação) continua quebrando linha como antes. */
.sgm-indicadores:not(.sgm-indicadores--lado) > .sgm-indicador .sgm-indicador__val[data-num] {
  font-size: clamp(0.8125rem, 9.5cqi, 1.0625rem);
  white-space: nowrap;
  overflow: hidden;
  overflow-wrap: normal;
}

/* --------------------------------------------------------------------------
   11h. O SUBMENU DA PIZZA NO "VER COMO" — 2026-10-15

   Pedido do Rodrigo: com mais de uma pizza possível (empenhado e saldo,
   liquidado e não liquidado, execução completa), o menu mostra UM item
   "Pizza", e o clique abre as opções logo abaixo dele, recuadas. Abaixo e não
   ao lado: o menu nasce colado na borda direita do card.

   ⚠️ `[hidden]` explícito pela regra de ouro 5: um `display` de autor vence o
      `hidden` do navegador.
   -------------------------------------------------------------------------- */
.sgm-menu__sub { display: flex; flex-direction: column; gap: 2px; margin: 2px 0 4px; }
.sgm-menu__sub[hidden] { display: none; }

.sgm-menu__item--sub {
  /* o texto começa onde começa o "Pizza": recuo = ícone (14px) + gap */
  padding-left: calc(var(--sgm-3) + 14px + var(--sgm-3));
  font-size: var(--sgm-t-sm);
}

.sgm-menu__seta {
  margin-left: auto;
  font-size: 10px;
  color: var(--color-on-surface-variant);
  transition: transform var(--sgm-fast) var(--sgm-ease);
}
.sgm-menu__item--grupo[aria-expanded="true"] .sgm-menu__seta { transform: rotate(180deg); }
.sgm-menu--vercomo .sgm-menu__item--grupo[data-ativo] { color: var(--color-primary-600); font-weight: 650; }
.sgm-menu--vercomo .sgm-menu__item--grupo[data-ativo] i { color: var(--color-primary-500); }
