:root {
  --bg: #f5f6f8;
  --panel: #ffffff;
  --border: #dde1e6;
  --text: #1f2430;
  --text-muted: #6b7280;
  --primary: #2563a6;
  --primary-dark: #1c4d80;
  --danger: #b3392c;
  --success-bg: #e6f4ea;
  --success-text: #1e6b3a;
  --error-bg: #fbe9e7;
  --error-text: #a8342a;
  --aviso-bg: #fff8dc;
  --aviso-borda: #f0dfa0;
  --radius: 6px;
  --campo-altura: 44px; /* altura padrão dos campos/botões — mesmo valor em qualquer dispositivo (touch-safe) */
  --input-bg: #ffffff;
  --input-border: #dde1e6;
  --focus-glow: rgba(37, 99, 166, 0.15);
  --label-gap: 5px;
  --campo-gap: 16px;
  --barra-fundo: var(--primary-dark);
  --barra-borda: transparent;
  --barra-texto: #ffffff;
  font-size: 15px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background-color: var(--bg);
  /* --bg-imagem (Parâmetro "Imagem de Fundo") tem prioridade sobre o
     gradiente do tema (--bg-gradiente) quando as duas existem. */
  background-image: var(--bg-imagem, var(--bg-gradiente, none));
  background-size: cover;
  background-position: center;
  background-attachment: fixed;
  background-repeat: no-repeat;
  color: var(--text);
  font-family: "Segoe UI", "Inter", system-ui, -apple-system, sans-serif;
}

.topbar {
  background: var(--barra-fundo);
  color: var(--barra-texto);
  border-bottom: 1px solid var(--barra-borda);
  padding: 12px 24px;
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.topbar__brand { font-weight: 700; letter-spacing: 0.04em; }
/* Versão ao lado da marca: precisa ser LEGÍVEL (é para ser conferida) e ao
   mesmo tempo não competir com "GRPW" — daí o peso normal, o tamanho menor e
   a opacidade. `tabular-nums` para o número não dançar entre builds. */
.topbar__versao {
  font-weight: 400; font-size: 0.72em; letter-spacing: 0.02em;
  opacity: 0.75; margin-left: 4px; font-variant-numeric: tabular-nums;
  cursor: help;
}
.topbar__crumb { color: var(--barra-texto); opacity: 0.85; font-size: 0.9em; }
/* Empresa da sessão (24/08/2026) — alinhada à ESQUERDA, logo depois da marca,
   antes do caminho da tela. Separada por uma barra vertical em vez de mais um
   `gap`: com marca, empresa e trilha em sequência, sem a divisa o cabeçalho
   vira uma fileira de textos sem hierarquia. `min-width:0` + `ellipsis` na
   razão social porque ela pode ser longa e não pode empurrar o resto da
   barra. O CNPJ usa tabular-nums para não "dançar" ao trocar de filial. */
.topbar__empresa {
  display: inline-flex; align-items: baseline; gap: 2px 8px; min-width: 0;
  padding-left: 12px; border-left: 1px solid rgba(255,255,255,0.28);
  /* `wrap` para a validade do certificado cair na LINHA DE BAIXO, sob o
     nome da filial — o `flex-basis: 100%` dela é quem força a quebra. */
  flex-wrap: wrap;
}
.topbar__empresa-nome {
  font-weight: 600; font-size: 0.9em; max-width: 34ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.topbar__empresa-cnpj {
  font-size: 0.8em; opacity: 0.8; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* VALIDADE DO CERTIFICADO DIGITAL (25/08/2026) — segunda linha do bloco da
   empresa. A cor é o recado: quem passa os olhos na barra tem que perceber a
   urgência sem ler a data. Vencido pisca em branco porque, ao contrário dos
   outros três estados, ele não é um aviso: é uma transmissão que já não
   funciona. */
.topbar__cert {
  flex-basis: 100%;              /* joga para a linha debaixo do nome */
  font-size: 0.74em; font-weight: 600; letter-spacing: 0.02em;
  white-space: nowrap; font-variant-numeric: tabular-nums; line-height: 1.1;
}
.topbar__cert--ativo   { color: #7ee29a; }
.topbar__cert--atencao { color: #ffd75e; }
.topbar__cert--critico { color: #ff8a80; }
.topbar__cert--vencido {
  color: #ffffff; animation: cert-pisca 1s steps(1, end) infinite;
}
@keyframes cert-pisca {
  0%, 49%  { opacity: 1; }
  50%, 100% { opacity: 0.15; }
}
/* Quem configurou o sistema para reduzir animação não perde o aviso: em vez
   de piscar, o vencido ganha fundo sólido. */
@media (prefers-reduced-motion: reduce) {
  .topbar__cert--vencido {
    animation: none; background: #b3261e; padding: 0 6px; border-radius: 3px;
  }
}

/* Na tela de LOGIN a empresa vai para a direita: ali o lado esquerdo tem só
   "GRPW / Login" e o direito está inteiramente vazio (sem seletor de filial,
   sem operador). A divisa muda de lado junto. */
.topbar__empresa--direita {
  /* sem divisa: ali ela não separa nada — ficaria uma barra solta no canto */
  border-left: none; padding-left: 0; padding-right: 2px;
}
@media (max-width: 900px) {
  /* em tela estreita o CNPJ sai e fica só o nome — a identificação continua,
     sem competir com o seletor de filial e o operador */
  .topbar__empresa-cnpj { display: none; }
  .topbar__empresa-nome { max-width: 20ch; }
  /* o certificado fica: é aviso, não identificação — o que sai é o CNPJ */
}
.topbar__spacer { flex: 1; }
.topbar__link {
  color: var(--barra-texto); opacity: 0.85; font-size: 0.82rem; text-decoration: none; margin-right: 6px;
}
.topbar__link:hover { color: var(--barra-texto); opacity: 1; text-decoration: underline; }
.topbar__operador {
  color: var(--barra-texto); opacity: 0.85; font-size: 0.82rem; font-weight: 600;
  letter-spacing: 0.02em;
}
.topbar__logout {
  color: var(--barra-texto); font-size: 0.82rem; text-decoration: none;
  border: 1px solid var(--barra-texto); border-radius: var(--radius);
  padding: 4px 10px;
}
.topbar__logout:hover { background: rgba(255,255,255,0.12); }

.barra-ferramentas {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  background: #eef1f5; border-bottom: 1px solid var(--border);
  padding: 6px 20px;
}
.barra-ferramentas-btn {
  align-items: center; gap: 4px;
  padding: 6px 12px; font-size: 0.82rem; font-weight: 600;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  color: var(--text); cursor: pointer; text-decoration: none;
}
/* Mesmo bug de especificidade CSS documentado no CLAUDE.md 2.4 (recorrente):
   a classe .barra-ferramentas-btn ganhava do atributo [hidden] por serem
   mesma especificidade — o botão "aparecia" mesmo escondido. Achado
   11/08/2026 testando a barra padrão na tela de Notas Fiscais; afeta toda
   tela que já usa este componente (Produtos, Pessoas, etc.), não só esta. */
.barra-ferramentas-btn:not([hidden]) { display: inline-flex; }
.barra-ferramentas-btn[hidden] { display: none; }
.barra-ferramentas-btn:hover { background: #f7f9fb; border-color: var(--primary); }
.barra-ferramentas-btn--perigo { color: var(--danger); }
.barra-ferramentas-dropdown { position: relative; }
.barra-ferramentas-dropdown summary { list-style: none; cursor: pointer; }
.barra-ferramentas-dropdown summary::-webkit-details-marker { display: none; }
.barra-ferramentas-dropdown ul {
  position: absolute; top: 100%; left: 0; z-index: 20; margin-top: 4px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  list-style: none; padding: 4px 0; box-shadow: 0 4px 12px rgba(0,0,0,0.1);
  /* `width:max-content` (14/08/2026) — antes era `min-width:160px` fixo,
     estreito demais pros rótulos mais longos (ex.: "Composição de
     Custos", "Disponibilidade dos Serviços (SEFAZ)"), que quebravam em
     2 linhas com `white-space:nowrap` abaixo cortando o texto. Agora a
     largura acompanha o conteúdo mais longo (incluindo o sub-nível
     aninhado, que soma na largura porque é `position:static`/inline),
     com teto pra nunca estourar a viewport numa tela estreita. */
  width: max-content; min-width: 220px; max-width: min(92vw, 480px); /* 480px (15/08/2026): rótulos longos do menu Ferramentas reordenado ("Geração de Notas Fiscais a partir de Pedidos do GRP Mobile") estouravam 360px */
}
/* Cor azul (`--primary`, não `--text`) de propósito (03/08/2026) — em
   Mapa Resumo de Caixa o usuário confundiu mais de uma vez itens
   HABILITADOS do dropdown "Rotinas" com os desabilitados (`--text` e
   `--text-muted` ficavam parecidos demais numa captura de tela
   comprimida). Azul = "isto é um link" é um sinal bem mais universal e
   não depende de calibração de tela/print pra distinguir do cinza dos
   itens desabilitados abaixo. */
.barra-ferramentas-dropdown li a { display: block; padding: 6px 14px; color: var(--primary); text-decoration: none; font-size: 0.85rem; white-space: nowrap; }
.barra-ferramentas-dropdown li a:hover { background: #f0f1f3; text-decoration: underline; }
/* Item do dropdown que precisa de POST (Estornar/Cancelar) em vez de
   navegação simples — mesmo visual de `li a`, mas é um <button> dentro de
   um <form> próprio (CLAUDE.md 2.13: forms independentes, nunca cruzados). */
.barra-ferramentas-dropdown li form { margin: 0; }
.barra-ferramentas-dropdown li button {
  display: block; width: 100%; text-align: left; padding: 6px 14px;
  color: var(--primary); text-decoration: none; font-size: 0.85rem;
  background: none; border: 0; cursor: pointer; font-family: inherit; white-space: nowrap;
}
.barra-ferramentas-dropdown li button:hover { background: #f0f1f3; text-decoration: underline; }
.barra-ferramentas-dropdown li hr { border: 0; border-top: 1px solid var(--border); margin: 4px 0; }
/* Item DESABILITADO do dropdown (15/08/2026, menu Ferramentas de Notas
   Fiscais reordenado item a item contra o PopupMenu do VB6): itens sem
   equivalente Flask ou indisponíveis no estado atual da nota aparecem
   cinza e sem link, com `title` explicando o motivo — como o VB6 mostra
   vários itens em cinza conforme o estado (Calcular/Cancelamento etc.). */
.barra-ferramentas-dropdown li .barra-ferramentas-item--desabilitado,
.barra-ferramentas-dropdown .barra-ferramentas-dropdown--sub > summary.barra-ferramentas-item--desabilitado {
  display: block; padding: 6px 14px; font-size: 0.85rem; white-space: nowrap;
  color: #9aa2ad; cursor: not-allowed; opacity: .8;
}

/* Variante "alinha à direita" (14/08/2026) — pra botão perto da borda
   direita da tela (ex.: "Ferramentas" no cabeçalho de Notas Fiscais):
   o padrão `left:0` faz o dropdown crescer PRA DIREITA a partir do
   botão, estourando a viewport quando o botão já está colado na borda.
   Aqui a borda DIREITA do dropdown alinha com a borda direita do botão
   (cresce pra esquerda) — escopado nesta classe própria, não no seletor
   base, porque outros usos de `.barra-ferramentas-dropdown` (Imprimir em
   telas com o botão mais à esquerda, Rotinas de Mapa Resumo de Caixa)
   continuam corretos com `left:0`. */
.barra-ferramentas-dropdown--alinhar-direita > ul { left: auto; right: 0; }

/* Sub-nível dentro de um dropdown (14/08/2026, menu "Ferramentas" de
   Notas Fiscais — recriação fiel do agrupamento por nível/subnível do
   PopupMenu `cmdOPCOES` real do VB6, ex.: "Integração de Arquivos ▸").
   Mesma estratégia já usada e testada no `.mainnav` (CLAUDE.md): só o
   dropdown de PRIMEIRO NÍVEL vira flyout flutuante (`position:absolute`);
   o `<details>` aninhado dentro dele expande INLINE, senão empilhar
   `position:absolute` em vários níveis vira bagunça visual. Precisa de
   `<li>` em volta do `<details>` aninhado (mesma estrutura do mainnav)
   pra herdar o espaçamento vertical de item de lista normalmente. */
.barra-ferramentas-dropdown .barra-ferramentas-dropdown--sub { position: static; }
.barra-ferramentas-dropdown .barra-ferramentas-dropdown--sub > summary {
  display: block; padding: 6px 14px; font-size: 0.85rem; font-weight: 600;
  color: var(--text); cursor: pointer; list-style: none; white-space: nowrap;
}
.barra-ferramentas-dropdown .barra-ferramentas-dropdown--sub > summary::-webkit-details-marker { display: none; }
.barra-ferramentas-dropdown .barra-ferramentas-dropdown--sub > summary::after { content: " ▾"; font-size: 0.7em; color: var(--text-muted); }
.barra-ferramentas-dropdown .barra-ferramentas-dropdown--sub[open] > summary { color: var(--primary); }
.barra-ferramentas-dropdown .barra-ferramentas-dropdown--sub > ul {
  position: static; margin: 0; padding: 0 0 4px 16px; min-width: 0; max-height: none;
  background: none; border: none; box-shadow: none;
}

/* Variante "abre pra cima" (03/08/2026) — pra dropdowns colados na base
   de um `.panel` (que tem `overflow: hidden`, cortando o `<ul>` quase
   inteiro se ele abrir pra baixo perto da borda). Usada em Mapa Resumo
   de Caixa (botões do rodapé) — achado real reportado pelo usuário. */
.barra-ferramentas-dropdown--cima ul { top: auto; bottom: 100%; margin-top: 0; margin-bottom: 4px; }

.mainnav {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px;
  background: var(--panel); border-bottom: 1px solid var(--border);
  padding: 0 24px;
  position: relative;
}
.mainnav a {
  display: inline-block; padding: 12px 14px; font-size: 0.88rem;
  font-weight: 600; color: var(--text-muted); text-decoration: none;
  border-bottom: 2px solid transparent;
}
.mainnav a:hover { color: var(--primary); border-bottom-color: var(--border); }

.mainnav__raiz { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; list-style: none; margin: 0; padding: 0; }
.mainnav__raiz > li { position: relative; }

/* MENU EXPANDIDO EM PAINEL (23/08/2026) — substitui o dropdown aninhado.
   Cada categoria de 1º nível abre um painel com TODOS os seus itens à
   vista, em colunas por subcategoria: o operador enxerga o sistema inteiro
   de um golpe em vez de caçar submenu por submenu. Cada item traz seu
   número, e digitar o número salta o foco direto pra ele (ver base.html). */
.mainnav__menu { position: relative; }
.mainnav__botao {
  display: inline-block; padding: 12px 14px; font-size: 0.88rem;
  font-weight: 600; color: var(--text-muted); cursor: pointer;
  background: none; border: none; font-family: inherit;
}
.mainnav__botao::after { content: " ▾"; font-size: 0.7em; }
.mainnav__botao:hover { color: var(--primary); }
.mainnav__botao[aria-expanded="true"] { color: var(--primary); background: var(--panel); }

/* `display:grid` numa classe vence `[hidden]` por especificidade — a
   armadilha que já mordeu este projeto 4 vezes (§2.4). O par abaixo é a
   forma correta: só declara display quando NÃO está escondido. */
.mainnav__painel:not([hidden]) { display: grid; }
.mainnav__painel[hidden] { display: none; }
.mainnav__painel {
  position: absolute; top: 100%; left: 0; z-index: 30;
  background: var(--panel); border: 1px solid var(--border);
  border-top: none; border-radius: 0 0 var(--radius) var(--radius);
  box-shadow: 0 14px 34px rgba(0,0,0,0.14);
  padding: 16px 18px; gap: 0 26px; align-items: start;
  /* Nenhum painel pode passar da tela: o Fiscal tem 68 itens e sairia pela
     borda de baixo num monitor comum. Rola dentro do próprio painel. */
  max-height: min(74vh, 620px); overflow-y: auto;
}
/* Fluxo em COLUNAS (não grade): com grade, uma coluna curta ("Estoque", 1
   item) deixava um buraco do tamanho da linha inteira. Em `columns` os
   grupos empacotam um embaixo do outro e a coluna quebra onde couber. */
.mainnav__painel[data-colunas="1"] { grid-template-columns: minmax(260px, 1fr); }
.mainnav__painel[data-colunas="2"] { grid-template-columns: repeat(2, minmax(250px, 1fr)); width: min(92vw, 620px); }
.mainnav__painel[data-colunas="3"] { grid-template-columns: repeat(3, minmax(240px, 1fr)); width: min(94vw, 900px); }
.mainnav__pilha { display: flex; flex-direction: column; gap: 14px; min-width: 0; }

.mainnav__coluna h4 {
  margin: 0 0 6px; font-size: 0.7rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-muted); font-weight: 600;
  border-bottom: 1px solid var(--border); padding-bottom: 5px;
}
.mainnav__subgrupo { margin-top: 8px; }
.mainnav__subgrupo h5 {
  margin: 0 0 3px; font-size: 0.72rem; color: var(--text-muted); font-weight: 600;
  padding-left: 8px;
}
.mainnav__itens { list-style: none; margin: 0; padding: 0; }
/* `.mainnav a` (0,1,1) vence `.mainnav__item` (0,1,0) por especificidade e
   devolvia o padding de 12px e o peso 600 da barra de topo pros itens do
   painel — com 68 itens abertos isso vira uma parede. Por isso a regra do
   item precisa carregar o mesmo peso de seletor. */
.mainnav .mainnav__item,
.mainnav a.mainnav__item {
  display: flex; align-items: baseline; gap: 8px;
  padding: 4px 8px; border-radius: 4px; font-size: 0.84rem; font-weight: 500;
  color: var(--text); text-decoration: none; border-bottom: none;
}
.mainnav a.mainnav__item:hover, .mainnav .mainnav__item--alvo {
  background: var(--focus-glow); color: var(--primary); border-bottom-color: transparent;
}
/* Item alcançado pela digitação do número — precisa saltar aos olhos mais
   que um hover comum, porque o operador não está com o mouse nele. */
.mainnav__item--alvo {
  outline: 2px solid var(--primary); outline-offset: -2px; background: var(--panel-2, #eaf1f9);
}
.mainnav__num {
  flex: 0 0 auto; min-width: 2.2em; text-align: right;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: 0.72rem; color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.mainnav__rotulo { flex: 1 1 auto; }
.mainnav__desabilitado { color: #c2c6cc; cursor: default; user-select: none; }
.mainnav__desabilitado .mainnav__num { color: #d5d8dd; }
.mainnav__separador { border-top: 1px solid var(--border); margin: 4px 8px; }
.mainnav__direita { margin-left: auto; display: flex; align-items: center; gap: 2px; }
.mainnav .mainnav__link-direita {
  padding: 12px 12px; font-size: 0.86rem; font-weight: 600;
  color: var(--text-muted); text-decoration: none; border-bottom: 2px solid transparent;
}
.mainnav .mainnav__link-direita:hover { color: var(--primary); }

/* LUPA DO MENU (01/09/2026) — pesquisa de item por código e por descrição.
   Fica à ESQUERDA da linha (primeiro filho da `.mainnav`, que é flex), antes
   da primeira categoria: é por onde se começa quando não se sabe para onde
   ir. O salto por número atende quem decorou o código; esta atende quem
   lembra do nome, ou de parte dele. */
.mainnav__lupa { position: relative; flex: 0 0 auto; }
.mainnav__lupa-botao {
  display: inline-block; padding: 10px 12px; font-size: 1rem; line-height: 1;
  background: none; border: none; cursor: pointer; font-family: inherit;
  color: var(--text-muted); border-radius: 4px;
}
.mainnav__lupa-botao:hover { color: var(--primary); background: var(--focus-glow); }
.mainnav__lupa-botao[aria-expanded="true"] { color: var(--primary); background: var(--panel); }

/* O par do §2.4: a classe declara `display`, então ela vence `[hidden]` por
   especificidade e o painel nasceria aberto sem esta segunda linha. */
.mainnav__lupa-painel:not([hidden]) { display: block; }
.mainnav__lupa-painel[hidden] { display: none; }
.mainnav__lupa-painel {
  position: absolute; top: 100%; left: 0; z-index: 40;
  width: min(92vw, 460px);
  background: var(--panel); border: 1px solid var(--border); border-top: none;
  border-radius: 0 0 var(--radius) var(--radius);
  box-shadow: 0 14px 34px rgba(0,0,0,0.14);
  padding: 10px;
}
/* Altura e fonte declaradas aqui porque a barra de menu NÃO está sob
   `tela-compacta` (§2.33 mira o campo dentro do corpo da tela, e o menu vive
   no cabeçalho, fora dela). */
.mainnav__lupa-campo {
  width: 100%; box-sizing: border-box; height: 32px;
  padding: 5px 9px; font-size: .86rem; font-family: inherit;
  border: 1px solid var(--border); border-radius: 4px; background: var(--bg, #fff);
  color: var(--text);
}
.mainnav__lupa-campo:focus { outline: 2px solid var(--primary); outline-offset: -1px; }

.mainnav__lupa-lista {
  list-style: none; margin: 8px 0 0; padding: 0;
  max-height: min(60vh, 420px); overflow-y: auto;
}
.mainnav__lupa-linha {
  display: flex; align-items: baseline; gap: 8px;
  padding: 5px 8px; border-radius: 4px; cursor: pointer; font-size: .84rem;
}
.mainnav__lupa-linha:hover,
.mainnav__lupa-linha--alvo { background: var(--focus-glow); color: var(--primary); }
.mainnav__lupa-linha--alvo { outline: 2px solid var(--primary); outline-offset: -2px; }
.mainnav__lupa-num {
  flex: 0 0 auto; min-width: 2.2em; text-align: right;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: .72rem; color: var(--text-muted); font-variant-numeric: tabular-nums;
}
/* `min-width: 0` porque um caminho longo ("Fiscal › Movimentações › …") num
   flex sem isso empurra a linha e faz o painel rolar na horizontal. */
.mainnav__lupa-texto { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.mainnav__lupa-texto b { font-weight: 600; }
.mainnav__lupa-texto small { font-size: .72rem; color: var(--text-muted); }
/* Tela ainda não migrada aparece — é a mesma informação que o menu dá em
   cinza. Sumir com ela faria a busca responder "não existe" para o que
   existe no produto (§1.3). */
.mainnav__lupa-linha--indisponivel { color: #c2c6cc; }
.mainnav__lupa-linha--indisponivel b { font-weight: 500; }
.mainnav__lupa-linha em {
  flex: 0 0 auto; font-size: .68rem; font-style: normal;
  color: #c2c6cc; white-space: nowrap;
}
.mainnav__lupa-vazio { padding: 10px 8px; font-size: .82rem; color: var(--text-muted); }

/* Indicador do número que está sendo digitado */
.mainnav__digitando:not([hidden]) { display: flex; }
.mainnav__digitando[hidden] { display: none; }
.mainnav__digitando {
  position: fixed; right: 22px; bottom: 22px; z-index: 60;
  align-items: center; gap: 10px;
  background: var(--primary); color: #fff; padding: 10px 16px;
  border-radius: var(--radius); box-shadow: 0 8px 22px rgba(0,0,0,.22);
  font-size: .9rem;
}
.mainnav__digitando b {
  font-family: ui-monospace, Consolas, monospace; font-size: 1.15rem;
  font-variant-numeric: tabular-nums; letter-spacing: .04em;
}
.mainnav__digitando span { opacity: .9; font-size: .82rem; }

@media (max-width: 639px) {
  .mainnav__painel { position: static; box-shadow: none; border: none; max-height: none;
                     grid-template-columns: 1fr !important; width: auto !important; padding: 8px 10px; }
  .mainnav__direita { margin-left: 0; }
}

/* flex-wrap adicionado em 08/08/2026 — sem isto, uma barra de ações com
   muitos botões (comum em telas "documento com estado" tipo Gestão de
   Inventários, que ganhou vários botões novos: Configurações/Gerar
   Informações Complementares/Exportar) simplesmente transborda a página
   em telas estreitas, em vez de quebrar linha. */
.panel__head-acoes { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

.dropdown-imprimir { position: relative; }
.dropdown-imprimir summary { cursor: pointer; list-style: none; }
.dropdown-imprimir summary::-webkit-details-marker { display: none; }
.dropdown-imprimir ul {
  position: absolute; top: 100%; right: 0; z-index: 30; margin-top: 4px;
  list-style: none; padding: 6px 0; min-width: 170px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 6px 16px rgba(0,0,0,0.1);
}
.dropdown-imprimir ul li a {
  display: block; padding: 9px 16px; font-size: 0.88rem; font-weight: 500;
  color: var(--text); text-decoration: none; white-space: nowrap;
}
.dropdown-imprimir ul li a:hover { background: #f0f1f3; }

.produtos-cabecalho {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px 16px;
  grid-column: 1 / -1; padding-bottom: 8px; margin-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.cadastro-generico-fieldset {
  display: contents;
}
.produtos-ref-unidade-setor-linha {
  display: grid; grid-template-columns: 160px 110px 1fr 120px;
  gap: 4px 16px; grid-column: 1 / -1;
}
/* Cabeçalho do cadastro de Produtos, reordenado a pedido do usuário em
   25/08/2026: identificação numa linha só (o Código é estreito e a Data
   também; a Referência fica com a folga), e os quatro lookups compactos
   — NCM, Embalagem, Marca e Setor de Balança — juntos numa fileira. */
.produtos-cabecalho-linha1 {
  /* Larguras pedidas pelo usuário em 25/08/2026, a partir das anteriores:
     Código −40% (110→66), Data de Cadastro −30% (130→91), Referência igual à
     Data já reduzida (91), Unidade de Venda −60% (145→58). A Descrição fecha
     a fileira e fica com TODO o resto (`1fr`). */
  /* A Unidade cresceu de 58 para 78px em 25/08/2026: com 58 o `select`
     cortava o valor de duas letras ("UN" virava "UI") — a seta do combo
     come ~20px. Os rótulos viraram "Cadastro" e "Unidade" na mesma rodada,
     e com isso nenhum quebra mais em duas linhas. */
  display: grid; grid-template-columns: 66px 91px 91px 78px 1fr;
  gap: 4px 16px; grid-column: 1 / -1;
  /* Os campos começam todos na MESMA altura, mesmo com rótulo de 1, 2 ou 3
     linhas (25/08/2026). Não se "adivinha" altura de rótulo: com
     `display: contents` nos campos, rótulos e caixas passam a ocupar linhas
     de grade PRÓPRIAS e compartilhadas entre as colunas — a linha 1 é a dos
     rótulos, a 2 a dos campos. Mesma técnica de `ncm-linha-4--rotulo-alinhado`,
     que nasceu do mesmo problema em outra tela. */
  grid-template-rows: auto auto;
  align-items: start;
}
.produtos-cabecalho-linha1 > .form__field { display: contents; }
.produtos-cabecalho-linha1 > .form__field label { grid-row: 1; min-height: 0; align-self: end; }
.produtos-cabecalho-linha1 > .form__field input,
.produtos-cabecalho-linha1 > .form__field select { grid-row: 2; }
/* Preços de Concorrentes: os quatro campos e o botão de incluir numa
   fileira só (25/08/2026). O botão fica na última coluna, do tamanho do
   texto — não do tamanho da coluna —, alinhado com os campos. */
.produtos-concorrente-linha {
  /* Larguras pelo CONTEÚDO (25/08/2026): um preço e duas datas não precisam
     de um quarto da linha cada. As datas ficam com 140px — o mínimo que o
     campo nativo aceita com o ícone de calendário é 126px, medido no
     navegador — e o preço com 130px. Todo o excedente vai para o
     Concorrente, que é um NOME de pessoa e tinha o mesmo espaço de um campo
     de 7 caracteres. */
  display: grid; grid-template-columns: 1fr 130px 140px 140px auto;
  gap: 4px 16px; grid-column: 1 / -1; align-items: end;
}
.produtos-concorrente-linha > .form__field { min-width: 0; }
.produtos-concorrente-botao {
  padding: 8px 14px; font-size: 0.85rem; white-space: nowrap; width: auto;
}
@media (max-width: 900px) {
  .produtos-concorrente-linha { grid-template-columns: 1fr 1fr; }
}

/* Unidades Alternativas de Venda: dois campos e o botão, todos encostados
   à ESQUERDA e alinhados pela base (25/08/2026). Aqui não se usa grade de
   colunas iguais — com dois campos só, esticar até a borda direita deixaria
   o botão longe de quem o usa. */
.produtos-unidade-alt-linha {
  display: flex; flex-wrap: wrap; align-items: end; gap: 4px 16px;
  grid-column: 1 / -1;
}
.produtos-unidade-alt-linha > .form__field { flex: 0 0 auto; min-width: 0; }
.produtos-unidade-alt-linha > .form__field:nth-child(2) { flex: 0 0 220px; }

/* Tipo de Item, Classificação Mercadológica e Gênero de Item na mesma
   fileira, com a largura proporcional ao tamanho MEDIDO das descrições de
   cada cadastro (média 15 / 10,6 / 67,4 caracteres). O `minmax` põe um piso:
   proporção pura deixaria os dois primeiros pequenos demais para ler. */
/* IPI (complemento): os três numa fileira. As larguras seguem o tamanho do
   campo — 3 e 5 caracteres nos dois primeiros, 60 no Selo de Controle. */
.produtos-ipi-linha {
  display: grid; grid-template-columns: minmax(200px, 1fr) minmax(210px, 1fr) minmax(300px, 3fr);
  gap: 4px 16px;
}
.produtos-ipi-linha > .form__field { min-width: 0; }
@media (max-width: 900px) {
  .produtos-ipi-linha { grid-template-columns: 1fr; }
}

/* Informações para a Balança: os quatro campos e as duas flags numa fileira
   só (25/08/2026). As flags são estreitas e ficam alinhadas pela BASE, na
   altura dos campos — por isso `align-items: end` e o rótulo vazio que elas
   não têm sai do caminho com `align-self`. */
.produtos-balanca-linha {
  display: grid;
  grid-template-columns: minmax(230px, 1.4fr) minmax(110px, .8fr) auto minmax(110px, .8fr) auto minmax(110px, .8fr);
  gap: 4px 16px; align-items: end;
}
.produtos-balanca-linha > .form__field { min-width: 0; }
.produtos-balanca-linha > .form__field--checkbox { padding-bottom: 9px; }
@media (max-width: 1200px) {
  .produtos-balanca-linha { grid-template-columns: repeat(2, 1fr); }
}

/* Similaridade (8cm, pedido do usuário) e Estoques lado a lado. Os cinco
   campos de estoque cabem no que sobra porque são números curtos — o maior
   valor da base tem 8 caracteres. */
/* Rótulo colado no seu texto — REGRA GERAL DO SISTEMA (25/08/2026).
   Nasceu na tela de Produtos, quando o usuário notou que o "Código" da
   Similaridade ficava mais perto do campo que o "Trocas" dos Estoques; ele
   gostou do resultado e pediu para valer em todo o sistema.

   A diferença vinha da regra logo acima
   (`.ncm-linha-4/5 > .form__field label { min-height: 2.6em }`), que reserva
   DUAS linhas de rótulo mesmo quando só uma é usada — 33px contra os 15px de
   um rótulo solto. A reserva existia para alinhar os campos quando um rótulo
   quebra e os vizinhos não, e é isso que `align-items: end` passa a resolver:
   cada campo é encostado na BASE da fileira, então as caixas ficam alinhadas
   mesmo com rótulos de alturas diferentes.

   Medido antes de generalizar, injetando a regra no navegador em cada tela
   que usa estas fileiras: NENHUMA piorou, as fileiras desalinhadas caíram de
   5 para 2 (o filtro de Produtos tinha 4) e os rótulos que reservavam duas
   linhas caíram de 79 para 4.

   Preferida à técnica de `display: contents` do cabeçalho de Produtos porque
   convive com `.form__field--full`, que existe em várias telas e às vezes no
   MEIO da fileira — com `contents` ele perderia o `grid-column: 1 / -1`. */
.ncm-linha-4,
.ncm-linha-5 { align-items: end; }

.produtos-similaridade-estoques {
  display: grid; grid-template-columns: 8cm 1fr; gap: 0 16px;
  align-items: start; grid-column: 1 / -1;
}
/* `grid-column: auto` desfaz o `1 / -1` que `.produtos-secao` traz de fábrica
   (ele existe para o quadro ocupar a linha inteira do formulário). Sem isto,
   cada um dos dois fieldsets continuava esticando por todas as colunas e eles
   ficavam um embaixo do outro, apesar da grade de duas colunas. */
.produtos-similaridade-estoques > .produtos-secao { grid-column: auto; min-width: 0; }
.produtos-similaridade-estoques .ncm-linha-5 { gap: var(--campo-gap) 8px; }
@media (max-width: 1200px) {
  .produtos-similaridade-estoques { grid-template-columns: 1fr; }
}

.produtos-lookups-largos {
  display: grid;
  /* O piso não é estético: cada coluna gasta ~115px com o campo de código e
     a lupa, então uma coluna de 200px deixa 85px de descrição — e "MERCADORIA
     PARA REVENDA" vira "MERCADORI...". Os pisos abaixo garantem ~21 e ~17
     caracteres visíveis (o 90º percentil de cada cadastro), e a PROPORÇÃO
     entre as três só vale daí para cima, na sobra da tela. */
  /* A largura acompanha o CAMPO, não a posição: quando Gênero e
     Classificação trocaram de lugar (25/08/2026), as colunas trocaram
     junto — o Gênero continua com a fatia grande porque as descrições
     dele é que são longas. */
  /* A terceira coluna passou a ser o NCM (25/08/2026): descrição de 42
     caracteres em média, 90% até 101 — precisa de bem mais espaço que a
     Classificação, que saiu daqui (média 11). Daí 3fr contra os 6fr do
     Gênero (média 67), na mesma lógica de sempre: largura pelo conteúdo. */
  grid-template-columns: minmax(355px, 1.6fr) minmax(360px, 6fr) minmax(340px, 3fr);
  gap: 4px 16px; grid-column: 1 / -1;
}
.produtos-lookups-largos > .form__field { min-width: 0; }
/* Largura do CÓDIGO pelo que ele guarda (26/08/2026), em vez dos 70px que o
   sistema dá a todo lookup (~784): Gênero são 2 dígitos — a tabela
   `generoitem` tem 110 linhas e nenhuma passa disso — e o NCM são 8, que não
   cabiam nos 70px e apareciam cortados ("1006302…"). */
.produtos-lookups-largos .form__field[data-lookup-campo="generoitem"] .lookup-generico-codigo {
  flex: 0 0 42px; min-width: 42px;
}
.produtos-lookups-largos .form__field[data-lookup-campo="codigomercosul"] .lookup-generico-codigo {
  flex: 0 0 92px; min-width: 92px;
}
@media (max-width: 1100px) {
  .produtos-lookups-largos { grid-template-columns: 1fr; }
}

.produtos-cabecalho-lookups {
  /* 3 colunas desde 25/08/2026: o Setor de Balança foi para o quadro
     "Informações para a Balança", onde quem cuida da balança procura.
     As três colunas eram iguais; em 25/08/2026 o usuário pediu Embalagem e
     Marca 20% menores (1 -> 0,8), e a Classificação ficou com a sobra — que
     é justamente quem precisa, por causa do código composto de 14
     caracteres. Em `fr` a conta se fecha sozinha: a unidade é fração da
     linha, então os três continuam cabendo em qualquer largura de tela.
     O conteúdo confirma: Embalagem tem descrição de 6 caracteres em média
     (máx 10) e Marca 7,5 (máx 17) — sobrava espaço nas duas. */
  display: grid; grid-template-columns: 1.05fr 0.8fr 0.75fr;
  gap: 4px 16px; grid-column: 1 / -1;
}
.produtos-cabecalho-linha1 > .form__field,
.produtos-cabecalho-lookups > .form__field { min-width: 0; }
/* Largura do campo de CÓDIGO dentro da lupa, pedida pelo usuário em
   25/08/2026: Classificação Mercadológica +130% e Embalagem −30%, sobre os
   70px que TODOS os códigos têm por padrão.

   Tem de ser `flex-basis`, não `width`: o código vive num container flex
   (`.lookup-generico-linha`) governado por
   `.lookup-generico-codigo { flex: 0 0 70px }` — um `width` inline ali é
   ignorado em silêncio, e era o que acontecia com os `style="width:140px"`
   e `style="width:84px"` que estavam no HTML sem efeito nenhum.

   O conteúdo justifica: o código da Classificação é composto
   (ex. "0001.001.0001", 13 caracteres) e não cabia em 70px; o da Embalagem
   tem 2 ou 3 caracteres e sobrava espaço. */
/* `.form__field` no meio do seletor NÃO é decoração: sem ele o seletor
   empata em especificidade (0,3,0) com a regra genérica de 70px lá embaixo,
   e num empate vence a que vem DEPOIS no arquivo — ou seja, a genérica.
   Com ele são 0,4,0 e a regra específica ganha, independente da ordem. */
/* Largura medida, não estimada (25/08/2026): mediu-se com `measureText` na
   fonte real do campo quanto ocupa o MAIOR valor possível de cada cadastro —
   "0001.0001.0001" (14 car.) na Classificação e "1035" (4 car., o maior das
   36 marcas) na Marca —, e somou-se o padding e a borda. Sobrava 21px num e
   10px no outro; essa folga foi devolvida à descrição. */
/* Redução de 10% pedida em 25/08/2026 (144 -> 130 e 64 -> 58). Como o passo
   anterior já tinha tirado toda a folga, os 10% SÓ cabem com a fonte do
   código menor: a 14,25px o maior valor da Classificação ocupa 116px e
   sobrariam 106; a 12,8px passa a ocupar 104. Por isso a `font-size` desce
   junto — é o que mantém a outra exigência do pedido, "sem cortar o
   conteúdo". Vale só para estes dois campos de CÓDIGO; a descrição ao lado
   continua no tamanho normal. */
.produtos-cabecalho-lookups .form__field[data-lookup-campo="classificacaomercadologica"] .lookup-generico-codigo {
  flex: 0 0 130px; min-width: 130px; font-size: 0.8rem;
}
.produtos-cabecalho-lookups .form__field[data-lookup-campo="marca"] .lookup-generico-codigo {
  flex: 0 0 58px; min-width: 58px; font-size: 0.8rem;
}
.produtos-cabecalho-lookups .form__field[data-lookup-campo="embalagem"] .lookup-generico-codigo {
  flex: 0 0 49px; min-width: 49px;
}
@media (max-width: 900px) {
  .produtos-cabecalho-lookups { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 639px) {
  .produtos-cabecalho-linha1,
  .produtos-cabecalho-lookups { grid-template-columns: 1fr; }
}
.produtos-ref-unidade-setor-linha > .form__field { min-width: 0; }
@media (max-width: 639px) {
  .produtos-ref-unidade-setor-linha { grid-template-columns: 1fr; }
}
.lookup-field { grid-column: span 1; }
.lookup-linha { display: flex; gap: 6px; }
.lookup-linha input:first-child { flex: 0 0 90px; min-width: 0; }
.lookup-linha .campo-lookup-resultado {
  flex: 1; min-width: 0; background: #f0f1f3; color: var(--text-muted);
  font-style: italic; font-size: 0.85rem;
}

.produtos-abas-nav {
  grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: 2px;
  border-bottom: 2px solid var(--border); margin-bottom: 16px;
}
.produtos-aba-btn {
  padding: 10px 14px; font-size: 0.85rem; font-weight: 600;
  background: none; border: none; color: var(--text-muted); cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -2px;
}
.produtos-aba-btn:hover { color: var(--text); }
.produtos-aba-btn--ativa { color: var(--primary); border-bottom-color: var(--primary); }
.produtos-aba-btn--pendente { color: #c3c8d0; font-style: italic; }

.produtos-aba-conteudo { grid-column: 1 / -1; }



.produtos-secao {
  grid-column: 1 / -1; border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--campo-gap) 16px 4px; margin-bottom: var(--campo-gap);
}

/* Seções tipo "popup"/aviso (ex.: Registro Fiscal de Alteração de
   Descrição, em Produtos) — fundo amarelo claro pra se diferenciar
   visualmente do resto da tela, pedido do usuário em 08/08/2026. */
.produtos-confirmacao-descricao {
  background: var(--aviso-bg); border-color: var(--aviso-borda);
}
.produtos-confirmacao-descricao legend { color: var(--text); }
.produtos-secao legend { padding: 0 8px; font-size: 0.85rem; font-weight: 600; color: var(--text-muted); }

.produtos-grid-checkbox {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 20px; margin-bottom: 12px;
}
/* Flags numa fileira só (25/08/2026): quadro de marcar não precisa de
   altura, precisa de varredura rápida com o olho. Quebra sozinho em telas
   estreitas, e cada flag fica inteira (nome nunca separado da caixinha). */
.produtos-linha-checkbox {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 8px 13px; margin-bottom: 12px;
}
.produtos-linha-checkbox > .checkbox-label { white-space: nowrap; }
/* Espaço entre a caixinha e o nome pode ser menor aqui: são oito flags
   competindo pela mesma fileira, e o par caixa+nome continua colado. */
.produtos-linha-checkbox > .checkbox-label { gap: 6px; }

/* As flags do cadastro de Produtos só ganham peso quando a tela está em
   EDIÇÃO (25/08/2026, pedido do usuário — documento "alterações grpw
   produtos", item 2). Com o registro travado elas ficam com peso normal,
   deixando claro que ali só se lê. Sem JavaScript: a barra de ferramentas
   já marca os `<fieldset>` como `disabled`, e o CSS lê esse estado. */
#produtos-form-principal fieldset[disabled] .checkbox-label { font-weight: 400; }

/* Agrupamento visual por CST (Fornecedor > Cálculos de Impostos), achado
   22/08/2026 (auditoria WhatsApp/Arthur): antes eram ~24 checkboxes soltos
   num grid de 2 colunas — CSTs com 3 sub-itens (ICMS/ICMS-ST/Cálc. Parcial)
   desalinhavam o CST seguinte. Uma linha por CST, com todos os seus
   sub-itens juntos, resolve isso por construção. */
.cst-grupo-lista { display: flex; flex-direction: column; gap: 2px; }
.cst-grupo-linha {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 6px 8px; border-bottom: 1px solid var(--border);
}
.cst-grupo-linha:last-child { border-bottom: none; }
.cst-grupo-rotulo { font-weight: 700; font-size: 0.85rem; color: var(--text-muted); min-width: 68px; }

.busca-generica {
  display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap;
}
.busca-generica input[type="search"] {
  flex: 1; min-width: 200px; padding: 9px 12px;
  border: 1px solid var(--border); border-radius: var(--radius); font-size: 0.9rem;
}
/* O campo é o primeiro alvo da tela: com foco, ele se destaca de verdade
   (25/08/2026, toda tela abre na pesquisa). */
.busca-generica__campo:focus {
  outline: none; border-color: var(--primario, #2c5aa0);
  box-shadow: 0 0 0 3px rgba(44, 90, 160, 0.18);
}
/* Quantas linhas a busca achou. Sem isso, "poucos resultados" e "filtro
   errado" têm a mesma cara — e uma grade longa não diz o próprio tamanho. */
.busca-generica__contador {
  align-self: center; font-size: 0.82rem; color: var(--text-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
/* Rótulo de um filtro próprio da tela dentro da barra (data, período).
   Estava repetido como `style="font-size:.85rem;color:var(--text-muted)"`
   em cada template que precisava. */
.busca-generica__filtro {
  align-self: center; font-size: 0.85rem; color: var(--text-muted);
  display: inline-flex; gap: 6px; align-items: center; white-space: nowrap;
}
.busca-generica__dica {
  align-self: center; font-size: 0.78rem; color: var(--text-muted);
}
/* Linha inteira clicável na grade de pesquisa (o JS mora em base.html).
   O cursor é o que avisa que a linha toda vale, não só o link. */
tr[data-href] { cursor: pointer; }
tr[data-href]:hover > td { background: var(--linha-hover, rgba(44, 90, 160, 0.07)); }
tr[data-href]:focus-visible { outline: 2px solid var(--primario, #2c5aa0); outline-offset: -2px; }

.produtos-textarea {
  width: 100%; padding: 8px 10px; border: 1px solid var(--border);
  border-radius: var(--radius); font-family: inherit; font-size: 0.9rem;
  resize: vertical;
}

.produtos-estoques-painel { padding: 20px; }
/* Correção de espaçamento: quando essa aba fica ativa, o <form> das
   outras abas fecha só com a barra de tabs visível, sobrando o
   padding-bottom dele (20px) somado ao padding-top desta seção (20px)
   — quase o dobro do espaçamento das demais abas (que é só o gap do
   grid, ~4px). Reduz só aqui, sem afetar as outras telas que usam
   produtos-estoques-painel. */
.pessoas-docsfiscais-painel { padding-top: 4px; }
.produtos-filtro-periodo {
  display: flex; gap: 12px; align-items: flex-end; margin-bottom: 16px;
  flex-wrap: wrap;
}
.produtos-filtro-periodo .form__field { margin: 0; }

.foto-upload-linha {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
}
.foto-preview {
  width: 96px; height: 96px; object-fit: cover;
  border-radius: var(--radius); border: 1px solid var(--border);
  /* Xadrez por baixo: depois do recorte por IA a foto tem fundo
     TRANSPARENTE, e sobre o branco da tela ela parece continuar com fundo
     branco — o operador não veria o que acabou de fazer. */
  background: repeating-conic-gradient(#e9ecef 0% 25%, #fff 0% 50%) 0 0 / 14px 14px;
}
/* Empilha as ações da foto (remover / recortar) ao lado da miniatura, em
   vez de espalhá-las na mesma linha do seletor de arquivo. */
.foto-acoes { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }

.combo-busca { position: relative; }
.combo-busca-texto {
  width: 100%; padding: 8px 10px; border: 1px solid var(--border);
  border-radius: var(--radius); font-size: 0.9rem;
}
.combo-busca-lista {
  position: absolute; z-index: 20; top: 100%; left: 0; right: 0;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  margin-top: 2px; max-height: 220px; overflow-y: auto;
  list-style: none; padding: 4px 0; box-shadow: 0 4px 12px rgba(0,0,0,0.12);
}
.combo-busca-lista li {
  padding: 8px 12px; cursor: pointer; font-size: 0.88rem;
}
.combo-busca-lista li:hover,
.combo-busca-lista li.combo-busca-item--ativo {
  background: var(--primary-bg, #f0f4ff);
}

.lookup-generico-linha {
  display: flex; gap: 6px; align-items: stretch;
}
/* flex-basis explícito (não "auto") — sem isso, um <input> sem `style="width"`
   próprio usa a largura padrão do navegador (~200px+, baseada no tamanho
   intrínseco do campo), sobrando quase nada pra `.lookup-generico-descricao`
   ao lado. Bug sistêmico achado em 11/08/2026 (tela de Notas Fiscais) —
   afetava ~39 outros lugares do sistema que não setavam width inline. */
.form__field .lookup-generico-linha .lookup-generico-codigo { flex: 0 0 70px; min-width: 70px; }
.form__field .lookup-generico-linha .lookup-generico-descricao { width: auto; flex: 1 1 0; min-width: 0; }
.lookup-generico-descricao[readonly] { text-overflow: ellipsis; }

/* CONTA CONTÁBIL — o código não cabia em lugar nenhum (03/09/2026, relato do
   usuário com print).

   Medido, não estimado (§2.33), com `measureText` na fonte real do campo
   (Arial 12,9px do padrão compacto): o maior código do plano deste cliente é
   `01.01.01.01.01`, 14 caracteres, que ocupam 87px de texto + 16px de padding
   e borda = 103px. O campo tinha os 70px que TODO código de lupa tem por
   padrão, e **164 das 300 contas (55%) têm esses 14 caracteres** — ou seja, a
   maioria aparecia cortada. Os `style="width:140px"` que estavam no HTML não
   faziam nada: dentro do flex de `.lookup-generico-linha` um `width` inline é
   ignorado em silêncio, a mesma armadilha já documentada na Classificação
   Mercadológica em 25/08/2026.

   A DESCRIÇÃO ao lado é `flex: 1 1 0` e absorve a diferença sozinha: a linha
   inteira continua com a mesma largura, e o leiaute da tela não se mexe. Foi
   o que o usuário pediu — alargar o código encolhendo a descrição na mesma
   medida.

   `.lookup-generico-linha` no meio do seletor NÃO é decoração: sem ele isto
   empata em (0,3,0) com a regra geral dos 70px, e no empate vence a que vier
   depois no arquivo. Com ele são (0,4,0) e esta ganha em qualquer ordem —
   mesma razão explicada no bloco da Classificação Mercadológica.

   Se um cliente usar máscara maior (o parâmetro MASCARAPLANOCONTAS; a coluna
   aceita 20 caracteres), esta medida precisa ser refeita. */
.form__field[data-lookup-campo="contacontabil"] .lookup-generico-linha .lookup-generico-codigo,
.form__field[data-lookup-campo="contacontabilcolaborador"] .lookup-generico-linha .lookup-generico-codigo,
.form__field[data-lookup-campo="contacontabilfornecedor"] .lookup-generico-linha .lookup-generico-codigo,
.form__field[data-lookup-campo="cod_cta"] .lookup-generico-linha .lookup-generico-codigo {
  flex: 0 0 104px; min-width: 104px;
}

/* Os VIZINHOS com o mesmo defeito (03/09/2026) — achados varrendo todos os
   lookups com `testes/teste_largura_codigo_lookup.py`, que mede cada campo
   contra o maior código que a própria rota `_lista` devolve.

   Centro de Custo é o mais gritante e o mais visível: fica na linha ao lado
   da Conta Contábil em Pessoas, Controle Interno e Gestão Financeira, e o
   maior código dele (`002.003.001.001`, 15 caracteres) precisa de 113px nos
   mesmos 70px de sempre. Corrigir um e deixar o outro cortado ao lado seria
   entregar meia tela.

   Medidas na mesma fonte real: Centro de Custo 113px, DRE 88px
   (`001.001.001`), Atividade Econômica 73px (`84829919` — este por 3px). A
   descrição ao lado absorve a diferença em todos, e a linha não muda de
   largura. */
.form__field[data-lookup-campo="centrodecusto"] .lookup-generico-linha .lookup-generico-codigo,
.form__field[data-lookup-campo="centrodecustos"] .lookup-generico-linha .lookup-generico-codigo,
.form__field[data-lookup-campo="centrodecustocolaborador"] .lookup-generico-linha .lookup-generico-codigo,
.form__field[data-lookup-campo="centrodecustofornecedor"] .lookup-generico-linha .lookup-generico-codigo {
  flex: 0 0 114px; min-width: 114px;
}
.form__field[data-lookup-campo="dre"] .lookup-generico-linha .lookup-generico-codigo {
  flex: 0 0 89px; min-width: 89px;
}
.form__field[data-lookup-campo="cod_ativ_econ"] .lookup-generico-linha .lookup-generico-codigo {
  flex: 0 0 74px; min-width: 74px;
}
.lookup-generico-botao {
  flex-shrink: 0; width: 40px; min-width: 40px; border: 1px solid var(--border);
  border-radius: var(--radius); background: #f7f8fa; cursor: pointer; font-size: 1.1rem;
}
.lookup-generico-botao:hover { background: #eef0f3; }

/* Ícone de inclusão rápida ao lado de um lookup (20/08/2026) — mesmo
   visual compacto do .lookup-generico-botao, só que como <a> (abre uma
   tela de cadastro de verdade em nova aba, não um popup JS). */
.lookup-incluir-botao {
  flex-shrink: 0; width: 40px; min-width: 40px; border: 1px solid var(--border);
  border-radius: var(--radius); background: #f7f8fa; cursor: pointer; font-size: 1.3rem;
  font-weight: 700; color: var(--primary); text-decoration: none; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}
.lookup-incluir-botao:hover { background: #eef0f3; }

/* "Nova Conta" em Converter Plano de Contas (19/08/2026, pedido do
   usuário) — o código do lado da contabilidade (`PlanoDeContaIntegracao.
   containtegracao`, alargado de 5 pra 20 caracteres na mesma entrega)
   não cabia nos 70px padrão do código de lookup. */
.planocontasconv-nova-conta .lookup-generico-linha .lookup-generico-codigo { flex: 0 0 150px; min-width: 150px; }

@media (max-width: 639px) {
  .lookup-generico-linha { flex-wrap: wrap; }
  .form__field .lookup-generico-linha .lookup-generico-codigo { width: 100%; flex-basis: 100%; }
  .form__field .lookup-generico-linha .lookup-generico-descricao { width: 100%; flex: 1 1 auto; }
}

/* <dialog> nativo desde 08/08/2026 (era div+hidden) — precisa zerar o
   estilo padrão do navegador pra <dialog> (borda/padding/max-width), que
   senão aparece por cima do overlay full-screen que já montamos com
   .modal-arvore. */
.modal-arvore {
  position: fixed; inset: 0; margin: 0; border: none; padding: 0;
  width: 100%; height: 100%; max-width: none; max-height: none;
  background: rgba(0,0,0,0.4);
  display: flex; align-items: center; justify-content: center; z-index: 100;
}
/* Especificidade de tipo+atributo sozinha perde pra especificidade de
   classe (.modal-arvore) — sem isto, o navegador aplicaria display:flex
   mesmo fechado. Precisa das DUAS regras: telas que ainda usam o padrão
   antigo (<div class="modal-arvore" hidden>, ex.: sugestaocompras.html —
   deliberadamente NÃO usa <dialog> nativo, pra evitar 2 popups
   empilhados na mesma tela) E o <dialog> nativo (só
   #modal-lookup-generico, base.html). Bug real corrigido em 08/08/2026:
   a conversão do modal de lookup pra <dialog> tinha removido a regra
   `[hidden]`, deixando TODO `.modal-arvore` baseado em div (não só o de
   lookup) sempre visível — os popups "Adicionar à Ordem de Compra"/
   "Adicionar à Cotação" de Sugestão de Compras apareciam abertos sem
   nenhum clique, sempre que a página recarregava. */
.modal-arvore[hidden] { display: none; }
dialog.modal-arvore:not([open]) { display: none; }
.modal-arvore::backdrop { background: transparent; }
.modal-arvore-caixa {
  background: var(--panel); border-radius: var(--radius); width: 480px; max-width: 92vw;
  max-height: 80vh; display: flex; flex-direction: column; box-shadow: 0 10px 40px rgba(0,0,0,0.25);
}
.modal-arvore-cabecalho {
  display: flex; justify-content: space-between; align-items: center;
  padding: 14px 16px; border-bottom: 1px solid var(--border);
}
.modal-arvore-fechar-x {
  background: none; border: none; font-size: 1.3rem; cursor: pointer; color: var(--text-muted);
}
/* **O id certo é `#modal-lookup-filtro`.** A regra apontava para
   `#modal-arvore-filtro`, que não existe em lugar nenhum do HTML — o id ficou
   órfão quando o modal virou o lookup compartilhado (`base.html`), e desde
   então o campo de busca de TODO lookup do sistema saía sem margem, sem
   padding e sem borda, com o placeholder longo transbordando. Seletor que
   não casa não dá erro: só não pinta, e ninguém percebe até alguém olhar.

   Os dois ficam na regra porque não custa nada e um `.frm` antigo pode
   voltar a usar o nome anterior. */
#modal-lookup-filtro, #modal-arvore-filtro {
  margin: 10px 16px 0; padding: 8px 10px; border: 1px solid var(--border);
  border-radius: var(--radius); font-size: .9rem;
}
.modal-arvore-conteudo { padding: 10px 16px; overflow-y: auto; flex: 1; }
.modal-arvore-rodape { padding: 10px 16px; border-top: 1px solid var(--border); text-align: right; }
.modal-arvore-lista { list-style: none; margin: 0; padding-left: 18px; }
.modal-arvore-lista:first-child { padding-left: 0; }
.modal-arvore-linha {
  display: flex; align-items: center; gap: 6px; padding: 5px 6px;
  cursor: pointer; border-radius: 4px; font-size: 0.88rem;
}
.modal-arvore-linha:hover { background: #f0f4ff; }
.modal-arvore-linha.modal-arvore-item--destaque, .modal-arvore-tabela tbody tr.modal-arvore-item--destaque { background: #dbe6ff; outline: 2px solid #7c9cf5; outline-offset: -2px; }
.modal-arvore-toggle {
  width: 16px; text-align: center; font-weight: 700; color: var(--text-muted); flex-shrink: 0;
}
li:not(.modal-arvore-item--aberto) > .modal-arvore-lista { display: none; }
li.modal-arvore-item--aberto > .modal-arvore-lista { display: block; }
.modal-arvore-item--filtrado { display: none; }
/* Com filtro ativo, o galho que aparece só como CAMINHO até um resultado
   fica esmaecido — ele está na tela para mostrar ONDE o resultado mora, e
   não é o que foi procurado. É o que explica, sem texto, por que o destaque
   passa por cima dele (23/09/2026, print do usuário: "frango inteiro"
   destacava ACOUGUE). Continua clicável: escolhê-lo de propósito é direito
   de quem olha. */
.modal-arvore-conteudo--filtrando
  .modal-arvore-item:not(.modal-arvore-item--casa) > .modal-arvore-linha { opacity: .55; }

/* Linha que a lista traz mas não se pode ESCOLHER (03/09/2026) — a conta
   sintética do Plano de Contas, que existe ali para segurar o ramo. Fica
   discreta e sem a mão do cursor: o que ela oferece é abrir o ramo, não
   ser selecionada. Não se usa `pointer-events: none` porque o clique
   ainda precisa chegar (é ele que abre/fecha). */
li.modal-arvore-item--nao-selecionavel > .modal-arvore-linha,
tr.modal-arvore-item--nao-selecionavel {
  color: var(--text-muted); cursor: default;
}
li.modal-arvore-item--nao-selecionavel > .modal-arvore-linha:hover { background: transparent; }

/* Grade de resultado do lookup (28/07/2026) — Código/Descrição em
   colunas alinhadas, em vez da lista de texto solto "código - descrição"
   de antes (pedido do usuário: colunas do mesmo tamanho em qualquer
   lookup do sistema). Só afeta o modo lista (`constroiLista`) — a
   árvore (`constroiArvore`) continua com indentação/toggle, que não faz
   sentido virar grade. */
.modal-arvore-tabela { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
.modal-arvore-tabela thead th {
  text-align: left; padding: 6px; font-size: 0.72rem; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--text-muted); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; background: var(--panel);
}
.modal-arvore-tabela tbody tr { cursor: pointer; }
.modal-arvore-tabela tbody tr:hover { background: #f0f4ff; }
.modal-arvore-tabela td { padding: 6px; border-bottom: 1px solid var(--border); }
.modal-arvore-tabela-codigo { width: 100px; white-space: nowrap; color: var(--text-muted); }
.modal-arvore-tabela-check { width: 30px; }

/* Popup "Adicionar Participantes" (Cotação de Preços, 29/07/2026) — caixa
   de tamanho FIXO (não cresce/encolhe com a quantidade de resultados),
   com a mesma borda padrão dos outros popups nas laterais; a lista em si
   usa `.modal-arvore-tabela` (mesma grade de Código/Descrição alinhados
   do modal de lookup compartilhado) em vez de texto solto, pra manter
   colunas do mesmo tamanho. */
.participante-lista-caixa {
  height: 280px; overflow-y: auto; margin-top: 8px;
  border: 1px solid var(--border); border-radius: var(--radius);
}

.produtos-subabas-nav {
  display: flex; flex-wrap: wrap; gap: 2px;
  border-bottom: 1px solid var(--border); margin-bottom: 16px;
}
.produtos-subaba-btn {
  padding: 8px 12px; font-size: 0.8rem; font-weight: 600;
  background: #f7f8fa; border: 1px solid var(--border); border-bottom: none;
  border-radius: var(--radius) var(--radius) 0 0; color: var(--text-muted); cursor: pointer;
  text-decoration: none; display: inline-block;
}
.produtos-subaba-btn--ativa { background: var(--panel); color: var(--primary); }

@media (max-width: 639px) {
  .produtos-cabecalho { grid-template-columns: 1fr; }
  .produtos-grid-checkbox { grid-template-columns: 1fr; }
}

.aviso-somente-leitura {
  margin: 0; padding: 10px 20px; background: #fff7e6; color: #8a6116;
  font-size: 0.86rem; border-bottom: 1px solid var(--border);
}

/* Armadilha §2.4: classe que declara `display` vence `[hidden]` por
   especificidade — sempre o par, nunca só a classe. */
.aviso-emitir-nao-gravado:not([hidden]) { display: block; }
.aviso-emitir-nao-gravado[hidden]       { display: none; }
.aviso-emitir-nao-gravado { color: #a15c00; margin-top: 6px; font-size: 0.86rem; }

.politicaprecos-col-margem { text-align: right; white-space: nowrap; }
.politicaprecos-linha-forte td { font-weight: 700; }
.panel--login { max-width: 400px; margin: 60px auto 0; }
.form--login .form__actions { margin-top: 10px; }
.form--login .form__actions .btn { width: 100%; justify-content: center; }

.login-lookup { display: flex; gap: 8px; }
.login-lookup input:first-child { min-width: 0; }
.login-lookup--filial input:first-child { flex: 0 0 60px; }
.login-lookup--operador input:first-child { flex: 0 0 130px; }
.form--login .campo-lookup-resultado {
  flex: 1; min-width: 0; background: #f0f1f3; color: var(--text-muted);
  font-style: italic; font-size: 0.85rem;
}

.panel--acesso-negado { max-width: 480px; margin: 60px auto 0; }
.acesso-negado__corpo { padding: 20px; }
.acesso-negado__corpo p { color: var(--text); margin: 0 0 16px; }

.panel--home { max-width: 560px; margin: 60px auto 0; }
.home__corpo { padding: 24px 20px; color: var(--text-muted); }

.page {
  max-width: 1800px;
  width: 100%;
  box-sizing: border-box;
  margin: 0 auto;
  padding: 24px;
}

.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 20px;
  border-bottom: 1px solid var(--border);
}
.panel__head h1 { font-size: 1.15rem; margin: 0; font-weight: 600; }
.panel__body { padding: 20px; }

/* Cabeçalho de Notas Fiscais (notasfiscais_revisar.html) — grid único de 12
   colunas em vez de 3 linhas com grid-template-columns independentes, pra
   manter os campos alinhados entre as linhas e preencher 100% da largura
   disponível (até o padding do .panel__body) sem sobrar vão nas bordas.
   Cada campo define seu próprio `grid-column: span N`; o auto-flow quebra
   de linha sozinho quando a soma dos spans completa 12. */
.nf-cabecalho-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 14px; align-items: start; }
.nf-cabecalho-grid > .form__field { min-width: 0; }
@media (max-width: 900px) {
  .nf-cabecalho-grid { grid-template-columns: repeat(4, 1fr); }
  .nf-cabecalho-grid > .form__field { grid-column: span 2 !important; }
}
@media (max-width: 639px) {
  .nf-cabecalho-grid { grid-template-columns: 1fr; }
  .nf-cabecalho-grid > .form__field { grid-column: 1 / -1 !important; }
}

/* 6ª vez desta armadilha no projeto (§2.4): `.btn` declara `display` e
   ganha do atributo `[hidden]` por especificidade (0,1,0 contra 0,0,1) — um
   botão com `hidden` continuava aparecendo. O par abaixo resolve para TODO
   botão do sistema de uma vez, no lugar de repetir a correção por tela. */
.btn[hidden] { display: none !important; }

.btn {
  display: inline-block;
  padding: 8px 16px;
  border-radius: var(--radius);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  border: 1px solid transparent;
}
.btn--primary { background: var(--primary); color: #fff; }
.btn--primary:hover { background: var(--primary-dark); }
.btn--laranja { background: #e8730c; color: #fff; }
.btn--laranja:hover { background: #c75f09; }
.btn--ghost { background: transparent; color: var(--text-muted); border-color: var(--border); }
.btn:disabled, .btn:disabled:hover {
  opacity: 0.45;
  cursor: not-allowed;
  background: #9aa2ad;
  color: #f0f1f3;
  border-color: transparent;
}
.btn--ghost:hover { background: #f0f1f3; }

.badge {
  display: inline-block; padding: 4px 10px; border-radius: 999px;
  font-size: 0.8rem; font-weight: 600;
}
.badge--sucesso { background: #e6f4ea; color: #1e7e34; }
/* CORES DA SITUAÇÃO DA NOTA FISCAL (05/10/2026, pedido do Arthur, item 5).
   Pendente=VERDE · Fechada=AZUL · Cancelada=VERMELHO · Inutilizada=LARANJA.

   Verde para "pendente" inverte a convenção comum (verde = concluído), e eu
   havia levantado isso. A resposta fecha a questão e é a razão de ser desta
   escolha: *"já fazemos assim no GRP"*. O operador vem de anos do sistema
   legado, e a cor é memória muscular — *padrão de interface que contraria o
   hábito de quem usa não é padrão, é obstáculo.*

   `denegada` fica junto de `cancelada` por natureza (a nota não vale), e
   `fechada-advertencia` mantém o âmbar: é fechada, porém com ressalva, e
   perder essa distinção apagaria o aviso. */
.badge--pendente { background: #e6f4ea; color: #1e7e34; }
.badge--fechada { background: #e7f0fb; color: #1a56a8; }
.badge--fechada-advertencia { background: #fdf1da; color: #8a5a00; }
.badge--cancelada, .badge--denegada { background: #fbe9e7; color: var(--danger); }
.badge--inutilizada { background: #fdeede; color: #b45309; }
/* O campo "Situação" da tela da Nota Fiscal reaproveita a COR do badge, mas
   não a forma: ele é um `<input readonly>` dentro da grade do cabeçalho, e
   herdar o fundo e o arredondamento do badge o faria parecer clicável.

   O seletor precisa ser `.form__field input.nf-situacao` porque
   `.form__field input[readonly]` (regra global, linha ~1313) pinta todo campo
   somente-leitura de cinza e **vence uma classe sozinha** por especificidade —
   medido: a cor saía cinza nas duas situações, com o CSS "certo" no lugar.
   *Classe nova que perde para a regra global falha em silêncio: o elemento
   existe, a regra existe, e a cor é a antiga.* */
.form__field input.nf-situacao { font-weight: 600; background: transparent; }
.form__field input.nf-situacao.badge--pendente { color: #1e7e34; }
.form__field input.nf-situacao.badge--fechada  { color: #1a56a8; }
.form__field input.nf-situacao.badge--fechada-advertencia { color: #8a5a00; }
.form__field input.nf-situacao.badge--cancelada,
.form__field input.nf-situacao.badge--denegada { color: var(--danger); }
.form__field input.nf-situacao.badge--inutilizada { color: #b45309; }

.grid { width: 100%; border-collapse: collapse; }
.grid--meses {
  table-layout: fixed;
}
.grid--meses th, .grid--meses td {
  padding: 6px 8px !important;
  text-align: center;
}
.grid--meses th:first-child, .grid--meses td:first-child {
  width: 90px;
  text-align: left;
}
.grid--meses input {
  width: 100%; padding: 5px 4px; font-size: 0.85rem; text-align: center;
}

.grid thead th {
  text-align: left;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  padding: 10px 20px;
  border-bottom: 1px solid var(--border);
  background: #fafbfc;
  position: sticky;
  top: 0;
  z-index: 1;
  white-space: nowrap;
}
.grid tbody td {
  padding: 11px 20px;
  border-bottom: 1px solid var(--border);
  font-size: 0.92rem;
  white-space: nowrap;
}
.grid tbody tr:hover { background: #f7f9fb; }
.grid__actions { text-align: right; white-space: nowrap; }
.grid__actions a { color: var(--primary); text-decoration: none; margin-right: 14px; font-size: 0.88rem; }
.grid__actions a:hover { text-decoration: underline; }
.grid__inline-form { display: inline; }
.link-danger {
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--danger); font-size: 0.88rem; font-family: inherit;
}
.link-danger:hover { text-decoration: underline; }
.link-ghost {
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--primary); font-size: 0.88rem; font-family: inherit; margin-right: 10px;
}
.link-ghost:hover { text-decoration: underline; }
.grid__empty { text-align: center; color: var(--text-muted); padding: 32px 20px; }

.form { padding: 20px; max-width: 480px; }
.form__field { margin-bottom: var(--campo-gap); }
.form__field--full { grid-column: 1 / -1; }
/* Ocupa o RESTO da fileira, em vez de uma fileira inteira (05/10/2026,
   pedido do Arthur, item 1). `--full` é `1 / -1`: ele SEMPRE começa na
   coluna 1, e por isso empurra para a linha de baixo mesmo quando sobrava
   espaço ao lado. No Cadastro Simplificado de Pessoas isso deixava "Código"
   sozinho numa fileira e "Nome" sozinho na seguinte.
   *Esticar até o fim e começar do começo são coisas diferentes, e uma classe
   só não diz as duas.* */
.form__field--resto { grid-column: auto / -1; }
.form__field label {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: var(--label-gap);
}
label.checkbox-label {
  min-height: 0 !important;
}
.form__field input {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--input-border);
  border-radius: var(--radius);
  font-size: 0.95rem;
  background: var(--input-bg);
}
.form__field input:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--focus-glow);
}
.form__field input[readonly] { background: #f0f1f3; color: var(--text-muted); }
.form__field textarea {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--input-border);
  border-radius: var(--radius);
  font-size: 0.95rem;
  background: var(--input-bg);
  font-family: inherit;
  resize: vertical;
}
.form__field textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--focus-glow);
}
.form__actions { display: flex; gap: 10px; margin-top: 22px; }

.form__field--checkbox:not([hidden]) { display: flex; align-items: center; }
.form__field--checkbox[hidden] { display: none; }
.checkbox-label {
  display: flex; align-items: center; gap: 8px;
  font-size: 0.92rem; font-weight: 500; color: var(--text);
  cursor: pointer;
}
.checkbox-label input[type="checkbox"],
.checkbox-label input[type="radio"] {
  width: 18px; height: 18px; min-height: auto; accent-color: var(--primary);
}

.form__field select {
  width: 100%; padding: 9px 11px; border: 1px solid var(--input-border);
  border-radius: var(--radius); font-size: 0.95rem; background: var(--input-bg);
  min-height: var(--campo-altura);
}

.lookup-field { display: flex; gap: 8px; min-width: 0; }
.lookup-field .lookup-code { flex: 0 0 108px; min-width: 0; }
.lookup-field .lookup-select {
  flex: 1; min-width: 0; border: 1px solid var(--input-border); border-radius: var(--radius);
  padding: 9px 11px; font-size: 0.92rem; background: var(--input-bg); min-height: var(--campo-altura);
}
.lookup-code--invalido { border-color: var(--danger) !important; }
/* Campo reprovado numa conferência de formato (EAN-13, 26/08/2026): a borda
   vermelha acompanha o aviso do topo e some assim que a pessoa digita. */
.campo-invalido { border-color: var(--danger) !important; background: #fff5f5; }
.lookup-erro {
  margin: 6px 0 0; font-size: 0.82rem; color: var(--error-text);
}

.form__field--condicional-oculto { display: none; }

.status-badge {
  display: inline-block; padding: 3px 10px; border-radius: 999px;
  font-size: 0.78rem; font-weight: 600;
}
.status-badge--ativo { background: var(--success-bg); color: var(--success-text); }
.status-badge--inativo { background: var(--error-bg); color: var(--error-text); }

.link-neutro {
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--text-muted); font-size: 0.88rem; font-family: inherit;
  margin-right: 14px;
}
.link-neutro:hover { text-decoration: underline; color: var(--text); }

.nivel-inline-form select {
  padding: 6px 8px; border: 1px solid var(--input-border); border-radius: var(--radius);
  font-size: 0.85rem; background: var(--input-bg); min-height: 36px;
}

.checklist { display: flex; flex-direction: column; gap: 10px; }
.checklist__item {
  padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius);
}

.texto-sutil { color: var(--text-muted); font-size: 0.85rem; }

.grid__linha--ativa { background: #e8f0fa; }
.grid__linha--clicavel { cursor: pointer; }
.grid__linha--clicavel:hover { background: #f7f9fb; }

.transferirbarras-layout {
  display: flex; gap: 20px; padding: 20px; align-items: flex-start;
}
.transferirbarras-coluna { flex: 1; min-width: 0; }
@media (max-width: 900px) {
  .transferirbarras-layout { flex-direction: column; }
}

.grupossimilares-layout {
  display: flex; gap: 20px; padding: 20px; align-items: flex-start;
}
.grupossimilares-coluna-lista { flex: 0 0 380px; min-width: 0; }
.grupossimilares-coluna-detalhe { flex: 1; min-width: 0; }
.grupossimilares-lista-grid { max-height: 560px; }

.parametros-busca-campo {
  width: 100%; padding: 9px 11px; margin-bottom: 8px;
  border: 1px solid var(--input-border); border-radius: var(--radius);
  font-size: 0.92rem; background: var(--input-bg); color: var(--text);
}
.parametros-busca-campo:focus {
  outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px var(--focus-glow);
}
#parametros-busca-resultado { margin: 0 0 8px; }
.parametros-arvore { max-height: 640px; padding: 12px; }
.parametros-arvore summary { cursor: pointer; font-weight: 600; padding: 4px 0; }
.parametros-arvore .parametros-subgrupo { margin-left: 16px; }
.parametros-arvore .parametros-subgrupo summary { font-weight: 500; color: var(--text-muted); }
.parametros-lista { list-style: none; margin: 4px 0 8px 24px; padding: 0; }
.parametros-lista li { padding: 3px 0; }
.parametros-lista a { text-decoration: none; color: var(--text); font-size: 0.88rem; }
.parametros-lista a:hover { text-decoration: underline; }
.parametros-item-ativo { font-weight: 700; color: var(--primary) !important; }
@media (max-width: 900px) {
  .grupossimilares-layout { flex-direction: column; }
  .grupossimilares-coluna-lista { flex: 1 1 auto; width: 100%; }
}

.produtos-pesquisa-grid thead th {
  padding: 3px 4px !important; font-size: 0.58rem !important; white-space: nowrap;
}
.produtos-pesquisa-grid tbody td {
  padding: 2px 4px !important; font-size: 0.62rem !important; white-space: nowrap;
}
.grid-wrap.ncm-lista-curta { max-height: 130px; overflow-y: auto; }
.ncm-lista-curta .grid a { color: var(--text); text-decoration: none; display: block; }
.ncm-lista-curta .grid a:hover { color: var(--primary); }

.ncm-detalhe { padding: 20px; }
.ncm-detalhe .form { padding: 0; max-width: none; }
.ncm-linha-4 {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--campo-gap) 16px;
  grid-column: 1 / -1;
}
.ncm-linha-4 > .form__field,
.ncm-linha-5 > .form__field {
  min-width: 0;
}
.ncm-linha-4 > .form__field label,
.ncm-linha-5 > .form__field label {
  /* `min-height: 2.6em` saiu daqui em 25/08/2026: ele reservava DUAS linhas
     de rótulo mesmo quando só uma era usada, e era o que deixava o rótulo
     longe do campo. O alinhamento que ele garantia passou para o
     `align-items: end` das duas fileiras (logo acima) — cada campo encosta
     na BASE, então as caixas ficam alinhadas mesmo com rótulos de alturas
     diferentes. Mexido AQUI, na regra de origem, e não numa regra nova
     depois: uma regra concorrente empataria em especificidade (0,3,0) e
     perderia por vir antes no arquivo. */
  line-height: 1.3;
}
/* Alinhamento robusto pra quando um label quebra em 2 linhas e os outros
   da mesma fileira não — em vez de "adivinhar" a altura do label, os
   labels e os campos passam a ocupar linhas de grid próprias e
   compartilhadas entre todas as colunas, então o campo sempre começa
   na mesma altura em qualquer coluna. Isolado numa classe própria pra
   não afetar as outras telas que usam ncm-linha-4/5. */
/* Fileira com menos de quatro campos (26/08/2026): em vez de deixar colunas
   vazias à direita e apertar o que está à esquerda, reparte a largura entre os
   campos que existem. Vale principalmente pra lookup, onde o espaço a mais vira
   descrição legível em vez de "Operações internas c...". O campo de código tem
   largura fixa (70px, ver ~784), então colunas iguais = descrições iguais. */
.ncm-linha-4--colunas-2 { grid-template-columns: repeat(2, 1fr); }
.ncm-linha-4--colunas-3 { grid-template-columns: repeat(3, 1fr); }
/* Fileira em que uma das células é mais ALTA que as outras (um campo com botão
   ao lado, ou com aviso embaixo): o padrão do sistema alinha pelo rodapé —
   ótimo quando os rótulos têm alturas diferentes (ver ~518), péssimo aqui,
   porque as outras células descem junto com a mais alta. */
.ncm-linha-4--topo { align-items: start; }

.ncm-linha-4--rotulo-alinhado {
  grid-template-rows: auto auto;
  align-items: start;
}
.ncm-linha-4--rotulo-alinhado > .form__field {
  display: contents;
}
.ncm-linha-4--rotulo-alinhado > .form__field label {
  grid-row: 1;
  min-height: 0;
}
.ncm-linha-4--rotulo-alinhado > .form__field input {
  grid-row: 2;
}
.ncm-linha-5 {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--campo-gap) 12px;
  grid-column: 1 / -1;
}
.produtos-busca-rapida-linha {
  display: grid; grid-template-columns: 80px 130px max-content 1fr max-content;
  gap: var(--campo-gap) 12px; align-items: end; grid-column: 1 / -1;
}
.produtos-busca-rapida-linha > .form__field { min-width: 0; }
.produtos-outros-filtros-linha {
  display: grid; grid-template-columns: max-content max-content max-content max-content 160px;
  gap: var(--campo-gap) 20px; align-items: end; grid-column: 1 / -1;
}
.produtos-outros-filtros-linha > .form__field { min-width: 0; }
/* Estatísticas do processo (Exportação PDV) — 3 colunas x 2 linhas
   (Arquivo/Acessados/Aceitos, Rejeitados/Tempo/Tamanho), campo estreito
   o bastante pro conteúdo (números, tempo, tamanho) sem esticar a caixa
   pela largura toda do painel. */
.exportacaopdv-stats-linha {
  display: grid; grid-template-columns: repeat(3, minmax(0, 220px));
  gap: var(--campo-gap) 24px; grid-column: 1 / -1;
}
.exportacaopdv-stats-linha > .form__field { min-width: 0; }
.exportacaopdv-stats-linha > .form__field input { width: 100%; min-width: 0; }
/* Bloco compacto (Dispositivo de saída/Tipo de Exportação/Estatísticas)
   não estica pela largura toda do painel — só o suficiente pro conteúdo,
   igual ao layout de referência do usuário (18/08/2026). */
.exportacaopdv-topo,
.exportacaopdv-stats-secao {
  max-width: 640px;
}
/* Exportar / Esquecer Alterados — os dois com a largura do texto do
   maior botão ("Esquecer Alterados"), lado a lado onde antes ficava o
   lembrete de texto sobre o dispositivo PDV/KW. */
.exportacaopdv-botoes-linha { display: flex; gap: 10px; margin-bottom: 14px; }
/* min-width em px (não ch) pra garantir os dois EXATAMENTE do mesmo
   tamanho — precisa ser >= a largura natural de "Esquecer Alterados"
   (o texto mais longo dos dois), senão só ele cresce além do outro. */
.exportacaopdv-btn-largo { min-width: 200px; text-align: center; }
.exportacaopdv-btn-largo:disabled { opacity: .6; }
/* Indicador de "ocupado" durante a geração do arquivo — sem isso, um
   modo "Geral" (catálogo inteiro, pode passar de 10s) parece ter
   travado a tela. Regra dividida em :not([hidden])/[hidden] (não só
   ".exportacaopdv-carregando { display: inline-flex }" sozinho) porque
   uma classe autoral com "display" sempre ganha do [hidden] do
   navegador na cascata, independente de especificidade — mesma
   armadilha já documentada no CLAUDE.md §2.4, aqui de novo. */
.exportacaopdv-carregando:not([hidden]) { display: inline-flex; align-items: center; gap: 8px; color: var(--text-muted); font-size: 0.9rem; }
.exportacaopdv-carregando[hidden] { display: none; }
.exportacaopdv-spinner {
  width: 16px; height: 16px; border: 2px solid var(--border); border-top-color: var(--primary);
  border-radius: 50%; display: inline-block; animation: exportacaopdv-girar 0.8s linear infinite;
}
@keyframes exportacaopdv-girar { to { transform: rotate(360deg); } }
body.exportacaopdv-processando,
body.exportacaopdv-processando * { cursor: wait !important; }
@media (max-width: 639px) {
  .ncm-linha-5 { grid-template-columns: repeat(2, 1fr); }
  .produtos-busca-rapida-linha { grid-template-columns: 1fr; }
  .produtos-outros-filtros-linha { grid-template-columns: 1fr; }
  .exportacaopdv-stats-linha { grid-template-columns: repeat(2, 1fr); }
  .exportacaopdv-botoes-linha { flex-direction: column; }
}
.ncm-transparencia {
  grid-column: 1 / -1; border: 1px solid var(--border); border-radius: var(--radius);
  padding: var(--campo-gap) 16px 4px; margin: 8px 0 var(--campo-gap);
}
.ncm-transparencia legend { padding: 0 8px; font-size: 0.85rem; font-weight: 600; color: var(--text-muted); }

@media (max-width: 639px) {
  .ncm-linha-4 { grid-template-columns: 1fr; }
}

.arvore-layout { display: flex; gap: 16px; align-items: flex-start; }
.arvore-painel-esquerda { flex: 1 1 45%; min-width: 0; }
.arvore-painel-direita { flex: 1 1 55%; min-width: 0; }
.arvore-corpo { padding: 16px 20px; max-height: 70vh; overflow-y: auto; }
.arvore-acoes-topo { display: flex; gap: 8px; }

.arvore-lista--raiz { padding-left: 0; margin-bottom: 6px; }
.arvore-link--raiz {
  font-weight: 700; text-transform: uppercase; font-size: 0.82rem;
  letter-spacing: 0.04em; color: var(--text-muted);
}
.arvore-link--raiz:hover { background: #f0f1f3; }

.arvore-lista { list-style: none; margin: 0; padding-left: 18px; }
.arvore-lista:first-child { padding-left: 0; }
.arvore-lista li { margin: 2px 0; }
.arvore-lista summary { cursor: pointer; list-style: none; padding: 2px 0; }
.arvore-lista summary::-webkit-details-marker { display: none; }
.arvore-lista summary::before { content: "▸ "; color: var(--text-muted); }
.arvore-lista details[open] > summary::before { content: "▾ "; }

.arvore-link {
  color: var(--text); text-decoration: none; font-size: 0.9rem;
  padding: 3px 6px; border-radius: 4px;
}
.arvore-link:hover { background: #f0f1f3; }
.arvore-link--ativo { background: var(--primary); color: #fff; font-weight: 600; }

.arvore-detalhe { padding: 20px; }

/* Gerenciador de Relatórios (20/08/2026) — folhas do catálogo VB6 ainda
   sem gerador Flask ficam esmaeciadas (navegáveis, mas visualmente
   diferentes das ~poucas já migradas), com uma marca "○" dedicada. */
.arvore-link.relatorio-nao-migrado { color: var(--text-muted); font-style: italic; }
.relatorio-pendente-marca { color: var(--text-muted); font-style: normal; }
/* Relatórios já com gerador Flask por trás (pedido do usuário,
   20/08/2026) — em negrito na árvore, pra destacar de cara o que já
   está pronto em meio aos ~395 nós ainda esmaecidos. */
.arvore-link.relatorio-implementado { font-weight: 700; }
/* Nome do GRUPO (categoria/subcategoria) em negrito quando TODAS as
   folhas dele já foram migradas (pedido do usuário, 21/08/2026) — dá
   visibilidade rápida de qual parte do catálogo já fechou 100%, sem
   precisar abrir e contar folha por folha. */
.arvore-link--categoria-completa { font-weight: 700; }

/* Campo "Buscar por características" (20/08/2026, pedido do usuário a
   partir de print anotado): campo grande (textarea, não input de 1
   linha) com o texto explicativo só como placeholder ("sombra" — some
   assim que o operador começa a digitar, em vez de ocupar uma linha de
   rótulo acima do campo o tempo todo) e o botão "Buscar" abaixo dele,
   alinhado à esquerda, 5mm de distância da caixa de texto (não mais ao
   lado do campo). */
.busca-caracteristicas-campo {
  min-height: 85px;
}
.busca-caracteristicas-campo::placeholder {
  color: var(--text-muted);
  font-style: italic;
  opacity: 0.85;
}
/* Formulário de busca (23/08/2026) — sem o padding/margin genéricos de
   `.form`/`.form__field`, pra ficar compacto (sem espaço vazio acima do
   campo nem abaixo do botão "Buscar", antes da árvore). Único `<form>`
   dentro do painel esquerdo, escopo seguro. */
.relatorios-subpainel-esquerda .form {
  padding: 0;
  margin-bottom: 10px;
}
.relatorios-subpainel-esquerda .form .form__field--full {
  margin-bottom: 0;
}
.busca-caracteristicas-acoes {
  display: flex;
  justify-content: flex-start;
  gap: 8px;
  margin-top: 8px;
}
/* Checkbox "Obrigatório ter todas as palavras" (20/08/2026) — entre o
   campo de busca e os botões, mesmo espírito compacto do resto do
   formulário. */
.busca-caracteristicas-flag {
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  gap: 6px;
  margin-top: 8px;
  margin-right: auto;
  width: fit-content;
  font-size: 0.88rem;
  color: var(--text);
  cursor: pointer;
}
.busca-caracteristicas-flag input[type="checkbox"] {
  width: 16px;
  height: 16px;
  min-height: auto;
  flex: 0 0 auto;
  margin: 0;
  accent-color: var(--primary);
}

/* Rótulo só pra leitor de tela — o texto explicativo virou placeholder
   (visível dentro do campo), mas o <label> continua existindo por
   acessibilidade, só escondido visualmente. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Visual próprio da árvore de NCM (22/07/2026) — escopado só aqui,
   não afeta as outras árvores do sistema (Centro de Custo, Plano de
   Contas, Classificação Mercadológica, Natureza da Operação), que
   continuam com o estilo genérico (.arvore-link, .arvore-link--raiz)
   sem essas variações de cor/tamanho por nível. */
.ncm-arvore-visual .arvore-link,
.ncm-arvore-visual .arvore-link--raiz {
  font-size: 0.9rem;
  text-transform: none;
  letter-spacing: normal;
}
.ncm-arvore-visual .arvore-link--nivel-1 { color: #0b3d78; font-weight: 700; }
.ncm-arvore-visual .arvore-link--nivel-2 { color: #1a5a9e; font-weight: 600; }
.ncm-arvore-visual .arvore-link--nivel-3 { color: #3878b8; font-weight: 500; }
.ncm-arvore-visual .arvore-link--nivel-4 { color: #6499cc; font-weight: 400; }
.ncm-arvore-visual .arvore-link--nivel-5 { color: #93b8dd; font-weight: 400; }
.ncm-arvore-visual .arvore-link--ativo,
.ncm-arvore-visual .arvore-link--ativo.arvore-link--nivel-1,
.ncm-arvore-visual .arvore-link--ativo.arvore-link--nivel-2,
.ncm-arvore-visual .arvore-link--ativo.arvore-link--nivel-3,
.ncm-arvore-visual .arvore-link--ativo.arvore-link--nivel-4,
.ncm-arvore-visual .arvore-link--ativo.arvore-link--nivel-5 {
  background: var(--primary); color: #fff;
}
/* Seta pra quem pode expandir (já existe no genérico); bolinha pra
   quem é folha (nível final, sem sub-nível) */
.ncm-arvore-visual .arvore-link--folha::before { content: "• "; color: var(--text-muted); }
.arvore-detalhe .form { padding: 0; max-width: none; }
.arvore-separador { border: none; border-top: 1px solid var(--border); margin: 20px 0; }
.arvore-vazio-msg { padding: 40px 20px; text-align: center; color: var(--text-muted); }

@media (max-width: 639px) {
  .arvore-layout { flex-direction: column; }
}

/* Gerenciador de Relatórios (22/08/2026, reforma da tela) — layout
   próprio: 1 único `.panel` (cabeçalho comum) com 2 subpainéis internos
   (árvore/busca à esquerda, relatório+parâmetros à direita), cada um com
   rolagem PRÓPRIA (`overflow-y:auto`) — os campos que passam da altura
   visível continuam alcançáveis rolando só aquele subpainel, sem rolar a
   página inteira. Classes escopadas só a esta tela (não reaproveita
   `.arvore-painel-esquerda`/`.arvore-painel-direita`, que são o layout de
   2 `.panel` lado a lado usado por Classificação Mercadológica/Centro de
   Custo/Plano de Contas/NCM/Natureza da Operação — mudar aquelas
   quebraria as outras 5 telas). */
.relatorios-subpaineis { display: flex; gap: 20px; align-items: stretch; padding: 16px 20px; }
.relatorios-subpainel { flex: 1 1 50%; min-width: 0; max-height: 75vh; overflow-y: auto; }
.relatorios-subpainel-esquerda { flex: 1 1 45%; border-right: 1px solid var(--border); padding-right: 20px; }
.relatorios-subpainel-direita { flex: 1 1 55%; }
.relatorios-subpainel-direita .panel__head { padding: 0 0 14px; margin-bottom: 14px; }
.relatorios-subpainel-direita .arvore-detalhe { padding: 0; }

@media (max-width: 639px) {
  .relatorios-subpaineis { flex-direction: column; }
  .relatorios-subpainel { max-height: none; overflow-y: visible; }
  .relatorios-subpainel-esquerda { border-right: none; border-bottom: 1px solid var(--border); padding-right: 0; padding-bottom: 20px; }
}

.flash-stack { margin-bottom: 16px; }
.flash {
  padding: 10px 14px;
  border-radius: var(--radius);
  font-size: 0.9rem;
  margin-bottom: 8px;
}
.flash--success { background: var(--success-bg); color: var(--success-text); }
.flash--error { background: var(--error-bg); color: var(--error-text); }

/* ==========================================================================
   Responsivo — smartphone, tablet, desktop
   ========================================================================== */

/* Base mobile-first: elementos interativos com alvo de toque >= altura padrão */
.btn, .link-danger, .grid__actions a {
  min-height: var(--campo-altura);
  display: inline-flex;
  align-items: center;
}
.form__field input { min-height: var(--campo-altura); }

.grid-wrap { width: 100%; overflow-x: auto; overflow-y: auto; max-height: 480px; }

/* Tablet e acima: layout com mais respiro + formulário em 2 colunas
   (só nos formulários de CADASTRO — o login (.form--login) fica de fora,
   ele é sempre coluna única, curto, não precisa desse tratamento) */
@media (min-width: 640px) {
  .page { padding: 32px; }

  .form:not(.form--login) {
    max-width: none;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px 24px;
    align-items: start;
  }
  /* Campos "grandes" (texto livre, lookup com dois controles) ficam melhores
     ocupando a linha toda em vez de dividir em 2 colunas */
  .form__field--full { grid-column: 1 / -1; }
  .form__field--resto { grid-column: auto / -1; }
  .form:not(.form--login) .form__actions { grid-column: 1 / -1; }
}

/* Abaixo de tablet: grid vira lista de cartões (tabela HTML continua acessível,
   só a apresentação visual muda — cada <tr> vira um cartão, cada <td> uma linha
   rotulada, usando o data-label já presente no HTML) */
@media (max-width: 639px) {
  .topbar { padding: 12px 16px; flex-wrap: wrap; }
  .page { margin: 0 auto; padding: 16px; }
  .panel__head { flex-direction: column; align-items: stretch; gap: 12px; padding: 16px; }
  .panel__head .btn { text-align: center; justify-content: center; }

  .grid thead { display: none; }
  .grid, .grid tbody, .grid tr, .grid td { display: block; width: 100%; }
  .grid tr {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    margin: 0 14px 14px;
    width: auto;
    overflow: hidden;
  }
  .grid__empty-row { border: none !important; margin: 0 !important; }
  .grid tbody td {
    border-bottom: 1px solid #eef0f2;
    padding: 10px 14px;
    display: flex;
    justify-content: space-between;
    gap: 12px;
    text-align: right;
    white-space: normal;
  }
  .grid tbody td:last-child { border-bottom: none; }
  .grid tbody td[data-label]:not([data-label=""])::before {
    content: attr(data-label);
    font-weight: 600;
    color: var(--text-muted);
    text-align: left;
  }
  .grid__actions { justify-content: flex-end; }
  .grid__actions a { margin-right: 0; }

  .form { padding: 16px; max-width: none; }
  .form__actions { flex-direction: column-reverse; }
  .form__actions .btn { width: 100%; justify-content: center; }
  .lookup-field { flex-direction: column; }
  .lookup-field .lookup-code { flex: none; }

  /* Vira layout de cards nessa largura — colunas congeladas não fazem
     sentido mais (ver .resultados-secao-grid__col-fixa acima). */
  .resultados-secao-grid__col-fixa {
    position: static; left: auto; width: auto; min-width: 0; box-shadow: none;
  }
}

/* Telas grandes: um pouco mais de largura útil + formulário em 3 colunas */
@media (min-width: 1200px) {
  .page { max-width: 1800px; }
  .form:not(.form--login) { grid-template-columns: repeat(3, 1fr); }
}

/* Monitores bem largos: a página já usa quase toda a largura disponível
   (teto de 1800px só pra não deixar linhas de texto absurdamente longas
   em ultrawide/4K) — aproveita o espaço extra com uma 4ª coluna no
   formulário, em vez de só alargar as 3 colunas existentes. */
@media (min-width: 1600px) {
  .form:not(.form--login) { grid-template-columns: repeat(4, 1fr); }
}

/* Respeita preferência de menos animação (não usamos animação hoje, mas já
   deixamos a base pronta pra quando o motor genérico ganhar transições) */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ==========================================================================
   Tela "Novo cadastro" por documento (Pessoas / Filiais)
   ========================================================================== */
.panel--novo-documento { max-width: 560px; }
.panel--novo-documento .panel__head { flex-direction: column; align-items: flex-start; gap: 8px; }
.panel--novo-documento .form { padding: 24px; max-width: none; }

.novo-documento-intro {
  margin: 0 0 22px;
  color: var(--text-muted);
  line-height: 1.5;
}
.novo-documento-intro strong { color: var(--text); }

.novo-documento-linha {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  flex-wrap: nowrap;
}

.novo-documento-checkbox {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  width: 150px;
  flex-shrink: 0;
  padding-top: 28px;
  font-size: 0.9rem;
  line-height: 1.3;
}
.novo-documento-checkbox input { margin-top: 2px; flex-shrink: 0; }

.novo-documento-campo { flex: 1; min-width: 200px; }
.novo-documento-campo label { color: var(--primary); font-weight: 600; }

.novo-documento-coluna { flex: 1; min-width: 200px; }

.novo-documento-acoes {
  margin-top: 18px;
  display: flex;
  align-items: center;
  gap: 18px;
}

.link-cancelar {
  color: #6d4aff;
  font-weight: 500;
  text-decoration: none;
}
.link-cancelar:hover { text-decoration: underline; }

@media (max-width: 480px) {
  .novo-documento-linha { flex-direction: column; gap: 16px; }
  .novo-documento-checkbox { padding-top: 0; max-width: none; }
}

/* Remarcação de Preços — painéis lado a lado (Precificação / Custos / Impostos) */
.remarcacao-linha-3 {
  display: grid; grid-template-columns: repeat(3, minmax(90px, auto)); gap: 4px 16px; width: max-content; max-width: 100%;
}
@media (max-width: 639px) {
  .remarcacao-linha-3 { grid-template-columns: 1fr; width: auto; }
}

.remarcacao-colunas {
  display: flex; gap: 12px; align-items: flex-start; margin-bottom: 8px;
}
.remarcacao-coluna { flex: 1 1 320px; min-width: 280px; }
.remarcacao-coluna.remarcacao-coluna--remarcacao {
  flex: none !important; width: 460px !important; min-width: 0 !important; max-width: 460px !important;
}
.remarcacao-coluna.remarcacao-coluna--dados {
  flex: 1 1 auto !important; min-width: 0 !important; width: auto !important;
}
.remarcacao-coluna--remarcacao .produtos-secao,
.remarcacao-coluna--dados .produtos-secao { min-width: 0; }

.remarcacao-dados-2col { display: flex; gap: 12px; }
.remarcacao-dados-2col .grid { flex: 1 1 50%; min-width: 0; }
.remarcacao-dados-grid tbody td {
  padding: 3px 8px !important; font-size: 0.78rem !important;
}

.remarcacao-nf-grid thead th {
  padding: 3px 5px !important; font-size: 0.62rem !important; white-space: nowrap;
}
.remarcacao-nf-grid tbody td {
  padding: 2px 5px !important; font-size: 0.68rem !important; white-space: nowrap;
}
.remarcacao-nf-grid input[type="text"] { font-size: 0.68rem; padding: 2px 4px; }


/* Grade limitada a ~10 linhas visíveis, resto por rolagem — altura
   calculada pro cabeçalho + 10 linhas de dados, diferente pra grade
   compacta (Entrada de Notas) e pra grade padrão (Itens Associados). */
.grid-wrap--10linhas { overflow-y: auto; }
.grid-wrap--10linhas.grid-wrap--compacta { max-height: 296px; }  /* cabeçalho ~26px + 10 linhas ~27px */
.grid-wrap--10linhas:not(.grid-wrap--compacta) { max-height: 460px; }  /* cabeçalho ~42px + 10 linhas ~42px */

.remarcacao-precificacao-topo {
  display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap;
}
.remarcacao-aba-preco {
  padding: 6px 14px; border: 1px solid var(--border); border-radius: var(--radius);
  background: #f0f1f3; font-weight: 600; font-size: 0.85rem; color: var(--text-muted);
}

.remarcacao-promocao-box { margin-top: 12px; position: relative; }
.remarcacao-promocao-box legend { display: flex; align-items: center; }
.remarcacao-promocao-box .checkbox-label { font-weight: 600; color: var(--text-muted); }
.remarcacao-remover-wrap { position: absolute; top: 10px; right: 14px; }

.remarcacao-frame-radios { padding: 8px 14px 6px; margin-bottom: 0; }
.remarcacao-frame-radios legend { font-size: 0.8rem; }
.remarcacao-radios-linha {
  display: flex; flex-wrap: wrap; gap: 8px 20px; align-items: center;
}
.remarcacao-radios-linha .checkbox-label { display: inline-flex; white-space: nowrap; }

.remarcacao-busca-linha { display: flex; gap: 6px; align-items: flex-end; flex-wrap: wrap; margin-bottom: 12px; }
.remarcacao-busca-linha .form__field { margin-bottom: 0; }

.remarcacao-frames-linha { display: flex; gap: 16px; align-items: flex-start; flex-wrap: wrap; }
.remarcacao-frame-compacto { flex: 0 0 auto; width: auto; }
.remarcacao-frame-flex { flex: 1 1 auto; min-width: 280px; }
.remarcacao-frame-compacto .remarcacao-radios-linha,
.remarcacao-frame-flex .remarcacao-radios-linha { flex-wrap: nowrap; }
@media (max-width: 700px) {
  .remarcacao-frame-compacto .remarcacao-radios-linha,
  .remarcacao-frame-flex .remarcacao-radios-linha { flex-wrap: wrap; }
}

@media (max-width: 900px) {
  .remarcacao-colunas { flex-direction: column; }
  .remarcacao-coluna { flex: 1 1 auto; width: 100%; }
}

/* Configuração de Tela (Manutenção) */
.cfgtela-linha-campo { display: flex; align-items: center; gap: 8px; }
.cfgtela-amostra {
  flex-shrink: 0; width: 28px; height: 28px; border-radius: 6px;
  border: 1px solid var(--border); display: inline-block;
}
.cfgtela-linha-campo input[type="color"] {
  flex-shrink: 0;
  width: 48px;
  height: 36px;
  padding: 2px !important;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
}
.cfgtela-presets { display: flex; flex-wrap: wrap; gap: 8px; }

/* Busca Rápida de Cadastro — trocar de registro sem voltar pra listagem */
.busca-rapida-cadastro {
  max-width: 360px; margin: 0 0 var(--campo-gap);
  padding-bottom: var(--campo-gap); border-bottom: 1px solid var(--border);
}
.busca-rapida-cadastro label {
  display: block; font-size: 0.85rem; font-weight: 600; color: var(--text-muted);
  margin-bottom: var(--label-gap);
}
.busca-rapida-input { background: var(--input-bg); }

.cfgtela-preview-linha { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; padding: 8px 0; }
.cfgtela-preview-card {
  display: flex; flex-direction: column; gap: 2px; padding: 12px 16px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.cfgtela-preview-texto-forte { color: var(--text); font-weight: 600; }
.cfgtela-preview-texto-secundario { color: var(--text-muted); font-size: 0.85em; }
.cfgtela-preview-texto-apagado { color: var(--text-muted); font-size: 0.8em; opacity: 0.75; }
.cfgtela-preview-btn-destaque {
  padding: 10px 18px; border: none; border-radius: var(--radius);
  background: var(--primary); color: #fff; cursor: default;
}
.cfgtela-preview-sucesso {
  padding: 6px 12px; border-radius: var(--radius);
  background: var(--success-bg); color: var(--success-text);
}
.cfgtela-preview-perigo {
  padding: 6px 12px; border-radius: var(--radius);
  color: var(--danger);
}
.cfgtela-preview-faixa {
  padding: 6px 12px; border-radius: var(--radius);
  background: var(--bg); border: 1px solid var(--border);
  color: var(--text-muted);
}
.cfgtela-preview-campo-rotulado { display: flex; flex-direction: column; }
.cfgtela-preview-label {
  font-size: 0.8em; font-weight: 600; color: var(--text-muted); margin-bottom: var(--label-gap, 5px);
}
.cfgtela-preview-input {
  padding: 8px 10px; border-radius: var(--radius);
  background: var(--input-bg); border: 1px solid var(--input-border);
}
.cfgtela-preview-input:focus { outline: none; box-shadow: 0 0 0 3px var(--focus-glow); }

/* Tipos de Notas Fiscais (24/07/2026) — lookup simples (texto + descrição
   buscada via AJAX ao lado, sem o <select> completo do motor genérico,
   já que algumas dessas tabelas — Conta Contábil, Tipo de Título — têm
   muitos registros pra popular um <select> inteiro de cara) */
.lookup-field-simples { display: flex; align-items: center; gap: 8px; }
.lookup-field-simples input { flex: 0 0 140px; }
.lookup-descricao-exibida { color: var(--text-muted); font-size: 0.85rem; }
.lookup-descricao-exibida.lookup-erro-texto { color: var(--danger, #c0392b); }

/* Popup de edição das configurações de um CFOP dentro do Tipo de Nota
   Fiscal (equivalente ao frmINCLUIRCFOP.frm do VB6) */
.popup-edicao-cfop {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 24px; max-width: 760px; width: 90vw;
}
.popup-edicao-cfop::backdrop { background: rgba(0, 0, 0, 0.4); }

/* Popup "Novo Lote" (Gestão de Inventários > Contagens) — 08/08/2026,
   antes era um formulário inline empurrando as Contagens pra baixo; virou
   popup pra deixar as Contagens logo abaixo da grade de Lotes. Usa
   .ncm-linha-4 nas fileiras internas (mesmo motivo de sempre: min-width:0
   nos campos evita o corte de lookup da armadilha da seção 2.7). */
.popup-novo-lote {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 24px; max-width: 640px; width: 92vw;
}
.popup-novo-lote::backdrop { background: rgba(0, 0, 0, 0.4); }
.popup-novo-lote h2 { margin-top: 0; font-size: 1.1rem; }
.popup-novo-lote .form { padding: 0; max-width: none; }

/* Popup "Selecionar Itens" (equivalente a frmConsultaItens.frm) — Itens
   do Inventário > Adicionar Itens. Bem mais largo que .popup-edicao-cfop
   (tem uma grade de filtros de 4 colunas + tabela de resultados). */
.popup-selecionar-itens {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 24px; max-width: 1450px; width: 96vw;
}
.popup-selecionar-itens::backdrop { background: rgba(0, 0, 0, 0.4); }
.popup-selecionar-itens h2 { margin-top: 0; font-size: 1.1rem; }
/* Fonte menor na grade de resultados (9 colunas de valores/estoque) —
   pedido do usuário em 08/08/2026 pra caber mais coluna sem precisar
   rolar tanto na horizontal. */
/* Grade compacta — fonte/padding reduzidos pra caber mais coluna sem
   precisar rolar tanto na horizontal. Usada primeiro no popup "Selecionar
   Itens" (08/08/2026), depois reaproveitada na grade principal de Itens
   do Inventário (mesma tela) a pedido do usuário — qualquer `.grid-wrap`
   novo com muitas colunas de valor/estoque pode usar a mesma classe. */
.grid-compacta .grid { font-size: 0.52rem; }
.grid-compacta .grid th, .grid-compacta .grid td { padding: 4px 6px; }

/* Campo de Quantidade editável direto na grade de Contagens (sem botão
   Salvar — grava sozinho no blur/Enter, ver inventario_lotes.html) —
   fundo azul claro pedido pelo usuário em 08/08/2026, pra destacar
   visualmente que é um campo editável dentro da grade. */
.campo-contagem-quantidade {
  width: 90px; padding: 4px 6px; border: 1px solid var(--input-border, #ccc);
  border-radius: var(--radius); background: #e3f2fd; font: inherit;
}
.campo-contagem-quantidade:focus { outline: none; border-color: var(--primary); background: #d0e8fc; }

.popup-edicao-cfop h2 { margin-top: 0; font-size: 1.1rem; grid-column: 1 / -1; }
.tiponf-config-linha3 {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 16px;
  grid-column: 1 / -1;
}
/* Lookups do popup de CFOP empilhados (um embaixo do outro, largura
   cheia) em vez de lado a lado — assim a seleção (<select>) tem
   espaço de verdade pra mostrar a descrição inteira. */
.tiponf-lookups-empilhados {
  grid-column: 1 / -1; display: flex; flex-direction: column; gap: 4px;
}
.tiponf-lookups-empilhados .form__field { width: 100%; }
.popup-edicao-cfop .lookup-code { flex: 0 0 140px; }

/* Combobox de pesquisa (Informações Adicionais) — campo compacto
   (parece um lookup normal), mas abre um dropdown que filtra por
   qualquer parte do texto digitado, com opções que quebram linha
   normalmente (diferente do <select> nativo, que nunca quebra linha
   e só busca pelo INÍCIO do texto). */
.combobox-lookup { position: relative; }
.combobox-input { width: 100%; }
.combobox-dropdown {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 30;
  margin-top: 4px; max-height: 320px; overflow-y: auto;
  background: var(--input-bg); border: 1px solid var(--input-border);
  border-radius: var(--radius); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
}
.combobox-opcao {
  padding: 8px 12px; font-size: 0.85rem; line-height: 1.4;
  white-space: normal; word-wrap: break-word; overflow-wrap: break-word;
  border-bottom: 1px solid var(--border); cursor: pointer;
}
.combobox-opcao:last-child { border-bottom: none; }
.combobox-opcao:hover { background: #f0f4fa; }
.combobox-opcao--vazia { color: var(--text-muted); font-style: italic; cursor: default; }
.combobox-opcao--vazia:hover { background: transparent; }

.linha-clicavel:hover { background: #f0f4fa; }
.linha-selecionada { background: var(--primary-bg, #f0f4ff); font-weight: 600; }

/* Notas Fiscais (listagem) — linha inteira colorida por direção (Entrada/
   Saída), seleção só por foco na linha (sem rádio), fundo destacado
   reaproveitando `.linha-selecionada` já existente. */
tr.linha-nf { cursor: pointer; }
tr.linha-nf:focus { outline: none; }
tr.linha-nf--entrada { color: var(--danger); }
tr.linha-nf--saida { color: var(--primary); }

/* Grade da listagem de Notas Fiscais — largura fixa por coluna (colgroup no
   template) pra caber as 13 colunas de uma vez, sem rolagem horizontal, na
   escala de 100% do navegador (pedido do usuário, 12/08/2026). Só esta
   grade usa `table-layout: fixed` — é uma exceção deliberada e local à
   regra geral da seção 2.15 do CLAUDE.md (que evita `fixed` porque corta
   texto longo); aqui célula estreita usa `text-overflow: ellipsis` +
   `title` no `<td>` com o valor por extenso, então nada é perdido, só não
   ocupa espaço à toa. */
.grid--nf-lista { table-layout: fixed; }
/* Mesma estrutura de seletor de `.grid thead th`/`.grid tbody td`
   (style.css ~526/545) — precisa bater a especificidade pra vencer (não só
   ter uma classe a mais), senão o padding/font-size largos de lá continuam
   valendo e a coluna estreita trunca o texto mesmo com largura "suficiente"
   no colgroup. */
.grid--nf-lista thead th { padding: 8px 6px; font-size: 0.72rem; overflow: hidden; text-overflow: ellipsis; }
.grid--nf-lista tbody td, .grid--nf-lista tfoot td { padding: 7px 6px; font-size: 0.82rem; overflow: hidden; text-overflow: ellipsis; }
.grid--nf-lista .badge { padding: 2px 7px; font-size: 0.72rem; white-space: nowrap; }
.grid--nf-lista tfoot td { border-top: 2px solid var(--border); border-bottom: none; padding-top: 10px; font-weight: 700; }
.grid--nf-lista .grid__espelho { text-align: center; }
.grid--nf-lista .grid__espelho a { text-decoration: none; }

/* Classificação Fiscal de PIS/PASEP e COFINS (26/07/2026) — dois grids
   compactos (só ~3 linhas visíveis, resto com scroll interno) pra tudo
   caber na tela sem rolar, igual ao efeito do VB6 original (SSPanel com
   os dois ListViews pequenos + campos de detalhe logo abaixo). */
.piscof-grid-wrap { max-height: 118px; overflow-x: auto; overflow-y: auto; border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 16px; }

/* Gestão de Contratos Financeiros (26/07/2026) — formulário de filtro
   sempre em 4 colunas (independente de largura de tela, diferente do
   .form genérico que só chega a 4 colunas em telas muito largas). */
.gestaocontratos-filtro {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--campo-gap, 12px) 16px;
  border: none; padding: 0; margin: 0; min-width: 0;
}
/* Sem isto, cada .form__field (item de grid) usa min-width:auto por
   padrão — se o conteúdo (ex.: uma linha de lookup com código+descrição+
   botão) não coubesse na fração 1fr da coluna, o item força a TRILHA
   inteira a crescer além do container, e como .panel tem overflow:hidden
   o excesso simplesmente some (sem barra de rolagem, sem erro visível) —
   achado em 08/08/2026 revisando telas com muitos lookups lado a lado
   (Coletor de Dados, Configurações do Inventário). Mesmo padrão já usado
   em outras telas (.produtos-busca-rapida-linha, .ncm-linha-5 etc.). */
.gestaocontratos-filtro > .form__field { min-width: 0; }
.gestaocontratos-filtro .checkbox-linha {
  display: flex; align-items: center; gap: 6px; font-size: 0.9rem; white-space: nowrap;
}
@media (max-width: 900px) {
  .gestaocontratos-filtro { grid-template-columns: repeat(2, 1fr); }
}
/* Sugestão de Compras (28/07/2026) — layout de filtro pedido pelo
   usuário (mockup próprio, diferente do padrão de 4 colunas iguais das
   outras telas): 2 colunas de larguras DIFERENTES (esquerda mais larga
   pros lookups/descrição, direita mais estreita pros selects). Cada
   campo declara `grid-row`/`grid-column` explícito (ver template) — é
   uma grade HTML de verdade, então o próprio motor de grid alinha as
   linhas usando a altura real de cada campo (`align-items: start` +
   `grid-auto-rows: minmax(var(--campo-altura), auto)`), sem precisar de
   nenhum espaçador com altura "chutada" manualmente (1ª tentativa usava
   duas colunas flex independentes + uma div vazia de altura fixa — não
   alinhava de verdade porque a altura real de cada campo varia um
   pouco). Em telas estreitas some a 2ª coluna e os campos empilham na
   ordem do DOM (que já é a ordem visual certa). */
.sugestaocompras-filtro {
  display: grid; grid-template-columns: minmax(0, 620px) minmax(0, 320px);
  grid-auto-rows: minmax(var(--campo-altura, 44px), auto);
  align-items: start;
  column-gap: 24px; row-gap: var(--campo-gap, 16px);
  border: none; padding: 0; margin: 0; min-width: 0;
}
/* `.form__field` global já tem margin-bottom — some daria espaçamento
   duplicado somado ao `row-gap` da grade acima. */
.sugestaocompras-filtro .form__field { margin-bottom: 0; }
@media (max-width: 900px) {
  .sugestaocompras-filtro { grid-template-columns: 1fr; }
  .sugestaocompras-filtro > * { grid-column: 1 !important; grid-row: auto !important; }
}

@media (max-width: 560px) {
  .gestaocontratos-filtro { grid-template-columns: 1fr; }
}

/* Monitor (Inteligência) — controle deslizante de período (2 sliders nativos
   sobrepostos, técnica padrão de dual-range com <input type="range">). Os
   inputs ficam com pointer-events:none (o "track" transparente inteiro não
   intercepta clique) e só o thumb de cada um reabilita pointer-events — assim
   cada bolinha é arrastável independente mesmo sobrepondo o outro slider. */
.monitor-slider { position: relative; height: 36px; margin: 8px 0 4px; }
.monitor-slider-track {
  position: absolute; top: 50%; left: 0; right: 0; height: 4px;
  transform: translateY(-50%); background: var(--border); border-radius: 2px;
}
.monitor-slider-range {
  position: absolute; top: 50%; height: 4px; min-width: 4px;
  transform: translateY(-50%); background: var(--primary); border-radius: 2px;
}
/* Precisa de mais especificidade que ".form__field input" (que aplica fundo
   branco/borda/padding a QUALQUER input dentro de um .form__field) — sem
   isso o fundo opaco de um dos dois sliders sobrepostos cobre o outro por
   inteiro (não só a faixa/thumb), escondendo-o completamente por trás do
   que estiver por cima na ordem do DOM. Achado testando em navegador real,
   20/08/2026 — só um dos 2 círculos aparecia, nunca os dois. */
.form__field .monitor-slider-input {
  position: absolute; top: 50%; left: 0; width: 100%; margin: 0;
  padding: 0; border: none;
  transform: translateY(-50%); background: transparent;
  appearance: none; -webkit-appearance: none; pointer-events: none;
}
.form__field .monitor-slider-input:focus { outline: none; border: none; box-shadow: none; }
.monitor-slider-input::-webkit-slider-runnable-track { background: transparent; }
.monitor-slider-input::-moz-range-track { background: transparent; }
.monitor-slider-input::-webkit-slider-thumb {
  appearance: none; -webkit-appearance: none; pointer-events: auto;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--primary); border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,0.3); cursor: pointer;
}
.monitor-slider-input::-moz-range-thumb {
  pointer-events: auto; width: 18px; height: 18px; border-radius: 50%;
  background: var(--primary); border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,0.3); cursor: pointer;
}
/* Chave "1 gráfico / 2 gráficos" (topo da tela, 20/08/2026) — link simples
   (GET, preserva todo o resto da querystring — ver `_link_trocando_paineis`
   em admin_monitor.py), não checkbox/JS: trocar o nº de painéis muda o que
   o servidor CALCULA (com 1 só, o painel B nem roda a query), não só o que
   aparece na tela. */
.monitor-modo-paineis {
  display: flex; align-items: center; gap: 8px; margin-bottom: 12px; flex-wrap: wrap;
}
.monitor-modo-paineis span { color: var(--text-muted); font-size: 0.9rem; }
.btn--toggle {
  display: inline-block; padding: 6px 14px; border-radius: var(--radius);
  border: 1px solid var(--border); background: var(--panel); color: var(--text);
  font-size: 0.85rem; text-decoration: none; cursor: pointer;
}
.btn--toggle.is-ativo { background: var(--primary); border-color: var(--primary); color: #fff; }

/* Tela Monitor: 2 painéis (A/B) empilhados pra comparar 2 períodos
   (20/08/2026, invertido de lado-a-lado pra empilhado no mesmo dia —
   lado a lado deixava pouca largura pros gráficos de barra horizontal,
   que aí precisavam de MUITA altura pra caber as ~20 categorias sem
   truncar o rótulo). Cada painel ocupa a largura cheia da tela; a altura
   de cada um é metade da altura DISPONÍVEL da tela (viewport menos
   topbar+navbar+padding do container + a chave "Exibir" acima — `199px`
   medido via Playwright), não metade da altura do conteúdo — por isso
   `height` explícito no wrap, não só `flex:1` (senão a soma dos painéis
   ficaria do tamanho do conteúdo, não da tela). Com 1 painel só, o mesmo
   `flex:1` já faz ele ocupar o wrap inteiro sozinho, sem regra extra. */
/* Altura do gráfico. Até 24/08/2026 o conjunto era espremido em
   `calc(100vh - 199px)`, dividido entre os painéis: com 2 gráficos abertos
   sobravam ~80px pra cada um — barra virava traço e o filtro ganhava barra de
   rolagem própria. Agora cada painel tem altura de verdade e quem rola é a
   PÁGINA, que é como se compara um gráfico com o outro. */
:root { --monitor-altura-grafico: 460px; }
.monitor-comparar-wrap {
  display: flex; flex-direction: column; gap: 16px;
}
/* Um gráfico só na tela: usa a folga pra crescer. */
.monitor-comparar-wrap--um { --monitor-altura-grafico: min(620px, calc(100vh - 260px)); }
.monitor-comparar-wrap .panel--monitor {
  width: 100%; display: flex; flex-direction: column;
}
.monitor-comparar-wrap .panel--monitor .panel__body {
  flex: 1; min-height: 0; display: flex; flex-direction: column;
}
.monitor-painel-rotulo { font-weight: 400; color: var(--text-muted); font-size: 0.9rem; }

/* Layout interno de cada painel: filtro pequeno à esquerda (não estica —
   `align-self:start`, já que o grid pai agora estica os itens por padrão
   pra preencher a altura toda) e gráfico ocupando o resto da altura
   disponível. Abaixo de 900px vira 1 coluna só (filtro em cima, gráfico
   embaixo), mesmo critério de `.gestaocontratos-filtro`. */
.monitor-layout {
  display: grid; grid-template-columns: 1fr 3fr; gap: 16px;
  min-height: var(--monitor-altura-grafico);
}
@media (max-width: 900px) {
  .monitor-layout { grid-template-columns: 1fr; }
}
/* `.panel` (regra global) tem `overflow:hidden` — sem altura travada +
   rolagem própria aqui, os 5 campos deste formulário (mais alto que a
   metade da tela sobrando em viewports comuns) ficavam cortados pelo
   `.panel` pai, escondendo o botão "Atualizar" por completo (achado
   testando em navegador real, 20/08/2026). `align-self` fica no padrão
   (stretch) — ocupa a altura toda da linha do grid, igual ao gráfico ao
   lado — e rola sozinho se não couber. */
/* Sem rolagem interna: o filtro cabe inteiro agora que o painel tem altura
   (a barra de rolagem dentro do filtro era sintoma do mesmo aperto). */
.monitor-filtro-painel {
  background: #fbe1de; border: 1px solid #eeb2ab; border-radius: var(--radius);
  padding: 14px; min-width: 0; align-self: start;
}
.monitor-filtro-painel .form__field { margin-bottom: 10px; }
.monitor-filtro-painel .form__field:last-child { margin-bottom: 0; }
/* Compacta o formulário pra caber na metade da altura da tela (layout
   empilhado, 20/08/2026): Data Inicial/Final lado a lado, e o slider de
   período junto com o botão "Atualizar" na mesma linha — sem isso o
   formulário (5 campos empilhados) ficava mais alto que a área disponível
   e o botão só aparecia rolando dentro do próprio painel de filtro. */
.monitor-filtro-datas { display: flex; gap: 10px; margin-bottom: 10px; }
.monitor-filtro-datas .form__field { flex: 1 1 0; min-width: 0; margin-bottom: 0; }
.monitor-filtro-slider-linha { display: flex; gap: 14px; align-items: flex-end; }
.monitor-filtro-slider-campo { flex: 1 1 auto; min-width: 0; margin-bottom: 0 !important; }
.monitor-filtro-slider-linha .btn { white-space: nowrap; }
.monitor-grafico-painel {
  min-width: 0; min-height: 0; display: flex; flex-direction: column;
}
/* Área rolável só do GRÁFICO (não da legenda, que fica sempre visível
   acima) — um gráfico de barra com muitas categorias pode pedir mais
   altura (JS define px fixo) do que sobrou pro painel; em vez de
   espremer as barras ou estourar a altura combinada dos 2 painéis, essa
   região rola sozinha. Gráfico de linha não seta altura própria — só
   preenche os 100% que sobrarem aqui. */
.monitor-grafico-scroll {
  flex: 1; min-height: var(--monitor-altura-grafico); overflow-y: auto;
}
.monitor-grafico-canvas-wrap { position: relative; height: 100%; min-height: var(--monitor-altura-grafico); }
/* Legenda (esquerda) + seletor de visualização (direita, sempre visível —
   fica FORA da área rolável do gráfico, 20/08/2026) na mesma linha,
   quebrando pra 2 linhas se a largura não alcançar. */
.monitor-grafico-topo {
  display: flex; flex-wrap: wrap; justify-content: space-between;
  align-items: flex-start; gap: 10px; margin-bottom: 10px;
}
.monitor-legenda { display: flex; flex-wrap: wrap; gap: 16px; font-size: 0.9rem; }
.monitor-legenda-item { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.monitor-legenda-cor {
  display: inline-block; width: 12px; height: 12px; border-radius: 50%;
}
.monitor-viz-campo {
  display: flex; align-items: center; gap: 6px; font-size: 0.85rem;
  color: var(--text-muted); white-space: nowrap;
}
.monitor-viz-select {
  font-size: 0.85rem; padding: 4px 8px; border-radius: var(--radius);
  border: 1px solid var(--input-border); background: var(--input-bg); color: var(--text);
}

/* Gestão de Contratos Financeiros (26/07/2026) — cores de situação
   exatas do VB6 (os valores &H... lá são BGR, não RGB — já convertidos). */
.cor-liberado, .cor-liberado td { color: #0000ff; }
.cor-avaliacao, .cor-avaliacao td { color: #ff8000; }
.cor-suspenso, .cor-suspenso td { color: #ff0000; }

/* Prevenção de Perdas (01/08/2026) — amarelo escuro pra "vence em breve",
   sem equivalente nas cores acima (a mais próxima, cor-avaliacao, é
   laranja, cor diferente pedida pelo usuário). */
.cor-vencimento-proximo, .cor-vencimento-proximo td { color: #8a6d00; }

/* Vendas dos PDVs (02/08/2026) — "Aberto" (&H8000& = verde escuro no VB6
   real), sem equivalente nas cores acima. */
.cor-aberto, .cor-aberto td { color: #008000; }

/* Resultados por Seção (28/07/2026): preenchimento de fundo de colunas
   específicas, a pedido do usuário, pra destacar visualmente os
   componentes do cálculo de Lucro. */
.bg-azul-claro { background-color: #d6e4f7; }
.bg-vermelho-claro { background-color: #f8d7da; }
.bg-amarelo-claro { background-color: #fff3cd; }
.bg-cinza-claro { background-color: #e9ecef; }

/* Resultados por Seção (28/07/2026): colunas Seção/Descrição (ou
   Produto/Descrição, no drill-down de itens — mesma classe reaproveitada
   nas duas grades, que têm os mesmos campos) congeladas durante a
   rolagem horizontal do grid (Total Saídas/CMV/Impostos/C Oper/Lucro
   ficam com muitas colunas à direita). */
.resultados-secao-grid__col-fixa {
  position: sticky;
  z-index: 1;
  background: #fff;
}
.resultados-secao-grid thead .resultados-secao-grid__col-fixa {
  z-index: 2;
  background: #fafbfc;
}
.resultados-secao-grid tbody tr:hover .resultados-secao-grid__col-fixa {
  background: #f7f9fb;
}
.resultados-secao-grid__col-fixa--1 { left: 0; width: 80px; min-width: 80px; }
.resultados-secao-grid__col-fixa--2 {
  left: 80px; width: 260px; min-width: 260px;
  box-shadow: 2px 0 4px -2px rgba(0, 0, 0, 0.15);
}

/* Remessas Bancárias (26/07/2026): coluna central com os botões >>/<<
   entre os dois grids de Títulos — cada grid continua dentro do seu
   próprio <form> independente (mais robusto pra submit), só que o form
   vira "display:contents" pra deixar os filhos (legenda/grid/botão)
   participarem diretamente do grid de 3 colunas do container pai. */
.grid-titulos-wrapper {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 16px;
  margin-top: 20px;
  align-items: start;
}
.form-contents { display: contents; }

/* Larguras padronizadas nas colunas COMPARTILHADAS pelos dois grids de
   Títulos de REMESSAS BANCÁRIAS (Ref/Título/Parc/R$ Valor não "dançam" mais
   de largura entre um grid e outro, então os cabeçalhos ficam alinhados de
   verdade).

   O seletor nomeia os dois grids de propósito (24/08/2026). Antes valia pra
   qualquer `table[data-grid-titulos]`, e a Gestão de Contratos usa esse
   atributo só pra o JS do "Marcar Todos" — herdava, sem querer, larguras
   pensadas pra outra tela. O efeito visível: a coluna "Contrato", cujo
   conteúdo tem 2 dígitos, ficava presa nos 160px da 5ª regra e abria um vão
   de 4cm até a coluna seguinte, além de forçar barra de rolagem horizontal.
   Largura por POSIÇÃO de coluna só faz sentido entre grids irmãos que
   precisam alinhar entre si. */
table[data-grid-titulos="sem-remessa"] th:nth-child(1), table[data-grid-titulos="sem-remessa"] td:nth-child(1),
table[data-grid-titulos="da-remessa"] th:nth-child(1), table[data-grid-titulos="da-remessa"] td:nth-child(1) { min-width: 32px; }
table[data-grid-titulos="sem-remessa"] th:nth-child(2), table[data-grid-titulos="sem-remessa"] td:nth-child(2),
table[data-grid-titulos="da-remessa"] th:nth-child(2), table[data-grid-titulos="da-remessa"] td:nth-child(2) { min-width: 64px; }
table[data-grid-titulos="sem-remessa"] th:nth-child(3), table[data-grid-titulos="sem-remessa"] td:nth-child(3),
table[data-grid-titulos="da-remessa"] th:nth-child(3), table[data-grid-titulos="da-remessa"] td:nth-child(3) { min-width: 72px; }
table[data-grid-titulos="sem-remessa"] th:nth-child(4), table[data-grid-titulos="sem-remessa"] td:nth-child(4),
table[data-grid-titulos="da-remessa"] th:nth-child(4), table[data-grid-titulos="da-remessa"] td:nth-child(4) { min-width: 48px; }
table[data-grid-titulos="sem-remessa"] th:nth-child(5), table[data-grid-titulos="sem-remessa"] td:nth-child(5),
table[data-grid-titulos="da-remessa"] th:nth-child(5), table[data-grid-titulos="da-remessa"] td:nth-child(5) { min-width: 160px; }
table[data-grid-titulos="sem-remessa"] th:nth-child(6), table[data-grid-titulos="sem-remessa"] td:nth-child(6),
table[data-grid-titulos="da-remessa"] th:nth-child(6), table[data-grid-titulos="da-remessa"] td:nth-child(6) { min-width: 90px; }
table[data-grid-titulos="sem-remessa"] th:nth-child(7), table[data-grid-titulos="sem-remessa"] td:nth-child(7),
table[data-grid-titulos="da-remessa"] th:nth-child(7), table[data-grid-titulos="da-remessa"] td:nth-child(7) { min-width: 78px; }
.piscof-grid-wrap .grid thead th { padding: 6px 12px; font-size: 0.72rem; position: sticky; top: 0; }
.piscof-grid-wrap .grid tbody td { padding: 5px 12px; font-size: 0.85rem; }

/* Sugestão de Compras (28/07/2026) — 11 colunas com padding padrão
   (20px de cada lado) não cabiam na tela sem rolar; aproxima as colunas
   mantendo a leitura, igual já foi feito em .piscof-grid-wrap. */
.sugestaocompras-grid-wrap .grid thead th { padding: 8px 10px; }
.sugestaocompras-grid-wrap .grid tbody td { padding: 6px 10px; }
.sugestaocompras-grid-wrap .grid input[type="number"] { width: 64px; }
.sugestaocompras-grid-wrap .grid .btn { padding: 2px 6px; font-size: 0.82rem; }

/* Ordens de Compra (28/07/2026) — mesmo ajuste (grade de Itens tem 12
   colunas, padding padrão de 20px por lado forçava rolagem desnecessária). */
.ordenscompra-grid-wrap .grid thead th { padding: 8px 10px; }
.ordenscompra-grid-wrap .grid tbody td, .ordenscompra-grid-wrap .grid tfoot td { padding: 6px 10px; }
.ordenscompra-grid-wrap .grid input[type="number"],
.ordenscompra-grid-wrap .grid input[type="text"] { padding: 4px 6px; }
.ordenscompra-grid-wrap .grid .btn { padding: 2px 6px; font-size: 0.82rem; }

/* Cotação de Preços (29/07/2026) — 4 grades (Itens/Participantes/Preços
   por Fornecedor/Desempate) empilhadas na mesma tela; padding padrão
   (20px/11px) deixava altura de linha e espaço entre colunas
   desproporcionais, mais evidente ainda ao lado da grade compacta do
   popup de Participantes (`.modal-arvore-tabela`, 6px). Pedido do
   usuário: compactar ao máximo — mesmo ajuste já usado em Sugestão de
   Compras/Ordens de Compra/PIS-COFINS, no nível mais compacto de todos
   (igual a `.piscof-grid-wrap`). */
.cotacao-grid-wrap .grid thead th { padding: 6px 12px; font-size: 0.72rem; }
.cotacao-grid-wrap .grid tbody td { padding: 5px 12px; font-size: 0.85rem; }
.cotacao-grid-wrap .grid input[type="text"],
.cotacao-grid-wrap .grid input[type="number"],
.cotacao-grid-wrap .grid input[type="email"],
.cotacao-grid-wrap .grid select { padding: 4px 6px; }
.cotacao-grid-wrap .grid .btn { padding: 2px 6px; font-size: 0.82rem; }

/* Gestão Financeira (02/08/2026) — grade de pesquisa (11 colunas +
   checkbox) e grade de Parcelas do editor, mesmo ajuste já usado nas
   telas irmãs de Compras. */
.gestaofinanceira-grid-wrap .grid thead th { padding: 6px 12px; font-size: 0.72rem; }
.gestaofinanceira-grid-wrap .grid tbody td, .gestaofinanceira-grid-wrap .grid tfoot td { padding: 5px 12px; font-size: 0.85rem; }
.gestaofinanceira-grid-wrap .grid input[type="text"],
.gestaofinanceira-grid-wrap .grid input[type="number"],
.gestaofinanceira-grid-wrap .grid select { padding: 4px 6px; }
.gestaofinanceira-grid-wrap .grid .btn { padding: 2px 6px; font-size: 0.82rem; }

/* Vendas dos PDVs (02/08/2026) — várias grades com muitas colunas,
   mesmo ajuste compacto já usado nas telas irmãs de Compras/Financeiro. */
.vendaspdv-grid-wrap .grid thead th { padding: 6px 12px; font-size: 0.72rem; }
.vendaspdv-grid-wrap .grid tbody td { padding: 5px 12px; font-size: 0.85rem; }

/* Cupom Fiscal selecionado na grade (Cupons Fiscais) — classe própria,
   não reaproveita `.cor-liberado` porque essa já é usada pra colorir o
   texto da situação "Baixado" (mesma cor azul), o que faria uma linha
   Baixada parecer "selecionada" mesmo sem ter sido clicada. */
.vendaspdv-cupom-selecionado td { background: #e7f0fe; }

/* Grades altas de Vendas dos PDVs (02/08/2026) — a principal de Cupons
   Fiscais pode ter centenas de linhas (uma por venda do dia), e a de
   Itens do cupom selecionado também pode ter bastante linha; pedido do
   usuário pra mostrar só ~4 linhas por vez em cada uma, com rolagem
   própria, deixando mais espaço de tela pro resto da tela. Reaproveitada
   nos dois grides (classe genérica, apesar do nome). */
.vendaspdv-grid-cupons { max-height: 160px; overflow-y: auto; }
.vendaspdv-grid-cupons .grid thead th { position: sticky; top: 0; background: var(--panel); z-index: 1; }

/* Mapa Resumo de Caixa (02/08/2026, layout corrigido em 03/08/2026 a
   partir de print real — ver CLAUDE.md seção 36.8) — mesmo ajuste
   compacto das telas irmãs de Compras/Financeiro/Vendas dos PDVs. */
.maparesumocaixa-grid-wrap .grid thead th { padding: 6px 12px; font-size: 0.72rem; }
.maparesumocaixa-grid-wrap .grid tbody td { padding: 5px 12px; font-size: 0.85rem; }

/* Linha de Data selecionada na grade principal — classe própria (não
   reaproveita `.cor-liberado`/`.cor-suspenso`, que já têm semântica de
   situação em outras telas; aqui é só destaque de seleção). */
.maparesumocaixa-linha-selecionada td { background: #e7f0fe; }

/* Cabeçalho (Filial/CNPJ/Razão Social/Data Inicial/Data Final) — grid
   de 6 colunas, campo de Razão Social ocupando 3 (mais largo, texto
   variável), fiel ao print real da tela. */
.maparesumocaixa-cabecalho {
  display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--campo-gap, 12px) 16px;
  border: none; padding: 0; margin: 0; min-width: 0;
}
@media (max-width: 900px) { .maparesumocaixa-cabecalho { grid-template-columns: repeat(2, 1fr); } }

.maparesumocaixa-toolbar { display: flex; gap: 8px; align-items: center; margin-top: 10px; flex-wrap: wrap; }

/* Painel de detalhe (Data selecionada) — espelha as colunas da grade
   principal como campos individuais, mesmo padrão "barra de
   ferramentas" (Editar/Gravar/Cancelar) já usado no resto do projeto —
   só o campo Observações é editável de verdade, o resto é sempre
   calculado/refletido da linha da grade. */
.maparesumocaixa-detalhe {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--campo-gap, 12px) 16px;
  border: none; padding: 0; margin: 12px 0 0;
}
.maparesumocaixa-detalhe fieldset { border: none; padding: 0; margin: 0; grid-column: 1 / -1; }
.maparesumocaixa-detalhe textarea { width: 100%; font: inherit; }
@media (max-width: 900px) { .maparesumocaixa-detalhe { grid-template-columns: repeat(2, 1fr); } }

/* Totais do Período pesquisado inteiro (linha própria, abaixo do
   detalhe) — sempre somente-leitura, não há edição de período. */
.maparesumocaixa-periodo {
  display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--campo-gap, 12px) 16px;
  border: none; padding: 0; margin: 0; min-width: 0;
}
@media (max-width: 900px) { .maparesumocaixa-periodo { grid-template-columns: repeat(2, 1fr); } }

/* Itens desabilitados (fora de escopo) dentro do dropdown "Rotinas" —
   mesma classe `.barra-ferramentas-dropdown` já usada pro "Imprimir"
   de `_barra_ferramentas.html`, só que aqui alguns itens são `<span>`
   em vez de `<a>` (sem destino real) — precisa do próprio padding.
   `opacity` reduzida (além da já existente `color: var(--text-muted)`)
   pra reforçar ainda mais o contraste com os links azuis acima — 2
   sinais diferentes (cor E transparência) em vez de só 1, pra não
   depender de calibração de tela pra dar pra distinguir. */
.barra-ferramentas-dropdown li span { display: block; padding: 6px 14px; font-size: 0.85rem; color: var(--text-muted); opacity: 0.6; cursor: not-allowed; }

/* Painéis de reconciliação Mapa×Import.PDVs (Lançamentos, seção 36.12)
   — "Vlr Dif" sempre em destaque (vermelho/negrito), mesma convenção
   já usada no resto do projeto pra divergência. */
.maparesumocaixa-dif { color: var(--error-text); font-weight: bold; }
.maparesumocaixa-reconciliacao {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--campo-gap, 12px) 16px;
  border: none; padding: 0; margin: 0; min-width: 0;
}
@media (max-width: 900px) { .maparesumocaixa-reconciliacao { grid-template-columns: repeat(2, 1fr); } }

/* Tela "Lançamentos" (seção 36.12) — 2 colunas (Caixas/contadores/
   Anotações/reconciliação à esquerda, Alíquotas/Finalizadoras à
   direita), mesmo espírito visual do print real. */
.maparesumocaixa-lancamentos-colunas { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; align-items: start; }
@media (max-width: 900px) { .maparesumocaixa-lancamentos-colunas { grid-template-columns: 1fr; } }

/* Campos com auto-salvamento inline na grade de Participantes (29/07/2026,
   Vendedor/Telefone/E-mail) — pedido do usuário: sem caixa (sem borda),
   só um fundo azul claro sinalizando que são editáveis, sem botão de
   salvar — grava sozinho ao perder o foco (ver JS em cotacao_form.html). */
.cotacao-campo-editavel {
  border: none; background: #e7f0fe; width: 100%;
  border-radius: 4px; font: inherit; color: inherit;
}
.cotacao-campo-editavel:focus { outline: 2px solid var(--primary); outline-offset: -2px; }

/* Sufixo "Dias" dentro do próprio campo (01/08/2026, pedido do usuário) —
   Entrega/Pagamento da grade de Participantes: em vez de um texto solto
   do lado de fora do campo, a unidade fica sobreposta DENTRO da caixa
   (input ganha padding-right pra sobrar espaço), lembrete visível mesmo
   com o campo já preenchido. `pointer-events:none` no sufixo pra não
   atrapalhar o clique/edição do campo por baixo dele. */
.cotacao-campo-com-sufixo { position: relative; }
.cotacao-campo-com-sufixo .cotacao-campo-sufixo {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  font-size: 0.72rem; color: var(--text-muted); pointer-events: none;
}

/* Painel "Geral" do popup de item (28/07/2026) — Estoques/Custos/
   Percentuais/histórico mensal, réplica da aba Geral do
   frmCOMPRASEVENDASITENS.frm real. */
.item-geral-tabela { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.item-geral-tabela td { padding: 2px 6px; border-bottom: 1px dotted var(--border); }
.item-geral-tabela td:first-child { color: var(--text-muted); }
.item-geral-tabela td:last-child { text-align: right; font-weight: 600; }

/* Popup de item de Ordem de Compra (28/07/2026) — mais alto que o
   .modal-arvore-caixa padrão (80vh) pra caber a aba "Geral" inteira sem
   rolar por dentro da rolagem do popup; `.item-aba` com altura mínima
   fixa (do tamanho da aba mais cheia, "Geral") pra trocar de aba não
   fazer a tela "pular" de tamanho. */
.ordenscompra-item-modal { max-height: 94vh; }
.item-aba { min-height: 480px; }

/* Popup "Adicionar à Ordem de Compra" — z-index abaixo do modal de lookup
   compartilhado (.modal-arvore padrão = 100, base.html), pra que o popup
   de busca de Fornecedor sempre fique por cima quando os dois estão
   abertos ao mesmo tempo. */
.sugestaocompras-dialog { z-index: 90; }

/* Grid "Itens em Ordens de Compra Abertas" (28/07/2026) — linha de
   cabeçalho de cada Ordem, separando visualmente os grupos. */
.sugestaocompras-ordem-cabecalho td { background: var(--primary-bg, #f0f4ff); font-weight: 600; }

/* Grids "Itens em Ordens de Compra Abertas" e "Itens em Cotações Abertas"
   (28/07/2026) — são duas <table> INDEPENDENTES com as mesmas 6 colunas
   (Produto/Descrição/Quantidade/Emb./Editar/Excluir), e o usuário pediu
   que ficassem perfeitamente alinhadas entre si. `min-width` (o padrão
   preferido do projeto, seção 2.15 do CLAUDE.md) não resolve aqui porque
   cada tabela tem seu PRÓPRIO texto de cabeçalho de grupo (nome de
   Fornecedor vs período da Cotação, larguras bem diferentes) — auto-layout
   deixaria cada tabela calcular colunas diferentes mesmo com o mesmo
   min-width declarado. `table-layout: fixed` com largura fixa por coluna
   garante que as duas tabelas fiquem sempre idênticas, independente do
   conteúdo de cada linha — a única coluna sem largura fixa (Descrição)
   ocupa o espaço restante, e o texto que não couber quebra linha em vez
   de estourar (aceitável aqui: a linha de cabeçalho de grupo é só
   informativa, não é um valor que precise ficar sempre visível inteiro
   numa linha só). */
.sugestaocompras-itens-grid { table-layout: fixed; width: 100%; }
.sugestaocompras-itens-grid th:nth-child(1), .sugestaocompras-itens-grid td:nth-child(1) { width: 90px; }
.sugestaocompras-itens-grid th:nth-child(3), .sugestaocompras-itens-grid td:nth-child(3) { width: 120px; }
.sugestaocompras-itens-grid th:nth-child(4), .sugestaocompras-itens-grid td:nth-child(4) { width: 70px; }
.sugestaocompras-itens-grid th:nth-child(5), .sugestaocompras-itens-grid td:nth-child(5) { width: 170px; }
.sugestaocompras-itens-grid th:nth-child(6), .sugestaocompras-itens-grid td:nth-child(6) { width: 90px; }
.sugestaocompras-itens-grid.grid tbody td {
  overflow-wrap: break-word; white-space: normal;
}
.piscof-grid-linha { cursor: pointer; }
.piscof-grid-linha:hover td { background: #f0f4fa; }
.piscof-grid-linha--selecionada td { background: var(--primary-bg, #f0f4ff); font-weight: 600; }
.piscof-grid-linha--capitulo td { font-weight: 600; }
.cadastro-generico-fieldset__legenda { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin: 0 0 6px; }
.piscof-grupos-topo { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.busca-generica--compacta input[type="search"] { width: 220px; }

/* Blocos de cada aba do formulário de Tipos de Notas Fiscais (Dados
   Cadastrais / Configurações) — precisam de display:contents quando
   visíveis (senão os campos ficam empilhados numa coluna só, perdendo
   o grid de 2 colunas do .form), e display:none quando escondidos
   (regra em separado porque display:contents sozinho ganha do
   [hidden] do navegador — mesma correção já validada no CFOP). */
.tiponf-aba-conteudo:not([hidden]) { display: contents; }
.tiponf-aba-conteudo[hidden] { display: none; }

/* Aba "Configurações" de Tipos de Notas Fiscais — layout de 3 colunas,
   igual ao VB6 original (coluna 1: checkboxes gerais; coluna 2: os 3
   quadros de emissão; coluna 3: Padrões para NF de Serviço). Não usa
   display:contents porque essa aba tem seu PRÓPRIO grid interno de 3
   colunas, não participa do grid de 2 colunas do .form pai. */
.tiponf-config-conteudo {
  grid-column: 1 / -1;
}
.tiponf-config-conteudo:not([hidden]) {
  display: grid; grid-template-columns: 1.6fr 1.3fr 1fr; gap: 0 20px; align-items: start;
}
.tiponf-config-conteudo[hidden] { display: none; }
.tiponf-config-col { display: flex; flex-direction: column; gap: 2px; }
.tiponf-config-col .form__field { margin-bottom: 6px; }
.tiponf-config-linha2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
@media (max-width: 900px) {
  .tiponf-config-conteudo:not([hidden]) { grid-template-columns: 1fr; }
}

/* Impressão de Etiquetas (Automação) — filtro em 3 grupos lado a lado
   (Modelo de etiqueta / Selecionar por / Configurações), cada um um
   fieldset próprio. `align-items: stretch` (padrão do flexbox, aqui
   explícito) faz os 3 ficarem do tamanho do maior automaticamente —
   os botões de ação não devem esticar junto, por isso `align-self:
   flex-start` neles. O subcampo do "Selecionar por" marcado (lookup ou
   campo de texto/data) fica FORA dos 3 frames, numa área própria
   abaixo, alinhada à mesma margem esquerda da linha de frames (pedido
   do usuário, 09/08/2026) — só um fica visível por vez (mesmo padrão
   [hidden] de outras telas). */
.etiquetas-filtro {
  display: flex; flex-wrap: wrap; gap: 20px; align-items: stretch;
}
.etiquetas-grupo {
  border: 1px solid var(--borda, #dde1e6); border-radius: 6px; padding: 12px 16px;
  min-width: 240px; flex: 1 1 260px;
}
.etiquetas-grupo legend { font-weight: 600; padding: 0 6px; }
.etiquetas-radios { display: flex; flex-direction: column; gap: 4px; }
.etiquetas-radios label { font-weight: 400; display: flex; align-items: center; gap: 6px; }
.etiquetas-acoes { align-self: flex-start; flex-wrap: wrap; }
#etq-opcoes-barras, #etq-opcoes-gondolas { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; padding-left: 18px; }
#etq-opcoes-barras label, #etq-opcoes-gondolas label { font-weight: 400; }
.etiquetas-subcampos { margin-top: 20px; }
.etiquetas-subcampo[hidden] { display: none; }
.etiquetas-subcampo textarea { width: 100%; }
/* Larguras pedidas pelo usuário (09/08/2026) só pros lookups desta área
   (não mexe no `.lookup-generico` padrão usado no resto do sistema). */
.etiquetas-subcampos .lookup-generico-linha .lookup-generico-codigo { width: 5cm; flex: 0 0 5cm; }
.etiquetas-subcampos .lookup-generico-linha .lookup-generico-descricao { width: 20cm; flex: 0 0 20cm; }

/* Tela C (impressão) — etiqueta física em tamanho real (mm), 1 por
   "página" via @page, campos posicionados absolutamente em cima do
   bloco (ver templates/etiquetas_imprimir.html). */
.etiqueta-etq { position: relative; overflow: hidden; }
.etiqueta-etq .campo-etq { position: absolute; white-space: nowrap; line-height: 1; }
.etiqueta-etq .campo-etq img { display: block; }

/* Editor de layout de etiqueta (canvas de arrastar) — 4px por mm, ver
   templates/etiquetas_layout.html. Sem lib de drag-and-drop no projeto
   até aqui; construído do zero com mousedown/mousemove/mouseup. */
.etq-editor { display: flex; gap: 24px; flex-wrap: wrap; align-items: flex-start; }
.etq-canvas {
  position: relative; background: #fff; border: 2px solid #1f2430;
  background-image: linear-gradient(#eef0f2 1px, transparent 1px), linear-gradient(90deg, #eef0f2 1px, transparent 1px);
  background-size: 4mm 4mm; flex: 0 0 auto;
}
/* Campo NOVO preso ao ponteiro (28/09/2026): o cursor e o contorno são o
   que dizem que falta um clique para soltá-lo. Sem sinal, quem clicou em
   "+ Campo" e não viu nada acontecer clica de novo, e sai com dois. */
.etq-canvas--soltando { cursor: crosshair; outline: 2px dashed var(--primary); outline-offset: 2px; }

.etq-elemento {
  position: absolute; cursor: move; padding: 1px 3px; white-space: nowrap;
  border: 1px dashed #9aa2ad; background: rgba(255,255,255,.85); user-select: none;
}
.etq-elemento--selecionado { border: 1px solid #2563eb; background: rgba(219,234,254,.9); }
.etq-editor-painel { flex: 0 0 300px; display: flex; flex-direction: column; gap: 16px; }

/* Sistema de "cards de seção" — introduzido em 11/08/2026 na tela de
   Importação de XML (notasfiscais_importar.html), generalizado no mesmo
   dia pro popup de item de Notas Fiscais (notasfiscais_revisar.html) e
   reutilizável em qualquer tela nova que precise agrupar campos
   visualmente. `.secao-grade` é o grid externo (2 colunas, cards largos
   via `--larga`); `.secao-cartao--*` são variantes de cor (mesmo espírito
   dos blocos coloridos ICMS/ST/FCP/IPI/Livro já usados no popup de item,
   agora com o MESMO padrão de card/título/ícone das demais seções, em vez
   de `<div style="background:...">` soltos). Campos DENTRO de um
   `.secao-cartao__corpo` sempre usam grid com `minmax()` (nunca coluna
   fixa mais estreita que o mínimo real de um `.lookup-generico-linha`,
   116px — foi exatamente esse erro que quebrou o popup de item antes
   desta entrega, coluna de 1fr/70-90px pra campo de lookup, forçando
   overflow horizontal do modal inteiro). */
.secao-grade {
  display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start;
}
.secao-cartao {
  background: #fbfcfd; border: 1px solid var(--border); border-radius: 10px;
  padding: 20px 22px; box-shadow: 0 1px 3px rgba(20, 30, 50, 0.04);
}
.secao-cartao--larga { grid-column: 1 / -1; }
.secao-cartao__titulo {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 16px; font-size: 0.95rem; font-weight: 700; color: var(--text);
}
.secao-cartao__icone {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 8px; font-size: 1rem;
  background: rgba(37, 99, 166, 0.1); flex-shrink: 0;
}
.secao-cartao__corpo { display: flex; flex-direction: column; gap: 14px; }
.secao-cartao__corpo .form__field { margin-bottom: 0; }
.secao-cartao__corpo select { width: 100%; }
.secao-cartao__ajuda {
  font-size: 0.78rem; color: var(--text-muted); margin: -8px 0 0; line-height: 1.4;
}
.secao-cartao__campos {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 12px 14px;
}
.secao-cartao__campos .lookup-generico { grid-column: span 2; min-width: 220px; }

/* Variante de grid fixo de 12 colunas — cada campo declara seu próprio
   `grid-column: span N` (inline, no HTML) em vez de depender do
   `auto-fill` acima. `auto-fill`+`minmax` calcula um número de colunas
   IMPLÍCITO a partir da largura do container, que pode diferir entre
   linhas com totais de span diferentes (uma linha com lookups "span 2"
   ocupa proporcionalmente mais unidades que uma linha só de campos
   simples) — o resultado visual são campos que não alinham verticalmente
   entre si, mesmo dentro do mesmo cartão (achado 14/08/2026, popup de
   item de Notas Fiscais). Só usar em telas onde TODOS os campos do
   `.secao-cartao__campos` declaram `grid-column: span N` explicitamente
   — não é drop-in replacement do padrão `auto-fill` acima. */
.secao-cartao__campos--fixo12 { grid-template-columns: repeat(12, 1fr); }
.secao-cartao__campos--fixo12 > * { min-width: 0; }
.secao-cartao__campos--fixo12 .lookup-generico { min-width: 0; }
@media (max-width: 639px) {
  .secao-cartao__campos--fixo12 { grid-template-columns: 1fr; }
  .secao-cartao__campos--fixo12 > * { grid-column: 1 / -1 !important; }
}

/* Variante de 3 colunas fixas (Substituição em Massa, 19/08/2026) — igual
   espírito do --fixo12 acima, mas pra painéis de Filtro onde 3 colunas já
   é a largura ideal (os campos são majoritariamente pequenos — número,
   Sim/Não, data). Cada coluna aqui já fica larga o bastante (painel
   inteiro ÷ 3) pra um `.lookup-generico` caber sozinho numa coluna só —
   por isso a regra global `.secao-cartao__campos .lookup-generico
   { grid-column: span 2 }` (linha ~1890, pensada pro grid `auto-fill` de
   colunas ~110px de outras telas) é anulada aqui de propósito
   (`span 1`), senão só 1 lookup cabia por linha nas 3 colunas — pedido
   do usuário foi "pelo menos 3 lookups lado a lado". Chegou a virar
   `auto-fill` dinâmico (pra "comprimir os espaços" do GRID) por
   engano — usuário corrigiu que o pedido era sobre a GRADE DE
   RESULTADOS, não este painel, e que esta versão de 3 colunas fixas
   era a melhor mesmo; revertido de volta pra este estado. */
.secao-cartao__campos--fixo3 { grid-template-columns: repeat(3, 1fr); }
.secao-cartao__campos--fixo3 > * { min-width: 0; }
.secao-cartao__campos--fixo3 .lookup-generico { min-width: 0; grid-column: span 1; }
@media (max-width: 900px) {
  .secao-cartao__campos--fixo3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 639px) {
  .secao-cartao__campos--fixo3 { grid-template-columns: 1fr; }
  .secao-cartao__campos--fixo3 > * { grid-column: 1 / -1 !important; }
}

/* Variantes de cor — mesma paleta de frmNFEIMPORTACAOITEM.frm (skill
   grp-notasfiscais 3.2/3.7): ICMS laranja, ST verde, FCP amarelo, IPI
   rosa, Livro azul. */
.secao-cartao--icms { background: #fdf3e4; border-color: #f3ddb0; }
.secao-cartao--icms .secao-cartao__icone { background: rgba(196, 130, 20, 0.16); }
.secao-cartao--st { background: #ecf8ec; border-color: #c9e8c9; }
.secao-cartao--st .secao-cartao__icone { background: rgba(30, 107, 58, 0.14); }
.secao-cartao--fcp { background: #fdf9dd; border-color: #ecdf9e; }
.secao-cartao--fcp .secao-cartao__icone { background: rgba(163, 138, 12, 0.16); }
.secao-cartao--ipi { background: #fdecee; border-color: #f2c6cb; }
.secao-cartao--ipi .secao-cartao__icone { background: rgba(179, 57, 44, 0.14); }
.secao-cartao--livro { background: #eaf1fb; border-color: #c6d9f2; }
.secao-cartao--livro .secao-cartao__icone { background: rgba(37, 99, 166, 0.16); }

/* 3 variantes novas (Substituição em Massa, 19/08/2026, pedido do
   usuário) — mesmo espírito/paleta das acima, cor por cartão pra
   diferenciar visualmente Filtro/Tipo de Substituição/Parâmetros à
   primeira vista. */
.secao-cartao--azul-claro { background: #eaf1fb; border-color: #c6d9f2; }
.secao-cartao--azul-claro .secao-cartao__icone { background: rgba(37, 99, 166, 0.16); }
.secao-cartao--laranja { background: #fdecda; border-color: #f3c894; }
.secao-cartao--laranja .secao-cartao__icone { background: rgba(196, 120, 20, 0.18); }
.secao-cartao--lilaz { background: #f2ecfa; border-color: #d9c6ef; }
.secao-cartao--lilaz .secao-cartao__icone { background: rgba(124, 58, 207, 0.16); }

/* Lookups nos 3 cartões coloridos acima (Substituição em Massa,
   19/08/2026) — o campo de descrição de um `.lookup-generico` é
   `readonly` e por padrão ganha fundo cinza claro (`.form__field
   input[readonly]`, #f0f1f3, regra global) pra sinalizar "não
   editável" — mas #f0f1f3 quase não contrasta com o fundo pastel do
   cartão (`--azul-claro` principalmente, tom bem parecido). Pedido do
   usuário: branco puro só aqui, pra destacar o campo contra a cor do
   cartão — não mexe no cinza padrão usado no resto do sistema (lá o
   cinza É o contraste, contra um cartão branco). */
.secao-cartao--azul-claro .lookup-generico-descricao[readonly],
.secao-cartao--laranja .lookup-generico-descricao[readonly],
.secao-cartao--lilaz .lookup-generico-descricao[readonly] {
  background: #ffffff;
}

/* Barra "Registros encontrados: N / Marcar Todos / Substituir" fixa
   durante a rolagem da grade (Substituição em Massa, 19/08/2026,
   pedido do usuário) — o `.grid thead th` já é sticky (`top:0`, regra
   global) contra o próprio `.grid-wrap` (que rola sozinho, `overflow-y:
   auto; max-height:480px`); esta barra fica ACIMA da tabela dentro do
   mesmo `.grid-wrap`, então também precisa de `position:sticky` pra
   não rolar junto com as linhas. Como a barra passa a ocupar o
   `top:0`, o cabeçalho da tabela precisa descer pra logo abaixo dela —
   a altura real da barra varia (Tipos com botão auxiliar extra, texto
   de "mostrando os 500 primeiros" quebrando linha), por isso o `top`
   do thead é calculado em JS (ver script no fim do arquivo), não um
   valor fixo aqui. */
#grade-resultados .sm-resultados-cabecalho {
  position: sticky; top: 0; z-index: 2; background: #fff;
  padding: 6px 0; margin-bottom: 0;
}
#grade-resultados table.grid thead th { background: #fff; }

.opcoes-grade { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
@media (max-width: 900px) { .opcoes-grade { grid-template-columns: 1fr; } }
.opcao-cartao {
  display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 8px; background: #fff;
  cursor: pointer; transition: border-color .12s, background .12s;
}
.opcao-cartao:hover { border-color: var(--primary); background: #f5f9ff; }
.opcao-cartao input[type="checkbox"] {
  width: 18px; height: 18px; margin-top: 2px; accent-color: var(--primary); flex-shrink: 0; cursor: pointer;
}
.opcao-cartao__texto { display: flex; flex-direction: column; gap: 2px; }
.opcao-cartao__texto strong { font-size: 0.86rem; color: var(--text); font-weight: 600; }
.opcao-cartao__texto small { font-size: 0.78rem; color: var(--text-muted); line-height: 1.35; }

@media (max-width: 900px) {
  .secao-grade { grid-template-columns: 1fr; }
}

/* Importação de XML de NF-e (Notas Fiscais) — zona de arrastar-arquivo,
   ver templates/notasfiscais_importar.html. */
.nfimport-intro {
  color: var(--text-muted); margin: 0 0 24px; max-width: 720px; line-height: 1.5;
}
.nfimport-drop {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; text-align: center; padding: 32px 20px; border: 2px dashed var(--border);
  border-radius: 10px; background: #fff; cursor: pointer; transition: border-color .12s, background .12s;
}
.nfimport-drop:hover, .nfimport-drop--sobre { border-color: var(--primary); background: #f5f9ff; }
.nfimport-drop--preenchido { border-style: solid; border-color: var(--success-text); background: var(--success-bg); }
.nfimport-drop__icone { font-size: 2rem; line-height: 1; opacity: .7; }
.nfimport-drop__titulo { font-weight: 600; color: var(--text); font-size: 0.92rem; }
.nfimport-drop__legenda { font-size: 0.78rem; color: var(--text-muted); }
.nfimport-drop__nome { font-size: 0.85rem; color: var(--success-text); font-weight: 600; word-break: break-all; }
.nfimport-drop input[type="file"] { display: none; }

.nfimport-rodape {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; margin-top: 24px; padding-top: 18px; border-top: 1px solid var(--border);
  flex-wrap: wrap;
}
.nfimport-obrigatorios { font-size: 0.78rem; color: var(--text-muted); margin: 0; }
.btn--large { padding: 12px 28px; font-size: 0.95rem; }

/* =====================================================================
   Notas Fiscais — EMISSÃO, harmonização visual contra frmEMISSAODENF/
   frmITENSEMISSAONF (15/08/2026, skill grp-notasfiscais 8-30decies).
   Prefixo `.nfem-*` — só a tela de revisão de Emissão e o popup de item.
   ===================================================================== */
.nfem-topo { display: grid; grid-template-columns: minmax(0, 1fr) 215px; gap: 14px; align-items: start; }
@media (max-width: 1000px) { .nfem-topo { grid-template-columns: 1fr; } }
.nfem-cabecalho { min-width: 0; }
.nfem-cartao { margin: 0; }
.nfem-grid { gap: 8px 10px; }
.nfem-grid .form__field label { font-size: 0.72rem; }
.nfem-grid .form__field input, .nfem-grid .form__field select { padding: 5px 7px; font-size: 0.86rem; }
.nfem-amarelo { background: #fff9c4 !important; font-weight: 600; text-transform: uppercase; }
.nfem-regime { color: #c0392b !important; font-weight: 600; }
.nfem-numero { color: #c0392b !important; font-weight: 700; }

/* Painel lateral "Situação" — fora do form (o dropdown Ferramentas tem forms). */
.nfem-situacao { border: 1px solid var(--border, #d7dbe0); border-radius: 8px; padding: 10px 12px; background: var(--panel, #fff); display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.nfem-situacao__legenda { margin: 0; font-size: 0.72rem; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted, #6b7280); }
.nfem-situacao__estado { text-align: center; }
.nfem-situacao__estado .badge { font-size: 0.95rem; padding: 6px 14px; }
.nfem-situacao__ferramentas { display: flex; justify-content: center; }
.nfem-situacao__ferramentas .barra-ferramentas-dropdown { width: 100%; }
.nfem-situacao__ferramentas .barra-ferramentas-dropdown > summary { width: 100%; justify-content: center; }
.nfem-situacao__nfe { border: 1px solid var(--border, #d7dbe0); border-radius: 6px; padding: 6px 10px 8px; margin: 0; display: flex; flex-direction: column; gap: 4px; font-size: 0.82rem; }
.nfem-situacao__nfe legend { font-size: 0.72rem; color: var(--text-muted, #6b7280); padding: 0 4px; }
.nfem-situacao__datas { display: flex; flex-direction: column; gap: 6px; }
.nfem-situacao__datas .form__field label { font-size: 0.72rem; }
.nfem-situacao__datas .form__field input { padding: 4px 6px; font-size: 0.84rem; }

/* Barra de Totais (SSPEMISSAONF(0)) — 3 linhas de "caixinhas" com rótulo em
   maiúsculas em cima e valor embaixo alinhado à direita, bordas finas. */
.nfem-totais { border: 1px solid var(--border, #d7dbe0); border-radius: 6px; padding: 6px; background: #fbfcfd; display: flex; flex-direction: column; gap: 4px; margin: 6px 0 4px; }
.nfem-totais__linha { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 4px; }
.nfem-totais__linha--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.nfem-tot { border: 1px solid #cfd4da; background: #fff; border-radius: 3px; padding: 3px 6px 4px; min-width: 0; display: flex; flex-direction: column; }
.nfem-tot label { font-size: 0.6rem; text-transform: uppercase; letter-spacing: .02em; color: #4b5563; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin: 0 0 2px; }
.nfem-tot span, .nfem-tot--edit input { display: block; width: 100%; box-sizing: border-box; height: 1.35rem; line-height: 1.35rem; padding: 0; margin: 0; font: inherit; font-size: 0.86rem; font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; color: inherit; }
/* Campos digitáveis da barra (Desc. Tributado/Estorno Desc.) têm o MESMO
   visual das células só-leitura — sem caixa/borda própria; só ao focar aparece
   um sublinhado discreto (pedido do usuário, 15/08/2026). */
.nfem-tot--edit input { background: transparent; border: 0; border-bottom: 1px solid transparent; border-radius: 0; outline: none; }
.nfem-tot--edit input:focus { border-bottom-color: #2563eb; background: #f5f9ff; }
.nfem-tot--edit input:disabled { color: inherit; opacity: 1; -webkit-text-fill-color: inherit; }
.nfem-tot--destaque { background: #eef6ff; }
.nfem-tot--destaque span { color: #1d4ed8; }
@media (max-width: 900px) { .nfem-totais__linha, .nfem-totais__linha--5 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.nfem-grade-itens tbody tr { cursor: pointer; }

/* Popup "Lançamento do Item" (frmITENSEMISSAONF) — abas + fieldsets no
   estilo "Frame" do VB6, compactos. */
.nfem-item-produto { margin-bottom: 8px; }
/* Código/EAN mais largo que os 70px padrão do lookup (cabe EAN-13); Referência estreita (pedido do usuário, 15/08/2026). */
.nfem-item-produto .lookup-generico-linha .lookup-generico-codigo { flex: 0 0 170px; }
.nfem-item-abas { margin-bottom: 8px; }
.nfem-item-aba:not([hidden]) { display: block; }
.nfem-item-aba[hidden] { display: none; }
/* Sub-abas aninhadas da aba IBS/CBS (16/08/2026) — mesmo padrão acima
   (CLAUDE.md §2.4: sempre usar :not([hidden]) contra especificidade CSS
   de outras classes, nunca só "display: block" fixo). */
[data-nfi-ibscbs-conteudo]:not([hidden]) { display: block; }
[data-nfi-ibscbs-conteudo][hidden] { display: none; }
[data-nfi-ibs-conteudo]:not([hidden]) { display: block; }
[data-nfi-ibs-conteudo][hidden] { display: none; }
.nfem-fs { border: 1px solid #cfd4da; border-radius: 6px; padding: 6px 10px 8px; margin: 0 0 8px; min-width: 0; }
.nfem-fs legend { font-size: 0.74rem; font-weight: 600; color: #374151; padding: 0 4px; }
.nfem-fs .form__field label { font-size: 0.7rem; }
.nfem-fs .form__field input, .nfem-fs .form__field select { padding: 4px 6px; font-size: 0.84rem; }
.nfem-fs .checkbox-label { font-size: 0.82rem; }
.nfem-fs__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 6px 10px; }
.nfem-fs__grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.nfem-fs__grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.nfem-fs__grid--8 { grid-template-columns: repeat(8, minmax(0, 1fr)); }
.nfem-fs__grid > * { min-width: 0; }
.nfem-fs--icms { background: #fff4e5; }
.nfem-fs--st { background: #eaf7ea; }
.nfem-fs--fcp { background: #fffbe0; }
.nfem-fs--placeholder { opacity: .6; }
.nfem-minigrid { font-size: 0.78rem; }
.nfem-minigrid th, .nfem-minigrid td { padding: 3px 6px; }
.nfem-minigrid td input { width: 100%; padding: 2px 4px; font-size: 0.8rem; text-align: right; }
.nfem-atencao { margin: 8px 0 0; font-size: 0.78rem; font-weight: 600; color: #b45309; }
.nfem-item-rodape { display: flex; justify-content: flex-end; gap: 10px; margin-top: 10px; border-top: 1px solid var(--border, #d7dbe0); padding-top: 10px; }
/* Aba "Gás" (SSPITEMNF(10), "Detalhamento Específico de Combustíveis") —
   linhas label-à-esquerda/campo-numérico-à-direita, igual ao print real
   (16/08/2026). */
.nfem-gas-linha { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 4px 0; font-size: 0.82rem; }
.nfem-gas-linha label { flex: 1 1 auto; }
.nfem-gas-linha input { flex: 0 0 auto; width: 110px; text-align: right; padding: 4px 6px; font-size: 0.84rem; }
.nfem-gas-linha input#nfi-gas-ufconsumo { width: 46px; text-align: center; }
@media (max-width: 900px) { .nfem-fs__grid--3, .nfem-fs__grid--8 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* fieldset nasce com min-inline-size:min-content — impede encolher dentro do
   grid do popup (conteúdo estourava a caixa de 1100px). */
#form-item-emissao fieldset, .nfem-fs { min-inline-size: 0; }
#dialog-item-emissao .modal-arvore-conteudo { overflow-x: hidden; }
.nfem-minigrid { width: 100%; min-width: 0; table-layout: auto; }
.nfem-minigrid td input { min-width: 0; width: 100%; max-width: 110px; }
.nfem-fs .form__field { min-width: 0; }
.nfem-fs .form__field input, .nfem-fs .form__field select { min-width: 0; width: 100%; }
.nfem-minigrid th, .nfem-minigrid td { white-space: normal; }
.nfem-minigrid-wrap { overflow-x: auto; max-width: 100%; }
/* "Outros Valores" (Frete/Seguro/Despesas) — visual de planilha, mais
   compacto e sem moldura em volta de cada campo (pedido do usuário,
   16/08/2026): linhas separadas por um traço fino em vez de cada `input`
   parecer uma caixa de formulário solta. */
.nfem-minigrid--planilha td { padding: 2px 6px; }
.nfem-minigrid--planilha tbody tr:not(:last-child) td { border-bottom: 1px solid var(--border); }
.nfem-minigrid--planilha td input { border: none; background: transparent; border-radius: 3px; }
.nfem-minigrid--planilha td input:focus { outline: none; background: var(--focus-glow); }
.nfem-minigrid--planilha td input[readonly] { color: var(--text-muted); }

/* --------------------------------------------------------------------
   SQL Command (Manutenção) — tela de execução livre de SQL, equivalente
   a SQL.frm. Editor (CodeMirror vendorizado) + grade de resultado com
   colunas dinâmicas (a consulta é arbitrária) + sidebar de abas.
   -------------------------------------------------------------------- */
.sqlcommand-layout { display: grid; grid-template-columns: 1fr 320px; gap: 16px; align-items: start; }
@media (max-width: 900px) { .sqlcommand-layout { grid-template-columns: 1fr; } }
.sqlcommand-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 10px; }
.sqlcommand-toolbar .checkbox-label { margin: 0; }
.sqlcommand-editor-wrap .CodeMirror {
  height: 240px; border: 1px solid var(--input-border); border-radius: var(--radius);
  font-family: "Lucida Console", Consolas, monospace; font-size: 0.88rem;
}
.sqlcommand-editor-wrap .CodeMirror-focused { border-color: var(--primary); box-shadow: 0 0 0 3px var(--focus-glow); }
.sqlcommand-resultado-cabecalho { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin: 14px 0 8px; }
.sqlcommand-badge-tipo {
  display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 0.75rem;
  font-weight: 700; letter-spacing: .02em; background: #eef0f2; color: var(--text-muted);
}
.sqlcommand-badge-tipo--leitura { background: rgba(37, 99, 166, 0.14); color: var(--primary-dark); }
.sqlcommand-badge-tipo--escrita { background: rgba(196, 120, 20, 0.18); color: #8a5a0c; }
.sqlcommand-badge-tipo--ddl { background: rgba(179, 57, 44, 0.16); color: var(--danger); }
.sqlcommand-paginacao { display: flex; align-items: center; gap: 8px; font-size: 0.85rem; }
.sqlcommand-paginacao input { width: 60px; text-align: center; }
.sqlcommand-sidebar { border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); overflow: hidden; }
.sqlcommand-aba-btns { display: flex; border-bottom: 1px solid var(--border); }
.sqlcommand-aba-btn {
  flex: 1; padding: 9px 6px; text-align: center; font-size: 0.82rem; background: none; border: none;
  cursor: pointer; color: var(--text-muted); border-bottom: 2px solid transparent;
}
.sqlcommand-aba-btn--ativa { color: var(--primary); border-bottom-color: var(--primary); font-weight: 600; }
.sqlcommand-aba { display: none; padding: 10px; max-height: 480px; overflow-y: auto; }
.sqlcommand-aba--ativa { display: block; }
.sqlcommand-lista-item {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  padding: 6px 8px; border-radius: 4px; cursor: pointer; font-size: 0.82rem;
}
.sqlcommand-lista-item:hover { background: #f7f9fb; }
.sqlcommand-lista-item__texto { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sqlcommand-lista-item__excluir { color: var(--danger); background: none; border: none; cursor: pointer; font-size: 0.9rem; padding: 0 2px; }
.sqlcommand-lista-vazia { color: var(--text-muted); font-size: 0.82rem; padding: 6px 8px; }
.sqlcommand-tabela-item { font-size: 0.82rem; }
.sqlcommand-tabela-item summary { cursor: pointer; padding: 4px 2px; }
.sqlcommand-tabela-item summary:hover { color: var(--primary); }
.sqlcommand-tabela-item__colunas { color: var(--text-muted); padding: 2px 0 6px 14px; word-break: break-word; }
.sqlcommand-filtro-tabela { width: 100%; margin-bottom: 8px; }
#dialog-sqlcommand-confirmar { max-width: 560px; width: 92vw; }
#dialog-sqlcommand-confirmar pre {
  background: #f7f9fb; border: 1px solid var(--border); border-radius: 4px; padding: 8px;
  max-height: 140px; overflow: auto; font-size: 0.8rem; white-space: pre-wrap; word-break: break-word;
}
.sqlcommand-aviso { background: var(--aviso-bg); border: 1px solid var(--aviso-borda); border-radius: 4px; padding: 8px 10px; font-size: 0.85rem; margin: 8px 0; }

/* Logs de Operações (Manutenção) — equivalente a frmDIARIO modo 0. A
   coluna Descrição foge de propósito da regra geral de grid (seção
   2.15, nowrap+scroll horizontal): textos de log são frases inteiras,
   melhor legibilidade com quebra de linha normal do que rolagem lateral. */
.grid--logsgrp__operacao { white-space: normal; word-break: break-word; }

/* NFS-e (22/08/2026) — barra de ícones inspirada no Portal Contribuinte
   do Sistema Nacional NFS-e (Nova NFS-e/Notas Emitidas/Notas Recebidas/
   Rascunhos/Configurações), acima do painel em toda tela do módulo. */
.nfse-barra-superior { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
/* `.dropdown-imprimir ul` original assume o botão no canto DIREITO de uma
   barra (`right:0`, abre pra esquerda) — aqui "Nova NFS-e" é o primeiro
   botão (esquerda da barra), então o menu tem que abrir pra direita, senão
   fica cortado fora do painel. */
.nfse-barra-superior .dropdown-imprimir ul { right: auto; left: 0; min-width: 280px; }
.nfse-filtro-periodo { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; margin-bottom: 16px; }
.nfse-filtro-periodo .form__field { margin: 0; }

/* Importação de Dados Legados — tela de escolha de tabelas (23/08/2026).
   Linha sem destino identificado / com destino apenas SUGERIDO por
   estrutura ficam visualmente separadas do caso certo (nome igual ou
   renome conhecido), porque só o caso certo vem marcado sozinho. */
.importacao-sem-destino > td { opacity: .72; }
.importacao-sugerida > td { background: var(--aviso-bg); }
.importacao-destino {
  width: 100%;
  min-width: 190px;
  font-size: .82rem;
  padding: 3px 6px;
}

/* Seletor de FILIAL ATIVA no topo (23/08/2026, multifilial — CLAUDE.md §1.4).
   Fica ao lado do nome do operador; some sozinho quando só existe uma filial
   ou quando o operador não tem permissão de trocar. */
.topbar__filial { display: flex; align-items: center; gap: 6px; margin-right: 14px; }
.topbar__filial label { font-size: .78rem; opacity: .85; }
/* SÓLIDO, não translúcido — e a razão é um bug de plataforma, não gosto.
   O Chrome no Windows aplica o fundo da `option` ao select FECHADO; com
   `option { background: var(--panel) }` (branco) e `select { color:
   var(--barra-texto) }` (branco), o campo virava BRANCO SOBRE BRANCO e a
   filial em uso sumia da barra. No Linux e no Firefox o select fechado
   ignora a regra da option, então o defeito só aparecia no Windows —
   achado por print do usuário em 06/09/2026.
   Fundo claro e texto escuro, iguais no select e na option: renderiza o
   mesmo em toda plataforma, e não depende de qual das duas regras o
   navegador resolve primeiro. */
.topbar__filial select {
  font-size: .8rem; padding: 2px 6px; max-width: 230px;
  border-radius: var(--radius); border: 1px solid rgba(255,255,255,.35);
  background: #fff; color: var(--text);
}
.topbar__filial select option { color: var(--text); background: #fff; }
.topbar__filial-fixa { font-size: .78rem; opacity: .85; margin-right: 14px; }

/* Seleção de FILIAIS nos relatórios (23/08/2026, multifilial — CLAUDE.md §1.4).
   Lista de marcação com rolagem: com 10 lojas ainda cabe na tela, com 40 não
   empurra o resto do formulário pra baixo. */
.relatorio-filiais-caixa {
  border: 1px solid var(--input-border); border-radius: var(--radius);
  background: var(--input-bg); padding: 6px 8px; max-height: 118px; overflow-y: auto;
}
.relatorio-filiais-item { display: flex; align-items: center; gap: 6px; font-weight: normal; margin: 2px 0; }
.relatorio-filiais-item input { width: 16px; height: 16px; min-height: auto; margin: 0; flex: 0 0 auto; }
.relatorio-filiais-item span { font-size: .82rem; }
.relatorio-filiais-dica { display: block; margin-top: 3px; font-size: .72rem; color: var(--text-muted); }

/* CÓDIGO do relatório (VND005): fica FORA da tela por decisão do usuário
   (23/08/2026) — o rótulo mostra só o nome limpo. O código continua vivo
   como chave de BUSCA (atributo `data-relatorio-arquivo` na árvore, token
   próprio na busca por características) e no tooltip do item, pra quem
   decorou o código do sistema antigo continuar achando. */

/* Campo CÓDIGO do relatório (23/08/2026): número curto e estável, mostrado
   na frente do nome na árvore e nos resultados de busca. Largura fixa pra
   os nomes ficarem alinhados entre si, como uma coluna de verdade. */
.arvore-link--folha, .arvore-link--raiz { display: flex; align-items: baseline; gap: 8px; }
.relatorio-codigo {
  flex: 0 0 auto;
  min-width: 2.6em;
  text-align: right;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: .74rem;
  color: var(--text-muted);
}
.relatorio-nome { flex: 1 1 auto; min-width: 0; }
.arvore-link--ativo .relatorio-codigo { color: inherit; }

/* Primeiro acesso de uma empresa recém-ativada (23/08/2026) — a tela que
   pergunta se os dados de partida do GRP legado devem ser importados. */
.primeiro-acesso__empresa { font-size: .95rem; line-height: 1.6; margin: 0 0 22px; }
.primeiro-acesso__pergunta { font-size: 1.15rem; margin: 0 0 8px; }
.primeiro-acesso__texto { max-width: 68ch; color: var(--text-muted); font-size: .92rem; margin: 0 0 22px; }
.primeiro-acesso__opcoes { display: flex; flex-direction: column; gap: 12px; }
.primeiro-acesso__opcoes form { display: flex; align-items: center; gap: 12px; padding: 0; margin: 0; }
.primeiro-acesso__opcoes .btn { min-width: 190px; }

/* Grade "Este produto em cada loja" (23/08/2026) — equivalente ao
   LvPRODUTOSFILIAIS do VB6, abaixo das abas do cadastro de Produtos. */
/* `min-width: 0` não é enfeite: item de grid/flex nasce com `min-width: auto`,
   então a faixa cresce até caber a tabela inteira (1916px) e a rolagem do
   `.grid-wrap` nunca chega a existir — a tabela some pela direita sem barra
   nenhuma, que foi o que aconteceu aqui. */
/* Desde 26/08/2026 a grade ABRE a aba Estoques: o afastamento que antes era
   por cima (ela fechava a tela) passou a ser por baixo, separando-a do filtro
   de período que vem logo em seguida. */
.produtos-grade-filiais { margin: 0 0 14px; min-width: 0; max-width: 100%; grid-column: 1 / -1; }
.produtos-grade-filiais .grid-wrap { min-width: 0; max-width: 100%; overflow-x: auto; }
/* Barra sempre visível: a "overlay" só aparece durante a rolagem, e quem não
   sabe que a grade continua não vai procurar. Sem `scrollbar-width` de
   propósito — declarar a propriedade padrão faz o Chrome ignorar as regras
   `::-webkit-scrollbar` abaixo e voltar pra barra que some. */
.produtos-grade-filiais .grid-wrap::-webkit-scrollbar { height: 11px; }
.produtos-grade-filiais .grid-wrap::-webkit-scrollbar-track { background: var(--surface-2, #eef1f5); border-radius: 6px; }
.produtos-grade-filiais .grid-wrap::-webkit-scrollbar-thumb { background: #9aa2ad; border-radius: 6px; }
.produtos-grade-filiais .grid-wrap::-webkit-scrollbar-thumb:hover { background: #7b838e; }
/* A coluna da loja fica presa: rolando 16 colunas, o número perde o dono se o
   nome da filial sair da tela. */
.produtos-grade-filiais .grid th:first-child,
.produtos-grade-filiais .grid td:first-child {
  position: sticky; left: 0; z-index: 1;
  background: var(--surface, #fff);
  box-shadow: 1px 0 0 var(--input-border, #d6dae0);
}
.produtos-grade-filiais .grid thead th:first-child { z-index: 2; background: var(--surface-2, #f4f6f8); }
.produtos-grade-filiais__atual > td:first-child { background: var(--linha-destaque, #e8f3ff); }
.produtos-grade-filiais__titulo { font-size: 1rem; margin: 0 0 8px; }
.produtos-grade-filiais .grid td.num { text-align: right; font-variant-numeric: tabular-nums; }
.produtos-grade-filiais__atual > td { background: var(--linha-destaque, #e8f3ff); font-weight: 600; }

/* Filtro da Gestão Financeira: Data Inicial/Final travadas enquanto não há
   critério escolhido. Escopo restrito ao formulário de filtro de propósito —
   um `input:disabled` global mudaria a aparência de toda tela travada pela
   barra de ferramentas (que trava via `<fieldset disabled>`). */
#form-filtro input:disabled {
  background: #eef0f3; color: #8b929b; cursor: not-allowed; border-color: #dfe3e8;
}
#form-filtro .rotulo-travado { opacity: .55; }
/* Campo desligado pelo Tipo de Pesquisa (Gestão Financeira) — o VB6 apaga o
   rótulo junto, senão o operador não entende por que não consegue digitar. */
#form-filtro .campo-travado label,
#form-filtro label.campo-travado { opacity: .5; }
#form-filtro .campo-travado input:disabled,
#form-filtro .campo-travado select:disabled { background: #eef0f3; color: #8b929b; cursor: not-allowed; }
#form-filtro .campo-travado button:disabled { opacity: .45; cursor: not-allowed; }
/* Grades próprias da Gestão Financeira (fluxo de caixa, previsão, posição). */
.gf-grade-inicial > td { background: var(--surface-2, #f1f4f7); font-style: italic; }
.gf-grade-divergente > td { background: #fff4e5; }
.gf-marca-divergente { color: #b3392c; font-weight: 700; }

/* ============================================================
   Gestão Financeira — filtro em 6 linhas, fiel ao frmTITULOSPESQUISA.frm
   (24/08/2026). Antes usava `.gestaocontratos-filtro` (grid de 4 colunas
   iguais em fluxo automático): com ~30 campos, cada um caía onde coubesse
   e nenhuma das linhas do original sobrevivia — "Vlr Parcela" separava do
   valor, o bloco "Em atraso" quebrava em 3 níveis e invadia a linha de
   baixo, e Caixa Previsto/Realizado subiam pra junto de Nº Documento.
   Aqui cada linha declara suas PRÓPRIAS frações, na proporção que os
   Top/Left do .frm indicam.
   ============================================================ */
.gf-filtro { display: grid; gap: 14px; border: none; padding: 0; margin: 0; min-width: 0; }
.gf-filtro__linha { display: grid; gap: var(--campo-gap, 12px) 16px; align-items: end; min-width: 0; }
/* Sem isto, um campo cujo conteúdo (lookup = código+descrição+botão) não cabe
   na fração da coluna força a TRILHA a estourar o container, e como `.panel`
   tem overflow:hidden o excesso some sem barra de rolagem — mesmo achado já
   documentado em `.gestaocontratos-filtro` (CLAUDE.md, 08/08/2026). */
.gf-filtro__linha > * { min-width: 0; }

/* Filial (larga, com razão social) | Data | Data Inicial | Data Final | Total de Pessoas */
.gf-filtro__linha--1 { grid-template-columns: 2.6fr 1.6fr 1fr 1fr 0.9fr; }
/* Tipo de Pesquisa | Tipo de Lançamento | Vlr Parcela | Nosso Número | checkboxes | Em atraso */
.gf-filtro__linha--2 { grid-template-columns: 1.3fr 1.3fr 1fr 1fr 2.1fr 1.35fr; }
/* Nº Documento | Título | Situação | Cobrança | Caixa Previsto | Caixa Realizado */
.gf-filtro__linha--3 { grid-template-columns: 1fr 0.8fr 1.2fr 1.1fr 1.5fr 1.5fr; }
/* Pessoa (com os 4 radios em cima) | Documento Financeiro | Meio de Pagamento */
.gf-filtro__linha--4 { grid-template-columns: 3.5fr 1.25fr 1.25fr; }
/* Tipo de Título | Classificação DRE | Centro de Custo | Conta Contábil */
.gf-filtro__linha--5 { grid-template-columns: repeat(4, 1fr); }
/* Banco | Prazo | Histórico — a 4ª fração fica vazia, como no original */
.gf-filtro__linha--6 { grid-template-columns: repeat(4, 1fr); }

.gf-filtro__obrigatorio { color: #b3392c; }
.gf-filtro__somenteleitura { background: var(--surface-2, #f1f4f7); text-align: right; }

/* Coluna de checkboxes da linha 2 — empilham, como no VB6. */
.gf-filtro__checks { display: flex; flex-direction: column; gap: 3px; justify-content: flex-end; }
.gf-filtro__checks .checkbox-label { font-size: 0.82rem; white-space: nowrap; }

/* Os 4 OptPESSOAPESQUISA + "Somente Colaboradores", em cima do campo Pessoa. */
.gf-filtro__radios { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 0.8rem; margin-bottom: 3px; }
.gf-filtro__radios .checkbox-label { white-space: nowrap; }

/* `FraATRASO`: frame de verdade (o checkbox é a legenda dele). */
.gf-filtro__atraso {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px;
  border: 1px solid var(--border); border-radius: 4px; padding: 2px 10px 8px;
  margin: 0; min-width: 0; font-size: 0.82rem;
}
.gf-filtro__atraso legend { padding: 0 4px; font-size: 0.82rem; }
.gf-filtro__atraso .checkbox-label { white-space: nowrap; margin: 0; }
.gf-filtro__tolerar { white-space: nowrap; }
.gf-filtro__tolerar input { width: 52px; display: inline-block; }

.gf-filtro__acoes { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* Telas estreitas: as 6 linhas viram 2 colunas e depois 1, na ordem do DOM
   (que já é a ordem visual do original). */
@media (max-width: 1200px) {
  .gf-filtro__linha--1, .gf-filtro__linha--2,
  .gf-filtro__linha--3, .gf-filtro__linha--4,
  .gf-filtro__linha--5, .gf-filtro__linha--6 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 700px) {
  .gf-filtro__linha--1, .gf-filtro__linha--2,
  .gf-filtro__linha--3, .gf-filtro__linha--4,
  .gf-filtro__linha--5, .gf-filtro__linha--6 { grid-template-columns: 1fr; }
}

/* Tela Sobre — ficha da versão em duas colunas (rótulo / valor). */
.sobre-versao {
  display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px;
  margin: 18px 0 0; padding-top: 14px; border-top: 1px solid var(--border);
  font-size: 0.92rem;
}
.sobre-versao dt { color: var(--text-muted); }
.sobre-versao dd { margin: 0; font-variant-numeric: tabular-nums; }

/* A Mensalidade mora aqui desde 24/09/2026 — saiu da barra do topo. Este é o
   único caminho para ela, então fica solto abaixo da ficha, não dentro dela. */
.sobre-mensalidade { margin: 14px 0 0; font-size: 0.92rem; }

/* Campo com atalho ao lado (ex.: "Contrato" + "Abrir contrato" no título
   financeiro). O input continua ocupando o espaço disponível e o botão fica
   colado, sem empurrar a grade do formulário. */
.campo-com-atalho { display: flex; gap: 6px; align-items: center; min-width: 0; }
.campo-com-atalho > input { flex: 1; min-width: 0; }
.btn--mini { padding: 4px 10px; font-size: 0.78rem; white-space: nowrap; }

/* Linha de total do Gerador de Títulos — destacada do corpo da grade sem
   virar outra cor de fundo forte. */
.geradortitulos-total > td {
  background: var(--surface-2, #f1f4f7);
  border-top: 2px solid var(--line-2, #c6d2db);
  font-variant-numeric: tabular-nums;
}
/* O total imita a CAIXA dos inputs da coluna Valor (mesma largura, mesma
   borda, mesmo alinhamento à direita) para cair exatamente sob os números que
   soma — pedido do usuário em 24/08/2026. Diferenças propositais: fundo da
   linha de total e peso maior, para ler como resultado e não como mais um
   campo editável. `box-sizing` explícito porque o input tem `width:100px`
   contando a borda. */
.geradortitulos-total-caixa {
  display: inline-block; box-sizing: border-box;
  width: 100px; padding: 4px 8px;
  border: 1px solid var(--line-2, #c6d2db); border-radius: 3px;
  background: var(--surface, #fff);
  text-align: right; font-weight: 700;
  /* mesma fonte da grade — a caixa é parte da tabela, não um destaque à parte */
  font-size: inherit; font-family: inherit; line-height: inherit;
  font-variant-numeric: tabular-nums;
}
/* Campo monetário da grade. `font: inherit` é o que importa: input não herda
   fonte do documento por padrão — o navegador aplica a dele (Arial 13,33px),
   e o campo ficava maior que a célula ao lado. */
.campo-moeda {
  font: inherit; font-variant-numeric: tabular-nums;
}

/* --- Prévia do Gerador de Títulos: pesquisa e ordenação (24/08/2026) --- */
.gt-barra-filtro {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 10px 0 12px;
}
.gt-barra-filtro input[type="search"] {
  flex: 1 1 320px; max-width: 460px; min-width: 0;
}
.gt-contador { font-size: 0.82rem; color: var(--text-muted); white-space: nowrap; }

/* Cabeçalho ordenável. A seta só aparece na coluna ativa — uma seta em cada
   coluna vira ruído e some com a informação de qual está ordenando. O
   `padding-right` fixo reserva o espaço da seta desde sempre, senão o
   cabeçalho "pula" de largura no primeiro clique. */
th.col-ord { cursor: pointer; user-select: none; position: relative; padding-right: 22px; }
th.col-ord:hover { color: var(--ink, #14202b); }
th.col-ord::after {
  content: ""; position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  opacity: 0; font-size: 0.75em;
}
th.col-ord.ord-asc::after  { content: "\25B2"; opacity: .75; }
th.col-ord.ord-desc::after { content: "\25BC"; opacity: .75; }

/* Ações da prévia do Gerador de Títulos. O botão de exclusão fica separado do
   de gerar por um respiro maior que o gap normal — botões destrutivos colados
   nos construtivos convidam ao clique errado. */
.gt-acoes { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
.gt-acoes .btn--perigo { margin-left: 18px; }
.gt-dica { font-size: 0.8rem; color: var(--text-muted); }
.btn--perigo {
  background: #b3392c; color: #fff; border-color: #99301f;
}
.btn--perigo:hover:not(:disabled) { background: #99301f; }
/* Caixa de exclusão: vermelha, para não se confundir com a de gerar. */
.gt-excluir-checkbox { accent-color: #b3392c; }
/* Linha já gerada: fundo cinza de verdade. O texto azul (`cor-liberado`) diz
   "concluído" na convenção do sistema, mas sozinho não separa a linha do
   resto — e tanto o texto de ajuda quanto o aviso do botão mandam o operador
   "marcar as linhas em cinza". O fundo é o que torna essa instrução legível. */
.gt-linha-gerada > td { background: #eef0f3; }
.gt-linha-gerada:hover > td { background: #e6e9ee; }


/* Grade com 5mm entre colunas (24/08/2026) — pedido do usuário nos dois grids
   da Gestão de Contratos. A grade padrão usa 20px de cada lado (40px entre o
   conteúdo de duas colunas vizinhas), o que empurrava as colunas de dinheiro
   pra fora da tela numa grade de 16 colunas. 2,5mm de cada lado = os 5mm
   pedidos entre uma coluna e outra. */
.grid--5mm { table-layout: auto; }
.grid--5mm thead th { padding-left: 2.5mm; padding-right: 2.5mm; }

/* A folga toda vai pra UMA coluna (`col-elastica`, na prática a de Nome /
   Razão Social) em vez de ser repartida entre todas — 24/08/2026.
   
   Motivo real: `.grid` tem `width: 100%`, e com conteúdo curto o navegador
   distribuía o espaço que sobrava por todas as colunas. Resultado visível:
   um vão largo entre "48" e "R$ 800,00", como se o padding de 5mm não
   tivesse sido aplicado — mas o padding estava certo; o que inflava era a
   largura da coluna. Com `width: 100%` numa coluna só, ela absorve a sobra
   e as demais encolhem até o conteúdo. */
/* `width: 1px` + o `nowrap` que a grade já tem = cada coluna encolhe até
   caber exatamente o seu conteúdo (o navegador respeita o mínimo, não o 1px).
   A `col-elastica` fica com 100% e engole todo o resto. É o que tira a barra
   de rolagem horizontal sem truncar nada: o espaço morto que estava
   espalhado por 11 colunas passa a existir numa só, a de Nome — que é
   justamente a que sabe usá-lo. */
.grid--5mm th,
.grid--5mm td { width: 1px; }
.grid--5mm .col-elastica { width: 100%; }
.grid--5mm tbody td,
.grid--5mm tfoot td { padding-left: 2.5mm; padding-right: 2.5mm; }

/* Coluna de número: alinhada à direita e com dígito de largura fixa
   (`tabular-nums`), pra casa decimal cair sob casa decimal — sem isso o
   total do rodapé não se alinha de verdade com a pilha que ele soma, mesmo
   estando na mesma coluna. */
.grid .col-num { text-align: right; font-variant-numeric: tabular-nums; }

/* Linha de totais: mesma fonte da grade, só o peso muda.

   `white-space: nowrap` é obrigatório aqui: a regra global da grade (§2.15)
   cobre `thead th` e `tbody td`, mas NÃO o `tfoot` — sem isto "R$ 106,50"
   quebrava em duas linhas ("R$" em cima, "106,50" embaixo) nas colunas
   estreitas, e o total deixava de ficar sob a pilha que soma. */
.grid tfoot tr.grid-totais td {
  font-weight: 700;
  border-top: 2px solid var(--border);
  background: #fafbfc;
  white-space: nowrap;
}

/* Cabeçalho ordenável: a seta aparece na coluna em uso, e o cursor avisa que
   dá pra clicar. `::after` reserva o espaço da seta sempre, senão a coluna
   pula de largura no primeiro clique. */
.grid thead th.col-ord { cursor: pointer; user-select: none; }
.grid thead th.col-ord:hover { color: var(--text); }
.grid thead th.col-ord::after { content: "\2195"; opacity: .25; margin-left: 3px; font-size: .8em; }
.grid thead th.col-ord.ord-asc::after  { content: "\2191"; opacity: 1; }
.grid thead th.col-ord.ord-desc::after { content: "\2193"; opacity: 1; }
.grid thead th.col-ord:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

/* ==========================================================
   Faturamento de Serviços (24/08/2026)
   ==========================================================
   O "trilho" das 4 etapas. A cor não é decoração: é a resposta à
   pergunta que o operador faz ao abrir a tela — "em que pé está?".
   Verde = concluída, azul = é a vez dela, cinza = ainda esperando a
   anterior. */
.fat-trilho {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px;
  margin: 16px 0 4px;
  padding: 0;
}
.fat-etapa {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.fat-etapa--ok     { border-color: #2e7d32; box-shadow: inset 3px 0 0 #2e7d32; }
.fat-etapa--vez    { border-color: #1565c0; box-shadow: inset 3px 0 0 #1565c0; }
.fat-etapa--espera { opacity: .72; }

.fat-etapa__cabeca { display: flex; align-items: flex-start; gap: 8px; flex-wrap: wrap; }
.fat-trilho__num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--border); color: var(--text); font-size: .78rem; font-weight: 700;
}
.fat-etapa--ok  .fat-trilho__num { background: #2e7d32; color: #fff; }
.fat-etapa--vez .fat-trilho__num { background: #1565c0; color: #fff; }

.fat-etapa__texto  { font-size: .8rem; color: var(--text-muted); margin: 0; }
.fat-etapa__quando { font-size: .75rem; color: var(--text-muted); margin: 0; }
.fat-etapa__motivo { font-size: .75rem; color: var(--text-muted); margin: 0; font-style: italic; }
.fat-etapa__trava  { font-size: .75rem; color: var(--text-muted); cursor: help; }
.fat-etapa__acoes  { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: auto; }
.fat-etapa__acoes form { display: contents; }

/* ---- Indicador de progressão do lote (27/08/2026) --------------------
   Uma faixa, dois estados: as cinco etapas lado a lado quando parado, a
   barra da ação em curso quando alguma roda. Os dois vivem no mesmo bloco e
   se alternam por `hidden` — e como as duas classes declaram `display`,
   elas precisam do par `:not([hidden])`/`[hidden]` (§2.4, a armadilha que
   já apareceu 6 vezes neste projeto). */
.fat-progresso { margin-top: 12px; }

.fat-progresso__etapas:not([hidden]) { display: grid; }
.fat-progresso__etapas[hidden] { display: none; }
.fat-progresso__etapas {
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
}
@media (max-width: 900px) {
  .fat-progresso__etapas { grid-template-columns: repeat(2, 1fr); }
}

.fat-progresso__etapa { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.fat-progresso__trilho {
  height: 7px; border-radius: 4px; overflow: hidden;
  background: var(--border, #d7dde5);
}
.fat-progresso__barra {
  height: 100%; background: var(--primary, #1f4e79); border-radius: 4px;
  /* a barra ANDA em vez de saltar — em etapa de 40 itens o salto seco não
     deixa ver que está progredindo */
  transition: width .25s ease;
}
.fat-progresso__rotulo {
  font-size: .7rem; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.fat-progresso__conta {
  font-size: .72rem; font-weight: 600; font-variant-numeric: tabular-nums;
}
/* Etapa sem nenhum item elegível: barra vazia sem explicação parece etapa
   esquecida — fica cinza e mostra "—". */
.fat-progresso__etapa--vazia .fat-progresso__rotulo,
.fat-progresso__etapa--vazia .fat-progresso__conta { opacity: .5; }

.fat-progresso__vivo:not([hidden]) { display: block; }
.fat-progresso__vivo[hidden] { display: none; }
.fat-progresso__trilho--vivo { height: 12px; border-radius: 6px; }
.fat-progresso__barra--vivo {
  background: linear-gradient(90deg, var(--primary, #1f4e79), #3b82c4);
}
.fat-progresso__vivo-texto {
  display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap;
  margin-top: 5px; font-size: .78rem;
}
.fat-progresso__vivo-texto span { font-variant-numeric: tabular-nums; }
/* Link não tem `disabled`: enquanto a etapa roda ele fica inerte igual a um
   botão desabilitado (§2.12 — o operador precisa VER que não pode clicar). */
.btn--inerte { opacity: .45; pointer-events: none; }

.fat-selo {
  font-size: .68rem; text-transform: uppercase; letter-spacing: .03em;
  padding: 1px 6px; border-radius: 10px; font-weight: 700;
}
.fat-selo--ok       { background: #e8f5e9; color: #1b5e20; }
.fat-selo--pendente { background: #fff8e1; color: #8d6e00; }
/* "Fora do envio" não é pendência nem erro: é cliente que a etapa não tem
   como alcançar. Cor própria, para não se confundir com nenhum dos dois. */
.fat-selo--fora     { background: #eceff1; color: #455a64; }
.fat-etapa__fora {
  margin: 4px 0 0; padding-left: 18px; font-size: .78rem; color: #546e7a;
}
.fat-etapa__fora li { margin: 1px 0; }

/* Vitrine do trilho na tela de filtro — mesma leitura, sem estado. */
.fat-trilho--vitrine { margin-bottom: 14px; }
.fat-trilho--vitrine li {
  border: 1px dashed var(--border); border-radius: 8px; padding: 10px 12px;
  font-size: .85rem; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.fat-trilho--vitrine em { font-style: normal; font-size: .75rem; color: var(--text-muted); flex-basis: 100%; }

/* Cabeçalho do lote: pares rótulo/valor, sem tabela (não é dado tabular). */
.fat-resumo {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px 18px; margin-bottom: 6px;
}
.fat-resumo > div { display: flex; flex-direction: column; }
.fat-resumo span   { font-size: .72rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .03em; }
.fat-resumo strong { font-size: .95rem; }

.fat-situacao { font-weight: 700; }
.fat-situacao--0 { color: var(--text-muted); }
.fat-situacao--1 { color: #1565c0; }
.fat-situacao--2 { color: #6a1b9a; }
.fat-situacao--3 { color: #ef6c00; }
.fat-situacao--4 { color: #2e7d32; }

.fat-status {
  font-size: .7rem; font-weight: 700; padding: 1px 7px; border-radius: 10px;
}
.fat-status--ok      { background: #e8f5e9; color: #1b5e20; }
.fat-status--aviso   { background: #fff8e1; color: #8d6e00; }
.fat-status--erro    { background: #ffebee; color: #b71c1c; }
.fat-status--estorno { background: #ede7f6; color: #4527a0; }

/* Faturamento — linha cuja mensalidade JÁ TEM TÍTULO mas ainda não foi
   faturada em lote nenhum (24/08/2026). Não é "pronta" (o cinza de
   `gt-linha-gerada` diria isso e desanima o operador, que foi o relato
   real: "a tela ficou cinza e parou de totalizar"); é "tem trabalho a
   fazer aqui": marque e o título é incorporado ao lote. Faixa âmbar à
   esquerda, texto normal. */
.gt-linha-adotar td:first-child { box-shadow: inset 3px 0 0 #ef6c00; }

/* Rótulo secundário no cabeçalho da grade — diz de ONDE o campo vem ou
   PARA ONDE ele vai, quando duas colunas vizinhas parecem a mesma coisa
   (24/08/2026: "Serviço (na nota)" x "Histórico (no título)"). */
.gt-col-origem { font-weight: 400; font-size: .72rem; color: var(--text-muted); }

/* ==========================================================================
   ALTURA COMPACTA DA TELA DE PRODUTOS (26/08/2026)
   Copia a densidade da tela de Notas Fiscais (.nfem-fs, ~2814) para o cadastro
   de Produtos: mesma altura de campo, mesmo corpo de letra no rótulo.
   PARA DESFAZER: tire a classe "tela-compacta" do <div class="panel">
   em templates/produtos_form.html (a tela volta na hora ao padrão), ou apague
   este bloco inteiro. Backup do antes em _backup_staging/produtos_altura_26082026/.
   ========================================================================== */
.tela-compacta .form__field label,
.tela-compacta .produtos-secao legend { font-size: 0.74rem; }
.tela-compacta .form__field > label { font-size: 0.7rem; }

/* O alvo é o CAMPO, não o `.form__field`: metade das telas do sistema tem
   campo solto dentro de `<label>` ou de um quadro com classe própria (SPED,
   Apuração do IPI, Comparativo de Bases), e uma regra presa ao container
   deixaria essas de fora — foi o que a varredura das 153 telas mostrou.
   FICAM DE FORA de propósito, na lista `:not()` abaixo: a BARRA DE BUSCA
   (`.busca-generica`, 36px, casada com a altura dos botões ao lado — é gesto
   de entrada, não digitação de cadastro), o campo de amostra da Configuração
   de Tela (tem que mostrar a altura que o operador configurou, não a nossa) e
   o seletor de cor, que é um quadrado de amostra. */
.tela-compacta input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]):not(.cfgtela-preview-input):not(.busca-generica *),
.tela-compacta select:not(.busca-generica *),
.tela-compacta textarea:not(.busca-generica *),
.tela-compacta .lookup-field .lookup-code,
.tela-compacta .lookup-field .lookup-select,
.tela-compacta .lookup-generico input,
.tela-compacta .lookup-generico .lookup-generico-texto {
  padding: 5px 7px; font-size: 0.86rem; min-height: 0;
}
/* Campo fora de `.form__field` nunca recebeu a moldura do sistema e ficava com
   a borda cinza-inset do NAVEGADOR (achado ao varrer as 153 telas: a tolerância
   de atraso da Gestão Financeira e o localizador do Gerenciador de Relatórios,
   ambos 29px por causa dos 2px de borda padrão do Chrome, ao lado de vizinhos
   de 27px com a borda de 1px do sistema). Agora todo campo alcançado pelo
   carimbo usa a mesma moldura. */
.tela-compacta input:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]):not([type="file"]):not(.cfgtela-preview-input):not(.busca-generica *),
.tela-compacta select:not(.busca-generica *):not(.cfgtela-preview-input),
.tela-compacta textarea:not(.busca-generica *) {
  border: 1px solid var(--input-border);
  border-radius: var(--radius);
  background: var(--input-bg);
}

/* A lupa é o que puxava a altura do lookup pra cima (26/08/2026): o emoji
   🔍 vinha com 16,5px de fonte e fazia o botão medir 29px, e como a linha do
   lookup é `align-items: stretch`, o código e a descrição esticavam junto —
   dois pixels a mais que os campos comuns da mesma fileira. Com a lupa menor
   que o campo, quem manda na altura passa a ser o campo. */
.tela-compacta .lookup-generico-botao {
  min-height: 0; padding: 3px 8px; font-size: 0.85rem; line-height: 1.1;
}
/* Data e select trazem controle NATIVO do navegador dentro (calendário,
   seta) e ficam 2px mais altos com o mesmo padding. Vale também para o
   `<select>` do lookup simples (`.lookup-field`, o padrão de tabela pequena
   do §2.7), que é quem o motor genérico de cadastros usa: como a linha é
   flex, o select mais alto esticava o campo de código junto — descontar aqui é o que
   deixa a fileira toda com a mesma altura. Os dois `:not()` no seletor da
   data não são enfeite: sem eles a regra tem MENOS peso que a geral logo
   acima (que carrega `:not([type=checkbox]):not([type=radio])`) e o padding
   de 4px simplesmente não valia. */
.tela-compacta input[type="date"]:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]):not(.busca-generica *),
.tela-compacta input[type="month"]:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]):not(.busca-generica *),
.tela-compacta input[type="time"]:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]):not(.busca-generica *),
.tela-compacta input[type="datetime-local"]:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]):not(.busca-generica *),
.tela-compacta select:not(.busca-generica *):not(.cfgtela-preview-input),
.tela-compacta .lookup-field .lookup-select { padding: 4px 6px; }
/* O seletor de arquivo desenha o botão "Escolher arquivo" por conta própria:
   sobra só apertar o que está em volta. */
.tela-compacta input[type="file"]:not([type="checkbox"]):not([type="radio"]):not([type="color"]):not([type="range"]):not(.busca-generica *) { padding: 2px 6px; }

/* Campo dentro de GRADE (a matriz de entradas/consumo da aba Movimentações)
   não passa por `.form__field` e por isso ficava 2px mais alto que o resto. */
.tela-compacta .grid input:not([type="checkbox"]):not([type="radio"]),
.tela-compacta .grid select {
  padding: 4px 6px; font-size: 0.86rem; min-height: 0;
}

/* A BARRA DE BUSCA tem escala própria (36px, casada com os botões ao lado) e
   fica fora do bloco compacto — mas ela também precisa ser uniforme por
   dentro: telas anteriores à macro `_busca.html` montam a barra à mão, com
   `<label>` de 0,85rem e o campo herdando o tamanho padrão do navegador (a
   Apuração do IPI tinha datas de 21px ao lado de botões de 34). Esta regra
   iguala filtro e campo dentro da barra, em qualquer tela. */
.busca-generica input:not([type="checkbox"]):not([type="radio"]):not(.busca-generica__campo),
.busca-generica select { padding: 8px 10px; font-size: 0.9rem; }
/* Data traz calendário nativo e mede 2px a mais com o mesmo padding. Os
   `:not()` repetidos existem só para esta regra pesar mais que a de cima —
   sem eles ela perde e o padding de 7px não vale. */
.busca-generica input[type="date"]:not([type="checkbox"]):not([type="radio"]):not(.busca-generica__campo),
.busca-generica input[type="month"]:not([type="checkbox"]):not([type="radio"]):not(.busca-generica__campo) {
  padding: 7px 10px;
}

/* Código do IBGE tem 7 dígitos e não cabia nos 70px que todo lookup ganha
   (§2.7): o campo cortava o próprio código no Cadastro Simplificado de
   Pessoas — o `style="width:93px"` do HTML é letra morta, `flex` vence
   `width` (a mesma armadilha de sempre). */
.tela-compacta .form__field[data-lookup-campo="codigomunicipio"] .lookup-generico-codigo {
  flex: 0 0 84px; min-width: 84px;
}

.tela-compacta .checkbox-label { font-size: 0.82rem; }
.tela-compacta .produtos-secao { padding: 6px 10px 8px; }

/* Folga de baixo igual em TODOS os quadros (26/08/2026): o espaço sobrando
   embaixo de alguns frames era a margem do último elemento de dentro
   (a fileira de flags, o texto de exemplo) SOMANDO com o padding do quadro
   — dava 21-22px onde os outros tinham 9px. Zerar a margem do que fecha o
   quadro deixa a distância valendo só o padding, igual em todo lugar. */
.tela-compacta .produtos-secao > *:last-child,
.tela-compacta .produtos-secao > *:last-child > *:last-child,
.tela-compacta .produtos-secao > *:last-child > *:last-child > *:last-child {
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   ABAS COM LAPELA (26/08/2026, pedido do usuário) — as abas de fora e as de
   dentro passam a ser pastas de verdade: a lapela ativa é da cor do painel e
   se EMENDA nele (border-bottom da cor do fundo + margin-bottom -1px), e o
   conteúdo ganha moldura, pra dar a sensação de navegar num objeto tabular.
   O padrão é o mesmo das sub-abas de Impostos, que o usuário aprovou.

   Faixa em UMA LINHA SÓ, com rolagem horizontal quando não couber: em duas
   linhas a lapela ativa da linha de cima não teria painel embaixo pra se
   emendar (era o "ficou faltando a lapela"). No VB6 o SSTab resolve isso
   trocando as linhas de lugar (TabsPerRow=8, 16 abas); aqui a linha única
   dispensa a troca e nenhuma aba fica órfã.
   -------------------------------------------------------------------------- */
.tela-compacta .produtos-abas-nav,
.tela-compacta .produtos-subabas-nav {
  display: flex; flex-wrap: nowrap; align-items: flex-end; gap: 3px;
  border-bottom: none; margin: 0; padding: 0 2px;
  overflow-x: auto; overflow-y: hidden; scrollbar-width: thin;
}
.tela-compacta .produtos-aba-btn,
.tela-compacta .produtos-subaba-btn {
  flex: 0 0 auto; margin-bottom: -1px; border-radius: 6px 6px 0 0;
  background: #f1f3f6; border: 1px solid var(--border); color: var(--text-muted);
  cursor: pointer; white-space: nowrap;
}
.tela-compacta .produtos-aba-btn { padding: 6px 8px; font-size: 0.78rem; font-weight: 600; }
.tela-compacta .produtos-subaba-btn { padding: 5px 11px; font-size: 0.76rem; font-weight: 600; }
.tela-compacta .produtos-aba-btn:hover:not(.produtos-aba-btn--ativa),
.tela-compacta .produtos-subaba-btn:hover:not(.produtos-subaba-btn--ativa) {
  background: #e7eaef; color: var(--text);
}
/* A lapela ativa some com a linha de baixo: é ela que "abre" pro painel. */
.tela-compacta .produtos-aba-btn--ativa,
.tela-compacta .produtos-subaba-btn--ativa {
  background: var(--panel); color: var(--primary);
  border-bottom-color: var(--panel); padding-bottom: 7px;
}
.tela-compacta .produtos-aba-btn[disabled] { color: #c3c8d0; cursor: not-allowed; }

/* O painel é a pasta: moldura fechada, cantos arredondados menos no de cima
   à esquerda, que é onde a primeira lapela encosta. */
.tela-compacta .produtos-aba-conteudo,
.tela-compacta .produtos-subaba-conteudo {
  border: 1px solid var(--border); border-radius: 0 6px 6px 6px;
  background: var(--panel); padding: 10px 12px; margin-bottom: 14px;
}
.tela-compacta .produtos-subaba-conteudo { margin-bottom: 0; }

/* Quadro colado na moldura fica com duas bordas quase juntas: o de cima
   perde a margem que o separava da lapela. */
.tela-compacta .produtos-aba-conteudo > .produtos-secao:first-child,
.tela-compacta .produtos-subaba-conteudo > .produtos-secao:first-child { margin-top: 2px; }

/* ==========================================================================
   BI — PAINEL DO CONSULTOR (26/08/2026)
   Regras de desenho vindas da pesquisa (Few, Tufte, IBCS, NN/g): cinza como
   padrão e cor só onde ela significa; dois painéis com a MESMA estrutura, um
   ao lado do outro; tabela densa com números alinhados à direita; e a
   explicação do indicador visível, não escondida em tooltip.
   ========================================================================== */
.bi-barra {
  display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap;
  padding-bottom: 10px; border-bottom: 1px solid var(--border); margin-bottom: 10px;
}
.bi-barra__indicador { min-width: 420px; }
.bi-barra__indicador select { font-weight: 600; }
.bi-pergunta {
  margin: 0 0 4px; font-size: 0.95rem; color: var(--text); font-style: italic; flex: 1; min-width: 260px;
}

.bi-ajuda {
  background: var(--surface-2, #f5f6f8); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 10px 14px; margin-bottom: 12px;
}
.bi-ajuda__grade { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.bi-ajuda h3 {
  margin: 0 0 4px; font-size: 0.72rem; letter-spacing: .04em; text-transform: uppercase;
  color: var(--primary);
}
.bi-ajuda p { margin: 0; font-size: 0.82rem; line-height: 1.45; color: var(--text); }
.bi-ajuda__rodape {
  margin: 10px 0 0; padding-top: 8px; border-top: 1px dashed var(--border);
  font-size: 0.74rem; color: var(--text-muted);
}
@media (max-width: 1100px) { .bi-ajuda__grade { grid-template-columns: 1fr; } }

/* Os dois painéis. `min-width: 0` nas duas colunas é o que permite a tabela
   rolar dentro do painel em vez de esticar a página (§2.15). */
.bi-paineis { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.bi-paineis > .bi-painel { min-width: 0; }
@media (max-width: 1200px) { .bi-paineis { grid-template-columns: 1fr; } }

.bi-painel {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--panel); padding: 10px 12px 12px;
}
.bi-painel__head { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.bi-painel__marca {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%; background: var(--primary); color: #fff;
  font-weight: 700; font-size: 0.8rem; flex: 0 0 auto;
}
.bi-painel__filtros { display: flex; gap: 8px; flex-wrap: wrap; flex: 1; min-width: 0; }
.bi-painel__filtros .form__field { margin: 0; }
.bi-painel__filtros input[type="date"] { width: 132px; }
.bi-lojas { min-width: 160px; max-width: 210px; height: auto; }
.bi-painel__acoes { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.bi-exportar { display: inline-flex; gap: 4px; }
.bi-exportar .btn { padding: 4px 8px; font-size: 0.74rem; }

.bi-painel__filtro-texto {
  margin: 8px 0 6px; font-size: 0.74rem; color: var(--text-muted);
  border-bottom: 1px solid var(--border); padding-bottom: 6px;
}
.bi-painel__corpo { position: relative; }
.bi-painel .grid-wrap { max-height: 46vh; overflow: auto; }
.bi-painel .grid thead th { position: sticky; top: 0; z-index: 1; }
.bi-grafico { height: 46vh; }
.bi-vazio, .bi-carregando { margin: 12px 0; color: var(--text-muted); font-size: 0.82rem; }

/* Linha que leva a algum lugar: o sinal é visível (NN/g — clicável tem que
   parecer clicável), e não depende só do hover, que no toque não existe. */
.bi-linha--navega { cursor: context-menu; }
.bi-linha--navega:hover { background: var(--linha-destaque, #e8f3ff); }
.bi-kebab {
  border: none; background: none; cursor: pointer; color: var(--text-muted);
  font-size: 0.9rem; line-height: 1; padding: 0 2px; margin-left: 6px; vertical-align: middle;
}
.bi-kebab:hover { color: var(--primary); }

.bi-menu {
  position: fixed; z-index: 90; min-width: 220px; background: var(--panel);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 8px 22px rgba(16, 24, 40, .18); padding: 4px;
}
.bi-menu__item {
  display: block; padding: 7px 10px; font-size: 0.8rem; color: var(--text);
  text-decoration: none; border-radius: 4px;
}
.bi-menu__item:hover, .bi-menu__item:focus { background: var(--linha-destaque, #e8f3ff); outline: none; }

/* Barra de seleção da grade de itens do Faturamento de Serviços (26/08/2026):
   o operador escolhe de quais boletos sai nota antes de executar a etapa. */
.fat-selecao {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 8px 10px; margin-bottom: 10px;
  background: var(--surface-2, #f5f6f8); border: 1px solid var(--border);
  border-radius: var(--radius);
}
.fat-selecao__conta { color: var(--text-muted); font-size: 0.8rem; }

/* Janela do cancelamento de NFS-e (26/08/2026) — motivo da lista oficial e
   justificativa de 15 caracteres no mínimo não cabem num confirm(). */
.fat-dialogo {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 18px 20px; max-width: 520px; width: 92vw;
  box-shadow: 0 18px 44px rgba(16, 24, 40, .24);
}
.fat-dialogo::backdrop { background: rgba(16, 24, 40, .45); }
.fat-dialogo h2 { margin: 0 0 4px; font-size: 1.05rem; }
.fat-dialogo .form__field { margin-top: 10px; }
.fat-dialogo textarea { width: 100%; }
.fat-aviso {
  margin: 10px 0; padding: 8px 10px; font-size: 0.8rem;
  background: var(--aviso-bg, #fff8e1); border: 1px solid var(--aviso-borda, #f0d48a);
  border-radius: var(--radius);
}
.fat-dialogo__acoes { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }

/* ------------------------------------------------------------------
   PAINEL DE FILTROS das telas de pesquisa (26/08/2026) — o equivalente
   web dos painéis do VB6, declarado em `pesquisa_avancada.Campo` e
   desenhado por `_filtro_avancado.html`. As linhas reproduzem o
   posicionamento por Top/Left do original: campos que estão na mesma
   linha da tela real ficam na mesma linha aqui, com largura própria.
   ------------------------------------------------------------------ */
.filtro-avancado {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px 12px; margin-bottom: 12px;
  background: var(--panel-alt, #f6f7f9); border: 1px solid var(--line, #dfe3e8);
  border-radius: 6px;
}
.filtro-avancado__linha { display: flex; flex-wrap: wrap; gap: 10px; align-items: end; }
.filtro-avancado__campo { display: flex; flex-direction: column; gap: 2px; flex: 1 1 140px; min-width: 0; }
.filtro-avancado__campo > label { font-size: .7rem; color: var(--muted, #6b7280); }
.filtro-avancado__campo--check { flex: 0 0 auto; justify-content: end; padding-bottom: 4px; }
.filtro-avancado__rotulo-check { display: flex; align-items: center; gap: 5px; font-size: .78rem; white-space: nowrap; }
/* Campo desabilitado por dependência: cinza e sem cursor, como no VB6 —
   continua VISÍVEL de propósito, para o operador entender que existe. */
.filtro-avancado__campo--travado > label,
.filtro-avancado__campo--travado .filtro-avancado__rotulo-check { opacity: .45; }
.filtro-avancado__acoes { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.filtro-avancado__acoes .btn { padding: 6px 14px; }
/* O lookup dentro do filtro segue a escala compacta (§2.33) — a busca
   simples (`.busca-generica`) é que tem escala própria. */
.filtro-avancado .lookup-generico { display: flex; gap: 4px; align-items: stretch; }
/* `min-width: 0` é obrigatório: o `min-width` que o campo herda do padrão
   compacto vence o `flex-basis` e o código empurrava a descrição para 16px
   (medido no navegador, não estimado — §2.24). */
.filtro-avancado .lookup-generico-codigo { flex: 0 0 5.5em; min-width: 0; }
.filtro-avancado .lookup-generico-descricao { flex: 1 1 3em; min-width: 0; background: #eef0f3; }
/* A lupa nunca encolhe nem sai da caixa — sem isto ela era empurrada para
   fora nos campos estreitos (Filial, UF) e sumia da tela. */
.filtro-avancado .lookup-generico-botao { flex: 0 0 auto; }
.filtro-avancado__campo > label > small { font-weight: normal; font-size: .64rem; opacity: .75; }

/* ------------------------------------------------------------------
   CABEÇALHO DE SEÇÃO — legenda à esquerda, ações à direita
   (26/08/2026). Antes os botões ficavam DENTRO da legenda, no meio do
   texto: com o padrão compacto a legenda encolheu para .74rem e o botão
   ao lado dela passou a parecer solto, fora de alinhamento — foi o que
   o usuário viu na Cotação de Preços. Aqui a legenda fica na sua linha
   de base e as ações num grupo próprio, com a mesma folga em todas as
   seções.
   ------------------------------------------------------------------ */
.secao-cabecalho {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin: 18px 0 8px;
}
.secao-cabecalho > .cadastro-generico-fieldset__legenda { margin: 0; }
.secao-cabecalho__acoes { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.secao-cabecalho__acoes form { margin: 0; }

/* Ações de mesmo peso: todos os botões do grupo com a MESMA largura e a mesma
   altura, independente do tamanho do texto (26/08/2026, pedido do usuário na
   aba Resultados da Cotação). `grid-auto-columns: 1fr` com o grupo em
   `max-content` faz todas as colunas medirem o item mais largo — e o
   `stretch` do grid iguala a altura sem precisar fixar pixel nenhum. */
.secao-cabecalho__acoes--uniformes {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  width: max-content; gap: 8px; align-items: stretch;
}
.secao-cabecalho__acoes--uniformes form { display: flex; }
.secao-cabecalho__acoes--uniformes .btn { width: 100%; justify-content: center; }

/* E-mail editável na grade do lote (26/08/2026): largura pelo conteúdo real
   — dois endereços cabem sem esconder o segundo, e a grade continua rolando
   na horizontal em vez de espremer as outras colunas (§2.15). */
.fat-email { min-width: 260px; }

/* Linha de fechamento nas grades do BI (subtotal da DRE): negrito e um fio
   acima, para o olho achar o número que importa sem procurar. */
.bi-linha--destaque td { font-weight: 700; border-top: 1px solid var(--line, #dfe3e8); background: #f7f9fb; }

/* Coluna de CONTA nas grades do BI: o nome longo cede espaço ao número.
   Preferir reticências à rolagem aqui é decisão consciente (§2.15 pede o
   contrário como regra) — num painel de meia largura, um resultado que só
   aparece rolando não é resultado. O texto inteiro fica no tooltip. */
.bi-col-conta { max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- DF-e Recebidos (31/08/2026) ---------------------------------- */
/* Cartões de contagem no topo da caixa de entrada. O prazo é o eixo desta
   tela — 90 dias da autorização, e o silêncio confirma automaticamente —,
   então o que vence logo precisa saltar aos olhos antes de qualquer rolagem. */
/* **Uma grade só para as DUAS fileiras** de caixas do painel de DF-e
   (01/09/2026): a de cima conta a caixa inteira, a de baixo conta o recorte
   do filtro. Eram duas grades separadas, e por isso não alinhavam — cada uma
   media o próprio conteúdo e a caixa de baixo caía deslocada da de cima.
   Compartilhando o contêiner, a coluna 1 tem a mesma largura nas duas.

   `1fr` e não `max-content`: são QUATRO em cima e QUATRO embaixo, ocupando a
   largura toda (pedido do usuário em 01/09/2026). O painel é o resumo que se
   lê de longe — caixa do tamanho do texto desperdiça a largura disponível e
   deixa o número pequeno justamente onde ele é a informação. */
.dfe-painel {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: .6rem;
  margin: .4rem 0 .6rem;
}
/* Abaixo de 900px quatro colunas espremeriam "confirmadas por decurso de
   prazo" em cinco linhas. Duas colunas mantêm a leitura, e as de cima
   continuam alinhadas com as de baixo — que é o ponto da grade única. */
@media (max-width: 900px) {
  .dfe-painel { grid-template-columns: repeat(2, 1fr); }
}
/* Os rótulos das fileiras atravessam a grade inteira. */
.dfe-quadro__faixa {
  grid-column: 1 / -1;
  margin: .35rem 0 0;
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--text-muted, #6b7280);
}
.dfe-quadro__faixa:first-child { margin-top: 0; }
.dfe-quadro__vazio { grid-column: 1 / -1; margin: 0; }
/* O valor é a terceira linha da caixa; as de cima não têm, e por isso ele
   não pode ter altura reservada — senão as quatro de cima crescem à toa. */
.dfe-cartao__valor { font-size: .95rem; font-weight: 600; opacity: .8; white-space: nowrap; }
.dfe-cartao {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: .1rem;
  min-width: 0;            /* sem isto o texto longo estoura a coluna do grid */
  padding: .7rem .9rem;
  border: 1px solid var(--linha, #d6d6d6);
  border-radius: 4px;
}
/* **O número em destaque, e em negrito**: é ele que se lê de relance, e o
   rótulo só existe para dizer do que ele é. `nowrap` porque "1.003" partido
   no ponto de milhar vira dois números diferentes para quem passa o olho. */
.dfe-cartao__numero {
  font-size: 2rem;
  font-weight: 700;
  line-height: 1.05;
  white-space: nowrap;
}
.dfe-cartao__rotulo { font-size: .82rem; font-weight: 600; opacity: .8; }
.dfe-cartao--urgente { border-color: #c62828; }
.dfe-cartao--urgente .dfe-cartao__numero { color: #c62828; }

.dfe-urgente { color: #c62828; font-weight: 600; }
.dfe-alerta { color: #c62828; }
/* Cancelada pelo emitente: continua na lista com o que declaramos — apagar
   seria apagar a prova —, mas não pode parecer boa. */
.dfe-cancelada { opacity: .62; text-decoration: line-through; }
.dfe-cancelada a, .dfe-cancelada button { text-decoration: none; }

.dfe-dialogo-botoes { display: flex; gap: .5rem; margin-top: .6rem; }

/* §2.4 — o par obrigatório. Esta classe declara `display`, então venceria
   `[hidden]` por especificidade e o campo de justificativa nasceria visível
   nas três manifestações que não o comportam. */
.form__field.dfe-just:not([hidden]) { display: block; }
.form__field.dfe-just[hidden]       { display: none; }

/* Aviso de DF-e pendentes na tela de Notas Fiscais. Discreto de propósito —
   é lembrete, não erro —, mas com a cor que faz o olho parar. */
.dfe-aviso-nf {
  margin: 0 0 .5rem;
  padding: .35rem .6rem;
  border-left: 3px solid #c62828;
  background: rgba(198, 40, 40, .07);
  font-size: .78rem;
}

/* ---- DF-e Recebidos: barra de ações e grade (leiaute do print, 31/08/2026) */
/* A barra age sobre as linhas marcadas. Azul cheio como no print — é a ação
   principal da tela, e a caixa de entrada existe para levar a ela. */
.dfe-acoes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .4rem;
  margin: .5rem 0 .35rem;
}
.dfe-acoes__form { display: contents; }
.dfe-acao {
  border: 0;
  border-radius: 3px;
  background: #1a7fd4;
  color: #fff;
  font-size: .78rem;
  padding: .38rem .8rem;
  cursor: pointer;
}
.dfe-acao:hover:not(:disabled) { background: #1569b0; }
.dfe-acao:disabled { background: #b9c6d2; cursor: not-allowed; }
.dfe-acoes__conta { font-size: .72rem; opacity: .8; }

.dfe-col-marca { width: 2.2rem; text-align: center; }
.dfe-grid td small { display: block; line-height: 1.1; }

/* As quatro marcas de status. Cinza é "ainda não", nunca erro — uma nota
   recém-chegada tem três cinzas, e isso é o estado normal. Cada uma leva
   `title`: cor sozinha não informa quem não decorou a legenda. */
.dfe-status { white-space: nowrap; }
.dfe-bolha {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.35rem;
  height: 1.35rem;
  margin-right: .18rem;
  border-radius: 50%;
  font-size: .72rem;
  line-height: 1;
  color: #fff;
  cursor: help;
}
.dfe-bolha--verde    { background: #1e9e57; }
.dfe-bolha--vermelha { background: #d33; }
.dfe-bolha--amarela  { background: #e8b011; }
.dfe-bolha--cinza    { background: #c3ccd4; }

.dfe-opcoes { white-space: nowrap; }
.dfe-opcoes a, .dfe-opcoes span { margin-right: .3rem; text-decoration: none; }
.dfe-opcao--off { opacity: .3; cursor: not-allowed; }

/* Prazo vencido: passado o prazo a nota já foi confirmada pelo silêncio, então
   não é "mais urgente" — é outro estado. Cinza riscado, não vermelho, porque
   vermelho pede ação e aqui a ação passou. */
.dfe-vencido { opacity: .7; }
.dfe-vencido small { font-weight: 600; }
.dfe-cartao--vencido { border-color: #8a6d3b; }
.dfe-cartao--vencido .dfe-cartao__numero { color: #8a6d3b; }

/* As cores dos tipos são as MESMAS das séries do gráfico e das etiquetas da
   grade — é por elas que o olho liga as três leituras do mesmo dado. */
.dfe-cartao--nfe  { border-color: #2563eb; }
.dfe-cartao--cte  { border-color: #b45309; }
.dfe-cartao--nfse { border-color: #15803d; }
/* **Abaixo de `.dfe-cartao`, e não acima.** Mesma especificidade: a regra que
   vem antes perde da geral e simplesmente não vale — foi o que aconteceu na
   primeira versão, e a cor não aparecia. */

/* Liga/desliga do monitoramento automático. Estado por PALAVRA, não só por
   cor: "LIGADO" escrito não depende de o operador lembrar o que verde quer
   dizer, nem de ele enxergar a diferença entre os dois tons. */
.dfe-chave {
  display: flex;
  align-items: center;
  gap: .5rem;
  flex-wrap: wrap;
  margin: .3rem 0 .5rem;
}
.dfe-chave__estado { font-size: .78rem; font-weight: 600; opacity: .65; }
.dfe-chave__estado--on { color: #1e9e57; opacity: 1; }

/* Tipo do documento na caixa de entrada. O CT-e é frete e o "emitente" dele é
   a TRANSPORTADORA — sem a etiqueta, quem olha estranha ver uma transportadora
   onde esperava o fornecedor. */
.dfe-doc {
  display: inline-block;
  padding: .05rem .3rem;
  border-radius: 3px;
  font-size: .68rem;
  font-weight: 600;
  white-space: nowrap;
}
.dfe-doc--nfe { background: #e3edf7; color: #1a5c94; }
.dfe-doc--cte { background: #efe6f7; color: #6a3d93; }
.dfe-doc--nfse { background: #e6f4ea; color: #1e6b3a; }

/* A corrente nota → CT-e → MDF-e. Indentação mostra a hierarquia da viagem
   sem precisar de desenho. */
.dfe-frete { margin-bottom: .5rem; }
.dfe-frete__linha { margin: .15rem 0; font-size: .8rem; }
.dfe-frete__filho { padding-left: 1.6rem; }
.dfe-doc--mdfe { background: #fdf0e3; color: #96591a; }



/* Altura FIXA no contêiner do gráfico, com `maintainAspectRatio: false` no
   Chart.js: sem isso o canvas cresce a cada redesenho, porque o Chart.js lê a
   altura do pai e o pai lê a do canvas. */
.dfe-graficos { display: grid; grid-template-columns: 2fr 1fr; gap: 12px; }
@media (max-width: 900px) { .dfe-graficos { grid-template-columns: 1fr; } }
.dfe-grafico__titulo { font-size: .82rem; margin: 0 0 1px; }
.dfe-grafico__ajuda  { font-size: .7rem; margin: 0 0 6px; }
.dfe-grafico__tela   { position: relative; height: 210px; }

/* Escolha do XML na caixa de DF-e, dentro da importação de NF-e de entrada
   (01/09/2026). A grade tem altura máxima e rola por dentro: a lista pode
   passar de quinhentas linhas, e sem teto ela empurraria o resto do
   formulário — inclusive o botão de importar — para fora da tela. */
.dfe-escolha__grade { max-height: 260px; overflow-y: auto; }
.dfe-escolha__linha { cursor: pointer; }
.dfe-escolha__linha:focus { outline: 2px solid var(--primary, #2563eb); outline-offset: -2px; }
/* **A linha marcada, com especificidade suficiente para vencer o hover da
   grade.** `.grid tbody tr:hover` pesa 0-2-2; `.dfe-escolha__linha--marcada:hover`
   pesa 0-2-0 e PERDE — com o mouse ainda sobre a linha logo depois do clique,
   o hover pintava #f7f9fb por cima do azul, e a seleção aparecia como uma
   linha branca. É a armadilha de especificidade do §2.33: a regra que parece
   mais específica para o humano não é a mais específica para o navegador.

   E vai no `td`, não só no `tr`: a célula tem fundo próprio e pinta por cima
   do fundo da linha. */
.grid tbody tr.dfe-escolha__linha--marcada,
.grid tbody tr.dfe-escolha__linha--marcada:hover { background: var(--primary); }
.grid tbody tr.dfe-escolha__linha--marcada > td,
.grid tbody tr.dfe-escolha__linha--marcada:hover > td {
  background: var(--primary);
  color: #fff;
}

/* Período do expurgo de XML (01/09/2026) — pedido do usuário: campo de data
   com a MESMA altura do botão, os três alinhados pela BASE, e o texto de
   apoio 3mm abaixo.

   **Declarar altura de campo contraria o §2.33 de propósito**, e por isso a
   regra é presa a esta faixa (`.expurgo-periodo`) em vez de solta: aqui o
   campo divide a fileira com um botão, e a diferença de 7px entre os dois
   (27 contra 34) aparecia como degrau. Fora daqui o padrão compacto continua
   valendo inteiro. */
.expurgo-periodo { align-items: start; }
.expurgo-periodo input[type="date"],
.expurgo-periodo .btn {
  height: 34px;
  box-sizing: border-box;
}
/* O `3mm` vai em milímetro mesmo, e não convertido para pixel: foi assim que
   foi pedido, e a unidade diz sozinha o que a conta esconderia. */
.expurgo-periodo .secao-cartao__ajuda { margin-top: 3mm; }

/* AJUDA POR TELA (02/09/2026) — a página que o [Ajuda] da barra abre.
   Coluna de leitura estreita de propósito: é texto para ler, não grade
   para varrer, e linha longa demais cansa. */
/* A largura de leitura vai nas SEÇÕES, não no container: assim o print
   pode ser largo (é uma tela inteira, ilegível a 74ch) enquanto o texto
   continua estreito o bastante para ler sem cansar. */
.ajuda__caminho { color: var(--text-muted); font-size: .82rem; margin: 0 0 14px; }
.ajuda__contagem { color: var(--text-muted); font-size: .84rem; margin: 0 0 14px; }
.ajuda__secao { margin: 0 0 26px; max-width: 74ch; }
.ajuda__secao h2 {
  font-size: .95rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--primary); margin: 0 0 10px; padding-bottom: 5px;
  border-bottom: 1px solid var(--border);
}
.ajuda p { line-height: 1.62; margin: 0 0 11px; }

.ajuda__secao--atencao p {
  border-left: 3px solid #d9a441; padding: 8px 0 8px 12px;
  background: rgba(217,164,65,.07); border-radius: 0 4px 4px 0;
}

/* Manual de TREINAMENTO (08/09/2026) — a única seção que precisa ser mais
   larga que a medida de leitura de 74ch: o diagrama tem que caber sem
   espremer o texto das caixas. */
.ajuda__secao--diagrama { max-width: none; }
.ajuda__diagrama { max-width: 860px; overflow-x: auto; margin: 0 0 8px; }
.ajuda__diagrama svg { display: block; }

.ajuda__passos { list-style: none; counter-reset: passo; margin: 0; padding: 0; }
.ajuda__passos li {
  counter-increment: passo; position: relative;
  padding: 0 0 14px 34px; line-height: 1.62;
}
.ajuda__passos li::before {
  content: counter(passo); position: absolute; left: 0; top: 1px;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--primary); color: #fff;
  font-size: .74rem; font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}
.ajuda__passos li b { display: block; margin-bottom: 2px; }

.ajuda__print { margin: 0 0 26px; max-width: 1120px; }
.ajuda__print img {
  width: 100%; height: auto;
  border: 1px solid var(--border); border-radius: var(--radius);
  display: block;
}
.ajuda__print figcaption {
  font-size: .74rem; color: var(--text-muted); margin-top: 6px;
}

.ajuda__relacionadas { list-style: none; margin: 0; padding: 0; max-width: 74ch; }
.ajuda__relacionadas li {
  display: flex; align-items: baseline; gap: 9px;
  padding: 6px 0; border-bottom: 1px solid var(--border);
}
.ajuda__relacionadas li:last-child { border-bottom: none; }
.ajuda__relacionadas small { color: var(--text-muted); font-size: .74rem; }
.ajuda__indisponivel { color: #c2c6cc; }
.ajuda__link-ajuda {
  margin-left: auto; flex: 0 0 auto;
  width: 20px; height: 20px; border-radius: 50%;
  border: 1px solid var(--border); color: var(--text-muted);
  font-size: .72rem; text-decoration: none;
  display: inline-flex; align-items: center; justify-content: center;
}
.ajuda__link-ajuda:hover { border-color: var(--primary); color: var(--primary); }

.ajuda__num {
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: .72rem; color: var(--text-muted);
  font-variant-numeric: tabular-nums; min-width: 2.2em; text-align: right;
}

/* AJUDA — os PONTOS (bolas numeradas sobre o print) e o GLOSSÁRIO
   (02/09/2026). As cores vivem em `ajuda_catalogo.CORES` e chegam aqui por
   `style=`: um só lugar governa a bola do print, a bola da lista e a
   legenda, e é isso que impede a legenda de mentir. */
.ajuda__legenda { display: flex; flex-wrap: wrap; gap: 14px; margin: 0 0 14px; }
.ajuda__legenda span {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .76rem; color: var(--text-muted);
}
.ajuda__legenda i { width: 11px; height: 11px; border-radius: 50%; flex: 0 0 auto; }

.ajuda__pontos { list-style: none; margin: 0; padding: 0; }
.ajuda__pontos li { display: flex; gap: 11px; padding: 0 0 14px; line-height: 1.62; }
.ajuda__pontos li > div { display: flex; flex-direction: column; }
.ajuda__pontos li b { margin-bottom: 2px; }
.ajuda__bola {
  flex: 0 0 auto; width: 23px; height: 23px; border-radius: 50%;
  color: #fff; font-size: .76rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 2px #fff, 0 1px 3px rgba(0,0,0,.3);
}

.ajuda__busca {
  width: 100%; max-width: 74ch; box-sizing: border-box; height: 32px;
  padding: 5px 9px; font-size: .86rem; font-family: inherit;
  border: 1px solid var(--border); border-radius: 4px; margin: 0 0 16px;
  background: var(--bg, #fff); color: var(--text);
}
.ajuda__busca:focus { outline: 2px solid var(--primary); outline-offset: -1px; }

.ajuda__glossario { margin: 0; max-width: 74ch; }
/* O par do §2.4: a classe declara `display`, então vence `[hidden]` por
   especificidade e o verbete filtrado continuaria visível. */
.ajuda__verbete:not([hidden]) { display: block; }
.ajuda__verbete[hidden] { display: none; }
.ajuda__verbete { padding: 11px 0; border-bottom: 1px solid var(--border); }
.ajuda__verbete:last-child { border-bottom: none; }
.ajuda__verbete dt { margin: 0 0 4px; }
.ajuda__verbete dt b { font-size: .95rem; color: var(--primary); }
.ajuda__verbete dt span { font-size: .78rem; color: var(--text-muted); margin-left: 7px; }
.ajuda__verbete dd { margin: 0; }
.ajuda__verbete dd p { margin: 0 0 5px; line-height: 1.6; }
.ajuda__verbete-telas { display: flex; flex-wrap: wrap; gap: 12px; font-size: .78rem; }
.ajuda__vazio-glossario:not([hidden]) { display: block; }
.ajuda__vazio-glossario[hidden] { display: none; }
.ajuda__vazio-glossario { color: var(--text-muted); font-size: .84rem; }

/* AJUDA — DUAS COLUNAS (02/09/2026). O texto sozinho ocupava 706px de 1374
   disponíveis: a medida de leitura (74ch) é regra boa, mas aplicada sozinha
   deixava METADE da tela vazia e esticava a página para três rolagens. A
   coluna da direita não é preenchimento — leva o material de REFERÊNCIA
   (telas relacionadas, termos do glossário), que se consulta e não se lê em
   sequência, e com isso a página encurta. */
.ajuda__colunas {
  display: grid; grid-template-columns: minmax(0, 74ch) minmax(0, 1fr);
  gap: 30px; align-items: start;
  /* Casa com a largura do print acima (1120px): as duas colunas terminam
     na mesma linha vertical em que a imagem termina. Sem isto a lateral
     esticava até 598px — larga demais para itens de uma linha, e o bloco
     ficava desalinhado do print. */
  max-width: 1120px;
}
.ajuda__principal { min-width: 0; }

/* `sticky` para a referência acompanhar a leitura: quem está no meio de
   "Os campos da tela" continua com as telas relacionadas à vista. */
.ajuda__lateral { position: sticky; top: 12px; display: flex;
                  flex-direction: column; gap: 14px; }

.ajuda__caixa {
  border: 1px solid var(--border); border-radius: var(--radius);
  padding: 12px 14px; background: var(--panel);
}
.ajuda__caixa h3 {
  margin: 0 0 9px; font-size: .74rem; text-transform: uppercase;
  letter-spacing: .05em; color: var(--text-muted); font-weight: 700;
}
.ajuda__caixa-rodape { margin: 9px 0 0; font-size: .76rem; }

.ajuda__lateral-lista { list-style: none; margin: 0; padding: 0; }
.ajuda__lateral-lista li {
  display: flex; align-items: baseline; gap: 7px;
  padding: 5px 0; font-size: .8rem; line-height: 1.4;
}
.ajuda__lateral-lista li + li { border-top: 1px solid var(--border); }

.ajuda__lateral-termos { list-style: none; margin: 0; padding: 0; }
.ajuda__lateral-termos li + li { border-top: 1px solid var(--border); }
.ajuda__lateral-termos a {
  display: flex; flex-direction: column; padding: 6px 0; text-decoration: none;
}
.ajuda__lateral-termos b { font-size: .82rem; color: var(--primary); }
.ajuda__lateral-termos small { font-size: .7rem; color: var(--text-muted); line-height: 1.3; }
.ajuda__lateral-termos a:hover b { text-decoration: underline; }

/* O verbete alvo do link piscando de leve — sem isso o salto por âncora
   deixa o leitor procurando qual dos 22 ele pediu. */
.ajuda__verbete:target { background: var(--focus-glow); border-radius: 4px;
                         box-shadow: 0 0 0 8px var(--focus-glow); }

/* Numa tela estreita as duas colunas viram uma, e a referência vai para o
   fim — é consulta, não leitura. */
@media (max-width: 1100px) {
  .ajuda__colunas { grid-template-columns: minmax(0, 1fr); }
  .ajuda__lateral { position: static; }
}

/* AJUDA — as SUB-TELAS no índice (02/09/2026). Notas Fiscais é um item de
   menu só, mas o fluxo tem catorze telas; elas aparecem recuadas sob a dona,
   e não como itens de primeiro nível, porque não é assim que se chega nelas. */
.ajuda__filhas {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  padding: 4px 0 8px 34px; font-size: .78rem;
  border-bottom: 1px solid var(--border);
}

/* AJUDA — A TRILHA (02/09/2026; visual refeito em 03/09/2026 a pedido do
   usuário). Pedido original: a lista inteira em cinza escuro, e o item vai
   para AZUL à medida que ganha ajuda — a cor não é enfeite, é o mapa do que
   falta, à vista, sem precisar contar.

   O REDESENHO de 03/09: fora o desenho da árvore (as linhas verticais e os
   traços que ligavam galho e tronco) e fora o sublinhado. Numa lista de 60
   itens em catorze capítulos, o rabisco competia com o texto e não dizia
   nada que a INDENTAÇÃO já não diga. O que separa os níveis agora é o
   tamanho da letra: o item de menu é maior e em negrito, a sub-tela é
   menor e leve. E o NÚMERO da tela ficou em negrito, porque é por ele que
   se acha a tela no menu — é dado, não enfeite. */
.ajuda__trilha { max-width: 74ch; }

/* Divisão TREINAMENTO (08/09/2026) — separada da trilha (tela-a-tela) de
   propósito: aqui o "item" é um manual inteiro, não uma tela. */
.ajuda__divisao {
  max-width: 74ch; margin: 0 0 30px; padding: 18px 20px;
  background: var(--panel-2, #eaf1f9); border: 1px solid var(--border);
  border-radius: var(--radius);
}
.ajuda__divisao h2 {
  font-size: .95rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--primary); margin: 0 0 6px;
}
.ajuda__treinamentos { list-style: none; margin: 14px 0 0; padding: 0; }
.ajuda__treinamento-item { padding: 10px 0; border-top: 1px solid var(--border); }
.ajuda__treinamento-item a { font-weight: 600; }
.ajuda__treinamento-item p {
  color: var(--text-muted); font-size: .84rem; margin: 4px 0 0;
}

.ajuda__cap { margin: 0 0 26px; }
.ajuda__cap h2 {
  font-size: .95rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--primary); margin: 0 0 4px; padding-bottom: 5px;
  border-bottom: 1px solid var(--border);
}
.ajuda__cap-resumo { color: var(--text-muted); font-size: .82rem; margin: 0 0 10px; }

/* Sem linha vertical, sem traço de ligação: só indentação. */
.ajuda__galhos {
  list-style: none; margin: 0; padding: 0 0 0 4px;
}
.ajuda__galho {
  position: relative; padding: 3px 0 3px 2px; line-height: 1.4;
}
.ajuda__galho-num {
  display: inline-block; min-width: 2.6em; margin-right: 8px;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: .78rem; font-weight: 700; color: var(--text-muted);
  font-variant-numeric: tabular-nums; text-align: right;
}

/* PRIMEIRO NÍVEL — o item de menu: maior e em negrito. */
.ajuda__galho > a,
.ajuda__galho > span:not(.ajuda__galho-num) {
  font-size: .98rem; font-weight: 700; text-decoration: none;
}
.ajuda__galho > a:hover { text-decoration: underline; }

/* CINZA ESCURO = ainda sem ajuda. Não é `disabled` nem apagado: a tela
   existe, o texto é que não. */
.ajuda__galho--vazia > span:not(.ajuda__galho-num) { color: #5b6472; }
/* AZUL = já escrita, e clicável. `:visited` junto, senão o navegador pinta
   de roxo o que já foi lido e a cor deixa de ser o mapa da dívida. */
.ajuda__galho--escrita > a,
.ajuda__galho--escrita > a:visited { color: var(--primary); }

/* SUB-NÍVEL — as telas de dentro do fluxo: um pouco menores e leves, sem
   marcador nenhum; a indentação já diz que são filhas. */
.ajuda__subgalhos {
  list-style: none; margin: 1px 0 2px; padding: 0 0 0 3.4em;
  display: flex; flex-direction: column; gap: 1px;
}
.ajuda__subgalhos li { position: relative; }
.ajuda__subgalhos a,
.ajuda__subgalhos a:visited {
  font-size: .84rem; font-weight: 400; color: var(--primary);
  text-decoration: none;
}
.ajuda__subgalhos a:hover { text-decoration: underline; }

.ajuda__legenda-azul  { color: var(--primary); font-weight: 600; }
.ajuda__legenda-cinza { color: #5b6472; font-weight: 600; }

/* AJUDA — o PRINT abre a tela (02/09/2026, correção do usuário). Dentro da
   ajuda, link leva a ajuda; para ir à tela de verdade o gesto é clicar no
   print dela. É o alvo mais óbvio da página e não tira ninguém do lugar por
   engano — quem clica numa foto da tela quer a tela. */
.ajuda__print-link { display: block; position: relative; text-decoration: none; }
.ajuda__print-link img { transition: box-shadow .12s, transform .12s; }
.ajuda__print-link:hover img {
  box-shadow: 0 0 0 2px var(--primary), 0 8px 22px rgba(0,0,0,.16);
}
.ajuda__print-abrir {
  position: absolute; right: 10px; bottom: 10px;
  background: var(--primary); color: #fff;
  padding: 5px 10px; border-radius: 4px; font-size: .74rem; font-weight: 600;
  opacity: 0; transition: opacity .12s; pointer-events: none;
}
.ajuda__print-link:hover .ajuda__print-abrir { opacity: 1; }
/* Sem :hover (toque), o convite fica sempre visível — senão no celular
   ninguém descobre que o print é clicável. */
@media (hover: none) { .ajuda__print-abrir { opacity: 1; } }

.ajuda__caixa-nota {
  margin: -5px 0 8px; font-size: .7rem; color: var(--text-muted);
}

/* ------------------------------------------------------------------------
   GEOLOCALIZAÇÃO DE CLIENTES (08/09/2026, mapa 2D desde 09/09/2026) —
   Comercial > Vendas > Análise. Tela nova sem equivalente no VB6; segue o
   mesmo espírito visual do painel de BI (.bi-*), com um mapa (Leaflet +
   OpenStreetMap) no lugar do gráfico.
   ------------------------------------------------------------------------ */
.geo-subtitulo {
  margin: 2px 0 12px; font-size: .82rem; color: var(--text-muted); max-width: 720px;
}
/* Filiais à esquerda, De/Até empilhados à direita (09/09/2026, layout
   pedido pelo usuário por print) — por isso `align-items: flex-start`,
   não `flex-end`: os dois blocos começam no mesmo topo, e Filiais é mais
   alto que uma linha de data só. */
.geo-barra { display: flex; align-items: flex-start; gap: 20px; flex-wrap: wrap; }
.geo-barra .form__field { margin: 0; }
.geo-barra input[type="date"] { width: 132px; }
.geo-barra .relatorio-filiais { min-width: 200px; max-width: 260px; }
.geo-datas { display: flex; flex-direction: column; gap: 10px; }
.geo-nota {
  margin: 0 0 0 auto; max-width: 320px; font-size: .74rem; color: var(--text-muted);
}

.geo-resumo {
  margin: 10px 0 4px; padding: 6px 10px; border-radius: 4px;
  background: var(--linha-destaque, #eef4fb); font-size: .82rem; font-weight: 600;
}

.geo-cores { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 4px 0 0; font-size: .76rem; color: var(--text-muted); }
.geo-cor-item { display: inline-flex; align-items: center; gap: 6px; }
.geo-cor-bola { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex: none; }

/* Mapa 30% mais estreito, produtos/clientes 30% mais largos pra compensar
   (09/09/2026, pedido do usuário — a legenda estava cortando informação
   com a coluna do CÓDIGO do produto nova, e a lista deixou de ter só 5
   linhas). Era `1fr 320px` (legenda fixa, ~23% da largura); a proporção
   nova (8fr:7fr ≈ 53%:47%) dá à legenda quase o dobro do espaço. */
.geo-corpo { display: grid; grid-template-columns: 8fr 7fr; gap: 14px; margin-top: 10px; }
.geo-globo-wrap { position: relative; border: 1px solid var(--line, #dfe3e8); border-radius: 6px; overflow: hidden; }
#geo-mapa2d { width: 100%; height: 520px; }
.geo-globo-dica {
  position: absolute; left: 10px; bottom: 8px; margin: 0;
  font-size: .7rem; color: rgba(255,255,255,.85); text-shadow: 0 1px 2px rgba(0,0,0,.6);
  pointer-events: none;
}

.geo-legenda {
  border: 1px solid var(--line, #dfe3e8); border-radius: 6px; padding: 12px;
  min-width: 0; max-height: 520px; overflow: auto;
}
.geo-legenda h3 { margin: 0 0 8px; font-size: .92rem; }
.geo-legenda-vazio { font-size: .8rem; color: var(--text-muted); }
.geo-legenda-meta { font-size: .76rem; color: var(--text-muted); margin: 0 0 8px; }
.geo-legenda-sem { font-size: .8rem; color: var(--text-muted); }
/* Lista de produtos deixou de ter só 5 linhas (09/09/2026, "ver todos os
   produtos") — rolagem PRÓPRIA, mais estreita que o padrão de `.grid-wrap`
   (480px), pra sobrar espaço pro título e a meta acima dela dentro do
   `.geo-legenda` (que também rola, se precisar). */
/* Aproveita quase toda a altura do painel (520px, igual ao mapa) — só
   título e meta ficam de fora; linhas mais baixas (abaixo) cabem bem mais
   nesse espaço do que a linha padrão de 42px do `.grid`. */
.geo-legenda-produtos-wrap { max-height: 420px; }
/* Descrição do produto pode ser mais larga que a coluna elástica sozinha
   resolve (o `.grid--5mm` padrão mede cada coluna pelo conteúdo mais
   largo, sem quebrar linha) — libera a quebra só nesta coluna, pra não
   empurrar QTD./VALOR pra fora do painel. */
#geo-legenda-tabela td:nth-child(2) { white-space: normal; word-break: break-word; }
/* Linha mais baixa (09/09/2026, "aproveite a altura... para caber mais
   itens") — de 11px/20px de sobra pra 3px/2.5mm, quase a metade da
   altura da linha padrão do `.grid`, pra listar bem mais produtos sem
   rolar. */
#geo-legenda-tabela thead th { padding-top: 5px; padding-bottom: 5px; }
#geo-legenda-tabela tbody td { padding-top: 3px; padding-bottom: 3px; font-size: 0.82rem; }

.geo-tabelas { display: grid; grid-template-columns: 2fr 1fr; gap: 14px; margin-top: 18px; }
.geo-tabelas h3 { margin: 0 0 6px; font-size: .9rem; }
.geo-tabela-municipios .grid-wrap { max-height: 46vh; overflow: auto; }
.geo-tabela-municipios .grid thead th { position: sticky; top: 0; z-index: 1; background: var(--bg, #fff); }
.geo-linha-municipio:hover { background: var(--linha-destaque, #e8f3ff); }

.geo-tabela-clientes { margin-top: 18px; }
.geo-tabela-clientes h3 { margin: 0 0 6px; font-size: .9rem; }
.geo-tabela-clientes .grid-wrap { max-height: 40vh; overflow: auto; }
.geo-tabela-clientes .grid thead th { position: sticky; top: 0; z-index: 1; background: var(--bg, #fff); }
.geo-tabela-clientes tbody tr:hover { background: var(--linha-destaque, #e8f3ff); }
.geo-tabela-clientes tr.geo-linha-selecionada { background: var(--linha-destaque, #dbeafe); }
.geo-clientes-dica { margin: 6px 0 0; font-size: .72rem; color: var(--text-muted); }

@media (max-width: 1100px) {
  .geo-corpo { grid-template-columns: 1fr; }
  .geo-tabelas { grid-template-columns: 1fr; }
  .geo-legenda { max-height: none; }
}

/* ------------------------------------------------------------------------
   PEDIDOS DO GRP MOBILE (09/09/2026) — três painéis-filtro clicáveis
   (Operações/UFs/Situações), substituindo o filtro de texto livre antigo;
   layout inspirado na tela real do VB6 (frmNFEPEDIDOS.frm), print do
   usuário. Sem padrão de "tile clicável" no projeto — cada linha do
   painel é uma âncora de verdade (GET), não um componente novo.
   ------------------------------------------------------------------------ */
.pedidosgrpm-periodo { display: flex; gap: 14px; margin-bottom: 12px; }
.pedidosgrpm-paineis { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 16px; }
.pedidosgrpm-painel {
  flex: 1 1 220px; min-width: 200px; border: 1px solid var(--border);
  border-radius: var(--radius); padding: 6px 10px 4px;
}
.pedidosgrpm-painel legend { padding: 0 6px; font-size: .8rem; font-weight: 600; color: var(--text-muted); }
.pedidosgrpm-painel table { width: 100%; }
.pedidosgrpm-painel td a { color: var(--text); text-decoration: none; display: block; }
.pedidosgrpm-painel tr:hover { background: var(--linha-destaque, #eef4fb); cursor: pointer; }
/* Linha mais baixa pra caber mais item, e rolagem PRÓPRIA quando a lista
   passa da altura — pedido do usuário, 16/09/2026. O cabeçalho continua
   fixo no topo (herda o `position: sticky` de `.grid thead th`) porque
   é o SCROLL (não o fieldset inteiro) que cria a área de rolagem.
   `scroll` (não `auto`): a barra fica sempre à vista, mesmo com poucas
   linhas — pedido explícito do usuário, que não via a barra aparecer
   com `auto` (as 3 caixas raramente têm linha suficiente pra estourar). */
.pedidosgrpm-painel-scroll { max-height: 190px; overflow-y: scroll; }
.pedidosgrpm-painel .grid thead th { padding: 6px 10px; font-size: .72rem; }
.pedidosgrpm-painel .grid tbody td { padding: 4px 10px; font-size: .82rem; }
.pedidosgrpm-linha-ativa { background: var(--linha-destaque, #dbeafe); font-weight: 600; }
.pedidosgrpm-subtitulo { margin: 18px 0 6px; font-size: .92rem; }
.pedidosgrpm-linha-faturada { cursor: pointer; color: var(--primary, #2563eb); }
.pedidosgrpm-linha-faturada:hover { background: var(--linha-destaque, #eef4fb); }
.pedidosgrpm-acoes { display: flex; gap: 10px; margin-top: 10px; }

/* Legenda da Lista de Pedidos (07/10/2026) — cinco estados que a grade
   distingue por COR e por CAIXA, e que ninguém adivinha olhando.
   As cores vêm das MESMAS variáveis que as linhas usam: mudar a linha sem
   mudar aqui faz a legenda mentir. */
.pedidosgrpm-legenda {
    list-style: none;
    margin: 0 0 12px;
    padding: 8px 12px;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 22px;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    background: var(--panel);
    font-size: .85rem;
}
.pedidosgrpm-legenda li { display: flex; align-items: center; gap: 6px; }
.pedidosgrpm-legenda input[type="checkbox"] { margin: 0; }
/* A LINHA e a LEGENDA do não-suportado compartilham a cor de propósito:
   eram `#9aa2ad` fixo na linha e variável na legenda, e no tema escuro as
   duas divergiriam — a legenda passaria a descrever um cinza que a grade
   não usa. */
.pedidosgrpm-linha-naosuportada,
.pedidosgrpm-legenda__naosuportado { color: var(--text-muted); }
.pedidosgrpm-legenda__faturado { color: var(--primary); }
/* O traço ocupa a largura de uma caixa, para os cinco itens alinharem. */
.pedidosgrpm-legenda__semcaixa {
    display: inline-block;
    width: 13px;
    text-align: center;
    opacity: .55;
}

/* A LICENÇA na barra do topo (24/09/2026) — mesmo lugar e mesmo peso do
   indicador de certificado, porque as duas respondem à mesma pergunta:
   "isto aqui vai parar de funcionar em breve?". As cores seguem os
   limiares pedidos pelo usuário: verde acima de 5 dias, amarelo de 5 a 3,
   vermelho de 2 a 0 — e vermelho fixo quando bloqueada. */
.topbar__licenca {
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.02em;
  padding: 2px 9px; border-radius: 999px; margin-left: 10px;
  background: rgba(255,255,255,0.10);
}
.topbar__licenca--verde    { color: #7ee29a; }
.topbar__licenca--amarelo  { color: #ffd75e; }
.topbar__licenca--vermelho { color: #ff8a80; background: rgba(255,80,80,0.18); }

/* ---------------------------------------------------------------------
   Atendimento Vixtec (tela 166, 25/09/2026) — a conversa com o suporte.
   A bolha é o único desenho novo: o resto da tela usa `produtos-secao`,
   `ncm-linha-4` e `grid` como qualquer outra.
   --------------------------------------------------------------------- */
#vx-conversa {
  display: flex; flex-direction: column; gap: 8px;
  /* Mais alta que antes: o compositor virou uma barra fina e devolveu
     espaço à leitura. O PISO importa tanto quanto o teto: sem ele a área
     encolhia com o conteúdo, e a barra de escrever subia e descia a cada
     mensagem nova — quem está digitando via o campo fugir. */
  min-height: min(260px, 34vh);
  max-height: 58vh; overflow-y: auto;
  /* O conteúdo começa embaixo: com poucas mensagens, a última fica junto do
     campo de escrever, e não flutuando no alto de um retângulo vazio. */
  justify-content: flex-end;
  padding: 10px; margin-bottom: 12px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--bg);
}
.vx-msg {
  max-width: min(560px, 82%);
  padding: 7px 11px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--panel);
  /* `break-word`: mensagem colada de um log vem numa linha só e estouraria
     a largura da conversa inteira. */
  overflow-wrap: break-word;
}
.vx-msg--eu {
  align-self: flex-end;
  background: var(--success-bg);
  border-color: var(--success-text);
}
.vx-msg__quem { font-size: 0.78rem; color: var(--text-muted); margin-bottom: 2px; }
/* O campo de texto ocupa a fileira; o botão fica do lado, como nas demais. */
.vx-campo-texto { flex: 1 1 60%; }
/* ---------------------------------------------------------------------
   O COMPOSITOR da tela 166 — a barra de escrever, que gruda no fim da tela.
   A conversa mora no pé de uma página que cresce com a grade de chamados; sem
   `sticky` o operador rolava para ver a última frase e para escrever.
   --------------------------------------------------------------------- */
/* A barra de estado do chamado, acima da conversa (tela 166). Diz em que
   pé está o atendimento e oferece a saída — o botão de encerrar. */
.vx-barra {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 8px;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}
.vx-barra .btn { margin-left: auto; }
.vx-barra[hidden] { display: none; }   /* §2.4: esta classe declara display */

/* A AVALIAÇÃO DO ATENDIMENTO, dentro da barra (tela 166). Ocupa a faixa
   inteira: a pergunta é o assunto da barra enquanto não houver nota, e
   dividir a linha com o "encerrado" faria as duas coisas competirem. */
.vx-avaliar {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
}
/* O `margin-left: auto` da regra acima empurraria cada botão de nota para a
   direita, um por linha. Ele existe para o [Encerrar]; aqui não serve. */
.vx-avaliar .btn { margin-left: 0; }
.vx-avaliar-topo { font-weight: 600; }
.vx-avaliar-notas { display: flex; flex-wrap: wrap; gap: 5px; }
/* Largura MÍNIMA e não fixa: o dígito é estreito, mas um botão de 2ch fica
   difícil de acertar com o dedo. Sem declarar altura nem fonte — o padrão
   compacto do §2.33 mira o campo, e botão novo entra nele sozinho. */
.vx-nota { min-width: 2.6rem; justify-content: center; }
.vx-nota--escolhida {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
  font-weight: 700;
}
/* §2.4, SEXTA APARIÇÃO DA ARMADILHA: esta classe declara `display`, e classe
   com `display` vence `[hidden]` por especificidade — sem o par abaixo o campo
   de motivo nasceria VISÍVEL, pedindo justificativa antes de haver nota. Só
   navegador mostra isso; `test_client()` não aplica CSS. */
.vx-avaliar-motivo:not([hidden]) {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.vx-avaliar-motivo[hidden] { display: none; }
.vx-avaliar-motivo .btn { align-self: flex-start; }

/* --- A DICA QUE APARECE AO PASSAR O MOUSE ---------------------------------
   Própria, e não o `title` do navegador, por três motivos medidos: o `title`
   demora cerca de um segundo para aparecer (quem já desistiu não vê), não se
   estiliza, e some sozinho depois de poucos segundos — curto demais para a
   frase que explica POR QUE o microfone está desligado.

   Aparece também no FOCO, não só no hover: quem navega por teclado precisa
   da mesma informação, e é o que torna a dica acessível em vez de decorativa. */
[data-dica] { position: relative; }
[data-dica]::after {
  content: attr(data-dica);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(3px);
  z-index: 40;
  /* Largura máxima com quebra: a dica do áudio é uma frase, não um rótulo.
     `nowrap` a jogaria para fora da tela. */
  width: max-content;
  max-width: 260px;
  white-space: normal;
  text-align: left;
  line-height: 1.35;
  padding: 7px 9px;
  border-radius: 6px;
  background: #1f2937;
  color: #f8fafc;
  font-size: 0.78rem;
  font-weight: 400;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.28);
  opacity: 0;
  pointer-events: none;   /* a dica nunca rouba o clique do botão */
  transition: opacity 0.12s ease, transform 0.12s ease;
}
[data-dica]:hover::after,
[data-dica]:focus-visible::after,
[data-dica]:focus-within::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
/* ANCORAGEM PELA BORDA, para quem está na ponta da fileira.
   A dica nasce CENTRADA no botão, e no primeiro botão metade dela cai fora
   da borda esquerda: o texto aparecia cortado, "ncerrar o atendimento"
   (relato com print, 26/09/2026). Quem está na ponta ancora pela SUA borda
   em vez de pelo centro — sem JavaScript e sem medir nada. */
[data-dica][data-dica-de="esquerda"]::after {
  left: 0; right: auto; transform: translateY(3px);
}
[data-dica][data-dica-de="esquerda"]:hover::after,
[data-dica][data-dica-de="esquerda"]:focus-visible::after,
[data-dica][data-dica-de="esquerda"]:focus-within::after {
  transform: translateY(0);
}
[data-dica][data-dica-de="direita"]::after {
  left: auto; right: 0; transform: translateY(3px);
}
[data-dica][data-dica-de="direita"]:hover::after,
[data-dica][data-dica-de="direita"]:focus-visible::after,
[data-dica][data-dica-de="direita"]:focus-within::after {
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  [data-dica]::after { transition: none; }
}
/* O invólucro do botão desabilitado: elemento `disabled` não dispara evento
   de mouse, então quem carrega a dica é o <span> em volta. */
.vx-dica-caixa { display: inline-flex; }

/* Encerrar: mesmo tamanho dos outros, tom de alerta contido — é uma ação
   sem volta, mas não é um erro. */
.vx-acao--fim { color: var(--danger); }
.vx-acao--fim:hover:not(:disabled) { background: var(--error-bg); }

/* O PAR DO `[hidden]` (§2.4, sétima aparição — 26/09/2026). Esta classe
   declara `display`, e classe vence atributo por especificidade: sem a
   segunda regra, `comp.hidden = true` não esconde nada, e o compositor
   continuava de pé num chamado já encerrado. Só aparece em navegador —
   `test_client()` não aplica CSS. */
.vx-compositor:not([hidden]) {
  position: sticky; bottom: 0; z-index: 3;
  display: flex; align-items: flex-end; gap: 8px;
  padding: 10px 0 2px;
  background: var(--panel);
  /* A sombra separa o compositor do texto que passa por baixo ao rolar —
     sem ela, a última bolha encosta na barra e as duas viram uma coisa só. */
  box-shadow: 0 -10px 12px -10px rgba(0, 0, 0, 0.25);
}
.vx-compositor[hidden] { display: none; }

.vx-compositor textarea {
  flex: 1 1 auto; min-width: 0;
  font-size: 1rem; line-height: 1.45;
  /* Cresce com o texto até um teto, como em qualquer mensageiro: uma linha
     para "ok", cinco para explicar um problema. */
  min-height: 42px; max-height: 8.5rem; resize: vertical;
  padding: 9px 12px;
}
.vx-acao {
  flex: 0 0 auto;
  width: 42px; height: 42px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 50%;
  background: var(--panel); color: var(--text-muted);
  cursor: pointer; padding: 0;
}
.vx-acao svg {
  width: 21px; height: 21px;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.vx-acao svg .cheio { fill: currentColor; stroke: none; }
.vx-acao:hover:not(:disabled) { color: var(--primary); border-color: var(--primary); }
.vx-acao:disabled { opacity: 0.45; cursor: not-allowed; }
.vx-acao--enviar {
  background: var(--primary); border-color: transparent; color: #fff;
}
.vx-acao--enviar:hover:not(:disabled) { background: var(--primary-dark); color: #fff; }
/* Gravando: o botão vira vermelho e mostra os segundos, em vez de trocar de
   texto — o ícone continua dizendo o que ele é. */
.vx-acao--gravando {
  background: var(--danger); border-color: transparent; color: #fff;
  position: relative;
}
.vx-acao--gravando::after {
  content: attr(data-seg);
  position: absolute; top: -6px; right: -6px;
  background: var(--danger); color: #fff;
  font-size: 0.66rem; font-weight: 600;
  padding: 1px 5px; border-radius: 9px;
  font-variant-numeric: tabular-nums;
}

/* O diálogo de abertura de chamado (tela 166). */
#vx-dialogo { min-width: min(620px, 94vw); }

/* EXCEÇÃO DELIBERADA ao padrão compacto (§2.33), pedida pelo usuário em
   25/09/2026: aqui a fonte e a altura SÃO declaradas.
   A razão é que este campo não é um campo de cadastro — é onde se escreve a
   primeira mensagem de uma conversa, e ela vai aparecer do outro lado numa
   bolha de chat a 1rem. Com o campo a 0,86rem, o operador escrevia menor do
   que o texto que ia ler depois, e num parágrafo de cinco linhas isso cansa.
   Fonte igual à da bolha, e altura para caber o problema inteiro sem rolar. */
#vx-dialogo textarea {
  width: 100%;
  font-size: 1rem;
  line-height: 1.5;
  min-height: 11rem;
  padding: 10px 12px;
}
#vx-dialogo h2 { margin-bottom: 4px; }
/* `.form` tem `max-width: 480px` — teto certo para um formulário de cadastro
   e errado aqui, porque encolhia o diálogo inteiro junto: a caixa de texto
   saía com 201px de largura, medida no navegador. Dentro deste diálogo o
   formulário ocupa a largura que o diálogo pedir. */
#vx-dialogo .form { max-width: none; width: 100%; padding: 18px 20px; }
/* `.form` é GRID de duas colunas, e o campo caía numa delas: 201px de
   largura num diálogo de 727px (medido, não estimado — §2.33). Aqui o campo
   atravessa as colunas, que é o que `--full` já faz nos formulários grandes. */
#vx-dialogo .form__field { grid-column: 1 / -1; }
#vx-dialogo .form__actions { grid-column: 1 / -1; justify-content: flex-end; }
#vx-dialogo .form__field > label { font-size: 0.82rem; }
/* Anexos da conversa do Atendimento (tela 166). */
.vx-anexo-img { display:block; max-width:min(420px,100%); border-radius:6px;
                margin-top:5px; cursor:zoom-in; }
.vx-anexo-audio { display:block; width:min(320px,100%); margin-top:5px; }
/* O consumo no cabeçalho da tela 166. Mora no `panel__head`, ao lado do
   título — é o primeiro lugar em que o olho cai ao abrir a tela. */
.vx-consumo {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-top: 4px; font-size: 0.86rem; color: var(--text-muted);
}
.vx-consumo b { color: var(--text); font-variant-numeric: tabular-nums; font-size: 1.05rem; }
.vx-consumo__rot { text-transform: uppercase; letter-spacing: 0.08em; font-size: 0.7rem; }
.vx-consumo--excedeu b { color: var(--danger); }
/* O relógio do chamado, na legenda do quadro da conversa. */
.vx-crono { font-variant-numeric: tabular-nums; color: var(--text-muted); font-weight: 400; }
.vx-crono--correndo { color: var(--success-text); font-weight: 600; }

/* Grupo na barra da direita (25/09/2026) — usado quando uma categoria de
   posição `direita` tem MAIS DE UM item. Com um só, continua link direto. */
.mainnav__grupo-direita { position: relative; display: inline-block; }
.mainnav__abre-grupo { background: none; border: 0; cursor: pointer; font: inherit; }
.mainnav__submenu {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 40;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: 0 8px 24px rgba(0,0,0,0.18);
  min-width: 190px; padding: 4px 0;
}
/* O PAR do `[hidden]` (§2.4): a regra acima não declara `display`, mas o
   par fica escrito assim mesmo — a próxima pessoa a acrescentar um
   `display` aqui não vai reintroduzir o bug pela sétima vez. */
.mainnav__submenu:not([hidden]) { display: block; }
.mainnav__submenu[hidden] { display: none; }
.mainnav__submenu a {
  display: block; padding: 7px 14px; color: var(--text);
  text-decoration: none; white-space: nowrap; font-size: 0.92rem;
}
.mainnav__submenu a:hover { background: var(--bg); color: var(--primary); }
/* A faixa de "gravação indisponível" foi embora em 26/09/2026: o motivo
   virou a DICA do microfone (`[data-dica]` acima). Dizia a mesma coisa,
   ocupava uma linha permanente e só era lida na primeira vez. */


/* Aviso da gravação automática das guias da Nota Fiscal (05/10/2026, item 9
   do Arthur). Discreto, mas presente: sem ele, tirar o botão "Gravar" deixa
   o operador sem saber se o que digitou foi para o banco. */
.autogravar-aviso { display: inline-block; margin-top: 10px; font-size: .82rem; min-height: 1.2em; }
.autogravar-aviso--indo  { color: var(--text-muted); }
.autogravar-aviso--ok    { color: #1e7e34; }
.autogravar-aviso--erro  { color: var(--danger); font-weight: 600; }
