/* Componentes reutilizáveis. */

.card {
  background: var(--surf);
  border: 1px solid var(--line);
  border-radius: var(--rad);
  box-shadow: var(--sh-1);
  min-width: 0;
}
.card-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px 10px;
  border-bottom: 1px solid var(--line);
}
.card-title { font-size: var(--fs-sm); font-weight: 650; letter-spacing: -.1px; }
.card-sub { font-size: var(--fs-xs); color: var(--ink-mute); }

/*
 * O TÍTULO QUE ABRE O PRÓPRIO CARTÃO — 13/09/2026.
 *
 * A composição da DRE passou a começar recolhida, e o controle que a abre é o
 * título dela. Ele precisa PARECER um título: um botão com a moldura do
 * navegador no meio de uma fileira de cartões leria como formulário.
 *
 * O que sobra do botão é o que importa — foco visível pelo teclado e cursor de
 * mão —, mais a seta, que é o único sinal de que ali há algo a abrir.
 */
.card-title.is-toggle {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 0; border: 0; background: none;
  font: inherit; font-size: var(--fs-sm); font-weight: 650; letter-spacing: -.1px;
  color: inherit; cursor: pointer;
}
.card-title.is-toggle:hover { color: var(--navy-2); }
.card-title.is-toggle:focus-visible { outline: 2px solid var(--navy-2); outline-offset: 3px; border-radius: 4px; }
.card-title.is-toggle .chevron { font-size: 11px; color: var(--ink-mute); line-height: 1; }

/*
 * O NÚMERO QUE ABRE, dentro de uma frase — §7, 05/09/2026.
 *
 * Herda tudo da frase (tamanho, cor, família) e muda só o peso e o sublinhado
 * pontilhado: quem lê percebe que ali dá para clicar sem que o número vire um
 * link azul no meio de uma legenda cinza.
 */
.link-num {
  appearance: none; background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; font-weight: 650; cursor: pointer;
  border-bottom: 1px dotted currentColor;
}
.link-num:hover { color: var(--navy); }
.link-num:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: 2px; }
.card-actions { margin-left: auto; display: flex; gap: 6px; align-items: center; }
.card-body { padding: 14px 16px; }
.card-body.flush { padding: 0; }
.card-foot {
  padding: 9px 16px; border-top: 1px solid var(--line);
  font-size: var(--fs-xs); color: var(--ink-mute); display: flex; align-items: center; gap: 8px;
}

/* ---------------------------------------------------------------- KPI */

.kpi { padding: 14px 16px 13px; display: flex; flex-direction: column; gap: 3px; position: relative; }
.kpi-label { font-size: var(--fs-xs); color: var(--ink-mute); font-weight: 550; letter-spacing: .01em; display: flex; align-items: center; gap: 6px; }
.kpi-value { font-size: var(--fs-xl); font-weight: 660; letter-spacing: -.9px; line-height: 1.12; }
.kpi-value.neg { color: var(--neg); }
.kpi-value.pos { color: var(--pos); }
.kpi-value.muted { color: var(--ink-faint); font-size: var(--fs-md); font-weight: 550; letter-spacing: 0; }
.kpi-meta { font-size: var(--fs-xs); color: var(--ink-soft); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.kpi-trace {
  position: absolute; top: 10px; right: 10px;
  opacity: 0; transition: opacity .12s;
  color: var(--ink-faint); border-radius: 4px; padding: 2px;
}
.kpi:hover .kpi-trace, .kpi-trace:focus { opacity: 1; }
.kpi-trace:hover { color: var(--steel); background: var(--info-bg); }

.delta { font-weight: 650; font-size: var(--fs-xs); }
.delta.pos { color: var(--pos); }
.delta.neg { color: var(--neg); }
.delta.muted { color: var(--ink-mute); }

/* ------------------------------------------- caixa disponível p/ compra */

.cash-card {
  background: linear-gradient(158deg, var(--navy) 0%, var(--navy-2) 62%, var(--navy-3) 100%);
  color: #e7eef7;
  border: none;
  border-radius: var(--rad-l);
  box-shadow: var(--sh-2);
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(240px, 340px) minmax(0, 1fr);
}
@media (max-width: 900px) { .cash-card { grid-template-columns: minmax(0, 1fr); } }

.cash-main { padding: 20px 22px; display: flex; flex-direction: column; justify-content: center; gap: 4px; border-right: 1px solid rgba(255,255,255,.09); }
.cash-eyebrow { font-size: var(--fs-micro); letter-spacing: .13em; text-transform: uppercase; color: var(--gold-3); font-weight: 650; }
.cash-value { font-size: var(--fs-3xl); font-weight: 700; letter-spacing: -2px; line-height: 1.02; color: #fff; }
.cash-value .cur { font-size: var(--fs-lg); font-weight: 600; letter-spacing: -.4px; color: #9db1ca; margin-right: 6px; vertical-align: 14%; }
.cash-value.neg { color: #ff9ba4; }
.cash-note { font-size: var(--fs-xs); color: #9db1ca; line-height: 1.5; margin-top: 6px; max-width: 40ch; }

.cash-break { padding: 16px 20px; display: flex; flex-direction: column; gap: 1px; }
.cash-row { display: flex; align-items: center; gap: 10px; padding: 5px 0; font-size: var(--fs-sm); color: #c6d5e6; }
.cash-row .lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cash-row .val { font-variant-numeric: tabular-nums; font-weight: 600; color: #e7eef7; }
.cash-row.is-head { color: #fff; font-weight: 650; border-bottom: 1px solid rgba(255,255,255,.12); padding-bottom: 8px; margin-bottom: 4px; }
.cash-row.total { color: #fff; font-weight: 700; border-top: 1px solid rgba(255,255,255,.16); padding-top: 9px; margin-top: 5px; font-size: var(--fs-md); }
.cash-row .why {
  opacity: 0; color: #7e93ae; transition: opacity .12s; padding: 1px 4px; border-radius: 4px;
}
.cash-row:hover .why { opacity: 1; }
.cash-row .why:hover { color: var(--gold-3); }

/* Duas linhas de proposito: o controle deslizante tem largura minima propria e,
   numa coluna estreita, disputar a mesma linha com o rotulo estourava a caixa. */
.margin-ctrl {
  display: grid; grid-template-columns: 1fr auto; align-items: center;
  column-gap: 10px; row-gap: 6px;
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid rgba(255,255,255,.1);
}
.margin-ctrl label { grid-column: 1 / -1; font-size: var(--fs-xs); color: #9db1ca; }
.margin-ctrl input[type=range] { width: 100%; min-width: 0; accent-color: var(--gold); }
.margin-ctrl output { font-size: var(--fs-sm); font-weight: 700; color: var(--gold-3); min-width: 40px; text-align: right; }


/* -------------------------------------------------------------- badges */

.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-micro); font-weight: 650; letter-spacing: .02em;
  padding: 2px 7px; border-radius: 20px; white-space: nowrap;
  border: 1px solid transparent;
}
.badge.pos     { background: var(--pos-bg);  color: var(--pos);  }
.badge.neg,
.badge.crit    { background: var(--neg-bg);  color: var(--neg);  }
.badge.warn    { background: var(--warn-bg); color: var(--warn); }
.badge.info    { background: var(--info-bg); color: var(--info); }
.badge.neutral { background: var(--paper-3); color: var(--ink-soft); }
.badge.muted   { background: transparent; color: var(--ink-faint); border-color: var(--line); }
.badge.gold    { background: #faf4e4; color: var(--gold-2); }
.badge .dotm { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }

.badge-class { width: 18px; height: 18px; border-radius: 4px; display: inline-grid; place-items: center; font-size: var(--fs-micro); font-weight: 800; }
.badge-class.A { background: var(--pos); color: #fff; }
.badge-class.B { background: var(--gold); color: var(--navy); }
.badge-class.C { background: var(--paper-3); color: var(--ink-soft); }

.src-tag {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-micro); color: var(--ink-faint);
}
.src-tag::before { content: ""; width: 4px; height: 4px; border-radius: 50%; background: currentColor; }

/* -------------------------------------------------------------- tabelas */

.table-wrap { overflow-x: auto; }

/*
 * ---------------------------------------------------------------------------
 * TABELA FORA DE CARTÃO GANHA A SUPERFÍCIE DO CARTÃO — 17/09/2026
 * ---------------------------------------------------------------------------
 *
 * O padrão da casa é `el('div.card', el('div.card-body.flush', DataTable(...)))`
 * — e ele é escrito à mão em cada chamada. Cartões, Inventário da empresa e
 * Resultado declarado nasceram com `children: DataTable({...})` direto, sem o
 * embrulho, e as tabelas dessas três telas ficavam sobre o fundo cinza da
 * página: sem branco, sem borda, sem sombra, ao lado de tabelas iguais que
 * tinham as três coisas.
 *
 * Corrigir as nove chamadas resolveria hoje e voltaria a acontecer na décima —
 * é o mesmo tipo de defeito que já apareceu quatro vezes nesta base por
 * depender de alguém lembrar de uma lista. A regra aqui é estrutural: toda
 * `.table-wrap` que NÃO esteja dentro de um cartão recebe a mesma superfície
 * que teria dentro dele. Quem já embrulha continua igual, e não há caminho
 * para uma tabela nascer sem fundo.
 */
.table-wrap:not(.card *) {
  background: var(--surf);
  border: 1px solid var(--line);
  border-radius: var(--rad);
  box-shadow: var(--sh-1);
  min-width: 0;
}

table.data { font-size: var(--fs-sm); }
table.data th {
  text-align: left; font-weight: 600; font-size: var(--fs-xs);
  color: var(--ink-mute); padding: 8px 12px;
  border-bottom: 1px solid var(--line); white-space: nowrap;
  position: sticky; top: 0; background: var(--surf); z-index: 2;
}
table.data th.r, table.data td.r { text-align: right; }
table.data th.c, table.data td.c { text-align: center; }
table.data td { padding: 8px 12px; border-bottom: 1px solid var(--paper-3); vertical-align: middle; }
table.data tbody tr:hover { background: var(--paper-2); }
table.data tbody tr.clickable { cursor: pointer; }
table.data tbody tr.is-sel { background: var(--info-bg); }
table.data tfoot td { padding: 9px 12px; border-top: 1.5px solid var(--line-2); font-weight: 700; background: var(--paper-2); }
table.data td.strong { font-weight: 650; }
table.data .sub { display: block; font-size: var(--fs-micro); color: var(--ink-mute); margin-top: 1px; }
table.data.compact td, table.data.compact th { padding: 6px 10px; }

.sortable { cursor: pointer; user-select: none; }
.sortable:hover { color: var(--ink); }
.sortable .arrow { opacity: .4; font-size: 9px; margin-left: 3px; }
.sortable.is-sorted .arrow { opacity: 1; color: var(--steel); }

.bar-cell { position: relative; }
.bar-cell .bar { position: absolute; left: 0; top: 3px; bottom: 3px; background: var(--info-bg); border-radius: 2px; z-index: 0; }
.bar-cell .txt { position: relative; z-index: 1; }

/* --------------------------------------------------------------- filtros */

.filterbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: var(--gap-s); }
.field { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 9px; border: 1px solid var(--line); border-radius: var(--rad-s); background: var(--paper); }
.field label { font-size: var(--fs-xs); color: var(--ink-mute); }
.field select, .field input { border: none; outline: none; background: none; font-size: var(--fs-sm); font-weight: 550; max-width: 200px; }

.seg { display: inline-flex; background: var(--paper-3); border-radius: var(--rad-s); padding: 2px; gap: 2px; }
.seg button {
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink-soft);
  padding: 4px 10px; border-radius: 4px; white-space: nowrap;
}
.seg button:hover { color: var(--ink); }
.seg button.is-active { background: var(--surf); color: var(--navy); box-shadow: var(--sh-1); }

.btn {
  display: inline-flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 11px; border-radius: var(--rad-s);
  font-size: var(--fs-sm); font-weight: 600;
  border: 1px solid var(--line); background: var(--paper); color: var(--ink-2);
}
.btn:hover { border-color: var(--line-2); background: var(--paper-2); }
.btn.primary { background: var(--navy); border-color: var(--navy); color: #fff; }
.btn.primary:hover { background: var(--navy-2); }
.btn.ghost { border-color: transparent; background: transparent; color: var(--steel); }
.btn.ghost:hover { background: var(--info-bg); }
.btn.sm { height: 26px; font-size: var(--fs-xs); padding: 0 9px; }

/*
 * BOTAO DESLIGADO PRECISA PARECER DESLIGADO.
 *
 * Sem isto, «Confirmar e gravar 0 linhas» ficava com o mesmo azul-marinho do
 * botao ativo ao lado: o usuario clica, nada acontece, e a conclusao razoavel
 * e que o sistema travou — nao que a acao nao fazia sentido.
 */
.btn:disabled,
.btn[disabled] {
  opacity: .45;
  cursor: not-allowed;
  filter: grayscale(.35);
}

/* O hover nao responde: passar o mouse nao promete o que o clique nao entrega. */
.btn:disabled:hover           { background: var(--paper); border-color: var(--line); }
.btn.primary:disabled:hover   { background: var(--navy);  border-color: var(--navy); }
.btn.ghost:disabled:hover     { background: transparent; }
.btn.danger:disabled:hover    { background: #fff; color: var(--neg); border-color: #eccdd2; }

/* --------------------------------------------------------------- alertas */

.alert {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 12px; border-radius: var(--rad-s);
  border: 1px solid var(--line); background: var(--surf);
  cursor: pointer; transition: border-color .12s, box-shadow .12s;
  text-align: left; width: 100%;
}
.alert:hover { border-color: var(--line-2); box-shadow: var(--sh-1); }
.alert .mark { width: 3px; align-self: stretch; border-radius: 3px; flex: none; }
.alert.crit .mark { background: var(--neg-2); }
.alert.warn .mark { background: var(--gold-2); }
.alert.info .mark { background: var(--steel-2); }
.alert-body { min-width: 0; flex: 1; }
.alert-title { font-size: var(--fs-sm); font-weight: 650; line-height: 1.3; }
.alert-detail { font-size: var(--fs-xs); color: var(--ink-soft); line-height: 1.5; margin-top: 3px; }
.alert-arrow { color: var(--ink-faint); flex: none; margin-top: 2px; }
.alert:hover .alert-arrow { color: var(--steel); }

/* ----------------------------------------------------------- notas/estados */

.note {
  font-size: var(--fs-xs); line-height: 1.55; color: var(--ink-soft);
  background: var(--paper-2); border: 1px solid var(--line);
  border-left: 3px solid var(--line-2);
  border-radius: var(--rad-s); padding: 9px 12px;
}
.note.warn { background: var(--warn-bg); border-color: #ecd9ac; border-left-color: var(--gold-2); color: #6d4a10; }
.note.info { background: var(--info-bg); border-color: #cfe0ef; border-left-color: var(--steel); color: #123d5e; }
.note.crit { background: var(--neg-bg); border-color: #f0c8cd; border-left-color: var(--neg-2); color: #7a1a25; }
.note strong { font-weight: 650; }

.empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; padding: 40px 20px; text-align: center; color: var(--ink-mute);
}
.empty-title { font-size: var(--fs-sm); font-weight: 650; color: var(--ink-soft); }
.empty-desc { font-size: var(--fs-xs); max-width: 46ch; line-height: 1.55; }

.skel { background: linear-gradient(90deg, var(--paper-3) 25%, var(--paper-2) 50%, var(--paper-3) 75%); background-size: 400% 100%; animation: sh 1.3s linear infinite; border-radius: 5px; }
@keyframes sh { from { background-position: 100% 0; } to { background-position: -100% 0; } }

.insufficient {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-xs); color: var(--ink-faint); font-style: italic;
}

/* --------------------------------------------------------------- gavetas */

.scrim { position: fixed; inset: 0; background: rgba(3, 21, 49, .38); z-index: var(--z-drawer); animation: fade .14s; }
@keyframes fade { from { opacity: 0; } }

.drawer {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: min(520px, 94vw);
  background: var(--surf);
  z-index: calc(var(--z-drawer) + 1);
  box-shadow: var(--sh-3);
  display: flex; flex-direction: column;
  animation: slide .18s cubic-bezier(.22, .8, .3, 1);
}
.drawer.wide { width: min(760px, 96vw); }
@keyframes slide { from { transform: translateX(24px); opacity: .4; } }

.drawer-head { padding: 16px 20px 13px; border-bottom: 1px solid var(--line); display: flex; align-items: flex-start; gap: 12px; }
.drawer-eyebrow { font-size: var(--fs-micro); letter-spacing: .11em; text-transform: uppercase; color: var(--ink-mute); font-weight: 650; }
.drawer-title { font-size: var(--fs-lg); font-weight: 660; letter-spacing: -.4px; margin-top: 2px; line-height: 1.2; }
.drawer-close { margin-left: auto; }
.drawer-body { flex: 1; overflow-y: auto; padding: 16px 20px 28px; }

.trace-value { font-size: var(--fs-2xl); font-weight: 680; letter-spacing: -1.2px; line-height: 1.1; }
.trace-value.neg { color: var(--neg); }

.kv { display: grid; grid-template-columns: 128px minmax(0, 1fr); gap: 6px 14px; font-size: var(--fs-sm); }
.kv dt { color: var(--ink-mute); font-size: var(--fs-xs); padding-top: 1px; }
.kv dd { margin: 0; line-height: 1.5; }

.breakdown { border: 1px solid var(--line); border-radius: var(--rad-s); overflow: hidden; }
.breakdown-row { display: flex; align-items: center; gap: 10px; padding: 7px 11px; font-size: var(--fs-sm); border-bottom: 1px solid var(--paper-3); }
.breakdown-row:last-child { border-bottom: none; }
.breakdown-row .lbl { flex: 1; min-width: 0; color: var(--ink-soft); }
.breakdown-row .val { font-variant-numeric: tabular-nums; font-weight: 600; }
.breakdown-row.total { background: var(--paper-2); font-weight: 700; }

/*
 * A LINHA DE COMPOSIÇÃO QUE ABRE — §10 e §11 do Bloco 8B, 08/09/2026.
 *
 * Vira `<button>` de largura cheia, sem parecer um. O que muda no repouso é
 * só o cursor; a moldura aparece no hover e no foco, onde ela informa.
 */
.breakdown-row.is-clicavel {
  width: 100%; text-align: left; font: inherit; cursor: pointer;
  background: transparent; border-left: none; border-right: none; border-top: none;
  transition: background .12s;
}
.breakdown-row.is-clicavel.total { background: var(--paper-2); }
.breakdown-row.is-clicavel:hover { background: var(--paper-3); }
.breakdown-row.is-clicavel:focus-visible { outline: 2px solid var(--steel-2); outline-offset: -2px; }

/* A PARCELA QUE LEVA A OUTRO NÍVEL — KPI → componente → detalhe → origem.
   Ela é um <button>, então desfaz o estilo do navegador e fica idêntica à linha
   de texto ao lado: a diferença entre as duas é a seta, e não uma caixa cinza
   no meio da composição. */
button.breakdown-row {
  width: 100%; text-align: left; background: none; border: none;
  border-bottom: 1px solid var(--paper-3); font: inherit; cursor: pointer;
}
button.breakdown-row:last-child { border-bottom: none; }
button.breakdown-row:hover { background: var(--wash); }
button.breakdown-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.breakdown-seta { display: inline-flex; color: var(--ink-mute); margin-left: 2px; }

/* A TRILHA DE VOLTA. Descer sem caminho de volta é armadilha: quem abre a
   composição de um componente precisa saber de onde veio e poder voltar. */
.trace-trilha {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin-bottom: 14px; font-size: var(--fs-xs);
}
.trace-trilha-passo {
  background: none; border: none; padding: 0; cursor: pointer; font: inherit;
  color: var(--accent); text-decoration: underline; text-underline-offset: 2px;
}
.trace-trilha-passo::after { content: ' ›'; color: var(--ink-mute); text-decoration: none; }
.trace-trilha-atual { color: var(--ink-mute); }

.drawer-section { margin-top: 20px; }
.drawer-section:first-child { margin-top: 0; }
.drawer-section-title { font-size: var(--fs-xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--ink-mute); margin-bottom: 8px; }

/* ------------------------------------------------------------- DRE / cascata */

table.dre td.lbl { white-space: normal; }
table.dre tr.lvl-0 td { font-weight: 650; }
table.dre tr.lvl-1 td.lbl { padding-left: 26px; color: var(--ink-soft); }
table.dre tr.k-subtotal td { background: var(--paper-2); border-top: 1px solid var(--line); }
table.dre tr.k-total td { background: var(--navy); color: #fff; font-weight: 700; border: none; }
table.dre tr.k-total td .pct { color: #9db1ca; }
table.dre td .pct { color: var(--ink-mute); font-size: var(--fs-xs); }
table.dre tr.clickable:hover td { background: var(--info-bg); }
table.dre tr.k-total.clickable:hover td { background: var(--navy-2); }
/* 17/09/2026: detalhe de receita (produtos · serviços), o bloco de margens % e o separador dele. */
table.dre tr.lvl-2 td.lbl { padding-left: 44px; color: var(--ink-mute); font-size: var(--fs-xs); }
table.dre tr.k-detalhe td { font-weight: 400; }
table.dre tr.k-separador td { padding-top: 14px; border-bottom: 1px solid var(--line); text-transform: uppercase; letter-spacing: .04em; }
table.dre tr.k-ratio td { font-weight: 600; background: var(--paper); }

/* --------------------------------------------------------- conciliação */

.recon { display: grid; grid-template-columns: 1fr 34px 1fr; gap: 0; align-items: stretch; }
.recon-col { min-width: 0; }
.recon-col-head { font-size: var(--fs-xs); font-weight: 650; color: var(--ink-mute); padding: 8px 12px; border-bottom: 1px solid var(--line); background: var(--paper-2); }
.recon-pair { display: contents; }
.recon-cell { border-bottom: 1px solid var(--paper-3); padding: 8px 12px; font-size: var(--fs-sm); min-width: 0; }
.recon-link { display: grid; place-items: center; border-bottom: 1px solid var(--paper-3); }
.recon-link .pill { width: 24px; height: 18px; border-radius: 9px; display: grid; place-items: center; font-size: 9px; font-weight: 800; }
.recon-link .pill.CONCILIADO { background: var(--pos-bg); color: var(--pos); }
.recon-link .pill.POSSIVEL { background: var(--warn-bg); color: var(--warn); }
.recon-cell.empty-side { background: repeating-linear-gradient(135deg, var(--paper-2), var(--paper-2) 6px, var(--paper-3) 6px, var(--paper-3) 12px); }

/* ----------------------------------------------------------- misc */

.stack { display: flex; flex-direction: column; gap: var(--gap-s); }
.row { display: flex; align-items: center; gap: var(--gap-s); flex-wrap: wrap; }
.row.tight { gap: 6px; }
.muted { color: var(--ink-mute); }
.faint { color: var(--ink-faint); }
.pos { color: var(--pos); }
.neg { color: var(--neg); }
.tiny { font-size: var(--fs-xs); }
.micro { font-size: var(--fs-micro); }
.right { text-align: right; }
.nowrap { white-space: nowrap; }
.grow { flex: 1; min-width: 0; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: var(--fs-xs); color: var(--ink-soft); }
.legend-item { display: inline-flex; align-items: center; gap: 6px; }
.legend-swatch { width: 10px; height: 3px; border-radius: 2px; }
.legend-swatch.dashed { background: repeating-linear-gradient(90deg, currentColor 0 4px, transparent 4px 7px); height: 3px; }

.company-card { padding: 14px 16px; display: flex; flex-direction: column; gap: 9px; }
.company-id { font-size: var(--fs-micro); color: var(--ink-mute); font-variant-numeric: tabular-nums; }
.company-name { font-size: var(--fs-md); font-weight: 650; letter-spacing: -.2px; }
.company-legal { font-size: var(--fs-xs); color: var(--ink-soft); }
.company-metrics { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 12px; margin-top: 3px; }
.company-metric .l { font-size: var(--fs-micro); color: var(--ink-mute); }
.company-metric .v { font-size: var(--fs-base); font-weight: 650; font-variant-numeric: tabular-nums; }

.state-chip { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-micro); font-weight: 650; padding: 1px 6px; border-radius: 4px; }
.state-chip.REALIZADO { background: var(--paper-3); color: var(--ink-soft); }
.state-chip.PROJETADO { background: var(--info-bg); color: var(--info); }
.state-chip.ESTIMADO, .state-chip.MANUAL { background: var(--warn-bg); color: var(--warn); }
.state-chip.RECONSTRUIDO, .state-chip.IMPORTADO { background: var(--info-bg); color: var(--info); }
.state-chip.VALIDADO { background: var(--pos-bg); color: var(--pos); }
.state-chip.PENDENTE, .state-chip.INDISPONIVEL, .state-chip.PARCIAL { background: var(--neg-bg); color: var(--neg); }
.state-chip.MOCK { background: #f2eafa; color: #5b3a86; }

/* busca global */
.search-wrap { position: relative; }
.search-results {
  position: absolute; top: 38px; right: 0; width: 340px;
  background: var(--surf); border: 1px solid var(--line); border-radius: var(--rad);
  box-shadow: var(--sh-2); max-height: 380px; overflow-y: auto; z-index: 50;
}
.search-results:empty { display: none; }
.search-group {
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-faint); padding: 9px 12px 4px;
}
.search-hit {
  display: flex; flex-direction: column; gap: 1px;
  padding: 6px 12px; font-size: var(--fs-sm); border-left: 2px solid transparent;
}
.search-hit:hover { background: var(--paper-2); border-left-color: var(--gold); }
.search-empty { padding: 14px 12px; font-size: var(--fs-sm); color: var(--ink-mute); }

/* formulários em gaveta */
.form-row { display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-xs); color: var(--ink-mute); }
.form-row select, .form-row input {
  height: 32px; padding: 0 9px; border: 1px solid var(--line); border-radius: var(--rad-s);
  background: var(--paper); font-size: var(--fs-sm); color: var(--ink); outline: none;
}
.form-row select:focus, .form-row input:focus { border-color: var(--steel-2); box-shadow: 0 0 0 3px rgba(46,124,184,.12); }

/* cadeia venda -> caixa */
.chain { display: flex; align-items: stretch; gap: 0; overflow-x: auto; }
.chain-step { display: flex; align-items: center; min-width: 0; }
.chain-node {
  min-width: 190px; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--rad);
  background: var(--paper-2); display: flex; flex-direction: column; gap: 2px;
}
.chain-label { font-size: var(--fs-xs); color: var(--ink-mute); font-weight: 600; }
.chain-value { font-size: var(--fs-lg); font-weight: 660; letter-spacing: -.5px; font-variant-numeric: tabular-nums; }
.chain-value.neg { color: var(--neg); }
.chain-hint { font-size: var(--fs-micro); color: var(--ink-mute); line-height: 1.45; max-width: 26ch; }
.chain-arrow { color: var(--line-2); padding: 0 8px; flex: none; }

/* ============================================================ REVISÃO ==== */

/* Cartões ganham presença: numa página quase branca, um branco sobre branco
   com borda de 4% de contraste simplesmente não aparece. */
.card,
/* A tabela solta segue o cartão também aqui: um branco sobre branco com borda
   de 4% de contraste não aparece nem dentro nem fora de um cartão. */
.table-wrap:not(.card *) {
  border-color: var(--line);
  box-shadow: 0 1px 2px rgba(3, 21, 49, .06), 0 1px 0 rgba(3, 21, 49, .02);
}
.card-head { background: linear-gradient(180deg, #fbfcfe, #fff); border-bottom-color: var(--line); }
.card.kpi { border-top: 2px solid var(--navy-2); }
.card.kpi:hover { box-shadow: var(--sh-2); }

/* Avisos: respiro entre eles e caixa com peso próprio. */
.stack { gap: var(--gap); }
.alert {
  gap: 12px; padding: 13px 14px;
  border-radius: var(--rad);
  border-color: var(--line);
  align-items: stretch;
}
.alert + .alert { margin-top: 0; }
.alert .mark { width: 4px; border-radius: 4px; }
.alert-title { margin-bottom: 2px; }
.alert-detail { line-height: 1.6; }
.alert.crit { background: linear-gradient(90deg, rgba(251,231,233,.6), #fff 42%); }
.alert.warn { background: linear-gradient(90deg, rgba(251,240,220,.6), #fff 42%); }
.alert.info { background: linear-gradient(90deg, rgba(228,238,247,.6), #fff 42%); }
.alert:hover { border-color: var(--line-2); box-shadow: var(--sh-2); transform: translateY(-1px); }
.alert { transition: border-color .12s, box-shadow .12s, transform .12s; }

/* Ações de linha e botões destrutivos. */
.row-actions { display: inline-flex; gap: 2px; opacity: 0; transition: opacity .12s; }
tr:hover .row-actions, tr:focus-within .row-actions { opacity: 1; }
.icon-btn.sm { width: 26px; height: 26px; }
.icon-btn.danger:hover { background: var(--neg-bg); color: var(--neg); }
.btn.danger { color: var(--neg); border-color: #eccdd2; background: #fff; }
.btn.danger:hover { background: var(--neg); border-color: var(--neg); color: #fff; }

/* Formulário de registro. */
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.form-row { grid-column: span 2; }
.form-row.half { grid-column: span 1; }
.form-row > span { display: flex; align-items: center; gap: 3px; font-weight: 600; }
.form-row .req { color: var(--neg); font-style: normal; }
.form-row textarea {
  padding: 7px 9px; border: 1px solid var(--line); border-radius: var(--rad-s);
  font-size: var(--fs-sm); resize: vertical; outline: none;
}
.form-hint { font-size: var(--fs-micro); color: var(--ink-faint); font-weight: 400; line-height: 1.45; }
.form-actions { display: flex; gap: 8px; align-items: center; margin-top: 4px; }

/* O erro do backend, no campo que ele nomeou. Vazio nao ocupa espaco. */
.form-hint.erro { color: var(--neg); font-weight: 600; }
.form-hint.escolhido { color: var(--ink); font-weight: 600; }
.form-hint.erro:empty { display: none; }
.form-actions .btn.danger { margin-left: auto; }
.form-errors:empty { display: none; }

/* Indicador de alterações da sessão. */
.change-chip {
  display: inline-flex; align-items: center; gap: 6px;
  /* 32px, e nao 30: a linha do cabecalho tem uma altura so. */
  height: 32px; padding: 0 10px; border-radius: 20px;
  background: #faf4e4; color: var(--gold-2);
  border: 1px solid #ecdcb2;
  font-size: var(--fs-xs); font-weight: 650; white-space: nowrap;
}
.change-chip:hover { background: #f5ecd6; }

/* Página com ação principal no cabeçalho. */
.page-head-actions .btn.primary { height: 34px; padding: 0 14px; }

/* Nota de contexto colapsável: uma linha na superfície, detalhe sob demanda. */
.note { padding: 10px 13px; line-height: 1.6; }
.note.is-collapsible { padding: 9px 13px; }
.note-head { display: flex; align-items: baseline; gap: 10px; }
/*
 * O BOTÃO DA NOTA FALA A MESMA LÍNGUA DO «?» DAS COLUNAS — 08/09/2026.
 *
 * Ele era um rótulo de texto («POR QUÊ» / «OCULTAR») numa caixa retangular.
 * Passou a ser o mesmo círculo do marcador de ajuda das tabelas, para que «tem
 * explicação aqui» tenha UMA forma no painel inteiro, e não duas.
 *
 * O cursor é `pointer` e não `help`: este abre um bloco na própria página,
 * enquanto o das colunas abre um popover. A diferença é pequena e é real.
 */
.note-toggle {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; padding: 0;
  border: 1px solid var(--line-2); border-radius: 50%;
  background: transparent; color: var(--ink-mute);
  font-size: 10px; font-weight: 700; line-height: 1;
  cursor: pointer; opacity: .6;
  transition: opacity .12s, color .12s, border-color .12s, background .12s;
}
.note-toggle:hover,
.note-toggle:focus-visible { opacity: 1; color: var(--steel); border-color: var(--steel-3); outline: none; }
.note.is-open .note-toggle { opacity: 1; color: var(--steel); border-color: var(--steel-3); }
.note.warn .note-toggle { color: var(--gold-2); }
.note.warn .note-toggle:hover { background: rgba(168, 139, 76, .12); }
.note.crit .note-toggle { color: var(--neg); }
.note.crit .note-toggle:hover { background: rgba(148, 35, 47, .09); }
.note-more { display: none; margin-top: 8px; padding-top: 8px; border-top: 1px dashed currentColor; opacity: .95; }
.note.is-open .note-more { display: block; }

/* ================================================= RESPIRO E HIERARQUIA ==== */

/*
 * ─────────────────────────────────────────────────────────────────────────────
 * A SEÇÃO PASSOU A DISTRIBUIR O PRÓPRIO ESPAÇO — 17/09/2026.
 * ─────────────────────────────────────────────────────────────────────────────
 *
 * Havia aqui duas listas de pares de vizinhos, escritas em 12 e 13/09, cada uma
 * resolvendo a combinação que alguém tinha visto colada: `.card + .card`,
 * `.grid + .card`, `.grid + .grid`, `.card + .grid`… Oito seletores.
 *
 * É o mesmo defeito que a página teve até 04/09, e ele reapareceu um nível
 * abaixo: **o problema dessa forma não é o que ela cobre, é o que ela não
 * cobre**. `.grid + .table-wrap` não estava lá — e uma tabela não vem embrulhada
 * em `.card`. Resultado medido na tela nova de Cartões: os três KPIs terminavam
 * em y=436 e a tabela começava em y=436. Vão de ZERO, exatamente o que o
 * comentário de 13/09 dizia ter curado; ele curou o par, não a relação.
 *
 * A cura é a mesma que a página recebeu: quem espaça é o CONTÊINER. A seção
 * vira coluna com `gap`, as margens dos filhos morrem no primeiro nível dela, e
 * a folga entre QUALQUER par de blocos passa a ser a mesma sem que ninguém
 * precise prevê-la. Combinação nova nasce espaçada.
 *
 * Três exceções, cada uma com um significado — e nenhuma delas é um par
 * avulso, são relações estruturais:
 *
 *   cabeçalho → primeiro bloco   10px   o bloco PERTENCE ao título
 *   nota → nota                  10px   continuação da mesma explicação
 *   seção → subseção             24px   afastamento declara subordinação
 *
 * Elas se escrevem descontando do `gap` (como `.page > .page-head + *` já fazia
 * desde 04/09) em vez de somar por cima dele — somar é o que produziu 40px na
 * primeira tentativa daquela vez.
 *
 * AS REGRAS MORAM JUNTO COM AS DA PÁGINA, no fim deste arquivo: são a mesma
 * ideia em dois níveis, e lá elas vêm DEPOIS de `.note`, que traz margem
 * própria com a mesma especificidade (0,1,0). Declaradas aqui, a zeragem
 * perdia o empate por ordem de arquivo e a nota somava a margem dela ao gap do
 * contêiner — medido na tela de Cartões: 32px onde o ritmo pede 16.
 */

/* Nota de contexto nunca encosta no que vem antes nem no que vem depois. */
.note { margin: var(--gap) 0 0; }

/*
 * NENHUMA TARJA FIXA NO CORPO DAS TELAS — 17/09/2026, pedido do gestor:
 * «não quero esse tipo de mensagem fixa no sistema; se for para atribuir,
 * coloca nos Avisos». Nota no corpo de uma página não aparece; o que pede ação
 * está em Avisos, o porquê está no «?» de cada tela e cartão, e dentro das
 * gavetas — que se abrem sob demanda — a explicação continua visível.
 */
.page .note { display: none; }
.note:first-child { margin-top: 0; }

/*
 * NO PRIMEIRO NÍVEL DA PÁGINA, A NOTA NÃO SE ESPAÇA — 04/09/2026.
 *
 * Esta regra dava `margin-top: 16px` à nota, e fazia sentido quando cada bloco
 * cuidava do próprio afastamento. Desde que `.page` virou coluna com `gap`, ela
 * SOMA: a folga antes de uma nota ficava 40px contra 24px em toda parte, e o
 * ritmo voltava a depender da ordem dos blocos.
 *
 * Some no primeiro nível, e continua valendo dentro de cartão e de seção, onde
 * ninguém distribui espaço por ela.
 */
.page > .note { margin-top: 0; }
.page > .note + .note { margin-top: calc(var(--gap-s) - var(--gap-l)); }

.card-body > .note:first-child { margin-top: 0; }

/*
 * ─────────────────────────────────────────────────────────────────────────────
 * A LISTA DE PARES DE VIZINHOS FOI REMOVIDA — 04/09/2026.
 * ─────────────────────────────────────────────────────────────────────────────
 *
 * Havia aqui oito seletores enumerando combinações: `.grid + .note`,
 * `.note + .grid`, `.card + .note`, `.cash-card + .section`… Cada um resolvia
 * um par que alguém tinha visto colado.
 *
 * O problema dessa forma não é o que ela cobre — é o que ela NÃO cobre. Uma
 * combinação nova nasce a cada tela, ninguém lembra de acrescentá-la, e o
 * resultado medido em 1440px era este:
 *
 *     16, 16, 24, 24, 24, 16, 16, 24, 16    (Estoque)
 *     16, 16, 0, 16, 10, 16, 24, 24, 16     (Preço e Mercado — dois blocos colados)
 *
 * Agora `.page` é coluna com `gap`, e o espaço entre QUALQUER par de blocos é
 * o mesmo sem que ninguém precise prevê-lo. As regras abaixo, que somavam por
 * cima do gap, saíram junto: manter as duas formas ao mesmo tempo dobrava o
 * afastamento onde as duas se aplicavam.
 */

.page-head + .cash-card { margin-top: 0; }

/* ================================================ MÊS EM CURSO (PARCIAL) === */

.partial-panel {
  border: 1px solid var(--line);
  border-radius: var(--rad-l);
  background: var(--surf);
  box-shadow: var(--sh-1);
  overflow: hidden;
  margin-top: var(--gap);
}
.partial-head {
  display: flex; align-items: center; gap: var(--gap);
  padding: 13px 18px;
  background: linear-gradient(180deg, #fbfcfe, #fff);
  border-bottom: 1px solid var(--line);
}
.partial-title { font-size: var(--fs-md); font-weight: 650; letter-spacing: -.2px; }
.partial-sub { font-size: var(--fs-xs); color: var(--ink-mute); margin-top: 2px; }
.partial-progress { margin-left: auto; display: flex; align-items: center; gap: 9px; min-width: 190px; }
.partial-bar { flex: 1; height: 7px; border-radius: 4px; background: var(--paper-3); overflow: hidden; }
.partial-fill { height: 100%; border-radius: 4px; background: linear-gradient(90deg, var(--gold-3), var(--gold-2)); }

.partial-body { display: grid; grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) { .partial-body { grid-template-columns: 1fr; } }
.partial-col { padding: 14px 18px 16px; }
.partial-col + .partial-col { border-left: 1px solid var(--line); }
@media (max-width: 900px) { .partial-col + .partial-col { border-left: none; border-top: 1px solid var(--line); } }
.partial-col.is-outlook { background: repeating-linear-gradient(135deg, transparent, transparent 9px, rgba(107,163,208,.05) 9px, rgba(107,163,208,.05) 18px); }
.partial-col-head {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--ink-mute);
}
.partial-row { display: flex; align-items: baseline; gap: 10px; padding: 5px 0; font-size: var(--fs-sm); }
.partial-row .lbl { flex: 1; color: var(--ink-soft); min-width: 0; }
.partial-row .val { font-variant-numeric: tabular-nums; font-weight: 600; }
.partial-row.is-strong { font-weight: 650; color: var(--ink); border-top: 1px solid var(--paper-3); padding-top: 7px; }
.partial-row.is-strong .lbl { color: var(--ink); }
.partial-row.is-total {
  margin-top: 6px; padding: 8px 10px; border-radius: var(--rad-s);
  background: var(--navy); color: #fff; font-weight: 700;
}
.partial-row.is-total .lbl { color: #fff; }
.partial-row.is-total .val.neg { color: #ff9ba4; }
.partial-metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin-top: 12px; padding-top: 11px; border-top: 1px dashed var(--line); }
.partial-metric .l { font-size: var(--fs-micro); color: var(--ink-mute); }
.partial-metric .v { font-size: var(--fs-base); font-weight: 650; font-variant-numeric: tabular-nums; }
.partial-foot {
  padding: 10px 18px; border-top: 1px solid var(--line);
  background: var(--paper-2); font-size: var(--fs-xs); color: var(--ink-soft); line-height: 1.6;
}

.page-title { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.page-title .badge { font-size: var(--fs-xs); padding: 3px 9px; }

.row-actions.is-static { opacity: .35; }
.company-card:hover .row-actions.is-static { opacity: 1; }
.company-card.is-idle { background: repeating-linear-gradient(135deg, #fff, #fff 10px, var(--paper-2) 10px, var(--paper-2) 20px); }
.company-card.is-idle .company-name { color: var(--ink-soft); }

.partial-range {
  margin-top: 8px; padding: 8px 10px; border-radius: var(--rad-s);
  background: var(--warn-bg); border: 1px solid #ecd9ac;
}
.partial-range .l { display: block; font-size: var(--fs-micro); color: var(--warn); font-weight: 650; }
.partial-range .v { display: block; font-size: var(--fs-sm); font-weight: 700; color: #6d4a10; margin-top: 2px; }
.partial-scenarios { display: flex; flex-direction: column; gap: 1px; margin-top: 5px; }

/* ============================================ CADEIA VENDA -> CAIXA ======= */

/* Escada proporcional. Cada elo declara quanto do faturamento ainda sobra ali,
   e o degrau entre dois elos so afirma diferenca quando ela existe de fato. */
.ladder { display: flex; flex-direction: column; }
.ladder-row { padding: 2px 0; }
.ladder-head { display: flex; align-items: baseline; gap: 10px; }
.ladder-label {
  display: flex; align-items: center; gap: 7px;
  font-size: var(--fs-sm); font-weight: 620; color: var(--ink);
}
.ladder-kind {
  font-size: var(--fs-micro); font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; padding: 1px 6px; border-radius: 4px;
  border: 1px solid transparent; cursor: help;
}
.ladder-kind.is-flow  { color: var(--steel); background: var(--info-bg); border-color: #cfe0ef; }
.ladder-kind.is-stock { color: #6d4a10; background: var(--warn-bg); border-color: #ecd9ac; }
.ladder-value {
  margin-left: auto; font-size: var(--fs-lg); font-weight: 660;
  letter-spacing: -.5px; font-variant-numeric: tabular-nums;
}
.ladder-value.neg { color: var(--neg); }

.ladder-track {
  position: relative; height: 26px; margin-top: 7px;
  background: var(--paper-3); border-radius: var(--rad-s); overflow: hidden;
}
.ladder-fill {
  height: 100%; border-radius: var(--rad-s);
  background: linear-gradient(90deg, #2e7cb8, #0f3460);
  transition: width .25s ease;
}
.ladder-fill.is-receivable { background: linear-gradient(90deg, #d9b96a, #a88b4c); }
.ladder-fill.is-payout     { background: linear-gradient(90deg, #4f9d7a, #1f6b4d); }
.ladder-fill.is-cash       { background: linear-gradient(90deg, #123d5e, #031531); }
.ladder-share {
  position: absolute; top: 0; right: 10px; height: 26px;
  display: flex; align-items: center;
  font-size: var(--fs-micro); font-weight: 650; color: var(--ink-mute);
}

.ladder-foot {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 7px; font-size: var(--fs-micro); color: var(--ink-mute);
}
.ladder-hint { line-height: 1.5; max-width: 62ch; }
.ladder-foot .btn.sm { margin-left: auto; }

.ladder-gap {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 10px 0 12px; padding: 8px 11px;
  border-left: 2px solid var(--line-2);
  font-size: var(--fs-micro); color: var(--ink-soft); line-height: 1.55;
}
.ladder-gap-mark { color: var(--line-2); flex: none; display: flex; }
.ladder-gap strong { color: var(--ink); font-weight: 660; font-variant-numeric: tabular-nums; }
.ladder-gap-note { color: var(--ink-mute); }

@media (max-width: 680px) {
  .ladder-head { flex-wrap: wrap; }
  .ladder-value { margin-left: 0; }
  .ladder-foot .btn.sm { margin-left: 0; }
}
.ladder-share.is-muted { font-weight: 500; color: var(--ink-faint); font-style: italic; }

/* Resultado projetado como faixa: quando duas bases legitimas discordam, a
   faixa e a linha principal e o valor central perde o destaque. */
.partial-range-block { margin-top: 6px; }
.partial-row.is-total.is-range .val { font-size: var(--fs-sm); letter-spacing: -.2px; }
.partial-range-note {
  margin-top: 7px; padding: 8px 10px; border-radius: var(--rad-s);
  background: var(--warn-bg); border: 1px solid #ecd9ac;
  font-size: var(--fs-micro); color: #6d4a10; line-height: 1.55;
}
.partial-range-block .partial-scenarios { gap: 3px; margin-top: 8px; }
.partial-scenario {
  display: flex; align-items: baseline; gap: 10px;
  font-size: var(--fs-micro); color: var(--ink-mute);
}
.partial-scenario .l { flex: 1; min-width: 0; }
.partial-scenario .v { font-weight: 650; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.partial-scenario .v.neg { color: var(--neg); }

/* O painel do mes em curso nunca encosta no bloco seguinte. */
.page > .partial-panel + .grid,
.page > .partial-panel + .section,
.page > .partial-panel + .note,
.page > .partial-panel + .card { margin-top: var(--gap); }
.partial-basis {
  margin-bottom: 9px; padding-bottom: 8px;
  border-bottom: 1px dashed var(--line);
  font-size: var(--fs-micro); color: var(--ink-mute); line-height: 1.5;
}

/* O estado vazio e um bloco de pagina como outro qualquer: entra no mesmo
   ritmo vertical em vez de encostar no aviso que o antecede. */
.page > .empty { margin-top: var(--gap); }
.page > .page-head + .empty { margin-top: 0; }
.page > .note + .empty,
.page > .empty + .note,
.page > .empty + .section,
.page > .empty + .grid { margin-top: var(--gap); }
.company-idle-note {
  margin-top: 8px; padding: 8px 10px; border-radius: var(--rad-s);
  background: var(--paper-2); border: 1px dashed var(--line);
  font-size: var(--fs-micro); color: var(--ink-mute); line-height: 1.55;
}

/* ---------------------------------------------------------------- login
   A tela de entrada. E a UNICA que aparece antes de haver sessao, entao nao
   pode depender de nada que o boot carrega depois. */

.login-tela {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--navy);
}

.login-caixa {
  width: 100%;
  max-width: 380px;
  padding: 34px 30px;
  border-radius: 14px;
  background: var(--paper);
  border: 1px solid var(--line);
  box-shadow: 0 18px 48px rgba(3, 21, 49, 0.32);
  text-align: center;
}

.login-marca { width: 54px; height: auto; margin-bottom: 14px; }

.login-caixa h1 {
  margin: 0;
  font-size: 20px;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.login-sub {
  margin: 4px 0 24px;
  font-size: 13px;
  color: var(--ink-mute);
}

.login-form { display: flex; flex-direction: column; gap: 14px; text-align: left; }

.login-form label { display: flex; flex-direction: column; gap: 6px; }

.login-form label span {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-mute);
}

.login-form input {
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--ink);
  font-size: 14px;
  font-family: inherit;
}

.login-form input:focus {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold);
}

.login-form button { margin-top: 6px; padding: 11px; font-size: 14px; width: 100%; }
.login-form button[disabled] { opacity: 0.6; cursor: progress; }

.login-erro {
  padding: 9px 11px;
  border-radius: 8px;
  background: rgba(148, 35, 47, 0.08);
  border: 1px solid rgba(148, 35, 47, 0.35);
  color: var(--neg);
  font-size: 13px;
  line-height: 1.4;
}

.login-rodape {
  margin: 22px 0 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--ink-mute);
}

/* ------------------------------------------------------- aviso de origem
   Aparece quando alguma colecao NAO veio do banco. Fica na casca, nao nas
   telas: 22 telas nao podem cada uma lembrar de avisar. */

.avisos { display: flex; flex-direction: column; gap: 8px; margin: 0 0 16px; }

.aviso-origem {
  padding: 10px 13px;
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.45;
  background: rgba(193, 165, 97, 0.10);
  border: 1px solid rgba(193, 165, 97, 0.45);
  color: var(--ink);
}

.aviso-origem.grave {
  background: rgba(148, 35, 47, 0.08);
  border-color: rgba(148, 35, 47, 0.40);
  color: var(--neg);
  font-weight: 500;
}

.aviso-origem.leve {
  background: rgba(122, 140, 163, 0.08);
  border-color: rgba(122, 140, 163, 0.35);
  color: var(--ink-mute);
}


/* ------------------------------------------------------------- Registrar --
   Cartoes de acao da tela de eventos. Cada um abre um formulario que GRAVA;
   por isso sao botoes de verdade, e nao divs clicaveis — teclado e leitor de
   tela precisam alcanca-los.                                               */

.acoes-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); gap: 12px; }

.acao-card {
  display: flex; flex-direction: column; gap: 5px; align-items: flex-start;
  text-align: left; padding: 15px 16px; border-radius: var(--rad-l);
  border: 1px solid var(--line); background: var(--paper); cursor: pointer;
  transition: border-color .12s, box-shadow .12s, transform .12s;
}
.acao-card:hover:not(:disabled) {
  border-color: var(--steel-2); box-shadow: 0 2px 10px rgba(3, 21, 49, .07); transform: translateY(-1px);
}
.acao-card:focus-visible { outline: 2px solid var(--steel-2); outline-offset: 2px; }
.acao-card:disabled { opacity: .55; cursor: progress; }

.acao-titulo { font-size: var(--fs-sm); font-weight: 660; color: var(--ink); letter-spacing: -.2px; }
.acao-desc   { font-size: var(--fs-xs); color: var(--ink-mute); line-height: 1.5; }

.lista-simples { margin: 0; padding-left: 18px; font-size: var(--fs-sm); line-height: 1.9; }

/* ===========================================================================
   DRE DE TRÊS COLUNAS — o mês em curso

   Realizado, projetado e fechamento na mesma régua. A coluna do meio é a
   DIFERENÇA entre as outras duas, calculada no backend: é o que ainda vem.

   A hierarquia visual é deliberada. O fechamento é a coluna que responde "como
   agosto vai fechar", e por isso tem fundo próprio; o realizado é fato e fica
   em tinta cheia; o projetado é estimativa e fica em itálico apagado — a mesma
   convenção do tracejado nos gráficos.
   =========================================================================== */
.dre-parcial .card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); padding: var(--sp-4) var(--sp-4) var(--sp-3); }
.dre-parcial .card-head h3 { font-size: var(--fs-md); font-weight: 650; color: var(--ink); }
.dre-parcial .card-head .sub { font-size: var(--fs-xs); color: var(--ink-mute); margin-top: 2px; }

/* A divisão entre o que aconteceu e o que ainda vai acontecer. A posição vem
   da cobertura do backend — quando a carga de amanhã chegar, ela anda. */
.cobertura { padding: 0 var(--sp-4) var(--sp-3); }
.cobertura-trilho { position: relative; height: 6px; border-radius: 3px; background: var(--paper-3); overflow: visible; }
.cobertura-feito { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; background: linear-gradient(90deg, var(--steel), var(--steel-2)); }
.cobertura-divisor { position: absolute; top: -4px; bottom: -4px; width: 2px; background: var(--gold); border-radius: 1px; }
.cobertura-legenda { display: flex; justify-content: space-between; margin-top: var(--sp-2); font-size: var(--fs-micro); color: var(--ink-mute); }
.cobertura-legenda .dir { font-style: italic; }

.dre-3col { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }
.dre-3col th, .dre-3col td { padding: var(--sp-2) var(--sp-4); }
.dre-3col thead th { font-size: var(--fs-xs); font-weight: 600; color: var(--ink-mute); border-bottom: 1px solid var(--line); text-align: left; vertical-align: bottom; }
.dre-3col thead th.r { text-align: right; }
.dre-3col thead th .sub { display: block; font-size: var(--fs-micro); font-weight: 500; color: var(--ink-faint); margin-top: 1px; }
.dre-3col td.r, .dre-3col th.r { text-align: right; }
.dre-3col tbody th { text-align: left; font-weight: 500; color: var(--ink-2); }
.dre-3col tbody th .hint { margin-left: 5px; cursor: help; }
.dre-3col tbody tr.n1 th { padding-left: var(--sp-6); color: var(--ink-soft); }
.dre-3col tbody tr.t-subtotal th, .dre-3col tbody tr.t-subtotal td { font-weight: 650; border-top: 1px solid var(--paper-3); }
.dre-3col tbody tr.t-total th, .dre-3col tbody tr.t-total td { font-weight: 700; border-top: 1.5px solid var(--line-2); font-size: var(--fs-base); }
.dre-3col td.num { font-variant-numeric: tabular-nums; }
.dre-3col td.neg { color: var(--neg); }
.dre-3col td.vazio { color: var(--ink-faint); }

/* TELA ESTREITA — o que transbordava a 390 px (validação visual de 11/09/2026).
   As duas demonstrações não cabem em 358 px (476 e 443) e empurravam a página
   inteira para o lado; rolam dentro do cartão, como toda tabela do painel. O
   rodapé do cartão quebra a linha: com as etiquetas de fonte ocupando tudo, o
   texto ao lado ficava com 0 px e vazava por cima da borda. */
@media (max-width: 680px) {
  .dre-parcial > .card-body.flush,
  .card-body.flush:has(> table.data.dre) { overflow-x: auto; }
  .card-foot { flex-wrap: wrap; }
  .card-foot > .grow:not(:empty) { flex-basis: 100%; }
}

/* Projetado em itálico apagado: a mesma convenção do tracejado nos gráficos —
   um número estimado nunca usa a mesma tinta de um número medido. */
.dre-3col td.is-proj { color: var(--ink-mute); font-style: italic; }

/* O fechamento é a coluna que responde "como o mês vai fechar". */
.dre-3col .is-close { background: var(--surf-sunk); }
.dre-3col thead th.is-close { color: var(--navy-2); font-weight: 700; }
.dre-3col tbody td.is-close { color: var(--ink); font-weight: 600; }
.dre-3col tfoot th, .dre-3col tfoot td { border-top: 1px solid var(--line); font-size: var(--fs-xs); color: var(--ink-soft); padding-top: var(--sp-3); padding-bottom: var(--sp-3); }


/* O aviso de coleções em demonstração é verdadeiro e não é manchete. Ele
   ocupava o topo do dashboard com um parágrafo cinza de duas linhas, ANTES de
   qualquer número — e a primeira dobra pertence à resposta, não à ressalva
   sobre a resposta. Uma linha, tipografia menor, sem caixa pesada. */
.aviso-origem.is-compacto {
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-xs);
  line-height: 1.45;
  background: transparent;
  border: none;
  border-left: 2px solid var(--line-2);
  color: var(--ink-mute);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A venda direta fica FORA da cascata, e visivelmente fora: ela é medida por
   PEDIDO, e a cascata acima é medida pelo relatório transacional. Uma linha
   dentro do corpo da tabela seria lida como parcela do total — e não é. */
.dre-3col tbody.fora-da-cascata { border-top: 2px solid var(--line-2); }
.dre-3col tr.t-extra th { font-weight: 600; color: var(--ink-2); padding-top: var(--sp-3); }
.dre-3col tr.t-extra th .sub { display: block; font-size: var(--fs-micro); font-weight: 500; color: var(--ink-faint); margin-top: 2px; }
.dre-3col tr.t-extra td { padding-top: var(--sp-3); }

/* O KPI INTEIRO É O ALVO DE CLIQUE.

   Havia um ícone de 15px que só aparecia no hover: não existia para toque nem
   para teclado, e ensinava que o número é um beco sem saída. Agora o cartão é
   um `<button>` — foco, Enter e leitor de tela vêm junto de graça. */
.card.kpi.is-clicavel {
  width: 100%;
  text-align: left;
  font: inherit;
  cursor: pointer;
  border: 1px solid var(--line);
  border-top: 2px solid var(--navy-2);
  transition: box-shadow .12s, border-color .12s, transform .12s;
}
.card.kpi.is-clicavel:hover { box-shadow: var(--sh-2); border-color: var(--line-2); }
.card.kpi.is-clicavel:active { transform: translateY(1px); }
.card.kpi.is-clicavel:focus-visible { outline: 2px solid var(--steel-2); outline-offset: 2px; }

/*
 * O CARD QUE ESTÁ FILTRANDO precisa se distinguir dos irmãos — 03/09/2026.
 *
 * Na Curva ABC os três cards de concentração filtram a tabela acima. Sem marca
 * visível, quem clicasse em «A» veria a tabela encolher sem saber por quê, e
 * iria procurar o filtro em outro lugar da tela. A borda acesa é a mesma
 * linguagem que o card clicável já usa, só que ligada.
 */
.card.kpi.is-clicavel.is-ativa {
  border-color: var(--steel-2);
  border-top-color: var(--steel-2);
  box-shadow: var(--sh-2);
}

.kpi-seta {
  position: absolute; top: 12px; right: 12px;
  color: var(--ink-faint);
  opacity: 0; transition: opacity .12s, transform .12s;
}
.card.kpi.is-clicavel:hover .kpi-seta,
.card.kpi.is-clicavel:focus-visible .kpi-seta { opacity: 1; transform: translateX(2px); }

/* No mobile a gaveta ocupa a tela: 520px numa tela de 375 deixaria o conteúdo
   espremido contra a borda. */
@media (max-width: 680px) {
  .drawer, .drawer.wide { width: 100vw; }
  .kpi-seta { opacity: .5; }
}


/* A linha da DRE e um alvo de clique: ela abre a composicao na gaveta. */
.dre-3col tbody tr.is-clicavel { cursor: pointer; }
.dre-3col tbody tr.is-clicavel:hover { background: var(--paper-2); }
.dre-3col tbody tr.is-clicavel:focus-visible { outline: 2px solid var(--steel-2); outline-offset: -2px; }
.dre-3col tbody tr.is-clicavel:hover .is-close { background: var(--paper-3); }


/* Escolha multipla como caixas, e nao `select multiple`: este ultimo exige
   Ctrl+clique para marcar mais de um, e quem nao sabe disso apaga o anterior
   sem perceber. Num campo que define quais empresas a pessoa enxerga, apagar
   sem perceber e caro. */
.check-grid { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-4); padding: var(--sp-2) 0; }
.check-item { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); cursor: pointer; }
.check-item input { margin: 0; }

/* CAMADAS DO RECEBÍVEL — vendido, liberado, a receber, projetado, cancelado.

   Cinco caixas lado a lado, cada uma com o próprio selo de estado. O selo NÃO
   é decoração: é o que separa «R$ 13.355,96 projetado pela mediana» de
   «R$ 305.124,17 liberado», e sem ele os dois números pareceriam a mesma
   afirmação. */
/* ---------------------------------------------------------------------------
   O CARTÃO DE EMPRESA QUE ABRE — 14/09/2026.

   Os cartões de regime e alíquota por estabelecimento abrem o detalhe, a
   edição e a exclusão. O cartão inteiro é o alvo, e ele precisa DIZER que é:
   cursor de mão, borda que acende no hover e foco visível pelo teclado.

   (As linhas tracejadas de matriz e filial dentro do cartão da PJ, de
   13/09/2026, saíram junto com aquele cartão: cada unidade tem o seu agora.)
--------------------------------------------------------------------------- */
.company-card.is-clicavel { cursor: pointer; transition: border-color .12s, box-shadow .12s; }
.company-card.is-clicavel:hover { border-color: var(--line-2); box-shadow: var(--sh-2); }
.company-card.is-clicavel:focus-visible { outline: 2px solid var(--steel-2); outline-offset: 2px; }

.camadas {
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
}
.camada {
  display: flex; flex-direction: column; gap: 4px;
  padding: var(--sp-3); border: 1px solid var(--line); border-radius: 5px;
  background: var(--paper-2);
}
/*
 * A CAMADA QUE ABRE — §8 e §12 do Bloco 8B, 08/09/2026.
 *
 * Ela vira `<button>` quando tem detalhe. O invólucro existe só para pendurar
 * o «?» como irmão, e não como filho do botão.
 */
.camada-wrap { position: relative; display: flex; }
.camada-wrap > .camada { flex: 1; min-width: 0; }

.camada-wrap > .col-ajuda {
  position: absolute; top: 8px; right: 8px;
  margin-left: 0; z-index: 1; background: var(--paper-2);
}

.camada.is-clicavel {
  width: 100%; text-align: left; font: inherit; cursor: pointer;
  transition: border-color .12s, box-shadow .12s, transform .12s;
}
.camada.is-clicavel:hover { border-color: var(--line-2); box-shadow: var(--sh-1); }
.camada.is-clicavel:active { transform: translateY(1px); }
.camada.is-clicavel:focus-visible { outline: 2px solid var(--steel-2); outline-offset: 2px; }

/* O «?» fica no canto: o rótulo precisa do espaço dele de volta. */
.camada-wrap > .camada .camada-label { padding-right: 20px; }

.camada-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); }
.camada-label { font-size: var(--fs-xs); font-weight: 620; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .02em; }
.camada-valor { font-size: var(--fs-lg); font-weight: 680; color: var(--ink); font-variant-numeric: tabular-nums; }
.camada-valor.neg { color: var(--neg); }

.camada-total {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3); margin-top: var(--sp-2);
  border-top: 2px solid var(--paper-3);
}
.camada-total .lbl { flex: 1; font-weight: 620; color: var(--ink); }
.camada-total .val { font-size: var(--fs-lg); font-weight: 700; font-variant-numeric: tabular-nums; }

/* NÃO MEDIDO não é um estado vazio: é uma resposta, e ocupa o mesmo espaço que
   a resposta teria. Um espaço em branco convidaria a supor zero. */
.naomedido {
  padding: var(--sp-4); border: 1px dashed var(--line-2); border-radius: 5px;
  display: flex; flex-direction: column; gap: var(--sp-2);
}
.naomedido-head { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-md); }
.naomedido p { margin: 0; }

/* ------------------------------------------------------------- dicionário
 *
 * O marcador de ajuda no cabeçalho da tabela e o pop-up que ele abre.
 *
 * O marcador é discreto de propósito: ele existe para quem procura, e não pode
 * competir com o número. Ganha contorno só no hover e no foco — a tela
 * continua limpa enquanto ninguém pergunta.
 */

.col-ajuda {
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; margin-left: 5px; padding: 0;
  border: 1px solid var(--line-2); border-radius: 50%;
  background: transparent; color: var(--ink-mute);
  font-size: 10px; font-weight: 700; line-height: 1;
  cursor: help; vertical-align: middle;
  opacity: .55; transition: opacity .12s, color .12s, border-color .12s;
}

.col-ajuda:hover,
.col-ajuda:focus-visible { opacity: 1; color: var(--steel); border-color: var(--steel-3); outline: none; }

/*
 * O «?» DE UM CARTÃO DE KPI — 08/09/2026.
 *
 * Ele é IRMÃO do cartão, e não filho: dentro do botão seria botão aninhado,
 * inválido em HTML e anunciado como alvo único por leitor de tela. O invólucro
 * existe só para posicioná-lo, e por isso não desenha nada.
 *
 * `align-self: stretch` mantém o cartão com a altura dos irmãos dentro da
 * grade: sem isso, um cartão com «?» encolheria para o conteúdo e quebraria a
 * linha de base da fileira.
 */
.kpi-wrap { position: relative; display: flex; align-self: stretch; min-width: 0; }
.kpi-wrap > .card.kpi { flex: 1; min-width: 0; }

.kpi-wrap > .col-ajuda {
  position: absolute; top: 9px; right: 9px;
  margin-left: 0; z-index: 1;
  background: var(--paper);
}

/*
 * O RÓTULO DEVOLVE O ESPAÇO DO «?» — medido a 1024px, 08/09/2026.
 *
 * Sem esta reserva o marcador cai POR CIMA da última palavra do rótulo. Em
 * «Entra com data conhecida» e «Entra por estimativa» a colisão empurrava o
 * texto para uma segunda linha em alguns cartões e não em outros, e a fileira
 * ficava com dois pés-direitos: 132px ao lado de 96px.
 */
.kpi-wrap > .card.kpi .kpi-label { padding-right: 22px; }

/* Véu TRANSPARENTE: existe para capturar o clique de fora, e não para
 * escurecer a tela — o usuário precisa continuar lendo a tabela. */
.popover-veu { position: fixed; inset: 0; z-index: var(--z-drawer); background: transparent; }

.popover {
  position: fixed; width: min(320px, calc(100vw - 24px));
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 10px; box-shadow: 0 10px 30px rgba(3, 21, 49, .16);
  animation: fade .12s;
}

.popover-head {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 11px 12px 9px; border-bottom: 1px solid var(--line);
}

.popover-title { font-size: var(--fs-sm); font-weight: 660; letter-spacing: -.2px; line-height: 1.25; }
.popover-close { margin-left: auto; flex: none; }

.popover-body { padding: 11px 12px 13px; display: flex; flex-direction: column; gap: 10px; }

.popover-rotulo {
  font-size: var(--fs-micro); letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-mute); font-weight: 650; margin-bottom: 2px;
}

.popover-texto { font-size: var(--fs-sm); color: var(--ink-2); line-height: 1.45; }

/* Em tela estreita a caixa vira faixa embaixo: ancorar num cabeçalho que rola
 * na horizontal deixaria o pop-up fora da área visível. */
.popover-rodape {
  left: 12px; right: 12px; bottom: 12px; top: auto;
  width: auto; max-height: 60vh; overflow-y: auto;
}

/* ── MEMÓRIA DE CÁLCULO ─────────────────────────────────────────────────────
 *
 * A conta literal é o único lugar do sistema onde o alinhamento dos dígitos
 * não importa e a LEITURA importa: lê-se da esquerda para a direita, como uma
 * frase. Por isso o resultado quebra para baixo, em bloco próprio — «= 218
 * unidades» na mesma linha vira ruído no fim de uma sequência de valores.
 */
.memoria {
  background: var(--wash); border: 1px solid var(--line);
  border-radius: var(--rad-s); padding: 12px 13px;
}

.memoria-rotulo {
  font-size: var(--fs-micro); letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-mute); font-weight: 650;
}

.memoria-formula {
  font-size: var(--fs-sm); color: var(--ink-2); line-height: 1.45; margin-top: 3px;
}

.memoria-conta { margin-top: 3px; display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; }
.memoria-rotulo + .memoria-rotulo, .memoria-conta + .memoria-rotulo, .memoria-formula + .memoria-rotulo { margin-top: 11px; }

.memoria-operacao {
  font-family: var(--mono); font-size: var(--fs-sm); color: var(--ink);
  font-variant-numeric: tabular-nums; line-height: 1.5;
}

.memoria-igual {
  font-family: var(--mono); font-size: var(--fs-sm); font-weight: 680;
  color: var(--ink); font-variant-numeric: tabular-nums;
  flex-basis: 100%;
}

/* De onde saiu um termo que não está na composição por ser derivado. */
.memoria-derivado {
  display: flex; flex-wrap: wrap; gap: 3px 8px; margin-top: 9px;
  padding-top: 9px; border-top: 1px dashed var(--line);
  font-size: var(--fs-xs); color: var(--ink-mute);
}

.memoria-derivado .lbl { font-weight: 620; }
.memoria-derivado .num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* A explicação em prosa continua existindo abaixo da conta: ela diz o que a
 * fórmula não diz — por que a receita líquida não deduz tributo, por exemplo. */
.memoria-prosa { margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--line); }

/* ══ O CABEÇALHO ════════════════════════════════════════════════════════════
 *
 * -----------------------------------------------------------------------------
 * POR QUE ESTE BLOCO EXISTE — 05/09/2026
 * -----------------------------------------------------------------------------
 *
 * O layout do cabeçalho estava escrito em três lugares e em seis momentos
 * diferentes: `.head` em `base.css`, os grupos aqui, e um bloco de remendos por
 * elemento no fim de `base.css` — `.head > *`, `.head-title`, `.selector`,
 * `.selector select`, `.search-wrap`, `.search` — mais três media queries.
 *
 * Cada remendo resolvia um aperto que alguém tinha visto. Juntos, brigavam:
 *
 *   `.head > * { flex: none }` (0,1,1) vencia `.head-spacer { flex: 1 }` (0,1,0)
 *
 * O espaçador parou de crescer. Medido a 1440px: as ações terminavam em x=1216
 * com a borda do cabeçalho em x=1430 — **190px de sobra à direita**, e o avatar
 * flutuando no meio do nada.
 *
 * Ao mesmo tempo `.selector select { max-width: 160px }` cortava o texto do
 * próprio seletor: `scrollWidth 188` contra `clientWidth 160`, e a tela dizia
 * «Setembro/2026 · em andam▾». O «Atualizar» era um `<button class="icon-btn">`
 * de 32×32 com 58px de conteúdo dentro — a palavra escorria para fora do botão,
 * por cima da borda inferior do cabeçalho.
 *
 * É o MESMO defeito que `.page` tinha: regra por par de vizinhos, uma por
 * combinação que alguém encontrou. Não escala, e o que ela não cobre depende de
 * quem vier depois.
 *
 * -----------------------------------------------------------------------------
 * A ESTRUTURA
 * -----------------------------------------------------------------------------
 *
 *   [título] ←──────── espaço livre ────────→ [contexto] [busca] [ações]
 *
 * O título fica na esquerda e empurra o resto com `margin-right: auto`. Não
 * existe mais elemento espaçador: um `<div>` de largura zero só servia para
 * somar um `gap` extra e para ser anulado por outra regra.
 *
 * ENTRE grupos, `var(--gap)`; DENTRO do grupo, 6px. Dois números, e a razão
 * entre eles é o que faz o olho ler três blocos em vez de sete peças.
 *
 * QUEM ENCOLHE, E EM QUE ORDEM. É isto que faltava: sem declarar a ordem, o
 * navegador encolhe o que estiver mais à mão.
 *
 *   ações      nunca      são alvos de clique; encolher vira erro de mira
 *   contexto   por último  empresa e período dizem o que a tela mostra
 *   busca      primeiro    é a única peça que continua útil menor
 */
.head {
  display: flex; align-items: center; gap: var(--gap);
  padding: 0 var(--gap-l);
}

.head-title { flex: 0 0 auto; margin-right: auto; }

.head-grupo { display: flex; align-items: center; gap: 6px; min-width: 0; }

/* Os pesos de encolhimento IMPLEMENTAM a ordem declarada acima. Sem eles o
 * navegador reparte o aperto na proporção do tamanho de cada um, e o contexto
 * — que é o maior — absorvia dois terços: a busca ficava intacta enquanto
 * empresa e período viravam reticências. */
.head-contexto { flex: 0 1 auto; }
.head-busca    { flex: 0 8 260px; min-width: 120px; }
.head-acoes    { flex: 0 0 auto; }

/* Todo controle do cabeçalho na MESMA altura. O chip do usuário media 30px
 * contra 32 dos demais, e 2px de diferença numa linha de seis peças é o que se
 * lê como «torto» sem se conseguir apontar onde. */
.head-grupo > * { height: 32px; }
.head-grupo .user-chip-wrap,
.head-grupo .user-chip-btn { height: 32px; }

/* O seletor cabe no próprio texto quando há espaço, e encolhe com reticências
 * quando não há. `max-width` fixo fazia as duas coisas erradas ao mesmo tempo:
 * cortava com folga na tela e não encolhia mais quando faltava. */
.head-grupo .selector { flex: 0 1 auto; min-width: 0; overflow: hidden; }
/* O seletor de empresa NÃO pode recortar: o menu de caixas dele flutua para
 * fora da caixa. Como ele não recorta, quem encolhe é o botão — e para isso o
 * invólucro entre os dois precisa poder encolher também. Sem o `min-width: 0`
 * aqui, o botão media 130px dentro de uma caixa de 111px e o texto passava por
 * cima da borda a 1024px. */
.head-grupo .selector.is-multi { overflow: visible; }
.head-grupo .selector-drop { flex: 0 1 auto; min-width: 0; display: flex; }
.head-grupo .selector select {
  min-width: 0; max-width: none; flex: 0 1 auto;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* No botão de empresa quem recorta é o RÓTULO, e não o botão: a seta `▾` é um
 * `::after`, isto é, texto — recortando o botão inteiro, ela era a primeira a
 * sumir, e sobrava «Todas as emp…» sem nenhum sinal de que aquilo abre. */
.head-grupo .selector-toggle { min-width: 0; max-width: none; flex: 0 1 auto; display: flex; align-items: center; }
.head-grupo .selector-toggle-txt { min-width: 0; flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.head-grupo .selector-toggle::after { flex: none; }

/* -----------------------------------------------------------------------------
 * A ESCADA DE LARGURA — uma coisa some por degrau, e cada degrau tem motivo.
 * -----------------------------------------------------------------------------
 *
 * Medido com a barra lateral aberta (284px) e 24px de recuo de cada lado.
 */

/* Nome e cargo são o que menos informa: quem está logado já é o próprio avatar. */
@media (max-width: 1280px) {
  .user-chip .user-name, .user-chip .user-role { display: none; }
}

/* O título da tela é redundante com o item marcado no menu lateral, que
 * continua à vista. Ele SOME — não encolhe: a 1024px ele virava «P». */
@media (max-width: 1180px) {
  .head-title { display: none; }
}

/* Os rótulos «Empresa» e «Período» saem, e o «Atualizar» fica só com o ícone:
 * os dois seletores continuam legíveis pelo próprio valor, e o botão mantém a
 * dica no `title`. */
@media (max-width: 1100px) {
  .selector label { display: none; }
  .atualizar-btn .btn-acao-rotulo { display: none; }
  .atualizar-btn { width: 32px; padding: 0; justify-content: center; }
}

/* Abaixo daqui a barra lateral já virou gaveta e devolveu 284px; o que falta é
 * espaço para os seletores, e a busca é a peça que se recupera com um clique
 * no menu. */
@media (max-width: 680px) {
  .head { padding: 0 var(--gap); }
  .head-busca { display: none; }
  .head-contexto { flex: 1 1 auto; }
  .head-grupo .selector { flex: 1 1 auto; }
}

/* Botão de ação do cabeçalho: ícone + rótulo, altura da linha, largura pelo
 * conteúdo. `.icon-btn` é uma caixa de 32×32 com `place-items: center` — texto
 * dentro dela não encolhe a caixa, escorre para fora dela. */
.btn-acao {
  display: inline-flex; align-items: center; gap: 6px;
  height: 32px; padding: 0 10px;
  border: 1px solid var(--line); border-radius: var(--rad-s);
  background: var(--paper); color: var(--ink-2);
  font-size: var(--fs-xs); font-weight: 650; white-space: nowrap;
  cursor: pointer;
}
.btn-acao:hover { background: var(--paper-2); border-color: var(--line-2); color: var(--ink); }
.btn-acao:focus-visible { outline: 2px solid var(--steel-2); outline-offset: 1px; }
.btn-acao:disabled { opacity: .6; cursor: default; }
.btn-acao .ico { flex: none; }

/* ── A IMAGEM DO PRODUTO ─────────────────────────────────────────────────────
 *
 * Tamanho fixo nos dois eixos e `object-fit: contain`: as fotos da Amazon vêm
 * em proporções diferentes, e sem isso cada linha da tabela teria uma altura,
 * o que destrói o ritmo de leitura de uma tabela de cinquenta linhas.
 *
 * `contain` e não `cover` porque recortar embalagem esconde justamente o que
 * distingue um tapete de outro. Fundo claro para as fotos com transparência.
 */
.miniatura {
  width: 28px; height: 28px; flex: none;
  object-fit: contain; border-radius: 4px;
  background: var(--paper-2); border: 1px solid var(--line);
  display: block;
}

/* Sem ASIN não há imagem. A inicial DISTINGUE; um ícone genérico igual para
 * todos faria dois produtos diferentes parecerem o mesmo. */
/* A célula que junta imagem e nome. `nowrap` explícito: com quebra, a imagem
 * subia para uma linha própria e a altura da linha ia de 44 para 83px — numa
 * tabela de cinquenta linhas, o ritmo vertical é o que se lê primeiro. */
.celula-produto { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; min-width: 0; }
.celula-produto-txt { min-width: 0; }

/* Código de vendedor não quebra: ele tem hífens, e o navegador quebra neles.
 * «P6-IFDW-QRBT» em três linhas triplica a altura da linha inteira. */
table.data td .mono.tiny { white-space: nowrap; }

.miniatura.is-vazia {
  display: grid; place-items: center;
  font-size: var(--fs-xs); font-weight: 700; color: var(--ink-faint);
}

/* No detalhe do SKU a imagem tem espaço para ser vista. */
.produto-foto {
  width: 132px; height: 132px; flex: none;
  object-fit: contain; border-radius: var(--rad-s);
  background: var(--paper-2); border: 1px solid var(--line);
}
.produto-foto-nota { font-size: var(--fs-micro); color: var(--ink-faint); margin-top: 6px; }

/* ── O RITMO VERTICAL DA PÁGINA ─────────────────────────────────────────────
 *
 * Medido em 04/09/2026, com 1440px de largura, percorrendo as telas: a folga
 * entre os blocos de topo era 16, 16, 24, 24, 24, 16, 16, 24, 16… e em Preço e
 * Mercado havia um **0** — dois blocos encostados — e um 10.
 *
 * A causa não era descuido de nenhuma tela: `.section` traz `margin-top: 24px`
 * e `.grid` e as notas não trazem nada. A folga passava a depender de QUEM VEM
 * DEPOIS DE QUEM, e cada tela sorteava um ritmo diferente conforme a ordem dos
 * blocos. Ninguém consegue manter isso à mão em trinta telas.
 *
 * A cura é tirar a decisão de cada elemento e dá-la ao contêiner: a página
 * distribui um espaço só entre os filhos diretos, e o ritmo passa a ser o mesmo
 * em toda tela por construção.
 *
 * As margens antigas são zeradas SÓ no primeiro nível. Seção dentro de seção
 * continua com a margem dela — ali a hierarquia é outra, e o afastamento
 * declara subordinação.
 */
.page {
  display: flex;
  flex-direction: column;
  gap: var(--gap-l);
}

/*
 * NO PRIMEIRO NÍVEL, QUEM ESPAÇA É O CONTÊINER — e mais ninguém.
 *
 * Zerar só `.section` não bastou: `.note` também traz margem própria, e o
 * resultado foram folgas de 40px (24 do contêiner + 16 da nota) alternando com
 * 24px. Enquanto qualquer filho puder acrescentar margem, o ritmo volta a
 * depender da ordem dos blocos — o defeito original, com outro número.
 *
 * A margem VERTICAL morre aqui; a horizontal fica, porque `.page` é coluna e
 * nada nela empurra os lados.
 */
.page > * { margin-top: 0; margin-bottom: 0; }

/* O cabeçalho da página é o rótulo do que vem logo abaixo: ele fica mais perto
 * do primeiro bloco do que os blocos ficam entre si. Proximidade é o que diz
 * «isto pertence àquilo» sem precisar de linha nem de moldura. */
.page > .page-head + * { margin-top: calc(var(--gap) - var(--gap-l)); }

/* ── E O MESMO, UM NÍVEL ABAIXO: A SEÇÃO — 17/09/2026 ───────────────────────
 *
 * A explicação longa está lá em cima, em «A SEÇÃO PASSOU A DISTRIBUIR O
 * PRÓPRIO ESPAÇO». O resumo: dentro da seção a folga ainda era decidida por
 * lista de pares de vizinhos, e `.grid + .table-wrap` não estava na lista —
 * KPIs colados na tabela, medido em Cartões com vão de ZERO.
 *
 * As regras precisam vir DEPOIS de `.note`: aquela regra tem a mesma
 * especificidade da zeragem, e quem chega por último vence o empate.
 *
 * O ritmo interno é menor que o da página de propósito — 16 entre blocos
 * contra 24 —, porque hierarquia também se lê pelo espaço.
 */
.section { display: flex; flex-direction: column; gap: var(--gap); }
.section > * { margin-top: 0; margin-bottom: 0; }

/* Subordinação: uma seção dentro de outra se afasta mais do que dois blocos
 * irmãos. 24 no total, e não 24 somados aos 16 do contêiner. */
.section > .section { margin-top: calc(var(--gap-l) - var(--gap)); }

/* Notas seguidas são a continuação da mesma explicação, e ficam mais juntas. */
.section > .note + .note { margin-top: calc(var(--gap-s) - var(--gap)); }

/* O cabeçalho da seção, como o da página, cola no bloco que ele nomeia. Vem
 * por último de propósito: quando o primeiro bloco é uma subseção, quem manda
 * é a proximidade com o título, não a subordinação. */
.section > .section-head + * { margin-top: calc(var(--gap-s) - var(--gap)); }

/*
 * ESCOLHA PESQUISÁVEL — a lista que não deixa digitar fora dela.
 *
 * Usada onde a escolha precisa vir do cadastro: compor uma compra exige um SKU
 * que exista, e um campo de texto livre ali criaria custo para um produto que
 * ninguém cadastrou.
 *
 * A lista tem altura fixa e rola por dentro. Sem isso, cinquenta e quatro
 * produtos empurrariam o botão de gravar para fora da gaveta.
 */
.busca-campo { display: flex; flex-direction: column; gap: 6px; width: 100%; }
.busca-campo input[type="search"] { width: 100%; }

.busca-lista {
  display: flex; flex-direction: column;
  max-height: 168px; overflow-y: auto;
  border: 1px solid var(--line); border-radius: var(--rad-s);
  background: var(--paper);
}

.busca-item {
  display: flex; align-items: baseline; gap: 8px; text-align: left;
  padding: 6px 9px; border: 0; background: none; cursor: pointer;
  border-bottom: 1px solid var(--paper-3); font-size: var(--fs-sm);
}
.busca-item:last-child { border-bottom: none; }
.busca-item:hover { background: var(--paper-2); }

/* O escolhido precisa continuar visível depois que o foco sai do item. */
.busca-item.is-escolhido { background: var(--info-bg); font-weight: 600; }

.busca-nome { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.busca-vazia { padding: 9px; font-size: var(--fs-sm); color: var(--ink-mute); }

/*
 * CONTAGEM QUE FILTRA — Preço e mercado, 10/09/2026.
 *
 * A Distribuição era contagem estática. Virou botão: precisa parecer clicável
 * em repouso e continuar marcada depois de clicada, senão ninguém percebe que
 * a tabela abaixo está recortada.
 */
.chip-filtro {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 10px; margin: 0 8px 8px 0;
  border: 1px solid var(--paper-3); border-radius: 999px;
  background: var(--paper); font: inherit; cursor: pointer;
}
.chip-filtro:hover { background: var(--paper-2); }
.chip-filtro.is-ativo { border-color: var(--info, #165d90); background: var(--info-bg); font-weight: 600; }
.chip-filtro:focus-visible { outline: 2px solid var(--info, #165d90); outline-offset: 2px; }

/*
 * O BOTÃO «ESCOLHER ARQUIVO» — Importações, 10/09/2026.
 *
 * O navegador desenhava o botão nativo, cinza e fora da régua dos outros
 * botões da tela. `::file-selector-button` o põe no mesmo desenho, sem trocar
 * o controle: ele continua sendo o seletor de arquivo do sistema.
 */
input[type="file"] { font: inherit; font-size: var(--fs-sm); color: var(--ink-mute); max-width: 100%; }
input[type="file"]::file-selector-button {
  font: inherit; font-weight: 600; margin-right: 10px; padding: 7px 14px;
  border: 1px solid var(--paper-3); border-radius: 8px;
  background: var(--paper); color: inherit; cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: var(--paper-2); }
