/* components.css : botao, card e o que as telas reusam.
   A tabela da casa entra aqui na Fase 4, uma vez so, e nenhuma tela copia. */

/* ------------------------------------------------------------------ botao */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 9px 14px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-sm);
  background: var(--branco);
  color: var(--texto);
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  transition: background var(--transicao), border-color var(--transicao),
              color var(--transicao);
}

.btn:hover {
  background: var(--fundo);
  border-color: var(--texto-fraco);
  text-decoration: none;
}

.btn:disabled {
  opacity: .45;
  cursor: not-allowed;
}

.btn:disabled:hover { background: var(--branco); border-color: var(--borda); }

.btn-primary {
  background: var(--cor-primaria);
  border-color: var(--cor-primaria);
  color: var(--texto-sobre-cor-primaria);
  font-weight: 600;
}

.btn-primary:hover {
  background: var(--cor-primaria-hover);
  border-color: var(--cor-primaria-hover);
  color: var(--texto-sobre-cor-primaria);
}

/* exceção E2 (ver style.css): botão de ação secundária azul, ex.: "Resumo
   de Divergências" na Validação de Precificação. */
.btn-info {
  background: var(--info);
  border-color: var(--info);
  color: var(--texto-sobre-info);
  font-weight: 600;
}

.btn-info:hover {
  background: var(--info-hover);
  border-color: var(--info-hover);
  color: var(--texto-sobre-info);
}

/* Regra de laranja ampliada em 27/09/2026 (ver style.css:97): destaque de ação
   secundária isolada, fora do par "hoje x 2027". 1º uso: "Baixar modelo" na
   tela Dados. */
.btn-acento {
  background: var(--cor-acento);
  border-color: var(--cor-acento);
  color: var(--texto-sobre-cor-acento);
  font-weight: 600;
}

.btn-acento:hover {
  background: var(--cor-acento-hover);
  border-color: var(--cor-acento-hover);
  color: var(--texto-sobre-cor-acento);
}

.btn-sm {
  padding: 7px 11px;
  font-size: 12.5px;
}

.btn i { font-size: 15px; }

/* ------------------------------------------------------------------- card */

.cd {
  background: var(--branco);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  box-shadow: var(--sombra-sm);
  padding: 20px;
}

.cd-sm { padding: 12px; }
.cd-md { padding: 16px; }

.cd-cab {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--borda);
}

.cd-cab h2 { font-size: var(--fs-lg); flex: 1; min-width: 0; }

.cd-corpo {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding-top: var(--sp-3);
}

/* Card recolhivel: o cabecalho inteiro e o botao que abre e fecha. */
.cd-recolhivel .cd-cab { padding-bottom: 0; border-bottom: none; font-size: var(--fs-lg); }
.cd-recolhivel.aberto .cd-cab { padding-bottom: var(--sp-3); border-bottom: 1px solid var(--borda); }
.cd-toggle {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
  background: transparent;
  border: none;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.cd-toggle-titulo { flex: 1; min-width: 0; }
.cd-seta { transition: transform var(--transicao); color: var(--texto-fraco); }
.cd-recolhivel.aberto .cd-seta { transform: rotate(90deg); }

/* Selo de resultado ao lado do titulo. */
.selo {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: var(--raio-pill);
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
  background: var(--fundo);
  color: var(--texto-suave);
}
.selo-ok { background: var(--sucesso-suave); color: var(--sucesso); }
.selo-erro { background: var(--perigo-suave); color: var(--perigo); }

/* Checagem da maquina: uma linha por item. */
.maq-lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.maq-passos { padding-top: var(--sp-3); border-top: 1px dashed var(--borda); }
.maq-item { display: flex; align-items: baseline; gap: var(--sp-2); font-size: 13px; }
.maq-item i { font-size: 16px; align-self: center; }
.maq-item strong { min-width: 150px; font-weight: 600; }
.maq-item span { color: var(--texto-secundario); }
.maq-ok i { color: var(--sucesso); }
.maq-aviso i { color: var(--aviso); }
.maq-erro i { color: var(--perigo); }
.maq-erro span { color: var(--perigo); }
.maq-acoes { display: flex; gap: var(--sp-2); }

/* Cards irmaos numa grid tem a mesma altura. */
.grid {
  display: grid;
  gap: var(--sp-4);
  align-items: stretch;
}

.grid > .cd { height: 100%; }

.grid-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }

/* ------------------------------------------------------------------ texto */

.muted { color: var(--texto-fraco); }

.destaque {
  color: var(--cor-primaria-texto);
  font-weight: 600;
}

.caminho {
  font-family: ui-monospace, "Cascadia Mono", "Consolas", monospace;
  font-size: 13px;
  background: var(--fundo);
  border: 1px solid var(--borda);
  border-radius: var(--raio-sm);
  padding: 2px 6px;
}

/* ------------------------------------------------------------ selectbusca
   Dropdown com busca, substitui <select> nativo em todo o projeto.
   O painel e position:fixed de proposito: o JS calcula a posicao com
   getBoundingClientRect (coordenadas de viewport), e absolute erraria a
   conta assim que a pagina rolasse. */

.selectbusca { position: relative; min-width: 200px; }

.selectbusca .sb-display {
  height: 40px;
  box-sizing: border-box;
  padding: 0 var(--sp-3);
  background: var(--branco);
  border: 1px solid var(--borda);
  border-radius: var(--raio-sm);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
}

.selectbusca.open .sb-display { border-color: var(--cor-primaria); }

.selectbusca .sb-label { font-size: 14px; color: var(--texto); }
.selectbusca .sb-label.sb-placeholder { color: var(--texto-fraco); }

.selectbusca .sb-panel {
  position: fixed;
  z-index: 60;
  background: var(--branco);
  border: 1px solid var(--borda);
  border-radius: var(--raio-sm);
  box-shadow: var(--sombra);
  max-height: 280px;
  overflow-y: auto;
  display: none;
}

.selectbusca.open .sb-panel { display: block; }

.selectbusca .sb-search {
  width: 100%;
  padding: var(--sp-3);
  background: var(--fundo);
  border: none;
  border-bottom: 1px solid var(--borda);
  color: var(--texto);
  font-size: 13px;
}

.selectbusca .sb-opt {
  padding: var(--sp-2) var(--sp-3);
  cursor: pointer;
  font-size: 14px;
}

.selectbusca .sb-opt:hover {
  background: var(--cor-primaria-suave);
  color: var(--cor-primaria-escura);
}

.selectbusca .sb-vazio {
  padding: var(--sp-2) var(--sp-3);
  font-size: 13px;
  color: var(--texto-fraco);
}

/* --------------------------------------------------------------- ra-bar
   Linha de formulario: inputs e botao na mesma altura (40px), alinhados
   pela base. O botao usa o truque <label>&nbsp;</label> pra ficar na mesma
   altura total dos campos com label. */

.ra-bar {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-end;
  flex-wrap: wrap;
}

.ra-bar .campo {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.ra-bar label {
  font-size: 13px;
  font-weight: 600;
  color: var(--texto-secundario);
}

.ra-bar .input,
.ra-bar .selectbusca .sb-display,
.ra-bar > .btn,
.ra-bar .campo > .btn {
  height: 40px;
  box-sizing: border-box;
}

.ra-bar .selectbusca { min-width: 280px; }

/* ------------------------------------------------------------- im-msg
   Mensagem inline de sucesso ou erro, ao lado de uma acao. Cor por classe,
   nunca por style inline. */

.im-msg {
  font-size: 12.5px;
  color: var(--texto-suave);
  padding: 7px 12px;
  border-radius: var(--raio-sm);
}

.im-msg.ok {
  color: var(--sucesso);
  background: var(--cor-primaria-suave);
  font-weight: 600;
}

.im-msg.erro {
  color: var(--perigo);
  background: var(--perigo-suave);
  font-weight: 600;
}

/* Mensagem solta direto na pagina (fora de uma barra de acao horizontal):
   acompanha a largura do proprio texto, em vez de esticar pra largura toda
   que .pagina (flex column) daria por padrao. */
.im-msg.solta { align-self: flex-start; }

/* ------------------------------------------------------------- im-drop
   Caixa de upload arraste-e-solte (Padrao_Upload_Arquivo). 3 estados: inicial
   (tracejado), over (arrastando por cima, cor primaria), loaded (arquivo
   escolhido, mesmas cores de .im-msg.ok). */

.im-drop {
  display: block;
  border: 2px dashed var(--borda);
  border-radius: var(--raio);
  padding: var(--sp-6);
  text-align: center;
  color: var(--texto-secundario);
  cursor: pointer;
  transition: .15s;
  user-select: none;
}

.im-drop:hover,
.im-drop.over {
  border-color: var(--cor-primaria);
  background: var(--cor-primaria-suave);
  color: var(--cor-primaria-texto);
  border-style: solid;
}

.im-drop.loaded {
  border-style: solid;
  border-color: var(--sucesso);
  background: var(--sucesso-suave);
  color: var(--sucesso);
}

.im-drop i {
  font-size: 36px;
  display: block;
  margin-bottom: var(--sp-2);
}

.im-arq {
  display: block;
  margin-top: var(--sp-1);
  font-weight: 600;
  color: var(--sucesso);
}

/* Input file real fica fora da tela: o visual e so o .im-drop acima. */
.im-inp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}

/* Linha de acao do upload: mensagem a esquerda (margin-right:auto), botao
   Confirmar ancorado a direita (Acao_Primaria_a_Direita). */
.im-acao {
  display: flex;
  gap: var(--sp-2);
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
  margin-top: var(--sp-3);
}
.im-acao .im-msg { margin-right: auto; }

/* ---------------------------------------------------------------- vz
   Estado vazio de tela inteira: a tabela ou o conteudo sai, isto entra.
   Sem card, sem borda, sem botao que duplique um controle que ja existe na
   tela (o botao aqui e a UNICA acao possivel: ir pro lugar que resolve). */

.vz {
  flex: 1;
  min-height: 300px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--sp-6) var(--sp-5);
  gap: var(--sp-2);
}

/* [hidden] do navegador e display:none, mas e um estilo de USER AGENT: uma
   regra de autor com display (a .vz acima) sempre ganha da UA em empate de
   especificidade, entao [hidden] sozinho NAO escondia a .vz -- ela ficava
   visivel (display:flex) por baixo de qualquer tabela com linhas, o tempo
   todo, desde a Fase 4. .vz[hidden] tem mais especificidade que .vz e e do
   mesmo autor, entao esta regra ganha de verdade. */
.vz[hidden] { display: none; }

.vz .vz-icone {
  font-size: 40px;
  color: var(--texto-fraco);
  margin-bottom: var(--sp-2);
}

.vz-titulo {
  font-family: var(--font-titulo);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.02em;
  color: var(--texto);
}

.vz-sub {
  font-size: 13.5px;
  color: var(--texto-suave);
  max-width: 400px;
}

/* .vz-inline: tabela que continua na tela como "secao de card" nao tem area
   sobrando pra centrar em Y -- o vazio so respira, nao estica. E o caso da
   Excecao E3 (dono, 08/09/2026): o cabecalho fica sempre visivel, entao a
   <table> nunca some, e o bloco de vazio vive DENTRO do card. Medidas da
   propria nota Padrao_Estado_Vazio. */
.vz.vz-inline {
  flex: none;
  min-height: 150px;
  padding: 22px 16px;
}
.vz.vz-inline .vz-icone { font-size: 30px; margin-bottom: 10px; }
.vz.vz-inline .vz-titulo { font-size: 14.5px; }
.vz.vz-inline .vz-sub { font-size: 12.5px; }

/* ==================================================================
   TABELA DA CASA
   Macro: templates/_macros/tabela.html | Motor: static/js/tabela.js
   Modulo de consulta: tabela.py

   Regra dura de Padrao_Cabecalho_da_Tabela: o card NUNCA leva
   overflow:hidden aqui, senao o popup do menu sanduiche fica cortado.
   Quem recorta os cantos e o .tabela-scroll, via overflow-x.
   ================================================================== */

.tabela-wrap {
  background: var(--branco);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  box-shadow: var(--sombra-sm);
  /* SEM overflow:hidden aqui, de proposito */
}

.tabela-cab {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
  border-bottom: 1px solid var(--borda);
}

.tabela-titulo {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-lg);
}

.tabela-contagem-cab {
  font-size: 12.5px;
  color: var(--texto-suave);
  white-space: nowrap;
}

/* --------------------------------------------------- menu sanduiche */

.ta-menu-wrapper { position: relative; }

.ta-menu-btn {
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 1px solid var(--borda);
  border-radius: var(--raio-sm);
  background: var(--branco);
  cursor: pointer;
  color: var(--texto-secundario);
}

.ta-menu-btn:hover { border-color: var(--cor-primaria); color: var(--cor-primaria-texto); }
.ta-menu-btn i { font-size: 18px; }

.ta-menu {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 6px;
  min-width: 210px;
  background: var(--branco);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  box-shadow: var(--sombra);
  display: none;
  z-index: 50;
}

.ta-menu.aberto { display: block; }

.ta-menu-item {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 10px 14px;
  font-size: 13px;
  color: var(--texto);
  cursor: pointer;
}

.ta-menu-item:hover { background: var(--fundo); color: var(--cor-primaria-texto); }
.ta-menu-item i { font-size: 16px; color: var(--texto-secundario); }
.ta-menu-item:hover i { color: var(--cor-primaria-texto); }
.ta-menu-item.ativo { background: var(--cor-primaria-suave); color: var(--cor-primaria-escura); }
.ta-menu-item.ativo i { color: var(--cor-primaria-escura); }
.ta-menu-divider { height: 1px; background: var(--borda); margin: 4px 0; }

.ta-popup {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 6px;
  min-width: 240px;
  background: var(--branco);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  box-shadow: var(--sombra);
  display: none;
  z-index: 60;
  max-height: 320px;
  overflow-y: auto;
}

.ta-popup.aberto { display: block; }

.ta-popup-cab {
  padding: 10px 14px;
  border-bottom: 1px solid var(--borda);
  font-weight: 700;
  font-size: 13px;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.ta-popup-cab i { color: var(--cor-primaria-texto); }

.ta-popup-corpo { padding: 6px; }

.ta-popup-opcao {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: 8px 10px;
  font-size: 13px;
  border-radius: var(--raio-sm);
  cursor: pointer;
}

.ta-popup-opcao:hover { background: var(--fundo); }

.ta-popup-check {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 7px 10px;
  border-radius: var(--raio-sm);
  font-size: 13px;
  cursor: pointer;
}

.ta-popup-check:hover { background: var(--fundo); }
.ta-popup-check input { accent-color: var(--cor-primaria); margin: 0; }

/* rodape do popup (Pref_Tabela: "Restaurar larguras" mora dentro do popup
   Colunas, sem item novo no menu) */
.ta-popup-rodape {
  padding: 8px 10px;
  border-top: 1px solid var(--borda);
}

/* ---------------------------------------------------------- tabela */

.tabela-scroll { overflow-x: auto; }

/* Padrao_Cabecalho_Fixo (opt-in, pedido do dono 04/09/2026): uma tela passa
   cabecalho_fixo=true pra macro tabela() quando quer o <thead> fixo ao
   rolar. Por que nao e so "position:sticky no th, top calculado"? Testado
   ao vivo e achado um limite real do Chromium: quando o th sticky tem um
   ancestral com overflow-x:auto (igual .tabela-scroll, pra tabela larga
   rolar de lado -- e a especificacao de CSS FORCA overflow-y a computar
   'auto' tambem nesse caso, mesmo sem pedir), o sticky fica PRESO a um teto
   errado (travava a uns 105px do topo, nao no valor pedido, testado com
   varios valores de "top" diferentes -- sempre a MESMA distancia errada).
   Trocar overflow-y por 'hidden'/'clip' nao ajuda, o problema e QUALQUER
   overflow != visible num ancestral virar "scroll container" pro sticky.
   Solucao real (a mesma que apps de planilha usam): esta div vira uma
   caixa com ALTURA PROPRIA (max-height) e rolagem PROPRIA (overflow-y:
   auto) -- o <thead> fica sticky top:0 relativo a ELA, nao a pagina. Isso
   tambem cumpre ao pe da letra o pedido do dono ("ao rolar a tela, so as
   linhas descem"): quem rola sao as linhas, dentro desta caixa.
   --altura-ate-tabela (medida por main.js, com a pagina no topo) e a
   distancia real do topo do documento ate este card -- da o quanto sobra
   de tela pro restante (24px de folga no fim). Fallback 300px so entra se
   o JS nao rodar por algum motivo. */
.tabela-scroll-fixa {
  overflow-y: auto;
  /* clamp, nao so calc: numa janela baixa (notebook pequeno, zoom alto),
     o calc sozinho podia encolher a caixa a ponto de mostrar 1 ou 2 linhas
     so -- 280px (~6 linhas) e o minimo pra ainda ser util rolando por
     dentro dela. */
  max-height: clamp(280px, calc(100vh - var(--altura-ate-tabela, 300px) - 24px), 100vh);
}

/* so a 1a linha (nomes de coluna) fica fixa -- a 2a (filtro por coluna,
   opcional, escondida por padrao) e deixada de fora de proposito: se as 2
   grudassem no mesmo top:0, uma cobriria a outra quando o filtro por
   coluna estivesse aberto. */
.tabela-scroll-fixa thead tr:first-child th {
  position: sticky;
  top: 0;
  z-index: 15;
}

.tabela {
  width: 100%;
  /* separate, nao collapse: o Chromium calcula ERRADO o "top" de
     position:sticky em <th>/<td> quando a tabela usa border-collapse --
     achado ao vivo (04/09/2026) implementando o thead fixo (Padrao_
     Cabecalho_Fixo). So ha borda inferior em th/td (sem borda vertical em
     lugar nenhum), entao separate + border-spacing:0 renderiza identico. */
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13.5px;
}

/* Classe ligada por tabela.js depois de medir a largura natural de cada
   coluna (Pref_Tabela, "redimensionar colunas"): so entao table-layout vira
   fixed, senao a largura do <colgroup> ficaria disputando com o auto do
   navegador. */
.tabela.tabela-cols-fixas { table-layout: fixed; }

.tabela thead th {
  background: var(--branco);
  color: var(--texto-secundario);
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  text-align: left;
  padding: 10px 14px;
  border-bottom: 1px solid var(--borda);
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  position: relative;
}

.tabela thead th[data-nao-ordenavel] { cursor: default; }
.tabela thead th.th-ordenado { color: var(--cor-primaria-texto); }
.tabela thead th i { margin-left: 4px; font-size: 12px; }

/* rotulo em <span>, nao o <th> inteiro, ganha o corte com reticencias: assim
   o icone de ordenacao e a alca de arrastar (abaixo) nunca ficam escondidos
   quando o texto do rotulo e mais comprido que a coluna estreita. */
.tabela thead th .th-rotulo {
  display: inline-block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: middle;
}

/* Coluna redimensionavel arrastando a borda (Pref_Tabela, 22/09/2026; ver
   tabela.js, secao "redimensionar colunas"). A alca e injetada por JS, nunca
   pelo macro -- o HTML servido pelo Flask nao muda. */
.th-resize {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 8px;
  cursor: col-resize;
  z-index: 5;
}
.th-resize:hover, .th-resize:active { background: var(--cor-primaria); opacity: .5; }

body.redimensionando-coluna { cursor: col-resize; user-select: none; }
body.redimensionando-coluna * { cursor: col-resize !important; }

.tabela tbody td {
  padding: 9px 14px;
  border-bottom: 1px solid var(--borda);
  color: var(--texto);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tabela tbody tr:hover td { background: var(--fundo); }
.tabela tbody tr:last-child td { border-bottom: none; }

/* Tabela de GESTAO (painel admin): poucas linhas, com campos editaveis e uma
   coluna de acoes. Diferente da tabela de DADOS (larga, feita pra rolar de
   lado), esta tem que caber sem esconder a acao principal atras do scroll. Os
   inputs encolhem pra largura da celula e as celulas podem quebrar linha, em vez
   de forcar a tabela a transbordar. So as telas admin marcam .tab-admin, entao
   as tabelas de negocio (que herdam .tabela) nao mudam. */
.tab-admin tbody td { white-space: normal; overflow: visible; }
.tab-admin .input-sm { width: 100%; min-width: 84px; box-sizing: border-box; }
.tab-admin .maq-acoes { flex-wrap: wrap; justify-content: flex-end; }

/* Matriz de permissao (admin/permissoes.html): cabecalho de GRUPO (mesmo
   agrupamento da sidebar) em faixa colorida, e linha de SUBMENU indentada e
   com marcador -- pra quem monta o perfil enxergar a hierarquia do menu sem
   precisar abrir o menu de verdade pra comparar. */
.perm-grupo td {
  background: var(--cor-primaria-suave);
  color: var(--cor-primaria-texto);
  font-weight: 700;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: .04em;
  padding: 7px var(--sp-3);
}

.perm-sub td:first-child { padding-left: calc(var(--sp-3) + 22px); }

.perm-sub-seta { color: var(--texto-fraco); margin-right: 6px; }

.perm-sem-acao { color: var(--texto-fraco); font-size: var(--fs-xs); font-style: italic; }

/* campo divergente entre CODSTs (grupo.html): mesmo --perigo-suave que
   .im-msg.erro ja usa, nao uma cor nova. So marca as colunas de tributacao
   que TEM valor diferente entre as linhas do grupo -- e o proposito da tela,
   apontar onde a divergencia esta, sem precisar ler celula por celula. */
.tabela th.campo-divergente,
.tabela tbody td.campo-divergente { background: var(--perigo-suave); }
.tabela tbody tr:hover td.campo-divergente { background: var(--perigo-suave); }

/* linha clicavel (data-href, ver tabela.js): destaque mais forte que o hover
   comum, e a 1a coluna (o rotulo que identifica a linha) ganha a cor de
   marca, pra parecer link sem precisar virar <a> (a linha inteira e o alvo
   do clique, nao so o texto). */
.tabela tbody tr[data-href] { cursor: pointer; }
.tabela tbody tr[data-href]:hover td { background: var(--cor-primaria-suave); }

/* Padrao_Coluna_Negrito / Padrao_Celula_Destaque: mecanismo GENERICO da
   macro de tabela (Resumo de Divergências, Validação de Precificação, foi
   a 1a a pedir). Coluna nasce com {"negrito": true} na definicao (ex.: a
   coluna do preço do ERP, pra destacar contra as colunas calculadas) --
   estatico, mesmo em toda linha. _CELULAS_DESTAQUE e por LINHA: a tela poe
   essa chave (lista das chaves de coluna que devem ficar vermelhas
   NAQUELA linha) no dict antes de mandar pra tabela.paginar -- dinamico,
   decidido pelo backend linha a linha (ex.: só a diferença que estourou a
   tolerância fica vermelha, nao a outra). Mesmo --perigo/--perigo-suave
   que .campo-divergente ja usa (grupo.html): mesma cor, mecanismo
   diferente (aquele e estatico no template bespoke; este e dinamico,
   aplicado por tabela.js tambem ao redesenhar via fetch). */
.tabela tbody td.col-negrito { font-weight: 700; }
.tabela tbody td.celula-destaque { background: var(--perigo-suave); color: var(--perigo); font-weight: 600; }
.tabela tbody tr:hover td.celula-destaque { background: var(--perigo-suave); }
.tabela tbody tr[data-href] td:first-child { color: var(--cor-primaria-texto); font-weight: 600; }

/* linha de filtro por coluna, dentro do proprio thead */
.tabela-filtros th { padding: 6px 10px; border-bottom: 1px solid var(--borda); }

.filtro-coluna {
  width: 100%;
  height: 30px;
  box-sizing: border-box;
  padding: 0 8px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-sm);
  font-size: 12.5px;
  font-weight: 400;
  text-transform: none;
  color: var(--texto);
}

.filtro-coluna:focus { border-color: var(--cor-primaria); outline: none; }

/* ------------------------------------------------------------ rodape */

.tabela-rodape {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--borda);
}

.tabela-contagem-rodape {
  font-size: 12.5px;
  color: var(--texto-suave);
}

.tabela-nav {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  justify-self: center;
}

.btn-pagina {
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border: 1px solid var(--borda);
  border-radius: var(--raio-sm);
  background: var(--branco);
  color: var(--texto-secundario);
  cursor: pointer;
}

.btn-pagina:hover:not(:disabled) { border-color: var(--cor-primaria); color: var(--cor-primaria-texto); }
.btn-pagina:disabled { opacity: .35; cursor: not-allowed; }

.tabela-indicador {
  font-size: 12.5px;
  color: var(--texto);
  white-space: nowrap;
}

/* --------------------------------------------- drill-down (grupo divergente)
   Tabela pequena, sem paginacao, com uma linha escondida por baixo de cada
   linha de CODST -- por isso fora do tabela.js (o motor generico), que so
   sabe redesenhar <tr> planas. */

.linha-drill-cab { cursor: pointer; }

.drill-btn {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: none;
  background: none;
  color: var(--texto-secundario);
  cursor: pointer;
}

.linha-drill-corpo td {
  padding: var(--sp-3) var(--sp-4);
  background: var(--fundo);
}

/* width:auto pisando o width:100% de .tabela (que esta tabela TAMBEM usa,
   pra herdar fonte/borda): o <td colspan> pai e tao largo quanto a tabela
   de fora inteira (~27 colunas) -- com width:100% a coluna Descricao
   esticaria pra fora da tela, parecendo vazia (achado ao vivo, 04/09/2026:
   as linhas apareciam so com o codigo, a descricao sumia pra direita, fora
   do scroll visivel -- so trocar por "sem width nenhum" NAO bastou, porque
   .tabela ja tinha width:100% e nada aqui sobrescrevia). Com width:auto, a
   tabela fica do tamanho do proprio conteudo, encostada na esquerda. */
.tabela-aninhada { width: auto; border-collapse: collapse; }
.tabela-aninhada th {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--texto-secundario);
  text-align: left;
  padding: 4px 10px;
  border-bottom: 1px solid var(--borda);
}
.tabela-aninhada td { padding: 6px 10px; border-bottom: 1px solid var(--borda); font-size: 13px; }
.tabela-aninhada tr:last-child td { border-bottom: none; }

/* ------------------------------------------------------- barra fu-bar
   Filtro DE PAGINA (acima da tabela), diferente do filtro DE COLUNA
   (dentro do thead, acima). Infra pronta pra quando uma tela precisar. */

.fu-bar {
  display: flex;
  gap: var(--sp-3);
  flex-wrap: wrap;
  align-items: flex-end;
  --fu-h: 38px;
}

.fu-bar .g {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.fu-lbl {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--texto-secundario);
}

.fu-bar input,
.fu-bar .btn,
.fu-bar .selectbusca .sb-display {
  height: var(--fu-h);
  box-sizing: border-box;
  padding: 0 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-sm);
  font-size: 13px;
}

/* ------------------------------------------------------------- kpi-grid
   Padrao_KPI_Dashboard, pra relatorio com totalizadores (nao listagem
   operacional: Listagens_sem_KPI continua valendo pras telas de listagem).
   Cores adaptadas pros tokens de estado do projeto (--sucesso/--aviso), em
   vez das 6 variantes de gradiente da nota, que sao de outro cliente. */

.kpi-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

@media (max-width: 900px) { .kpi-grid { grid-template-columns: repeat(2, 1fr); } }

.kpi {
  background: var(--branco);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 14px;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: 12px;
}

.kpi::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--borda);
}

.kpi.sucesso::before { background: var(--sucesso); }
.kpi.aviso::before { background: var(--aviso); }

.kpi .kpi-ico {
  width: 44px;
  height: 44px;
  border-radius: var(--raio-sm);
  display: grid;
  place-items: center;
  font-size: 22px;
  flex-shrink: 0;
  background: var(--cor-primaria-suave);
  color: var(--cor-primaria-texto);
}

.kpi.sucesso .kpi-ico { background: var(--sucesso-suave); color: var(--sucesso); }
.kpi.aviso .kpi-ico { background: var(--aviso-suave); color: var(--aviso); }

.kpi .kpi-corpo { min-width: 0; flex: 1; display: flex; flex-direction: column; }

.kpi .kpi-lbl {
  font-size: 10.5px;
  color: var(--texto-secundario);
  text-transform: uppercase;
  letter-spacing: .03em;
  font-weight: 700;
}

.kpi .kpi-val {
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -.5px;
  line-height: 1.3;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------- loading-inline
   Padrao_Loading_Estado. So a variante inline: nada nesta tela bloqueia a
   pagina toda, entao overlay global nao se aplica ainda. */

.loading-inline {
  padding: 60px 20px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  background: var(--branco);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}

.loading-inline .spinner-circle {
  width: 44px;
  height: 44px;
  border: 4px solid var(--borda);
  border-top-color: var(--cor-primaria);
  border-radius: 50%;
  animation: spinner-rotate .8s linear infinite;
}

.loading-inline .loading-text {
  font-size: 14px;
  font-weight: 600;
  color: var(--texto);
}

@keyframes spinner-rotate { to { transform: rotate(360deg); } }

/* -------------------------------------------------------------- sw (on/off)
   Padrao_Toggle_OnOff, Tipo 3 da taxonomia (Padrao_Toggle_Tipos). Estado que
   liga/desliga 1 coisa. Verde = ativo (--sucesso do projeto, nao o
   #16a34a generico da nota: mesma cor que a Fase 6 ja usa pra "positivo",
   um vocabulario so pro app inteiro). Este app nao tem escrita AJAX pra este
   estado (nao e uma entidade no banco, e parametro de visao da tela): o
   onchange submete o form GET que envolve o switch, recarregando a pagina
   com o novo valor na querystring, mesma arquitetura de toda tela do app. */

.sw {
  position: relative;
  width: 42px;
  height: 24px;
  flex: 0 0 auto;
}

.sw input { display: none; }

.sw label {
  position: absolute;
  inset: 0;
  background: var(--borda);
  border-radius: var(--raio-pill);
  cursor: pointer;
  transition: background var(--transicao);
}

.sw label::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 20px;
  height: 20px;
  background: var(--branco);
  border-radius: 50%;
  transition: transform var(--transicao);
  box-shadow: var(--sombra-sm);
}

.sw input:checked + label { background: var(--sucesso); }

/* A chave laranja e a de 2027, pela mesma regra de cor do resto do app: verde e
   o que vale hoje, laranja e o que vale depois. Hoje so a chave "esta oferta ja
   inclui a CBS" usa ela -- a de IPI continua verde porque fala do preco de
   hoje. Quinta familia laranja do projeto (ver CHECKLIST_APLICACAO.md). */
.sw.sw-acento input:checked + label { background: var(--cor-acento); }
.sw input:checked + label::after { transform: translateX(18px); }

.sw input:focus-visible + label {
  outline: 2px solid var(--cor-primaria);
  outline-offset: 2px;
}

.sw-campo {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.sw-campo span {
  font-size: 13px;
  color: var(--texto);
}

/* ------------------------------------------------------------ Modo Leitura
   Pref_Tabela, item 3. Chave na topbar (_macros/modo_leitura.html), ligada
   por main.js. Ligado: some da pagina tudo que nao e a tabela nem caminho
   ate ela (barra de filtros, KPIs, avisos, textos, cards de acao) e os
   botoes da topbar; a sidebar recolhe (layout.css, mesma regra de
   [data-sidebar="destravada"]). A tabela fica inteira, com cabecalho, menu
   sanduiche e paginacao. As abas ficam: elas escolhem QUAL tabela se le,
   sem elas a leitura prende na primeira. Olha so 2 niveis abaixo da .pagina
   de proposito: :has() sobre as celulas custaria caro em tabela de 500
   linhas. */
.modo-leitura-chave > label[for] {
  font-size: 13px;
  color: var(--texto);
  cursor: pointer;
  white-space: nowrap;
}

/* .modo-leitura-controle: os interruptores proprios do Panorama (Modo Pareto
   e o Modo Leitura da propria tela). Ficam na topbar por design; sem
   poupar aqui, ligar o Modo Leitura escondia o botao de desligar e o Modo
   Pareto junto -- sem volta a nao ser o Esc (achado 25/09/2026). */
body.modo-leitura .topo-acoes > :not(.modo-leitura-chave):not(.modo-leitura-controle),
body.modo-leitura .pagina > :not(.tabela-wrap):not(:has(.tabela-wrap)),
body.modo-leitura .pagina > :not(.tabela-wrap) > :not(.tabela-wrap):not(.abas):not(:has(.tabela-wrap)) {
  display: none;
}

/* ------------------------------------------------------------------ abas
   Padrao_Tabs: troca o PAINEL visivel dentro da mesma pagina, sem recarregar
   (as duas visoes ja vem prontas do servidor no mesmo request). Sublinhado
   na ativa, nunca pilula/solido (isso e visual de toggle). */

.abas {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--borda);
  margin-bottom: var(--sp-4);
}

.aba {
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--texto-secundario);
  cursor: pointer;
  border: none;
  background: transparent;
  border-bottom: 2px solid transparent;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: inherit;
}

.aba:hover { color: var(--texto); }

.aba.ativa {
  color: var(--cor-primaria-texto);
  border-bottom-color: var(--cor-primaria);
}

.aba-painel { display: none; }
.aba-painel.ativa { display: block; }

/* --------------------------------------------------------- lista-simples
   Gerenciamento curto (poucas linhas, sem filtro/ordenacao/paginacao): a
   tabela da casa e overkill aqui. Usado pelas excecoes de divergencia. */

.lista-simples { display: flex; flex-direction: column; gap: var(--sp-2); }

.ls-linha {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--borda);
}

.ls-linha:last-child { border-bottom: none; }

.ls-linha .ls-principal { flex: 1; min-width: 0; font-size: 13px; color: var(--texto); }
.ls-linha .ls-motivo { flex: 1; min-width: 0; font-size: 12.5px; color: var(--texto-fraco); }

/* ------------------------------------------------------------ selectbusca
   Variante desabilitada: regiao sem produto escolhido ainda (Fase 8). */

.selectbusca.desabilitado { opacity: .55; pointer-events: none; }

/* --------------------------------------------------------------- ct-presets
   Padrao_Toggle_Tipos, Tipo 1 (multi opcoes), decidido no PASSO 0 pro
   alternador Ficha completa / So tributacao. Prefixo "ct" = modulo
   consulta_tributacao, convencao de Padrao_Barra_de_Filtros. */

.ct-presets, .painel-abas {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-sm);
  background: var(--branco);
}

.ct-presets button, .painel-abas button {
  height: 32px;
  border: 1px solid transparent;
  background: var(--branco);
  border-radius: calc(var(--raio-sm) - 2px);
  padding: 0 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--texto-secundario);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: inherit;
}

.ct-presets button:hover, .painel-abas button:hover { color: var(--cor-primaria-texto); }

.ct-presets button.on, .painel-abas button.on {
  border-color: var(--cor-primaria);
  background: var(--cor-primaria-suave);
  color: var(--cor-primaria-escura);
}

/* .painel-abas é visualmente igual ao .ct-presets, mas semanticamente
   diferente: troca qual painel aparece (Tabela × Comparativo, Panorama).
   .ct-presets fica reservado aos dois toggles que trocam valor enviado ao
   servidor sem trocar de painel — regra do CHECKLIST_APLICACAO.md §5. */

/* ------------------------------------------------------------- ficha (Fase 8)
   Porte do HTML que o app antigo escrevia na mao (style= inline, hex cru)
   pra card + token. Padrao_Box_Card: card base, raio/sombra por token. */

.ficha-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-4);
  align-items: start;
}

@media (max-width: 900px) { .ficha-grid { grid-template-columns: 1fr; } }

.ficha-bloco {
  background: var(--branco);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  overflow: hidden;
  box-shadow: var(--sombra-sm);
  margin-bottom: var(--sp-3);
}

.ficha-bloco-cab {
  background: var(--fundo);
  padding: 8px 14px;
  border-bottom: 1px solid var(--borda);
}

.ficha-bloco.destaque .ficha-bloco-cab { background: var(--cor-primaria-escura); }

.ficha-bloco-nome {
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--texto-secundario);
}

.ficha-bloco.destaque .ficha-bloco-nome { color: var(--branco); }

.ficha-bloco-sub { font-size: 11px; color: var(--texto-fraco); margin-top: 1px; }
.ficha-bloco.destaque .ficha-bloco-sub { color: var(--branco); opacity: .8; }

.ficha-linha {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-3);
  padding: 7px 14px;
  border-bottom: 1px solid var(--borda);
  font-size: 13px;
}

.ficha-linha:last-child { border-bottom: none; }

.ficha-linha .rotulo { color: var(--texto-secundario); }
.ficha-linha .valor { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--texto); }

.ficha-linha.destaque .rotulo,
.ficha-linha.destaque .valor { font-weight: 700; color: var(--texto); }

.ficha-nota {
  padding: 9px 14px;
  font-size: 12px;
  color: var(--texto-fraco);
  background: var(--fundo);
}

/* ---------------------------------------------------- quadros de tributacao
   EXCECAO E1 (sancionada pelo dono em 02/09/2026): unicas cores da tela que
   NAO sao --cor-primaria. Ver LASTRO. */

.quadros-trib {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-4);
}

@media (max-width: 700px) { .quadros-trib { grid-template-columns: 1fr; } }

.quadro-trib {
  border-radius: var(--raio);
  overflow: hidden;
  border: 1px solid var(--borda);
  box-shadow: var(--sombra-sm);
}

.quadro-trib-cab {
  padding: 10px 14px;
  text-align: center;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
}

.quadro-trib.transferencia { border-color: var(--cor-transferencia-suave); }
.quadro-trib.transferencia .quadro-trib-cab {
  background: var(--cor-transferencia);
  color: var(--texto-sobre-cor-transferencia);
}
.quadro-trib.transferencia .ficha-linha { background: var(--cor-transferencia-suave); }

.quadro-trib.venda { border-color: var(--cor-venda-suave); }
.quadro-trib.venda .quadro-trib-cab {
  background: var(--cor-venda);
  color: var(--texto-sobre-cor-venda);
}
.quadro-trib.venda .ficha-linha { background: var(--cor-venda-suave); }

/* ============================================================================
   ACRÉSCIMOS DESTE PROJETO
   ----------------------------------------------------------------------------
   Bloco A : formulário, portado LITERALMENTE do painel Gera Rotinas Automáticas
             (static/css/components.css de lá). O 8282 é app de leitura e não
             tinha campo de formulário; o painel tem, e já está auditado.
   Bloco B : componentes que só existem aqui — a barra de comparação e os
             quadros de resultado do simulador.

   Nenhum hex abaixo. Tudo sai de var(--...) do style.css.
   ========================================================================== */

/* ------------------------------------------------------------------ bloco A
   formulário (do painel Gera Rotinas) */

.campo { display: flex; flex-direction: column; gap: 6px; }

.campo > label,
.campo > .campo-rotulo {
  font-size: 12.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--texto-secundario);
}

.campo-largo { flex: 1; min-width: 0; }

/* Checkbox de parametro (ex.: travar a CBS), dentro de um .campo. Sobrescreve
   o rotulo em caixa-alta do .campo > label: aqui o rotulo E o proprio texto do
   checkbox, em caixa normal, lado a lado com a caixinha. */
.campo > label.campo-check {
  flex-direction: row;
  align-items: center;
  gap: 8px;
  text-transform: none;
  font-weight: 500;
  font-size: var(--fs-sm);
  color: var(--texto);
  cursor: pointer;
}

.campo-check input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--cor-primaria);
  flex-shrink: 0;
}

.input {
  height: 40px;
  box-sizing: border-box;
  padding: 0 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-sm);
  background: var(--branco);
  color: var(--texto);
  font-size: 13.5px;
}

.input:focus { border-color: var(--cor-primaria); outline: none; }

.input-sm { height: 32px; font-size: 12.5px; }

.input-num { text-align: right; font-variant-numeric: tabular-nums; }

.campo-com-botao { display: flex; gap: var(--sp-2); align-items: stretch; }
.campo-com-botao .input { flex: 1; min-width: 0; }
.campo-com-botao .btn { flex-shrink: 0; white-space: nowrap; }

.badge {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: var(--raio-pill);
  white-space: nowrap;
}

.badge-neutro { background: var(--fundo); color: var(--texto-secundario); }
.badge-marca { background: var(--cor-primaria-suave); color: var(--cor-primaria-escura); }
.badge-2027 { background: var(--cor-acento-suave); color: var(--cor-acento-escura); }
.badge-alerta { background: var(--aviso-suave); color: var(--aviso); }

.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 10px;
  border-radius: var(--raio-pill);
  font-size: 11.5px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.pill.on { background: var(--sucesso-suave); color: var(--sucesso); }
.pill.off { background: var(--fundo); color: var(--texto-fraco); border: 1px solid var(--borda); }

.aviso-faixa {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  font-size: 13px;
  color: var(--aviso);
  background: var(--aviso-suave);
  border: 1px solid var(--aviso-suave);
  border-radius: var(--raio-sm);
  padding: 10px 12px;
}

.aviso-faixa i { font-size: 16px; flex-shrink: 0; margin-top: 1px; }

.aviso-cartao { border-color: var(--aviso); }
.aviso-cartao .cd-cab i { color: var(--aviso); }

/* monoespaçada para código de produto, NCM e alíquota em coluna */
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ bloco B
   a barra de comparação hoje x 2027.

   Sem biblioteca de gráfico: barra horizontal é largura em percentual, e o app
   roda offline. Verde é hoje, laranja é 2027 -- e essa é a única leitura da
   cor em toda a tela. */

.cmp { display: flex; flex-direction: column; gap: var(--sp-3); }

.cmp-linha { display: grid; grid-template-columns: minmax(0, 250px) 1fr; gap: var(--sp-3); align-items: center; }

/* O rotulo QUEBRA em vez de virar reticencias. Descoberto com o recorte por
   cenario: os nomes comecam todos por "PIS/COFINS MONOFASICO," e, cortados no
   mesmo ponto, as dez linhas ficavam identicas -- um grafico onde nao dava pra
   saber qual barra e qual. Duas linhas de altura, e a terceira vira reticencias. */
.cmp-rot {
  font-size: var(--fs-sm);
  line-height: 1.25;
  color: var(--texto-secundario);
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

.cmp-barras { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

.cmp-par { display: flex; align-items: center; gap: var(--sp-2); }

.cmp-trilho { flex: 1; height: 14px; background: var(--fundo); border-radius: var(--raio-pill); overflow: hidden; min-width: 0; }

.cmp-preenche { height: 100%; border-radius: var(--raio-pill); transition: width var(--transicao); }

.cmp-hoje .cmp-preenche { background: var(--cor-primaria); }
.cmp-2027 .cmp-preenche { background: var(--cor-acento); }

.cmp-val {
  font-size: var(--fs-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  width: 104px;
  text-align: right;
  flex-shrink: 0;
}

.cmp-hoje .cmp-val { color: var(--cor-primaria-texto); }
.cmp-2027 .cmp-val { color: var(--cor-acento-texto); }

.cmp-legenda { display: flex; gap: var(--sp-4); font-size: var(--fs-xs); color: var(--texto-secundario); }
.cmp-legenda span { display: inline-flex; align-items: center; gap: 6px; }
.cmp-legenda i { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }
.cmp-legenda .lg-hoje { background: var(--cor-primaria); }
.cmp-legenda .lg-2027 { background: var(--cor-acento); }

/* KPI com os dois cenários lado a lado, dentro do mesmo cartão */

.kpi-par { display: flex; gap: var(--sp-4); align-items: baseline; flex-wrap: wrap; }
.kpi-lado { display: flex; flex-direction: column; gap: 2px; }
.kpi-lado .kpi-val { font-size: 22px; }
.kpi-cenario { font-size: 10.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; }
.kpi-hoje .kpi-val { color: var(--cor-primaria-texto); }
.kpi-hoje .kpi-cenario { color: var(--cor-primaria-texto); }
.kpi-2027 .kpi-val { color: var(--cor-acento-texto); }
.kpi-2027 .kpi-cenario { color: var(--cor-acento-texto); }

/* ------------------------------------------- quadros de resultado do simulador
   Nome .res de propósito: .quad já existe no painel Gera Rotinas com outro
   significado (quadradinho de legenda de calendário). Dois nomes iguais com
   comportamentos diferentes é armadilha para quem ler os dois projetos. */

.res-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--sp-4); align-items: stretch; }

.res {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--branco);
  padding: var(--sp-4);
}

.res-cab { display: flex; align-items: center; gap: var(--sp-2); font-family: var(--font-titulo); font-weight: 700; font-size: var(--fs-lg); }
.res-cab i { font-size: 18px; }

.res-hoje { border-color: var(--cor-primaria); }
.res-hoje .res-cab { color: var(--cor-primaria-texto); }
.res-alvo { border-color: var(--cor-acento); }
.res-alvo .res-cab { color: var(--cor-acento-texto); }
.res-veredito { border-color: var(--borda); background: var(--fundo); }

.res-linhas { display: flex; flex-direction: column; gap: var(--sp-2); }

.res-linha { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-3); font-size: var(--fs-sm); }
.res-linha .rl-rot { color: var(--texto-secundario); }
.res-linha .rl-val { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }

.res-total { border-top: 1px solid var(--borda); padding-top: var(--sp-3); }
.res-total .rl-rot { font-weight: 700; color: var(--texto); }
.res-total .rl-val { font-family: var(--font-titulo); font-size: var(--fs-xl); }

.res-hoje .res-total .rl-val { color: var(--cor-primaria-texto); }
.res-alvo .res-total .rl-val { color: var(--cor-acento-texto); }

.res-frase { font-size: var(--fs-sm); line-height: 1.5; color: var(--texto-secundario); }
.res-frase strong { color: var(--texto); }

.res-medidor { display: flex; flex-direction: column; gap: 6px; }
.res-medidor .md-trilho { height: 10px; background: var(--borda); border-radius: var(--raio-pill); overflow: hidden; }
.res-medidor .md-preenche { height: 100%; border-radius: var(--raio-pill); background: var(--cor-primaria); transition: width var(--transicao); }
.res-medidor.abaixo .md-preenche { background: var(--perigo); }
.res-medidor .md-nota { font-size: var(--fs-xs); color: var(--texto-secundario); }

/* estado vazio do filtro: a tabela existe, o filtro não achou nada */
.vz-inline { padding: var(--sp-6) var(--sp-4); text-align: center; color: var(--texto-suave); font-size: var(--fs-sm); }

/* ---------------------------------------------------------------- Bloco C
   Cabecalho de secao e barra de filtros.

   Duas coisas que o 8282 nao tem porque as telas dele sao de uma pergunta so:
   uma tabela por tela, sem secao intermediaria, e o filtro morando dentro da
   propria tabela (.tabela-filtros). Aqui o Panorama e uma tela longa -- filtros,
   KPIs, comparacao e tabela -- e sem separador visual ela vira uma parede.
   Nenhum hex aqui: so token. -------------------------------------------- */

.secao {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: var(--sp-6) 0 var(--sp-4);
}

.secao:first-child { margin-top: 0; }

.secao-titulo {
  font-family: var(--font-titulo);
  font-size: var(--fs-lg);
  font-weight: 700;
  color: var(--texto);
  margin: 0;
}

.secao-sub {
  font-size: 13px;
  color: var(--texto-secundario);
  margin: 0;
  max-width: 80ch;
}

/* Linha de filtros: cada .campo cresce ate caber, e quebra em vez de espremer.
   minmax de 180px porque abaixo disso o nome de fornecedor nao cabe na caixa. */
.filtros {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--sp-3) var(--sp-4);
  align-items: end;
}

/* Campo que precisa da largura toda da grade de .filtros (ex.: um checkbox com
   frase longa), em vez de disputar coluna com os outros campos da linha. */
.filtros > .campo-linha-inteira { grid-column: 1 / -1; }

.filtros-acoes {
  display: flex;
  gap: var(--sp-2);
  align-items: center;
  flex-wrap: wrap;
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--borda);
}

/* Empurra o que vier depois pra direita da barra. */
.filtros-acoes .espaco { flex: 1; }

/* ------------------------------------------------- Bloco D: tela Simulador
   Tres coisas que so esta tela precisa. Nada aqui e generico o bastante pra
   virar componente da casa -- se virar, sobe pro bloco de cima. */

.sim-pilha { display: flex; flex-direction: column; gap: var(--sp-5); }

/* O cartao que diz DE QUE item ou categoria e a conta fica ao lado das caixas
   de escolha, e nao um card inteiro abaixo: as duas coisas respondem a mesma
   pergunta, e separadas obrigavam a rolar a tela pra conferir se o produto
   escolhido era o certo (pedido do dono, 14/09/2026). Sem nada escolhido a
   segunda coluna nem existe, e as caixas ficam com a largura toda. */
.sim-topo {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-5);
  align-items: start;
}

.sim-topo.com-detalhe { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }

@media (max-width: 1050px) {
  .sim-topo.com-detalhe { grid-template-columns: minmax(0, 1fr); }
}

/* Os dois precos, lado a lado e alinhados pelo topo -- cada um leva a chave
   que o qualifica logo abaixo, e as chaves tem alturas iguais. */
.mesa-campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--sp-4);
  align-items: start;
  margin-bottom: var(--sp-4);
}

/* A aliquota da CBS e a unica caixa desta tela que nao carrega um dado: carrega
   um palpite. Nao ha aliquota oficial ainda e o resultado inteiro pende dela,
   entao ela sai da fileira dos precos (era ali que o alinhamento quebrava, com
   os vizinhos mais altos por causa das chaves) e ganha faixa propria, em
   laranja claro, com o aviso colado. Sexta familia laranja do projeto -- ver
   CHECKLIST_APLICACAO.md: entra na regra porque a pergunta e sobre 2027. */
.campo-estimativa {
  background: var(--cor-acento-suave);
  border: 1px solid var(--cor-acento);
  border-radius: var(--raio-sm);
  padding: var(--sp-3) var(--sp-4);
}

.campo-estimativa > label { color: var(--cor-acento-texto); }

.ce-linha {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

.ce-linha .input { width: 150px; flex: 0 0 auto; }

.ce-nota {
  flex: 1;
  min-width: 260px;
  display: flex;
  gap: 8px;
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--cor-acento-texto);
}

.ce-nota i { flex: 0 0 auto; font-size: 15px; }
