:root {
  --fundo: #f4f6f8;
  --superficie: #ffffff;
  --borda: #dfe4ea;
  --texto: #1d2733;
  --texto-fraco: #66748a;
  --primaria: #1f6feb;
  --primaria-escura: #1a5ac4;
  --ok: #1a7f4b;
  --ok-fundo: #e5f5ec;
  --atencao: #b06000;
  --atencao-fundo: #fdf1e0;
  --erro: #b3261e;
  --erro-fundo: #fdeceb;
  --andamento: #1f6feb;
  --andamento-fundo: #e8f1fe;
  --raio: 8px;

  /* Largura util. O teto de 2100px nao tem efeito num monitor de 1900px --
     existe so para a tabela nao ficar absurdamente esparsa em ultrawide. */
  --larg-conteudo: 2100px;
  --gutter: clamp(14px, 1.8vw, 34px);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: "Segoe UI", system-ui, -apple-system, Arial, sans-serif;
  font-size: 14px;
  color: var(--texto);
  background: var(--fundo);
  line-height: 1.5;
}

/* ---------------- topo ---------------- */
.topo {
  display: flex;
  align-items: center;
  gap: 16px 28px;
  /* Quebra em duas linhas quando o menu nao cabe, em vez de empurrar o
     conteudo para fora da tela. */
  flex-wrap: wrap;
  /* Mesmo gutter do main: e o que alinha a marca com o <h1> da pagina. */
  padding: 0 var(--gutter);
  min-height: 56px;
  background: var(--superficie);
  border-bottom: 1px solid var(--borda);
  position: sticky;
  top: 0;
  z-index: 10;
}
.marca { flex: 0 0 auto; }
.marca strong { font-size: 16px; letter-spacing: .2px; }
.marca span { color: var(--texto-fraco); margin-left: 8px; font-size: 13px; }
/* min-width: 0 deixa o menu encolher quando os rotulos ficam longos, em
   vez de empurrar o nome do usuario para fora da tela. */
.topo nav { display: flex; flex-wrap: wrap; gap: 4px; flex: 1 1 auto; min-width: 0; }
.topo nav > a, .topo nav .menu { flex: 0 1 auto; }
.topo nav > a { white-space: nowrap; }
.topo nav a {
  padding: 6px 12px;
  border-radius: var(--raio);
  color: var(--texto-fraco);
  text-decoration: none;
  font-weight: 500;
}
.topo nav a:hover { background: var(--fundo); color: var(--texto); }
.topo nav a.ativo { background: var(--andamento-fundo); color: var(--primaria); }
.sair { margin: 0; }

main {
  max-width: var(--larg-conteudo);
  margin: 0 auto;
  padding: 20px var(--gutter);
}

.rodape {
  max-width: var(--larg-conteudo);
  margin: 0 auto;
  padding: 14px var(--gutter) 28px;
  color: var(--texto-fraco);
  font-size: 12px;
}

/* O texto de apoio corre na largura da tela.

   Ele levava `max-width: 90ch`, pela regra de que linha longa cansa a
   leitura. Numa tela de 1.885px isso o prendia em 582px: a nota da
   carteira quebrava em TRÊS linhas com 1.235px vazios ao lado, e o texto
   do cabeçalho da etapa espremia junto -- o `div` que o contém é `flex`
   e encolhia até o limite do parágrafo.

   O pedido foi explícito e repetido: texto informativo em linha corrida,
   aproveitando a tela. `.observacao` e `.vazio p` continuam capados --
   eles moram em cartão estreito, onde a linha longa não acontece. */
.observacao, .vazio p { max-width: 90ch; }
/* O `.aviso` NÃO leva `max-width`. Ele levava 110ch, e por isso a
   notificação de estoque mínimo -- 95 caracteres -- quebrava em duas
   linhas dentro de 830px numa tela de 1.768. Notificação é recado curto:
   cabe em uma linha corrida, e o layout abaixo garante isso. */

/* ---------------- cabecalho de pagina ---------------- */
.cabecalho-pagina {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
h1 { font-size: 20px; margin: 0 0 4px; }
h2 { font-size: 15px; margin: 0 0 10px; }
.sub { margin: 0; color: var(--texto-fraco); }
.acoes { display: flex; gap: 8px; align-items: center; }
.acoes form { margin: 0; }

/* ---------------- botoes ---------------- */
.btn {
  display: inline-block;
  padding: 8px 16px;
  border-radius: var(--raio);
  border: 1px solid transparent;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  font-family: inherit;
}
.btn-primario { background: var(--primaria); color: #fff; }
.btn-primario:hover { background: var(--primaria-escura); }
.btn-primario:disabled { background: #9db8e6; cursor: not-allowed; }
.btn-secundario {
  background: var(--superficie);
  color: var(--texto);
  border-color: var(--borda);
}
.btn-secundario:hover { background: var(--fundo); }
.btn-grande { padding: 11px 22px; font-size: 15px; }
.link {
  background: none; border: none; padding: 0;
  color: var(--primaria); cursor: pointer;
  font-family: inherit; font-size: 14px; text-decoration: underline;
}

/* ---------------- avisos ---------------- */
.avisos { margin-bottom: 16px; display: grid; gap: 8px; }
/* Linha corrida: o negrito, o texto e o link lado a lado. Dos 16 avisos
   do sistema, 15 cabem em uma linha de 1.768px -- o único que não cabe
   tem 355 caracteres, e quebra por último em vez de estourar a tela.
   
   Por que não `white-space: nowrap`: com 355 caracteres o aviso sairia
   pela direita e levaria a página junto. `flex` com `min-width: 0` no
   texto dá a linha corrida sem esse risco. */
.aviso {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
  padding: 9px 14px;
  border-radius: var(--raio);
  border: 1px solid;
}
.aviso > span, .aviso > p { min-width: 0; margin: 0; }
.avisos > .aviso { flex-wrap: wrap; }
.aviso-sucesso { background: var(--ok-fundo); border-color: #b7e0c8; color: var(--ok); }
.aviso-erro { background: var(--erro-fundo); border-color: #f3c4c1; color: var(--erro); }

/* ---------------- indicadores ---------------- */
/* Toda tela tem exatamente 3 indicadores. Com auto-fit eles ESTICAVAM ate
   ~590px cada em tela larga; auto-fill com teto de trilha mantem o cartao
   do tamanho certo e joga a sobra para a direita. */
.painel-indicadores {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(165px, 225px));
  justify-content: start;
  gap: 10px;
  margin-bottom: 14px;
}
.indicador {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: 6px;
  padding: 9px 12px;
}
.indicador .valor {
  display: block;
  font-size: 20px;
  font-weight: 600;
  line-height: 1.15;
}
.indicador .rotulo {
  display: block;
  color: var(--texto-fraco);
  font-size: 11.5px;
  line-height: 1.3;
}
.indicador.alerta .valor { color: var(--atencao); }

/* ---------------- filtros ---------------- */
/* Barra de filtros: uma faixa só, da largura da tela. Antes a busca
   parava em 640px e os chips desciam em linhas próprias, deixando dois
   terços da largura vazios em qualquer monitor grande. */
.filtros {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  padding: 10px 14px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  margin-bottom: 14px;
}
.filtros input[type="search"] {
  flex: 1 1 280px;
  min-width: 0;
  padding: 8px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-family: inherit;
  font-size: 14px;
}
/* Botões e links de apoio encostam na direita, em vez de ficarem
   grudados na busca. */
.filtros > .btn { flex: 0 0 auto; }
.filtros > .link { margin-left: 2px; }

.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }

/* Filtros e chips adjacentes viram um cartão só: a pessoa lê "isto tudo
   filtra a tabela abaixo" de uma vez. */
.filtros:has(+ .chips) {
  margin-bottom: 0;
  border-radius: var(--raio) var(--raio) 0 0;
  border-bottom: none;
}
.filtros + .chips, .chips + .chips {
  align-items: center;
  padding: 9px 14px;
  border: 1px solid var(--borda);
  border-top: none;
  background: var(--superficie);
  margin-bottom: 0;
}
.filtros + .chips:has(+ .chips) { border-radius: 0; }
.chips:last-of-type {
  border-radius: 0 0 var(--raio) var(--raio);
  margin-bottom: 14px;
}
.chip {
  padding: 5px 11px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  background: var(--superficie);
  color: var(--texto-fraco);
  text-decoration: none;
  font-size: 13px;
}
.chip:hover { border-color: var(--primaria); color: var(--primaria); }
.chip.ativo {
  background: var(--andamento-fundo);
  border-color: var(--primaria);
  color: var(--primaria);
  font-weight: 500;
}
.chip .contador { opacity: .7; margin-left: 3px; }

/* Dois eixos de filtro na mesma faixa (situação | etapa). Cada eixo é um
   grupo próprio: quando a tela estreita, ele quebra inteiro para a linha
   de baixo em vez de partir no meio e deixar um chip órfão. */
.grupo-chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
}
.divisor-chips {
  width: 1px;
  align-self: stretch;
  min-height: 22px;
  margin: 0 5px;
  background: var(--borda);
}


.alternador { margin-bottom: 12px; font-size: 13px; }
.alternador a { color: var(--primaria); }
.alternador .nota { color: var(--texto-fraco); margin-left: 6px; }

/* ---------------- tabela ---------------- */
/* A tabela rola dentro da própria caixa, e não com a página: é o que
   permite o cabeçalho ficar grudado no topo enquanto se rola a lista. */
.tabela-wrap {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  overflow: auto;
  max-height: calc(100vh - 230px);
  /* Listas curtas não devem ganhar caixa alta à toa. */
  min-height: 0;
}
/* Tabela dentro de bloco/popup tem menos espaço em volta. */
.bloco .tabela-wrap, .dialogo .tabela-wrap { max-height: calc(100vh - 320px); }
.tabela { width: 100%; border-collapse: collapse; line-height: 1.4; }
.tabela th {
  text-align: left;
  padding: 8px 12px;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--texto-fraco);
  border-bottom: 1px solid var(--borda);
  /* Grudado no topo da caixa que rola. O fundo é obrigatório: sem ele as
     linhas apareceriam por baixo do cabeçalho. */
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--superficie);
  /* Mantido de proposito: e o que faz cada coluna estreita assentar na
     largura do proprio cabecalho, em vez de quebrar "Necessidade liquida"
     em tres linhas. Com .col-larga absorvendo a sobra, virou feature. */
  white-space: nowrap;
}
.tabela td {
  padding: 7px 12px;
  border-bottom: 1px solid #eef1f4;
  vertical-align: top;
}

/* Cada tabela tem uma coluna "gorda" (Produto / Item / Descricao) e o
   resto estreito. Dar 100% a ela faz absorver toda a folga da tela;
   as demais recuam para a largura do proprio conteudo. Uma por tabela --
   duas dividiriam a sobra e o efeito se perderia. */
.tabela th.col-larga { width: 100%; white-space: normal; }
.tabela tbody tr:last-child td { border-bottom: none; }
.tabela tbody tr:hover { background: #fafbfc; }
.tabela .num { text-align: right; white-space: nowrap; }
.linha-atrasada { background: #fffaf3; }
.linha-atrasada:hover { background: #fdf4e8; }

.numero-op { font-weight: 600; color: var(--primaria); text-decoration: none; white-space: nowrap; }
.numero-op:hover { text-decoration: underline; }
.produto-codigo { font-weight: 500; }
/* Corta com reticencia em vez do slice do Jinja: o corte por numero de
   caracteres nao enxerga a largura real e cortava sem aviso nenhum --
   num sistema de PCP isso vira leitura de codigo errado. O texto inteiro
   fica no title. */
.produto-desc {
  color: var(--texto-fraco);
  font-size: 12.5px;
  line-height: 1.35;
  max-width: 62ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.un { color: var(--texto-fraco); font-size: 12px; }
.local { color: var(--texto-fraco); font-size: 13px; white-space: nowrap; }
/* Colisao de nome: `.etapa` e o rotulo da etapa da OP numa celula, mas
   tambem e a <section> de cada passo do planejamento. O nowrap vazava
   para as secoes e deixava cada paragrafo de ajuda numa linha unica,
   empurrando a pagina para o lado. Escopado ao span. */
span.etapa { white-space: nowrap; }

.tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}
.tag-ok { background: var(--ok-fundo); color: var(--ok); }
.tag-andamento { background: var(--andamento-fundo); color: var(--andamento); }
.tag-atraso { background: var(--atencao-fundo); color: var(--atencao); margin-left: 6px; }

/* ---------------- vazio ---------------- */
.vazio {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 44px 24px;
  text-align: center;
  color: var(--texto-fraco);
}
.vazio .btn { margin-top: 12px; }
.vazio-inline { color: var(--texto-fraco); }

/* ---------------- formulario ---------------- */
.formulario {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 22px;
  display: grid;
  gap: 18px;
  /* NAO subir sem revisar: a 1100px o grid de .linha resolve 4 colunas,
     igual aos 940px de antes. A 1300px viraria 5 e desalinharia os
     campos com .campo-duplo em maquina_form e usuario_form. */
  max-width: 1100px;
}
.linha {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}
.campo { display: grid; gap: 5px; position: relative; min-width: 0; }
/* Item de grid nao encolhe abaixo do proprio conteudo sem isto -- e um
   <select> com opcao longa ("03 - ETR - Estoque em Posse de Terceiros")
   estourava o campo. Vale para todos os formularios. */
.campo > * { min-width: 0; max-width: 100%; }
/* .campo-largo era usada em 4 templates sem existir no CSS. Dentro de
   .linha, 1/-1 empurraria o campo para a linha de baixo -- por isso
   .campo-duplo separada, que e o que os formularios precisam. */
.campo-largo { grid-column: 1 / -1; }
.campo-duplo { grid-column: span 2; }
.campo label { font-weight: 500; font-size: 13px; }
.campo input, .campo select, .campo textarea {
  padding: 9px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-family: inherit;
  font-size: 14px;
  background: var(--superficie);
  color: var(--texto);
}
.campo input:focus, .campo select:focus, .campo textarea:focus {
  outline: 2px solid var(--andamento-fundo);
  border-color: var(--primaria);
}
.obrig { color: var(--erro); }
.ajuda { margin: 0; font-size: 12px; color: var(--texto-fraco); }
label.inline {
  display: inline-flex; align-items: center; gap: 6px;
  font-weight: 400; cursor: pointer;
}

.sugestoes {
  position: absolute;
  top: 100%;
  left: 0; right: 0;
  z-index: 20;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  box-shadow: 0 6px 18px rgba(0,0,0,.10);
  max-height: 320px;
  overflow-y: auto;
}
.sugestao {
  padding: 9px 12px;
  cursor: pointer;
  border-bottom: 1px solid #eef1f4;
}
.sugestao:last-child { border-bottom: none; }
.sugestao:hover, .sugestao.destacada { background: var(--andamento-fundo); }
.sugestao .cod { font-weight: 500; }
.sugestao .desc { color: var(--texto-fraco); font-size: 13px; }
.sugestao .sem-estrutura { color: var(--atencao); font-size: 12px; }

/* Abrir OP: as famílias como botões, sobre o campo de busca. */
.chips-familia { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 8px; }
.chips-familia .chip { cursor: pointer; font-family: inherit; }
/* A lista de sugestões de uma família pode ter centenas de itens. */
.formulario .sugestoes { max-height: 360px; overflow-y: auto; }

/* "O que a fábrica vai produzir": a peça interna marcada, o produto
   escolhido como alternativa. */
.interno-sugerido {
  display: grid;
  gap: 6px;
  margin-top: 8px;
  padding: 10px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
}
/* O `display: grid` acima vence o `hidden` do navegador: sem isto a caixa
   aparecia vazia, uma moldura sob a busca antes de escolher o produto. */
.interno-sugerido[hidden] { display: none; }
.interno-sugerido .interno-titulo {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--texto-fraco);
}
.opcao-interno {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: baseline;
  font-weight: 400;
  cursor: pointer;
}
.opcao-interno .desc { color: var(--texto-fraco); }

.escolhido {
  padding: 10px 12px;
  background: var(--andamento-fundo);
  border-radius: var(--raio);
  font-size: 13px;
}
.escolhido strong { display: block; }

.previa {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 16px;
  background: #fbfcfd;
}
.previa table { width: 100%; border-collapse: collapse; margin-top: 8px; }
.previa th, .previa td { padding: 6px 10px; text-align: left; font-size: 13px; }
.previa th {
  color: var(--texto-fraco); font-size: 11px;
  text-transform: uppercase; letter-spacing: .4px;
  border-bottom: 1px solid var(--borda);
}
.previa td.num, .previa th.num { text-align: right; }
.previa tbody tr { border-bottom: 1px solid #eef1f4; }

.rodape-form {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  border-top: 1px solid var(--borda);
  padding-top: 18px;
}
.alerta-gravacao { margin: 0; color: var(--atencao); font-size: 13px; }

/* ---------------- ficha / detalhe ---------------- */
.ficha {
  display: grid;
  /* auto-fit de proposito: o gap de 1px sobre o fundo de borda desenha
     as divisorias, e trilhas vazias apareceriam como blocos cinzas. */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1px;
  background: var(--borda);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  overflow: hidden;
  margin: 0 0 20px;
}
.ficha > div { background: var(--superficie); padding: 12px 16px; }
.ficha dt { color: var(--texto-fraco); font-size: 12px; margin-bottom: 3px; }
.ficha dd { margin: 0; font-weight: 500; }
.codigo-etapa { color: var(--texto-fraco); font-weight: 400; font-size: 12px; }

.bloco {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 18px;
  margin-bottom: 18px;
}
.bloco .tabela-wrap { border: none; }
.observacao { margin: 0; white-space: pre-wrap; }

/* ---------------- login ---------------- */
.login {
  max-width: 360px;
  margin: 72px auto;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 32px;
}
.login h1 { margin-bottom: 2px; }
.login .sub { margin-bottom: 22px; }
.login form { display: grid; gap: 16px; }

@media (max-width: 700px) {
  .topo { gap: 12px; }
  .marca span { display: none; }
  main { padding: 14px; }
  /* No celular os cartoes voltam a ser elasticos: teto de trilha fixo
     deixaria sobra irregular numa tela de 375px. */
  .painel-indicadores { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  .acoes-apont { grid-template-columns: 1fr; }
  .produto-desc { max-width: none; white-space: normal; }
}

/* ================= menu de cadastros ================= */
.menu { position: relative; }
.menu-botao {
  padding: 6px 12px; border: none; background: none; cursor: pointer;
  border-radius: var(--raio); color: var(--texto-fraco);
  font-family: inherit; font-size: 14px; font-weight: 500;
}
.menu-botao:hover { background: var(--fundo); color: var(--texto); }
.menu-botao.ativo { background: var(--andamento-fundo); color: var(--primaria); }
.menu-itens {
  display: none; position: absolute; top: 100%; left: 0; z-index: 30;
  min-width: 210px; background: var(--superficie);
  border: 1px solid var(--borda); border-radius: var(--raio);
  box-shadow: 0 6px 18px rgba(0,0,0,.10); padding: 5px;
}
.menu:hover .menu-itens, .menu:focus-within .menu-itens { display: block; }
.menu-itens a {
  display: block; padding: 8px 12px; border-radius: 5px;
  color: var(--texto); text-decoration: none; font-size: 14px;
}
.menu-itens a:hover { background: var(--fundo); }

/* ================= identificação do usuário ================= */
.usuario-topo {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;      /* nunca e espremido pelo menu */
}
.usuario-topo .nome { font-weight: 500; font-size: 13.5px; white-space: nowrap; }
.usuario-topo form { margin: 0; }
.papel-tag {
  font-size: 11.5px; padding: 2px 8px; border-radius: 999px;
  background: var(--fundo); color: var(--texto-fraco);
  border: 1px solid var(--borda); white-space: nowrap;
}

/* ================= tabelas editáveis ================= */
.tabela-editavel td { padding: 6px 10px; }
.campo-tabela {
  width: 100%; padding: 6px 9px; font-family: inherit; font-size: 13.5px;
  border: 1px solid transparent; border-radius: 5px;
  background: transparent; color: var(--texto);
}
.campo-tabela:hover { border-color: var(--borda); }
.campo-tabela:focus {
  border-color: var(--primaria); background: var(--superficie);
  outline: 2px solid var(--andamento-fundo);
}
/* Select na tabela editável: com `width: 100%` ele encolhia até a largura
   da coluna e mostrava só a seta -- a tela não dizia o que estava
   selecionado. A coluna é que cede espaço. */
.tabela-editavel select.campo-tabela { min-width: 8.5em; }
.tabela-editavel td:has(> select.campo-tabela) { white-space: nowrap; }
.campo-codigo { font-family: ui-monospace, Consolas, monospace; text-transform: uppercase; }
.campo-num, .campo-seq { text-align: right; max-width: 110px; }
.col-acao { width: 130px; }
.col-seq { width: 80px; }
.centro { text-align: center; }
.acao-linha { white-space: nowrap; display: flex; gap: 10px; align-items: center; }
.acao-linha form { margin: 0; }
.linha-nova { background: var(--fundo); }
.linha-nova td { border-top: 2px solid var(--borda); }
.linha-inativa { opacity: .55; }
.btn-pequeno { padding: 5px 12px; font-size: 13px; }
.link-perigo { color: var(--erro); }

.tag-inativo { background: var(--fundo); color: var(--texto-fraco); }
.tag-neutro {
  background: var(--fundo); color: var(--texto-fraco);
  border: 1px solid var(--borda); margin-right: 3px;
}

/* ================= blocos de formulário ================= */
.bloco-form {
  border: 1px solid var(--borda); border-radius: var(--raio);
  padding: 16px 18px 18px; margin: 0; display: grid; gap: 12px;
}
.bloco-form legend {
  font-weight: 600; font-size: 13px; padding: 0 8px;
  color: var(--texto);
}
.grade-checks {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 8px;
}

/* ================= login por PIN ================= */
.login-pin input { font-size: 20px; letter-spacing: .08em; text-align: center; }

/* ================= apontamento ================= */
.bloco-apont { margin-bottom: 26px; }
.bloco-apont h2 { font-size: 14px; color: var(--texto-fraco); text-transform: uppercase; letter-spacing: .4px; }
.cartoes { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px,1fr)); gap: 12px; }
.cartao {
  display: block; padding: 16px; border-radius: var(--raio);
  background: var(--superficie); border: 1px solid var(--borda);
  border-left: 4px solid var(--ok); text-decoration: none; color: var(--texto);
}
.cartao-parado { border-left-color: var(--atencao); background: #fffaf3; }
.cartao:hover { box-shadow: 0 3px 12px rgba(0,0,0,.08); }
.cartao-topo { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.cartao-op { font-weight: 600; font-size: 15px; }
.cartao-op-nome { font-size: 13px; margin-top: 4px; }
.cartao-maquina { color: var(--texto-fraco); font-size: 13px; }
.cartao-motivo { color: var(--atencao); font-size: 13px; margin-top: 4px; }
.cartao-numeros { display: flex; gap: 14px; margin-top: 10px; font-size: 13px; }
.cartao-numeros .perda { color: var(--atencao); }

/* O cartao da ordem em andamento: o que se produz, para quem, e as
   maquinas dela. Antes era um cartao por maquina -- tres tornos na mesma
   OP viravam tres cartoes iguais, e a maquina, que e a unica coisa que
   mudava entre eles, ficava perdida no meio da repeticao. */
.cartao-produto { font-size: 13px; margin-top: 6px; line-height: 1.35; }
.cartao-produto .codigo { font-weight: 600; margin-right: 4px; }
.cartao-pai {
  font-size: 12.5px; color: var(--texto-fraco); margin-top: 2px;
  line-height: 1.35;
}
.cartao-pai .rot { text-transform: uppercase; letter-spacing: .4px;
  font-size: 10.5px; margin-right: 3px; }
.cartao-pai .codigo { font-weight: 600; margin-right: 4px; }

/* Uma linha por maquina, com o estado na frente: e o que a pessoa le de
   relance para saber o que ainda esta rodando. */
.cartao-maquinas {
  list-style: none; margin: 10px 0 0; padding: 8px 0 0;
  border-top: 1px solid var(--borda);
  display: grid; gap: 5px;
}
.cartao-maquinas li {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; font-size: 13px;
}
.cartao-maquinas .cm-nome { min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }

.cartao-ordem {
  display: flex; gap: 16px; flex-wrap: wrap; align-items: flex-end;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 14px 16px; margin-bottom: 10px;
}
.ordem-info { flex: 1 1 300px; }
.ordem-numero { font-weight: 600; }
.ordem-produto { font-weight: 500; font-size: 13.5px; }
.ordem-desc { color: var(--texto-fraco); font-size: 13px; }
.ordem-qtde { font-size: 13px; margin-top: 4px; }
.ordem-escolhas { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
.ordem-escolhas label { display: grid; gap: 4px; font-size: 12px; color: var(--texto-fraco); }
.ordem-escolhas select {
  padding: 9px 11px; border: 1px solid var(--borda);
  border-radius: var(--raio); font-family: inherit; font-size: 14px;
  background: var(--superficie); color: var(--texto);
}
.btn-toque { padding: 12px 22px; font-size: 15px; min-height: 46px; }

/* Exatamente 3 paineis: com auto-fit cada um passaria de 590px. */
.acoes-apont {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 420px));
  justify-content: start;
  /* Sem isto os tres paineis esticam ate a altura do mais alto, e o de
     parada fica com um vazio enorme embaixo do botao. */
  align-items: start;
  gap: 14px;
  margin-bottom: 20px;
}
.painel-acao {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 16px;
  display: grid;
  /* minmax(0,1fr) e o que impede o <select> de estourar o cartao: item de
     grid nao encolhe abaixo do proprio conteudo sem esse minimo zero. */
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  align-content: start;
}
.painel-acao h2 { margin: 0; font-size: 14px; text-transform: none; letter-spacing: 0; color: var(--texto); }
.painel-acao > * { min-width: 0; }
.painel-acao select, .painel-acao input {
  width: 100%;
  min-width: 0;
  padding: 11px 12px; border: 1px solid var(--borda); border-radius: var(--raio);
  font-family: inherit; font-size: 15px; background: var(--superficie); color: var(--texto);
}
.painel-acao .btn { width: 100%; }
.painel-acao .ajuda { margin: 0; }
.painel-parado { border-left: 4px solid var(--atencao); background: #fffaf3; }
.painel-encerrar { border-left: 4px solid var(--borda); }
.linha-toque { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.linha-toque label { display: grid; gap: 4px; font-size: 12px; color: var(--texto-fraco); min-width: 0; }

.linha-tempo { list-style: none; margin: 0; padding: 0; }
.evento { display: flex; gap: 14px; padding: 7px 0; border-bottom: 1px solid #eef1f4; font-size: 13.5px; }
.evento:last-child { border-bottom: none; }
.evento .hora { font-family: ui-monospace, Consolas, monospace; color: var(--texto-fraco); }
.evento-parada .rotulo { color: var(--atencao); }
.evento-fim .rotulo { color: var(--ok); }

/* ================= chão de fábrica ================= */
.grade-maquinas { display: grid; grid-template-columns: repeat(auto-fill,minmax(280px,1fr)); gap: 14px; }
.painel-maquina {
  display: block; padding: 16px; border-radius: var(--raio);
  background: var(--superficie); border: 1px solid var(--borda);
  border-top: 4px solid var(--ok); text-decoration: none; color: var(--texto);
}
.painel-maquina.esta-parada { border-top-color: var(--atencao); background: #fffaf3; }
.pm-topo { display: flex; justify-content: space-between; gap: 8px; align-items: center; }
.pm-maquina { font-weight: 600; }
.pm-op { font-size: 13.5px; margin-top: 6px; }
.pm-operador { color: var(--texto-fraco); font-size: 13px; }
.pm-motivo { color: var(--atencao); font-size: 13px; margin-top: 4px; }
.pm-metricas, .pm-oee { display: grid; grid-template-columns: repeat(3,1fr); gap: 8px; margin-top: 12px; }
.pm-oee { border-top: 1px solid var(--borda); padding-top: 10px; }
.pm-metricas div, .pm-oee div { display: grid; }
.pm-metricas .rot, .pm-oee .rot { font-size: 11px; color: var(--texto-fraco); }

/* ================= planejamento ================= */
.aviso-info { background: var(--andamento-fundo); border-color: #bcd6f7; color: #14508f; }
.aviso-atencao { background: var(--atencao-fundo); border-color: #f0d3a8; color: var(--atencao); }
.formulario-linha {
  display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end;
  max-width: 1250px;
}
.formulario-linha .campo { flex: 1 1 150px; }
.filtro-campo { display: grid; gap: 4px; font-size: 12px; color: var(--texto-fraco); }
.filtro-campo input, .filtro-campo select {
  padding: 8px 11px; border: 1px solid var(--borda); border-radius: var(--raio);
  font-family: inherit; font-size: 14px; background: var(--superficie); color: var(--texto);
}
.tabela-plano .col-produto {
  min-width: 220px;
  max-width: 340px;      /* a sobra vai para os periodos, nao para o produto */
  position: sticky;
  left: 0;
  background: var(--superficie);
}
/* Sem z-index no thead a celula fixa passava por baixo ao rolar; e sem as
   regras de hover o fundo fixo divergia da linha destacada. */
.tabela-plano thead .col-produto { z-index: 3; }
.tabela-plano tbody .col-produto { z-index: 2; }
.tabela-plano tbody tr:hover .col-produto { background: #fafbfc; }
.tabela-plano tr.linha-atrasada .col-produto { background: #fffaf3; }
.tabela-plano .periodo { font-size: 11px; }
.celula-plano { line-height: 1.35; }
.celula-plano .demanda { font-weight: 600; }
.celula-plano .necessidade { color: var(--primaria); font-size: 12px; }
.celula-plano .projetado { color: var(--texto-fraco); font-size: 11.5px; }
.vazio-celula { color: #cdd5de; }
.demanda { font-weight: 600; }
.necessidade { color: var(--primaria); }
.projetado { color: var(--texto-fraco); }
.nivel-mrp {
  display: inline-block; min-width: 22px; text-align: center;
  background: var(--fundo); border: 1px solid var(--borda);
  border-radius: 4px; font-size: 12px; padding: 1px 5px;
}
.falta { color: var(--atencao); }

/* ================= permissões por funcionário ================= */
.grade-permissoes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 6px;
}
.permissao {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 8px 11px;
  border: 1px solid var(--borda);
  border-radius: 6px;
  background: var(--superficie);
  font-size: 13.5px;
  cursor: pointer;
}
.permissao:hover { border-color: var(--primaria); }
/* Azul marca o que foi ajustado fora do padrão do perfil. */
.permissao-alterada { border-color: var(--primaria); background: var(--andamento-fundo); }
.marca-excecao {
  display: block;
  font-size: 11px;
  font-style: normal;
  color: var(--primaria);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.tag-ajustado {
  background: var(--andamento-fundo);
  color: var(--primaria);
  margin-left: 5px;
}

/* ================= estoque de terceiros ================= */
.linha-retorno {
  display: flex; gap: 6px; align-items: center; flex-wrap: nowrap;
}
.linha-retorno .campo-tabela { border-color: var(--borda); }
.linha-retorno input.campo-num { width: 78px; flex: 0 0 78px; }
.linha-retorno select.campo-tabela { width: 150px; flex: 0 0 150px; }
.linha-retorno .btn { flex: 0 0 auto; white-space: nowrap; }
.acoes-omie {
  display: flex;
  gap: 20px;
  flex-wrap: wrap;
  align-items: flex-end;
  padding: 14px;
  background: var(--fundo);
  border-radius: var(--raio);
}
.acoes-omie form { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }

/* ================= barra de ação sob os filtros ================= */
.barra-acao {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-bottom: 12px;
}
.barra-acao .ajuda { margin: 0; }
.marca-pendente {
  display: inline-block;
  margin-left: 4px;
  width: 14px;
  text-align: center;
  border-radius: 3px;
  background: var(--atencao-fundo);
  color: var(--atencao);
  font-size: 11px;
  font-weight: 600;
  cursor: help;
}

/* ================= faixa de modo desenvolvedor ================= */
/* A trava de escrita na Omie. Vermelha e no topo de tudo: e o tipo de
   estado que nao pode passar despercebido nem por um dia. */
.faixa-travada {
  background: var(--atencao-fundo, #fdf1e0);
  color: var(--atencao, #b06000);
  border-bottom: 2px solid var(--atencao, #b06000);
  padding: 7px 16px;
  font-size: 13px;
  text-align: center;
}
.faixa-travada code {
  background: rgba(0, 0, 0, .06);
  padding: 1px 5px;
  border-radius: 4px;
}

.faixa-dev {
  background: #fff4d6;
  border-bottom: 1px solid #e6c976;
  color: #7a5600;
  padding: 6px var(--gutter);
  font-size: 12.5px;
}
.faixa-dev code {
  background: rgba(0,0,0,.06);
  padding: 1px 5px;
  border-radius: 3px;
}

/* ================= popup (dialog nativo) ================= */
.dialogo {
  border: none;
  border-radius: 10px;
  padding: 0;
  max-width: min(1720px, calc(100vw - 32px));
  width: 100%;
  max-height: calc(100vh - 60px);
  box-shadow: 0 12px 44px rgba(0, 0, 0, .22);
  color: var(--texto);
  background: var(--superficie);
}
.dialogo::backdrop { background: rgba(20, 32, 43, .45); }
.dialogo-topo {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 16px 22px;
  border-bottom: 1px solid var(--borda);
  position: sticky;
  top: 0;
  background: var(--superficie);
  z-index: 2;
}
.dialogo-topo h2 { margin: 0; font-size: 17px; }
.dialogo-fechar {
  border: none; background: none; cursor: pointer;
  font-size: 26px; line-height: 1; color: var(--texto-fraco);
  padding: 0 4px;
}
.dialogo-fechar:hover { color: var(--texto); }
.dialogo-corpo { padding: 18px 24px 24px; overflow-y: auto; }
/* Dentro do popup o formulário já está numa caixa: tira a moldura dupla. */
.dialogo-corpo .formulario {
  border: none; padding: 0; max-width: none; box-shadow: none;
}
/* Abrir nova OP: um formulário, não uma tabela -- não precisa da tela toda. */
.dialogo-medio { max-width: min(1040px, calc(100vw - 32px)); }
.dialogo-medio .rodape-form .acoes { display: flex; gap: 10px; }

/* ================= posto de apontamento ================= */
.faixa-posto {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  padding: 12px 18px;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-left: 4px solid var(--primaria);
  border-radius: var(--raio);
  margin-bottom: 14px;
}
.posto-item { display: grid; gap: 2px; }
.posto-item .rot {
  font-size: 11px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--texto-fraco);
}
.posto-item strong { font-size: 15px; }

/* ================= produto da ordem ================= */
.bloco-produto { padding: 18px; }
.produto-cabecalho {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
  justify-content: space-between;
  align-items: flex-start;
}
.produto-identidade { min-width: 0; flex: 1 1 320px; }
.produto-identidade .rot {
  font-size: 11px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--texto-fraco);
}
.produto-codigo-grande { font-size: 20px; font-weight: 600; line-height: 1.2; }
.produto-desc-grande { color: var(--texto-fraco); font-size: 14px; }
.produto-numeros { display: flex; flex-wrap: wrap; gap: 26px; }
.pn { display: grid; gap: 2px; text-align: right; }
.pn .rot {
  font-size: 11px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--texto-fraco);
}
.pn strong { font-size: 22px; font-weight: 600; }
.pn strong small { font-size: 12px; font-weight: 400; color: var(--texto-fraco); }
.pn-alerta strong { color: var(--atencao); }

.barra-progresso {
  height: 8px; border-radius: 999px; background: var(--fundo);
  margin-top: 16px; overflow: hidden;
}
.barra-feito { height: 100%; background: var(--ok); border-radius: 999px; }

.titulo-bloco {
  font-size: 12px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--texto-fraco); margin: 20px 0 8px;
}
/* A linha do próprio operador, na lista de quem está na ordem. */
.linha-atual { background: var(--andamento-fundo); }
.linha-atual:hover { background: #dceafd; }
.linha-total td { border-top: 2px solid var(--borda); background: var(--fundo); }

/* ================= seletor de produto da remessa ================= */
.seletor-produto {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.seletor-produto .campo { flex: 0 0 auto; min-width: 0; }
.seletor-produto .campo-cresce { flex: 1 1 320px; min-width: 0; }
.seletor-produto .campo-estreito { flex: 0 0 120px; }
.seletor-produto select, .seletor-produto input {
  padding: 9px 12px; border: 1px solid var(--borda); border-radius: var(--raio);
  font-family: inherit; font-size: 14px;
  background: var(--superficie); color: var(--texto);
  max-width: 100%;
}
.produto-tipo {
  font-size: 11px; color: var(--texto-fraco);
  text-transform: uppercase; letter-spacing: .3px;
}
.col-pai { width: 340px; }
.col-pai select { max-width: 340px; }

/* Linha densa da parte fiscal: 6 campos numa faixa só. */
.linha-fiscal { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.campo-estreito { max-width: 150px; }

/* Cancelada: cinza, para nao competir com o vermelho de erro. */
.tag-cancelada { background: #eceff2; color: #6b7c8c; text-decoration: line-through; }

.col-op { width: 260px; }
.col-op select { max-width: 260px; }

/* ---------- linhas do formulário de remessa ---------- */
/* O produto pai é o que vai na nota: precisa caber o código e a descrição,
   senão a pessoa escolhe às cegas. É a coluna mais larga da tabela. */
/* Piso de largura por coluna. Sem isto a coluna Produto (width:100%)
   engole o resto e o Serviço fica com 50px numa tela de 1280. Quando não
   couber, o .tabela-wrap rola em vez de espremer. */
.tabela-itens-remessa { min-width: 1080px; }
.tabela-itens-remessa th, .tabela-itens-remessa td { vertical-align: top; }
.tabela-itens-remessa .campo-tabela { width: 100%; max-width: none; }

.tabela-itens-remessa th:nth-child(1),
.tabela-itens-remessa td:nth-child(1) { width: 34px; text-align: center; }
.tabela-itens-remessa th:nth-child(3),
.tabela-itens-remessa td:nth-child(3) { width: 165px; min-width: 165px; }
/* O pai é o que vai na nota: tem que caber código e descrição, senão a
   pessoa escolhe às cegas. É a coluna mais larga depois do produto. */
.tabela-itens-remessa th:nth-child(4),
.tabela-itens-remessa td:nth-child(4) { width: 380px; min-width: 340px; }
.tabela-itens-remessa th:nth-child(5),
.tabela-itens-remessa td:nth-child(5) { width: 230px; min-width: 210px; }
.tabela-itens-remessa th:nth-child(6),
.tabela-itens-remessa td:nth-child(6) { width: 110px; min-width: 100px; }
.col-marca input { cursor: pointer; }

/* ---------- ação em massa nas linhas marcadas ---------- */
.acao-massa {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 10px;
  padding: 9px 14px;
  border: 1px solid var(--primaria);
  border-radius: var(--raio);
  background: var(--andamento-fundo);
}
.acao-massa label { font-size: 13px; color: var(--texto-fraco); }
.acao-massa select {
  padding: 6px 10px; border: 1px solid var(--borda);
  border-radius: var(--raio); font-family: inherit; font-size: 13px;
  background: var(--superficie); color: var(--texto);
}
.acao-massa-conta { font-size: 13px; }
.acao-massa .link-perigo { margin-left: auto; }

/* ---------- linha que abre no duplo clique ---------- */
.linha-clicavel { cursor: default; }
.linha-clicavel:hover { background: var(--fundo); }

/* ---------- botão destrutivo ---------- */
.btn-perigo {
  background: var(--superficie);
  color: var(--erro);
  border: 1px solid var(--erro);
}
.btn-perigo:hover { background: var(--erro); color: #fff; }

/* ================= apontamento: atividade, ditado e histórico ========= */
/* O cartão da ordem inteiro vira link — no chão de fábrica o alvo tem que
   ser grande, não um botãozinho no canto. */
.cartao-ordem-link {
  text-decoration: none;
  color: inherit;
  transition: border-color .12s, background .12s;
}
.cartao-ordem-link:hover {
  border-color: var(--primaria);
  background: var(--andamento-fundo);
}

/* Formulário de início e de produção: campos grandes, em faixa. */
/* auto-fit criava mais colunas do que campos e espremia cada select em
   ~180px, cortando o nome da máquina. Colunas fixas e largas resolvem: o
   operador precisa ler "25 — Torno Automático" inteiro. */
.form-iniciar, .form-producao {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 380px));
  justify-content: start;
  gap: 14px;
  align-items: end;
}
.form-iniciar .campo-toque-largo { grid-column: auto; min-width: 300px; }
.form-iniciar select, .form-producao select { text-overflow: ellipsis; }
.campo-toque { display: grid; gap: 6px; min-width: 0; }
.campo-toque > span { font-size: 13px; color: var(--texto-fraco); }
.campo-toque select, .campo-toque input, .campo-toque textarea {
  padding: 12px 13px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-family: inherit;
  font-size: 16px;          /* 16px evita o zoom automático no iOS */
  background: var(--superficie);
  color: var(--texto);
  width: 100%;
  max-width: 100%;
}
.campo-toque-largo { grid-column: 1 / -1; }
.btn-iniciar { grid-column: 1 / -1; }

/* Escolha à vista, no lugar da lista suspensa.

   No chão de fábrica o operador escolhe a etapa com o dedo, muitas vezes
   de luva. Uma suspensa custa dois toques e esconde o roteiro inteiro —
   justamente o que ele olha para saber onde a peça está. Aqui as opções
   ficam todas visíveis, e a marcada se destaca sozinha.

   O <input> continua no fluxo, só que discreto: escondê-lo com
   `display:none` tiraria o teclado e o leitor de tela junto. */
.escolha-etapa {
  border: none;
  padding: 0;
  margin: 0;
  min-width: 0;
}
.escolha-etapa legend {
  padding: 0;
  font-size: 13px;
  color: var(--texto-fraco);
}
.opcoes-toque {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}
.opcao-toque {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 14px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  cursor: pointer;
  font-size: 15px;
  /* Alvo de toque com dedo, e não com mouse. */
  min-height: 46px;
}
.opcao-toque:hover { border-color: var(--primaria); }
.opcao-toque input { margin: 0; width: 18px; height: 18px; flex: none; }
.opcao-toque strong { font-variant-numeric: tabular-nums; }
.opcao-toque:has(input:checked) {
  border-color: var(--primaria);
  background: var(--andamento-fundo);
  font-weight: 600;
}
.opcao-toque:focus-within {
  outline: 2px solid var(--primaria);
  outline-offset: 2px;
}

/* Microfone colado no campo de observação. */
.campo-ditado { display: flex; gap: 8px; align-items: stretch; }
.campo-ditado textarea, .campo-ditado input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 12px 13px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-family: inherit;
  font-size: 16px;
  background: var(--superficie);
  color: var(--texto);
  resize: vertical;
}
.btn-microfone {
  flex: 0 0 auto;
  font-size: 22px;
  line-height: 1;
  padding: 0 16px;
  cursor: pointer;
}
/* Gravando: o operador precisa ver de longe que o microfone está aberto. */
.btn-microfone.gravando {
  background: var(--erro);
  border-color: var(--erro);
  color: #fff;
  animation: pulso-microfone 1.1s ease-in-out infinite;
}
@keyframes pulso-microfone {
  0%, 100% { box-shadow: 0 0 0 0 rgba(179, 38, 30, .45); }
  50%      { box-shadow: 0 0 0 7px rgba(179, 38, 30, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .btn-microfone.gravando { animation: none; }
}

.bloco-observacao .form-observacao { display: grid; gap: 12px; }
.bloco-observacao .form-observacao > .btn { justify-self: start; }

/* As ações que o operador procura primeiro ficam em destaque. */
.acoes-primarias { margin-bottom: 18px; }

/* Histórico: linhas de observação em itálico, para separar do que é
   movimento de máquina. */
.tabela-historico tr.evento-observacao .produto-desc { font-style: italic; }
.tabela-historico tr.evento-fim td { border-top: 1px solid var(--borda); }

/* ================= planejamento em etapas ================= */
.atalhos-etapa { display: flex; gap: 8px; flex-wrap: wrap; }
.atalhos-etapa a {
  padding: 7px 14px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  font-size: 13px;
  color: var(--texto-fraco);
  text-decoration: none;
  white-space: nowrap;
}
.atalhos-etapa a:hover { border-color: var(--primaria); color: var(--primaria); }

/* Cada etapa é um bloco visualmente fechado, para a pessoa saber onde
   uma termina e a outra começa ao rolar. */
.etapa {
  margin: 26px 0;
  padding-top: 22px;
  border-top: 2px solid var(--borda);
  scroll-margin-top: 70px;      /* o topo fixo não pode cobrir o título */
}
.etapa:first-of-type { border-top: none; padding-top: 0; }
.etapa-topo { display: flex; gap: 14px; align-items: flex-start; margin-bottom: 14px; }
.etapa-topo h2 { margin: 0 0 3px; font-size: 19px; }
.etapa-topo .ajuda { margin: 0; }
.etapa-numero {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--primaria);
  color: #fff;
  font-weight: 600; font-size: 15px;
}

/* Barra de controles: cabe numa linha só em tela larga. */

/* ---------- minigráfico de venda mês a mês ---------- */
.col-serie { width: 250px; min-width: 220px; }
.serie-limites {
  display: block;
  font-size: 10.5px;
  font-weight: 400;
  color: var(--texto-fraco);
  text-transform: none;
  letter-spacing: 0;
}
.serie {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 34px;
  padding-bottom: 2px;
  border-bottom: 1px solid var(--borda);
}
.serie-barra {
  flex: 1 1 0;
  min-width: 3px;
  min-height: 2px;
  background: var(--primaria);
  border-radius: 1px 1px 0 0;
  opacity: .82;
}
.serie-barra:hover { opacity: 1; }
/* Mês sem venda vira um traço no rodapé, não uma barra invisível: o
   buraco no histórico é informação. */
.serie-barra.vazia { background: var(--borda); min-height: 2px; }

.tabela-sugestao td { vertical-align: middle; }

/* ---------- o que o MRP considera ---------- */
.painel-mrp {
  display: flex;
  gap: 18px;
  align-items: center;
  flex-wrap: wrap;
  padding: 14px 16px;
  margin-bottom: 14px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--fundo);
}
.consideracoes {
  flex: 1 1 460px;
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  border: none;
  margin: 0;
  padding: 0;
  min-width: 0;
}
.consideracoes legend {
  font-size: 12px;
  color: var(--texto-fraco);
  text-transform: uppercase;
  letter-spacing: .4px;
  padding: 0;
  margin-bottom: 6px;
}
.consideracoes .inline { align-items: flex-start; gap: 7px; font-size: 13.5px; }
.consideracoes .inline span { line-height: 1.35; }

/* Lançamento da carteira. O formulário de lançar é o caminho do dia a
   dia; importar planilha é a exceção -- por isso o primeiro toma quase
   toda a faixa e o segundo fica numa coluna estreita.

   auto-fit repartia a largura em partes iguais, e o anexo ficava do
   tamanho do formulário inteiro para caber um botão de arquivo. */
.lancar-carteira {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(260px, 1fr);
  gap: 16px;
  margin-bottom: 16px;
  align-items: start;
}
@media (max-width: 1100px) {
  .lancar-carteira { grid-template-columns: 1fr; }
}
.lancar-carteira > form {
  padding: 14px 16px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  align-items: end;
}
.form-importar .ajuda { flex-basis: 100%; margin: 6px 0 0; }

/* ================= ordens concluídas prontas para envio ================= */
.prontas-topo {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 18px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.prontas-topo h2 { margin: 0 0 3px; }
.prontas-topo .ajuda { margin: 0; }
.prontas-filtros { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.prontas-filtros input[type="search"] { width: 230px; }

/* Uma linha por produto, com as ordens do lado: a tela mostra tudo de uma
   vez, sem precisar abrir cartão nenhum. */
.prontas-grupos { max-height: 520px; overflow-y: auto; }
.tabela-prontas { min-width: 900px; }
.tabela-prontas td { vertical-align: middle; }
.tabela-prontas tbody tr:hover { background: var(--fundo); }
.col-ops { width: 100%; }

.prontas-ops { display: flex; flex-wrap: wrap; gap: 5px; }
.pronta-op {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
  background: var(--superficie);
}
.pronta-op:hover { border-color: var(--primaria); }
.pronta-op:has(input:checked) {
  border-color: var(--primaria);
  background: var(--andamento-fundo);
}
.pronta-op .op-numero { font-weight: 600; }
.pronta-op .op-qtde {
  font-variant-numeric: tabular-nums;
  color: var(--texto-fraco);
}
/* Já enviada: aparece só quando pedida, e desbotada para não ser marcada
   por engano junto com as demais. */
.pronta-op.ja-enviada { opacity: .62; }

/* ================= código e descrição em colunas próprias ============= */
/* Empilhados, o código ficava miúdo embaixo da descrição. Em coluna
   própria ele alinha e vira o que a pessoa varre com o olho. */
.col-codigo {
  white-space: nowrap;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--texto);
}
.tabela td.col-larga {
  white-space: normal;
  overflow-wrap: anywhere;
  color: var(--texto-fraco);
}

/* ================= coluna do fornecedor ================= */
/* Ela era a segunda .col-larga da tabela de compras -- e duas dividem a
   sobra, como diz o comentário lá em cima. O fornecedor ficava com um
   naco estreito e "INDUSTRIA METALURGICA MULTIART LTDA" quebrava em duas
   linhas, desalinhando a linha inteira.

   Aqui ela tem largura própria. 400px foi medido, não chutado: a maior
   razão social desta lista ocupa 328px na fonte da tabela, mais a seta do
   select e o respiro das bordas. Quem cede o espaço é a descrição, que é
   a coluna com `width: 100%` e absorve toda a sobra -- por isso a tabela
   não passa a rolar de lado.

   Há 3 razões sociais de ~60 caracteres no cadastro (a própria Omie corta
   o campo) que ainda não cabem. Para essas fica o title. */
.tabela th.col-fornecedor,
.tabela td.col-fornecedor {
  width: 400px;
  min-width: 400px;
  white-space: nowrap;
}
.tabela td.col-fornecedor { vertical-align: middle; }

/* O select ocupa a coluna inteira: depois de escolher, o que importa é
   ler o nome que ficou, não a caixinha. */
select.campo-fornecedor {
  width: 100%;
  max-width: 100%;
  /* A seta nativa some se o texto encostar nela. */
  padding-right: 4px;
}
.nome-fornecedor {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--texto-fraco);
}

/* ================= posto do operador ================= */
/* O que está acontecendo agora, em letra grande: é a primeira coisa que o
   operador procura ao chegar na máquina. */
.posto-agora {
  padding: 16px 20px;
  margin-bottom: 18px;
  border: 1px solid var(--borda);
  border-left: 5px solid var(--ok, #1e7d45);
  border-radius: var(--raio);
  background: var(--superficie);
}
.posto-agora.posto-pausado { border-left-color: var(--erro); }
.posto-agora.posto-fechado { border-left-color: var(--borda); opacity: .85; }
.agora-estado { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.agora-estado .rot {
  font-size: 11.5px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--texto-fraco);
}
.agora-atividade { font-size: 22px; line-height: 1.2; }
.agora-cronometro {
  font-size: 18px;
  font-variant-numeric: tabular-nums;
  color: var(--primaria);
  font-weight: 600;
}
.agora-posto {
  display: flex; gap: 22px; flex-wrap: wrap;
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--borda);
  font-size: 13.5px;
}
.agora-posto .rot {
  font-size: 11px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--texto-fraco); margin-right: 5px;
}

/* Os botões do dia a dia, em cartões do mesmo tamanho. */
.acoes-posto {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(270px, 340px));
  justify-content: start;
  align-items: start;
  gap: 14px;
  margin-bottom: 20px;
}
.cartao-acao {
  display: grid;
  gap: 9px;
  align-content: start;
  padding: 14px 16px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  min-width: 0;
}
.cartao-acao h3 { margin: 0; font-size: 15px; }
.cartao-acao .ajuda { margin: 0; font-size: 12.5px; }
.cartao-acao select, .cartao-acao input { min-width: 0; max-width: 100%; }
/* Pausar e reiniciar são o par que muda o estado: ganham cor. */
.cartao-pausar { border-color: #f0c9c5; }
.cartao-reiniciar { border-color: var(--primaria); background: var(--andamento-fundo); }
.cartao-turno { border-color: var(--primaria); }

/* Participação de cada tarefa no tempo total. */
.col-barra { width: 170px; min-width: 130px; }
.barra-participacao {
  height: 8px;
  border-radius: 4px;
  background: var(--fundo);
  overflow: hidden;
}
.barra-participacao .barra-feito { height: 100%; border-radius: 4px; }
.barra-participacao .barra-parada { background: var(--erro); }

/* ---------------- ordenação pelo cabeçalho ---------------- */
.th-ordenavel {
  cursor: pointer;
  user-select: none;
  padding-right: 20px;
  position: sticky;          /* repete o sticky: o seletor é mais específico */
  top: 0;
}
.th-ordenavel::after {
  content: "⇅";
  position: absolute;
  right: 7px;
  opacity: .3;
  font-size: 11px;
}
.th-ordenavel:hover { color: var(--primaria); }
.th-ordenavel:hover::after { opacity: .7; }
.th-ordenavel.ordenado { color: var(--primaria); }
.th-ordenavel[data-ordem="asc"]::after { content: "↑"; opacity: 1; }
.th-ordenavel[data-ordem="desc"]::after { content: "↓"; opacity: 1; }
.th-ordenavel:focus-visible { outline: 2px solid var(--primaria); outline-offset: -2px; }

/* A coluna fixa do Plano Mestre precisa passar por cima do corpo, mas por
   baixo do cabeçalho. */
.tabela-plano .col-produto { z-index: 1; }
.tabela-plano thead .col-produto { z-index: 4; }

/* Rodapé de totais gruda embaixo, pelo mesmo motivo do cabeçalho. */
.tabela tfoot td {
  position: sticky;
  bottom: 0;
  background: var(--fundo);
  z-index: 2;
}

/* ================= almoxarifado ================= */
/* Cada movimento é um mini-formulário na própria linha do material: o
   almoxarife lança sem sair da lista. */
.acoes-material { display: flex; flex-direction: column; gap: 5px; }
.linha-material {
  display: flex;
  gap: 5px;
  align-items: center;
  flex-wrap: nowrap;
}
.linha-material input.campo-num { width: 76px; flex: 0 0 76px; }
.linha-material select.campo-tabela { width: 132px; flex: 0 0 132px; }
.linha-material .btn { flex: 0 0 auto; white-space: nowrap; }

.barra-acao {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  padding: 12px 14px;
  margin-bottom: 14px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--fundo);
}

/* Cronômetro correndo: números tabulares para o texto não pular a cada
   segundo. */
.cronometro { font-variant-numeric: tabular-nums; }
.em-curso {
  font-size: 12px;
  color: var(--primaria);
  font-weight: 600;
}

/* Botões do posto: coluna à direita, um embaixo do outro, sempre no mesmo
   lugar da tela — iniciar, pausar e finalizar não mudam de lugar conforme o
   estado da ordem. Do tamanho de quem toca com a mão suja. */
.painel-com-acoes {
  display: flex;
  gap: 22px;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
}
.painel-com-acoes > *:first-child { flex: 1 1 420px; min-width: 0; }
.painel-acoes-topo {
  padding: 14px 16px;
  margin-bottom: 18px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
}
.painel-acoes-topo .ajuda { margin: 0; max-width: 62ch; }

.botoes-posto {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 0 0 auto;
  width: 260px;
}
.botoes-posto form { display: contents; }
.btn-posto {
  width: 100%;
  padding: 15px 20px;
  font-size: 16px;
  font-weight: 600;
}

@media (max-width: 760px) {
  .botoes-posto { width: 100%; }
}
.dialogo-estreito { max-width: min(520px, calc(100vw - 32px)); }

/* A confirmação do sistema. Estreita como uma pergunta -- não é tela. */
.dialogo-confirmar { max-width: min(520px, calc(100vw - 32px)); }
.confirmar-pergunta {
  margin: 0; font-size: 15px; font-weight: 600; line-height: 1.4;
}
.confirmar-detalhe p {
  margin: 10px 0 0; font-size: 13px; color: var(--texto-fraco);
  line-height: 1.5;
}
.dialogo-confirmar .rodape-form {
  justify-content: flex-end; gap: 10px; margin-top: 20px;
}
.bloco-lancar .form-producao { align-items: end; }

/* ============ minhas máquinas nesta ordem ============

   Várias máquinas trabalham a mesma ordem ao mesmo tempo, cada uma com o
   seu relógio e os seus lançamentos. Um cartão por máquina, lado a lado:
   é o que faz o paralelo ser visível -- antes cada uma exigia a sua
   própria tela, e a soma dos três tornos ficava na cabeça do operador. */
.grade-maquinas {
  display: grid;
  /* 380px e a medida do nome, e nao um numero redondo: descontados o
     recheio do cartao e a seta do campo, sobram 350px -- e a maior
     atividade, "Tratamento Externo (Superficial / Termico)", pede 342.
     Com os 320px de antes o nome cortava justamente na escolha. */
  grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
  gap: 14px;
}
.cartao-maquina {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 14px;
  background: var(--superficie);
  display: grid;
  /* Coluna travada na largura do cartao, e nao no conteudo mais teimoso.
     Com `auto`, o select de motivo da pausa -- cuja maior opcao tem 47
     caracteres -- esticava a coluna para 452px dentro de um cartao de
     384px, e TODAS as linhas vazavam pela borda direita: o botao Iniciar
     ficava metade fora da tela. */
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  align-content: start;
  min-width: 0;
}
/* O posto em que o operador está entra em destaque -- ele precisa achar
   o dele de relance no meio de três. */
.cartao-maquina-atual { border-color: var(--primaria); border-width: 2px; }
.cartao-maquina-parada { border-left: 4px solid var(--atencao); }
.cartao-maquina-nova { border-style: dashed; background: var(--fundo); }
.cartao-maquina-nova h3 { margin: 0; font-size: 14px; }

.cartao-maquina-topo {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: start;
}
.cartao-maquina-nome { font-size: 15px; }
.cartao-maquina-tempo { text-align: right; display: grid; gap: 4px; }
.cartao-maquina-tempo .cronometro {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--primaria);
}
.cartao-maquina-numeros {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 14px;
}
.cartao-maquina-numeros .rot { display: block; }

/* Três números curtos numa linha, o motivo embaixo: é como o operador
   lança -- olha a peça, digita, confirma. */
.form-lancar-maquina {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  align-items: end;
}
.form-lancar-maquina label {
  display: grid;
  gap: 4px;
  font-size: 12px;
  color: var(--texto-fraco);
  min-width: 0;
}
.form-lancar-maquina .campo-largo { grid-column: 1 / -1; }
.form-lancar-maquina input, .form-lancar-maquina select {
  padding: 11px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-family: inherit;
  font-size: 16px;          /* 16px evita o zoom automático no iOS */
  background: var(--superficie);
  color: var(--texto);
  width: 100%;
  min-width: 0;
}
.btn-lancar-maquina { grid-column: 1 / -1; width: 100%; }

.form-abrir-maquina { display: grid; gap: 8px; }
.form-abrir-maquina label {
  display: grid; gap: 4px; font-size: 12px; color: var(--texto-fraco);
}
.form-abrir-maquina select {
  padding: 11px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-family: inherit;
  font-size: 16px;
  background: var(--superficie);
  color: var(--texto);
  width: 100%;
  min-width: 0;
}

/* A atividade da máquina, e o botão que a faz começar. O campo fica com a
   linha inteira, e o botão embaixo: o nome é longo ("Tratamento Externo
   (Superficial / Térmico)", 42 caracteres) e é por ele que o operador
   escolhe -- dividir a linha com o botão cortava 73px do nome. */
.form-atividade-maquina {
  display: grid;
  gap: 8px;
}
.form-atividade-maquina label {
  display: grid;
  gap: 4px;
  font-size: 12px;
  color: var(--texto-fraco);
  min-width: 0;
}
.form-atividade-maquina select {
  padding: 11px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-family: inherit;
  font-size: 16px;
  background: var(--superficie);
  color: var(--texto);
  width: 100%;
  min-width: 0;
  text-overflow: ellipsis;
}
.form-atividade-maquina .btn { width: 100%; white-space: nowrap; }

/* Motivo e botão na mesma linha: parar é uma frase só -- "vou parar,
   por isto". */
.form-pausar-maquina { display: flex; gap: 8px; align-items: center; }
/* O botao nao encolhe: espremido pelo campo de motivo, "Pausar" quebrava
   em duas linhas e o cartao ficava com uma linha torta. Quem cede espaco
   e o campo. */
.form-pausar-maquina .btn { flex: 0 0 auto; white-space: nowrap; }
.form-pausar-maquina select {
  flex: 1 1 auto;
  min-width: 0;
  padding: 9px 10px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-family: inherit;
  font-size: 14px;
  background: var(--superficie);
  color: var(--texto);
}

.cartao-maquina-acoes {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  border-top: 1px solid var(--borda);
  padding-top: 10px;
}

/* A família vira atalho: clicar filtra a lista por ela. */
.link-familia { color: var(--texto-fraco); text-decoration: none; }
.link-familia:hover { color: var(--primaria); text-decoration: underline; }

/* Em processo externo: nem verde de concluído, nem vermelho de atraso —
   a peça está fora, e isso é uma situação própria. */
.tag-externo { background: #ede9fe; color: #6d3ecf; }

/* A estrutura mostra principal e substituto na mesma tabela; a cor de
   fundo separa quem é o quê sem precisar ler a coluna. */
.linha-substituto > td { background: #fbfcfe; }
.linha-complemento > td { background: #f5fbf7; }
.seta-substituto { color: var(--texto-fraco); margin-right: 3px; }
.bloco-etapa-maquinas { margin-bottom: 14px; }
.bloco-etapa-maquinas h3 { margin: 0 0 10px; font-size: 15px; }

/* A ordem gerada da entrega, na coluna ORDEM do Planejamento: o numero
   em cima, que e como a ordem e chamada na fabrica, e o andamento logo
   abaixo. Uma por linha quando a entrega tem mais de uma. */
.ordem-da-linha {
  display: grid;
  gap: 2px;
  justify-items: start;
  margin-bottom: 4px;
}
.ordem-da-linha:last-child { margin-bottom: 0; }
.ordem-numero-link {
  font-weight: 600;
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Duas acoes sobre a mesma linha, uma sob a outra. Lado a lado elas se
   leem como variacoes da mesma coisa -- e cancelar a entrega nao tem nada
   a ver com retroagir a ordem. */
.acoes-empilhadas {
  display: grid;
  gap: 2px;
  justify-items: end;
}

/* A linha que veio da Omie, na tabela que agora e uma so. Duas especies
   dividindo a tabela precisam se distinguir de relance: as acoes sao
   diferentes -- cancelar aqui escreve no ERP -- e o gestor nao pode
   descobrir isso clicando. Uma faixa lateral, e nao um fundo colorido: a
   linha ja usa fundo para "vencida". */
/* A faixa lateral saiu: a OP da Omie agora preenche as mesmas colunas e
   usa os mesmos botões das ordens da carteira, e quem diz de onde ela veio
   é o número embaixo do código ("OP 2026/…" x "INT-…"). A classe fica na
   linha como gancho, sem estilo próprio. */

/* Resumo de produção: as linhas de continuação de um mesmo posto não
   repetem máquina e operador — a coluna vazia já diz que é o mesmo. */
.tabela-resumo .linha-continuacao td:first-child,
.tabela-resumo .linha-continuacao td:nth-child(2) {
  border-top-color: transparent;
}
.tabela-resumo { min-width: 1100px; }

/* ================= blocos de consulta recolhidos ================= */
.dobra {
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
  margin-bottom: 12px;
}
.dobra > summary {
  padding: 12px 16px;
  cursor: pointer;
  font-weight: 600;
  font-size: 15px;
  display: flex;
  align-items: center;
  gap: 8px;
  list-style: none;
}
.dobra > summary::-webkit-details-marker { display: none; }
.dobra > summary::before {
  content: "▸";
  color: var(--texto-fraco);
  transition: transform .12s;
}
.dobra[open] > summary::before { content: "▾"; }
.dobra > summary:hover { color: var(--primaria); }
.dobra > *:not(summary) { padding: 0 16px 16px; }
.dobra-conta {
  font-size: 12px;
  font-weight: 400;
  color: var(--texto-fraco);
  background: var(--fundo);
  border-radius: 999px;
  padding: 1px 9px;
}

/* Troca de etapa na ficha da OP: seletor e botao na mesma linha, sem
   quebrar a grade da ficha quando o rotulo da etapa e longo. */
.troca-etapa {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
}
.troca-etapa select {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 240px;
  padding: 4px 6px;
  font-size: 13px;
}

/* Busca de ordens no painel do operador: alvos grandes, uma linha só
   enquanto couber. */
.busca-ordens {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.busca-ordens input[type="search"] {
  flex: 1 1 260px;
  min-width: 0;
  max-width: 460px;
}
.busca-ordens .marca-check {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  font-size: 14px;
}


/* Vários postos meus na mesma ordem: um botão por máquina, empilhados. */
.meus-postos {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.meus-postos .btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  text-align: left;
}
.posto-detalhe {
  font-size: 12px;
  font-weight: 400;
  opacity: .85;
}

/* ---------------------------------------------------------------- */
/* Requisição de materiais: cada ordem é uma dobra. Fechada, a linha  */
/* de resumo basta para saber em que pé está; aberta, os materiais    */
/* aparecem com um campo em cada coluna de movimento.                 */
details.req {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  margin-bottom: 8px;
}
details.req[open] { box-shadow: 0 1px 3px rgba(16, 24, 40, .06); }

/* A divisão da Requisição: entregue à produção, ainda não entregue,
   encerrada. Um título com a contagem e uma linha embaixo -- separa sem
   virar mais uma caixa em volta das caixas. */
.faixa-requisicao {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin: 22px 0 10px;
  padding-bottom: 6px;
  border-bottom: 2px solid var(--borda);
}
.faixa-requisicao:first-child { margin-top: 10px; }
.faixa-requisicao h2 { margin: 0; font-size: 15px; }

/* Cada faixa com a sua cor, sem aumentar a letra: fundo claro, barra
   grossa à esquerda e o título no tom escuro. Amarelo é o que espera o
   almoxarifado; azul-escuro, o que já está na fábrica; verde, o que
   fechou. Achar a faixa certa de relance era o que faltava -- os três
   títulos tinham o mesmo cinza. */
.faixa-requisicao.faixa-a-entregar,
.faixa-requisicao.faixa-entregue,
.faixa-requisicao.faixa-encerrada,
.faixa-requisicao.faixa-cancelada {
  padding: 8px 12px;
  border-bottom: 0;
  border-left: 5px solid;
  border-radius: var(--raio);
}
.faixa-requisicao.faixa-a-entregar { background: #fff5d1; border-left-color: #e0a800; }
.faixa-requisicao.faixa-a-entregar h2 { color: #6b4e00; }
.faixa-requisicao.faixa-entregue { background: #e2e9f5; border-left-color: #1b3a6b; }
.faixa-requisicao.faixa-entregue h2 { color: #1b3a6b; }
.faixa-requisicao.faixa-encerrada { background: #e2f3e7; border-left-color: #1f8a4c; }
.faixa-requisicao.faixa-encerrada h2 { color: #16633a; }
.faixa-requisicao.faixa-cancelada { background: #f1f2f4; border-left-color: #9aa1ab; }
.faixa-requisicao.faixa-cancelada h2 { color: #4b5563; }

.req-cabeca {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  padding: 10px 14px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.req-cabeca::-webkit-details-marker { display: none; }
/* Bege claro na linha da ordem: com várias abertas, o branco da cabeça
   se confundia com o branco das tabelas de dentro, e não se via onde
   acabava uma ordem e começava a outra. */
.req-cabeca { background: #fbf5ea; }
.req-cabeca:hover { background: #f6ecd9; }
details.req[open] > .req-cabeca {
  border-bottom: 1px solid #ecdfc6;
  background: #f8efdd;
}

.req-seta {
  color: var(--texto-fraco);
  transition: transform .12s ease;
  display: inline-block;
}
details.req[open] > .req-cabeca .req-seta { transform: rotate(90deg); }

.req-op { font-weight: 600; }
/* A descrição cede espaço antes de qualquer outra coisa quebrar. */
.req-desc {
  min-width: 0;
  max-width: 40ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Os números do resumo empurram as tags para a direita. */
.req-numeros {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  margin-left: auto;
  font-size: 12.5px;
  color: var(--texto-fraco);
  font-variant-numeric: tabular-nums;
}
.req-numeros b { color: var(--texto); font-weight: 600; }
.req-tags { display: flex; gap: 6px; flex-wrap: wrap; }

.req-corpo { padding: 12px 14px 14px; }
/* Célula de movimento: o acumulado em cima, o campo do que aconteceu
   agora embaixo. O campo tem borda de verdade -- o estilo transparente
   das tabelas de cadastro escondia que ali se digita. */
.cel-mov { vertical-align: top; }
.cel-mov .acumulado {
  display: block;
  font-variant-numeric: tabular-nums;
}
.campo-mov {
  display: block;
  width: 100%;
  min-width: 74px;
  margin-top: 4px;
  padding: 5px 7px;
  font-family: inherit;
  font-size: 13px;
  text-align: right;
  color: var(--texto);
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: 5px;
}
.campo-mov::placeholder { color: var(--texto-fraco); font-size: 12px; }
.campo-mov:focus {
  border-color: var(--primaria);
  background: var(--superficie);
  outline: 2px solid var(--andamento-fundo);
}
/* Preenchido, o campo se destaca: é o que vai ser gravado. */
.campo-mov:not(:placeholder-shown) {
  border-color: var(--primaria);
  font-weight: 600;
}
.campo-motivo { text-align: left; font-size: 12px; }

/* Perda e motivo são um par: a quantidade sozinha não diz nada, e o
   motivo sozinho não existe. Lado a lado eles se leem de uma vez, e a
   linha da tabela deixa de crescer uma terceira vez. */
.perda-com-motivo {
  display: flex;
  align-items: center;
  /* Quantidade e motivo na MESMA linha: "perdi tanto, por isto" se lê de
     uma vez. Os campos de quantidade têm largura fixa (esticavam e
     empurravam o motivo para baixo); o motivo fica com o nome inteiro. */
  flex-wrap: nowrap;
  gap: 5px;
  margin-top: 4px;
}
.perda-com-motivo .campo-mov { margin-top: 0; }
.perda-com-motivo input.campo-mov { flex: 0 0 72px; width: 72px; min-width: 0; }
/* Largura do texto do motivo, e não uma fixa: com 118px o almoxarife lia
   "Ponteira/Sobr" e escolhia no escuro. `auto` faz o select medir a opção
   mais longa; o piso segura o "motivo…" vazio, o teto a tabela. */
.perda-com-motivo select.campo-motivo {
  flex: 0 0 auto;
  width: auto;
  min-width: 16em;
  max-width: 30em;
}

/* "+ entregar outro material": fechado é uma linha de texto sob a
   descrição; aberto, uma faixa tracejada -- é uma escolha, não um
   movimento, e não pode se confundir com os campos de entrega. */
.dobra-incluir { margin-top: 6px; font-size: 12.5px; }
.dobra-incluir > summary {
  cursor: pointer;
  color: var(--primaria);
  list-style: none;
}
.dobra-incluir > summary::-webkit-details-marker { display: none; }
.form-incluir-material {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 8px;
  margin-top: 6px;
  padding: 8px 10px;
  border: 1px dashed var(--borda);
  border-radius: var(--raio);
  background: var(--fundo);
}
.form-incluir-material label,
.busca-material {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12px;
  color: var(--texto-fraco);
}
.form-incluir-material select { max-width: 34em; }
/* A caixa de sugestões é absoluta: ancora na busca, não na tabela. */
.busca-material { position: relative; flex: 1 1 18em; min-width: 16em; }
.busca-material input { width: 100%; }
.form-incluir-material .campo-fator { width: 7em; }
.form-tirar-material { display: inline; }

/* A linha de outro material: igual à do material, com a busca no lugar
   do código. O fundo levemente diferente diz que ela ainda não foi
   gravada -- some no Registrar, quando vira uma linha de verdade. */
/* A lista de materiais da linha nova: branca, uma linha por material,
   como os selects da tela. Fica presa ao <body> em posição fixa -- a
   tabela rola de lado e cortava qualquer caixa presa dentro dela. */
.lista-material {
  position: fixed;
  z-index: 1000;
  max-height: 290px;
  max-width: 640px;
  overflow-y: auto;
  padding: 4px 0;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  box-shadow: 0 8px 22px rgba(16, 24, 40, .14);
  font-size: 13px;
}
.opcao-material {
  display: flex;
  gap: 6px;
  align-items: baseline;
  padding: 6px 12px;
  white-space: nowrap;
  cursor: pointer;
  color: var(--texto);
}
.opcao-material .cod {
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;
  font-size: 12.5px;
  font-weight: 600;
}
.opcao-material .desc { overflow: hidden; text-overflow: ellipsis; }
.opcao-material .extra { color: var(--texto-fraco); font-size: 12px; }
.opcao-material:hover,
.opcao-material.ativa { background: var(--andamento-fundo); }
.lista-material-vazia { padding: 6px 12px; color: var(--texto-fraco); }

/* Substituir e Adicionar lado a lado, sob a descrição do material. */
.botoes-outro-material { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
/* Registrar e cancelar lado a lado em toda linha de material. */
.tabela-materiais .acao-linha { white-space: nowrap; }
.form-cancelar-material { display: inline; margin-left: 6px; }
/* Retroagir desfaz o que já saiu: nem azul de ação comum, nem vermelho de
   destruição -- amarelo de "atenção, isto volta atrás". */
.btn-retroagir {
  background: var(--atencao-fundo);
  border: 1px solid #e8c48a;
  color: var(--atencao);
  font-weight: 600;
}
.btn-retroagir:hover { background: #fbe4c4; border-color: #d9ad69; }
.tabela-materiais .acao-linha > .btn[disabled] { margin-left: 6px; opacity: .45; cursor: not-allowed; }
.linha-outro-material > td { background: var(--fundo); }
/* Registrar e cancelar lado a lado, com o mesmo peso -- são os dois
   desfechos da linha nova. */
.linha-outro-material > .acao-linha { white-space: nowrap; }
.linha-outro-material > .acao-linha .btn + .btn { margin-left: 6px; }
/* O codigo do material inteiro a vista: a celula tinha 9em e o campo
   ficava com 80px, cortando "ACRD030" -- o almoxarife digitava sem ver o
   que tinha escolhido. */
.celula-busca-material { position: relative; min-width: 13em; }
.celula-busca-material .campo-busca-material {
  display: inline-block;
  width: calc(100% - 1.4em);
  min-width: 10em;
  text-align: left;
}
.celula-busca-material .sugestoes { min-width: 26em; }

/* A matéria-prima no cartão da máquina: a escolha em cima, o que foi
   entregue embaixo -- a MP em uso em negrito. */
.cartao-maquina-material { margin: 8px 0; }
.form-material-maquina label {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 12px;
  color: var(--texto-fraco);
}
/* O mesmo campo das outras escolhas do cartão (Atividade): alto, com
   borda e letra de 16px -- era o select cru do navegador, miúdo e sem
   borda, e parecia de outra tela. */
.form-material-maquina select {
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-family: inherit;
  font-size: 16px;
  background: var(--superficie);
  color: var(--texto);
  text-overflow: ellipsis;
}
.form-material-maquina select:disabled {
  color: var(--texto-fraco);
  background: var(--fundo);
}
.mp-entregue {
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12px;
  color: var(--texto-fraco);
}
/* Cada material entregue num quadrinho: código e quantidade em cima, o
   nome inteiro embaixo (quebra linha, nunca corta). O que está em uso
   leva a faixa azul -- é o que cada lançamento vai carimbar. */
.mp-entregue li {
  padding: 6px 8px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
}
.mp-entregue li.em-uso {
  border-color: var(--primaria);
  box-shadow: inset 3px 0 0 var(--primaria);
  background: var(--andamento-fundo);
}
.mp-topo { display: flex; gap: 6px; align-items: baseline; flex-wrap: wrap; }
.mp-topo .codigo { font-weight: 600; color: var(--texto); }
.mp-nome {
  margin-top: 2px;
  font-size: 12.5px;
  line-height: 1.3;
  color: var(--texto);
  overflow-wrap: anywhere;
}

/* As peças parecidas dentro da seção Estrutura: um bloco à parte, sob a
   tabela -- é sugestão, não componente, e não pode parecer uma linha a
   mais da BOM. */
.sugestoes-bom {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px dashed var(--borda);
  border-radius: var(--raio);
  background: var(--fundo);
}
.sugestoes-bom h3 { margin: 0 0 4px; font-size: 14px; }
.sugestoes-bom .ajuda { margin-bottom: 8px; }
.sugestoes-bom .campo-num { width: 6em; }
/* Largo o bastante para "— não gravar —" inteiro: cortado em "— não g"
   ou "Substitu", o PCP escolhia sem ler o que estava marcado. */
.sugestoes-bom select[data-papel-sugestao] { min-width: 12em; }
/* O botão e o "no lugar de" embaixo, à direita: é o fim da lista, onde
   se confere o que foi marcado antes de gravar. */
.rodape-sugestoes {
  display: flex;
  justify-content: flex-end;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 10px;
}
.rodape-sugestoes label {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12px;
  color: var(--texto-fraco);
}

/* Lançar produção da ordem, máquina a máquina: uma linha por máquina
   aberta e o refugo sem máquina por último. As colunas são as mesmas em
   todas as linhas -- o número digitado cai sempre embaixo do mesmo
   rótulo, seja a máquina que for. */
.grade-lancamentos { display: grid; gap: 6px; margin-top: 8px; }
.lanc-cabeca,
.lanc-linha {
  display: grid;
  /* Só a coluna da máquina é elástica; as outras têm largura fixa. Cada
     linha é uma grade própria, e com colunas proporcionais ou `auto` a
     largura do botão ("Lançar" x "Lançar refugo") deslocava os campos --
     o número caía fora do rótulo de cima. */
  grid-template-columns: minmax(220px, 1fr) 96px 96px 96px 240px 124px;
  gap: 8px;
  align-items: center;
}
.lanc-cabeca {
  padding: 0 9px;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--texto-fraco);
}
.lanc-cabeca .num { text-align: right; }
.lanc-linha {
  padding: 8px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
}
.lanc-linha .campo-num,
.lanc-linha select { width: 100%; }
.lanc-maquina { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline; }
.lanc-maquina .produto-desc { flex-basis: 100%; }
.lanc-maquina input { flex-basis: 100%; margin-top: 4px; }
/* O refugo sem máquina: a mesma linha, tracejada -- não é uma máquina. */
.lanc-refugo { background: var(--fundo); border-style: dashed; }
.lanc-vazio { padding: 2px 9px; }

.tabela-materiais th { white-space: nowrap; }
/* Doze colunas, e a Perda com quantidade E motivo na mesma linha: sem
   aperto a tabela passava 57 a 252 px da tela e rolava de lado. O espaço
   sai de onde sobra -- a folga das células e a Descrição, que quebra
   linha à vontade e não precisa dos 320 px de piso das outras tabelas. */
.tabela.tabela-materiais th,
.tabela.tabela-materiais td { padding-left: 7px; padding-right: 7px; }
.tabela.tabela-materiais th.col-larga { min-width: 200px; }
.tabela-embutida { margin-top: 6px; font-size: 13px; }
.tabela-embutida th { background: transparent; }

/* Os três comandos do posto se distinguem pela cor, não pelo texto: no
   chão de fábrica o operador acha o botão antes de ler o rótulo.
   Azul começa, laranja interrompe, vermelho encerra. */
.btn-pausar {
  background: var(--atencao);
  border-color: var(--atencao);
  color: #fff;
}
.btn-pausar:hover:not(:disabled) { filter: brightness(.92); }

.btn-finalizar {
  background: var(--erro);
  border-color: var(--erro);
  color: #fff;
}
.btn-finalizar:hover:not(:disabled) { filter: brightness(.92); }

/* Desabilitado continua legível: some a cor, não o texto. */
.btn-pausar:disabled,
.btn-finalizar:disabled { opacity: .45; }

/* Linha de inclusão da estrutura: os campos ficam nas mesmas colunas da
   linha que já existe, então precisam parecer campo -- o .campo-tabela
   padrão é transparente de propósito nas telas de cadastro. */
.campo-visivel {
  border-color: var(--borda);
  background: var(--superficie);
}
.campo-visivel:focus { border-color: var(--primaria); }
.celula-campos {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.celula-campos select { flex: 1 1 180px; min-width: 0; }
.celula-campos input[type="number"] { flex: 0 0 68px; }
.rotulo-campo {
  font-size: 11px;
  color: var(--texto-fraco);
  text-transform: lowercase;
  white-space: nowrap;
}
/* A caixa de sugestões da busca precisa flutuar sobre a linha de baixo. */
tr.linha-nova .sugestoes { z-index: 30; }

/* O resumo da ordem fica sempre aberto, logo abaixo dos comandos: é o
   que o operador precisa ver antes de lançar quantidade -- quem mais
   está na ordem e quanto já saiu. A contagem no título mantém a pista
   visual que a dobra dava. */
.bloco-resumo > h2 {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Comparativo máquina a máquina: a melhor da ordem ganha destaque, e os
   operadores ficam recuados sob a máquina deles. */
.linha-destaque > td { background: var(--ok-fundo); }
.tabela-comparativo tbody tr:hover.linha-destaque > td { background: var(--ok-fundo); }

/* Controle de Produção: a mesma peça em mais de uma ordem. Verde claro
   também no hover, senão a marca sumia justo na linha que se olha. */
.tabela-internas tbody tr.linha-repetida > td,
.tabela-internas tbody tr.linha-repetida:hover > td { background: var(--ok-fundo); }
.legenda-repetida { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; }

/* ================= expedição ================= */
/* Os campos da saída na própria linha, como na planilha da doca: data,
   quantidade e nota, lado a lado, sem tirar o conferente da tabela. */
.tabela-expedicao .col-saida { white-space: nowrap; }
.form-saida { display: flex; align-items: flex-end; gap: 8px; }
.campo-saida { display: grid; gap: 3px; font-size: 11.5px;
               color: var(--texto-fraco); }
.campo-saida input {
  padding: 5px 7px; border: 1px solid var(--borda); border-radius: 5px;
  font-family: inherit; font-size: 13px; background: var(--superficie);
  color: var(--texto);
}
.campo-saida input:focus {
  border-color: var(--primaria); outline: 2px solid var(--andamento-fundo);
}
.campo-saida .campo-num { width: 84px; text-align: right;
                          font-variant-numeric: tabular-nums; }
.campo-nf input { width: 110px; }
.tabela-saidas { margin-top: 6px; }
.linha-saidas > td { background: var(--fundo); padding: 6px 10px 10px; }

/* A nota que a Omie já tem, sugerida enquanto se digita. Desenhada aqui
   porque o <datalist> nativo abre escuro e não mostra cliente nem data. */
.lista-nf {
  position: fixed; z-index: 60; max-height: 300px; overflow-y: auto;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); box-shadow: 0 8px 24px rgba(16, 24, 40, .14);
}
.opcao-nf {
  display: grid; gap: 2px; padding: 7px 11px; cursor: pointer;
  border-bottom: 1px solid #eef1f4; font-size: 13px;
}
.opcao-nf:last-child { border-bottom: none; }
.opcao-nf:hover, .opcao-nf.destacada { background: var(--andamento-fundo); }
.opcao-nf-apoio { color: var(--texto-fraco); font-size: 12px; }
.opcao-nf-vazia { cursor: default; color: var(--texto-fraco); }
.opcao-nf-vazia:hover { background: transparent; }
.amostra-repetida {
  display: inline-block; width: 14px; height: 14px; flex: none;
  background: var(--ok-fundo); border: 1px solid #b7e0c8; border-radius: 3px;
}

/* Visão agrupada: as ordens de um grupo, abertas embaixo dele. Fundo
   cinza-claro e o código recuado, para ler "isto é de dentro do grupo de
   cima" -- e o grupo aberto em negrito, para achar onde ele começa. */
.tabela-agrupada tr.linha-filha > td { background: var(--fundo); }
.tabela-agrupada tr.linha-filha > td.col-codigo { padding-left: 26px; }
.tabela-agrupada tr.grupo-aberto > td { font-weight: 600; }
.tabela-agrupada .produto-desc { font-weight: 400; }
.linha-operador > td {
  font-size: 12.5px;
  color: var(--texto-fraco);
  border-top: none;
  padding-top: 4px;
  padding-bottom: 4px;
}
.col-recuo { padding-left: 26px; }

/* ================= grade de ordens do apontamento ================= */
/* Uma linha por ordem deixava metade da tela vazia. Em grade cabem 4 a 6
   por linha num monitor de fábrica, e o cartão fica quadrado o bastante
   para o operador achar a OP dele de longe.

   auto-fill e não auto-fit: com 3 ordens na tela, auto-fit esticaria cada
   cartão até 600px e voltaríamos ao problema de origem. */
.grade-ordens {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 12px;
  margin-bottom: 14px;
}

.ficha-op {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 148px;
  padding: 14px;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  text-decoration: none;
  color: inherit;
  transition: border-color .12s, box-shadow .12s;
}
.ficha-op:hover {
  border-color: var(--primaria);
  box-shadow: 0 2px 8px rgba(16, 24, 40, .10);
}
/* Ordem que o operador já toca: barra lateral, para ele achar de relance. */
.ficha-op-minha { border-left: 4px solid var(--andamento); }

.ficha-op-topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.ficha-op-numero { font-weight: 600; font-size: 15px; }
.ficha-op-codigo {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 13px;
  color: var(--texto-fraco);
}
/* A descrição toma o espaço que sobra e corta em 3 linhas: sem isto um
   cartão com nome longo fica o dobro da altura dos vizinhos. */
.ficha-op-desc {
  flex: 1 1 auto;
  font-size: 13px;
  line-height: 1.35;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}
.ficha-op-rodape {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-top: 6px;
  padding-top: 8px;
  border-top: 1px solid var(--borda);
}
.ficha-op-qtde { font-weight: 600; font-size: 15px; }
.ficha-op-etapa {
  font-size: 12px;
  color: var(--texto-fraco);
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ficha-op-marca { align-self: flex-start; margin-top: 6px; }

@media (max-width: 700px) {
  .grade-ordens { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
}

/* Resumo em blocos: cada máquina com seu começo, meio e fim. A faixa do
   posto separa os blocos — sem ela os trechos de tornos diferentes se
   confundem, que era o problema da tabela contínua. */
.tabela-resumo tbody.posto-bloco + tbody.posto-bloco { border-top: 2px solid var(--borda); }
.tabela-resumo .linha-posto > td {
  background: var(--fundo);
  padding-top: 9px;
  padding-bottom: 9px;
}
.tabela-resumo .linha-posto:hover > td { background: var(--fundo); }
.posto-bloco-meu .linha-posto > td { background: var(--andamento-fundo); }
.posto-bloco-meu .linha-posto:hover > td { background: var(--andamento-fundo); }
.posto-maquina { font-weight: 600; }
.posto-operador { color: var(--texto-fraco); margin-left: 10px; }
.tabela-resumo .col-seq { width: 44px; color: var(--texto-fraco); }

/* ================= folha de ordem de produção ================= */
/* A primeira impressão do sistema. Uma ordem por página, para a folha ir
   com a peça pela fábrica. Sem PDF: o navegador imprime e pronto. */
.barra-impressao {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 12px 16px;
  margin-bottom: 16px;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}
.barra-impressao .acoes { display: flex; gap: 8px; flex-wrap: wrap; }

.folha-op {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 22px 26px;
  margin-bottom: 16px;
}
.folha-topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  padding-bottom: 14px;
  border-bottom: 2px solid var(--texto);
}
.folha-marca { font-weight: 700; letter-spacing: .3px; }
.folha-marca span { font-weight: 400; color: var(--texto-fraco); }
.folha-topo h1 { margin: 4px 0 0; font-size: 28px; }
.folha-etapa { text-align: right; }
.folha-rotulo {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--texto-fraco);
}

.folha-ficha {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 14px 20px;
  margin: 18px 0;
}
.folha-ficha dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--texto-fraco);
  margin-bottom: 2px;
}
.folha-ficha dd { margin: 0; font-size: 15px; }
.folha-larga { grid-column: span 2; }
.folha-destaque { font-size: 22px !important; font-weight: 700; }

/* Linhas em branco: a fábrica anota a caneta enquanto o apontamento não
   chega na máquina. */
.folha-tabela { width: 100%; border-collapse: collapse; margin-top: 8px; }
.folha-tabela th,
.folha-tabela td {
  border: 1px solid var(--borda);
  padding: 9px 10px;
  text-align: left;
}
.folha-tabela th {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--texto-fraco);
  background: var(--fundo);
}
.folha-tabela td { height: 30px; }

.folha-rodape {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 16px;
  padding-top: 10px;
  border-top: 1px solid var(--borda);
  font-size: 12px;
  color: var(--texto-fraco);
}

@media print {
  /* Fora do papel: navegação, barra de ação e qualquer cromo da tela. */
  .topo, .rodape, .barra-impressao, .avisos, .nao-imprimir { display: none !important; }
  body, main { background: #fff; padding: 0; margin: 0; max-width: none; }

  .folha-op {
    border: none;
    padding: 0;
    margin: 0;
    /* Uma ordem por página; a última não puxa folha em branco. */
    page-break-after: always;
  }
  .folha-op:last-child { page-break-after: auto; }
  /* Nada de cortar a ficha ou a tabela no meio de uma quebra. */
  .folha-ficha, .folha-tabela { page-break-inside: avoid; }
  .folha-tabela th { background: #f2f2f2 !important; -webkit-print-color-adjust: exact; }

  @page { margin: 14mm; }
}

/* ================= pré-impressão das ordens internas ================= */
/* A folha aparece dentro do popup, no Controle de Produção, antes de
   qualquer coisa ser liberada. Na tela ela é uma prévia; no papel, é o
   único conteúdo da página. */
#dlg-imprimir .folha-op {
  margin: 0;
  background: #fff;
  color: #14202b;
}
#dlg-imprimir .folha-topo { border-bottom-color: #14202b; }
#dlg-imprimir .folha-tabela th,
#dlg-imprimir .folha-tabela td { border-color: #cfd6dd; }
#dlg-imprimir .folha-tabela th { background: #f2f4f6; color: #55636f; }
#dlg-imprimir .folha-nota { margin: 14px 0 4px; font-size: 13px; }
#dlg-imprimir .folha-conferir { width: 60px; }
#dlg-imprimir .rodape-form { margin-top: 18px; }
#dlg-imprimir .ajuda { margin-top: 8px; }

/* O <dialog> aberto vive na top layer e navegador nenhum é confiável
   imprimindo de lá. A folha é copiada para cá -- fora da caixa -- e só ela
   sai na impressora. */
#area-impressao { display: none; }

@media print {
  /* Some com a tela inteira -- cabeçalho, faixas, a lista, o próprio
     popup -- e sobra a folha. Em duas etapas porque #area-impressao mora
     dentro do <main>. */
  body.imprimindo-folha > *:not(main) { display: none !important; }
  body.imprimindo-folha main > *:not(#area-impressao) { display: none !important; }
  body.imprimindo-folha #area-impressao { display: block; }
  body.imprimindo-folha .folha-op {
    border: none;
    padding: 0;
    margin: 0;
    background: #fff;
  }
  @page { margin: 14mm; }
}

/* Form que só existe para o atributo form= de um campo em outra parte da
   página: não ocupa espaço nem aparece. */
.oculto { display: none; }
/* Campo e botão de ajuste na mesma linha da tabela. */
.campo-inline { display: flex; align-items: center; gap: 8px; }
.campo-inline > span { font-size: 12.5px; color: var(--texto-fraco); }

/* Lançar produção pela tela do almoxarifado: campos em faixa, como a
   barra de comando do operador. */
.lancar-almox {
  display: flex;
  gap: 12px;
  align-items: flex-end;
  flex-wrap: wrap;
  margin-top: 8px;
}
.lancar-almox .campo-inline { flex-direction: column; align-items: stretch; gap: 3px; }
.lancar-almox .campo-inline > span { font-size: 11.5px; }
.lancar-almox input, .lancar-almox select { min-width: 110px; }
/* O botão fica na faixa do cabeçalho sem herdar o clique da dobra. */
.req-fechar { margin-left: auto; }

.linha-importar {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 4px;
}

/* Substituto na requisição: recuado sob o principal que ele cobre, para
   o almoxarife ver a alternativa sem confundir com outro material. */
.linha-substituto > td { background: var(--fundo); }
.linha-substituto .col-codigo { padding-left: 22px; }

/* ================= painel dinâmico dos indicadores ================= */
/* Gráfico de barras em SVG montado à mão: o projeto não carrega script
   de fora, e a forma é simples o bastante para não pedir biblioteca. */
.painel-topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.painel-filtros { display: flex; gap: 12px; flex-wrap: wrap; }
.painel-filtros select { min-width: 170px; }

.legenda-series {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  padding: 10px 0;
  border-top: 1px solid var(--borda);
  border-bottom: 1px solid var(--borda);
}
.chips-series { display: flex; gap: 8px; flex-wrap: wrap; }
.acoes-series { display: flex; gap: 12px; }

.chip-serie {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  font-size: 13px;
  border: 1px solid var(--borda);
  border-radius: 999px;
  cursor: pointer;
  user-select: none;
  background: var(--superficie);
}
.chip-serie.ativo { border-color: var(--primaria); background: var(--andamento-fundo); }
.chip-serie input { margin: 0; }
.cor-serie {
  display: inline-block;
  width: 11px;
  height: 11px;
  border-radius: 3px;
  flex: 0 0 auto;
}

/* O gráfico rola sozinho quando há muitos meses; a página nunca. */
.grafico-wrap { overflow-x: auto; padding: 14px 0 4px; }
.grafico-wrap svg { display: block; min-width: 100%; height: 300px; }
.grafico-wrap .grade { stroke: var(--borda); stroke-width: 1; }
.grafico-wrap .eixo-linha { stroke: var(--texto-fraco); stroke-width: 1; }
.grafico-wrap .eixo { font-size: 11px; fill: var(--texto-fraco); }
.grafico-wrap .barra { transition: opacity .12s; }
.grafico-wrap .barra:hover { opacity: .8; }
/* Mês sem apontamento não é zero: um traço no chão, não uma barra. */
.grafico-wrap .sem-dado { stroke: var(--borda); stroke-width: 3; }
.grafico-wrap .linha-meta {
  stroke: var(--ok);
  stroke-width: 1.5;
  stroke-dasharray: 5 4;
}
.grafico-wrap .rotulo-meta { font-size: 10.5px; fill: var(--ok); }

.tabela-painel .cor-serie { margin-right: 7px; }
.tabela-painel .linha-marcada > td { background: var(--andamento-fundo); }
.tabela-painel th { white-space: nowrap; }

/* Os três pilares do OEE: cada bloco explica a conta antes de mostrar o
   gráfico. O conceito é metade do valor da tela. */
.pilar-conceito { max-width: 68ch; }
.pilar-conceito h2 { margin-bottom: 4px; }
.formula {
  margin: 8px 0 0;
  padding: 7px 11px;
  display: inline-block;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 12.5px;
  color: var(--texto);
  background: var(--fundo);
  border-left: 3px solid var(--primaria);
  border-radius: 0 5px 5px 0;
}
/* Legenda do pilar: os componentes são fixos, não se marcam nem desmarcam. */
.chip-serie.estatico { cursor: default; }

/* Produto e cliente são os campos onde se lê texto longo: código mais
   descrição de parafuso passa de 60 caracteres, e razão social também.
   Os demais campos da linha são números e datas, e cabem apertados. */
/* O seletor de intermediário mostra código + descrição: não pode cortar. */
#em_processo { text-overflow: ellipsis; }
#em_processo:disabled { color: var(--texto-fraco); background: var(--fundo); }
.campo-arquivo { flex: 1 1 100%; }
.campo-arquivo input[type="file"] { max-width: 100%; }

/* Na coluna estreita da importação, a lista de colunas do CSV tem que
   quebrar: sem isto ela empurrava a página inteira para o lado. */
.form-importar { min-width: 0; }
.form-importar .campo,
.form-importar .ajuda { min-width: 0; max-width: 100%; }
.form-importar .ajuda {
  overflow-wrap: anywhere;
  line-height: 1.5;
}
.form-importar code { white-space: normal; overflow-wrap: anywhere; }
/* O formulário de lançar também não pode empurrar a grade. */
.lancar-carteira > form { min-width: 0; }
.lancar-carteira .campo { min-width: 0; }

/* Produto e cliente não podem encolher a ponto de esconder o código: a
   descrição de um parafuso passa de 60 caracteres. Os outros campos da
   linha são números e datas, e cedem primeiro. */

/* Produto, intermediário e cliente carregam texto longo: código mais
   descrição de parafuso passa de 60 caracteres, e razão social também.
   Os outros campos da linha são número e data, e cedem primeiro.

   O seletor precisa da especificidade de `.lancar-carteira` porque a
   regra genérica de `.campo` ali dentro fixa base de 150px. */
.lancar-carteira .campo-produto { flex: 2 1 300px; min-width: 260px; }
.lancar-carteira .campo-cliente { flex: 2 1 280px; min-width: 250px; }
.lancar-carteira .campo-produto input,
.lancar-carteira .campo-produto select,
.lancar-carteira .campo-cliente input { width: 100%; }

/* Altura ajustável da tabela: a alça nativa no canto de baixo à direita.
   Só aparece onde há o que ajustar -- a classe é posta pelo script quando
   a lista é mais alta do que a caixa. Duplo clique na alça volta ao
   tamanho padrão. */
.wrap-ajustavel {
  resize: vertical;
  /* Sem isto o canto redondo esconde metade da alça. */
  border-bottom-right-radius: 2px;
}
/* Uma pista de que dá para arrastar: a alça nativa do Chrome é discreta
   demais num fundo claro. */
.wrap-ajustavel::after {
  content: "";
  position: sticky;
  bottom: 0;
  left: 100%;
  display: block;
  width: 14px;
  height: 14px;
  margin-right: -1px;
  pointer-events: none;
  background:
    linear-gradient(135deg, transparent 46%, var(--borda) 46%, var(--borda) 54%, transparent 54%),
    linear-gradient(135deg, transparent 70%, var(--borda) 70%, var(--borda) 78%, transparent 78%);
}

/* ================= utilitárias ================= */
/* Substituem os `style=` inline, que a CSP `style-src 'self'` bloqueia.
   O atributo era ignorado em silêncio -- o HTML parecia certo e o
   espaçamento simplesmente não acontecia. */
.em-linha { display: inline; }
.respiro-10 { margin-top: 10px; }
.respiro-12 { margin-top: 12px; }
.respiro-14 { margin-top: 14px; }
.respiro-16 { margin-top: 16px; }
.respiro-18 { margin-top: 18px; }
/* Âncora do autocomplete: sem isto a caixa de sugestões se posicionava
   pela página e aparecia longe do campo. */
.ancora { position: relative; }
.indicador-largo { min-width: 150px; }

/* Totais do MRP por tipo de produto. A cor separa o que sai da fábrica
   (verde) do que entra nela (azul) -- é a leitura de um relance. */
.totais-mrp {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 10px;
  margin: 14px 0 0;
}
.total-tipo {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 11px 14px;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-left: 3px solid var(--texto-fraco);
  border-radius: var(--raio);
}
/* Produzido pela fábrica. */
.total-tipo-04, .total-tipo-03 { border-left-color: var(--ok); }
/* Comprado de fora. */
.total-tipo-01, .total-tipo-06,
.total-tipo-02, .total-tipo-07, .total-tipo-99 { border-left-color: var(--primaria); }

.total-rotulo {
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--texto-fraco);
}
.total-itens { font-size: 12px; color: var(--texto-fraco); }
.total-qtdes { display: flex; flex-wrap: wrap; gap: 10px; }
.total-qtde b { font-size: 19px; font-variant-numeric: tabular-nums; }

/* ================= MRP: de onde vem a necessidade ================= */
/* A demanda que ENTROU no cálculo, dita como insumo. Somada junto com o
   material na tira de totais, ela dominava os números (451.699 UN de
   acabado contra 2.995 KG de aço) e fazia parecer consumo. */
.linha-demanda {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 16px;
  margin: 0 0 10px;
  padding: 8px 14px;
  border-left: 3px solid var(--borda);
  background: var(--fundo);
  border-radius: 0 6px 6px 0;
  font-size: 13px;
  color: var(--texto-fraco);
}
.rotulo-demanda {
  font-weight: 600;
  color: var(--texto);
  text-transform: uppercase;
  font-size: 11.5px;
  letter-spacing: 0.4px;
}
.parcela-demanda b { color: var(--texto); }

/* Dos itens deste tipo, quantos faltam e quantos já estão na prateleira.
   "54 itens de matéria-prima" não distinguia os dois, e é justamente a
   pergunta de quem lê a tela. */
.parte-repor { color: var(--texto); font-weight: 600; }
.parte-estoque { color: var(--texto-fraco); }
.parte-estoque::before { content: "· "; }

/* ============ ordens: material na linha, etapa, ações ============ */
.col-dobra { width: 28px; padding-right: 0 !important; }
.botao-dobra {
  width: 20px; height: 20px; padding: 0;
  border: 1px solid var(--borda);
  border-radius: 4px;
  background: var(--superficie);
  color: var(--texto-fraco);
  cursor: pointer;
  line-height: 1;
}
.botao-dobra::before { content: "+"; font-size: 13px; }
.botao-dobra.aberto::before { content: "−"; }
.botao-dobra:hover { border-color: var(--primaria); color: var(--primaria); }

.linha-bom > td { padding: 0 12px 12px 40px; background: var(--fundo); }
.material-carregando, .material-vazio {
  padding: 10px 0; font-size: 12.5px; color: var(--texto-fraco);
}
/* Cada material numa linha só, lida da esquerda para a direita. Com a
   descricao quebrando em tres linhas nao dava para varrer a lista com o
   olho, que e todo o motivo de abrir a dobra. */
.tabela-material { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.tabela-material td, .tabela-material th { white-space: nowrap; }
/* A descricao e a unica que pode ser longa: corta com reticencias em vez
   de empurrar as colunas de numero para fora da tela. */
.tabela-material td.desc-material {
  max-width: 0;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tabela-material .col-numero { width: 150px; }
.tabela-material th {
  padding: 6px 10px; text-align: left;
  font-size: 11px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--texto-fraco); border-bottom: 1px solid var(--borda);
  white-space: nowrap;
}
.tabela-material th.num, .tabela-material td.num { text-align: right; }
.tabela-material td {
  padding: 5px 10px; border-bottom: 1px solid #eef1f4;
  color: var(--texto-fraco);
}
.tabela-material tbody tr:last-child td { border-bottom: none; }

/* A etapa vira escolha na própria linha: trocar exige abrir a ordem era
   um clique a mais para a operação mais frequente da tela. */
.col-etapa { min-width: 190px; }
.form-etapa { margin: 0; }
select.campo-etapa { width: 100%; font-size: 12.5px; }

.acao-linha { white-space: nowrap; }
.acao-linha .link { font-size: 12.5px; }

/* ==================== quadro por etapa ==================== */
/* Uma coluna por etapa, rolando de lado: o número de etapas vem do
   cadastro da Omie e pode crescer -- espremer todas na largura da tela
   deixaria os cards ilegíveis. */
.chips-visao { margin-top: 14px; }
.chips-visao .chip { cursor: pointer; font-family: inherit; }

.kanban {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  overflow-x: auto;
  padding-bottom: 12px;
  margin-bottom: 14px;
}
.kanban-coluna {
  /* Cresce para ocupar a tela, nunca encolhe.
     `grow: 1` reparte a sobra entre as colunas em vez de deixar um vazio
     à direita; `shrink: 0` com o mesmo valor de base garante que, quando
     as etapas forem muitas, elas passem a rolar de lado em vez de virar
     colunas estreitas demais para caber um card.
     O teto existe porque com duas ou três etapas a coluna chegaria a
     600px e o card ficaria com uma linha de texto perdida no meio. */
  flex: 1 0 300px;
  min-width: 300px;
  max-width: 460px;
  background: var(--fundo);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
}
.kanban-topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--borda);
}
.kanban-topo h3 {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
}
.kanban-conta {
  min-width: 22px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--superficie);
  border: 1px solid var(--borda);
  font-size: 12px;
  color: var(--texto-fraco);
  text-align: center;
}
/* Altura mínima para a coluna vazia continuar aceitando o card: sem ela
   não há onde soltar. */
.kanban-lista {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 90px;
  padding: 10px;
}
.solta-ativa {
  background: var(--andamento-fundo);
  border-radius: 0 0 var(--raio) var(--raio);
}

.kanban-card {
  padding: 10px 12px;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: 6px;
  font-size: 12.5px;
}
.kanban-card[draggable="true"] { cursor: grab; }
.kanban-card[draggable="true"]:active { cursor: grabbing; }
.kanban-card:hover { border-color: var(--primaria); }
.card-arrastando { opacity: .45; }
.card-atrasado { border-left: 3px solid var(--atraso, #d9822b); }

.card-topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}
.card-codigo {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 12px;
  font-weight: 600;
}
.card-desc {
  color: var(--texto-fraco);
  margin-bottom: 8px;
  /* Duas linhas: o card tem de caber na coluna, e a descrição completa
     está no title e no detalhe da ordem. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.card-rodape {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  color: var(--texto-fraco);
  font-size: 12px;
}
.card-qtde { font-weight: 600; color: var(--texto); }
/* Coluna sem ordem continua sendo alvo de arrastar: o texto ocupa o
   espaço e diz que ela está vazia de propósito, não quebrada. */
/* Na folha impressa nao ha cor: o "falta" precisa pesar em preto. */
.folha-falta-tag {
  margin-left: 4px;
  padding: 0 4px;
  border: 1px solid currentColor;
  border-radius: 3px;
  font-size: 10px;
  text-transform: uppercase;
}
.kanban-vazia {
  margin: 0;
  padding: 14px 4px;
  text-align: center;
  font-size: 12px;
  color: var(--texto-fraco);
}
.card-acoes {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid #eef1f4;
  font-size: 12px;
}

/* ============ filtro da lista de compras ============ */
.barra-filtro {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}
.campo-filtro {
  flex: 1 1 auto;
  max-width: 460px;
  padding: 7px 11px;
  font-family: inherit;
  font-size: 13.5px;
  border: 1px solid var(--borda);
  border-radius: 6px;
  background: var(--superficie);
  color: var(--texto);
}
.campo-filtro:focus {
  border-color: var(--primaria);
  outline: 2px solid var(--andamento-fundo);
}

/* O CNPJ acompanha o nome porque há razão social repetida no cadastro com
   códigos diferentes. Em fonte tabular ele alinha e vira coluna de leitura,
   em vez de virar ruído antes do nome. */
.cnpj-fornecedor {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 11.5px;
  color: var(--texto-fraco);
}

/* Os produtos que faltam cadastrar, dentro do próprio aviso: quem quer
   saber *quais são* não deve ter de trocar a visão da tabela e perder a
   tela onde estava. */
.lista-sem-estrutura {
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.lista-sem-estrutura li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  font-size: 13px;
}
.cod-sem-estrutura {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--primaria);
}

/* ============ itens da remessa a terceiros ============ */
/* O motivo da perda é o campo que se lê para decidir o que houve, e vinha
   cortado: o texto mais longo do cadastro ("Matéria-prima fora de
   especificação") mede 214px e o campo tinha 150. Aqui ele cabe inteiro.

   Os 100px extras saem da descrição, que é referência -- quem identifica
   o item é o código, na coluna ao lado. Ela passa a ocupar uma linha só,
   com reticências e o texto completo no title: assim a linha inteira da
   tabela fica com a altura de uma linha, que era o pedido. */
.tabela-itens-terceiros .linha-retorno select.campo-tabela {
  width: 250px;
  flex: 0 0 250px;
}
.tabela-itens-terceiros td.col-larga {
  max-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Colunas de número não precisam de folga além do próprio cabeçalho. */
.tabela-itens-terceiros td.num, .tabela-itens-terceiros th.num {
  white-space: nowrap;
}

/* ============ produtos relacionados pela marca ============ */
/* A Omie guarda no campo Marca do item de dentro o código da peça do
   cliente -- o mesmo do acabado. Esta coluna lê esse vínculo e deixa
   transformá-lo em estrutura sem sair da lista. */
/* Alargar a coluna até caber a descrição na mesma linha custava caro: a
   700px, 97 das 200 descrições do **próprio produto** passavam a quebrar
   em duas linhas -- espaço tirado de quem identifica a linha para dar a
   quem só a confirma.
   
   A descrição do relacionado ganha a linha de baixo dentro da própria
   célula: fica inteira (a maior pede 387px, a célula dá ~470) e não tira
   nada de ninguém. */
.col-relacionado { min-width: 500px; }

/* O código identifica, a descrição reconhece: quem vincula precisa saber
   que peça é antes de gravar na estrutura. Corta com reticências porque a
   linha da tabela não pode crescer por causa dela. */
.desc-relacionado {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 12px;
  color: var(--texto-fraco);
}

.form-vincular {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 5px 6px;
  margin: 0;
}
/* A célula tem duas faixas: o nome em cima, os controles embaixo. Deixar
   os cinco elementos soltos no mesmo flex partia a célula em quatro
   linhas e embaralhava a ordem -- `order` não resolveu, estrutura sim. */
.form-vincular { flex-direction: column; align-items: stretch; }
.relacionado-nome,
.relacionado-controles {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.relacionado-nome .desc-relacionado { flex: 1 1 auto; }
.relacionado-nome select.campo-tabela { width: 100%; max-width: none; }
.form-vincular select.campo-tabela { max-width: 190px; }
.form-vincular .btn { flex: 0 0 auto; }
/* Quantidade quase sempre é 1: um campo largo só chamaria atenção à toa. */
.campo-qtde-vinculo { width: 52px; flex: 0 0 52px; }
.campo-papel { width: 96px; flex: 0 0 96px; font-size: 12px; }

.cod-relacionado {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
}
.relacionado-feito {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px 6px;
  margin-bottom: 3px;
}
.relacionado-feito:last-child { margin-bottom: 0; }

/* ====== ficha do produto: padrão planejado × real medido ====== */
/* O padrão da etapa fica ao lado do título do bloco medido: é contra ele
   que cada máquina é comparada, e ter de subir a tela para lembrar o
   número tornava a coluna "contra o padrão" inútil. */
.padrao-etapa {
  margin-left: 8px;
  font-size: 12px;
  font-weight: 400;
  color: var(--texto-fraco);
}
.bloco-etapa-maquinas h3 .padrao-etapa { font-weight: 400; }
.sem-medicao {
  padding: 10px 14px;
  border: 1px dashed var(--borda);
  border-radius: 6px;
  margin: 0;
}

/* ====== planejamento: ordens e compras lado a lado ====== */
/* Saem do mesmo cálculo e se leem juntas -- "o que vou produzir" e "o que
   preciso comprar para isso". Empilhadas, a segunda ficava fora da tela e
   a pessoa não sabia que existia. */
.par-secoes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  align-items: start;
}
.par-secoes > .etapa { margin-bottom: 0; }
/* Tela estreita: volta a empilhar. Duas tabelas em 500px não se leem. */
@media (max-width: 1200px) {
  .par-secoes { grid-template-columns: 1fr; }
}

.origem-demanda {
  margin: 0 0 10px;
  padding: 7px 12px;
  border-left: 3px solid var(--borda);
  background: var(--fundo);
  border-radius: 0 6px 6px 0;
}

/* ============================================================
   Planejamento em meia tela

   Carteira e Sugestão de Demanda passaram a dividir a largura. Nove
   colunas não cabem em meia tela: o que era coluna virou segunda linha
   da célula. Nada foi escondido -- a informação mudou de lugar, não
   sumiu, e é isso que estas regras sustentam.
   ============================================================ */

/* A busca ao lado dos chips de situação, no espaço que já estava vazio. */
.chips-com-busca { align-items: center; gap: 8px; }
.chips-com-busca .campo-filtro { margin-left: auto; max-width: 320px; }
.chips-com-busca .conta-filtro { margin: 0; }
.conta-filtro { white-space: nowrap; }

/* Célula de duas linhas: a chave em cima, o apoio embaixo. O apoio corta
   com reticências -- deixá-lo quebrar dobrava a altura de toda a tabela
   (medido: 97 de 200 descrições quebravam em duas linhas). O texto
   inteiro fica no `title`. */
/* `table-layout: fixed` é o que faz o ellipsis funcionar: sem largura de
   coluna resolvida, o navegador não tem contra o que cortar e a descrição
   empurra a tabela para fora da meia tela. */
/* `th:nth-child(3) { width: 26% }` morava aqui e custou caro.
   
   Ela foi escrita quando a 3ª coluna da carteira era a descrição do
   produto. A tabela foi reorganizada e a 3ª coluna virou **Material** --
   que precisa de 59px e passou a receber 381, um buraco de 300px no meio
   da tela. E como `th:nth-child(3)` tem especificidade maior que
   `.col-material`, a largura declarada por nome não conseguia corrigir.
   
   A lição ficou: coluna se identifica por classe, nunca por posição. Uma
   reordenação move a regra para a coluna errada em silêncio. */
.tabela-carteira { table-layout: fixed; }

.cel-chave {
  display: inline;
  font-family: ui-monospace, Consolas, monospace;
  font-size: 12.5px;
  font-weight: 600;
}
.cel-apoio {
  display: block;
  color: var(--texto-fraco);
  font-size: 12px;
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.num .cel-apoio { text-align: right; }

/* Etiqueta de apoio dentro de uma célula que já tem número: ela informa
   sem disputar a leitura com o valor. */
.tag-mini {
  display: inline-block;
  margin-top: 2px;
  padding: 1px 6px;
  font-size: 10.5px;
  line-height: 1.5;
  font-weight: 500;
}

.tabela-carteira .col-entrega { width: 104px; white-space: nowrap; }
.tabela-carteira .col-entrega .tag { display: block; margin-top: 2px; }

/* O minigráfico em meia tela: menos largura que na tela cheia, mas as
   barras continuam legíveis porque são poucas (6 a 24 meses). */
.col-serie-estreita { width: 110px; min-width: 96px; }
.col-serie-estreita .serie { height: 26px; }

.col-estoque { width: 116px; }
/* 30px não cabia o checkbox somado ao padding padrão do <th>: faltavam
   2px e a tabela inteira ganhava barra de rolagem. */
.tabela-sugestao .col-marca { width: 34px; padding-left: 8px; padding-right: 4px; }
.tabela-sugestao .col-numero { width: 92px; }
/* Sete colunas em meia tela. Vieram de um pedido explicito: ver a media de
   vendas ao lado do que ja esta em carteira e do minimo, porque e dai que
   sai a sugestao -- e e olhando as tres juntas que se ve se vai faltar ou
   sobrar producao. */
/* Sete cabecalhos de meia tela nao cabem em uma linha so -- "VENDA MES A
   MES" e "MEDIA DE VENDAS" estouravam 33px. Encurtar os nomes era a saida
   facil, mas eles foram pedidos assim, e cada um diz o que a coluna e.
   Deixar quebrar em duas linhas custa uma faixa de cabecalho mais alta e
   preserva os nomes. */
/* `th.num`, e nao so `th`: `.tabela .num` tem duas classes e vence
   `.tabela-sugestao thead th`, que tem uma. Sem o `.num` aqui, as quatro
   colunas de numero continuavam `nowrap` e so elas cortavam o cabecalho. */
.tabela-sugestao thead th,
.tabela-sugestao thead th.num {
  white-space: normal;
  letter-spacing: .2px;
  padding-left: 8px;
  padding-right: 8px;
  vertical-align: bottom;
}
.tabela-sugestao tbody td { padding-left: 8px; padding-right: 8px; }
.tabela-sugestao .col-media { width: 94px; }
.tabela-sugestao .col-carteira { width: 82px; }
.tabela-sugestao .col-estoque { width: 100px; }

/* Número e etiqueta em linhas separadas. `.num` tem `white-space: nowrap`,
   então lado a lado ("16667 Em queda") estouravam a coluna em 23px --
   e o estouro de uma célula vira barra de rolagem na tabela toda. */
.num .tag-mini, .num .un { display: block; width: max-content; margin-left: auto; }
.num .un { margin-top: 1px; }

/* `.aviso-linha` existia para dar a UM aviso o que agora é de todos:
   linha corrida. Sobrou só o tom mais fraco do complemento. */
.aviso-linha > span { color: var(--texto-fraco); }

/* Em meia tela os indicadores viram quatro cartões pequenos, não três
   grandes: o de 165px mínimo estourava a coluna. */
.par-secoes .painel-indicadores {
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 8px;
}
.par-secoes .painel-indicadores .valor { font-size: 21px; }

/* ============================================================
   Controles por seção

   O balcão de filtros ficava no cabeçalho e parecia governar a tela
   inteira. Não governava: cada campo alimentava uma etapa. Agora cada um
   mora na sua, e a caixa fica mais leve que a do cabeçalho -- ela é parte
   da seção, não um painel de comando.
   ============================================================ */
.filtros-secao {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px 14px;
  margin-bottom: 12px;
  padding: 10px 12px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--fundo);
}
.filtros-secao .btn { margin-bottom: 1px; }
.filtros-secao .campo-busca { flex: 1 1 190px; min-width: 150px; }
.filtros-secao .campo-busca input { width: 100%; }

/* Os quatro aspectos do filtro da carteira, lado a lado. Ocupam juntos o
   espaco que era de um campo so, e cada um cresce por igual -- nenhum
   aspecto e mais importante que o outro. A ordem e o mais estreito porque
   o que se digita ali e curto. */
.filtro-aspectos {
  display: flex;
  flex: 1 1 520px;
  gap: 10px;
  flex-wrap: wrap;
  min-width: 0;
}
.filtro-aspectos .campo-busca { flex: 1 1 150px; min-width: 130px; }
.filtro-aspectos .campo-busca:first-child { flex: 0 1 140px; }

/* O recado de que aplicar refaz a lista ocupa a linha inteira, abaixo dos
   campos: quem muda o histórico perde as marcações, e descobrir isso
   depois de marcar trinta itens é caro. */
.aviso-troca { flex: 1 0 100%; margin: 2px 0 0; }

/* A janela do MRP fica dentro do formulário do MRP, sem moldura própria --
   duas caixas encaixadas viram ruído. */
.janela-mrp { border: none; background: none; padding: 0; margin-bottom: 4px; }


/* ============================================================
   A carteira, como a planilha do PCP

   Treze colunas estreitas, uma linha por entrega. `table-layout: fixed`
   porque sem largura resolvida a descrição empurra a tabela para fora da
   tela -- e aqui há duas descrições (o produto do cliente e a peça
   interna) competindo pelo espaço.
   ============================================================ */
/* 1.520px é a conta, não um chute: a coluna mais apertada é Térmico, com
   6,5% para "TEMP. E REVE." (84px + 14 de padding), o que exige uma tabela
   de 1.508px. Abaixo disso a caixa rola na horizontal em vez de cortar --
   valores como "M-12X1,25" e "SAE-1045" não têm espaço para quebrar, e
   cortá-los esconde justamente a medida da peça. A página nunca rola. */
.tabela-carteira { table-layout: fixed; min-width: 1810px; }

/* Larguras em PORCENTAGEM, não em pixel, e somando exatamente 100.
   
   Com pixels, a sobra entre a soma das colunas e a largura da tabela caía
   toda numa coluna só: em 1.850px de tela, Material ficava com 357px
   precisando de 59 -- um buraco de 298px no meio da tabela, que crescia
   junto com o monitor.
   
   As proporções vêm da medição do conteúdo real (o maior valor de cada
   coluna, com a fonte da célula):
   
     Código 296px · Peça interna 488px · Cliente 100 · Térmico 84
     Superficial 75 · Nº Pedido 73 · Rosca 67 · Material 59
     Chave 41 · Altura 26 · Tempo aprox. 46
   
   As duas descrições longas quebram em duas linhas; o resto cabe inteiro.
   
   A coluna Tempo entrou tirando 5 pontos de quem tinha folga (Peça interna
   3, Código 1, ação 1) e a tabela cresceu de 1.520 para 1.660px, de modo
   que nenhuma coluna existente perdeu pixel: Peça interna fica com 324px
   contra os 342 de antes em 1.520, e ganha os 18 de volta na largura nova.
   
   A caixa de marcação veio depois, com 3 pontos (Peça interna 2, Código 1)
   e mais 50px de tabela -- 1.710px. Uma caixa cabe em 51px com folga. */
.tabela-carteira .col-cliente-nome { width: 7%; }
.tabela-carteira .col-codigo { width: 13%; }
.tabela-carteira .col-material { width: 5%; }
.tabela-carteira .col-rosca { width: 6%; }
.tabela-carteira .col-medida { width: 4%; }
.tabela-carteira .col-trat { width: 6.5%; }
.tabela-carteira .col-pedido { width: 6%; }
.tabela-carteira .col-qtde { width: 6.5%; }
.tabela-carteira .col-entrega { width: 6%; }
.tabela-carteira .col-interno { width: 15.5%; }
.tabela-carteira .col-tempo { width: 5%; white-space: nowrap; }
.tabela-carteira .col-acao { width: 4%; }
/* O andamento da ordem: 'Em andamento' cabe em 90px sem quebrar. */
.tabela-carteira .col-status-op { width: 6%; }

.tabela-carteira thead th,
.tabela-carteira thead th.num {
  white-space: normal;
  padding-left: 7px;
  padding-right: 7px;
  vertical-align: bottom;
}
.tabela-carteira tbody td { padding-left: 7px; padding-right: 7px; }

/* A descrição da peça interna é longa (até 79 caracteres no cadastro) e
   quebra em duas linhas em vez de cortar: reticências no meio de
   "TEMP. E REVE. - OLEADO" escondem justamente o tratamento, que é o que
   distingue duas peças de mesma medida. */
.tabela-carteira .col-interno .cel-apoio,
.tabela-carteira .col-codigo .cel-apoio {
  white-space: normal;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

/* De onde o valor veio.

   Um número tirado por expressão regular e um confirmado pela engenharia
   não merecem a mesma confiança na tela. O cadastrado é o texto normal; o
   extraído fica mais fraco e em itálico, para a pessoa ver de relance o
   que ainda precisa ser conferido. */
.origem-cadastro { font-weight: 600; }
.origem-planilha { color: var(--texto); }
.origem-descricao {
  color: var(--texto-fraco);
  font-style: italic;
}

.sem-interno { font-style: italic; }

/* De onde saiu o vínculo com a peça interna.

   A etiqueta aparece em toda linha, e o peso dela diz o quanto o vínculo é
   firme: a estrutura é o cadastro da fábrica e fica discreta -- é o caso
   normal, e gritar 149 vezes o que é normal só cansa a vista. A Marca é
   uma via lateral, e aparece. A semelhança é palpite nosso, e tem de doer
   um pouco na tela até alguém confirmar. */
.vinculo-estrutura {
  background: transparent;
  border: 1px solid var(--borda);
  color: var(--texto-fraco);
}
.vinculo-marca {
  background: var(--fundo);
  border: 1px solid var(--borda);
  color: var(--texto);
}
.vinculo-semelhanca {
  background: var(--atencao-fundo);
  border: 1px solid var(--atencao);
  color: var(--atencao);
  font-style: italic;
  text-decoration: none;
}
a.vinculo-semelhanca:hover { border-color: var(--primaria); }

/* Os atributos técnicos na lista de Produtos.

   Entram no espaço que "Produtos relacionados" ocupava sem usar: ela tinha
   `min-width: 500px` e quase toda célula em "—". Continua sendo a coluna
   mais larga, só que sem sobra. */
/* Estreitas e sem quebra: são valores curtos ("SAE-1045", "M-10", "17").
   Sem `min-width` na descrição, porém, elas roubavam o espaço dela: a
   coluna Descrição caía para 94px e a frase virava uma fita vertical de
   dez linhas. `col-larga` pede `width: 100%` para absorver a folga, e com
   seis colunas novas não sobrava folga nenhuma. */
.col-atributo { width: 82px; white-space: nowrap; }
.tabela th.col-larga { min-width: 320px; }
.col-relacionado { min-width: 260px; }
/* O ciclo por peça: "11 min", "45 min", "1,5 h". Cabe em 84px e não
   quebra -- quebrar um número em duas linhas é pior do que rolar. */
.col-tempo-peca { width: 84px; white-space: nowrap; }

/* O tipo do produto no título da ficha. Um tom por tipo, porque a
   diferença entre em processo e intermediário decide roteiro, remessa e
   MRP -- e as duas palavras se parecem demais para se distinguirem só
   pelo texto. */
.tag-tipo {
  vertical-align: middle;
  margin-left: 10px;
  font-size: 13px;
  font-weight: 600;
  background: var(--fundo-alt, #eef1f5);
  color: var(--texto-fraco);
}
.tag-tipo.tipo-03 { background: var(--andamento-fundo); color: var(--andamento); }
.tag-tipo.tipo-06 { background: var(--atencao-fundo); color: var(--atencao); }
.tag-tipo.tipo-04 { background: var(--ok-fundo); color: var(--ok); }

/* O campo do formulário da ficha: seis lado a lado numa linha só. */
.campo-atributo { flex: 0 1 148px; min-width: 118px; }


/* ============================================================
   Título e indicadores na mesma faixa

   Medido no Planejamento a 1.850px: o texto da seção ocupava 582px de
   1.768, e sobravam **1.186px vazios** à direita do título -- enquanto os
   quatro cartões de indicador tomavam uma faixa própria embaixo,
   empurrando a tabela para baixo.

   Agora dividem a linha: título à esquerda, cartões à direita. Abaixo de
   1.100px voltam a empilhar, porque aí não há sobra para dividir.
   ============================================================ */
.faixa-topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.faixa-topo > .etapa-topo,
.faixa-topo > .cabecalho-pagina { flex: 1 1 380px; margin-bottom: 0; }

/* Aqui os cartões viram uma LINHA, não um grid.
   
   Com `grid` e `auto-fit`, dentro de um item flex que pode encolher, o
   navegador resolveu **uma coluna só**: os quatro cartões viraram um pilar
   de 132px por 260px de altura -- pior do que a faixa que eles ocupavam
   antes. `flex: 0 0 auto` faz a tira valer exatamente a soma dos cartões. */
.faixa-topo > .painel-indicadores {
  display: flex;
  flex: 0 0 auto;
  gap: 10px;
  margin-bottom: 0;
}
.faixa-topo > .painel-indicadores > .indicador { min-width: 108px; }

/* Abaixo de 1.100px não há sobra para dividir: voltam a ocupar a linha. */
@media (max-width: 1100px) {
  .faixa-topo > .painel-indicadores { flex: 1 1 100%; flex-wrap: wrap; }
}


/* ============================================================
   Gantt de carga por data de entrega

   Uma caixa que rola nos DOIS sentidos, com a coluna de produtos grudada à
   esquerda e a régua ao topo por `position: sticky`. É o que evita
   sincronizar dois contêineres rolando em JavaScript -- e sem JS não há o
   que dar errado.

   O desenho é SVG montado no servidor: 64 produtos × 103 dias seriam 6.592
   células de tabela para mostrar 192 barras.

   Cor por CLASSE, nunca por `style=`: a Content-Security-Policy do app é
   `style-src 'self'` e bloqueia estilo inline em silêncio.
   ============================================================ */
.gantt {
  overflow: auto;
  max-height: 560px;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--superficie);
}
.gantt-cabecalho, .gantt-corpo { display: flex; align-items: flex-start; }

/* A régua fica no topo mesmo rolando as 64 linhas. */
.gantt-cabecalho {
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--superficie);
  border-bottom: 1px solid var(--borda);
}

/* A coluna de produtos fica à esquerda mesmo rolando os 103 dias. */
.gantt-canto, .gantt-rotulos {
  position: sticky;
  left: 0;
  z-index: 2;
  flex: 0 0 auto;
  width: 232px;
  background: var(--superficie);
  border-right: 1px solid var(--borda);
}
/* O canto cruza os dois: precisa vencer a régua e a coluna. */
.gantt-canto {
  z-index: 4;
  height: 74px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 2px;
  padding: 0 10px 6px;
}
.gantt-canto-titulo {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--texto-fraco);
}
.gantt-canto-sub { font-size: 10.5px; color: var(--texto-fraco); }

.gantt-rotulo {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "codigo qtde" "peca qtde";
  align-items: center;
  column-gap: 8px;
  height: 26px;                  /* = ALTURA_LINHA do carga.py */
  padding: 0 10px;
  border-bottom: 1px solid var(--borda);
  font-size: 11.5px;
  line-height: 1.15;
}
.gantt-codigo {
  grid-area: codigo;
  font-family: ui-monospace, Consolas, monospace;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gantt-peca {
  grid-area: peca;
  font-size: 10px;
  color: var(--texto-fraco);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gantt-qtde {
  grid-area: qtde;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--texto-fraco);
}
.gantt-rotulo.atrasado .gantt-codigo { color: var(--erro); }

.gantt-regua, .gantt-barras { display: block; flex: 0 0 auto; }

/* ---------- o desenho ---------- */
/* Sábado e domingo em faixa: o dia não útil é informação, não decoração. */
.gantt-fds { fill: var(--fundo); }
.gantt-hoje { fill: var(--andamento-fundo); opacity: .55; }
.gantt-virada { stroke: var(--borda); stroke-width: 1; }
.gantt-linha { stroke: var(--borda); stroke-width: 1; opacity: .5; }
.gantt-chao { stroke: var(--borda); stroke-width: 1; }
.gantt-mes {
  font-size: 10px;
  fill: var(--texto-fraco);
  text-transform: uppercase;
  letter-spacing: .4px;
}
.gantt-dia { font-size: 9.5px; fill: var(--texto-fraco); }
.gantt-dia.fds { opacity: .5; }

.gantt-barra { fill: var(--primaria); opacity: .85; }
.gantt-barra:hover { opacity: 1; }
.gantt-total { fill: var(--texto); opacity: .72; }

/* Entrega já vencida: a barra ganha contorno, não outra cor -- a cor está
   reservada para a capacidade, e duas escalas de cor na mesma barra não se
   leem. */
.gantt-barra.atrasada { stroke: var(--erro); stroke-width: 1; }

/* O semáforo da capacidade. Hoje toda barra é `sit-sem-parametro` e usa a
   cor neutra acima; as três abaixo acendem sozinhas quando houver tempo no
   roteiro e jornada cadastrada. */
.gantt-barra.sit-folgado { fill: var(--ok); }
.gantt-barra.sit-apertado { fill: var(--atencao); }
.gantt-barra.sit-estourado { fill: var(--erro); }

/* ============================================================
   Os chips de competência: uma carteira por mês

   O mês vem da COMPETÊNCIA gravada na linha, não da data de entrega --
   reprogramar muda a entrega e não muda a competência de origem. Sem
   isso, o mês fechado se esvaziava a cada item adiado.
   ============================================================ */
.chips-competencia { margin-bottom: 8px; }
.chips-competencia .chip { font-variant-numeric: tabular-nums; }
.chip-conta {
  margin-left: 5px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--fundo);
  font-size: 11px;
  font-weight: 600;
  color: var(--texto-fraco);
}
.chip.ativo .chip-conta { background: rgba(255, 255, 255, .25); color: inherit; }
/* Mês fechado: o traço diz que ele não recebe mais lançamento. */
.chip-fechada { opacity: .72; }
.chip-cadeado { color: var(--ok); font-weight: 700; }

.btn-chip { padding: 5px 12px; font-size: 13px; }

/* ---------- a tela de fechamento ---------- */
.tabela-fechamento .col-destino { width: 290px; }
.destino-opcao {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 1px 0;
  font-size: 12.5px;
  cursor: pointer;
}
.destino-opcao .campo-num { width: 76px; }
/* O destino padrão em tom mais fraco: ele vale quando ninguém decide, e
   precisa parecer o que é -- o caminho de menor esforço, não uma escolha. */
.destino-padrao span { color: var(--texto-fraco); }

/* Os campos de data do filtro da carteira: quatro numa linha só. Sem
   largura fixa eles herdam o `flex: 1` dos irmãos e empurram a busca de
   produto para a linha de baixo. */
.filtro-data { flex: 0 0 auto; }
.filtro-data input { width: 150px; }

/* A ordem interna vista de perto, no dialogo do Controle de Producao.
   Duas colunas: o rotulo estreito a esquerda, o valor a direita -- e o
   valor pode quebrar em duas linhas sem empurrar o rotulo. */
.ficha-dados {
  display: grid;
  grid-template-columns: 128px 1fr;
  gap: 6px 14px;
  margin: 0 0 14px;
  align-items: baseline;
}
.ficha-dados dt { font-size: 12.5px; color: var(--texto-fraco); }
.ficha-dados dd { margin: 0; }
.ficha-dados dd .cel-apoio { display: block; }

/* ---------- as ordens internas no Controle de Producao ---------- */
/* Dez colunas: a peca que se produz e o produto que se vende, com codigo e
   descricao dos dois. Sem o par lado a lado, quem le a ordem nao liga o
   que saiu da maquina ao que foi vendido. */
.tabela-internas { min-width: 1400px; }
.tabela-internas .col-larga { min-width: 220px; }
/* A coluna de status so mostra o estado. Ela chegou a levar os links de
   mudanca embaixo da tag, e cada linha virou tres alturas -- uma coluna de
   acompanhamento nao e um painel de botoes. */
.tabela-internas .col-status-op { width: 110px; white-space: nowrap; }
/* Ver e imprimir lado a lado, na MESMA linha das informacoes da ordem.
   Com `flex-wrap: wrap` o "imprimir" caia para uma segunda linha e cada
   ordem passava a ocupar duas alturas -- a coluna e estreita, e o botao
   nao cabia ao lado. `nowrap` mais a largura abaixo resolvem: os dois
   controles cabem inteiros na horizontal. */
.acao-dupla {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: nowrap;
  white-space: nowrap;
}
.acao-dupla .btn { flex: 0 0 auto; }
.tabela-internas .col-acao { width: 148px; }
/* A quantidade a produzir e editavel na propria linha: campo curto mais o
   "ok", lado a lado, sem esticar a coluna. */
.col-produzir { width: 132px; }
.form-produzir { display: flex; gap: 5px; align-items: center; justify-content: flex-end; }
.form-produzir .campo-num { width: 74px; }
.tabela-agrupada { min-width: 1100px; }
/* A tabela cresceu com a marcacao e as duas quantidades. */
.tabela-internas { min-width: 1520px; }
.tabela-internas .col-marca { width: 38px; text-align: center; }
.chips-agrupar { display: inline-flex; gap: 6px; }
.cartao-internas { border-left: 3px solid var(--primaria); }

/* ---------- a cascata do OEE ---------- */
/* Os três fatores existiam como números soltos. Três números dizem
   QUANTO, não ONDE -- e o desenho mostra o tempo escorrendo degrau a
   degrau, com a perda que explica cada queda ao lado. */
.cascata-wrap { display: flex; gap: 14px; align-items: flex-start; }
.cascata-trilho { position: relative; flex: 0 0 130px; min-height: 1px; }
.cascata-razao {
  position: absolute;
  left: 0;
  width: 130px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  padding: 4px 8px;
  border-left: 3px solid var(--primaria);
  background: var(--fundo);
  border-radius: 0 6px 6px 0;
}
.razao-nome { font-size: 12px; font-weight: 600; }
.razao-formula { font-size: 11px; color: var(--texto-fraco); }
.razao-valor { font-size: 15px; }
/* A letra do degrau fica FORA do viewBox à esquerda; o padding do SVG a
   traz de volta para dentro da caixa. */
/* `width: 100%` com `preserveAspectRatio="none"`: o desenho estica ate o
   fim da tela em vez de parar nos 900px do viewBox, que deixavam um terco
   da largura vazio a direita. As proporcoes horizontais se mantem porque
   todas as barras dividem a mesma regua. */
.cascata { flex: 1 1 auto; width: 100%; height: auto; min-width: 0; }
.casc-letra { font-size: 13px; font-weight: 700; fill: var(--texto-fraco); }
.casc-texto { font-size: 12px; font-weight: 600; fill: #fff; }
.casc-numero { font-size: 11px; fill: #fff; opacity: .85; }

/* Verde escurecendo para dentro, como no desenho de referência: o tempo
   que sobra a cada degrau é sempre um pedaço do de cima. */
.casc-total { fill: #10401f; }
.casc-programado { fill: #1a7f4b; }
.casc-produzindo { fill: #229b5c; }
.casc-teorica { fill: #2bb26b; }
.casc-real { fill: #35c97b; }
.casc-total-pecas { fill: #45d98a; }
.casc-boas { fill: #5ce89c; }
/* As perdas em lilás, como no desenho -- e o texto delas escurece, porque
   branco sobre lilás claro não se lê. */
.casc-perda-disp, .casc-perda-perf, .casc-perda-qual { fill: #c9c9ee; }
.casc-fora { fill: #e2e2f2; }
.casc-fechado { fill: #f0f0f6; }
.casc-perda-disp ~ .casc-texto { fill: var(--texto); }

.filtros-cascata { display: flex; gap: 10px; align-items: flex-end; margin: 0; }

/* ---------- o calendário do ano, clicável ---------- */
/* Doze meses lado a lado, quantos couberem na largura. É aqui que o sábado
   trabalhado se resolve: clicar num dia inverte, clicar de novo desfaz. */
.ano-grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 18px;
  margin-top: 12px;
}
.mes-grade h3 {
  margin: 0 0 6px;
  font-size: 14px;
  text-transform: capitalize;
}
/* As sete colunas são as mesmas no cabeçalho e nos dias: uma grade só
   desalinharia na primeira semana, que começa com espaços vazios. */
.semana-cabecalho,
.mes-dias {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.semana-cabecalho span {
  text-align: center;
  font-size: 11px;
  color: var(--texto-fraco);
  padding-bottom: 2px;
}
.dia,
.dia-vazio {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  border-radius: 4px;
  border: 1px solid transparent;
}
.dia {
  cursor: pointer;
  font-family: inherit;
  color: var(--texto);
}
.dia:hover { border-color: var(--primaria); }
.dia-util { background: var(--superficie); border-color: var(--borda); }
.dia-folga { background: var(--fundo); color: var(--texto-fraco); }
.dia-parado { background: var(--atencao-fundo); color: var(--atencao); font-weight: 600; }
.dia-trabalhado { background: var(--ok-fundo); color: var(--ok); font-weight: 600; }
/* Hoje ganha contorno, não cor: a cor já diz outra coisa (útil, parado,
   trabalhado), e uma quinta cor tornaria a legenda ilegível. */
.dia-hoje { outline: 2px solid var(--primaria); outline-offset: -2px; }

.legenda-calendario {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
  font-size: 12px;
  color: var(--texto-fraco);
  margin: 8px 0;
}
.dia-legenda {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 3px;
  vertical-align: middle;
}

/* Feriado que cai no fim de semana: fica na lista para a pessoa ver que
   existe, mas em tom fraco -- ele não muda dia útil nenhum. */
.linha-fraca td { color: var(--texto-fraco); }
.campo-estreito { flex: 0 0 90px; }
.campo-larga { flex: 1 1 260px; }

/* ---------- excluir e editar em lote na carteira ---------- */
/* A barra fica ACIMA da tabela e o formulário dela mora fora dela: as
   caixas de dentro apontam para cá por `form="lote-carteira"`, porque
   cada linha já tem o seu próprio form (o "cancelar") e formulário
   aninhado é HTML inválido. */
.barra-lote {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  margin-bottom: 8px;
  border: 1px solid var(--borda);
  border-radius: 8px;
  background: var(--fundo-alt, #f7f8fa);
}
.barra-lote .campo-lote { display: flex; align-items: center; gap: 6px; }
.barra-lote .rotulo-lote { font-size: 13px; color: var(--texto-fraco); }
/* Largura fixa, e não `min-width`: `campo-visivel` dá 100% ao select, que
   esticava para 1.791px e empurrava os botões para uma terceira linha.
   Um valor de carteira ("YANMAR", "2026-08", "Temp. e Reve.") cabe em 200. */
.barra-lote .campo-valor-lote {
  flex: 0 0 200px;
  width: 200px;
  max-width: 200px;
}
/* O cliente é a exceção: 200px cortava "KOMATSU DO BRASIL LTDA" no meio,
   e o nome inteiro é justamente o que se confere antes de aplicar em
   várias linhas. Medido: a razão social mais longa do espelho tem 55
   caracteres, e 380px mostram ~48 -- o resto o `title` completa. */
.barra-lote .campo-cliente-lote {
  flex: 0 1 380px;
  width: 380px;
  max-width: 380px;
}
.barra-lote .campo-cliente-lote input[type="text"] { width: 100%; }
/* A conta do que está marcado ganha peso só quando há algo marcado --
   "nenhuma linha marcada" não precisa chamar atenção. */
.lote-conta { font-size: 13px; color: var(--texto-fraco); }
.lote-conta.tem-marcadas { color: var(--texto); font-weight: 600; }
.barra-lote button[disabled] { opacity: 0.45; cursor: not-allowed; }
.tabela-carteira .col-marca { width: 3%; text-align: center; }

/* ---------- a baixa pela OP concluída ---------- */
/* Uma OP costuma quitar mais de uma entrega -- medido: 41 dos 64 produtos
   da carteira entregam em dois ou mais meses. Cada destino ocupa a sua
   linha para que dê para conferir de relance qual mês foi quitado. */
#tab-baixa .col-larga { width: 300px; }
/* O campo de data herdava o `flex: 1` do formulário em linha e esticava
   para 1.072px -- medido. Uma data ocupa 170. */
.form-marco { align-items: flex-end; gap: 10px; }
.form-marco .campo { flex: 0 0 190px; margin: 0; }
.form-marco .campo input { width: 100%; }
.alocacao {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 1px 0;
  font-size: 12.5px;
  white-space: nowrap;
}

/* ---------- o de-para de cliente ---------- */
.form-cliente { gap: 8px; align-items: center; }
.form-cliente .campo-cliente { flex: 1 1 260px; margin: 0; }
.form-cliente .campo-cliente input { width: 100%; }
