/* ==========================================================================
   Guti · produção — sistema de design (docs/design/10-sistema.md)
   Um arquivo escrito à mão. Sem build. Tudo hospedado aqui (fontes em ../fonts).
   Ordem: tokens → fontes → reset → tipografia → layout → componentes →
          utilitários → responsivo → impressão → movimento reduzido.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  color-scheme: light dark;

  /* superfícies e linhas */
  --papel: #eeebe3;            /* o fundo da página: papel, não tela — um degrau ABAIXO da superfície (rodada de layout, 2026-09-08: era #f5f3ed, e caixa e página mediam 1,11:1, o mesmo cinza) */
  --superficie: #ffffff;       /* caixas, cards, campos */
  --superficie-2: #f0eee7;     /* cabeçalho de tabela, texto bruto, zebra */
  --superficie-3: #e6e3da;     /* chips neutros, marcos */
  --linha: #ddd9cf;            /* borda padrão */
  --linha-suave: #ebe8e0;      /* hairline entre linhas de tabela */
  --linha-forte: #989388;      /* borda de campo · 3,06:1 sobre branco (contorno de controle, WCAG 1.4.11)
                                  era #9a958a, que media 2,98:1 — falhava o mínimo por 0,02 enquanto o
                                  §2 do sistema afirmava que passava (crítica 1 do ciclo 2, achado 9) */

  /* tinta */
  --tinta: #1c1b18;            /* texto principal · 15,6:1 sobre branco */
  --tinta-2: #45423c;          /* texto secundário · 8,9:1 */
  --apagado: #6a665e;          /* metadados, rótulos · 5,3:1 sobre branco, 4,8:1 sobre papel */
  --apagado-2: #8a867d;        /* só para elementos decorativos (traços, separadores) */

  /* marca: o verde da polpa, único acento */
  --marca: #0f6b4c;            /* 5,9:1 sobre branco */
  --marca-forte: #0b543b;
  --marca-suave: #e2f0e9;
  --marca-tinta: #0a4a34;      /* texto sobre --marca-suave · 9:1 */

  /* compatibilidade com os templates que citam as variáveis antigas */
  --destaque: var(--marca);
  --fundo: var(--papel);

  /* semânticos */
  --erro: #a3282a;             /* 6,6:1 sobre branco */
  --erro-suave: #fbe9e7;
  --erro-tinta: #7a1d1f;
  --alerta: #8a5a00;           /* 5,9:1 */
  --alerta-suave: #fff5d6;
  --alerta-linha: #d4a800;
  --alerta-tinta: #5c3c00;
  --ok: var(--marca);
  --ok-suave: var(--marca-suave);
  --info: #2457a6;             /* 6,3:1 */
  --info-suave: #e8effa;
  --info-tinta: #173f7a;
  --foco: #2457a6;             /* anel de foco: azul, para nunca se confundir com a marca */

  /* a paleta das naturezas — a palavra vem antes; a cor só reforça */
  /* O «AFERIDO» TEM UM TOM SÓ DELE (decisão do dono, 2026-09-08). Era o MESMO verde da marca
     (#0f6b4c), e a decisão 5 do sistema — «nada que não seja aferido pode usar esse verde» — era
     impossível de cumprir: o botão, o menu e o chip escolhido já eram verde-aferido. Agora um botão
     verde nunca mais parece um número medido. Verde-azulado, 5,0:1 sobre branco. */
  --nat-aferido: #0e7c78;      /* ✓ · verde-azulado · 5,0:1 */
  --nat-contado: #2457a6;      /* # · azul · 6,3:1 */
  --nat-declarado: #8a5a00;    /* ~ · âmbar · 5,9:1 */
  --nat-estimado: #7b3fa0;     /* ≈ · roxo · 6,5:1 */
  --nat-calculado: #4f5b66;    /* = · ardósia · 7,1:1 */

  /* a marca de trecho reconhecido no texto bruto */
  --realce: #fdf0b5;
  --realce-linha: #d4a800;
  --marca-texto: var(--realce);  /* nome antigo */

  /* tipografia */
  --fonte: "IBM Plex Sans", "Segoe UI", Roboto, "Helvetica Neue", Arial, system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  /* a escala, e o papel de cada degrau (ciclo 2, D1/D3 da direção — docs/design/10-sistema.md §2) */
  --t-2: 0.6875rem;   /* 11 · rótulo de grupo na fita de navegação. Só isso. */
  --t-1: 0.75rem;     /* 12 · rótulo de caixa (h2 em caixa alta), chips de estado, legend, código técnico */
  --t0: 0.8125rem;    /* 13 · metadados, .nota, e TODA prosa explicativa (o pé da caixa) */
  --t1: 0.875rem;     /* 14 · seção de página (h2.secao), linha de tabela, botão */
  --t2: 0.9375rem;    /* 15 · corpo, linha da pauta, número secundário */
  --t3: 1.0625rem;    /* 17 · frase-chave, título do .bloco (o assunto) e O NÚMERO PRINCIPAL da linha */
  --t4: 1.25rem;      /* 20 · título de ficha */
  --t5: 1.5rem;       /* 24 · (livre desde o ciclo 2; era o h1) */
  --t6: 2rem;         /* 32 · o número do cartão */
  --t7: 1.75rem;      /* 28 · h1, título de página (22 em ≤ 600 px) */

  /* espaço · 4 · 8 · 12 · 16 · 24 · 32 · 48 */
  --e1: 4px; --e2: 8px; --e3: 12px; --e4: 16px; --e5: 24px; --e6: 32px; --e7: 48px;

  /* raios */
  --r1: 4px; --r2: 8px; --r3: 12px; --r-pilula: 999px;

  /* sombras: uma por superfície (rodada de layout, 2026-09-08). Até aqui a hierarquia era «da linha,
     não da sombra», e a linha media 1,27:1: a caixa não se separava da página. A superfície passa a
     ter três sinais — degrau de cor, borda e uma sombra curta — e a sombra é curta de propósito:
     é elevação de papel sobre mesa, não de cartão flutuando. */
  --sombra-1: 0 1px 2px rgba(28, 27, 24, .05), 0 2px 8px rgba(28, 27, 24, .05);
  --sombra-2: 0 4px 16px rgba(28, 27, 24, .10);
  --realce-superficie: inset 0 1px 0 rgba(255, 255, 255, 0);   /* no escuro vira um fio de luz na borda de cima */

  /* movimento */
  --rapido: 120ms;
  --normal: 200ms;
  --curva: cubic-bezier(.2, 0, 0, 1);

  /* medidas */
  --largura-conteudo: 1320px;
  --largura-leitura: 46rem;
  --altura-topo: 52px;       /* altura da barra quando ela vai para o topo (telas estreitas) */
  --largura-lateral: 220px;   /* rodada de layout 2: 20 px a mais, para o ícone do grupo e o recuo dos itens */
}

@media (prefers-color-scheme: dark) {
  :root {
    --papel: #111210;            /* rodada de layout: um degrau mais fundo, para a superfície subir */
    --superficie: #1c1e1d;
    --superficie-2: #262927;
    --superficie-3: #30332f;
    --linha: #383b37;
    --linha-suave: #2c2f2c;
    --linha-forte: #6f736c;      /* 3,3:1 sobre --superficie */

    --tinta: #ecebe4;
    --tinta-2: #c9c6bd;
    --apagado: #a29e94;
    --apagado-2: #7d7a71;

    --marca: #4fbf93;
    --marca-forte: #7ad4b0;
    --marca-suave: #1d3a30;
    --marca-tinta: #bfeadb;

    --erro: #f08a83;
    --erro-suave: #3d2321;
    --erro-tinta: #ffc9c4;
    --alerta: #e0a94a;
    --alerta-suave: #3a2f14;
    --alerta-linha: #c9962a;
    --alerta-tinta: #f5dca6;
    --info: #7fb0f5;
    --info-suave: #1e2c42;
    --info-tinta: #c6dbfa;
    --foco: #8fb8f7;

    --nat-aferido: #5fd3c9;      /* verde-azulado, longe do #4fbf93 da marca */
    --nat-contado: #7fb0f5;
    --nat-declarado: #e0a94a;
    --nat-estimado: #c98ef0;
    --nat-calculado: #a7b1bb;

    --realce: #4a3d0a;
    --realce-linha: #e0b93a;

    --sombra-1: 0 1px 2px rgba(0, 0, 0, .45), 0 2px 10px rgba(0, 0, 0, .35);
    --sombra-2: 0 4px 16px rgba(0, 0, 0, .5);
    --realce-superficie: inset 0 1px 0 rgba(255, 255, 255, .035);   /* o fio de luz: no escuro, sombra não separa — luz separa */
  }
}

/* --------------------------------------------------------------------------
   2. Fontes — hospedadas em app/static/fonts (nenhum pedido externo)
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 100 700;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-latin.07bd8809259a.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+2248, U+2713, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: italic;
  font-weight: 100 700;
  font-display: swap;
  src: url("../fonts/ibm-plex-sans-italic-latin.7218109c9d77.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+2248, U+2713, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono-400-latin.e7e1328cca81.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/ibm-plex-mono-500-latin.02ad29edd399.woff2") format("woff2");
}

/* --------------------------------------------------------------------------
   3. Reset — curto e sem opinião além do necessário
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: var(--e4); }
body {
  margin: 0;
  font: 400 var(--t2)/1.5 var(--fonte);
  color: var(--tinta);
  background: var(--papel);
  font-feature-settings: "kern", "liga", "tnum";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
}
img, svg { display: inline-block; vertical-align: middle; max-width: 100%; }
p, ul, ol, table, pre, fieldset { margin-top: 0; }
p, ul, ol { margin-bottom: var(--e3); }
ul, ol { padding-left: 1.25rem; }
li { margin: .2rem 0; }
fieldset { border: 0; padding: 0; margin-bottom: var(--e3); min-width: 0; }
legend { padding: 0; }
hr { border: 0; border-top: 1px solid var(--linha); margin: var(--e5) 0; }
code, kbd, samp { font-family: var(--mono); font-size: .92em; }
code { background: var(--superficie-2); padding: .05em .35em; border-radius: var(--r1); color: var(--tinta-2); }
strong, b { font-weight: 600; }
em, i { font-style: italic; }
small { font-size: var(--t1); }
[hidden] { display: none !important; }
::selection { background: var(--realce); color: var(--tinta); }

/* --------------------------------------------------------------------------
   4. Tipografia
   -------------------------------------------------------------------------- */
h1, h2, h3, h4 { margin: 0; font-weight: 600; line-height: 1.25; letter-spacing: -0.005em; }
/* D3: o título é a única âncora de quem abre uma tela por um link — ele tem de aguentar sozinho */
h1 { font-size: var(--t7); letter-spacing: -0.01em; margin: 0 0 var(--e4); }
/* o sufixo apagado dentro do h1 (padrão de todos os templates) vira a linha de metadados do cabeçalho */
h1 > .apagado, h1 > .pequeno { display: block; font-weight: 400; font-size: var(--t1); color: var(--apagado); letter-spacing: 0; line-height: 1.45; margin-top: var(--e1); }
h1 .titulo-sufixo { font-weight: 400; color: var(--tinta-2); }
h2 {
  font-size: var(--t-1);
  color: var(--apagado);
  text-transform: uppercase;
  letter-spacing: .08em;
  margin: var(--e5) 0 var(--e2);
}
h2 a { color: inherit; text-decoration-color: var(--linha-forte); }
h3 { font-size: var(--t2); margin: var(--e4) 0 var(--e2); }
/* D2 · o TERCEIRO degrau de cabeça: o h2 cujo título é o ASSUNTO (um nome, um pedido, um insumo),
   não uma categoria. 17/600 em tinta, sem caixa alta. Vem do componente .bloco (§ "Bloco"). */
.bloco > .bloco-cabeca > h2, h2.assunto {
  font-size: var(--t3); font-weight: 600; color: var(--tinta);
  text-transform: none; letter-spacing: -0.01em; margin: 0;
}
.caixa > h2:first-child, .card > h2:first-child, .caixa > .cabecalho-secao:first-child { margin-top: 0; }

a { color: var(--marca); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .14em; text-decoration-color: color-mix(in srgb, var(--marca) 45%, transparent); transition: text-decoration-color var(--rapido); }
a:hover { text-decoration-color: currentColor; }
a:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; border-radius: 2px; }

.frase { font-size: var(--t3); line-height: 1.45; }
.frase strong { font-weight: 600; }
.apagado { color: var(--apagado); }
.pequeno { font-size: var(--t1); }
.miudo { font-size: var(--t0); }
.mono, .codigo { font-family: var(--mono); font-size: .92em; }
/* O CÓDIGO DO ITEM À ESQUERDA DO NOME, nas listas (2026-09-10, a pedido do dono).
   `min-width` em `ch` alinha os NOMES numa coluna só, apesar de os códigos terem tamanhos
   diferentes (`MALTO` × `POLPA_ILHA`): sem isso, catorze nomes começam em catorze recuos e a lista
   deixa de se varrer. É também o que faz a padronização do cadastro parecer padronização.
   `tinta-2` e não `apagado`: identificador que quase não se vê não identifica nada — mas ele
   tampouco compete com o nome, que continua sendo a palavra em tinta cheia.
   Não quebra no meio: `INS-0024` partido em duas linhas deixa de ser um código. */
/* a linha do medidor na ficha do item: a barra ocupa a largura e a régua vem embaixo dela, em
   texto pequeno — o número do mínimo é referência, não resposta (a resposta é o saldo, acima). */
/* a ficha do item: duas colunas — o que se le primeiro a esquerda, o que se consulta a direita */
.ficha-item { display: grid; grid-template-columns: minmax(0, 20rem) minmax(0, 1fr); gap: var(--e4) var(--e5); align-items: start; }
.ficha-item > * { min-width: 0; }
.ficha-coluna > .caixa + .caixa { margin-top: var(--e4); }
@media (max-width: 900px) { .ficha-item { grid-template-columns: 1fr; } }
/* a segunda régua da ficha, separada da primeira por uma linha: elas nunca se somam, e o traço
   entre elas diz isso sem palavra nenhuma */
.regua-declarada { margin-top: var(--e4); padding-top: var(--e3); border-top: 1px solid var(--linha-suave); }
.regua-declarada .sub { display: block; margin-top: var(--e2); }
.medidor-linha { margin: var(--e3) 0 0; }
.medidor-linha .medidor { width: 100%; }
.medidor-linha .sub { margin: var(--e2) 0 0; display: block; }

span.item-codigo { color: var(--tinta-2); }   /* sem link: tinta secundária */
a.item-codigo { font-weight: 500; }            /* com link: a cor e o sublinhado do produto, e é ele que se clica */
.item-codigo { font-size: .92em; white-space: nowrap; display: inline-block; min-width: 10ch; }
.item-sep { color: var(--apagado); }
/* no telefone a tabela vira cartão e a célula é estreita: o código volta a ser inline, sem reserva */
@media (max-width: 700px) { .item-codigo { min-width: 0; } }
.negativo { color: var(--erro); }
.nao-quebrar { white-space: nowrap; }

/* --------------------------------------------------------------------------
   5. A gramática do número — .num e .nat andam colados, sempre em palavra
   -------------------------------------------------------------------------- */
.num { font-variant-numeric: tabular-nums; font-weight: 600; letter-spacing: -0.005em; white-space: nowrap; }
.num.grande { font-size: var(--t6); line-height: 1.1; font-weight: 500; }
/* D1 · UM número principal por linha, no máximo: o da coluna que dá nome à tela. 17 px, e continua
   17 no telefone (R2 — o rótulo encolhe, o número não). Os demais números da linha ficam em 15. */
.num.principal, .tabela .num.principal, table.proc .num.principal { font-size: var(--t3); }
/* a natureza colada a um número principal cresce junto, senão o par parece dois planos */
.num.principal + .nat { font-size: var(--t2); }
/* UM NÚMERO NUNCA FICA VERDE POR SER LINK (crítica 2, achado 7). Verde no número é a cor de
   `aferido`, e o §3 é explícito: a cor das naturezas não se usa em mais nada. Em /fabrica/, `920 kg`
   saía em tinta e `300 kg` em --marca, lado a lado, com `≈ estimado` roxo colado. A afordância do
   link continua sendo o sublinhado; o vermelho do negativo continua vencendo, porque é vocabulário. */
a .num, a:hover .num { color: var(--tinta); }
a .num.negativo, a:hover .num.negativo { color: var(--erro); }
.nat { font-weight: 500; font-size: .92em; white-space: nowrap; color: var(--apagado); }
.nat::before { font-family: var(--mono); font-weight: 500; }
.nat-aferido   { color: var(--nat-aferido); }   .nat-aferido::before   { content: "✓ "; }
.nat-contado   { color: var(--nat-contado); }   .nat-contado::before   { content: "# "; }
.nat-declarado { color: var(--nat-declarado); } .nat-declarado::before { content: "~ "; }
.nat-estimado  { color: var(--nat-estimado); }  .nat-estimado::before  { content: "≈ "; }
.nat-calculado { color: var(--nat-calculado); } .nat-calculado::before { content: "= "; }
/* a legenda das naturezas, para rodapé de relatório */
.legenda-naturezas { display: flex; flex-wrap: wrap; gap: var(--e2) var(--e4); font-size: var(--t0); color: var(--apagado); margin: var(--e3) 0 0; padding: 0; list-style: none; }

/* --------------------------------------------------------------------------
   6. Estados com nome — nunca célula vazia
   -------------------------------------------------------------------------- */
.estado {
  display: inline-block; font-size: var(--t-1); font-weight: 500; line-height: 1.4;
  padding: 1px 8px; border-radius: var(--r-pilula); border: 1px solid var(--linha);
  background: var(--superficie-3); color: var(--tinta-2); white-space: nowrap; vertical-align: baseline;
}
.estado-indisponivel  { background: var(--superficie-2); color: var(--tinta-2); border-style: dashed; border-color: var(--linha-forte); }
/* ausência: sem fundo, borda tracejada — NUNCA o cinza de "estado normal, nada a fazer".
   'sem mínimo definido' é ausência de régua, e ausência com cara de normal é a mentira mais barata (D5). */
/* «interrompida» entrou na FAMÍLIA DA AUSÊNCIA (decisão do dono, 2026-09-08): a corrente parou
   porque falta um elo, e falta se veste de tracejado — nunca de vermelho, que é diagnóstico virando
   culpa de quem opera. Caía no cinza de «normal, nada a fazer», que é o contrário do que ela diz. */
.estado-nao-informado, .estado-sem-minimo-definido, .estado-interrompida { background: transparent; color: var(--apagado); border-style: dashed; }
.estado-nao-controlado{ background: transparent; color: var(--tinta-2); border-color: var(--linha-forte); }
.estado-retificado    { background: var(--alerta-suave); color: var(--alerta-tinta); border-color: var(--alerta-linha); }
.estado-rascunho      { background: var(--info-suave); color: var(--info-tinta); border-color: color-mix(in srgb, var(--info) 40%, transparent); }
.estado-indeterminado { background: transparent; color: var(--apagado); border-style: dotted; border-color: var(--linha-forte); }
/* vermelho = problema em aberto: divergência aberta/reaberta, trecho aberto, tarefa que falhou,
   linha de nota sem de-para (ciclo 2, D5). NUNCA o lote aberto (estado normal de um lote em uso) */
.estado-aberta, .estado-reaberta, .estado-falhou, .estado-sem-de-para { background: var(--erro-suave); color: var(--erro-tinta); border-color: color-mix(in srgb, var(--erro) 40%, transparent); }
/* verde-suave = fechado, confirmado, vigente: o que está resolvido ou valendo */
.estado-ok, .estado-completa, .estado-ativo, .estado-confirmado, .estado-encerrada, .estado-vigente, .estado-explicada, .estado-aceita, .estado-ajustada, .estado-explicado, .estado-concluida, .estado-acima-do-minimo { background: var(--ok-suave); color: var(--marca-tinta); border-color: color-mix(in srgb, var(--marca) 40%, transparent); }
/* neutro (cinza, o padrão de .estado) = estado normal de um objeto em uso: lote aberto/recebido/em uso, batelada em curso, produto — nada a fazer */
.estado-aberto, .estado-recebido, .estado-em_uso, .estado-em_curso, .estado-fechado, .estado-liberado { background: var(--superficie-3); color: var(--tinta-2); }
/* apagado = o que já foi superado e continua legível: versão substituída, produto descontinuado,
   trecho descartado, e a linha de nota que a Guti disse que NÃO É INSUMO (ciclo 2, D5) */
.estado-substituida, .estado-descontinuado, .estado-descartado, .estado-abandonada, .estado-nao-e-insumo, .estado-cancelado { background: transparent; color: var(--apagado); border-color: var(--linha); }
/* âmbar = contexto que muda a leitura, sem violação: registro retificado, e o insumo abaixo da régua.
   "em baixa" e "abaixo do mínimo" são a MESMA coisa em duas palavras: têm de ter uma cara só.
   `precisa pedir` é a mesma família com outra palavra: a sugestão projeta sobre o prazo do fornecedor,
   e o saldo de hoje pode estar acima do mínimo — a classe passa a bater com a palavra (pedido da área A). */
.estado-abaixo-do-minimo, .estado-em-baixa, .estado-precisa-pedir { background: var(--alerta-suave); color: var(--alerta-tinta); border-color: var(--alerta-linha); }
/* PERTO DO MÍNIMO é aviso, não alerta: o estoque ainda está acima da régua, e a diferença é ter ou
   não folga para a próxima batelada. Se recebesse o âmbar de «abaixo», as duas leituras que a tela
   de compra existe para separar voltariam a parecer a mesma (2026-09-08). Contorno âmbar, fundo do
   ambiente: a cor diz a família, o preenchimento diz a urgência. */
.estado-perto-do-minimo { background: transparent; color: var(--alerta-tinta); border-color: var(--alerta-linha); }
/* «parcial» é meio caminho: âmbar de contorno, como «perto do mínimo» — atenção sem alarme */
.estado-parcial { background: transparent; color: var(--alerta-tinta); border-color: var(--alerta-linha); }
/* A quantidade a repor é um NÚMERO CLICÁVEL: o alvo do toque é a linha inteira do rótulo, não só a
   caixinha de 13 px — quem desmarca um item está decidindo não comprar, e essa decisão não pode
   depender de pontaria. */
/* O MEDIDOR · saldo contra o mínimo (2026-09-08, /compra/sugestao/).
   A coluna «contra o mínimo» eram treze selos, onze deles com a MESMA palavra: um muro de pastilhas
   verdes sem informação, e a única linha que importava afogada no meio. A pergunta da tela — *o que
   está para acabar* — é sobre PROPORÇÃO, e proporção não se lê em duas colunas de números; lê-se num
   traço. O marco no meio é o mínimo; a barra é o estoque. Quem está antes do marco está abaixo.

   A escala vai de zero a DUAS vezes o mínimo, então o marco fica sempre no meio e as linhas são
   comparáveis entre si. Acima disso a barra enche e ganha a seta: dizer «cabe mais» é honesto, e
   esticar a escala por causa de um insumo com trinta vezes o mínimo achataria os outros doze.

   A palavra só aparece na EXCEÇÃO. «Acima do mínimo» é o caso normal, e o normal não precisa de
   selo — a barra passando do marco já diz. É a mesma regra que tirou a coluna constante de /saldos/
   e de /contagem/, aplicada a um estado em vez de a um valor. */
/* CONTRASTE (2026-09-08) · desde que a palavra saiu da tela, a barra é a ÚNICA aparição de
   `abaixo do mínimo`, `perto do mínimo` e `acima do mínimo`. E ela era desenhada abaixo de 3:1 em
   três dos quatro estados: trilho 1,16:1 (1,10 no escuro), `perto` 1,43:1, `abaixo` 1,92:1, contra
   5,60:1 do caso normal. O contorno faz a escala existir (sem ver onde a barra acaba não se lê
   proporção) e a opacidade sai de cima dos dois estados que pedem decisão. O que separa `abaixo` de
   `perto` é o LADO do marco, que agora se vê. Nenhuma cor nova: o âmbar está certo e sobrevive a
   deuteranopia (5,70:1 de separação contra o verde). */
.medidor { display: block; position: relative; width: 100%; min-width: 5rem; height: 8px;
           background: var(--superficie-2); border-radius: 999px; overflow: hidden;
           box-shadow: inset 0 0 0 1px var(--linha-forte); }
.medidor > .barra { position: absolute; inset: 0 auto 0 0; background: var(--marca); border-radius: 999px; }
.medidor > .marco { position: absolute; left: 50%; top: -2px; bottom: -2px; width: 2px;
                    background: var(--tinta); }
.medidor.abaixo > .barra { background: var(--alerta-linha); }
.medidor.perto  > .barra { background: var(--alerta-linha); }
/* A PONTA QUE SE DESFAZ. Quem tem mais do que o dobro do mínimo não é «igual» a quem está quase
   lá — os dois enchem a barra porque a escala para em 2×. A barra que estoura termina desfazendo-se,
   o mesmo recurso de `.rolagem` para dizer «continua»; a que só chegou termina inteira. Era opacidade
   .3, que apagava justamente o estado de folga e o deixava mais fraco que o trilho. */
.medidor.estoura > .barra { background: linear-gradient(90deg, var(--marca) 72%, color-mix(in srgb, var(--marca) 30%, transparent)); }
/* largura para «abaixo do mínimo» caber numa linha: quebrando em duas, a linha da exceção ficava
   mais alta que as outras doze e o ritmo da tabela morria justamente onde o olho devia pousar. */
.celula-medidor { min-width: 9rem; width: 14%; }
/* O QUE A BARRA DIZ, PARA QUEM NÃO A VÊ. No monitor a barra é a leitura e a palavra seria redundante
   — foi ela que saiu daqui. No papel a barra é fundo colorido, e fundo colorido não imprime; no
   leitor de tela ela é um `role="img"` com nome, mas a célula ao lado fica muda. Nos dois casos a
   palavra volta. Não é `display:none`: isso a tiraria do leitor de tela junto. */
.so-fora-da-tela { position: absolute; width: 1px; height: 1px; overflow: hidden;
                   clip-path: inset(50%); white-space: nowrap; }
@media print {
  .so-fora-da-tela { position: static; width: auto; height: auto; clip-path: none; }
  .medidor { display: none; }
}

/* As regras de uma tela, quando existem, são uma LISTA — nunca um parágrafo. Um bloco de 197
   palavras não se lê nem quando alguém abre a dobra para lê-lo: procura-se dentro dele, e não se
   acha. Cada regra numa linha, com a mesma medida de leitura do pé de caixa. */
.regras-lista { margin: var(--e3) 0 0; padding-left: var(--e4); max-width: var(--largura-leitura);
                font-size: var(--t0); line-height: 1.55; color: var(--apagado); }
.regras-lista li + li { margin-top: var(--e2); }
.regras-lista strong, .regras-lista em { color: var(--tinta-2); }

.marca-item { display: inline-flex; align-items: baseline; gap: var(--e2); cursor: pointer; }
.marca-item input { flex: none; }
.estado-modo { background: var(--superficie-2); color: var(--tinta-2); font-family: var(--mono); font-weight: 500; text-transform: none; }
/* a completude da batelada: 'incompleta:' seguido de um chip por falta (templates/_faltas.html) — a mesma cara na mesa, na ficha, na pendência.
   Amarrado ao span do include: o nome .faltas é DELE, e não pode pegar de raspão uma lista de outra coisa. */
span.faltas, .mesa-faltas { display: inline-flex; flex-wrap: wrap; gap: var(--e1); vertical-align: baseline; }

/* --------------------------------------------------------------------------
   7. Layout — topo, navegação, conteúdo, rodapé
   -------------------------------------------------------------------------- */
.pular { position: absolute; left: -999px; top: var(--e2); z-index: 100; background: var(--superficie); color: var(--tinta); padding: var(--e2) var(--e3); border: 1px solid var(--marca); border-radius: var(--r1); }
.pular:focus { left: var(--e2); }
main:focus { outline: none; }

/* o corpo é uma grade: a lateral (navegação) e a página */
body { display: grid; grid-template-columns: var(--largura-lateral) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }
.topo { grid-row: 1 / -1; grid-column: 1; }
.conteudo { grid-column: 2; grid-row: 1; }
.rodape { grid-column: 2; grid-row: 2; }

/* a lateral: marca em cima, os quatro grupos de intenção, quem está logado embaixo */
.topo {
  position: sticky; top: 0; height: 100vh; overflow-y: auto; z-index: 50;
  display: flex; flex-direction: column; gap: var(--e3);
  padding: var(--e4) var(--e3);
  background: var(--superficie);
  border-right: 1px solid var(--linha);
  scrollbar-width: thin;
}
.marca {
  display: inline-flex; align-items: center; gap: var(--e2);
  font-weight: 600; font-size: var(--t3); letter-spacing: -0.01em;
  color: var(--tinta); text-decoration: none; white-space: nowrap;
  padding: var(--e1) var(--e2); margin: 0;
}
.marca:hover { text-decoration: none; }
.marca-sinal { width: 16px; height: 16px; border-radius: 4px 4px 4px 13px; background: var(--marca); flex: none; }
.marca .sep { color: var(--apagado-2); font-weight: 400; }
.marca .produto { font-weight: 400; color: var(--tinta-2); }

/* A BUSCA DE QUALQUER TELA (rodada de layout 2, 2026-09-08): o campo de /rastreabilidade/
   promovido à moldura. Um código de lote ou um número de registro chega de qualquer lugar. */
.busca-global { display: flex; align-items: center; gap: var(--e2); padding: 2px var(--e2) 2px var(--e3);
                border: 1px solid var(--linha); border-radius: var(--r2); background: var(--papel); color: var(--apagado); }
.busca-global .icone { width: 14px; height: 14px; flex: none; }
.busca-global input { border: 0; background: transparent; padding: 5px 0; font-size: var(--t1); min-width: 0; width: 100%; color: var(--tinta); box-shadow: none; }
.busca-global input::placeholder { color: var(--apagado); }
.busca-global:focus-within { border-color: var(--foco); box-shadow: 0 0 0 2px color-mix(in srgb, var(--foco) 30%, transparent); }
.busca-global input:focus { outline: none; }
/* o botão do menu só existe no telefone (ver o bloco ≤ 1000 px) */
.menu-botao { display: none; align-items: center; gap: var(--e2); padding: 6px var(--e3); min-height: 40px;
              border: 1px solid var(--linha-forte); border-radius: var(--r2); font-size: var(--t1); color: var(--tinta-2);
              cursor: pointer; user-select: none; }
.menu-tracos { width: 16px; height: 2px; background: currentColor; border-radius: 1px; box-shadow: 0 -5px 0 currentColor, 0 5px 0 currentColor; }
#menu-aberto:checked ~ .topo .menu-botao { background: var(--marca-suave); border-color: var(--marca); color: var(--marca-tinta); }
#menu-aberto:focus-visible ~ .topo .menu-botao { outline: 2px solid var(--foco); outline-offset: 2px; }

.navegacao { display: flex; flex-direction: column; gap: var(--e3); flex: 1; min-width: 0; }
.navegacao .grupo { display: flex; flex-direction: column; gap: 1px; }
/* OS GRUPOS RECOLHEM (rodada de layout 2): cada grupo é um <details open> e o rótulo é o summary —
   funciona sem JavaScript; o bloco 12 do producao.js só acrescenta a memória do que foi recolhido.
   O <details> fica em `display: block` de propósito: é o único valor em que abrir e fechar se
   comporta igual em todo navegador. O ritmo entre itens vem da margem, não do gap. */
.navegacao details.grupo { display: block; }
.navegacao details.grupo > a + a { margin-top: 1px; }
.navegacao details.grupo > summary + a { margin-top: 2px; }
.navegacao .grupo-rotulo { display: flex; align-items: center; gap: var(--e2); font-size: var(--t-1); text-transform: uppercase;
                           letter-spacing: .08em; color: var(--apagado); padding: var(--e1) var(--e2); margin: 0; white-space: nowrap;
                           list-style: none; cursor: pointer; border-radius: 6px; user-select: none; }
.navegacao .grupo-rotulo::-webkit-details-marker { display: none; }
.navegacao .grupo-rotulo:hover { color: var(--tinta-2); background: var(--superficie-2); }
.navegacao .grupo-rotulo .icone { width: 14px; height: 14px; color: var(--apagado-2); flex: none; }
.navegacao .grupo-rotulo::after { content: "›"; margin-left: auto; font-size: var(--t2); color: var(--apagado-2);
                                  transform: rotate(90deg); transition: transform var(--rapido) var(--curva); }
.navegacao details.grupo:not([open]) > .grupo-rotulo::after { transform: none; }
/* o item recua até o texto do rótulo (ícone + espaço), para as duas colunas de texto alinharem */
.navegacao details.grupo > a { padding-left: calc(var(--e2) + 14px + var(--e2)); }
.navegacao a .icone { width: 14px; height: 14px; color: var(--apagado-2); flex: none; }
.navegacao a[aria-current="page"] .icone { color: var(--marca); }
.navegacao a {
  display: flex; align-items: center; gap: var(--e2);
  padding: 5px var(--e2); border-radius: 6px;
  color: var(--tinta-2); text-decoration: none; font-size: var(--t1);
  border-left: 2px solid transparent;
  transition: color var(--rapido), background var(--rapido);
}
/* Incremento 13: os nomes de tela passaram a dizer o que a pessoa faz, e alguns são compridos de
   propósito ("Nome que ele usou e a Guti não cadastrou"). Na lateral eles QUEBRAM; na barra do topo
   (telas estreitas) continuam numa linha só, porque lá a rolagem é horizontal. */
.navegacao a { white-space: normal; text-wrap: balance; line-height: 1.3; }
.navegacao > .grupo:first-child a { font-weight: 600; }   /* "A fábrica" é destino, não item de grupo */
.navegacao a:hover { color: var(--tinta); background: var(--superficie-2); }
.navegacao a[aria-current="page"] { color: var(--marca-tinta); font-weight: 600; background: var(--marca-suave); border-left-color: var(--marca); border-left-width: 3px; }
.navegacao a:focus-visible { outline: 2px solid var(--foco); outline-offset: -2px; }
.topo .quem { display: flex; align-items: center; gap: var(--e2); color: var(--apagado); font-size: var(--t0); white-space: nowrap; padding: var(--e2) var(--e2) 0; border-top: 1px solid var(--linha-suave); min-width: 0; }
/* anônimo, o base.html emite a div vazia e sobrava um filete de ~16 px flutuando ao lado da marca —
   na PRIMEIRA TELA que qualquer pessoa vê (crítica 2, achado 16; ninguém tinha visto porque
   `capturar_paginas` não cobre as telas de acesso) */
.topo .quem:empty { display: none; }
.topo .quem .nome { color: var(--tinta-2); overflow: hidden; text-overflow: ellipsis; }

/* o recuo do conteúdo em variável, porque a faixa do cabeçalho (abaixo) sangra até ele — e a cada
   ponto de quebra os dois têm de mudar juntos, ou a faixa sai do lugar */
.conteudo { --recuo-x: var(--e6); --recuo-y: var(--e5); width: 100%; max-width: var(--largura-conteudo); min-width: 0; padding: var(--recuo-y) var(--recuo-x) var(--e7); }
.conteudo.bancada { max-width: none; }           /* a mesa usa a largura inteira do laptop */
.conteudo.leitura { max-width: var(--largura-leitura); } /* cartão, boletim: coluna de leitura */

.rodape {
  display: flex; flex-wrap: wrap; gap: var(--e2) var(--e5); align-items: baseline;
  max-width: var(--largura-conteudo); width: 100%;
  padding: var(--e4) var(--e6) var(--e5);
  color: var(--apagado); font-size: var(--t0); border-top: 1px solid var(--linha);
}
.rodape .apurado { margin-left: auto; }

/* cabeçalho de página */
/* A FAIXA (rodada de layout, 2026-09-08). O título de página era uma linha de texto solta em cima
   do papel, igual a qualquer outra; agora é uma faixa de superfície que sangra até as bordas do
   conteúdo, com a ação primária na ponta direita — o mesmo material da barra lateral, para os dois
   lerem como a MOLDURA da página e o papel abaixo como o conteúdo. Só sangra para cima quando é a
   primeira coisa do <main>: com um aviso ou a faixa de ensaio antes, ela começa embaixo deles. */
.cabecalho { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--e3) var(--e5);
  margin: 0 calc(-1 * var(--recuo-x)) var(--e6); padding: var(--e5) var(--recuo-x) var(--e4);
  background: var(--superficie); border-bottom: 1px solid var(--linha); box-shadow: var(--sombra-1); }
.conteudo > .cabecalho:first-child { margin-top: calc(-1 * var(--recuo-y)); }
.cabecalho > .texto { flex: 1 1 24rem; min-width: 0; }
.cabecalho h1 { margin: 0; }
.cabecalho .meta { display: flex; flex-wrap: wrap; gap: var(--e1) 0; margin: var(--e1) 0 0; color: var(--apagado); font-size: var(--t1); }
.cabecalho .meta > *:not(:last-child)::after { content: "·"; margin: 0 .5em; color: var(--apagado-2); }
.cabecalho .meta .codigo { color: var(--tinta-2); }
/* D3 · o código técnico (T-0, T-13, P0, R-05) sai da frente: vai para o FIM da linha de metadados,
   em mono 12 apagado. "T-13" não quer dizer nada para quem abre a tela — e hoje é a primeira coisa
   que ele lê abaixo do título. Uso: <span class="codigo-tecnico">T-13</span>, último filho da .meta. */
.meta .codigo-tecnico, .bloco-meta .codigo-tecnico, .codigo-tecnico { font-family: var(--mono); font-size: var(--t-1); color: var(--apagado); letter-spacing: 0; }
.cabecalho .acoes { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e2); }
.cabecalho .lede, .lede { color: var(--tinta-2); max-width: 60rem; margin: var(--e2) 0 0; }
.cabecalho-secao { display: flex; align-items: baseline; justify-content: space-between; gap: var(--e3); margin: var(--e5) 0 var(--e2); }
.cabecalho-secao h2 { margin: 0; }
.caixa > .cabecalho-secao:first-child { margin-top: 0; }
/* seção de página (fora de caixa/card): um degrau acima do rótulo de caixa — 14 px, 600, tinta-2, sem caixa alta, mais respiro em cima */
/* A ESCADA (rodada de layout, 2026-09-08). A seção media 14 e o item que ela agrupa, 17: o que
   agrupa era mais fraco do que o agrupado, e por isso a tela «obrigava a ler» em vez de deixar
   varrer. Página 28 › seção 20 › item 17 › rótulo 12 — quatro degraus que se distinguem de longe. */
h2.secao, .cabecalho-secao:not(.caixa *, .card *, .faixa *) > h2 { font-size: var(--t4); font-weight: 600; color: var(--tinta); text-transform: none; letter-spacing: -0.01em; line-height: 1.2; }
.cabecalho-secao:not(.caixa *, .card *, .faixa *) { margin-top: var(--e6); }
.cabecalho + .cabecalho-secao, .aviso + .cabecalho-secao, .lede + .cabecalho-secao { margin-top: var(--e4); }

/* grades */
.colunas { display: grid; grid-template-columns: 1fr 1fr; gap: var(--e4) var(--e5); align-items: start; }
.colunas-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--e4) var(--e5); align-items: start; }
.colunas > div > .caixa + .caixa { margin-top: var(--e6); }
.colunas > div > .caixa + .card, .pilha > * + * { margin-top: var(--e4); }
/* D6, o outro lado · quando a caixa é FILHA DIRETA da grade, `.caixa + .caixa` a alcança e a 2ª e a
   3ª coluna nascem 32 px abaixo da 1ª. Medido na crítica 2 (achado 1): /fabrica/ 800/832/832,
   /compra/ 108/140, /mesa/nota/ 108/140, /exportacao/ 108/140, /rastreabilidade/ 339/371/371,
   /mesa/ 108/140 — seis telas nas três áreas, e a área A já tinha resolvido só a sua no CSS local.
   Numa grade quem dá o ritmo é o `gap`; a margem entre irmãos é para a PILHA. */
.colunas > .caixa + .caixa, .colunas > .bloco + .bloco, .colunas > .bloco + .caixa, .colunas > .caixa + .bloco,
.colunas-3 > .caixa + .caixa, .colunas-3 > .bloco + .bloco, .colunas-3 > .bloco + .caixa, .colunas-3 > .caixa + .bloco,
.mesa-bancada > .caixa + .caixa, .mesa-bancada > .bloco + .bloco,
.bancada-grade > .caixa + .caixa, .bancada-grade > .bloco + .bloco { margin-top: 0; }
/* e o contrário (achado 2): depois de uma GRADE, a caixa seguinte não é irmã de `.caixa` e ficava
   colada — em /fabrica/ *Saiu* terminava em y=1051 e *Diferença de consumo* começava em y=1051,
   duas bordas formando um filete duplo na tela mais importante do produto. */
.colunas + .caixa, .colunas + .bloco, .colunas-3 + .caixa, .colunas-3 + .bloco,
.bancada-grade + .caixa, .bancada-grade + .bloco { margin-top: var(--e6); }
/* ...e ANTES da grade também. A enumeração cobria um sentido só, e uma grade depois de uma caixa
   nascia colada: /pagamento-direto/ media 0 px entre a borda de baixo da caixa e a de cima da
   coluna — o mesmo filete duplo que o outro sentido corrigiu. Cada área tapou o buraco do seu
   jeito (--e4 em leitura, --e7 em compra), e é isso que sai junto. */
.caixa + .colunas, .caixa + .colunas-3, .caixa + .grade-cartoes,
.bloco + .colunas, .bloco + .colunas-3, .bloco + .grade-cartoes,
.colunas + .colunas, .colunas + .colunas-3 { margin-top: var(--e6); }
/* a nota de rodapé de uma grade pertence à grade: --e3, não --e6 */
.grade-cartoes + p, .colunas + p, .colunas-3 + p { margin-top: var(--e3); }
.cabecalho-secao + .colunas, .cabecalho-secao + .colunas-3 { margin-top: var(--e2); }
/* item de grade nunca empurra a coluna: quem precisa de largura rola dentro de .rolagem */
.colunas > *, .colunas-3 > *, .bancada-grade > *, .mesa-bancada > * { min-width: 0; }

/* A GRADE DE CARTÕES (2026-09-05) · quantos couberem, do mesmo tamanho, e uma coluna no telefone.
   Não é `.colunas-3`: o número de cartões varia com os dados (um por insumo), então quem decide
   quantas colunas é a largura, não o template. `min(100%, 17rem)` é o que impede a grade de
   estourar uma coluna estreita — `minmax(17rem, 1fr)` sozinho não encolhe abaixo de 17rem.
   `stretch` (o padrão) é de propósito: numa fileira de cartões as bordas têm de bater. */
/* `stretch` foi decidido em 2026-09-05, quando o cartão tinha duas linhas e o desalinho custava
   40 px. Com «Diferença de consumo» listando 13 insumos o preço virou 1.436 px de branco dentro de
   *Comprar* e 1.006 dentro de *Na câmara*, na primeira tela do app. A altura da página não muda
   (quem manda é o cartão mais alto): o que sai é o vazio. */
.grade-cartoes { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); gap: var(--e4) var(--e5); align-items: start; }
.grade-cartoes > * { min-width: 0; }
/* numa grade quem dá o ritmo é o `gap` (a mesma regra das outras quatro grades, ver acima) */
.grade-cartoes > .caixa + .caixa, .grade-cartoes > .bloco + .bloco,
.grade-cartoes > .bloco + .caixa, .grade-cartoes > .caixa + .bloco { margin-top: 0; }
.grade-cartoes + .caixa, .grade-cartoes + .bloco, .grade-cartoes + .grade-cartoes,
.grade-cartoes + .cabecalho-secao { margin-top: var(--e6); }
.cabecalho-secao + .grade-cartoes { margin-top: var(--e2); }
.bancada-grade { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: var(--e5); align-items: start; }
.fixo { position: sticky; top: var(--e4); }

/* --------------------------------------------------------------------------
   8. Superfícies — caixa, card
   -------------------------------------------------------------------------- */
.caixa { min-width: 0; background: var(--superficie); border: 1px solid var(--linha); border-radius: var(--r2); padding: var(--e4) var(--e5); box-shadow: var(--realce-superficie), var(--sombra-1); }
.caixa + .caixa { margin-top: var(--e6); }   /* D6 · --e4 dentro, --e6 entre: o ritmo é o que diz "isto acabou" */
.caixa > :last-child, .card > :last-child { margin-bottom: 0; }
/* (a caixa não rola mais em silêncio: tabela de colunas vai dentro de .rolagem, que tem barra e sombra) */
.card { background: var(--superficie); border: 1px solid var(--linha); border-radius: var(--r2); padding: var(--e3) var(--e4); margin-bottom: var(--e3); }
.card.novo { border-style: dashed; background: color-mix(in srgb, var(--superficie) 60%, var(--papel)); }
.card.velho { color: var(--apagado); }
.card:target, .card.foco { outline: 2px solid var(--alerta-linha); outline-offset: 2px; }
.card > div:first-child > strong:first-child, .card .card-titulo { font-weight: 600; }
.card .card-meta, .card > .apagado.pequeno { color: var(--apagado); font-size: var(--t0); margin-top: var(--e1); }
fieldset.card { padding-top: var(--e2); }
fieldset.card > legend { padding: 0 var(--e1); margin-left: calc(-1 * var(--e1)); font-size: var(--t1); }

/* --- O BLOCO (ciclo 2, D2) -------------------------------------------------
   A caixa cujo título é o ASSUNTO — um insumo, um pedido, um fornecedor —, não uma categoria.
   .caixa é o painel (o título diz o que a caixa contém: CONSUMOS, PROCEDÊNCIA);
   .bloco é o item (o título diz de quem a caixa fala: "Maltodextrina", "pedido 12345678-0004").
   HTML mínimo:
     <section class="bloco" id="…">
       <div class="bloco-cabeca"><h2>Maltodextrina</h2><span class="estado estado-em-baixa">em baixa</span></div>
       <p class="bloco-meta"><span>pedir <span class="num principal">400 kg</span></span><span>até 12/09</span></p>
       …corpo livre: tabela, .kv, parágrafo…
       <div class="bloco-acoes"><button type="submit">Criar o pedido</button></div>
       <p class="pe-caixa">a frase de ensino, uma por bloco.</p>
     </section>                                                                */
.bloco { min-width: 0; background: var(--superficie); border: 1px solid var(--linha); border-radius: var(--r2); padding: var(--e4) var(--e5); box-shadow: var(--realce-superficie), var(--sombra-1); }
.bloco > :last-child { margin-bottom: 0; }
/* D6 · duas distâncias: --e4 dentro do bloco, --e6 entre blocos */
.bloco + .bloco, .bloco + .caixa, .caixa + .bloco { margin-top: var(--e6); }
.bloco-cabeca { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--e1) var(--e3); margin-bottom: var(--e2); }
.bloco-cabeca > h2 { flex: 1 1 auto; min-width: 0; }            /* o assunto: 17/600 tinta (ver §4) */
.bloco-cabeca > .estado, .bloco-cabeca > .nota { flex: none; }  /* o estado à direita, alinhado à cabeça */
.bloco-meta { display: flex; flex-wrap: wrap; gap: var(--e1) 0; margin: 0 0 var(--e3); color: var(--apagado); font-size: var(--t0); }
.bloco-meta > *:not(:last-child)::after { content: "·"; margin: 0 .5em; color: var(--apagado-2); }
.bloco-meta .num, .bloco-meta strong { color: var(--tinta-2); }
.bloco-acoes { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e2) var(--e3); margin-top: var(--e4); }

/* D1/D7 · o pé da caixa: TODA prosa explicativa, 13 px apagado, uma por caixa, depois de um hairline.
   Nenhuma tela abre com parágrafo; a explicação fica embaixo do dado que ela explica. */
.pe-caixa {
  margin: var(--e5) 0 0; padding-top: var(--e3); border-top: 1px solid var(--linha-suave);
  font-size: var(--t0); line-height: 1.55; color: var(--apagado);
  /* MEDIDA DE LEITURA (crítica 2, achado 5) · o pé tinha SEIS larguras: 672, 736, 1111, 1161, 1176 e
     26 rem — as três áreas inventaram três respostas a um pedido que o sistema não atendeu (pendência
     da área C). A 1176 px são ~150 caracteres por linha, e em /compra/sugestao/ o filete media 736
     sob blocos de 1176 e acabava no meio da página. Uma medida só, e é do sistema. */
  max-width: var(--largura-leitura);
}
/* O respiro antes do pé é --e7 quando a caixa tem CORPO DE VERDADE (tabela, formulário, lista) e
   --e5 quando o corpo é uma frase (crítica 2, achado 9): em /pendencias/, quatro caixas de conteúdo
   idêntico mediam 91 / 91 / 192 / 219 px para dizer a mesma coisa — "muito ar dentro, pouco fora". */
.caixa:has(> .rolagem) > .pe-caixa, .bloco:has(> .rolagem) > .pe-caixa,
.caixa:has(> form) > .pe-caixa, .bloco:has(> form) > .pe-caixa,
.caixa:has(> table) > .pe-caixa, .bloco:has(> table) > .pe-caixa,
.caixa:has(> dl) > .pe-caixa, .bloco:has(> dl) > .pe-caixa,
.caixa:has(> ol) > .pe-caixa, .bloco:has(> ol) > .pe-caixa,
.caixa:has(> ul) > .pe-caixa, .bloco:has(> ul) > .pe-caixa,
.caixa:has(> pre) > .pe-caixa, .bloco:has(> pre) > .pe-caixa { margin-top: var(--e7); }
/* ...mas um corpo que é um ESTADO VAZIO continua sendo uma frase, mesmo dentro de <ul> ou <table>:
   em /pendencias/, *Dosagens de insumo crítico sem aferição · 0* era uma caixa de 219 px para dizer
   "nenhuma", ao lado de uma de 91 px que dizia o mesmo. */
.caixa:has(> .vazio) > .pe-caixa, .bloco:has(> .vazio) > .pe-caixa,
.caixa:has(> ul > li.vazio) > .pe-caixa, .bloco:has(> ul > li.vazio) > .pe-caixa,
.caixa:has(> ol > li.vazio) > .pe-caixa, .bloco:has(> ol > li.vazio) > .pe-caixa,
.caixa:has(td.vazio) > .pe-caixa, .bloco:has(td.vazio) > .pe-caixa { margin-top: var(--e5); }
/* ...e um FORMULÁRIO DE UMA LINHA é um corpo de uma linha, não um corpo de verdade (2026-09-07,
   /contagem/): a caixa de *Abrir uma contagem* perdeu o mapa do processo que morava dentro dela e
   ficou com 48 px de vão entre o único campo e o filete. A regra acima já dizia o que fazer com
   corpo que é uma frase; `form.linha-unica` declara justamente isso na marcação. */
.caixa:has(> form.linha-unica) > .pe-caixa,
.bloco:has(> form.linha-unica) > .pe-caixa { margin-top: var(--e5); }
.pe-caixa strong, .pe-caixa em { color: var(--tinta-2); }
.pe-caixa a { color: var(--marca); }
.legenda-naturezas { margin-top: var(--e7); }

/* D4 · A PAUTA — o único bloco com faixa de superfície, porque é o único que exige decisão.
   No papel a faixa vira um fio preto e a hierarquia sobrevive inteira (nenhuma cor nova).
   HTML mínimo:
     <section class="bloco pauta" id="faltando">
       <div class="bloco-cabeca"><h2>Hoje pede decisão</h2><span class="nota">…</span></div>
       <ul class="pauta">
         <li class="pauta-item"><span class="pauta-o-que">Maltodextrina <strong>sem mínimo definido</strong></span>
             <a class="pauta-onde" href="/minimos/">dizer o mínimo</a></li>
       </ul>
     </section>                                                                */
.bloco.pauta { border-top: 2px solid var(--linha-forte); padding-top: 0; }
.bloco.pauta > .bloco-cabeca {
  margin: 0 calc(-1 * var(--e5)) var(--e3); padding: var(--e2) var(--e5);
  background: var(--superficie-2); border-bottom: 1px solid var(--linha);
}
/* a PAUTA VAZIA continua sendo um bloco — "nada exige decisão hoje" é informação — mas perde a faixa,
   porque a faixa é o sinal de que há decisão a tomar (§3 da direção). Era um modificador local da
   área de leitura (`.leitura-sem-pauta`); é comportamento do componente, e por isso mora aqui. */
.bloco.pauta:has(> .vazio) { border-top-color: var(--linha); }
.bloco.pauta:has(> .vazio) > .bloco-cabeca { background: none; border-bottom-color: var(--linha-suave); }
ul.pauta, ol.pauta { list-style: none; padding: 0; margin: 0; }
.pauta-item {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--e1) var(--e4);
  margin: 0; padding: var(--e2) 0; border-top: 1px solid var(--linha-suave);
}
.pauta-item:first-child { border-top: 0; }
.pauta-o-que { flex: 1 1 20rem; min-width: 0; font-size: var(--t2); }   /* uma frase, verbo na frente */
.pauta-o-que strong { font-weight: 600; }
.pauta-onde { flex: none; font-size: var(--t1); white-space: nowrap; }   /* o link à direita: onde se resolve */
.pauta-item .apagado, .pauta-item .nota { display: block; flex-basis: 100%; }

/* --- O CARTÃO (2026-09-05) -------------------------------------------------
   Pedido do dono: "quero a página inicial sendo representada por cards". `.cartao` é um
   MODIFICADOR de `.caixa` ou de `.bloco` — não um componente novo —, e não mexe na gramática do
   título (decisão 17): nome próprio (um insumo) continua `.bloco` com o assunto em 17/600; verbo
   ou categoria (ENTROU, COMPRAR) continua `.caixa` com o rótulo de 12 em caixa alta. O que ele
   muda é o que vem DEPOIS do título: o número primeiro, grande, com a natureza colada.
   Cuidado com os vizinhos de nome: `.card` é o card proposto da mesa e `.cartao-diario` é o cartão
   do dia (uma `.caixa`); nenhum dos dois tem relação com este.
   HTML mínimo — o que o app usa DE VERDADE (fabrica.html + _num.html), e não o que este comentário
   ensinava até 2026-09-08 com oito classes que não estilizavam nada:
     <section class="caixa cartao">
       <div class="cabecalho-secao"><h2>Entrou</h2><span class="nota">esta semana</span></div>
       {% include "_num.html" with rotulo="saldo pela receita" res=l.saldo %}   ← .cartao-n: rótulo + valor + apoio
       <div class="cartao-n"><span class="rotulo">itens</span><span class="cartao-conta">4</span></div>
       <ul class="lista-limpa cartao-itens">…</ul>
     </section>                                                              */
.cartao { display: flex; flex-direction: column; gap: var(--e2); border-radius: var(--r3); }
/* O NÚMERO DO CARTÃO É 32 (--t6), e o token dizia isso desde o ciclo 2 sem que regra nenhuma o
   usasse: o cartão saía com o mesmo 24 da ficha, e um cartão cujo número não é maior que o de uma
   linha de tabela é uma caixa com um número dentro. A cabeça ganha um fio embaixo: título, número
   e pé viram três andares em vez de três linhas. */
.cartao .cartao-n > .valor { font-size: var(--t6); line-height: 1.05; letter-spacing: -0.015em; }
.cartao > .bloco-cabeca, .cartao > .cabecalho-secao { padding-bottom: var(--e2); border-bottom: 1px solid var(--linha-suave); }
/* o pé desce para o fim: numa fileira de cartões de alturas iguais, as frases ficam alinhadas
   embaixo em vez de flutuarem no meio do vazio. (Vence os `:has` do pé por contagem de classes.) */
.caixa.cartao > .pe-caixa, .bloco.cartao > .pe-caixa { margin-top: auto; }
.cartao > .bloco-cabeca, .cartao > .cabecalho-secao { margin-bottom: 0; flex-wrap: wrap; }
/* o rótulo do cartão não quebra em duas linhas para caber ao lado da nota: quem desce é a nota
   (medido em *Diferença de consumo*, cujo rótulo virava duas linhas dentro de uma coluna de 340 px) */
.cartao > .cabecalho-secao > h2 { flex: 0 0 auto; }
.cartao > p, .cartao > ul { margin-top: 0; margin-bottom: 0; }
/* A GRAMÁTICA MORTA SAIU (2026-09-08, time de design). `.cartao-medida`, `.cartao-num`,
   `.cartao-pares/-par/-rotulo/-valor`, `.cartao-motivo` e `.cartao-de-que` não apareciam em template
   nenhum: quem desenha o destaque é `_num.html` com `.cartao-n` (§19.1). Com `.cartao .num.principal`
   fora, o `.num.principal` das listas de cartão volta sozinho a --t3 (17 px), que é o que D1 manda —
   antes ele saltava para 24 dentro de uma `.cartao-itens` de 14, empatado com a contagem logo acima.
   A CONTAGEM NÃO É GRANDEZA (§15.2, decisão que nunca tinha chegado ao CSS): --t4 em peso 400, para
   não ocupar o corpo do número que tem unidade e natureza. */
.cartao-conta { font-size: var(--t4); font-weight: 400; font-variant-numeric: tabular-nums; letter-spacing: 0; }
/* a lista de itens do cartão (é `.lista-limpa` com o valor à direita): o que não se pode somar */
.cartao-itens { margin-top: var(--e2); font-size: var(--t1); }
.cartao-itens > li { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--e1) var(--e3); }
.cartao-itens .cartao-o-que { min-width: 0; overflow-wrap: anywhere; }
.cartao-itens .sub { display: block; flex-basis: 100%; color: var(--apagado); font-size: var(--t0); }

/* o texto bruto: papel, nenhum caractere se perde */
pre.bruto {
  white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word;
  font: inherit; font-size: var(--t2); line-height: 1.8; margin: 0;
  padding: var(--e3) var(--e4); background: var(--superficie-2);
  border-left: 3px solid var(--linha-forte); border-radius: 0 var(--r1) var(--r1) 0;
}
mark.reg {
  background: var(--realce); color: inherit; border-bottom: 2px solid var(--realce-linha);
  padding: .05em .1em; border-radius: 2px; cursor: pointer;
  transition: background var(--rapido);
}
mark.reg:hover { background: color-mix(in srgb, var(--realce) 70%, var(--realce-linha)); }
mark.reg.foco { outline: 2px solid var(--realce-linha); outline-offset: 1px; }

/* a faixa de trechos não interpretados */
.faixa { margin-top: var(--e4); }
.faixa ul { list-style: none; padding: 0; margin: 0 0 var(--e2); display: flex; flex-wrap: wrap; gap: var(--e2); }
.faixa li { margin: 0; padding: 2px 10px; border: 1px dashed var(--linha-forte); border-radius: var(--r-pilula); font-size: var(--t1); background: var(--superficie); }
.faixa .pos { color: var(--apagado); font-size: var(--t-1); margin-left: .4em; font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   9. Tabelas
   -------------------------------------------------------------------------- */
table { border-collapse: collapse; border-spacing: 0; }
table.proc { width: 100%; font-size: var(--t1); }
/* A LISTA DE DEFINIÇÃO NÃO SE LÊ LARGA (2026-09-10, o dono: «essa página tá ruim a leitura»). Numa
   caixa de 1.000 px, o rótulo fica na borda esquerda, o valor começa a 40% e o resto da linha é
   vazio: o olho atravessa um vão para casar duas coisas que são um par. Trinta e oito rem é onde o
   par ainda se lê de uma vez — e é inofensivo nas fichas estreitas, que já estão abaixo disso.
   `:not(:has(th + th))` deixa de fora as tabelas de VÁRIAS colunas que também usam `.proc` (a
   comparação da retificação, a prévia da retroação): aquelas precisam da largura inteira. */
table.proc:not(:has(th + th)) { max-width: 38rem; }
table.proc th { text-align: left; color: var(--apagado); font-weight: 500; padding: .35rem .8rem .35rem 0; white-space: nowrap; vertical-align: top; }
table.proc td { padding: .35rem .8rem .35rem 0; vertical-align: top; overflow-wrap: anywhere; }
table.proc td .codigo, .tabela td .codigo { overflow-wrap: normal; white-space: nowrap; }   /* código de lote fica inteiro: a tabela rola, o código não quebra no meio */
table.proc tr + tr > td, table.proc tr + tr > th { border-top: 1px solid var(--linha-suave); }
table.proc tr:first-child:has(th + th) > th { border-bottom: 1px solid var(--linha); font-size: var(--t-1); text-transform: uppercase; letter-spacing: .06em; padding-bottom: .4rem; }
table.proc tr:first-child:has(th + th) + tr > td { border-top: 0; }
table.proc td:last-child, table.proc th:last-child { padding-right: 0; }
table.proc tr.apagado td { color: var(--apagado); }
table.proc tr.total td, table.proc tr.num td { font-weight: 600; background: var(--superficie-2); }
table.proc tr.negativa td { background: var(--erro-suave); }
table.proc td.n, table.proc th.n { text-align: right; font-variant-numeric: tabular-nums; }
table.proc .sub { display: block; color: var(--apagado); font-size: var(--t0); font-weight: 400; margin-top: 2px; }

/* a tabela de painel: com thead, zebra e números à direita */
.tabela { width: 100%; font-size: var(--t1); }
.tabela thead th { text-align: left; font-size: var(--t-1); text-transform: uppercase; letter-spacing: .06em; color: var(--apagado); font-weight: 500; padding: .45rem .8rem .45rem 0; border-bottom: 1px solid var(--linha); white-space: nowrap; }
/* dentro de uma COLUNA da grade o cabeçalho quebra: `nowrap` num rótulo de quatro palavras faz a
   tabela medir mais que a coluna, e o boletim mostrava `DESVIO CONTRA O ESPERA` — palavra partida —
   com 400 px de página vazia ao lado (crítica 2, achado 10). O número continua `nowrap`; o rótulo,
   que é palavra e não número, quebra. */
.colunas .tabela thead th, .colunas-3 .tabela thead th { white-space: normal; }
.tabela tbody td { padding: .5rem .8rem .5rem 0; vertical-align: top; border-top: 1px solid var(--linha-suave); }
.tabela tbody tr:first-child td { border-top: 0; }
.tabela tbody tr:last-child td { border-bottom: 1px solid var(--linha-suave); }
.tabela tbody tr:hover td { background: color-mix(in srgb, var(--superficie-2) 100%, transparent); }
/* a tabela ganha uma FAIXA de cabeçalho e um respiro nas pontas (rodada de layout): sem eles, o
   thead era uma linha de texto cinza e a primeira coluna encostava na borda da caixa */
.tabela thead th { background: var(--superficie-2); border-bottom: 1px solid var(--linha); }
.tabela thead th:first-child, .tabela tbody td:first-child { padding-left: .6rem; }
.tabela thead th:first-child { border-top-left-radius: var(--r1); }
.tabela thead th:last-child { border-top-right-radius: var(--r1); }
.tabela td:last-child, .tabela th:last-child { padding-right: .6rem; }
/* zebra suave: a linha 14 e a linha 15 de /saldos/ se distinguem sem régua no dedo. Vem ANTES do
   hover, que tem a mesma especificidade e precisa ganhar por ordem. */
.tabela tbody tr:nth-child(even) > td { background: color-mix(in srgb, var(--superficie-2) 45%, transparent); }
.tabela .n { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.tabela tr.total td { font-weight: 600; background: var(--superficie-2); }
.tabela tr.negativa td, .tabela tr.total.negativa td { background: var(--erro-suave); }   /* negativo vence total: um total negativo é a linha mais importante da tela */
.tabela tr.velho td, .tabela tr.velho td a { color: var(--apagado); }                     /* linha superada (movimento cancelado por contrário) */
.tabela .sub { display: block; color: var(--apagado); font-size: var(--t0); font-weight: 400; }
/* a natureza no CABEÇALHO (saldos.html, onde a régua da tabela é declarada uma vez): `.tabela .sub`
   (0,2,0) a punha um degrau ACIMA do th e vencia `.nat-declarado` (0,1,0), e o `text-transform` do
   th a deixava em caixa alta — uma forma que ela não toma em lugar nenhum do app, e maior que o
   rótulo que qualifica. Aqui ela volta ao vocabulário: 12 px, minúscula, na cor da natureza. */
.tabela thead th .sub { font-size: var(--t-1); }
.tabela thead th .nat { font-size: var(--t-1); text-transform: none; letter-spacing: 0; }
.tabela thead th .nat.nat-aferido   { color: var(--nat-aferido); }
.tabela thead th .nat.nat-contado   { color: var(--nat-contado); }
.tabela thead th .nat.nat-declarado { color: var(--nat-declarado); }
.tabela thead th .nat.nat-estimado  { color: var(--nat-estimado); }
.tabela thead th .nat.nat-calculado { color: var(--nat-calculado); }
/* a coluna numérica é `nowrap`, e isso está certo para o NÚMERO. Mas quando a célula é `indisponível`
   a linha de baixo é uma FRASE (o motivo), e frase que não quebra estoura a caixa: medido, /fabrica/
   ia a 631 px numa janela de 375. A área B corrigiu no CSS dela; a regra vale para qualquer área que
   ponha um motivo dentro de uma célula numérica, e por isso subiu para o sistema (pedido da área B). */
.tabela td.n .sub, table.proc td.n .sub { white-space: normal; }
/* rolagem horizontal com sinal: barra fina sempre visível e sombras nas bordas (scroll shadows) — vale para toda tabela do produto */
.rolagem {
  overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: thin;
  background:
    linear-gradient(90deg, var(--superficie) 30%, transparent) left / 40px 100% no-repeat,
    linear-gradient(270deg, var(--superficie) 30%, transparent) right / 40px 100% no-repeat,
    linear-gradient(90deg, rgba(28, 27, 24, .14), transparent) left / 14px 100% no-repeat,
    linear-gradient(270deg, rgba(28, 27, 24, .14), transparent) right / 14px 100% no-repeat;
  background-attachment: local, local, scroll, scroll;
}
.rolagem::-webkit-scrollbar { height: 8px; }
.rolagem::-webkit-scrollbar-thumb { background: var(--linha-forte); border-radius: 4px; }
.rolagem::-webkit-scrollbar-track { background: var(--superficie-2); }
@media (prefers-color-scheme: dark) {
  .rolagem { background:
    linear-gradient(90deg, var(--superficie) 30%, transparent) left / 40px 100% no-repeat,
    linear-gradient(270deg, var(--superficie) 30%, transparent) right / 40px 100% no-repeat,
    linear-gradient(90deg, rgba(0, 0, 0, .5), transparent) left / 14px 100% no-repeat,
    linear-gradient(270deg, rgba(0, 0, 0, .5), transparent) right / 14px 100% no-repeat;
    background-attachment: local, local, scroll, scroll; }
  /* a faixa da pauta é --superficie-2 sobre --superficie: 1,21:1 no claro e só 1,10:1 no escuro
     (crítica 2, achado 17). D4 escolheu a superfície em vez de uma sexta cor justamente para marcar
     o bloco que exige decisão — no escuro ela ficava na metade da força. --superficie-3 devolve
     1,23:1, a mesma separação do claro, sem cor nova. */
  .bloco.pauta > .bloco-cabeca { background: var(--superficie-3); }
  .bloco.pauta:has(> .vazio) > .bloco-cabeca { background: none; }
}

/* --- A TABELA-LISTA (ciclo 2, R1/R2) ---------------------------------------
   O celular não é a tela pequena: é a tela EM PÉ. Abaixo de 700 px a tabela marcada com .lista
   deixa de rolar para o lado e vira uma pilha de blocos — uma linha de tabela = um bloco, rótulo à
   esquerda em 13 apagado, valor à direita. Medido: a 500 px, /saldos/ escondia 506 px de linha
   dentro de uma caixa de 427, e o leitor não sabia o que estava perdendo.
   Como se usa: a classe .lista na tabela e data-rotulo em cada <td> (o mesmo texto do <th>):
     <div class="rolagem"><table class="tabela lista">
       <thead><tr><th>insumo</th><th>saldo</th><th>situação</th></tr></thead>
       <tbody><tr>
         <td>Maltodextrina</td>                                        <!-- 1ª célula = o assunto, sem rótulo -->
         <td data-rotulo="saldo"><span class="num principal">-267 kg</span> <span class="nat nat-declarado">declarado</span></td>
         <td data-rotulo="situação"><span class="estado estado-em-baixa">em baixa</span></td>
       </tr></tbody>
     </table></div>
   Vale para as tabelas que o telefone realmente lê (§4 R1 da direção); as outras seguem com .rolagem.
   Célula sem data-rotulo e célula com colspan viram bloco inteiro, sem rótulo.
   É `@media screen`: NO PAPEL a lista volta a ser tabela, sempre (§10 do mapa de trabalho).       */
@media screen and (max-width: 700px) {
  .rolagem:has(> .tabela.lista) { overflow: visible; background: none; }
  .tabela.lista { display: block; font-size: var(--t2); }
  .tabela.lista thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); }
  .tabela.lista tbody, .tabela.lista tr, .tabela.lista td { display: block; }
  .tabela.lista tbody tr {
    border: 1px solid var(--linha); border-radius: var(--r2); padding: var(--e2) var(--e3);
    margin-bottom: var(--e2); background: var(--superficie);
  }
  .tabela.lista tbody tr:hover td { background: transparent; }
  .tabela.lista tbody td { border-top: 1px solid var(--linha-suave); padding: .35rem 0; text-align: left; }
  .tabela.lista tbody td:first-child { border-top: 0; padding-top: 0; font-weight: 600; }   /* o assunto da linha */
  .tabela.lista tbody td:last-child { padding-bottom: 0; }
  /* rótulo à esquerda, valor à direita — e o valor NUNCA encolhe (R2): quando não cabe ao lado da
     natureza, a natureza desce inteira, em palavra. Nada é truncado, abreviado nem virou só cor. */
  /* o rótulo flutua à esquerda e o valor segue em FLUXO INLINE à direita: assim .num e .nat continuam
     no mesmo fluxo — se não couberem lado a lado, a natureza desce inteira, colada, e à direita.
     (grade não serve aqui: cada filho viraria uma célula e o par se separaria.) */
  .tabela.lista tbody td[data-rotulo] { display: flow-root; text-align: right; }
  .tabela.lista tbody td[data-rotulo]::before {
    content: attr(data-rotulo); float: left; max-width: 52%; margin-right: var(--e3);
    text-align: left; color: var(--apagado); font-size: var(--t0); font-weight: 400;
  }
  .tabela.lista tbody td.n { text-align: right; }
  .tabela.lista tbody td[colspan] { display: block; text-align: left; }
  .tabela.lista tbody td[colspan]::before { content: none; }
  .tabela.lista tbody td .sub { text-align: right; }
  .tabela.lista tbody tr.negativa { border-color: var(--erro); }
  .tabela.lista tbody tr.negativa td, .tabela.lista tbody tr.total.negativa td { background: transparent; }
  .tabela.lista tbody tr.negativa td:first-child::after { content: " (negativo)"; font-weight: 400; color: var(--erro); font-size: var(--t0); }
  .tabela.lista tbody tr.total { border-color: var(--linha-forte); }
  .tabela.lista tbody tr.velho { opacity: .8; }
  .tabela.lista tbody td.vazio { border: 0; }
  .tabela.lista .so-tela-larga { display: none; }
}

/* --------------------------------------------------------------------------
   10. Avisos, mensagens, vazios
   -------------------------------------------------------------------------- */
.aviso {
  border-left: 4px solid var(--alerta-linha); background: var(--alerta-suave); color: var(--alerta-tinta);
  padding: var(--e2) var(--e4); border-radius: 0 var(--r1) var(--r1) 0; margin: var(--e3) 0;
}
.aviso a { color: inherit; }
.aviso.erro { border-left-color: var(--erro); background: var(--erro-suave); color: var(--erro-tinta); }
.aviso.ok { border-left-color: var(--marca); background: var(--ok-suave); color: var(--marca-tinta); }
.aviso.info { border-left-color: var(--info); background: var(--info-suave); color: var(--info-tinta); }
.aviso.neutro { border-left-color: var(--linha-forte); background: var(--superficie-2); color: var(--tinta-2); }
p.aviso { margin: var(--e3) 0; }

/* mensagens flash e mensagens inline (.msg é o nome antigo, mantido) */
.flashes { margin: 0 0 var(--e4); display: grid; gap: var(--e2); }
.flash, .msg {
  display: flex; align-items: flex-start; gap: var(--e2);
  padding: var(--e2) var(--e3); border-radius: var(--r1); border: 1px solid transparent;
  font-size: var(--t1); margin: 0 0 var(--e2);
}
.flash .icone { flex: none; margin-top: .15em; }
.flash .texto { flex: 1; }
.flash-fechar { flex: none; appearance: none; background: transparent; border: 0; color: inherit; padding: 0 var(--e1); line-height: 1; cursor: pointer; opacity: .7; font-size: 1.1em; }
.flash-fechar:hover { opacity: 1; background: color-mix(in srgb, currentColor 12%, transparent); }
.flash-success, .msg.success { background: var(--ok-suave); color: var(--marca-tinta); border-color: color-mix(in srgb, var(--marca) 30%, transparent); }
.flash-error, .msg.error { background: var(--erro-suave); color: var(--erro-tinta); border-color: color-mix(in srgb, var(--erro) 35%, transparent); }
.flash-warning, .msg.warning { background: var(--alerta-suave); color: var(--alerta-tinta); border-color: var(--alerta-linha); }
.flash-info, .msg.info, .flash-debug { background: var(--info-suave); color: var(--info-tinta); border-color: color-mix(in srgb, var(--info) 30%, transparent); }
li.msg { list-style-position: inside; }

/* o aviso que não pode passar despercebido (sexta linha do cartão, marca de piloto) */
.alarme {
  display: flex; gap: var(--e3); align-items: flex-start;
  border: 2px solid var(--erro); background: var(--erro-suave); color: var(--erro-tinta);
  padding: var(--e3) var(--e4); border-radius: var(--r2); margin: var(--e3) 0; font-weight: 500;
}
.alarme .icone { color: var(--erro); flex: none; margin-top: .1em; }

/* (os quatro resultados de "em baixa" (C-30) moram agora no §6, junto com as outras famílias de estado;
   a redefinição de .estado-indisponivel que veio com eles foi desfeita — indisponível é o cinza tracejado
   de sempre. A lista de providências do /fabrica/ virou o componente .pauta, abaixo; o que era exceção
   local da área de leitura (.faltas .falta, .tabela tr.leitura-linha) foi para areas/leitura.css.) */

/* a marca de ensaio (docs/20 §4.6, Incremento 8): do conjunto, em palavra, e sobrevive ao recorte.
   Não usa cor de natureza nem o vermelho de problema: é tinta sobre listras — um carimbo, não um alerta. */
.ensaio-faixa {
  position: relative; display: flex; flex-wrap: wrap; gap: var(--e1) var(--e4); align-items: baseline;
  margin: 0 0 var(--e4); padding: var(--e3) var(--e4) var(--e3) calc(var(--e4) + 14px);
  border: 2px solid var(--tinta); border-radius: var(--r2); background: var(--fundo);
  color: var(--tinta); font-size: var(--t1); overflow: hidden;
}
.ensaio-faixa::before {          /* as listras: carimbo, não alerta */
  content: ""; position: absolute; inset: 0 auto 0 0; width: 12px;
  background: repeating-linear-gradient(135deg, var(--tinta) 0 5px, transparent 5px 10px);
}
.ensaio-faixa strong { font-weight: 700; letter-spacing: .02em; }
.ensaio-faixa span { color: var(--tinta-2); }
.ensaio-etiqueta {
  position: fixed; right: var(--e3); bottom: var(--e3); z-index: 60; pointer-events: none;
  padding: var(--e1) var(--e3); border: 2px solid var(--tinta); border-radius: var(--r1);
  background: var(--fundo); color: var(--tinta); font: 700 var(--t0)/1 var(--mono); letter-spacing: .12em;
}
.ensaio-rodape { font-weight: 700; color: var(--tinta); }

/* estado vazio: uma frase, nunca um vazio */
.vazio, .vazio-c { color: var(--apagado); padding: var(--e4); text-align: left; border: 1px dashed var(--linha-forte); border-radius: var(--r2); background: transparent; }
.vazio.curto { border: 0; padding: var(--e2) 0; }
td.vazio, li.vazio { border: 0; padding: .35rem 0; }

/* --------------------------------------------------------------------------
   11. Formulários — não parecem admin de banco
   -------------------------------------------------------------------------- */
form.linha, .grade { display: grid; grid-template-columns: 1fr 1fr; gap: var(--e3) var(--e4); align-items: end; }
.grade-3 { grid-template-columns: repeat(3, 1fr); }
form.linha label, .campo { display: flex; flex-direction: column; gap: var(--e1); font-size: var(--t0); color: var(--apagado); min-width: 0; align-self: start; }
/* item de grade nunca empurra a coluna (a mesma regra das outras cinco grades, §7). Só o `label`
   tinha `min-width: 0`; `fieldset`, `details` e `.acoes-form` são filhos diretos e não encolhiam —
   a `.mesa-itens` dentro do «o que ele disse ter gastado» levava a página a 462 px numa janela
   de 375. Quem precisa de largura rola dentro de `.rolagem`, que é onde ela deve rolar. */
form.linha > *, .grade > *, .grade-3 > * { min-width: 0; }
form.linha label > .nota, .campo > .nota { display: block; line-height: 1.4; }   /* ajuda do campo: a linha de baixo do label */
form.linha label > span, .campo > span { display: block; }
form.linha label.larga, .campo.larga, form.linha .larga, .grade .larga { grid-column: 1 / -1; }
form.linha label > input, form.linha label > select, form.linha label > textarea { color: var(--tinta); }
form.linha fieldset { display: block; }
fieldset.larga { grid-column: 1 / -1; }
/* legend = rótulo de seção do formulário: 12 px, caixa alta, 600 — um estilo só, em toda área */
form.linha fieldset legend, fieldset > legend { font-size: var(--t-1); font-weight: 600; text-transform: uppercase; letter-spacing: .08em; color: var(--apagado); padding: 0 var(--e1); margin-bottom: var(--e2); }
form.linha fieldset[style] { padding: var(--e2) var(--e3) var(--e3); }
form.linha .num { color: var(--tinta); }

input, select, textarea {
  font: inherit; font-size: var(--t2); color: var(--tinta);
  padding: .4rem .6rem; border: 1px solid var(--linha-forte); border-radius: 6px;
  background: var(--superficie); min-width: 0; width: 100%;
  transition: border-color var(--rapido), box-shadow var(--rapido);
}
input[type="checkbox"], input[type="radio"] { width: auto; padding: 0; margin: 0 .4em 0 0; accent-color: var(--marca); vertical-align: -.1em; }
input[type="date"], input[type="time"], input[type="datetime-local"] { font-variant-numeric: tabular-nums; }
input::placeholder, textarea::placeholder { color: var(--apagado); opacity: 1; }
input:hover, select:hover, textarea:hover { border-color: var(--tinta-2); }
input:focus-visible, select:focus-visible, textarea:focus-visible { outline: 2px solid var(--foco); outline-offset: 1px; border-color: var(--foco); }
input:disabled, select:disabled, textarea:disabled { opacity: .55; background: var(--superficie-2); }
input:user-invalid, select:user-invalid, textarea:user-invalid { border-color: var(--erro); }
select { appearance: none; -webkit-appearance: none; padding-right: 1.9rem;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1.5l5 5 5-5' fill='none' stroke='%236a665e' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat; background-position: right .6rem center; }
select[multiple] { background-image: none; padding-right: .6rem; }
@media (prefers-color-scheme: dark) {
  select { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1.5l5 5 5-5' fill='none' stroke='%23a29e94' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>"); }
}
textarea { min-height: 8rem; line-height: 1.6; resize: vertical; }

button, .botao {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--e2);
  font: inherit; font-size: var(--t1); font-weight: 500; line-height: 1.2;
  padding: .5rem .95rem; border-radius: 6px; cursor: pointer; text-decoration: none; white-space: nowrap;
  border: 1px solid var(--marca); background: var(--marca); color: #fff;
  transition: background var(--rapido), border-color var(--rapido), transform var(--rapido);
}
/* O hover base tem (0,1,1) e ganha de `.chip` (0,1,0): qualquer botão que veste uma classe era
   repintado de verde-escuro com a tinta clara por cima. Medido no escuro: «hoje» a 1,03:1 e o × do
   flash a 1,34:1 — o rótulo some exatamente quando o dedo está em cima dele. */
button:hover:not(:disabled, .secundario, .discreto, .chip, .flash-fechar),
.botao:hover:not(.secundario, .discreto, .chip) { background: var(--marca-forte); border-color: var(--marca-forte); text-decoration: none; }
button:active, .botao:active { transform: translateY(1px); }
button:focus-visible, .botao:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; }
/* [ciclo 3, passagem final · crítica 25] `opacity: .5` sobre o verde cheio dá, NO ESCURO, um verde
   que continua parecendo botão ligado — e derruba o contraste do rótulo branco abaixo de AA, de
   modo que o texto que explica o que o botão faria vira o menos legível da caixa. O desativado
   ganha cara própria: sem preenchimento, tinta apagada, contorno. A razão em palavra ao lado
   (que a view já sabe escrever) passa a ser a única voz da tela. */
button.secundario, .botao.secundario { background: var(--superficie); color: var(--marca); border-color: color-mix(in srgb, var(--marca) 55%, var(--linha-forte)); }
button.secundario:hover, .botao.secundario:hover { background: var(--marca-suave); color: var(--marca-tinta); }
button.discreto, .botao.discreto { background: transparent; border-color: transparent; color: var(--tinta-2); padding-inline: .5rem; }
button.discreto:hover, .botao.discreto:hover { background: var(--superficie-2); color: var(--tinta); }
button.grande, .botao.grande { font-size: var(--t2); padding: .65rem 1.2rem; }
button.miudo, .botao.miudo { font-size: var(--t0); padding: .25rem .6rem; }
a > button { vertical-align: baseline; }
/* o desativado vence a VARIANTE: a cara de desligado é do estado, não do tipo de botão. Vinha antes
   de `.secundario` e `.discreto`, com a mesma especificidade — e perdia por ordem, de modo que
   `<button class="discreto" disabled>` (mesa/nota_conferir.html) ficava pixel a pixel igual a um
   botão ligado, e os submits que o producao.js desativa ao enviar não reagiam. */
button:disabled, button:disabled:hover,
button.secundario:disabled, button.secundario:disabled:hover,
button.discreto:disabled, button.discreto:disabled:hover {
  background: transparent; color: var(--apagado); border: 1px solid var(--linha-forte);
  opacity: 1; cursor: not-allowed;
}
@media (prefers-color-scheme: dark) { button, .botao { color: #0e1a15; } button.secundario, .botao.secundario { color: var(--marca); } button.discreto, .botao.discreto { color: var(--tinta-2); } }
.acoes-form { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e2) var(--e3); grid-column: 1 / -1; }
.acoes-form .nota, .nota { color: var(--apagado); font-size: var(--t0); }

/* --- O FORMULÁRIO DE LINHA ÚNICA (ciclo 2, item 7 · R3 · R6) ----------------
   Um controle, a unidade presa a ele, e o botão — numa linha só no laptop, numa coluna no telefone.
   Três clientes com necessidades diferentes e um desenho só:
     · /minimos/  — vive DENTRO de um <td>: por isso é flex (não grade), e não impõe largura mínima;
     · /contagem/ — vive no telefone, em pé, com a caixa na outra mão: por isso vira coluna e o
                    botão ocupa a largura toda, com 44 px de alvo, embaixo (nunca ao lado do campo);
     · /mesa/de-para/ — tem select + campo + botão: os selects entram como mais um .campo.
   O rótulo é VISÍVEL e fica em cima do controle (R6): placeholder não é rótulo — some quando se digita.
   HTML mínimo:
     <form method="post" class="linha-unica">{% csrf_token %}
       <label class="campo"><span>novo mínimo</span>
         <span class="com-sufixo"><input type="text" name="quantidade" inputmode="decimal" required><span class="sufixo">kg</span></span>
       </label>
       <button type="submit" class="secundario">Publicar</button>
     </form>                                                                   */
.linha-unica { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--e2) var(--e3); margin: 0; }
.linha-unica > .campo, .linha-unica > label { flex: 1 1 8rem; min-width: 0; }
.linha-unica > .campo.estreito { flex: 0 1 7rem; }
.linha-unica > .campo.largo { flex: 2 1 14rem; }
.linha-unica > button, .linha-unica > .botao { flex: none; }
.linha-unica > .nota { flex-basis: 100%; }
td > .linha-unica, td > form.linha-unica { min-width: 12rem; }   /* dentro de célula: cabe, e não estica a coluna */

/* o campo com SUFIXO FIXO de unidade (R6): a unidade é o que não pode sumir, e placeholder some */
.com-sufixo { position: relative; display: block; min-width: 0; }
.com-sufixo > input { padding-right: 3.2rem; }
.com-sufixo.largo > input { padding-right: 5rem; }
.com-sufixo > .sufixo {
  position: absolute; right: .6rem; top: 50%; transform: translateY(-50%);
  color: var(--apagado); font-size: var(--t0); pointer-events: none; white-space: nowrap;
}

/* o campo de ARQUIVO com cara de campo. Sem JavaScript continua sendo o controle nativo, que funciona
   (regra 5): o polimento em PT-BR só entra quando producao.js marca o embrulho com data-js.
   HTML mínimo:
     <div class="campo-arquivo">
       <input type="file" name="xml" id="xml" accept=".xml" required>
       <label class="botao secundario" for="xml">Escolher o arquivo</label>
       <span class="campo-arquivo-nome">nenhum arquivo escolhido</span>
     </div>                                                                    */
.campo-arquivo { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e2) var(--e3); min-width: 0; }
.campo-arquivo > input[type="file"] { flex: 1 1 16rem; padding: .35rem .5rem; font-size: var(--t1); }
.campo-arquivo > input[type="file"]::file-selector-button {
  font: inherit; font-size: var(--t1); font-weight: 500; margin-right: var(--e3);
  padding: .3rem .8rem; border-radius: 6px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--marca) 55%, var(--linha-forte));
  background: var(--superficie); color: var(--marca);
}
.campo-arquivo > label, .campo-arquivo > .campo-arquivo-nome { display: none; }
.campo-arquivo[data-js] > input[type="file"] { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; }
.campo-arquivo[data-js] > label { display: inline-flex; }
.campo-arquivo[data-js] > .campo-arquivo-nome { display: inline; min-width: 0; overflow-wrap: anywhere; color: var(--apagado); font-size: var(--t0); }
.campo-arquivo[data-js] > .campo-arquivo-nome.escolhido { color: var(--tinta-2); }
.campo-arquivo[data-js]:focus-within > label { outline: 2px solid var(--foco); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   12. Linha do tempo, cadeia de retificação, procedência
   -------------------------------------------------------------------------- */
.linha-tempo { display: flex; gap: var(--e2); flex-wrap: wrap; padding: 0; margin: 0 0 var(--e3); list-style: none; }
.linha-tempo .marco, .linha-tempo > a.card {
  display: block; min-width: 12rem; flex: 1 1 12rem; margin: 0;
  padding: var(--e2) var(--e3); border: 1px solid var(--linha); border-radius: var(--r2); background: var(--superficie);
  color: inherit; text-decoration: none; position: relative;
}
.linha-tempo a.marco:hover, .linha-tempo > a.card:hover { border-color: var(--marca); }
.linha-tempo .marco.vigente, .linha-tempo .marco[aria-current] { border-color: var(--marca); box-shadow: inset 3px 0 0 var(--marca); }
.linha-tempo .marco.encurtada, .linha-tempo .encurtada { border-style: dashed; }
.linha-tempo .marco .versao { font-weight: 600; }
.linha-tempo .marco .periodo { color: var(--tinta-2); font-variant-numeric: tabular-nums; }
.linha-tempo .marco .quantas { display: block; color: var(--apagado); font-size: var(--t0); margin-top: 2px; }
.corte { border-left: 2px solid var(--erro); padding-left: var(--e2); color: var(--erro); font-size: var(--t0); }

ol.cadeia { list-style: none; padding: 0; margin: 0 0 var(--e3); position: relative; }
ol.cadeia li { position: relative; padding: var(--e1) 0 var(--e1) var(--e5); margin: 0; }
ol.cadeia li::before { content: ""; position: absolute; left: 6px; top: .85em; width: 9px; height: 9px; border-radius: 50%; background: var(--marca); border: 2px solid var(--superficie); box-shadow: 0 0 0 1px var(--marca); }
ol.cadeia li + li::after { content: ""; position: absolute; left: 10px; top: -1em; bottom: calc(100% - .85em); width: 1px; background: var(--linha-forte); }
ol.cadeia li.velho { color: var(--apagado); }
ol.cadeia li.velho::before { background: var(--superficie); box-shadow: 0 0 0 1px var(--linha-forte); }
ol.cadeia li .pequeno { color: var(--tinta-2); margin-top: 2px; }
ol.cadeia li.velho .pequeno { color: var(--apagado); }

/* --------------------------------------------------------------------------
   13. Cartão diário e boletim — coluna de leitura, celular primeiro
   -------------------------------------------------------------------------- */
.cartao-diario { max-width: var(--largura-leitura); }
.cartao-diario ol { list-style: none; padding: 0; margin: 0; counter-reset: linha; }
.cartao-diario ol > li { counter-increment: linha; display: grid; grid-template-columns: 1.6rem 1fr; gap: var(--e2); padding: var(--e3) 0; border-top: 1px solid var(--linha-suave); margin: 0; }
.cartao-diario ol > li:first-child { border-top: 0; }
.cartao-diario ol > li::before { content: counter(linha); color: var(--apagado); font-variant-numeric: tabular-nums; font-size: var(--t0); padding-top: .2em; }
.cartao-diario ol > li > strong { display: block; }
.cartao-diario ol > li.msg { display: flex; }

/* --------------------------------------------------------------------------
   14. Ícones — SVG do sprite, sempre com palavra ao lado
   -------------------------------------------------------------------------- */
.icone { width: 1.1em; height: 1.1em; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; flex: none; vertical-align: -.2em; }
.icone.grande { width: 1.5em; height: 1.5em; }

/* --------------------------------------------------------------------------
   15. Utilitários
   -------------------------------------------------------------------------- */
.visualmente-oculto { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.linha-meta { display: flex; flex-wrap: wrap; gap: var(--e1) 0; color: var(--apagado); font-size: var(--t0); }
.linha-meta > *:not(:last-child)::after { content: "·"; margin: 0 .5em; color: var(--apagado-2); }
.separado > *:not(:last-child)::after { content: " · "; color: var(--apagado-2); }
.direita { text-align: right; } .centro { text-align: center; }
.mt0 { margin-top: 0 !important; } .mb0 { margin-bottom: 0 !important; }
.mt2 { margin-top: var(--e2); } .mt3 { margin-top: var(--e3); } .mt4 { margin-top: var(--e4); } .mt5 { margin-top: var(--e5); }
.largura-leitura { max-width: var(--largura-leitura); }
.largura-forma { max-width: 40rem; }
.so-impressao { display: none; }
.lista-limpa { list-style: none; padding: 0; margin: 0; }
.lista-limpa > li { padding: .35rem 0; border-top: 1px solid var(--linha-suave); margin: 0; }
.lista-limpa > li:first-child { border-top: 0; }
.chips { display: flex; flex-wrap: wrap; gap: var(--e2); }
.chips.filtros { margin: 0 0 var(--e4); align-items: center; }   /* filtros de lista: logo abaixo do cabeçalho, à esquerda, nunca nas ações */
.chip { display: inline-flex; align-items: center; gap: .35em; font-size: var(--t0); padding: 2px 10px; border-radius: var(--r-pilula); border: 1px solid var(--linha); background: var(--superficie); color: var(--tinta-2); }
.chip.ativo { border-color: var(--marca); color: var(--marca-tinta); background: var(--marca-suave); font-weight: 500; }
/* o recorte que veio na URL é FATO DITO, não filtro ligado: não é link, não recebe foco e não se
   desliga clicando (quem desliga é o «ver todos» ao lado, que é branco). Verde é só o que se liga
   clicando. */
.chip.recorte { background: var(--superficie-3); color: var(--tinta-2); border-color: var(--linha); font-weight: 500; }
a.chip { text-decoration: none; }
a.chip:hover { border-color: var(--linha-forte); }
/* chave/valor fora de tabela: a mesma cara de table.proc (hairline entre linhas, chave em 500) e nunca mais largo que a caixa */
.kv { display: grid; grid-template-columns: minmax(6rem, max-content) minmax(0, 1fr); gap: 0; font-size: var(--t1); margin: 0; }
.kv dt { color: var(--apagado); font-weight: 500; margin: 0; padding: .35rem .8rem .35rem 0; overflow-wrap: anywhere; }
.kv dd { margin: 0; min-width: 0; padding: .35rem 0; overflow-wrap: anywhere; }
.kv dt + dd + dt, .kv dt + dd + dt + dd { border-top: 1px solid var(--linha-suave); }
.kv dt:first-child, .kv dt:first-child + dd { border-top: 0; }
/* a linha secundária de um valor do .kv — a mesma `.sub` de table.proc e de .tabela. Estava em
   areas/compra.css sem prefixo de área, ou seja: uma área escrevendo regra de sistema. */
.kv .sub { display: block; color: var(--apagado); font-size: var(--t0); font-weight: 400; margin-top: 2px; }

/* --------------------------------------------------------------------------
   16. Responsivo — celular para cartão e boletim; laptop para a mesa
   -------------------------------------------------------------------------- */
@media (max-width: 1240px) {
  .bancada-grade { grid-template-columns: 1fr; }
}
@media (max-width: 1000px) {
  .colunas, .colunas-3 { grid-template-columns: 1fr; }
  body { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto; }
  /* A BARRA E A GAVETA (rodada de layout 2, 2026-09-08). A fita horizontal que rolava — com um
     degradê na borda dizendo «há mais» — saiu: vinte links numa fita de 375 px é um menu em que
     ninguém acha nada. Fica uma barra com a marca, a busca e o botão Menu; a navegação inteira
     mora numa GAVETA que abre debaixo da barra, em coluna, com os mesmos grupos do laptop. Sem
     JavaScript abre e fecha igual: o botão é o <label> de uma caixa de marcar. */
  .topo { grid-row: 1; grid-column: 1; height: auto; overflow: visible; border-right: 0; border-bottom: 1px solid var(--linha);
          flex-direction: row; flex-wrap: wrap; align-items: center; gap: var(--e2) var(--e3); padding: var(--e2) var(--e4);
          min-height: var(--altura-topo); box-shadow: var(--sombra-1); }
  .conteudo { --recuo-x: var(--e4); --recuo-y: var(--e4); grid-column: 1; grid-row: 2; padding: var(--recuo-y) var(--recuo-x) var(--e6); }
  .rodape { grid-column: 1; grid-row: 3; padding-inline: var(--e4); }
  .marca { order: 0; margin: 0; padding: 0; }
  .busca-global { order: 1; flex: 1 1 12rem; max-width: 28rem; }
  .topo .quem { order: 2; margin-left: auto; border: 0; padding: 0; }
  .menu-botao { order: 3; display: inline-flex; }
  .navegacao { display: none; order: 5; flex-basis: 100%; flex-direction: column; gap: var(--e2);
               padding: var(--e2) 0 var(--e3); margin-top: var(--e1); border-top: 1px solid var(--linha-suave); }
  #menu-aberto:checked ~ .topo .navegacao { display: flex; }
  .navegacao a { white-space: normal; padding-block: var(--e2); }   /* na gaveta o dedo é o ponteiro */
  .cabecalho { align-items: flex-start; }
  .fixo, .ficha-origem { position: static; }
}

/* ── o corte do celular (R1–R6): 700 px é onde a tabela vira lista e o formulário vira coluna ── */
@media screen and (max-width: 700px) {
  form.linha, .grade, .grade-3 { grid-template-columns: 1fr; }        /* R6 · uma coluna, rótulo em cima */
  .linha-unica { flex-direction: column; align-items: stretch; }      /* R3 · nunca botão ao lado de campo */
  .linha-unica > .campo, .linha-unica > label, .linha-unica > .campo.estreito, .linha-unica > .campo.largo { flex: none; }
  .linha-unica > button, .linha-unica > .botao, .bloco-acoes > button, .bloco-acoes > .botao,
  .acoes-form > button:first-child, .acoes-form > .botao:first-child { width: 100%; }
  .bloco-acoes, .acoes-form { flex-direction: column; align-items: stretch; }
  .bloco-acoes > .nota, .acoes-form > .nota { text-align: left; }
  /* R3 · alvo de 44 px no que se toca (o botão de fechar um aviso e os miúdos continuam miúdos) */
  .conteudo button:not(.flash-fechar, .miudo), .conteudo .botao:not(.miudo) { min-height: 44px; }
  .conteudo input:not([type="checkbox"], [type="radio"]), .conteudo select { min-height: 44px; }
  .conteudo input[type="checkbox"], .conteudo input[type="radio"] { width: 1.15rem; height: 1.15rem; }
  /* R3 · abaixo de 16 px o Safari do iOS amplia a página ao focar o campo, e não desfaz ao sair.
     Os campos computam 15 (var(--t2)) e os de .mesa-itens 14 — o único ponto do app em que o
     aparelho muda o enquadramento sem ninguém pedir. O `<meta viewport>` continua sem
     `maximum-scale`: quem precisa ampliar continua podendo. A densidade de bancada é do laptop.
     A segunda linha leva `.conteudo` na frente de propósito: `areas/mesa.css` carrega DEPOIS deste
     arquivo, e `.mesa-itens input` (0,1,1) empataria e venceria por ordem. */
  .conteudo input, .conteudo select, .conteudo textarea { font-size: 1rem; }
  .conteudo .mesa-itens input, .conteudo .mesa-itens select { font-size: 1rem; }
  /* R3, o resto · a regra de 44 px nomeava tags, e os controles de 2026-09-08 não são tags: medido
     a 375 px, `label.chip.escolha` = 33,9 px (são 22 deles em /producao/, e são O controle da
     tela), `.regras > summary` = 19,5 px (é por ele que se chega a metade dos campos) e
     `a.chip` = 25,5. Na mesma fileira conviviam 34 e 44 px só porque um é label e o outro é
     button. O chip de filtro fica em 32 e não em 44: são cinco numa fileira, e 44 viraria um
     teclado. O selo não clicável (span.chip) fica de fora do :is — não é alvo. */
  .conteudo .escolhas > .escolha { min-height: 44px; }
  .conteudo details > summary { display: flex; min-height: 44px; align-items: center; }
  .conteudo .chip:is(a, button, label) { min-height: 32px; padding-block: 4px; }
  /* a zebra é de LINHA; quando a tabela vira lista (cada linha um cartão) ela pintava cartões
     alternados inteiros, e o segundo cartão de /producao/ parecia selecionado */
  .tabela.lista tbody tr:nth-child(even) > td { background: transparent; }
  .bloco { padding: var(--e3) var(--e4); }
  /* uma coluna de cartões (a regra do celular, §4 da direção do ciclo 2). O `auto-fit` já daria
     isso na maioria das larguras; escrito para não depender da conta. O NÚMERO NÃO ENCOLHE (R2). */
  .grade-cartoes { grid-template-columns: 1fr; gap: var(--e4); }
  .caixa.cartao > .pe-caixa, .bloco.cartao > .pe-caixa { margin-top: var(--e4); }
  .bloco.pauta > .bloco-cabeca { margin-inline: calc(-1 * var(--e4)); padding-inline: var(--e4); }
  .pauta-onde { white-space: normal; }
  .pe-caixa { margin-top: var(--e5); }
  .chips.filtros { flex-wrap: wrap; }                                  /* R4 · filtro é chip, sempre */
}

@media (max-width: 600px) {
  .topo { position: static; }                                   /* no celular a barra não fica presa: 100 px de 812 é caro demais */
  .cabecalho-secao { flex-wrap: wrap; }                          /* a nota desce para a linha de baixo, em toda área */
  .cabecalho-secao .nota { flex-basis: 100%; }
  table.proc th { white-space: normal; }                         /* a chave quebra; o número e a natureza ficam inteiros */
  .kv { grid-template-columns: minmax(7rem, max-content) minmax(0, 1fr); }
  .caixa { padding: var(--e3) var(--e4); border-radius: var(--r2); }
  .conteudo { --recuo-x: var(--e3); --recuo-y: var(--e3); padding: var(--recuo-y) var(--recuo-x) var(--e6); }
  .cabecalho .meta { font-size: var(--t0); }
  h1 { font-size: 1.375rem; }                                    /* D3 · 28 no laptop, 22 em pé */
  /* a busca cabe na barra do tablet, não na do celular: aqui ela vai para dentro da gaveta */
  .busca-global { display: none; }
  #menu-aberto:checked ~ .topo .busca-global { display: flex; order: 4; flex-basis: 100%; max-width: none; margin-top: var(--e2); }
  .busca-global input { font-size: 1rem; }                       /* o iOS não amplia a página ao focar */
  .linha-tempo .marco { min-width: 9rem; }
  .num.grande { font-size: var(--t5); }
}

/* --------------------------------------------------------------------------
   17. Impressão — fichas e boletim honestos em preto e branco
   -------------------------------------------------------------------------- */
@media print {
  :root { --papel: #fff; --superficie: #fff; --superficie-2: #f3f3f3; --linha: #bbb; --linha-suave: #ddd; --tinta: #000; --tinta-2: #222; --apagado: #444; }
  @page { margin: 14mm 12mm; }
  html { font-size: 11.5pt; }
  body { background: #fff; color: #000; display: block; }
  .topo, .rodape .apurado ~ *, .pular, .flashes, .flash, form:not(.imprimir), button, .botao, .acoes, .so-tela, .flash-fechar { display: none !important; }
  .rodape { border-top: 1px solid #000; margin-top: 12mm; font-size: 9pt; color: #000; }
  .rodape .apurado { display: inline; }
  .conteudo { --recuo-x: 0px; --recuo-y: 0px; max-width: none; padding: 0; }
  .cabecalho { margin: 0 0 var(--e4); padding: 0 0 var(--e3); background: none; box-shadow: none; }
  .caixa, .card, .bloco { border: 1px solid #999; border-radius: 0; box-shadow: none; padding: 8pt 10pt; break-inside: avoid; }
  .caixa + .caixa, .bloco + .bloco, .bloco + .caixa, .caixa + .bloco { margin-top: 10pt; }
  /* o bloco: o assunto continua sendo a cabeça, e a faixa da pauta vira um fio preto */
  .bloco > .bloco-cabeca > h2, h2.assunto { font-size: 12pt; color: #000; }
  .bloco.pauta { border-top: 2pt solid #000; padding-top: 0; }
  .bloco.pauta > .bloco-cabeca { background: #fff; border-bottom: 1px solid #000; margin: 0 -10pt 6pt; padding: 4pt 10pt; }
  .pauta-item { border-top: 1px solid #bbb; }
  .pe-caixa { margin-top: 10pt; border-top: 1px solid #bbb; color: #222; font-size: 9pt; }
  /* a tabela-lista é @media screen: no papel ela já é tabela. Isto é o cinto, além do suspensório. */
  .tabela.lista, .tabela.lista tbody, .tabela.lista tr, .tabela.lista td { display: revert; }
  .tabela.lista thead { display: revert; position: static; width: auto; height: auto; clip: auto; overflow: visible; }
  .tabela.lista td[data-rotulo]::before, .tabela.lista tr.negativa td:first-child::after { content: none; }
  .tabela.lista tbody tr { border: 0; padding: 0; margin: 0; }
  .colunas, .colunas-3, .bancada-grade { grid-template-columns: 1fr; }
  /* os cartões continuam em grade no papel: uma coluna de cartões com um número no alto de cada um
     gasta três páginas para dizer o que cabe em uma. E o número de destaque volta ao corpo da
     página — 24 px de tela viram 17 pt de cartaz. */
  .grade-cartoes { grid-template-columns: repeat(2, 1fr); gap: 8pt; }
  .cartao .num.principal { font-size: 13pt; }
  .cartao-conta { font-size: 11pt; font-weight: 400; }
  .caixa.cartao > .pe-caixa, .bloco.cartao > .pe-caixa { margin-top: 10pt; }
  a { color: #000; text-decoration: none; }
  a[href^="http"]::after { content: ""; }
  h1 { font-size: 16pt; } h2 { color: #000; }
  /* a natureza sobrevive: prefixo + palavra, em preto; a cor era só reforço */
  .nat, .nat-aferido, .nat-contado, .nat-declarado, .nat-estimado, .nat-calculado { color: #000; }
  /* o sinal do número já vem do filtro; nenhum sinal a mais, nunca (a classe também é usada só para cor, sem número) */
  .negativo { color: #000; font-weight: 700; }
  .corte { color: #000; border-left-color: #000; }
  mark.reg { background: transparent; color: #000; border-bottom: 1.5px solid #000; }
  pre.bruto { border-left: 2px solid #000; background: #fff; }
  .aviso, .alarme, .msg, .estado { border: 1px solid #000; background: #fff; color: #000; }
  .aviso.erro, .aviso.ok, .aviso.info, .aviso.neutro, .msg.error, .msg.success, .msg.info { background: #fff; color: #000; border-left-color: #000; }
  #faixa.retroagindo { background: #fff; color: #000; border-left-color: #000; }
  .aviso { border-left-width: 4px; }
  .alarme { border-width: 2px; }
  .ensaio-faixa { border: 2px solid #000; background: #fff; color: #000; }   /* a marca vai ao papel, em toda página (etiqueta fixa repete por página) */
  .ensaio-etiqueta { border-color: #000; color: #000; background: #fff; }
  .estado::before { content: "[ "; } .estado::after { content: " ]"; }
  table.proc tr.negativa td, .tabela tr.negativa td, .tabela tr.total.negativa td { background: #fff; }
  table.proc tr.negativa td:first-child::before, .tabela tr.negativa td:first-child::before { content: "(negativo) "; font-weight: 600; }
  /* no papel a tabela não rola: abre inteira, em corpo menor, com o cabeçalho quebrando */
  .rolagem { overflow: visible; background: none; }
  .tabela { font-size: 9pt; table-layout: auto; }
  .tabela thead th { white-space: normal; }
  .tabela td, table.proc td { overflow-wrap: anywhere; }
  table.proc th { white-space: normal; }
  .tabela .n, .num { white-space: normal; }
  tr, li { break-inside: avoid; }
  .so-impressao { display: block; }
  .legenda-naturezas { display: flex; color: #000; }
}

/* --------------------------------------------------------------------------
   18. Movimento reduzido
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0ms !important; animation-duration: 0ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; }
}

/* --------------------------------------------------------------------------
   19. Os três componentes de contenção
   Nasceram da revisão de 2026-09-06: a tela inicial tinha 759 palavras e 11
   frases de mais de 18 palavras, porque `.vazio`, `.estado` e o lugar do número
   aceitavam prosa livre. Aqui a brevidade é ESTRUTURAL: o que passa de duas
   linhas é cortado pelo CSS, e o motivo comprido vai para `title=` ou para a
   dobra `.regras` — nada da honestidade se perde, ela só sai da cara.
   -------------------------------------------------------------------------- */

/* corta o que crescer: usado no apoio do número e na mensagem do vazio */
.duas-linhas {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden; text-overflow: ellipsis;
}

/* 19.1 · cartão de número — rótulo pequeno, número grande, apoio curto */
.cartao-n { display: flex; flex-direction: column; gap: var(--e1); min-width: 0; }
/* D2, o terceiro degrau, dentro do cartão · quando o cartão tem UMA linha, é este `.rotulo` que
   recebe o NOME PRÓPRIO — e «ENTROU» (a categoria) e «MALTODEXTRINA» (o assunto) saíam com o mesmo
   corpo, o mesmo peso, a mesma cor e a mesma caixa alta, um em cima do outro. Duas fileiras acima,
   o mesmo nome sai em 17/600 tinta. Nome próprio não é rótulo. */
.cartao-n.de-nome > .rotulo {
  font-size: var(--t3); font-weight: 600; color: var(--tinta);
  text-transform: none; letter-spacing: -0.01em;
}
.cartao-n > .rotulo {
  font-size: var(--t-1); text-transform: uppercase; letter-spacing: .06em;
  font-weight: 600; color: var(--apagado);
}
.cartao-n > .valor { font-size: var(--t5); line-height: 1.1; font-weight: 600; font-variant-numeric: tabular-nums; }
.cartao-n > .valor .num { font-size: inherit; font-weight: inherit; }
.cartao-n > .valor .nat { font-size: var(--t0); font-weight: 500; }
.cartao-n > .valor .estado { font-size: var(--t1); vertical-align: middle; }
.cartao-n > .apoio { font-size: var(--t0); color: var(--apagado); }
.cartao-n > .apoio.duas-linhas { max-height: 2.8em; }

/* 19.2 · vazio com saída — título curto, uma frase, e um caminho */
/* os dois vazios eram a MESMA caixa tracejada com uma diferença só: `.vazio-c` não declarava
   `color`, e usado como parágrafo cru (sem os filhos que _vazio.html emite) saía em tinta cheia —
   «nada a pedir hoje», o melhor resultado da tela de compra, era a tinta mais pesada da página.
   A caixa dos dois está definida junto de `.vazio`; aqui ficam só os filhos de _vazio.html. */
.vazio-c > .titulo { font-weight: 600; color: var(--tinta-2); }
.vazio-c > p { margin: var(--e1) 0 0; font-size: var(--t0); color: var(--apagado); max-width: 42ch; }
.vazio-c > .acao { margin-top: var(--e2); display: inline-block; }

/* 19.3 · a dobra das regras — a honestidade continua escrita, sob demanda */
.regras { margin-top: var(--e5); border-top: 1px solid var(--linha-suave); padding-top: var(--e3); }
.regras > summary {
  cursor: pointer; font-size: var(--t0); color: var(--apagado);
  list-style: none; display: inline-flex; align-items: center; gap: var(--e1);
}
.regras > summary::-webkit-details-marker { display: none; }
.regras > summary::before { content: "›"; font-size: .8em; transition: transform var(--rapido); }
.regras[open] > summary::before { transform: rotate(90deg); }
.regras > summary:hover { color: var(--tinta-2); }
.regras > summary:focus-visible { outline: 2px solid var(--foco); outline-offset: 2px; border-radius: var(--r1); }
.regras .pe-caixa { margin-top: var(--e2); }

/* no papel a dobra abre: quem imprime leva as regras junto */
@media print { .regras > summary { display: none; } .regras > *:not(summary) { display: block !important; } }

/* 19.4 · o código técnico sai da tela (revisão de 2026-09-06: 109 deles visíveis em 35 telas).
   `T-0`, `P2`, `R-05` são identificadores dos documentos de planejamento, não do chão de fábrica.
   Continuam no HTML — para os testes, para copiar e colar, e para o leitor de tela — e voltam a
   aparecer no papel, onde a ficha é documento de auditoria e o código é o que liga tela e doc. */
.codigo-tecnico { display: none; }
@media print { .codigo-tecnico { display: inline; } }

/* 19.5 · o separador não fica órfão quando o vizinho seguinte é um código escondido (§19.4):
   `.meta`/`.bloco-meta` põem o "·" no irmão ANTERIOR, então esconder o último elemento deixava
   um ponto solto no fim da linha. Some também no papel? Não: lá o código volta, e o "·" faz falta. */
@media screen {
  .cabecalho .meta > *:has(+ .codigo-tecnico:last-child)::after,
  .bloco-meta > *:has(+ .codigo-tecnico:last-child)::after,
  .nota > *:has(+ .codigo-tecnico:last-child)::after { content: none; }
}

/* 19.6 · a dobra do texto pronto: some do papel (quem imprime já tem o relatório acima) */
.texto-pronto > summary > .nota { margin-left: .4em; }
.texto-pronto .caixa { margin-top: var(--e2); }
@media print { .texto-pronto { display: none; } }


/* ==========================================================================
   20. A lista que cresceu
   Nasceu do ciclo 3 (2026-09-07), o primeiro em que as telas têm dado de
   verdade. Os ciclos 1 e 2 desenharam contra listas de zero a três linhas,
   e o sistema não tinha nada a dizer sobre a quarta pergunta de uma tela de
   trabalho: **o que acontece quando são cinquenta?** Movimentos já tem 19 e
   nenhuma busca, nenhum filtro, nenhuma ordenação e nenhum fim; Saldo tem
   11 linhas em 8 colunas e repete a mesma instalação em todas elas.

   Nada aqui muda uma tela sozinho: são todos **opt-in**. Uma tabela sem
   `.densa` continua com o respiro de hoje; sem `.fixa`, o cabeçalho rola
   como sempre. O que o sistema passa a garantir é que, quando a lista
   crescer, as seis respostas já existam — e sejam a mesma em toda área.
   -------------------------------------------------------------------------- */

/* 20.1 · densidade de razão — a tabela que se lê de cima a baixo, não de longe.
   O número NÃO encolhe (R2): quem encolhe é o respiro e o rótulo. */
.tabela.densa tbody td { padding: .3rem .7rem .3rem 0; }
.tabela.densa thead th { padding: .35rem .7rem .35rem 0; }
.tabela.densa tbody tr td { line-height: 1.35; }
.tabela.densa .sub { display: inline; margin-left: .5em; }         /* a segunda linha vira aposto */
.tabela.densa td.n .sub { display: block; margin-left: 0; }        /* menos na coluna de número, onde ela é o motivo */

/* 20.2 · o cabeçalho que fica — só faz sentido com altura máxima, senão não há o que fixar.
   `.rolagem.alta` rola nos dois eixos; o `th` precisa de fundo opaco para não deixar a
   linha passar por baixo. No papel a tabela abre inteira (§9) e nada disto vale. */
.rolagem.alta { max-height: 70vh; overflow-y: auto; }
.tabela.fixa thead th {
  position: sticky; top: 0; z-index: 2;
  background: var(--superficie); box-shadow: inset 0 -1px 0 var(--linha);
  border-bottom: 0;
}
@media print {
  .rolagem.alta { max-height: none; overflow: visible; }
  .tabela.fixa thead th { position: static; box-shadow: none; border-bottom: 1px solid var(--linha); }
}

/* 20.3 · ordenação — o `th` vira link e o sentido é dito em palavra no `title`/`aria-sort`.
   A seta é reforço; quem carrega o sentido é `aria-sort`, que o leitor de tela anuncia. */
.tabela th.ord { padding-right: 0; }
.tabela th.ord > a { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: .3em; padding-right: .8rem; }
.tabela th.ord > a:hover { color: var(--tinta-2); text-decoration: underline; }
.tabela th.ord > a::after { content: "»"; font-size: .9em; color: var(--apagado-2); }
.tabela th[aria-sort="ascending"] > a { color: var(--tinta); }
.tabela th[aria-sort="ascending"] > a::after { content: "↑"; color: var(--tinta-2); }
.tabela th[aria-sort="descending"] > a { color: var(--tinta); }
.tabela th[aria-sort="descending"] > a::after { content: "↓"; color: var(--tinta-2); }
@media print { .tabela th.ord > a::after { content: none; } }

/* 20.4 · a coluna constante — quando o mesmo valor se repete em todas as linhas
   (`Instalação de produção`, 19 vezes), ele é contexto, não dado: sai do primeiro plano
   e continua legível. Não se apaga coluna: apaga-se o volume dela. */
.tabela td.constante, table.proc td.constante { color: var(--apagado); font-weight: 400; }
/* No telefone apagar a tinta não resolve o VOLUME: na tabela-lista cada célula é uma linha inteira,
   e onze linhas dizendo «instalação — Instalação de produção» custam onze rolagens para dizer o
   mesmo (crítica 42). A constante sai da pilha e é dita uma vez, na barra da lista ou no pé — quem
   marcou a célula foi a view, e é ela que sabe que o valor é constante na página. */
@media screen and (max-width: 700px) { .tabela.lista tbody td.constante { display: none; } }
/* A exceção `td.codigo { white-space: nowrap }` foi escrita para o CÓDIGO DE LOTE dentro de
   `.rolagem`, onde a tabela rola e o código não parte. Na `.tabela.lista` do celular não há
   container que role: quem rola é a página — e uma chave de acesso de 46 caracteres levou
   /mesa/nota/ a 439 px numa janela de 390, a única das 49 telas a estourar (crítica 11). */
@media screen and (max-width: 700px) {
  .tabela.lista td.codigo { white-space: normal; overflow-wrap: anywhere; }
}

/* 20.5 · a barra da lista — busca, filtro e contagem num lugar só, **abaixo do cabeçalho e à
   esquerda** (decisão 9: nunca nas `.acoes`, que somem no papel). A contagem é a única parte
   que vai ao papel — ela diz quantas linhas a folha deveria ter. */
.barra-lista { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e3) var(--e4); margin-bottom: var(--e3); }
.barra-lista > form { margin: 0; }
.barra-lista .lista-conta { font-size: var(--t0); color: var(--apagado); margin-left: auto; }
.barra-lista .lista-conta strong { font-weight: 600; color: var(--tinta-2); }
@media (max-width: 700px) {
  .barra-lista { gap: var(--e2); }
  .barra-lista .lista-conta { margin-left: 0; width: 100%; }
}
@media print { .barra-lista > form, .barra-lista .chip:not(.ativo) { display: none; } }

/* 20.6 · paginação — nunca “carregar mais” sem fim: quem confere precisa saber onde está e
   quanto falta. A frase vem antes dos botões, e é ela que sobrevive sem JavaScript. */
.paginacao { display: flex; flex-wrap: wrap; align-items: center; gap: var(--e3); margin-top: var(--e4); padding-top: var(--e3); border-top: 1px solid var(--linha-suave); }
.paginacao .onde { font-size: var(--t0); color: var(--apagado); }
.paginacao .onde strong { font-weight: 600; color: var(--tinta-2); }
.paginacao .passos { display: flex; gap: var(--e2); margin-left: auto; }
.paginacao .passos > .fim { font-size: var(--t0); color: var(--apagado-2); align-self: center; }
@media (max-width: 700px) {
  .paginacao .passos { margin-left: 0; width: 100%; }
  .paginacao .passos > a, .paginacao .passos > .botao { flex: 1; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; }
}
@media print { .paginacao .passos { display: none; } }

/* 20.7 · estado de carga — a tela que está esperando diz que está esperando, com palavra.
   `aria-busy="true"` é o interruptor; as barras são reforço e param com `prefers-reduced-motion`.
   Só existe onde algo demora de verdade (exportação, extração): não se põe esqueleto em página
   que o servidor devolve pronta. */
[aria-busy="true"] .carregando-palavra::after { content: " …"; }
.carregando { display: flex; flex-direction: column; gap: var(--e2); }
.carregando .carregando-palavra { font-size: var(--t0); color: var(--apagado); }
.carregando-linha { height: .8rem; border-radius: var(--r1); background: var(--superficie-2); position: relative; overflow: hidden; }
.carregando-linha:nth-child(2) { width: 80%; }
.carregando-linha:nth-child(3) { width: 60%; }
.carregando-linha::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, var(--superficie-3), transparent);
  transform: translateX(-100%); animation: carregando-passa 1.4s infinite;
}
@keyframes carregando-passa { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .carregando-linha::after { animation: none; } }
@media print { .carregando { display: none; } }
