/* ==========================================================================
   Vinheria - tema visual
   Paleta: bordo, dourado envelhecido, verde-garrafa, creme
   ========================================================================== */

:root {
  /* Cores base */
  --bordo:        #722F37;
  --bordo-claro:  #8E3F49;
  --bordo-escuro: #4A1D23;
  --ouro:         #C9A227;
  --ouro-claro:   #E0C05A;
  --ouro-fosco:   #9A7B22;
  --verde:        #1F3B2C;
  --verde-claro:  #2E5540;
  --creme:        #F3EAD9;
  --creme-escuro: #E2D5BC;

  /* Superficies - tema escuro (padrao) */
  --bg:           #16121A;
  --bg-alt:       #1E1820;
  --surface:      #241C27;
  --surface-2:    #2C2331;
  --surface-3:    #362B3C;
  --linha:        #3E3244;
  --linha-forte:  #55465C;

  --texto:        #F0E7DA;
  --texto-suave:  #C3B5AC;
  --texto-fraco:  #8C7F88;

  /* A MARCA DA PLATAFORMA NA BARRA LATERAL.
   *
   * Tokens próprios, e não reaproveitamento de --creme e --ouro. A lateral
   * tem fundo PRÓPRIO (um gradiente que não sai da paleta), então a cor que
   * a torna legível não é a mesma que serve ao resto da tela. Reaproveitar
   * --creme foi exatamente o que fez "VINHE" sumir no modo claro: --creme é
   * a cor do papel do rótulo, quase branca, e a lateral clara também é.
   *
   * Estes são os valores de repouso, para quando o dono desligou "aplicar ao
   * tema ao sistema". Com o tema ligado, temas.js os sobrescreve com cores
   * CALCULADAS para bater a razão de contraste da WCAG contra o fundo real
   * da lateral, paleta a paleta. */
  --marca-tinta:  #F0E7DA;
  --marca-acento: #C9A227;
  --marca-sub:    #A2949B;

  --ok:           #4E8C5E;
  --alerta:       #C98A2B;
  --perigo:       #B3453F;
  --info:         #4A6E8C;

  /* Formas */
  --r-sm: 6px;
  --r-md: 10px;
  --r-lg: 16px;
  --r-xl: 24px;

  --sombra-sm: 0 2px 6px rgba(0,0,0,.30);
  --sombra-md: 0 8px 24px rgba(0,0,0,.35);
  --sombra-lg: 0 18px 48px rgba(0,0,0,.45);

  --serif: "Cormorant Garamond", "Playfair Display", Georgia, serif;
  --sans: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;

  --nav-w: 232px;
  --topo-h: 64px;
}

:root[data-theme="light"] {
  --bg:           #F6F1E8;
  --bg-alt:       #EFE8DC;
  --surface:      #FFFFFF;
  --surface-2:    #F7F2E9;
  --surface-3:    #EDE4D5;
  --linha:        #DDD1BE;
  --linha-forte:  #C4B49B;
  --texto:        #2A2028;
  --texto-suave:  #5C4F58;
  --texto-fraco:  #8C7F88;

  /* No modo claro a lateral é quase branca: a marca precisa ser ESCURA.
     Era aqui que "VINHE" sumia, pintado com a cor do papel do rótulo. */
  --marca-tinta:  #4A1D23;
  --marca-acento: #7A6014;
  --marca-sub:    #5C4F58;
  --sombra-sm: 0 2px 6px rgba(74,29,35,.08);
  --sombra-md: 0 8px 24px rgba(74,29,35,.12);
  --sombra-lg: 0 18px 48px rgba(74,29,35,.16);
}

/* ==========================================================================
   Reset e base
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

body {
  background: var(--bg);
  background-image:
    radial-gradient(ellipse 900px 600px at 12% -8%, rgba(114,47,55,.30), transparent 60%),
    radial-gradient(ellipse 700px 500px at 92% 4%, rgba(201,162,39,.10), transparent 62%),
    radial-gradient(ellipse 800px 700px at 50% 108%, rgba(31,59,44,.22), transparent 60%);
  background-attachment: fixed;
  color: var(--texto);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 600;
  letter-spacing: .01em;
  margin: 0 0 .4em;
  line-height: 1.2;
}

h1 { font-size: 2.1rem; }
h2 { font-size: 1.6rem; }
h3 { font-size: 1.25rem; }

a { color: var(--ouro-claro); text-decoration: none; }
a:hover { color: var(--ouro); text-decoration: underline; }

p { margin: 0 0 1em; }

::selection { background: var(--bordo); color: var(--creme); }

/* Barra de rolagem */
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--linha-forte);
  border-radius: 99px;
  border: 3px solid transparent;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--bordo-claro); background-clip: content-box; }

/* ==========================================================================
   Utilitarios
   ========================================================================== */

.oculto { display: none !important; }
.centro { text-align: center; }
.flex { display: flex; }
.itens-centro { align-items: center; }
.entre { justify-content: space-between; }
.gap-8 { gap: 8px; } .gap-12 { gap: 12px; }
.gap-16 { gap: 16px; }
.crescer { flex: 1; }
.mt-8 { margin-top: 8px; } .mt-16 { margin-top: 16px; } .mt-24 { margin-top: 24px; }
.mb-8 { margin-bottom: 8px; } .mb-16 { margin-bottom: 16px; } .mb-24 { margin-bottom: 24px; }

.texto-suave { color: var(--texto-suave); }
.texto-fraco { color: var(--texto-fraco); }
.texto-ouro  { color: var(--ouro-claro); }
/* Número que pede ação: tarefa atrasada, prazo estourado. Fica ao lado das
   outras utilidades de cor para não virar um estilo inline em cada tela. */
.texto-perigo { color: var(--perigo); }
/* Um degrau abaixo do perigo: ainda não quebrou, mas vai. Barrica no sexto
   uso, lote sem responsável, contraprova sem etiqueta — coisas que pedem
   olho, não socorro. Sem esta classe, cada tela improvisava o próprio
   amarelo em estilo inline, e o tom mudava de tela para tela. */
.texto-alerta { color: var(--alerta); }
.pequeno { font-size: .82rem; }
.mono { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }

/* Filete dourado decorativo */
.filete {
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--ouro-fosco), transparent);
  border: 0;
  margin: 20px 0;
}

/* ==========================================================================
   Botoes
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 9px 18px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  background: var(--surface-2);
  color: var(--texto);
  font-family: var(--sans);
  font-size: .9rem;
  font-weight: 500;
  cursor: pointer;
  transition: background .16s, border-color .16s, transform .08s, color .16s;
  white-space: nowrap;
  white-space: nowrap;
  /* O .btn tem de ficar IGUAL em qualquer elemento que o vista.
   *
   * "Importar backup" é um <label> com input de arquivo escondido, porque
   * <button> não abre seletor de arquivo. Só que a regra genérica `label`
   * mais abaixo aplica maiúsculas, espaçamento entre letras e margem
   * inferior — e o .btn não desfazia nada disso. O resultado era um botão
   * 5 px mais alto que os vizinhos, deslocado, e com o texto em caixa alta
   * enquanto os outros dois estavam em caixa mista.
   *
   * Estas quatro linhas não mudam nada nos <button>, que já têm esses
   * valores por padrão; elas existem para o <label> e para qualquer <a>
   * que venha a usar a classe. */
  line-height: 1.2;
  letter-spacing: normal;
  text-transform: none;
  margin: 0;
}
.btn:hover { background: var(--surface-3); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn:focus-visible { outline: 2px solid var(--ouro); outline-offset: 2px; }

.btn-primario {
  background: linear-gradient(180deg, var(--bordo-claro), var(--bordo));
  border-color: var(--bordo-escuro);
  color: var(--creme);
  box-shadow: var(--sombra-sm);
}
.btn-primario:hover { background: linear-gradient(180deg, #9C4751, var(--bordo-claro)); }

.btn-ouro {
  background: linear-gradient(180deg, var(--ouro-claro), var(--ouro));
  border-color: var(--ouro-fosco);
  color: #2A2008;
  font-weight: 600;
}
.btn-ouro:hover { background: linear-gradient(180deg, #EDD07A, var(--ouro-claro)); }

.btn-fantasma {
  background: transparent;
  border-color: var(--linha-forte);
  color: var(--texto-suave);
}
.btn-fantasma:hover { border-color: var(--ouro-fosco); color: var(--ouro-claro); background: transparent; }

.btn-perigo { background: transparent; border-color: var(--perigo); color: #E08A85; }
.btn-perigo:hover { background: rgba(179,69,63,.16); }

.btn-sm { padding: 5px 11px; font-size: .8rem; }
.btn-icone {
  padding: 7px;
  width: 34px; height: 34px;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--texto-fraco);
}
.btn-icone:hover { background: var(--surface-3); color: var(--ouro-claro); }

/* ==========================================================================
   Formularios
   ========================================================================== */

label, .rotulo {
  display: block;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--texto-fraco);
  margin-bottom: 6px;
}

/* A LISTA É POR TIPO, e um tipo esquecido some do estilo inteiro.
 *
 * `month` faltava, e o seletor de mês do Gantt saiu cru do navegador — fundo
 * branco, borda de sistema, altura própria — ao lado de botões estilizados.
 * Não é um defeito daquela tela: é o preço de enumerar tipos. Um seletor
 * `input:not([type=checkbox]):not([type=radio])...` evitaria a classe inteira
 * de bug, mas pegaria `range`, `file` e `submit`, que têm desenho próprio
 * logo abaixo — e desfazer três estilos para não esquecer um sai mais caro.
 * Ficou a lista, agora com os tipos de data todos juntos. */
input[type=text], input[type=password], input[type=number],
input[type=date], input[type=month], input[type=time], input[type=datetime-local],
input[type=search], input[type=email], select, textarea {
  width: 100%;
  padding: 9px 12px;
  background: var(--bg-alt);
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
  color: var(--texto);
  font-family: var(--sans);
  font-size: .92rem;
  transition: border-color .16s, box-shadow .16s;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--ouro-fosco);
  box-shadow: 0 0 0 3px rgba(201,162,39,.16);
}
input::placeholder { color: var(--texto-fraco); }
textarea { resize: vertical; min-height: 80px; }

select {
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path d='M2 4l4 4 4-4' fill='none' stroke='%238C7F88' stroke-width='1.6' stroke-linecap='round'/></svg>");
  background-repeat: no-repeat;
  background-position: right 10px center;
  padding-right: 30px;
}

.campo { margin-bottom: 16px; }

/* Busca com icone */
.busca { position: relative; }
.busca input { padding-left: 34px; }
.busca .fa-magnifying-glass {
  position: absolute;
  left: 12px; top: 50%;
  transform: translateY(-50%);
  color: var(--texto-fraco);
  font-size: .85rem;
  pointer-events: none;
}

/* Grupo de opcoes (radio estilizado) */
.opcoes { display: flex; gap: 8px; flex-wrap: wrap; }
.opcoes input[type=radio] { position: absolute; opacity: 0; pointer-events: none; }
.opcoes label {
  margin: 0;
  padding: 8px 16px;
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
  background: var(--bg-alt);
  color: var(--texto-suave);
  font-size: .86rem;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  cursor: pointer;
  transition: all .16s;
}
.opcoes label:hover { border-color: var(--linha-forte); color: var(--texto); }
.opcoes input[type=radio]:checked + label {
  background: var(--bordo);
  border-color: var(--bordo-claro);
  color: var(--creme);
}
.opcoes input[type=radio]:focus-visible + label { outline: 2px solid var(--ouro); outline-offset: 2px; }

/* ==========================================================================
   Cartoes e paineis
   ========================================================================== */

.cartao {
  background: var(--surface);
  border: 1px solid var(--linha);
  border-radius: var(--r-md);
  padding: 20px;
  box-shadow: var(--sombra-sm);
}

.cartao-ouro {
  position: relative;
  border-color: var(--ouro-fosco);
}
.cartao-ouro::before {
  content: "";
  position: absolute; inset: 3px;
  border: 1px solid rgba(201,162,39,.22);
  border-radius: calc(var(--r-md) - 3px);
  pointer-events: none;
}

.cartao-titulo {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--serif);
  font-size: 1.2rem;
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--linha);
}
.cartao-titulo i { color: var(--ouro); font-size: .95rem; }

/* CARTÃO QUE É LINK.
   Existia como `.tile-link`, uma classe extra que era preciso lembrar de
   escrever — e que sumiu junto com a unificação dos tiles, deixando um
   cartão da cervejaria sem o gesto de hover. Como `a.cartao`, todo
   cartão-âncora ganha o comportamento por ser o que é, sem ninguém
   precisar lembrar de nada. */
a.cartao {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: border-color .16s, transform .12s;
}
a.cartao:hover {
  text-decoration: none;
  transform: translateY(-2px);
  border-color: var(--linha-forte);
}
a.cartao:focus-visible { outline: 2px solid var(--ouro); outline-offset: 2px; }

.grade { display: grid; gap: 16px; }
.grade-2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grade-3 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.grade-4 { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }

/* Etiquetas */
.etiqueta {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border-radius: 99px;
  font-size: .74rem;
  font-weight: 600;
  letter-spacing: .03em;
  background: var(--surface-3);
  color: var(--texto-suave);
  border: 1px solid var(--linha);
}
.etiqueta-ouro   { background: rgba(201,162,39,.14); color: var(--ouro-claro); border-color: rgba(201,162,39,.35); }
.etiqueta-bordo  { background: rgba(114,47,55,.28);  color: #E9A7AC; border-color: rgba(142,63,73,.5); }
.etiqueta-verde  { background: rgba(78,140,94,.16);  color: #8FD3A2; border-color: rgba(78,140,94,.4); }
.etiqueta-alerta { background: rgba(201,138,43,.16); color: #EFC176; border-color: rgba(201,138,43,.4); }
.etiqueta-perigo { background: rgba(179,69,63,.18);  color: #EDA09B; border-color: rgba(179,69,63,.45); }

/* ==========================================================================
   Layout da aplicacao
   ========================================================================== */

.app { display: flex; min-height: 100vh; }

/* --- Barra lateral --- */
.lateral {
  width: var(--nav-w);
  flex-shrink: 0;
  background: linear-gradient(180deg, rgba(30,24,32,.96), rgba(22,18,26,.98));
  border-right: 1px solid var(--linha);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  z-index: 20;
}

.marca {
  padding: 22px 20px 18px;
  border-bottom: 1px solid var(--linha);
  text-align: center;
}
.marca-nome {
  font-family: var(--serif);
  font-size: 1.6rem;
  font-weight: 600;
  /* --marca-tinta, e NÃO --creme: ver o comentário no :root. A cor do papel
     do rótulo não serve para pintar texto sobre a barra lateral. */
  color: var(--marca-tinta);
  letter-spacing: .08em;
  line-height: 1;
}
.marca-nome span { color: var(--marca-acento); }

/* Logomarca da organização + nome, lado a lado.
   A margem que antes era do .marca-sub subiu para cá: com a imagem ao lado,
   quem precisa de respiro em relação ao nome da plataforma é a LINHA
   inteira, e não só o texto dela. */
.marca-org {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 7px;
  min-width: 0;
}
/* A altura é obrigatória, e o object-fit também.
   Logomarca é arquivo que vem de fora: pode ter 2000px de lado, e sem regra
   de tamanho o navegador a desenha no tamanho natural — foi exatamente assim
   que a logo do Nori engoliu a página inteira no rótulo impresso uma vez. */
.marca-logo {
  height: 24px;
  width: auto;
  max-width: 68px;
  object-fit: contain;
  flex-shrink: 0;
  display: block;
}
.marca-sub {
  font-size: .64rem;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--marca-sub);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Prévia da logomarca nas Configurações.
   O xadrez claro/escuro é proposital: quase toda logomarca chega com fundo
   transparente, e sobre um retângulo liso não dá para saber se o branco ao
   redor das letras é do arquivo ou da tela. No xadrez, dá. */
.marca-previa {
  width: 132px;
  height: 88px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
  border: 1px dashed var(--linha-forte);
  border-radius: var(--r-md);
  background-color: var(--surface-2);
  background-image:
    linear-gradient(45deg, rgba(128,128,128,.10) 25%, transparent 25%),
    linear-gradient(-45deg, rgba(128,128,128,.10) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, rgba(128,128,128,.10) 75%),
    linear-gradient(-45deg, transparent 75%, rgba(128,128,128,.10) 75%);
  background-size: 14px 14px;
  background-position: 0 0, 0 7px, 7px -7px, -7px 0;
  flex-shrink: 0;
}
.marca-previa img { max-width: 100%; max-height: 100%; object-fit: contain; }

.menu { flex: 1; padding: 10px 10px 14px; overflow-y: auto; }

/* ==========================================================================
   Seções colapsáveis da lateral
   ==========================================================================

   Sete seções e dezenove itens não cabem na altura útil de um portátil, e a
   lateral vivia rolando — a pessoa perdia de vista onde estava para alcançar
   Administração no fim. Colapsar resolve sem esconder nada de ninguém: o que
   sai da tela é o que a própria pessoa fechou.

   O ESTADO É DO APARELHO, como o tema e o modo. Um operador que trabalha o dia
   todo em Produção fecha as outras e o navegador lembra; no computador do lado
   a escolha é outra, porque quem usa é outra pessoa. Guardar isso no servidor
   transformaria uma preferência de tela numa configuração de conta.

   ABREM TODAS, no primeiro acesso. O contrário — tudo fechado — economizaria
   mais espaço e faria a interface parecer vazia para quem nunca a viu: sete
   palavras e nenhum caminho. */
.menu-secao { margin-bottom: 2px; }
/* Pelo mesmo motivo do `.menu-item[hidden]` mais abaixo: a seção inteira some
   quando o papel não alcança nenhum item dela, e um bloco vazio ainda ocuparia
   a margem entre as vizinhas. */
.menu-secao[hidden] { display: none; }

.menu-grupo {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 9px 12px 7px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--texto-fraco);
  font: inherit;
  font-size: .64rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  cursor: pointer;
  text-align: left;
  transition: color .15s, background .15s;
}
.menu-grupo:hover { color: var(--texto-suave); background: var(--surface-2); }

.menu-grupo-icone { font-size: .78rem; width: 15px; text-align: center; opacity: .75; }
/* O TEXTO NÃO VAZA. Com `letter-spacing` de .18em, "ESTATÍSTICAS" já ocupa
   quase toda a largura útil — e numa lateral estreita ele empurrava a seta
   para fora. `min-width: 0` é o que permite ao flex encolher o span; sem ele
   um filho de flex se recusa a ficar menor que o próprio conteúdo. */
.menu-grupo-texto {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.menu-grupo-seta {
  font-size: .62rem;
  opacity: .55;
  transition: transform .18s ease;
  flex-shrink: 0;
}

/* A ANIMAÇÃO É POR `grid-template-rows`, e não por `max-height`.
 *
 * `max-height` exige um número chutado maior que o conteúdo — e o chute erra
 * duas vezes: pequeno demais corta o último item, grande demais faz a transição
 * parecer que trava no fim, porque metade do tempo é gasto animando um vazio.
 * `1fr → 0fr` anima a altura REAL, seja ela qual for. */
.menu-itens {
  display: grid;
  grid-template-rows: 1fr;
  transition: grid-template-rows .2s ease;
}
/* O EMBRULHO INTERNO É OBRIGATÓRIO, e não estilo.
 *
 * A linha de grade que encolhe é a EXPLÍCITA. Com os itens soltos aqui, só o
 * primeiro cairia nela e os outros iriam para linhas implícitas de altura
 * automática — a seção fecharia o primeiro item e deixaria os demais na tela.
 * Um filho único garante que tudo o que existe está na linha que anima. */
.menu-lista { min-height: 0; }
.menu-secao.fechada .menu-itens { grid-template-rows: 0fr; }
.menu-secao.fechada .menu-lista { overflow: hidden; }
.menu-secao.fechada .menu-grupo-seta { transform: rotate(-90deg); }

/* SEÇÃO FECHADA COM O ITEM ATIVO DENTRO acende no cabeçalho.
 *
 * Sem isto, fechar a seção em que se está apaga a única pista de onde a pessoa
 * está — a lateral inteira fica sem nada aceso, e a tela aberta passa a não
 * ter lugar no menu. O ponto dourado devolve a pista sem reabrir nada. */
.menu-secao.fechada.tem-ativo .menu-grupo { color: var(--ouro-claro); }
.menu-secao.fechada.tem-ativo .menu-grupo-icone { opacity: 1; color: var(--ouro); }

@media (prefers-reduced-motion: reduce) {
  .menu-itens, .menu-grupo-seta { transition: none; }
}

.menu-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  color: var(--texto-suave);
  font-size: .9rem;
  cursor: pointer;
  text-decoration: none;
  border-left: 2px solid transparent;
  transition: background .15s, color .15s, border-color .15s;
}
.menu-item:hover { background: var(--surface-2); color: var(--texto); text-decoration: none; }

/* O ATRIBUTO `hidden` TEM DE VENCER O `display: flex` ACIMA.
 *
 * `[hidden] { display: none }` é regra da folha do NAVEGADOR, e regra de folha
 * do navegador perde para qualquer regra de autor com seletor de classe. Sem
 * esta linha, `el.hidden = true` em app.js não escondia coisa nenhuma:
 * "Culturas" aparecia na vinícola e na licoreira, e o painel da casa aparecia
 * numa organização de um ambiente só — justamente os dois itens que o
 * JavaScript acreditava ter escondido. */
.menu-item[hidden] { display: none; }
.menu-item i { width: 17px; text-align: center; font-size: .92rem; color: var(--texto-fraco); }
.menu-item.ativo {
  background: linear-gradient(90deg, rgba(114,47,55,.42), transparent);
  color: var(--creme);
  border-left-color: var(--ouro);
}
.menu-item.ativo i { color: var(--ouro); }
.menu-item .contador {
  margin-left: auto;
  font-size: .72rem;
  padding: 1px 7px;
  border-radius: 99px;
  background: var(--surface-3);
  color: var(--texto-fraco);
}

/* ==========================================================================
   Rodapé da lateral — quem entrou, e com que chapéu
   ==========================================================================

   Duas faixas, e não uma linha só. Na versão anterior tudo dividia a mesma
   linha: avatar, nome, papel, seletor de modo e o botão de sair. O seletor
   ficava espremido numa coluna de uns cem pixels, e "Administração" vazava por
   cima da própria seta.

   Agora a identidade ocupa a primeira faixa e o seletor a segunda, com a
   largura inteira. Trocar de chapéu não é um detalhe do nome de quem entrou —
   é a decisão que muda a lateral toda. */
.rodape-lateral {
  padding: 10px 10px 12px;
  border-top: 1px solid var(--linha);
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex-shrink: 0;
}

.rodape-identidade {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 2px;
  min-width: 0;
}

/* `min-width: 0` NÃO É REDUNDANTE AQUI.
 *
 * Um filho de flex se recusa a encolher abaixo do próprio conteúdo, e sem esta
 * linha um nome de usuário comprido empurra o botão de sair para fora da
 * lateral em vez de virar reticências. É a mesma razão em toda parte deste
 * arquivo onde ela aparece ao lado de um `text-overflow`. */
.rodape-quem { flex: 1; min-width: 0; }

.rodape-nome {
  font-size: .86rem;
  color: var(--texto);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rodape-papel {
  font-size: .72rem;
  color: var(--texto-fraco);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-top: 1px;
}

/* O botão de sair fica DISCRETO até o cursor chegar perto, e vermelho quando
   chega. É a única ação destrutiva da lateral, e a única que não tem desfazer
   — mas anunciá-la em vermelho o tempo todo faria a lateral terminar num
   alarme. */
.rodape-sair {
  flex-shrink: 0;
  color: var(--texto-fraco);
  transition: color .15s, background .15s;
}
.rodape-sair:hover { color: var(--perigo); background: var(--surface-2); }

.avatar {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--bordo), var(--bordo-escuro));
  border: 1px solid var(--ouro-fosco);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--serif);
  font-size: .92rem;
  color: var(--creme);
  flex-shrink: 0;
  text-transform: uppercase;
}

/* --- Area principal --- */
.principal { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.topo {
  height: var(--topo-h);
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 0 28px;
  border-bottom: 1px solid var(--linha);
  background: rgba(22,18,26,.72);
  backdrop-filter: blur(10px);
  position: sticky;
  top: 0;
  z-index: 15;
}
:root[data-theme="light"] .topo { background: rgba(246,241,232,.8); }
:root[data-theme="light"] .lateral {
  background: linear-gradient(180deg, #FFFDF8, #F3EDE2);
}

.topo-titulo { font-family: var(--serif); font-size: 1.35rem; margin: 0; }
.topo-acoes { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.conteudo {
  flex: 1;
  padding: 28px;
  max-width: 1440px;
  width: 100%;
  margin-left: auto;
  margin-right: auto;
}

.menu-hamburguer { display: none; }

/* ==========================================================================
   Estado vazio
   ========================================================================== */

.vazio {
  text-align: center;
  padding: 64px 24px;
  color: var(--texto-fraco);
}
.vazio i { font-size: 2.6rem; color: var(--linha-forte); margin-bottom: 16px; display: block; }
.vazio h3 { font-family: var(--serif); color: var(--texto-suave); margin-bottom: 6px; }

/* ==========================================================================
   Tela de login
   ========================================================================== */

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

.login-caixa {
  width: 100%;
  max-width: 400px;
  background: var(--surface);
  border: 1px solid var(--ouro-fosco);
  border-radius: var(--r-lg);
  padding: 40px 34px 32px;
  box-shadow: var(--sombra-lg);
  position: relative;
}
.login-caixa::before {
  content: "";
  position: absolute; inset: 5px;
  border: 1px solid rgba(201,162,39,.18);
  border-radius: calc(var(--r-lg) - 5px);
  pointer-events: none;
}

.login-marca { text-align: center; margin-bottom: 28px; }
.login-marca .taca { font-size: 2.2rem; color: var(--marca-acento); margin-bottom: 10px; }
/* Os mesmos tokens da barra lateral, pelo mesmo motivo: aqui o nome da
   plataforma também era pintado com --creme, a cor do papel do rótulo, e
   sumia inteiro no modo claro. Esta é a PRIMEIRA tela que alguém vê. */
.login-marca h1 {
  font-size: 2.3rem;
  letter-spacing: .1em;
  color: var(--marca-tinta);
  margin-bottom: 4px;
}
.login-marca h1 span { color: var(--marca-acento); }
.login-marca .sub {
  font-size: .66rem;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--texto-fraco);
}

.login-erro {
  background: rgba(179,69,63,.15);
  border: 1px solid rgba(179,69,63,.45);
  color: #EDA09B;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  font-size: .85rem;
  margin-bottom: 14px;
}

/* ==========================================================================
   Avisos (toasts)
   ========================================================================== */

.avisos {
  position: fixed;
  bottom: 22px; right: 22px;
  display: flex; flex-direction: column; gap: 10px;
  z-index: 100;
  max-width: 380px;
}
.aviso {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--surface-2);
  border: 1px solid var(--linha-forte);
  border-left: 3px solid var(--ouro);
  border-radius: var(--r-sm);
  padding: 12px 15px;
  box-shadow: var(--sombra-md);
  font-size: .88rem;
  animation: entra .22s ease;
}
.aviso.ok     { border-left-color: var(--ok); }
.aviso.erro   { border-left-color: var(--perigo); }
.aviso.alerta { border-left-color: var(--alerta); }
.aviso i { margin-top: 2px; }
.aviso.ok i     { color: #8FD3A2; }
.aviso.erro i   { color: #EDA09B; }
.aviso.alerta i { color: #EFC176; }

@keyframes entra {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ==========================================================================
   Responsivo
   ========================================================================== */

@media (max-width: 900px) {
  .lateral {
    position: fixed;
    left: 0; top: 0;
    transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: var(--sombra-lg);
  }
  .lateral.aberta { transform: translateX(0); }
  .menu-hamburguer { display: inline-flex; }
  .conteudo { padding: 18px; }
  .topo { padding: 0 16px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ==========================================================================
   Tabelas
   ========================================================================== */

.tabela {
  width: 100%;
  border-collapse: collapse;
  font-size: .86rem;
}
.tabela th {
  text-align: left;
  padding: 9px 12px;
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texto-fraco);
  border-bottom: 1px solid var(--linha-forte);
  white-space: nowrap;
  position: sticky;
  top: 0;
  background: var(--surface);
}
.tabela td {
  padding: 9px 12px;
  border-bottom: 1px solid var(--linha);
  vertical-align: top;
}
.tabela tbody tr:hover { background: var(--surface-2); }
.tabela tbody tr:last-child td { border-bottom: 0; }
.tabela td b { font-weight: 600; }

/* ==========================================================================
   Ajuda contextual nos títulos de coluna
   ========================================================================== */

.com-ajuda {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  cursor: help;
  border-bottom: 1px dotted var(--linha-forte);
  padding-bottom: 1px;
}
.com-ajuda i {
  font-size: .72rem;
  color: var(--linha-forte);
  transition: color .15s;
}
.com-ajuda:hover { border-bottom-color: var(--ouro); color: var(--ouro-claro); }
.com-ajuda:hover i { color: var(--ouro); }

.legenda-unidades {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 10px 13px;
  border: 1px dashed var(--linha-forte);
  border-radius: var(--r-sm);
  background: rgba(201,162,39,.06);
  font-size: .82rem;
  color: var(--texto-suave);
  line-height: 1.5;
}
.legenda-unidades i { color: var(--ouro); margin-top: 3px; flex-shrink: 0; }
.legenda-unidades b { color: var(--ouro-claro); font-weight: 600; }

/* ==========================================================================
   Ficha técnica
   ========================================================================== */

/* ==========================================================================
   FICHA — a linha de "rótulo à esquerda, valor à direita"

   O componente mais reusado do sistema, e o que mais partia texto.

   Era `grid-template-columns: 1fr auto`. Numa grade, a coluna `auto` pega toda
   a largura de que precisa e a `1fr` fica com o resto — então um valor
   comprido ("24 meses após o envase · consumir até 03/2028") espremia o rótulo
   até ele quebrar em três linhas de duas palavras. O valor cabia inteiro; a
   pergunta é que virava confete.

   Agora é FLEX COM QUEBRA, e a diferença é o que acontece quando os dois não
   cabem juntos: em vez de esmagar um deles, o valor desce inteiro para a linha
   de baixo. Um texto que não cabe muda de linha como uma unidade — ele não se
   fragmenta.

   As três linhas que fazem isso funcionar:
     `flex-wrap: wrap`   permite a quebra em vez do esmagamento
     `min-width` no rótulo  garante largura legível antes de qualquer quebra
     `margin-left: auto` no valor mantém a direita quando os dois cabem
   ========================================================================== */
.ficha-linha {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--linha);
}
.ficha-linha:last-child { border-bottom: 0; }

/* O rótulo não encolhe abaixo do legível: sem este piso, ele volta a se
   partir em vez de deixar o valor descer. */
.ficha-rotulo {
  font-size: .82rem;
  color: var(--texto-suave);
  min-width: 7rem;
  flex: 0 1 auto;
}

/* `margin-left: auto` alinha à direita enquanto os dois estão na mesma linha,
   e some sozinho quando o valor quebra para a linha de baixo. */
.ficha-valor {
  font-size: .95rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  margin-left: auto;
  flex: 0 1 auto;
  overflow-wrap: anywhere;
}

/* A ajuda ocupa a largura inteira, abaixo dos dois. Era `grid-column: 1 / -1`;
   em flex, o equivalente é uma base de 100%. */
.ficha-ajuda {
  flex: 0 0 100%;
  font-size: .74rem;
  color: var(--texto-fraco);
  line-height: 1.45;
}

.alerta-linha {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 13px;
  margin-bottom: 8px;
  border-radius: var(--r-sm);
  border-left: 3px solid var(--alerta);
  background: rgba(201,138,43,.10);
  font-size: .86rem;
  line-height: 1.5;
}
.alerta-linha i { color: #EFC176; margin-top: 3px; }
.alerta-linha.bloqueio {
  border-left-color: var(--perigo);
  background: rgba(179,69,63,.14);
}
.alerta-linha.bloqueio i { color: #EDA09B; }
.alerta-linha.info {
  border-left-color: var(--info);
  background: rgba(74,110,140,.12);
}
.alerta-linha.info i { color: #9BC0DB; }

.mult-exemplo .tabela th { font-size: .64rem; }
.mult-exemplo .tabela td { padding: 6px 10px; font-size: .82rem; }

input[type=range] {
  -webkit-appearance: none;
  appearance: none;
  height: 6px;
  border-radius: 99px;
  background: var(--surface-3);
  outline: none;
}
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: linear-gradient(180deg, var(--ouro-claro), var(--ouro));
  border: 1px solid var(--ouro-fosco);
  cursor: pointer;
  box-shadow: 0 2px 5px rgba(0,0,0,.4);
}
input[type=range]::-moz-range-thumb {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--ouro);
  border: 1px solid var(--ouro-fosco);
  cursor: pointer;
}

.check-linha {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  font-size: .88rem;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--texto);
  cursor: pointer;
}
.check-linha input { width: auto; accent-color: var(--bordo-claro); }

/* ==========================================================================
   Sala de containers
   ========================================================================== */

.cont-grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 16px;
}

.cont-cartao {
  display: flex;
  gap: 14px;
  background: var(--surface);
  border: 1px solid var(--linha);
  border-radius: var(--r-md);
  padding: 16px;
  box-shadow: var(--sombra-sm);
  transition: border-color .16s, transform .12s;
}
.cont-cartao:hover { border-color: var(--linha-forte); transform: translateY(-2px); }
.cont-cartao.ocupado { border-left: 3px solid var(--bordo-claro); }

.cont-visual { position: relative; flex-shrink: 0; width: 78px; }
.cont-svg { width: 78px; height: 108px; display: block; }
.cont-nivel {
  position: absolute;
  bottom: 2px; left: 0; right: 0;
  text-align: center;
  font-size: .72rem;
  font-weight: 700;
  color: var(--creme);
  text-shadow: 0 1px 3px rgba(0,0,0,.8);
}

.cont-info { flex: 1; min-width: 0; }
.cont-cabeca { display: flex; align-items: center; gap: 8px; margin-bottom: 2px; }
.cont-codigo { font-family: var(--serif); font-size: 1.15rem; }
.cont-nome { font-size: .82rem; color: var(--texto-fraco); margin-bottom: 8px; }

.cont-meta { display: flex; flex-direction: column; gap: 3px; margin-bottom: 8px; }
.cont-meta span { font-size: .78rem; color: var(--texto-suave); }
.cont-meta i { width: 14px; color: var(--texto-fraco); margin-right: 4px; }

.cont-estagios { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 8px; }
.cont-estagios .etiqueta { font-size: .66rem; padding: 1px 7px; }

.cont-lote {
  font-size: .8rem;
  padding: 7px 9px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  margin-bottom: 7px;
}
.cont-lote i { color: var(--bordo-claro); margin-right: 5px; }

.cont-reservas {
  font-size: .76rem;
  color: var(--texto-fraco);
  margin-top: 6px;
}
.cont-reservas i { color: var(--ouro-fosco); margin-right: 5px; }

.cont-alerta {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font-size: .74rem;
  color: #EFC176;
  margin-top: 6px;
  line-height: 1.4;
}

.cont-acoes { display: flex; gap: 6px; margin-top: 10px; }

/* ==========================================================================
   Modal
   ========================================================================== */

.modal-fundo {
  position: fixed;
  inset: 0;
  background: rgba(10,7,12,.72);
  backdrop-filter: blur(3px);
  display: flex;
  /* `flex-start` FICA, e quem centraliza é a margem automática da caixa.
   *
   * O caminho óbvio seria `align-items: center`, e ele tem um defeito
   * conhecido: quando o conteúdo passa da altura da tela, o item centralizado
   * transborda para CIMA — e o topo fica fora da área rolável, inalcançável
   * por qualquer rolagem. A ficha de análise da amostra e a folha de rótulo
   * são altas o bastante para cair nisso.
   *
   * Margem automática no eixo transversal vence o `align-items` e não tem
   * esse problema: sobrando espaço ela centraliza; faltando, resolve para
   * zero e a caixa volta a rolar normalmente a partir do topo. */
  align-items: flex-start;
  justify-content: center;
  padding: 5vh 20px;
  overflow-y: auto;
  z-index: 80;
}
.modal-caixa {
  /* Ver o comentário do `.modal-fundo`: é esta linha que centraliza. */
  margin-block: auto;
  width: 100%;
  max-width: 620px;
  background: var(--surface);
  border: 1px solid var(--ouro-fosco);
  border-radius: var(--r-lg);
  padding: 24px;
  box-shadow: var(--sombra-lg);
}

/* ==========================================================================
   Contenção de altura — nenhum card cresce sem limite
   ========================================================================== */

/* Área rolável padrão para tabelas e listas longas dentro de um card */
.rolavel {
  max-height: 380px;
  overflow-y: auto;
  overflow-x: auto;
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
  background: var(--bg-alt);
}
.rolavel .tabela { margin: 0; }
.rolavel .tabela th {
  background: var(--surface-2);
  box-shadow: 0 1px 0 var(--linha-forte);
}
.rolavel-alto { max-height: 560px; }
.rolavel-baixo { max-height: 240px; }

/* Sombra sutil indicando que há mais conteúdo abaixo */
.rolavel::after { content: ""; display: block; height: 1px; }

/* O card cresce com o conteúdo. Quem rola é a PÁGINA.
 *
 * Aqui havia `.cartao { max-height: 78vh }` com o comentário "o conteúdo rola
 * dentro dele em vez de esticar a página". Só que o `.cartao` nunca teve
 * `overflow` — sem isso, `max-height` não contém coisa alguma: o conteúdo
 * excedente simplesmente TRANSBORDA a caixa e é pintado por cima do que vem
 * depois. Somado a `flex-shrink: 1` + `min-height: 0` nos filhos, que os
 * deixava encolher abaixo do próprio conteúdo, o resultado era um `.campo` de
 * 7 px com 87 px de texto dentro, e uma `.grade` de 23 px com 254 px.
 *
 * A tela de Configurações era o pior caso — o card fiscal pedia 711 px e
 * recebia 412 px — mas o defeito valia para os 156 cards do sistema. A regra
 * nunca funcionou como anunciada: ela só produzia sobreposição.
 *
 * A contenção de verdade é a `.rolavel` logo acima, que tem `max-height` E
 * `overflow-y: auto`. É ela que deve embrulhar tabela e lista longa.
 */
.cartao { display: flex; flex-direction: column; }
.cartao-titulo { flex-shrink: 0; }

/* Linha de químico desmarcada */
.linha-desativada { opacity: .42; }
.linha-desativada b { text-decoration: line-through; }
.linha-desativada:hover { opacity: .7; }

.tabela input[type=checkbox] {
  width: 17px; height: 17px;
  accent-color: var(--bordo-claro);
  cursor: pointer;
}

/* Etiquetas dentro de células ficam menores para não quebrar o ritmo */
.tabela .etiqueta { font-size: .64rem; padding: 1px 6px; margin-left: 5px; }

/* Barras de rolagem internas mais discretas */
.rolavel::-webkit-scrollbar { width: 9px; height: 9px; }
.rolavel::-webkit-scrollbar-thumb {
  background: var(--linha-forte);
  border-radius: 99px;
  border: 2px solid transparent;
  background-clip: content-box;
}

@media (max-height: 800px) {
  .rolavel { max-height: 300px; }
}

/* ==========================================================================
   Lotes e linha do tempo
   ========================================================================== */

.lote-grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
  gap: 16px;
}

/* ==========================================================================
   Cartão de receita
   ==========================================================================

   O texto vazava por três razões, e nenhuma delas era tamanho de fonte:

     1. um `<b>` dentro de um flex NÃO encolhe abaixo do próprio conteúdo sem
        `min-width: 0` — o nome comprido empurrava as estrelas para fora;
     2. a lista de insumos de uma receita de corte escrevia quatro linhas e
        empurrava os botões para além da borda do cartão;
     3. a fila de cinco botões não quebrava linha, e numa coluna de 330 px o
        último saía pela direita.

   O cartão agora é uma coluna com altura cheia, o nome tem reticências, os
   insumos param em duas linhas e os botões quebram. */
.rec-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  margin: 0;
}

.rec-card-topo {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  min-width: 0;
}
.rec-card-nome {
  flex: 1;
  min-width: 0;
  font-family: var(--serif);
  font-size: 1.1rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rec-card-coracao { color: var(--bordo-claro); flex-shrink: 0; }
.rec-card-nota { flex-shrink: 0; white-space: nowrap; }

/* DUAS LINHAS E RETICÊNCIAS. `line-clamp` faz o corte no meio da palavra
   errada de vez em quando; a alternativa — altura fixa com `overflow: hidden`
   — corta letras pela metade na horizontal, que é pior. O `title` no elemento
   devolve a lista inteira a quem passar o cursor. */
.rec-card-insumos {
  font-size: .82rem;
  color: var(--texto-suave);
  line-height: 1.4;
  margin-bottom: 10px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* `margin-top: auto` empurra a meta e os botões para o rodapé, e é o que
   alinha a fileira inteira quando uma receita tem menos texto que a vizinha. */
.rec-card-meta { margin-top: auto; margin-bottom: 10px; }

.rec-card-acoes {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* O RODAPÉ DE REGISTRO, e por que ele é uma faixa e não mais dois botões
   no fim da mesma fila. Ler a ficha e usar a receita para abrir um lote é o
   trabalho de quem produz — fica na linha de cima, centralizada. Favoritar e
   apagar mexem no que a casa registra como sendo o produto dela; são de outra
   natureza, e por isso ganham chão próprio, com fundo e linha de separação.
   Misturados na mesma fila, faziam a pessoa procurar "Usar" entre dois
   quadradinhos.

   `space-evenly` é literalmente o padrão X botão X botão X: o mesmo vão
   antes do primeiro, entre os dois e depois do segundo. Os dois botões
   ganharam texto justamente para isso — só com os ícones eles somavam 70 px
   numa faixa de 300 e os vãos ficavam largos demais para os dois parecerem um
   par. As margens negativas sangram a faixa até a borda do cartão, cancelando
   os 20 px de `padding` do `.cartao`. */
.rec-card-rodape {
  display: flex;
  align-items: center;
  justify-content: space-evenly;
  gap: 8px;
  flex-wrap: wrap;
  margin: 14px -20px -20px;
  padding: 10px 14px;
  background: var(--surface-2);
  border-top: 1px solid var(--linha);
  border-radius: 0 0 var(--r-md) var(--r-md);
}

.lote-cartao {
  background: var(--surface);
  border: 1px solid var(--linha);
  border-radius: var(--r-md);
  overflow: hidden;
  cursor: pointer;
  transition: border-color .16s, transform .12s, box-shadow .16s;
  box-shadow: var(--sombra-sm);
}
.lote-cartao:hover {
  border-color: var(--ouro-fosco);
  transform: translateY(-3px);
  box-shadow: var(--sombra-md);
}
.lote-faixa { height: 5px; }
.lote-corpo { padding: 16px; }
.lote-codigo { font-family: var(--serif); font-size: 1.05rem; }
.lote-nome { font-size: 1.05rem; font-weight: 600; margin-bottom: 8px; }

.lote-frutas { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; }
.lote-frutas span {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: .78rem; color: var(--texto-suave);
}
.lote-frutas .ponto { width: 9px; height: 9px; }

.lote-meta { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 12px; }
.lote-meta span { font-size: .78rem; color: var(--texto-fraco); }
.lote-meta i { margin-right: 4px; }

.lote-progresso { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.lote-barra {
  flex: 1; height: 6px; border-radius: 99px;
  background: var(--surface-3); overflow: hidden;
}
.lote-barra > div {
  height: 100%;
  background: linear-gradient(90deg, var(--bordo-claro), var(--ouro));
  transition: width .3s;
}

.lote-proxima {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 9px 11px; border-radius: var(--r-sm);
  background: var(--surface-2); font-size: .8rem;
}
.lote-proxima i { color: var(--ouro); margin-top: 3px; }

/* --------------------------------- linha do tempo --------------------- */

.linha-tempo {
  position: relative;
  max-height: 60vh;
  overflow-y: auto;
  padding-left: 6px;
}
.linha-tempo::before {
  content: "";
  position: absolute;
  left: 22px; top: 12px; bottom: 12px;
  width: 2px;
  background: var(--linha);
}

.et-linha {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 12px 11px 0;
  cursor: pointer;
  border-radius: var(--r-sm);
  transition: background .15s;
}
.et-linha:hover { background: var(--surface-2); }

.et-marco {
  position: relative;
  z-index: 1;
  width: 34px; height: 34px;
  flex-shrink: 0;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-3);
  border: 2px solid var(--linha-forte);
  color: var(--texto-fraco);
  font-size: .82rem;
}
.et-linha.feita .et-marco {
  background: rgba(78,140,94,.2);
  border-color: #4E8C5E;
  color: #8FD3A2;
}
.et-linha.atrasada .et-marco {
  background: rgba(179,69,63,.2);
  border-color: var(--perigo);
  color: #EDA09B;
  animation: pulsa 2s infinite;
}
.et-linha.pulada .et-marco { opacity: .45; }

@keyframes pulsa {
  0%, 100% { box-shadow: 0 0 0 0 rgba(179,69,63,.5); }
  50%      { box-shadow: 0 0 0 6px rgba(179,69,63,0); }
}

.et-corpo { flex: 1; min-width: 0; }
.et-topo { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.et-topo b { font-size: .92rem; }
.et-linha.feita .et-topo b { color: var(--texto-suave); }
.et-linha.pulada .et-topo b { text-decoration: line-through; opacity: .6; }
.et-data { font-size: .76rem; color: var(--texto-fraco); margin-top: 3px; }
.et-data i { margin-right: 4px; }
.et-acao { color: var(--linha-forte); font-size: .8rem; }
.et-linha:hover .et-acao { color: var(--ouro); }

.et-instrucoes {
  padding: 16px;
  background: var(--bg-alt);
  border-radius: var(--r-sm);
  font-size: .88rem;
  line-height: 1.65;
  color: var(--texto-suave);
  max-height: 320px;
  white-space: normal;
}

/* ==========================================================================
   Adega
   ========================================================================== */

.adega-grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
  gap: 14px;
}

.gf-cartao {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: linear-gradient(180deg, var(--surface), var(--bg-alt));
  border: 1px solid var(--linha);
  border-radius: var(--r-md);
  padding: 14px 10px 12px;
  cursor: pointer;
  transition: transform .14s, border-color .14s, box-shadow .14s;
  text-align: center;
}
.gf-cartao:hover {
  transform: translateY(-4px);
  border-color: var(--ouro-fosco);
  box-shadow: var(--sombra-md);
}
.gf-cartao.aberta { opacity: .78; }
.gf-cartao.aberta .gf-svg { filter: grayscale(.35); }

.gf-svg { width: 56px; height: 158px; display: block; }
.gf-visual { margin-bottom: 8px; }

.gf-info { width: 100%; }
.gf-codigo { font-family: var(--serif); font-size: .95rem; color: var(--creme); }
.gf-lote {
  font-size: .8rem; color: var(--texto-suave);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  margin-bottom: 6px;
}
.gf-frutas { display: flex; gap: 3px; justify-content: center; margin-bottom: 6px; }
.gf-frutas .ponto { width: 8px; height: 8px; }
.gf-meta {
  display: flex; gap: 8px; justify-content: center;
  font-size: .72rem; color: var(--texto-fraco); margin-bottom: 5px;
}
.gf-fase { font-size: .74rem; font-weight: 600; margin-bottom: 3px; }
.gf-idade { font-size: .68rem; color: var(--texto-fraco); }
.gf-nota { margin-top: 5px; font-size: .68rem; }
.gf-fase-grande { font-size: .95rem; }

/* ------------------------------- avaliação ---------------------------- */

.aval-grade {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 4px 20px;
}
.aval-linha {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 7px 0;
  border-bottom: 1px solid var(--linha);
}
/* O rótulo é quem cede espaço, mas nunca até virar texto vertical.
 *
 * `.aval-estrelas` tem `flex-shrink: 0` — e tinha de ter, senão as estrelas se
 * amassam umas nas outras. Só que sem `min-width: 0` aqui, TODO o aperto caía
 * no rótulo: numa coluna de 230 px ele era espremido a 114 px e "Intensidade
 * das notas" quebrava em três linhas, empilhado na vertical. */
.aval-rotulo {
  font-size: .86rem;
  color: var(--texto-suave);
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: break-word;
}
/* Estrelas um pouco menores: são cinco por linha, e cada pixel a menos aqui é
   um pixel a mais para o rótulo antes de ele precisar quebrar. */
.aval-estrelas { display: flex; gap: 2px; flex-shrink: 0; }
.aval-estrelas i {
  cursor: pointer;
  color: var(--linha-forte);
  font-size: .95rem;
  transition: color .12s, transform .12s;
}
.aval-estrelas i.fa-solid { color: var(--ouro); }
.aval-estrelas:hover i { transform: scale(1.08); }

/* Escala de alvo (JAR): 3 é o acerto, e por isso fica no meio e marcado
   com um alvo em vez de um número — a leitura precisa ser "cheguei no
   ponto", não "tirei 3 de 5". */
.aval-linha { display: grid; grid-template-columns: 1fr auto auto; }

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

/* ==========================================================================
   Receita reversa — "o que dá para fazer hoje"
   ========================================================================== */

.rv-grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 16px;
}

.rv-cartao {
  background: var(--surface);
  border: 1px solid var(--linha);
  border-left: 3px solid var(--cor-fruta, var(--bordo));
  border-radius: var(--r-md);
  padding: 16px;
  box-shadow: var(--sombra-sm);
  transition: border-color .16s, transform .12s;
}
.rv-cartao:hover { transform: translateY(-2px); box-shadow: var(--sombra-md); }

.rv-cabeca {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}
.rv-cabeca b { font-family: var(--serif); font-size: 1.12rem; }
.rv-cabeca .etiqueta { margin-left: auto; }

.rv-aroma {
  font-size: .78rem;
  color: var(--texto-fraco);
  margin-bottom: 12px;
  min-height: 1.1em;
}

.rv-destaque {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 10px 12px;
  border-radius: var(--r-sm);
  background: var(--bg-alt);
  margin-bottom: 6px;
}
.rv-numero {
  font-family: var(--serif);
  font-size: 1.6rem;
  font-weight: 600;
  color: var(--ouro-claro);
  line-height: 1;
}
.rv-legenda {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--texto-fraco);
}

.rv-obs {
  font-size: .74rem;
  color: var(--texto-fraco);
  line-height: 1.45;
  margin-bottom: 12px;
}

.rv-dados {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 12px;
  margin: 0 0 10px;
  align-items: baseline;
}
.rv-dados dt {
  font-size: .74rem;
  color: var(--texto-fraco);
  white-space: nowrap;
}
.rv-dados dd {
  margin: 0;
  font-size: .84rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.rv-notas {
  border-top: 1px dashed var(--linha);
  padding-top: 10px;
}
.rv-notas-rotulo {
  display: block;
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--texto-fraco);
  margin-bottom: 6px;
}
.rv-notas .etiqueta { margin: 0 4px 4px 0; }

@media (max-width: 520px) {
  .rv-dados { grid-template-columns: 1fr; gap: 2px; }
  .rv-dados dd { text-align: left; margin-bottom: 6px; }
}

/* ==========================================================================
   Rótulo da garrafa — a prévia
   ==========================================================================

   O DESENHO DO RÓTULO NÃO ESTÁ MAIS AQUI.

   Ele é gerado por static/js/rotulos/formatos.js, em milímetros, e injetado
   num <style> junto da prévia. Foi assim que a tela e o papel deixaram de ser
   dois desenhos parecidos e passaram a ser o mesmo: as regras que existiam
   neste bloco estavam em pixel, as da impressão em milímetro, e as duas
   divergiam a cada ajuste.

   O que sobra aqui é só o PALCO: onde a prévia é apoiada dentro do modal.
   Ele não sabe nada sobre rótulo — nem medida, nem cor, nem fonte. */

.rot-palco {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: flex-start;
  justify-content: center;
  padding: 16px;
  border-radius: var(--r-md);
  background: var(--surface-2);
  /* Rótulo de growler tem 165 mm; num modal estreito ele estouraria a caixa
     e empurraria o layout inteiro. A rolagem é do palco, não da página. */
  overflow-x: auto;
}

/* ==========================================================================
   Painel
   ========================================================================== */

/* ==========================================================================
   TILE — o cartão de número que abre quase toda tela
   ==========================================================================

   Ícone à esquerda, número grande, rótulo embaixo, filete colorido na borda.
   Aparece em sete telas, e por muito tempo existiu em sete cópias de estilo
   INLINE, com tamanhos de fonte que discordavam entre si (1,35rem numa tela,
   1,4rem noutra, 1,5rem na terceira).

   A oitava cópia — a da Vitrine — tentou fazer certo e usou classes. Só que as
   classes nunca foram escritas: `.tile`, `.tile-icone`, `.tile-valor` e
   `.tile-rotulo` não existiam em folha nenhuma. O resultado é o pior tipo de
   defeito de CSS, porque não é erro: os `div` viraram blocos comuns, o número
   e o rótulo desceram para baixo da caixinha do ícone, e a tela continuou
   "funcionando".

   A LIÇÃO, e ela vale para toda classe nova: uma classe usada e não definida
   NÃO causa erro, NÃO aparece no console e NÃO quebra o teste de renderização.
   Ela silenciosamente desmonta o layout. É por isso que `verificar-ui.js`
   confere isto — e é por isso que ele precisa estar funcionando de verdade.

   O TEXTO NÃO VAZA, e três linhas garantem:
     `min-width: 0`      deixa o bloco de texto encolher dentro do flex
     `flex-shrink: 0`    impede o ícone de ser espremido até sumir
     `overflow-wrap`     quebra palavra comprida em vez de esticar o cartão
   ========================================================================== */
.tile {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--linha);
  border-left: 3px solid var(--linha-forte);
  border-radius: var(--r-md);
  min-width: 0;
}

/* O ícone tem tamanho próprio e NÃO encolhe: um flex sem `flex-shrink: 0`
   espreme o ícone antes do texto, e o resultado é um símbolo achatado ao lado
   de um número inteiro. */
.tile-icone {
  flex-shrink: 0;
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--r-sm);
  font-size: 1.25rem;
}

/* `min-width: 0` É O QUE IMPEDE O VAZAMENTO.
   Um filho de flex se recusa a ficar menor que o próprio conteúdo, e um rótulo
   comprido empurrava o cartão inteiro em vez de quebrar dentro dele. */
.tile-texto {
  min-width: 0;
  flex: 1;
}

.tile-valor {
  font-family: var(--serif);
  font-size: 1.42rem;
  line-height: 1.15;
  color: var(--texto);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

.tile-rotulo {
  font-size: .78rem;
  color: var(--texto-fraco);
  line-height: 1.3;
  margin-top: 2px;
  overflow-wrap: anywhere;
}

/* A variante clicável. Herda tudo e só acrescenta o gesto. */
a.tile { text-decoration: none; transition: border-color .16s, transform .12s; }
a.tile:hover {
  text-decoration: none;
  transform: translateY(-2px);
  border-color: var(--linha-forte);
}
a.tile:focus-visible { outline: 2px solid var(--ouro); outline-offset: 2px; }

.agenda-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--linha);
  color: var(--texto);
  text-decoration: none;
  transition: background .15s;
}
.agenda-item:hover { background: var(--surface-2); text-decoration: none; }
.agenda-item:last-child { border-bottom: 0; }
.agenda-item.atrasada { border-left: 3px solid var(--perigo); }
.agenda-item.hoje { border-left: 3px solid var(--ouro); }

.agenda-data {
  flex-shrink: 0;
  width: 46px;
  font-family: var(--serif);
  font-size: .9rem;
  color: var(--texto-suave);
  text-align: center;
}
.agenda-item.atrasada .agenda-data { color: #EDA09B; }
.agenda-corpo { flex: 1; min-width: 0; }
.agenda-corpo b { display: block; font-size: .88rem; font-weight: 600; }
.agenda-corpo span { display: block; font-size: .74rem; }
.agenda-item > i { color: var(--linha-forte); font-size: .75rem; }

.agenda-grupo {
  font-size: .66rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--texto-fraco);
  padding: 12px 12px 5px;
  background: var(--surface-2);
  position: sticky;
  top: 0;
  z-index: 1;
}

.passo-cartao {
  display: flex;
  gap: 14px;
  padding: 16px;
  border: 1px solid var(--linha);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--texto);
  text-decoration: none;
  transition: border-color .16s, transform .12s;
}
.passo-cartao:hover {
  text-decoration: none;
  border-color: var(--ouro-fosco);
  transform: translateY(-2px);
}
.passo-num {
  flex-shrink: 0;
  width: 30px; height: 30px;
  border-radius: 50%;
  background: var(--bordo);
  color: var(--creme);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--serif);
  font-size: 1rem;
}
.passo-cartao i { color: var(--ouro); margin-right: 5px; }

/* ==========================================================================
   Refino final: acessibilidade e telas pequenas
   ========================================================================== */

/* Visível apenas para leitores de tela */
.sr-apenas {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Atalho para pular o menu; aparece só quando recebe o foco pelo teclado */
.pular-menu {
  position: absolute; left: 12px; top: -60px; z-index: 200;
  background: var(--ouro); color: #1a1208;
  padding: 10px 16px; border-radius: var(--r-sm);
  font-weight: 600; text-decoration: none;
  transition: top .16s ease;
}
.pular-menu:focus { top: 12px; }

/* Foco de teclado consistente em tudo que é navegável.
   `.menu-grupo` entrou na lista quando virou <button>: um cabeçalho de seção
   que abre e fecha é alcançável por Tab, e sem anel de foco quem navega por
   teclado não sabe que chegou nele. */
.menu-item:focus-visible,
.menu-grupo:focus-visible,
.btn-icone:focus-visible,
.gf-cartao:focus-visible,
.cont-cartao:focus-visible,
.lote-cartao:focus-visible,
.rv-cartao:focus-visible,
a:focus-visible {
  outline: 2px solid var(--ouro);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

/* Tabela larga nunca empurra a página: rola dentro do próprio bloco */
.tabela-rolavel {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.tabela-rolavel .tabela { min-width: 520px; }

@media (max-width: 640px) {
  .conteudo { padding: 14px; }
  .topo-titulo {
    font-size: 1.1rem;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .cartao { padding: 14px; }
  .tabela { font-size: .8rem; }
  .tabela th, .tabela td { padding: 7px 8px; }
  .grade { gap: 12px; }
  /* Ações em coluna para não estourar a largura */
}

/* Telas muito estreitas: uma coluna sempre */
@media (max-width: 420px) {
  .grade-2, .grade-3, .grade-4 { grid-template-columns: 1fr; }
}

/* Campo numérico compacto, usado na conferência do que foi realmente usado */
.campo-mini {
  width: 100%;
  padding: 5px 8px;
  font-size: .84rem;
  font-family: ui-monospace, monospace;
  background: var(--surface-2);
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
  color: var(--texto);
}
.campo-mini:focus {
  outline: none;
  border-color: var(--ouro);
  background: var(--surface-3);
}

/* ==========================================================================
   Abas de navegação dentro de uma tela
   ========================================================================== */

/* FILEIRA DE ABAS É UM OBJETO ÚNICO, e objeto único se centraliza.
 *
 * Encostada na margem esquerda com espaço vazio à direita, ela parece um erro
 * de alinhamento em vez de uma escolha — e a assimetria fica mais evidente
 * quanto mais larga a tela. A aba de Configurações já era centralizada; estas
 * ficaram para trás, e a diferença entre telas era o que mais se notava.
 *
 * A regra que separa os dois casos: conjunto FECHADO de controles irmãos, que
 * cabe numa linha, centraliza. Conteúdo que se lê em sequência — tabela,
 * lista, formulário — alinha à esquerda, porque a margem esquerda constante é
 * o que deixa o olho varrer uma coluna de cima a baixo. */
.abas {
  display: flex; gap: 4px; flex-wrap: wrap;
  justify-content: center;
  border-bottom: 1px solid var(--linha);
  padding-bottom: 0;
}
.aba {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 16px;
  background: transparent;
  border: 1px solid transparent;
  border-bottom: 2px solid transparent;
  color: var(--texto-fraco);
  font-family: var(--sans);
  font-size: .88rem; font-weight: 500;
  cursor: pointer;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  transition: color .14s, border-color .14s, background .14s;
}
.aba:hover { color: var(--texto-suave); background: var(--surface-2); }
.aba.ativa {
  color: var(--ouro-claro);
  border-bottom-color: var(--ouro);
  background: var(--surface-2);
}
.aba:focus-visible { outline: 2px solid var(--ouro); outline-offset: -2px; }

/* Barra de proporção compacta, usada dentro de tabelas */
.barra-mini {
  height: 6px; width: 100%; max-width: 120px;
  background: var(--surface-3);
  border-radius: 99px;
  overflow: hidden;
  margin-bottom: 3px;
}
.barra-mini > div {
  height: 100%;
  background: linear-gradient(90deg, var(--bordo-claro), var(--ouro));
  border-radius: 99px;
}

/* Linha de tabela em destaque (processo em curso) */
.tabela tbody tr.linha-ativa { background: rgba(201,162,39,.10); }
.tabela tbody tr.linha-ativa td { border-bottom-color: var(--ouro-fosco); }

/* Container clicável */
.cont-cartao { cursor: pointer; }

/* ==========================================================================
   Prévia do engarrafamento
   ========================================================================== */

.ev-resumo {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 20px;
  align-items: start;
}
.ev-resumo-num {
  display: flex; flex-direction: column;
  padding-right: 20px;
  border-right: 1px solid var(--linha);
}
.ev-resumo-num b {
  font-family: var(--serif);
  font-size: 1.5rem;
  line-height: 1.1;
  color: var(--ouro-claro);
}
.ev-resumo-lista {
  margin: 0; padding: 0; list-style: none;
  font-size: .86rem;
  font-variant-numeric: tabular-nums;
}
.ev-resumo-lista li { padding: 1px 0; color: var(--texto-suave); }
.ev-resumo-sobra {
  grid-column: 2;
  margin-top: 6px;
  font-size: .82rem;
  color: var(--texto-fraco);
}

@media (max-width: 640px) {
  .ev-resumo { grid-template-columns: 1fr; }
  .ev-resumo-num { border-right: 0; padding-right: 0; padding-bottom: 8px; }
  .ev-resumo-sobra { grid-column: 1; }
}

/* ==========================================================================
   Vitrine
   ========================================================================== */

/* Abas também funcionam como links (Adega usa <a>) */
a.aba { text-decoration: none; }
a.aba:hover { text-decoration: none; }

.aba-cont {
  display: inline-block;
  min-width: 20px; padding: 1px 6px;
  border-radius: 99px;
  background: var(--surface-3);
  color: var(--texto-fraco);
  font-size: .72rem; font-weight: 600;
  text-align: center;
}
.aba.ativa .aba-cont { background: var(--ouro); color: #1a1208; }
.aba-cont:empty { display: none; }

.vt-cartao { position: relative; }
.vt-cartao.escolhida {
  border-color: var(--ouro);
  box-shadow: 0 0 0 1px var(--ouro) inset;
}
.vt-check {
  position: absolute; top: 8px; left: 8px; z-index: 2;
  width: 18px; height: 18px;
  accent-color: var(--ouro);
  cursor: pointer;
}
.vt-preco {
  font-family: var(--serif);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--ouro-claro);
  margin-top: 2px;
}
.vt-preco.sem {
  font-family: var(--sans);
  font-size: .78rem;
  font-weight: 500;
  color: var(--perigo);
}

/* ==========================================================================
   Avaliação em dois passos
   ========================================================================== */

.aval-passo {
  margin-left: auto;
  font-family: var(--sans);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--texto-fraco);
}

/* Passo 1: só rótulo e estrelas, sem a coluna de alvo que confundia */
/* Última defesa contra o rótulo vertical: se mesmo assim não couber rótulo e
   estrelas lado a lado, as estrelas descem para a linha de baixo. Duas linhas
   legíveis valem mais que uma linha ilegível. */
.aval-linha-simples {
  display: flex; align-items: center; justify-content: space-between;
  gap: 4px 12px; padding: 7px 0;
  border-bottom: 1px solid var(--linha);
  flex-wrap: wrap;
}

/* Passo 2: escala de alvo de 1 a 10 */
.jar-lista { display: grid; gap: 18px; }

.jar-item { display: grid; gap: 5px; }

.jar-cabeca {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px;
}
.jar-rotulo { font-size: .9rem; color: var(--texto); }
.jar-leitura {
  font-size: .8rem; font-weight: 600;
  text-align: right;
}

/* O degradê é uma camada própria e o range fica transparente por cima.
   Estilizar o input direto não funciona: input[type=range] tem especificidade
   maior que uma classe e vence a regra do degradê. */
.jar-trilha {
  position: relative;
  height: 8px;
  border-radius: 99px;
  /* Mesma cor das pontas do degradê: as tampas de 9 px que sobram de cada
     lado emendam sem costura visível. */
  background: #8E2A2A;
}
/* O degradê vive SÓ no trecho que a alça percorre.
   Uma alça de 18 px anda de 9 px até (largura - 9 px), então um degradê de
   ponta a ponta ficaria deslocado em relação ao valor.

   Com a escala de 0 a 10, pct = v / 10 x 100 — o alvo cai exatamente no meio
   da barra, e a faixa verde de 4,5 a 5,5 ocupa de 45% a 55%, simétrica.
     v=2,5 -> 25%   v=4,5 -> 45%   v=5 -> 50%   v=5,5 -> 55%   v=7,5 -> 75% */
.jar-degrade {
  position: absolute;
  top: 0; bottom: 0; left: 9px; right: 9px;
  border-radius: 99px;
  background: linear-gradient(90deg,
    #8E2A2A 0%,
    #B3453F 14%,
    #C97A2E 25%,
    #D9A32E 36%,
    #4C8A52 45%,
    #4C8A52 55%,
    #D9A32E 64%,
    #C97A2E 75%,
    #B3453F 86%,
    #8E2A2A 100%);
  box-shadow: inset 0 1px 3px rgba(0,0,0,.3);
  pointer-events: none;
}
.jar-slider {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  background: transparent !important;
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  cursor: pointer;
}
.jar-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--surface);
  border: 3px solid var(--ouro);
  box-shadow: 0 2px 8px rgba(0,0,0,.5);
  cursor: grab;
}
.jar-slider::-webkit-slider-thumb:active { cursor: grabbing; }
.jar-slider::-moz-range-thumb {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--surface);
  border: 3px solid var(--ouro);
  box-shadow: 0 2px 8px rgba(0,0,0,.5);
  cursor: grab;
}
.jar-slider::-moz-range-track { background: transparent; }
.jar-slider:focus-visible { box-shadow: 0 0 0 3px rgba(201,162,39,.35); border-radius: 99px; }

.jar-valor {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.jar-escala {
  display: flex; justify-content: space-between;
  font-size: .7rem;
  color: var(--texto-fraco);
}
.jar-escala span:nth-child(2) { color: #4E8C5E; font-weight: 600; }

/* ==========================================================================
   Ficha da garrafa: visual e condições de guarda
   ========================================================================== */

/* O desenho da ficha usa o MESMO SVG do card. Antes o card fixava 56 px e a
   ficha usava uma caixa de 80 px, então a garrafa aparecia menor e deslocada
   dentro do espaço. Aqui o SVG preenche o contêiner. */
.gf-visual-ficha {
  width: 80px;
  flex-shrink: 0;
}
.gf-visual-ficha .gf-svg {
  width: 100%;
  height: auto;
}
/* Garrafa aberta é dessaturada no card; a ficha precisa concordar, senão a
   mesma garrafa aparece com duas cores diferentes. */
.gf-visual-ficha.aberta .gf-svg { filter: grayscale(.35); }

.ficha-guarda {
  display: flex;
  align-items: flex-end;
  gap: 20px;
  flex-wrap: wrap;
  padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
}
.ficha-guarda .rotulo {
  display: block;
  font-size: .7rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--texto-fraco);
  margin-bottom: 2px;
}
.ficha-guarda b { font-size: .9rem; font-weight: 500; }
.ficha-guarda > button { margin-left: auto; }

@media (max-width: 640px) {
  .ficha-guarda > button { margin-left: 0; width: 100%; justify-content: center; }
}

/* Nota em três níveis na ficha da garrafa */
.ficha-notas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
}
/* Rótulo em cima, VALOR INTEIRO numa linha só embaixo.
 *
 * Era um flex em coluna, e como `4,15`, as estrelas e `2 garrafa(s)` são
 * filhos DIRETOS, cada um virava uma linha: o número ficava órfão em cima do
 * que ele significa. Em bloco, o rótulo ocupa a própria linha e o resto do
 * conteúdo flui inline, que é como se lê "4,15 ★★★★ 2 garrafas". */
.fn-item { display: block; }
.fn-item .rotulo {
  display: block;
  font-size: .7rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--texto-fraco); margin: 0 0 2px;
}
.fn-item b + span, .fn-item i + span { margin-left: 4px; }
.fn-item b {
  font-family: var(--serif);
  font-size: 1.35rem;
  color: var(--ouro-claro);
  line-height: 1.1;
}
.fn-quebra { color: var(--texto-fraco); }

/* Estrela emprestada do lote, quando a garrafa ainda não foi provada */
.gf-nota.do-lote { opacity: .6; }
.gf-nota.do-lote .pequeno { color: var(--texto-fraco); margin-left: 4px; }

/* Cartão com checkbox, usado nas chaves de compartilhamento */
.check-cartao {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px; margin: 0;
  background: var(--surface-2);
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
  cursor: pointer;
  text-transform: none; letter-spacing: normal;
  font-size: 1rem; font-weight: 400; color: var(--texto);
  transition: border-color .14s, background .14s;
}
.check-cartao:hover { border-color: var(--linha-forte); }
.check-cartao.ligado { border-color: var(--ouro); background: rgba(201,162,39,.08); }
.check-cartao input { width: 18px; height: 18px; margin-top: 2px; accent-color: var(--ouro); flex-shrink: 0; }
.check-cartao b { display: block; margin-bottom: 3px; font-weight: 600; }
.check-cartao span { display: block; line-height: 1.45; }

/* ==========================================================================
   Prévia da ficha pública — o que o QR abre
   ========================================================================== */

/* A página pública é carregada num iframe em vez de reconstruída aqui: o que
   o dono da adega confere é literalmente o que o comprador recebe. */
.previa-publica {
  margin-top: 12px;
  border: 1px solid var(--linha-forte);
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--bg-alt);
}
.previa-publica iframe {
  display: block;
  width: 100%;
  height: 58vh;
  min-height: 320px;
  border: 0;
}

/* O QR do rótulo vira alvo de clique. A moldura só aparece no hover e no
   foco, para não sujar a prévia de impressão do rótulo. */
.rot-qr-clicavel { cursor: pointer; border-radius: 4px; }
.rot-qr-clicavel:hover { outline: 2px solid var(--ouro); outline-offset: 3px; }
.rot-qr-clicavel:focus-visible { outline: 2px solid var(--ouro); outline-offset: 3px; }

@media print {
  .rot-qr-clicavel:hover, .rot-qr-clicavel:focus-visible { outline: none; }
}

/* ==========================================================================
   Código de acesso de suporte
   ========================================================================== */

/* O código é ditado por telefone ou colado num chat, então ele precisa ser
   legível de longe e fácil de selecionar. O alfabeto do gerador já exclui
   I, O, 0 e 1 pelo mesmo motivo. */
.sp-codigo {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 16px 18px;
  background: rgba(201, 162, 39, .10);
  border: 1px solid var(--ouro-fosco);
  border-radius: var(--r-sm);
}
.sp-codigo-valor {
  font-size: 1.6rem; letter-spacing: .16em; color: var(--ouro-claro);
  user-select: all;
}

@media (max-width: 520px) {
  .sp-codigo-valor { font-size: 1.25rem; letter-spacing: .1em; }
}

/* ==========================================================================
   Selo "Powered by Nori"
   ========================================================================== */

/* Fixo no canto, discreto, presente em todas as telas — inclusive na ficha
   pública e no login, que são as duas que alguém de fora vê.
   
   `pointer-events: none` no bloco e `auto` só no link: o selo fica sobre o
   conteúdo, e sem isso ele engoliria cliques de qualquer coisa embaixo dele,
   como o botão de ação flutuante ou o rodapé de uma tabela longa. */
.selo-nori {
  position: fixed;
  right: 14px;
  bottom: 12px;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 7px;
  pointer-events: none;
  opacity: .5;
  transition: opacity .18s;
}
.selo-nori:hover { opacity: 1; }

.selo-nori span {
  font-size: .64rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texto-fraco);
  white-space: nowrap;
  /* line-height: 1 faz a caixa do texto abraçar as letras.
   *
   * Com a entrelinha padrão (15,9px para uma fonte de 10px) a caixa fica ~6px
   * mais alta que as letras, e o `align-items: center` centraliza a CAIXA —
   * não as letras. O resultado é o texto aparentando flutuar acima da logo,
   * mesmo com os retângulos perfeitamente alinhados. */
  line-height: 1;
  /* Meio pixel para baixo: a logo é minúscula sem maiúsculas altas, e o texto
   * em caixa alta pesa mais no topo. Alinhamento óptico, não geométrico. */
  padding-top: 1px;
}

.selo-nori a {
  pointer-events: auto;
  display: block;
  line-height: 0;
}

/* A logo tem 2857x576 e vem com fundo transparente; a altura fixa preserva a
   proporção sem precisar declarar a largura. */
.selo-nori img {
  height: 17px;
  width: auto;
  display: block;
}

/* No celular o selo brigaria com o conteúdo: fica só a marca, sem o texto. */
@media (max-width: 640px) {
  .selo-nori { right: 10px; bottom: 8px; opacity: .38; }
  .selo-nori span { display: none; }
}

/* Papel impresso não leva selo de plataforma. */
@media print {
  .selo-nori { display: none !important; }
}

/* ==========================================================================
   Configurações em abas
   ========================================================================== */

/* Centralizadas, e SEM barra de rolagem.
 *
 * O `overflow-x: auto` de antes reservava altura para uma barra horizontal
 * que quase nunca aparecia, e o resultado era um sulco cinza embaixo das abas.
 * Agora elas quebram em duas linhas quando não couberem — em telas estreitas
 * isso é melhor do que esconder abas atrás de um arrasto que ninguém descobre. */
.cfg-abas {
  display: flex; gap: 4px; margin-bottom: 20px;
  justify-content: center; flex-wrap: wrap;
  border-bottom: 1px solid var(--linha);
}
.cfg-aba {
  padding: 11px 16px; background: transparent; border: 0;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  color: var(--texto-fraco); font-family: var(--sans); font-size: .88rem;
  cursor: pointer; white-space: nowrap;
  display: flex; align-items: center; gap: 8px;
  transition: color .14s, border-color .14s;
}
.cfg-aba:hover { color: var(--texto-suave); }
.cfg-aba.ativa { color: var(--ouro-claro); border-bottom-color: var(--ouro); }
.cfg-aba i { font-size: .82rem; }
.cfg-painel[hidden] { display: none; }

/* ==========================================================================
   Carrossel de temas e paletas
   ========================================================================== */

.carrossel { position: relative; margin-top: 14px; }

/* Sem barra de rolagem: quem navega são as setas.
 *
 * Ter as duas coisas era contraditório — a barra sugeria arrastar, as setas
 * sugeriam clicar, e arrastar não mudava a seleção. O trilho continua rolando
 * por programa, para centralizar o item escolhido, mas a barra some. */
.carrossel-trilho {
  display: flex; gap: 12px;
  overflow-x: hidden;
  /* A folga no topo NÃO é estética: o selo do tema ativo fica em top:-7px,
     acima da borda do cartão, e `overflow-x: hidden` recorta nos dois eixos.
     Com 4px de padding o V do selo saía cortado pela metade. */
  padding: 14px 40px 10px;
  scroll-behavior: smooth;
}

.carrossel-seta {
  position: absolute; top: 50%; transform: translateY(-50%);
  z-index: 2; width: 32px; height: 32px; border-radius: 50%;
  background: var(--surface-2); border: 1px solid var(--linha-forte);
  color: var(--texto-suave); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.carrossel-seta:hover { background: var(--surface-3); color: var(--creme); }
.carrossel-seta.esq { left: 0; }
.carrossel-seta.dir { right: 0; }

.carro-item {
  flex: 0 0 auto; width: 150px; scroll-snap-align: center;
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
  padding: 12px 10px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--linha);
  border-radius: var(--r-sm);
  transition: border-color .14s, transform .12s;
}
.carro-item:hover { border-color: var(--linha-forte); transform: translateY(-2px); }
/* Escolhido: marcado, ainda não aplicado. Anel simples. */
.carro-item.escolhido {
  border-color: var(--ouro); box-shadow: 0 0 0 1px var(--ouro) inset;
}

/* Ativo: o que está VALENDO na adega. Brilho, para a pessoa saber de relance
   qual tema está no ar — e não só qual ela acabou de marcar. */
.carro-item.ativo {
  border-color: var(--ouro-claro);
  box-shadow: 0 0 0 1px var(--ouro-claro) inset,
              0 0 14px -2px var(--ouro),
              0 0 30px -8px var(--ouro);
}
.carro-item.ativo.escolhido {
  box-shadow: 0 0 0 2px var(--ouro-claro) inset,
              0 0 16px -2px var(--ouro),
              0 0 34px -8px var(--ouro);
}
.carro-item { position: relative; }
.carro-selo {
  position: absolute; top: -7px; right: -7px; z-index: 1;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--ouro); color: #201A12;
  display: flex; align-items: center; justify-content: center;
  font-size: .6rem;
  box-shadow: 0 0 10px -1px var(--ouro);
}
.carro-item:focus-visible { outline: 2px solid var(--ouro); outline-offset: 2px; }

.carro-nome {
  font-size: 1rem; color: var(--creme); line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Barra de cores: as cinco sementes da paleta, na ordem em que são usadas. */
.carro-cores { display: flex; gap: 0; border-radius: 3px; overflow: hidden; height: 10px; }
.carro-cores i { flex: 1; display: block; }

/* Miniatura do rótulo dentro do cartão do carrossel. */
.carro-mini {
  display: block; border-radius: 3px; border: 1px solid;
  padding: 8px 7px; text-align: center; line-height: 1.25;
}
.carro-mini b { display: block; font-size: .68rem; }
.carro-mini i { display: block; height: 1px; margin: 4px auto; width: 60%; }
.carro-mini em { display: block; font-size: .52rem; font-style: normal; }

/* ==========================================================================
   Prévia tripla: rótulo, comprovante e plataforma
   ========================================================================== */

.previa-tripla {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 18px; margin-top: 14px;
}
.previa-rotulo-titulo {
  font-size: .72rem; text-transform: uppercase; letter-spacing: .08em;
  color: var(--texto-fraco); margin-bottom: 8px;
}

.pv-rotulo, .pv-comprovante {
  position: relative; overflow: hidden;
  border-radius: 3px; padding: 14px 16px;
}
.pv-rotulo { min-height: 190px; }
.pv-halo { position: absolute; inset: -30%; pointer-events: none; }

.pv-marca { font-size: .7rem; margin-bottom: 6px; position: relative; }
.pv-filete { height: 2px; width: 42px; margin-bottom: 10px; position: relative; }
.pv-nome { font-size: 1.25rem; line-height: 1.15; margin-bottom: 5px; position: relative; }
.pv-frutas { font-size: .72rem; position: relative; }
.pv-notas { font-size: .66rem; font-style: italic; margin-top: 2px; position: relative; }

.pv-meio {
  display: flex; justify-content: space-between; align-items: flex-end;
  margin-top: 14px; position: relative;
}
.pv-dados { font-size: .68rem; line-height: 1.6; }
.pv-qr { width: 38px; height: 38px; border-radius: 2px; opacity: .85; }

.pv-rodape {
  display: flex; justify-content: space-between;
  font-size: .56rem; margin-top: 10px; padding-top: 6px; position: relative;
}

.pv-cp-topo { font-size: .74rem; margin-bottom: 6px; }
.pv-cp-linha { display: flex; justify-content: space-between; margin: 6px 0; font-size: .8rem; }
.pv-cp-total { display: flex; justify-content: space-between; margin-top: 10px; padding-top: 7px; }
.pv-cp-codigo {
  margin-top: 12px; padding: 8px; border-radius: 3px;
  text-align: center; font-size: .6rem; line-height: 1.6;
}

/* --------------------------------------------------------------- maquete

   Bloco isolado que recebe as cores da paleta em estilo inline. Não usa as
   variáveis do :root de propósito: precisa mostrar o modo claro E o escuro ao
   mesmo tempo, e variável de tema só tem um valor por documento. */
.pv-maquete {
  border: 1px solid; border-radius: var(--r-sm);
  overflow: hidden; margin-bottom: 10px; position: relative;
}
.pv-mq-etiqueta {
  position: absolute; top: 4px; right: 7px;
  font-size: .54rem; text-transform: uppercase; letter-spacing: .1em;
}
.pv-mq-topo { padding: 7px 10px; font-size: .68rem; border-bottom: 1px solid; }
.pv-mq-corpo { display: flex; min-height: 78px; }
.pv-mq-menu {
  width: 30px; border-right: 1px solid; padding: 8px 5px;
  display: flex; flex-direction: column; gap: 5px;
}
.pv-mq-menu span { height: 4px; border-radius: 2px; display: block; }
.pv-mq-area { flex: 1; padding: 8px; display: flex; flex-direction: column; gap: 7px; }
.pv-mq-card {
  border: 1px solid; border-radius: 4px; padding: 7px;
  display: flex; flex-direction: column; gap: 4px;
}
.pv-mq-t { height: 5px; width: 42%; border-radius: 2px; display: block; }
.pv-mq-l { height: 3px; width: 100%; border-radius: 2px; display: block; opacity: .5; }
.pv-mq-l.curta { width: 62%; }
.pv-mq-botoes { display: flex; gap: 5px; }
.pv-mq-botoes span { height: 12px; width: 30px; border-radius: 3px; display: block; }

/* ==========================================================================
   Acessibilidade — tudo por atributo no <html>, lido daqui
   ========================================================================== */

/* Escala a raiz: como as medidas do tema são em rem, o layout inteiro
   acompanha sem precisar de uma segunda folha de estilo. */
:root[data-a11y-fonte="sim"] { font-size: 115%; }

/* O !important aqui NÃO é preguiça.
 *
 * O tema escreve as variáveis de cor inline no <html>, via
 * style.setProperty(), e estilo inline vence qualquer regra de folha por
 * especificidade. Sem o !important, ligar o alto contraste não mudava nada
 * enquanto houvesse uma paleta aplicada — ou seja, sempre.
 *
 * Acessibilidade tem de vencer personalização: a paleta é gosto, o contraste
 * é a diferença entre ler e não ler. */
:root[data-a11y-contraste="sim"] {
  --texto:       #FFFFFF !important;
  --texto-suave: #E6E0DA !important;
  --texto-fraco: #C2BAB4 !important;
  --linha:       #6E6270 !important;
  --linha-forte: #9A8CA0 !important;
}
:root[data-a11y-contraste="sim"] .cartao,
:root[data-a11y-contraste="sim"] .tabela th { border-color: var(--linha-forte); }
:root[data-a11y-contraste="sim"][data-theme="light"] {
  --texto:       #000000 !important;
  --texto-suave: #1E1A1C !important;
  --texto-fraco: #3E3438 !important;
}

:root[data-a11y-animacao="sim"] *,
:root[data-a11y-animacao="sim"] *::before,
:root[data-a11y-animacao="sim"] *::after {
  animation-duration: .001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: .001ms !important;
  scroll-behavior: auto !important;
}

:root[data-a11y-sublinhar="sim"] a { text-decoration: underline; }
:root[data-a11y-sublinhar="sim"] .menu-item,
:root[data-a11y-sublinhar="sim"] .btn { text-decoration: none; }

@media (max-width: 640px) {
  .carro-item { width: 128px; }
  .cfg-aba { padding: 10px 12px; font-size: .82rem; }
  .cfg-aba span { display: none; }
}

/* Números da calibração compartilhada: o valor e o rótulo formam uma frase
   só — "12 fatores que você aprendeu" —, então ficam na mesma linha, com o
   número em destaque e o texto alinhado pela base dele. */
.cm-numeros > div {
  display: flex; align-items: baseline; gap: 7px;
  padding: 8px 0;
}
.cm-numeros b {
  font-family: var(--serif); font-size: 1.5rem;
  color: var(--ouro-claro); line-height: 1; flex-shrink: 0;
}
.cm-numeros span { line-height: 1.35; }

/* Rodapé de formulário: opção à esquerda, ação à direita, sempre na mesma
   linha até a tela estreitar. Nasceu porque o botão de criar usuário, quando
   era a quarta coluna de uma grade, caía sozinho numa segunda linha. */
/* A FILEIRA DE AÇÃO DE UM CARTÃO: o estado à esquerda, a ação à direita.
 *
 * Existe para que as abas de Configurações parem de inventar cada uma a sua.
 * Antes eram três padrões para a mesma coisa — em Dados legais e Desvio o
 * botão de salvar ficava à ESQUERDA do aviso, na Qualidade ficava à direita —,
 * e trocar de aba mudava o lugar do botão. Quem repete um gesto três vezes por
 * dia repara nisso antes de qualquer outra coisa da tela.
 *
 * O botão à direita não é gosto: numa fileira que quebra em telas estreitas, o
 * último item é o que fica sozinho na segunda linha, e é melhor que seja o
 * botão do que a explicação dele. */
.linha-acao {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-top: 16px;
}
/* O texto encolhe; o botão, não. Sem isto um aviso comprido espreme o botão
   até o ícone encostar na letra. */
.linha-acao > span:first-child { flex: 1; min-width: 160px; }
.linha-acao .btn { flex-shrink: 0; }
/* Quando são DOIS botões, eles andam juntos como um bloco só. */

/* ==========================================================================
   O que este rótulo usa, e de onde veio
   ==========================================================================

   Não é um formulário: é uma resposta. A tela de impressão deixou de escolher
   formato, recipiente e verso — a decisão desce do lote, da receita ou da
   área, e chega aqui pronta. O que a pessoa precisa saber é o que está sendo
   usado e ONDE se muda, porque "por que este rótulo?" e "onde eu troco isso?"
   são as duas perguntas que um valor não editável sempre provoca. */
.rot-decisao {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}
.rot-decisao-item {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.rot-decisao-rot {
  font-size: .62rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--texto-fraco);
}
/* A EXCEÇÃO DO VERSO, dentro do painel de decisão.
   Um checkbox miúdo colado no valor, e não um controle de formulário: ele não
   escolhe o padrão — abre uma exceção a ele, para esta impressão. Pôr-lhe o
   peso visual de um campo faria parecer que ali se configura a casa. */
.rot-decisao-excecao {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: .72rem;
  color: var(--texto-fraco);
  cursor: pointer;
  margin: 0;
  padding: 0;
  text-transform: none;
  letter-spacing: normal;
}
.rot-decisao-excecao input { margin: 0; width: 13px; height: 13px; flex-shrink: 0; }

/* O item com explicação no title ganha o cursor de ajuda: sem ele não há
   nada dizendo que existe algo a ler ali. */
.rot-decisao-ajuda { cursor: help; }

.rot-decisao-item b {
  font-size: .96rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Assinatura da plataforma no rótulo.
   Minúscula de propósito: vai colada numa garrafa que o cliente leva para
   casa, então precisa estar presente sem disputar atenção com o vinho. */
.rot-plataforma {
  display: flex; align-items: center; justify-content: center; gap: 4px;
  font-size: .5rem; letter-spacing: .04em;
  color: var(--rot-fraca, #8C7F88);
  margin-top: 4px; opacity: .75;
}
.rot-plataforma img { height: 6px; width: auto; display: block; }

/* Marca branca no card da adega, na tela do admin do sistema. */
/* Faixa de interruptores do cartão de organização (ambientes, assinatura).
 *
 * OCUPA A LINHA INTEIRA da grade do cartão. Sem isso ela cai na coluna
 * estreita da direita — a das ações — e cada caixa de seleção vai para uma
 * linha, empilhadas, em vez de ficarem lado a lado como a faixa pede.
 * O `grid-column` só tem efeito quando o pai é grade; nos demais contextos
 * a declaração é simplesmente ignorada. */
.org-marca {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 12px; margin-top: 10px;
  background: var(--surface-2); border-radius: var(--r-sm);
}
/* O título não encolhe: com flex-wrap, um rótulo espremido quebraria em duas
   linhas e desalinharia verticalmente as caixas ao lado dele. */
.org-marca-titulo {
  font-size: .68rem; text-transform: uppercase; letter-spacing: .08em;
  color: var(--texto-fraco);
  flex-shrink: 0;
}
/* Dentro da faixa, cada caixa é um item de linha: altura própria zerada para
   que todas assentem na mesma base, independentemente do ícone que carregam. */
.org-marca .check-linha { margin: 0; line-height: 1.2; }

/* Nota média do recipiente, ao lado do título do histórico.
   Só a forma das estrelas, entre parênteses — o número e a legenda saíram
   porque é dado de contexto, não a informação principal da tela. */
.cont-estrelas { margin-left: 6px; font-weight: 400; }
.cont-estrelas i { font-size: .78rem; margin: 0 .5px; }

/* Barra de ações dentro de um modal: CENTRALIZADA.
 *
 * Botões alinhados à esquerda numa caixa estreita e centrada deixam um vazio
 * à direita que parece erro de layout. No corpo da página o alinhamento à
 * esquerda faz sentido, porque acompanha o texto; no modal, o conteúdo já é
 * um bloco centrado e as ações têm de acompanhá-lo.
 *
 * Classe própria, e não uma regra em `.modal-caixa .flex`, porque nem toda
 * linha flex de modal é barra de ação — a lista de defeitos da avaliação,
 * por exemplo, é uma fileira de caixas de seleção e deve continuar à esquerda. */
.acoes-modal {
  display: flex; align-items: center; justify-content: center;
  gap: 8px; flex-wrap: wrap;
}

/* A tabela da ficha de análise.
   As três colunas de valor ficam alinhadas à direita e com largura própria: a
   comparação entre elas é o ponto da tela, e números de larguras diferentes,
   com o rótulo espremido ao lado, obrigam a lê-los um por um. */
.fi-tabela td:nth-child(2),
.fi-tabela td:nth-child(3),
.fi-tabela th:nth-child(2),
.fi-tabela th:nth-child(3) { width: 130px; }
.fi-tabela th:nth-child(4) { width: 150px; }
/* A coluna da Qualidade é a única editável, e a faixa a distingue de relance
   das duas de leitura. */
.fi-tabela td:nth-child(4) { background: var(--surface-2); }

/* ==========================================================================
   Tela de equipe
   ==========================================================================

   Um cartao por pessoa, e nao uma tabela. A tabela foi a primeira tentativa e
   nao serve: sao quatro blocos com tres a quatro numeros cada, e catorze
   colunas na horizontal viram uma planilha que ninguem le. No cartao, cada
   pessoa e uma unidade que se compara com a de baixo pelo mesmo bloco. */
/* --------------------------------------------------- consolidado do admin

   Cartões maiores que os de pessoa, e de propósito: são MENOS. Uma casa tem
   três ou quatro equipes e vinte pessoas, e usar a mesma largura para as duas
   coisas faria três cartões flutuarem perdidos numa grade feita para vinte. */
.eq-resumo {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  align-items: stretch;
}

/* O CARTÃO É UMA COLUNA DE ALTURA CHEIA.
 *
 * Sem isto, cada cartão terminava onde o conteúdo dele acabava, e o botão
 * "Ver a equipe" caía numa altura diferente em cada um — quatro cartões lado a
 * lado com quatro botões em quatro alturas. `height: 100%` estica o cartão até
 * a altura da linha da grade, e o `margin-top: auto` do botão o empurra para o
 * rodapé. É o que alinha a fileira inteira sem fixar altura nenhuma. */
.eq-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  margin: 0;
}

/* --- faixa 1: identidade ------------------------------------------------ */
.eq-card-topo {
  display: flex;
  align-items: center;
  gap: 11px;
  padding-bottom: 11px;
  border-bottom: 1px solid var(--linha);
}
.eq-card-icone { color: var(--ouro); font-size: 1rem; flex-shrink: 0; }

/* `min-width: 0` é o que permite ao nome virar reticências em vez de empurrar
   a etiqueta para fora do cartão. Um filho de flex não encolhe abaixo do
   próprio conteúdo sem ele. */
.eq-card-id { flex: 1; min-width: 0; }

.eq-card-nome {
  font-family: var(--serif);
  font-size: 1.06rem;
  line-height: 1.25;
  color: var(--texto);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.eq-card-sup {
  font-size: .76rem;
  color: var(--texto-fraco);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  margin-top: 1px;
}
.eq-card-topo .etiqueta { flex-shrink: 0; }

/* --- faixa 2: tamanho --------------------------------------------------- */
.eq-card-gente {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: .82rem;
  color: var(--texto-suave);
  padding: 11px 0 0;
  min-width: 0;
}
.eq-card-gente > i { color: var(--texto-fraco); font-size: .78rem; flex-shrink: 0; }
.eq-card-total {
  margin-left: auto;
  font-size: .74rem;
  color: var(--texto-fraco);
  white-space: nowrap;
  flex-shrink: 0;
}

/* --- faixa 3: os quatro números ---------------------------------------- */

/* DUAS COLUNAS FIXAS, e não `auto-fit`. Com `auto-fit`, um cartão mais largo
   que o outro numa grade responsiva quebrava em 4×1 enquanto o vizinho ficava
   em 2×2 — dois desenhos diferentes na mesma fileira. Dois por linha, sempre,
   e a métrica sempre no mesmo lugar em todos os cartões. */
.eq-card-nums {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 14px;
  margin-top: 14px;
  padding-top: 13px;
  border-top: 1px solid var(--linha);
}
.eq-card-num { min-width: 0; }
.eq-card-val {
  font-family: var(--serif);
  font-size: 1.34rem;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* O RÓTULO RESERVA DUAS LINHAS. "Contraprovas vencidas" quebra em duas e "Na
   bancada" cabe numa; sem a reserva, a primeira fileira de números ficava mais
   alta que a segunda em alguns cartões e não em outros. Reservar é mais
   honesto que truncar: o rótulo inteiro continua legível. */
.eq-card-rot {
  font-size: .74rem;
  color: var(--texto-fraco);
  line-height: 1.3;
  min-height: 1.95em;
  margin-top: 3px;
}
.eq-card-ajuda { font-size: .68rem; opacity: .6; cursor: help; }

/* --- faixa 4: o caminho para o detalhe ---------------------------------- */
.eq-card-ir {
  margin-top: auto;
  align-self: flex-start;
}

/* A equipe que não atua nesta área não some — desbota, e mostra travessões no
   lugar dos números. Sumir faria o admin concluir que ela não existe; trocar a
   estrutura por um parágrafo faria o cartão desalinhar de todos os outros. */
.eq-card-apagado { opacity: .6; }
.eq-card-apagado .eq-card-val { color: var(--texto-fraco); }

@media (max-width: 420px) {
  .eq-card-nums { grid-template-columns: 1fr; }
}

.eq-grade {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
}
.eq-cartao {
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
  background: var(--surface);
  padding: 12px;
}
.eq-nome {
  font-weight: 600; font-size: .95rem;
  padding-bottom: 8px; margin-bottom: 8px;
  border-bottom: 1px solid var(--linha);
}
.eq-nome i { color: var(--texto-fraco); margin-right: 6px; }

.eq-bloco { margin-bottom: 10px; }
.eq-bloco:last-child { margin-bottom: 0; }
.eq-bloco-tit {
  font-size: .68rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--texto-fraco); margin-bottom: 4px;
}
.eq-bloco-tit i { margin-right: 4px; }

/* O bloco de volume e o DENOMINADOR de todos os outros, e o fundo o separa:
   ele nao mede desempenho, ele da escala ao que os de cima mediram. */
.eq-denominador {
  background: var(--surface-2);
  border-radius: var(--r-sm);
  padding: 8px; margin-top: 10px;
}

.eq-linha {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 10px; padding: 2px 0;
  font-size: .82rem;
}
.eq-rot { color: var(--texto-suave); }
.eq-val { font-variant-numeric: tabular-nums; color: var(--texto); }

/* ==========================================================================
   Lista de alertas
   ==========================================================================

   Lista densa, e nao cartoes: sao avisos curtos que se le em varredura, e um
   cartao por linha faria oito alertas ocuparem a tela inteira.

   O NAO LIDO E O ESTADO PADRAO. O lido e que recua — some a barra lateral
   colorida e o texto esmaece. E o contrario do habitual, e e deliberado: a
   lista existe para o que ainda nao foi visto. */
.al-lista { display: flex; flex-direction: column; }

.al-item {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 12px 10px;
  border-left: 3px solid var(--linha-forte);
  border-bottom: 1px solid var(--linha);
}
.al-item:last-child { border-bottom: 0; }
.al-item.lido { border-left-color: transparent; opacity: .55; }

.al-icone { font-size: .95rem; margin-top: 3px; width: 18px; text-align: center; }
.al-icone.perigo { color: var(--perigo); }
.al-icone.alerta { color: var(--alerta); }

.al-topo { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; }
.al-quem { margin-top: 3px; }
.al-ler { flex-shrink: 0; }

/* Barra proporcional na tabela de perdas.
   A porcentagem sozinha obriga a comparar numeros; a barra deixa a proporcao
   visivel de relance, que e a pergunta que a coluna responde: qual fatia da
   perda foi de cada tipo. */
.pd-barra { position: relative; height: 18px; min-width: 90px; }
.pd-barra-int {
  position: absolute; inset: 0 auto 0 0;
  background: rgba(179,69,63,.28);
  border-radius: 3px;
}
.pd-barra span { position: relative; padding-left: 5px; line-height: 18px; }

/* A frase do custo. Corpo maior porque e o que alguem repete numa reuniao —
   os numeros da tabela acima sao a evidencia, e ela e a conclusao. */
.pd-frase { font-size: 1.05rem; line-height: 1.5; margin-bottom: 10px; }

/* ==========================================================================
   Folha de etiquetas de amostra
   ==========================================================================

   Etiqueta de bancada: pequena, alta em contraste, com o codigo legivel de
   longe. Ela vai colada num tubo de 15 mm de diametro, e o que se le de frente
   e uma faixa de uns 30 mm — por isso o codigo domina e o resto e miudo.

   FUNDO BRANCO E TEXTO PRETO, sempre, nos dois temas: isto e para o papel, e
   papel nao tem modo escuro. Uma etiqueta que sai do tema bordo da casa
   consome tinta e fica ilegivel na impressora termica. */
.etq-folha {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 8px;
  max-height: 340px; overflow-y: auto;
  padding: 4px;
}
.etq {
  border: 1px dashed #999;
  border-radius: 3px;
  background: #fff; color: #111;
  padding: 8px 10px;
  font-size: .68rem;
  line-height: 1.35;
}
.etq-casa {
  font-size: .58rem; letter-spacing: .12em; text-transform: uppercase;
  color: #666; margin-bottom: 2px;
}
.etq-codigo {
  font-family: var(--mono, monospace);
  font-size: 1rem; font-weight: 700; letter-spacing: .04em;
}
.etq-linha {
  display: flex; justify-content: space-between; gap: 8px;
  font-family: var(--mono, monospace);
  border-bottom: 1px solid #ddd; padding-bottom: 3px; margin-bottom: 3px;
}
.etq-meta { color: #444; }
.etq-rodape {
  display: flex; justify-content: space-between; gap: 8px;
  color: #666; margin-top: 4px;
  border-top: 1px solid #eee; padding-top: 3px;
}

/* NA IMPRESSAO, so a folha existe.
   O modal, a barra lateral e os botoes somem, e as etiquetas ocupam a pagina
   inteira — senao sai uma folha com a interface em volta e seis etiquetas no
   meio. */
/* A marca vem do JavaScript, e nao de um seletor esperto.
   `body > *:not(:has(.etq-folha))` funcionava e era fragil: bastava o modal
   mudar de lugar na arvore para a folha sair com a interface em volta. Uma
   classe posta antes de imprimir e tirada depois nao depende de onde o modal
   esta. */
@media print {
  html.imprimindo-etiquetas .app { display: none !important; }
  html.imprimindo-etiquetas .modal-fundo:not(#mf-etq) { display: none !important; }
  .modal-fundo { position: static !important; background: none !important; }
  .modal-caixa {
    max-width: none !important; box-shadow: none !important;
    border: 0 !important; padding: 0 !important;
  }
  .cartao-titulo, .rev-aviso, .acoes-modal { display: none !important; }
  .etq-folha {
    max-height: none !important; overflow: visible !important;
    grid-template-columns: repeat(3, 1fr);
  }
  .etq { break-inside: avoid; }
}

/* ==========================================================================
   Prateleira de amostras
   ==========================================================================

   Cada LOTE e um cartao; dentro dele, cada ETAPA e uma faixa. A faixa mostra
   DEZ POR LINHA e DUAS LINHAS, e rola sozinha passando disso.

   O scroll e da FAIXA, e nao do cartao: uma descuba com sessenta amostras rola
   dentro dela mesma, e o engarrafamento logo abaixo continua a vista. Um scroll
   no cartao inteiro esconderia as outras etapas atras da maior.

   As dimensoes sao as mesmas da adega — 168px de coluna, 158px de desenho —
   porque frasco e garrafa convivem aqui, e a garrafa ja tem um tamanho que a
   pessoa reconhece. */
.am-etapa { margin-top: 14px; }
.am-etapa:first-of-type { margin-top: 8px; }

.am-etapa-tit {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  padding: 0 0 6px;
  border-bottom: 1px solid var(--linha);
  margin-bottom: 8px;
  font-size: .86rem;
}
.am-etapa-tit > i { color: var(--texto-fraco); }

/* A ALTURA E O PONTO. 2 linhas de 236px (cartao) + 12px de gap = 484px.
   Passando disso, rola — e o `overflow-y: auto` so aparece quando precisa. */
.am-prateleira {
  max-height: 484px;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 4px 2px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  border-bottom: 5px solid var(--surface-3);
}

/* DEZ POR LINHA em tela larga, e menos conforme ela encolhe. `auto-fill` com
   minimo de 152px da dez colunas a partir de ~1560px de area util e degrada
   sozinho — uma contagem fixa quebraria no notebook. */
.am-grade {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(152px, 1fr));
  gap: 12px;
}

.am-item { position: relative; }

.am-abrir {
  display: flex; flex-direction: column; align-items: center;
  width: 100%;
  background: linear-gradient(180deg, var(--surface), var(--bg-alt));
  border: 1px solid var(--linha);
  border-radius: var(--r-md);
  padding: 12px 8px 10px;
  cursor: pointer; text-align: center;
  font: inherit;
  transition: transform .14s, border-color .14s, box-shadow .14s;
}
.am-abrir:hover {
  transform: translateY(-3px);
  border-color: var(--ouro-fosco);
  box-shadow: var(--sombra-md);
}

.am-item.vencida .am-abrir { border-color: var(--perigo); }
.am-item.morta .am-abrir { opacity: .5; }
.am-item.morta .gf-svg { filter: grayscale(.7); }

.am-visual { margin-bottom: 6px; }
/* O frasco e mais estreito que a garrafa, e o desenho ja reflete isso no
   viewBox — a largura aqui e a mesma para os dois, e e o conteudo que difere. */
.am-visual .gf-svg { width: 52px; height: 148px; }

.am-codigo { font-family: var(--serif); font-size: .82rem; color: var(--creme); }
.am-sub { font-size: .7rem; color: var(--texto-fraco); margin-bottom: 5px; }
.am-estado { font-size: .62rem; padding: 0 6px; }

/* A caixa de selecao fica FORA do botao: um checkbox dentro de um botao faz o
   clique disputar entre selecionar e abrir. */
.am-check {
  position: absolute; top: 6px; left: 8px; z-index: 2;
  display: flex; padding: 2px;
}
.am-check input { cursor: pointer; }

/* A bandeira de "sem etiqueta". Canto oposto ao da selecao, para os dois nao
   competirem pelo mesmo canto do cartao. */
.am-flag {
  position: absolute; top: 8px; right: 10px;
  font-size: .72rem; color: var(--alerta);
}

/* ==========================================================================
   Seletor de modo do admin
   ==========================================================================

   Mesmo gesto do seletor de ambiente lá em cima, e de propósito: a pessoa já o
   aprendeu, e repeti-lo embaixo custa zero aprendizado. A diferença é a
   direção — este abre para CIMA, porque mora no rodapé, e uma lista que
   abrisse para baixo sairia da tela.

   Ele ganhou a largura inteira da lateral. Antes dividia uma coluna estreita
   com o nome e o papel de quem entrou, e "Administração" não cabia: o texto
   passava por cima da seta. Não era um ajuste de fonte — era o lugar errado. */
.seletor-modo { position: relative; }

.modo-atual {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--texto-suave);
  font: inherit; font-size: .78rem;
  cursor: pointer; text-align: left;
  transition: border-color .16s, background .16s, color .16s;
}
.modo-atual:hover {
  border-color: var(--ouro-fosco);
  background: var(--surface-3);
  color: var(--texto);
}
.modo-atual > i:first-child { color: var(--ouro-fosco); width: 15px; text-align: center; }

/* O RÓTULO ENCOLHE; A SETA, NÃO.
   Sem `min-width: 0` no texto, o flex mantém o rótulo no tamanho natural e
   empurra a seta para fora da caixa — que era exatamente o vazamento. */
.modo-rotulo {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.modo-atual .modo-seta { flex-shrink: 0; font-size: .66rem; opacity: .6; }

/* O rótulo "MODO" acima do valor. Sem ele, "Administração" no rodapé parece o
   cargo da pessoa — que é justamente o que está escrito na linha de cima. */
.modo-etiqueta {
  font-size: .58rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--texto-fraco);
  padding: 0 2px 4px;
}

.modo-lista {
  position: absolute; z-index: 60; left: 0; right: 0; bottom: calc(100% + 5px);
  padding: 5px;
  border: 1px solid var(--linha-forte);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  box-shadow: var(--sombra-md);
}
.modo-item {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 9px; border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--texto);
  font: inherit; font-size: .82rem; cursor: pointer; text-align: left;
}
.modo-item:hover { background: var(--surface-3); }
.modo-item.ativa { background: var(--surface-3); font-weight: 600; }
.modo-item > i:first-child { color: var(--ouro-claro); width: 16px; text-align: center; }
.modo-item .modo-rotulo { flex: 1; min-width: 0; }

/* ==========================================================================
   Faixa de situação da lista de lotes
   ==========================================================================

   Não é a mesma coisa que `.cfg-abas`, e por isso não reaproveita a classe: lá
   são painéis de conteúdo diferente, aqui é um FILTRO sobre a mesma lista. A
   diferença aparece no contador — cada aba diz quantos lotes existem nela,
   inclusive quando não é a aba aberta, que é o que permite decidir para onde
   ir sem clicar em todas. */
.abas-situacao {
  display: flex; gap: 6px; flex-wrap: wrap;
  justify-content: center;
}
.aba-situacao {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px;
  border: 1px solid var(--linha);
  border-radius: 999px;
  background: var(--surface);
  color: var(--texto-suave);
  font: inherit; font-size: .84rem;
  cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}
.aba-situacao:hover { border-color: var(--linha-forte); color: var(--texto); }
.aba-situacao i { font-size: .8rem; color: var(--texto-fraco); }
.aba-situacao.ativa {
  border-color: var(--ouro-fosco);
  background: var(--surface-2);
  color: var(--texto);
  font-weight: 600;
}
.aba-situacao.ativa i { color: var(--ouro-claro); }

/* O contador. Apagado quando zera, e NÃO escondido: sumir com ele mudaria a
   largura da aba a cada busca, e o alvo do clique se moveria debaixo do dedo
   de quem está filtrando. */
.aba-conta {
  min-width: 18px; padding: 1px 6px;
  border-radius: 999px;
  background: var(--surface-3);
  color: var(--texto-fraco);
  font-size: .72rem; font-variant-numeric: tabular-nums;
  text-align: center;
}
.aba-situacao.ativa .aba-conta { background: var(--ouro-fosco); color: var(--marca-tinta); }
.aba-situacao.vazia { opacity: .5; }
.aba-situacao.vazia.ativa { opacity: 1; }

/* Produtos químicos: fator de potência e destaque de valor suspeito. */
.pq-fator { display: flex; align-items: center; gap: 6px; }
.pq-fator .btn-icone {
  width: 22px; height: 22px; font-size: .8rem; line-height: 1;
  /* O `padding: 7px` herdado de .btn-icone sobrava numa caixa de 22px:
     restavam 8px de área útil para um ícone de ~13px, e a borracha do "limpar
     calibração" saía torta, para fora do botão. Zerar o padding e centrar por
     flex conserta os três botões da linha de uma vez. */
  padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
/* Linha inteira marcada quando a potência está muito longe da referência —
   quase sempre g/L digitado onde o rótulo dizia g/hL. */
.pq-extremo { background: rgba(201, 138, 43, .10); }
.pq-extremo td { border-color: var(--alerta); }

/* ==========================================================================
   Galeria de formatos de rótulo (Configurações > Personalização)
   ==========================================================================

   Cada item mostra o rótulo REAL, gerado pelo mesmo módulo que imprime, e
   reduzido por transform. Reduzir por transform (e não redesenhar menor) é o
   ponto: uma miniatura aproximada esconderia justamente o que se quer ver —
   se o nome cabe, se a moldura fecha, se o QR espreme os dados.

   O palco tem a medida JÁ REDUZIDA porque transform não afeta o fluxo: sem
   ele, cada rótulo continuaria ocupando o espaço do tamanho original e a
   galeria ficaria cheia de buracos. */

.fmt-galeria {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  align-items: flex-end;
}

.fmt-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 12px;
  background: var(--surface-2);
  border: 1px solid var(--linha);
  border-radius: var(--r-md);
  cursor: pointer;
  font: inherit;
  color: var(--texto);
  transition: border-color .16s, transform .12s;
}
.fmt-item:hover { border-color: var(--linha-forte); transform: translateY(-2px); }
.fmt-item.escolhido {
  border-color: var(--ouro);
  box-shadow: 0 0 0 1px var(--ouro) inset;
}

.fmt-palco { display: block; position: relative; overflow: hidden; }
/* A origem no canto é obrigatória: com o padrão (centro), o rótulo reduzido
   sairia da caixa pela esquerda e pelo topo. */
.fmt-escala { display: block; transform-origin: top left; }

.fmt-nome { font-size: .84rem; font-weight: 600; }
.fmt-medida { font-size: .68rem; color: var(--texto-fraco); }

/* ==========================================================================
   Janela de revisão do rótulo
   ==========================================================================

   É a tela mais séria do sistema: nela alguém assume responsabilidade legal
   pelo que vai impresso em cada garrafa de um lote. O visual acompanha —
   o aviso não se fecha, os selos de estado gritam, e o campo que falta fica
   marcado em vermelho enquanto faltar. */

.modal-largo { max-width: 860px; }

.rev-aviso {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px 16px;
  margin-bottom: 18px;
  border-radius: var(--r-md);
  background: rgba(179,69,63,.14);
  border: 1px solid rgba(179,69,63,.5);
}
.rev-aviso i { color: var(--perigo); font-size: 1.3rem; margin-top: 2px; }
.rev-aviso b { display: block; margin-bottom: 4px; }
.rev-aviso p { margin: 0; font-size: .86rem; color: var(--texto-suave); }

.rev-campos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 14px;
}

.rev-campo {
  padding: 12px;
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
  background: var(--surface-2);
}
/* O campo que falta continua vermelho ATÉ ser preenchido — o estado é
   recalculado a cada tecla, e não só no envio. */
.rev-campo.faltando { border-color: var(--perigo); background: rgba(179,69,63,.08); }

.rev-campo-topo {
  display: flex; align-items: center; gap: 8px;
  justify-content: space-between; margin-bottom: 6px;
}
.rev-campo-topo label { font-size: .84rem; font-weight: 600; margin: 0; }
.rev-obrig { color: var(--perigo); }
.rev-campo input[type="text"] { width: 100%; }

.rev-selo {
  font-size: .62rem; text-transform: uppercase; letter-spacing: .06em;
  padding: 2px 7px; border-radius: 99px; white-space: nowrap; cursor: help;
}
.rev-ok      { background: rgba(78,140,94,.20);  color: #8FD1A0; }
.rev-atencao { background: rgba(201,138,43,.20); color: #E5B769; }
.rev-perigo  { background: rgba(179,69,63,.24);  color: #F0A9A4; }
.rev-neutro  { background: var(--surface-3);     color: var(--texto-fraco); }
:root[data-theme="light"] .rev-ok      { color: #2E6B41; }
:root[data-theme="light"] .rev-atencao { color: #7A5310; }
:root[data-theme="light"] .rev-perigo  { color: #8C2A25; }

.rev-ajuda { font-size: .74rem; color: var(--texto-fraco); margin: 6px 0; line-height: 1.4; }

.rev-check {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .8rem; font-weight: 600; margin: 4px 0 0; cursor: pointer;
  text-transform: none; letter-spacing: 0;
}
.rev-check input { width: auto; accent-color: var(--ok); }

/* A LINHA DE CONFERÊNCIA — uma caixa de seleção com o texto ao lado.
 *
 * `align-items: flex-start` porque a explicação embaixo do título é normal
 * aqui: com centralização, a caixinha flutuaria no meio de um parágrafo de
 * três linhas em vez de ficar junto do que ela marca. */
.rev-linha {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 9px 4px; cursor: pointer; font-size: .86rem;
  border-bottom: 1px solid var(--linha);
}
.rev-linha:last-child { border-bottom: 0; }
.rev-linha input { width: auto; margin-top: 3px; accent-color: var(--ok); }
.rev-linha:hover { background: var(--surface-3); }

/* A opção que a norma não permite continua VISÍVEL, apagada e com o motivo
   ao lado. Sumir com ela responderia "essa opção não existe", quando a
   resposta certa é "ela existe e não cabe neste caso, por isto". */
.rev-linha-inerte { opacity: .55; cursor: not-allowed; }

/* AS CONSEQUÊNCIAS DE UMA EXCLUSÃO NÃO SÃO NOTA DE RODAPÉ.

   Estas linhas nasceram reaproveitando `.rev-linha`, e estava errado por dois
   motivos. Um é o tamanho: `.rev-linha` é 0,86rem porque ela lista dez ou
   quinze campos de conferência, e ali a densidade é a virtude — quem lê está
   varrendo uma lista que já conhece. Aqui são três linhas, elas são o conteúdo
   principal da tela, e a pessoa está lendo cada uma pela primeira vez para
   decidir. Texto pequeno num aviso é a forma mais silenciosa de tornar o aviso
   decorativo: ele está lá, ninguém leu.

   O outro é o cursor: `.rev-linha` tem `cursor: pointer` e fundo no hover
   porque é rótulo de caixa de seleção. Estas não são clicáveis, e prometer
   clique onde não há é ruído. */
.aviso-consequencias {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.aviso-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 4px;
  font-size: .95rem;
  line-height: 1.55;
  border-bottom: 1px solid var(--linha);
}
.aviso-item:last-child { border-bottom: 0; }
.aviso-item > i {
  flex-shrink: 0;
  width: 1.1rem;
  margin-top: .2rem;
  text-align: center;
  font-size: 1rem;
}
.aviso-item > span { min-width: 0; }

/* O TÍTULO DO AVISO CRESCE JUNTO. Uma frase de peso em corpo 0,86 ao lado de
   três linhas em 0,95 lê como legenda das linhas, e não como o aviso que ela
   é. Aqui a hierarquia é: primeiro a frase, depois o detalhe. */
.rev-aviso-forte b { font-size: 1.02rem; line-height: 1.45; }
.rev-aviso-forte p { font-size: .92rem; line-height: 1.5; margin-top: 6px; }
.rev-linha-inerte:hover { background: none; }

.rev-fecho {
  margin-top: 18px; padding: 14px 16px;
  border: 1px dashed var(--linha-forte); border-radius: var(--r-md);
}
.rev-fecho label { display: block; margin-bottom: 8px; font-size: .88rem; }
.rev-fecho input { width: 100%; font-family: ui-monospace, monospace; letter-spacing: .06em; }
.rev-fecho .pequeno { margin-top: 8px; }

/* Faixa de situação da revisão, dentro da janela do rótulo.
   Fica ACIMA da prévia: é ela que explica a tarja de RASCUNHO que a pessoa
   está vendo no desenho. Embaixo, seria lida depois da dúvida. */
.rot-situacao {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 14px; margin-bottom: 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--linha);
  background: var(--surface-2);
}
.rot-situacao i { font-size: 1.15rem; }
.rot-situacao b { display: block; }
.rot-situacao span { display: block; }
.rot-situacao.ok { border-color: rgba(78,140,94,.55); background: rgba(78,140,94,.12); }
.rot-situacao.ok i { color: var(--ok); }
.rot-situacao.pendente { border-color: rgba(201,138,43,.55); background: rgba(201,138,43,.12); }
.rot-situacao.pendente i { color: var(--alerta); }

/* ==========================================================================
   Seletor de ambiente de produção
   ==========================================================================

   Aparece só quando a organização tem duas ou mais áreas. A cor vem da área
   (--area-cor), não da paleta: é o sinal que diz, de relance, em que
   ambiente a pessoa está — e ele precisa continuar distinguível mesmo que
   duas áreas tenham escolhido o mesmo tema. */

/* O PADDING DE CIMA NÃO É ENFEITE.
 *
 * Sem ele o seletor encosta na borda de baixo do bloco da marca, e o ambiente
 * escolhido parece parte do cabeçalho da plataforma — a marca da casa e o
 * ambiente viram um bloco só — em vez de um controle com vida própria. */
.seletor-area { position: relative; padding: 14px 12px 10px; }

/* A COR DA ÁREA, resolvida por modo.
 *
 * `areas.js` emite as DUAS variantes já ajustadas para contraste — o matiz é
 * o mesmo, a luminosidade é que muda — e a escolha acontece aqui, em CSS
 * puro. Fosse em JavaScript, o seletor precisaria ser repintado a cada troca
 * de tema, e o botão de tema não sabe que o seletor existe.
 *
 * O padrão é o escuro porque o tema escuro é o padrão da aplicação. */
.seletor-area { --area-cor: var(--area-cor-escuro, var(--ouro)); }
.area-atual, .area-item { --area-cor: var(--area-cor-escuro, var(--ouro)); }

:root[data-theme="light"] .area-atual,
:root[data-theme="light"] .area-item {
  --area-cor: var(--area-cor-claro, var(--ouro));
}

.area-atual {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--linha);
  border-left: 3px solid var(--area-cor, var(--ouro));
  border-radius: var(--r-sm);
  background: var(--surface);
  color: var(--texto);
  font: inherit; font-size: .9rem; font-weight: 600;
  cursor: pointer; text-align: left;
  transition: border-color .16s, background .16s;
}
.area-atual:hover { border-color: var(--linha-forte); background: var(--surface-2); }
.area-atual > i:first-child { color: var(--area-cor, var(--ouro)); }

.area-lista {
  position: absolute; z-index: 60; left: 12px; right: 12px; top: calc(100% - 4px);
  padding: 5px;
  border: 1px solid var(--linha-forte);
  border-radius: var(--r-sm);
  background: var(--surface-2);
  box-shadow: var(--sombra-md);
}

.area-item {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 10px; border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--texto);
  font: inherit; font-size: .88rem; cursor: pointer; text-align: left;
}
.area-item:hover { background: var(--surface-3); }
.area-item.ativa { background: var(--surface-3); font-weight: 600; }
.area-item > i:first-child { color: var(--area-cor, var(--ouro)); width: 18px; text-align: center; }
.area-item .pequeno { display: block; font-weight: 400; }

/* Cabeçalho de grupo dentro do recibo da loja.
   A venda é uma só; o agrupamento é de LEITURA, para quem confere os códigos
   de compra numa compra que misturou vinho e cerveja. */
.recibo-grupo td {
  background: var(--surface-3);
  font-size: .74rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--texto-suave);
  font-weight: 600;
}

/* ==========================================================================
   Cervejaria
   ==========================================================================

   A ficha da brassagem tem seis números que decidem tudo — OG, FG, ABV, IBU,
   cor e equilíbrio — e eles precisam ser lidos JUNTOS: mexer no malte muda
   quatro deles ao mesmo tempo. Por isso a grade, e não uma lista. */

.cv-numeros {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 10px;
}
.cv-numero {
  background: var(--surface-2);
  border: 1px solid var(--linha);
  border-radius: var(--r-sm);
  padding: 8px 10px;
  text-align: center;
}
.cv-numero b {
  display: block;
  font-family: var(--serif);
  font-size: 1.35rem;
  color: var(--ouro-claro);
  line-height: 1.1;
}
.cv-numero-rot {
  display: block; font-size: .62rem; text-transform: uppercase;
  letter-spacing: .1em; color: var(--texto-fraco);
}
.cv-numero-ajuda { display: block; font-size: .64rem; color: var(--texto-fraco); }

.cv-linha {
  display: flex; justify-content: space-between; gap: 10px;
  padding: 3px 0; color: var(--texto-suave);
}
.cv-linha span:last-child { font-variant-numeric: tabular-nums; color: var(--texto); }

/* A cor da cerveja, desenhada.
   "40 EBC" não diz nada a ninguém; a amostra ao lado diz tudo, e é a
   primeira coisa que se quer saber ao montar uma receita. */
.amostra-cor {
  display: inline-block; width: 20px; height: 20px;
  border-radius: 50%; border: 1px solid var(--linha-forte);
  flex-shrink: 0;
}
.amostra-cor.grande { width: 52px; height: 52px; }
.cv-amostra {
  height: 46px; border-radius: var(--r-sm);
  border: 1px solid var(--linha-forte); margin-top: 12px;
}

.cv-rampa {
  background: var(--surface-2); border: 1px solid var(--linha);
  border-radius: var(--r-sm); padding: 10px 14px; text-align: center;
}
.cv-rampa b { display: block; font-family: var(--serif); font-size: 1.2rem; }
.cv-rampa span { display: block; font-size: .76rem; color: var(--texto-suave); }

/* A tela de nova brassagem é formulário à esquerda e ficha grudada à
   direita: cada alteração no malte muda a densidade, e ver o efeito exige
   os dois na mesma tela. */
.grade-calc { display: grid; grid-template-columns: 1fr 330px; gap: 20px; align-items: start; }
@media (max-width: 980px) { .grade-calc { grid-template-columns: 1fr; } }

.agenda-item.feita { opacity: .55; }
.agenda-item.feita b { text-decoration: line-through; }

/* Caixa dentro de um cartão, para destacar uma lista que não é opção nem
   formulário — o que NÃO se configura, por exemplo. Sem ela, a lista some no
   meio dos campos e a pessoa acredita ter coberto tudo ao ajustar os que vê. */
/* Título de seção DENTRO de um cartão — a ficha da receita empilha cinco
   blocos, e sem uma marca clara entre eles a página vira uma tabela só. */
.secao-titulo {
  margin: 0 0 8px;
  font-family: var(--serif);
  font-size: .98rem;
  font-weight: 600;
  color: var(--texto);
  padding-bottom: 5px;
  border-bottom: 1px solid var(--linha);
}

.cartao-interno {
  padding: 12px 14px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  border: 1px solid var(--linha);
}
.cartao-interno ul { line-height: 1.6; }

/* ==========================================================================
   Gantt de ocupação dos containers
   ==========================================================================

   UMA GRADE SÓ, e não uma tabela com barras posicionadas por porcentagem.

   A tentação é desenhar cada barra com `left: 12%; width: 30%`. Funciona até
   o mês ter 28 dias, ou 31, ou até alguém redimensionar a janela — e então as
   barras deixam de bater com os números do cabeçalho por dois ou três pixels,
   o suficiente para uma barra que termina no dia 14 parecer terminar no 15.
   Com `grid-column: 12 / 20`, a barra ocupa as colunas dos dias 12 a 19 por
   construção. Não há como divergir do cabeçalho: são a mesma grade.

   `--dias` é o número de dias do mês, escrito pelo JavaScript. É a única coisa
   que muda de mês para mês. */
.gt-topo {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.gt-navegacao {
  display: flex;
  align-items: center;
  gap: 6px;
}
/* A ALTURA ACOMPANHA OS BOTÕES DE SETA ao lado. O campo de mês tem padding
   próprio do navegador e vinha uns três pixels mais alto que os vizinhos — o
   bastante para a fileira inteira parecer torta sem que se saiba por quê. */
.gt-navegacao input[type="month"] {
  width: auto;
  min-width: 150px;
  margin: 0;
  height: 34px;
  padding: 0 10px;
  font-size: .86rem;
}
/* O ícone de calendário do navegador é escuro por padrão e some no tema
   escuro. `invert` é o único caminho: o pseudo-elemento não aceita `color`. */
:root:not([data-theme="light"]) .gt-navegacao input[type="month"]::-webkit-calendar-picker-indicator {
  filter: invert(.75);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .gt-navegacao input[type="month"]::-webkit-calendar-picker-indicator {
    filter: invert(.75);
  }
}
.gt-navegacao .btn { height: 34px; }

.gt-cartao { padding: 0; overflow: hidden; }

/* A rolagem é HORIZONTAL e do bloco, não da página. Um mês de 31 dias com
   dezessete recipientes não cabe num portátil, e fazer a página inteira rolar
   para o lado levaria a barra lateral junto. */
.gt-rolagem { overflow-x: auto; padding: 14px; }

.gt-grade {
  display: grid;
  /* A primeira coluna é o rótulo do recipiente e não rola com os dias: ela é
     a única pista de QUAL linha se está lendo depois de rolar duas semanas. */
  grid-template-columns: 148px minmax(806px, 1fr);
  /* `stretch`, e NÃO `center`.
   *
   * O rótulo e a faixa são duas células da mesma linha, e cada uma carrega
   * metade do filete que separa os recipientes. Centralizadas, cada uma ficava
   * com a altura do próprio conteúdo — e um recipiente livre, cuja faixa não
   * tem barra nenhuma, produzia uma célula mais baixa que a vizinha. As duas
   * metades do filete caíam em alturas diferentes, e a linha divisória parecia
   * saltar para cima justamente nas linhas vazias.
   *
   * Esticadas, as duas ocupam a altura inteira da linha e o filete é um só. */
  align-items: stretch;
  gap: 4px 10px;
  min-width: 100%;
}

.gt-canto {
  font-family: var(--serif);
  font-size: 1.02rem;
  color: var(--texto-suave);
  text-transform: capitalize;
  white-space: nowrap;
}

.gt-cabecalho {
  display: grid;
  /* 22 px por dia: com 31 dias dá 682 px, que é mais que a maioria das telas
     comporta sem rolagem — e é de propósito. Espremer o mês inteiro na largura
     disponível é o que produzia barras finas demais para ler; a rolagem
     horizontal do bloco resolve sem encolher nada. */
  grid-template-columns: repeat(var(--dias), minmax(26px, 1fr));
  position: relative;
}

.gt-cabecalho { gap: 0; }
.gt-dia {
  font-size: .7rem;
  text-align: center;
  color: var(--texto-fraco);
  padding-bottom: 4px;
  border-bottom: 1px solid var(--linha);
}
/* Fim de semana em tom mais fraco: não é feriado, mas é o dia em que ninguém
   trasfega — e isso muda como se lê um prazo apertado. */
.gt-fds { opacity: .45; }
.gt-dia.gt-hoje {
  color: var(--ouro-claro);
  font-weight: 700;
  border-bottom-color: var(--ouro);
}

.gt-rotulo {
  display: flex;
  flex-direction: column;
  /* A célula agora é esticada; o texto dentro dela é que se centraliza. */
  justify-content: center;
  gap: 0;
  min-width: 0;
  padding: 2px 0;
}
.gt-rotulo b {
  font-size: .95rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}



/* O HOJE ATRAVESSA A LINHA, e é o que separa "aconteceu" de "vai acontecer"
   sem obrigar ninguém a contar colunas até achar a data. */
/* O HOJE ATRAVESSA A LINHA INTEIRA — as duas fileiras, não uma.
   Posicionado em absoluto dentro da faixa (que é `position: relative`), ele
   não participa de grade nenhuma e por isso não empurra nada. Antes era um
   item de grade, e quando a faixa deixou de ser grade ele virou um bloco de
   largura inteira que desmontava a linha. */
.gt-linha-hoje {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 0;
  border-left: 2px solid var(--ouro);
  opacity: .55;
  pointer-events: none;
  z-index: 1;
}

.gt-barra {
  grid-row: 1;
  height: 32px;
  /* `min-width: 0` NÃO É DETALHE AQUI.
     Sem ele, um item de grade se recusa a ficar menor que o próprio conteúdo:
     a barra de dois dias esticava até caber o texto, invadia as colunas
     seguintes e passava por cima da barra vizinha. Com ele, a barra respeita
     as colunas que lhe cabem e o texto é que se corta. */
  min-width: 0;
  border: 1px solid transparent;
  border-radius: 4px;
  padding: 0 7px;
  font: inherit;
  font-size: .84rem;
  cursor: pointer;
  overflow: hidden;
  display: flex;
  align-items: center;
  gap: 6px;
  text-align: left;
  transition: filter .14s, transform .08s;
}
.gt-barra:hover { filter: brightness(1.18); }
.gt-barra:active { transform: translateY(1px); }
.gt-barra:focus-visible { outline: 2px solid var(--ouro); outline-offset: 1px; }

.gt-barra-texto {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

/* AS TRÊS TEXTURAS SÃO TRÊS GRAUS DE CERTEZA, e não três enfeites.
   Encerrada aconteceu; ativa tem líquido dentro agora; reserva é plano — e é
   só no tracejado que o botão de replanejar mexe. */
.gt-encerrada {
  background: var(--surface-3);
  border-color: var(--linha-forte);
  color: var(--texto-suave);
}
.gt-ativa {
  background: linear-gradient(180deg, var(--bordo-claro), var(--bordo));
  border-color: var(--bordo-escuro);
  color: var(--creme);
}
.gt-reserva {
  background: transparent;
  border: 1px dashed var(--ouro-fosco);
  color: var(--ouro-claro);
}
.gt-conflito {
  background: rgba(179, 69, 63, .30);
  border: 1px solid var(--perigo);
  color: #E9A7AC;
}

/* Ponta chanfrada quando a ocupação atravessa a borda do mês: a barra não
   começa nem termina ali, e um canto reto diria que sim. */
.gt-vem-de-antes   { border-top-left-radius: 0; border-bottom-left-radius: 0;
                     border-left-style: dotted; }
.gt-segue-depois   { border-top-right-radius: 0; border-bottom-right-radius: 0;
                     border-right-style: dotted; }


.gt-legenda {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  padding: 12px 14px;
  border-top: 1px solid var(--linha);
  font-size: .82rem;
  color: var(--texto-fraco);
}
.gt-legenda span { display: flex; align-items: center; gap: 6px; }
.gt-amostra {
  width: 22px; height: 11px;
  border-radius: 3px;
  display: inline-block;
  flex-shrink: 0;
}
.gt-am-encerrada { background: var(--surface-3); border: 1px solid var(--linha-forte); }
.gt-am-ativa     { background: linear-gradient(180deg, var(--bordo-claro), var(--bordo));
                   border: 1px solid var(--bordo-escuro); }
.gt-am-reserva   { border: 1px dashed var(--ouro-fosco); }
.gt-am-conflito  { background: rgba(179,69,63,.30); border: 1px solid var(--perigo); }

@media (max-width: 700px) {
  .gt-grade { grid-template-columns: 110px minmax(700px, 1fr); }
}

/* ==========================================================================
   Personalização — tema, paleta e prévia num cartão só
   ==========================================================================

   Eram três cartões e um quarto com o botão. Cada um era honesto sozinho e o
   conjunto enganava: a prévia ficava tão longe dos carrosséis que ninguém
   percebia que ela reagia a eles, e o botão que aplica tudo morava num cartão
   que parecia falar de outro assunto — havia quem trocasse o tema e fosse
   embora sem aplicar.

   Dentro de um cartão só, as divisões passam a ser TÍTULOS DE SEÇÃO. Elas
   separam sem cortar, que é a diferença entre "outro assunto" e "a próxima
   parte deste". */
.tm-secao {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 20px 0 10px;
  padding-top: 14px;
  border-top: 1px solid var(--linha);
  font-family: var(--serif);
  font-size: 1rem;
  color: var(--texto);
}
.tm-secao i { color: var(--ouro); font-size: .88rem; }

/* OS BOTÕES CENTRALIZADOS, e no fim.
   Eles fecham uma decisão que ocupou o cartão inteiro. Encostados à direita,
   ao lado de um aviso, o Aplicar parecia o botão de salvar de um campo
   qualquer — e era o botão que decide o visual de tudo o que a casa imprime. */
.tm-acoes {
  display: flex;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--linha);
}
.tm-aviso {
  text-align: center;
  margin-top: 8px;
  min-height: 1.1em;
}

/* --------------------------------------------------------- linha em duas
   fileiras: etapa em cima, barra embaixo

   As duas dividiam o mesmo retângulo, e a etapa saía em minúscula e apagada
   para não competir com o código do lote — o que a deixava feia e ilegível ao
   mesmo tempo. Não era problema de cor: eram duas informações de naturezas
   diferentes disputando uma linha só. O código identifica o LOTE; a etapa diz
   o que está ACONTECENDO ali.

   Separadas em duas fileiras da MESMA grade, cada uma ganha o seu espaço e as
   duas continuam alinhadas ao mesmo intervalo de dias — é a grade que garante
   o alinhamento, e não um cálculo de largura que erraria por um pixel. */
.gt-faixa {
  display: block;
  position: relative;
  min-height: 0;
  background: none;
  padding: 5px 0 7px;
}

.gt-fileira-etapas,
.gt-fileira-barras {
  display: grid;
  grid-template-columns: repeat(var(--dias), minmax(26px, 1fr));
}

/* ALTURA MÍNIMA NAS DUAS FILEIRAS, para a linha vazia medir o mesmo que a
   cheia. Sem ela, esticar resolve o filete torto mas deixa as linhas com
   alturas diferentes — e um Gantt de linhas desiguais é difícil de percorrer
   com o olho, que é a única coisa que se faz nele. */
.gt-fileira-etapas { margin-bottom: 4px; min-height: 17px; }

/* O trilho de fundo desceu para a fileira das barras: é ela que representa a
   ocupação do dia. Riscar também a fileira das etiquetas duplicaria as linhas
   verticais e faria a grade parecer uma folha quadriculada. */
.gt-fileira-barras {
  min-height: 32px;
  border-radius: var(--r-sm);
  background: repeating-linear-gradient(
    90deg, transparent 0, transparent calc(100% / var(--dias) - 1px),
    var(--linha) calc(100% / var(--dias) - 1px), var(--linha) calc(100% / var(--dias)));
}

/* A ETIQUETA DA ETAPA. Legível: caixa alta pequena com espaçamento, que é o
   tratamento que o resto do sistema dá a rótulo de campo. Nada de minúscula
   apagada — ela não é uma nota de rodapé da barra, é o nome do que acontece
   naquele período. */
.gt-etapa {
  grid-row: 1;
  min-width: 0;
  font-size: .72rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--texto-suave);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 0 2px;
  border-left: 2px solid var(--linha-forte);
  line-height: 1.5;
  transition: opacity .16s;
}
.gt-etapa-conflito { color: #E9A7AC; border-left-color: var(--perigo); }

/* --------------------------------------------------------- separadores

   Cada recipiente é uma faixa horizontal com fundo alternado e um filete
   embaixo. Sem isso, dezessete linhas de barras soltas no branco não dizem
   onde uma acaba e a outra começa — e a leitura "esta barra é do GAL-03"
   passa a depender de o olho percorrer o caminho inteiro até o rótulo. */
.gt-rotulo,
.gt-faixa {
  border-bottom: 1px solid var(--linha);
  padding-top: 6px;
  padding-bottom: 7px;
}
/* A ALTERNÂNCIA VEM DO JS, e não de `:nth-of-type`.
   Todos os filhos da grade são `div` — o canto e o cabeçalho entrariam na
   contagem e a listra começaria trocada. Quem sabe qual linha é a segunda é
   quem as desenha. */
.gt-par.gt-rotulo,
.gt-par.gt-faixa { background: var(--surface-2); }
.gt-rotulo { padding-left: 4px; padding-right: 8px; }

/* --------------------------------------------------------- o filtro

   Filtrar um Gantt tirando linhas da tela é perder o que ele tem de melhor: o
   contexto. Quem procura as fermentações do mês quer vê-las destacadas ENTRE
   as outras — é contra as outras que elas disputam recipiente. Então nada
   sai: o que não é da etapa escolhida perde opacidade e continua no lugar. */
/* AS DUAS FILEIRAS DIVIDEM UMA GRADE SÓ.
 *
 * Cada uma era um flex independente, e como "Destacar lotes em" e
 * "Recipientes que fazem" têm larguras diferentes, os botões de cada fileira
 * começavam num ponto — duas linhas de chips desalinhadas, cada uma terminando
 * onde calhava. Numa grade compartilhada a coluna do rótulo é calculada uma
 * vez, pelo maior dos dois textos, e as duas fileiras nascem alinhadas.
 *
 * `max-content` na primeira coluna é o que faz isso: ela cresce até o maior
 * rótulo e para. Uma largura fixa alinharia igual e quebraria no dia em que o
 * texto mudasse. */
.gt-filtros {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 10px 20px;
  align-items: center;
  padding: 12px 14px;
  border-bottom: 1px solid var(--linha);
}
.gt-filtro-rot {
  font-size: .7rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texto-fraco);
  cursor: help;
  line-height: 1.3;
}
.gt-filtro-chips {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  min-width: 0;
}

/* O filete entre as duas fileiras é posto nas DUAS células da segunda: numa
   grade não existe "a linha" como elemento para receber a borda. */
.gt-filtro-2 { border-top: 1px solid var(--linha); padding-top: 10px; }

/* Numa lateral estreita o rótulo e os chips deixam de caber lado a lado, e a
   coluna `max-content` passaria a espremer os botões num fio. Empilhados,
   cada um usa a largura inteira. */
@media (max-width: 760px) {
  .gt-filtros { grid-template-columns: 1fr; gap: 6px; }
  .gt-filtro-rot.gt-filtro-2 { margin-top: 6px; }
  .gt-filtro-chips.gt-filtro-2 { border-top: 0; padding-top: 0; }
}

.gt-chip {
  padding: 5px 13px;
  border: 1px solid var(--linha-forte);
  border-radius: 99px;
  background: transparent;
  color: var(--texto-suave);
  font: inherit;
  font-size: .84rem;
  cursor: pointer;
  transition: border-color .14s, color .14s, background .14s;
}
.gt-chip:hover { border-color: var(--ouro-fosco); color: var(--ouro-claro); }
.gt-chip.ativa {
  border-color: var(--ouro);
  background: rgba(201,162,39,.14);
  color: var(--ouro-claro);
  font-weight: 600;
}
.gt-chip:focus-visible { outline: 2px solid var(--ouro); outline-offset: 2px; }

/* APAGA, NÃO ESCONDE. `.28` é fraco o bastante para o destaque saltar e forte
   o bastante para a barra continuar sendo lida como ocupação — o ponto é
   comparar, e uma barra invisível não se compara com nada. */
.gt-apagada { opacity: .28; }
.gt-apagada.gt-barra { cursor: default; }
