/* ============================================================
   UbiSafe Fábrica — ui.css
   Refatoração do front-end (design handoff, 13/08/2026)
   ============================================================

   Por que este arquivo existe
   ---------------------------
   O projeto tinha DOIS CSS concorrendo (`app.css` e `styles.css`) com
   vocabulários paralelos para a mesma coisa (.card x .g-card, .btn x .g-btn,
   .tbl x .g-table). Vários templates carregavam os dois e misturavam os dois
   na mesma tela — é parte do "cada tela parece de um sistema diferente".

   `ui.css` é o vocabulário ÚNICO do design novo. Prefixo `u-`, sem exceção.
   Ele NÃO substitui os outros dois de uma vez: convivem enquanto a migração
   acontece tela a tela. Uma tela portada usa só `u-`; uma tela ainda não
   portada continua no vocabulário antigo e só ganha o shell novo.

   REGRA TRAVADA POR TESTE (tests/test_css_tokens.py)
   --------------------------------------------------
   Este arquivo NÃO PODE declarar nenhum token `--g-*`. A fonte única dos
   `--g-*` é `static/tokens.css` e continua sendo — quase mil atributos
   `style=""` nos templates dependem daqueles nomes. Aqui só existe `--u-*`.

   E, pelo mesmo motivo, NÃO aliase as escalas: `--g-8` é 32px e `--g-space-8`
   é 40px, são escalas diferentes. Este arquivo não toca em nenhuma das duas;
   os espaçamentos do design novo são literais, do handoff.

   Princípios do design (não são preferência, são contrato)
   --------------------------------------------------------
   - Raio 0 em tudo. Nenhum canto arredondado em lugar nenhum.
   - Sem sombra. Nada flutua: alinhamento e a força das réguas organizam.
   - Régua estrutural 2px `--u-ink`. Régua de linha 1px `--u-rule`. Não afine
     as de 2px — é a espessura que faz a página ler como impressa.
   - Todo número usa `tabular-nums`, senão a coluna dança a cada atualização.
   ============================================================ */

/* ------------------------------------------------------------
   Fonte — Archivo, servida LOCALMENTE.

   O handoff sugere o <link> do Google Fonts, mas a aplicação hoje não busca
   NADA na internet (conferido: zero URLs externas em templates/ e static/), e
   o servidor da fábrica pode estar sem saída. Um <link> externo ali vira
   espera de DNS em toda página, no aparelho que menos pode esperar — o celular
   que chega pelo QR do posto.

   São dois arquivos variáveis (400–800 num arquivo só), 67 KB no total:
   latin e latin-ext. O latin-ext é o que carrega o "ç/ã/õ" fora do latin
   básico; sem ele o português cai em fallback no meio da palavra.
   ------------------------------------------------------------ */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 100%;
  font-display: swap;
  src: url('/static/fonts/archivo-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                 U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                 U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 800;
  font-stretch: 100%;
  font-display: swap;
  src: url('/static/fonts/archivo-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                 U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* ---- Marca (lida do print do produto real) ----
     O teal está DIVIDIDO POR PAPEL de propósito: o botão real da marca
     (#2ba193) dá só 3,2:1 com branco em cima. Não use texto branco nele. */
  --u-teal:          #2ba193;  /* só onde NÃO há texto: marcador do rail, barras */
  --u-teal-campo:    #14685f;  /* campo/botão que carrega texto branco — 10,3:1 */
  --u-teal-600:      #10554e;  /* hover do botão primário */
  --u-teal-700:      #0c443e;  /* pressionado; chips no painel teal */
  --u-teal-texto:    #0f5f57;  /* kicker, link sobre fundo claro — 6,7:1 */
  --u-teal-link-hover:#12756c; /* hover de link — 5,0:1 */
  --u-rail-num:      #1a7d72;  /* quadrado numerado ativo no rail — 5,0:1 c/ branco */

  /* ---- Superfícies e tinta ---- */
  --u-bg:        #eef4f3;  /* fundo da aplicação (mint da marca) */
  --u-surface:   #f7fbfa;  /* cartão do posto */
  --u-ink:       #1a1b1b;  /* texto principal, rail, réguas de 2px */
  --u-ink-2:     #444141;  /* lead, leitura do número */
  --u-ink-3:     #5c6360;  /* texto secundário, rótulos */
  --u-rule:      #d3dcda;  /* régua fina de 1px */
  --u-track:     #d9e8e6;  /* trilha das barras */
  --u-selection: #cfe9e5;

  /* ---- Rail escuro ----
     15/08/2026 — o rail era `#1a1b1b`, o MESMO preto neutro das réguas de 2px.
     Colado no mint quase branco do conteúdo, o corte ficava agressivo: um salto
     de quase-preto para quase-branco sem meio-termo nenhum, e a tela lia como
     preto-e-branco em vez de UbiSafe.

     Agora é um CARVÃO PUXADO PARA O TEAL: mesma profundidade, mas com a
     temperatura da marca. O degradê vertical é de propósito quase imperceptível
     (dois passos, ~6 pontos de luminância) — ele existe para o rail não ler como
     um retângulo chapado de 252px, não para parecer degradê. Gradiente visível
     brigaria com o resto do sistema, que é chapado por decisão de design.

     A tinta das réguas (`--u-ink`) continua `#1a1b1b`: o preto neutro está certo
     para linha impressa, o que estava errado era usá-lo como SUPERFÍCIE. */
  --u-rail:        #1e4a44;  /* topo do degradê — teal médio */
  --u-rail-fim:    #143732;  /* pé do degradê */
  --u-rail-ativo:  #2a5751;  /* MAIS CLARO que o rail, não mais escuro (ver abaixo) */
  --u-rail-linha:  #4a7a72;  /* quadrado numerado + divisores */
  --u-rail-rotulo: #b0bcba;  /* 5,0:1 */
  --u-rail-item:   #d3dedc;  /* 7,2:1 */
  --u-rail-w:      252px;

  /* Por que estes cinco valores mudaram JUNTOS:
     clarear o fundo sem clarear o que está em cima derruba a legibilidade, e
     esta tela é lida de longe no chão de fábrica, às vezes com reflexo. Sobre
     o `#1e4a44`, os tons antigos davam: item `#b9c2c0` = 4,4:1 e rótulo de
     grupo `#9aa3a1` = 3,8:1 — os dois REPROVAM o mínimo AA de 4,5:1, e o
     rótulo é texto de 9px, onde o erro dói mais.

     E `--u-rail-ativo` inverteu de lógica: no rail quase preto ele era um
     cinza MAIS CLARO que o fundo; num rail médio, um `#1e2e2b` seria mais
     ESCURO, e o item selecionado apareceria como um buraco em vez de um
     realce. Mesma coisa com `--u-rail-linha`, que pinta os quadrados
     numerados e os divisores: ele tem de continuar flutuando ACIMA do fundo.

     O `#4a7a72` dos quadrados é uma TROCA medida, não um chute. O quadrado
     numerado tem duas exigências que puxam para lados opostos: precisa se
     destacar do rail (senão o marcador da etapa some como forma) e precisa
     segurar o número branco de 10px (que exige 4,5:1). Medido:
       #345a54 → 1,3:1 do rail (invisível) · 7,7:1 no branco
       #4a7a72 → 2,0:1 do rail             · 4,9:1 no branco   <- escolhido
       #55897f → 2,5:1 do rail             · 4,0:1 no branco (reprova o número)
     Clarear mais faz o número sumir; escurecer faz o quadrado sumir. */

  /* ---- Semáforo ----
     Dois níveis por tom. O de LINHA pinta borda/barra; o de FILL fica atrás de
     texto branco. Status como texto em <=11px usa o FILL: #15803d e #b45309
     dão 4,49:1 nesse tamanho e reprovam AA por pouco.
     O verde foi afastado do teal da marca de propósito, para não confundir
     identidade com status.

     REGRA DE USO (15/08/2026, decisão do dono — vale para o sistema inteiro):
     `u-crit` e `u-warn` são para AÇÃO OU CONDIÇÃO COM CONSEQUÊNCIA, nunca para
     decoração. Ação segura — simular, conferir, pré-visualizar — é neutra, por
     mais importante que seja.

     O caso que originou a regra: na tela Importar, o selo "Dry-run antes de
     gravar" (a rede de segurança) vinha em `u-warn`, e a única ação sem volta da
     página — apagar códigos do banco — era um checkbox cinza. Quem varre a tela
     lê o tom antes da palavra, então aquilo ensinava duas coisas erradas de uma
     vez: que o âmbar não precede nada de grave, e que antes de apagar dado não
     há sinal nenhum a procurar. Quando tudo é urgente, nada é.

     A ÊNFASE é outro eixo e continua onde estava: quem grava é preenchido
     (`u-btn-solid`), quem simula é contorno. Tom ≠ peso.
     Travado, na tela onde nasceu, por tests/test_tom_por_consequencia.py. */
  --u-ok:        #157a42;
  --u-ok-fill:   #14713d;  /* 7,2:1 com branco */
  --u-warn:      #b45309;
  --u-warn-fill: #8a4008;  /* 7,4:1 */
  --u-crit:      #b91c1c;
  --u-crit-fill: #a11616;  /* 8,0:1 */

  /* ---- Tipografia ---- */
  --u-font: 'Archivo', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  /* ---- Ritmo da página (literais do handoff) ---- */
  --u-pad-x:     44px;   /* padding lateral de toda seção */
  --u-pad-sec:   34px;   /* padding vertical padrão de seção */
  --u-shell-gap: 0px;
}

/* Tons como custom property: um modificador só, herdado pelos filhos.
   É o que deixa `.u-queue-row.u-crit` pintar borda, número e status de uma vez
   sem três classes diferentes. */
.u-ok   { --u-tone: var(--u-ok);   --u-tone-fill: var(--u-ok-fill); }
.u-warn { --u-tone: var(--u-warn); --u-tone-fill: var(--u-warn-fill); }
.u-crit { --u-tone: var(--u-crit); --u-tone-fill: var(--u-crit-fill); }
.u-ink  { --u-tone: var(--u-ink);  --u-tone-fill: var(--u-ink); }

/* ============================================================
   1. Base
   ============================================================ */

.u-app,
body.u-app {
  margin: 0;
  background: var(--u-bg);
  color: var(--u-ink);
  font-family: var(--u-font);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

.u-app *,
.u-app *::before,
.u-app *::after { box-sizing: border-box; }

.u-app ::selection { background: var(--u-selection); }

.u-app a { color: var(--u-teal-campo); }
.u-app a:hover { color: var(--u-teal-link-hover); }

/* Nunca o anel azul padrão do browser. */
.u-app :focus-visible {
  outline: 2px solid var(--u-teal-campo);
  outline-offset: 2px;
}

/* Nada arredondado, nada flutuando — inclusive no que vier de fora. */
.u-app :where(button, input, select, textarea, .u-card, .u-btn) {
  border-radius: 0;
  box-shadow: none;
}

.u-tnum { font-variant-numeric: tabular-nums; }

/* ============================================================
   2. Shell — rail lateral fixo

   O rail é a linha de produção como espinha, numerada 1 a 7, e é ele que
   responde "onde eu estou". Substitui a barra horizontal escura com dropdowns.

   POR QUE `position: fixed` + irmão geral, e não um wrapper em grid:
   o rail é um `{% include %}` no meio do `{% block body %}` de 47 templates.
   Um wrapper exigiria abrir a <div> num partial e fechar noutro — e um grid de
   duas colunas quebraria em toda tela que tem um terceiro filho no body (os
   <dialog> das telas de conferência e inspeção viravam uma terceira coluna).
   Com fixed + `~ main`, o partial continua fechado em si mesmo e qualquer
   elemento extra no body fica de fora da conta.
   ============================================================ */

.u-rail {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--u-rail-w);
  z-index: 40;
  /* `--u-rail` sozinho como fallback: navegador que não pintar o gradiente fica
     com o carvão chapado, que continua correto. */
  background: var(--u-rail);
  background: linear-gradient(180deg, var(--u-rail) 0%, var(--u-rail-fim) 100%);
  background-attachment: local; /* o degradê acompanha o rail quando ele rola por dentro */
  color: var(--u-bg);
  display: flex;
  flex-direction: column;
  gap: 22px;
  padding: 26px 0 32px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.u-rail ~ main,
.u-rail ~ .u-main { margin-left: var(--u-rail-w); }

/* O banner global nasce ANTES do rail no body (base.html), então não é irmão
   posterior — `~` não o alcança. */
body:has(> .u-rail) .g-banner-global { margin-left: var(--u-rail-w); }

.u-main {
  min-width: 0;
  background: var(--u-bg);
}

/* -- lockup da marca: marca + régua de 1px + "Fábrica" -- */
.u-rail-top {
  padding: 0 22px;
  display: flex;
  align-items: center;
  gap: 11px;
}
.u-rail-top img { height: 26px; width: auto; display: block; flex: none; }
.u-rail-rule {
  width: 1px;
  height: 20px;
  background: var(--u-rail-linha);
  display: block;
  flex: none;
}
.u-rail-word {
  font-weight: 800;
  font-size: 15px;
  letter-spacing: -.01em;
  color: var(--u-bg);
}

/* Setor do operador, sob o lockup. Margem negativa no topo para colar no
   lockup: os 22px de gap do rail separam GRUPOS, e o subtítulo pertence à
   marca, não é um grupo à parte. */
.u-rail-sub {
  margin-top: -14px;
  padding: 0 22px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--u-rail-rotulo);
}

/* -- navegação --
   O seletor é `.u-rail .nav` e não uma classe `u-` própria porque o <nav> tem
   de sair do template como `class="nav"` exato: tests/test_topbar_por_papel.py
   casa `<nav class="nav"[^>]*>` e LEVANTA se não achar. Ver _topbar.html. */
.u-rail .nav {
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.u-nav-group { display: flex; flex-direction: column; gap: 1px; }
.u-nav-title {
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--u-rail-rotulo);
  padding: 0 22px 9px;
}

/* `.u-rail` no seletor NÃO é enfeite — é o que faz a cor valer.
   Os itens são <a>, e a regra global `.u-app a { color: var(--u-teal-campo) }`
   tem especificidade (0,1,1), que vence `.u-nav-item` sozinho (0,1,0). Resultado:
   o teal ESCURO de link-sobre-fundo-claro pintava o menu do rail ESCURO, e o
   `--u-rail-item` nunca era aplicado. O item ativo escapava por acidente — o
   seletor dele tem duas classes e ganhava da global.
   Isso existia desde o primeiro dia do rail; só ficou visível quando o fundo
   clareou. Especificidade silenciosa é assim: não quebra nada, só entrega a cor
   errada e deixa quem olha achando que está ficando cego. */
.u-rail .u-nav-item {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 9px 22px 9px 19px;
  border-left: 3px solid transparent;
  color: var(--u-rail-item);
  font-size: 13px;
  font-weight: 400;
  text-decoration: none;
}
.u-rail .u-nav-item:hover {
  background: var(--u-rail-ativo);
  color: var(--u-bg);
}
.u-rail .u-nav-item[aria-current="page"] {
  border-left-color: var(--u-teal);
  background: var(--u-rail-ativo);
  color: var(--u-bg);
  font-weight: 600;
}
.u-nav-label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.u-nav-num {
  width: 20px;
  height: 20px;
  flex: none;
  display: grid;
  place-items: center;
  font-size: 10px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  background: var(--u-rail-linha);
  color: #fff;
}
.u-rail .u-nav-item[aria-current="page"] .u-nav-num { background: var(--u-rail-num); }
.u-nav-mark {
  margin-left: auto;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .1em;
  padding: 2px 6px;
  background: var(--u-rail-linha);
  color: var(--u-rule);
  flex: none;
}

/* SMD: submenu lateral nativo; abrir o grupo não navega nem consulta a máquina. */
.u-rail .u-nav-smd > summary { cursor: pointer; list-style: none; }
.u-rail .u-nav-smd > summary::-webkit-details-marker { display: none; }
.u-rail .u-nav-smd > summary::marker { content: ""; }
.u-rail .u-nav-smd > summary:focus-visible { outline: 2px solid var(--u-teal); outline-offset: -3px; }
.u-nav-smd-arrow { margin-left: auto; font-size: 20px; line-height: 1; transition: transform .15s; }
.u-nav-smd[open] > summary .u-nav-smd-arrow { transform: rotate(90deg); }
.u-rail .u-nav-smd-children .u-nav-item { padding-left: 49px; font-size: 12px; }
/* Direção (19/09): mesmo submenu, mas no Comando o summary não tem número —
   os 49px acima pressupõem o quadrado numerado; aqui o filho recua só um passo. */
.u-rail .u-nav-dir .u-nav-smd-children .u-nav-item { padding-left: 31px; }
@media (max-width: 880px) {
  .u-rail .u-nav-smd { flex: none; min-width: 150px; }
  .u-rail .u-nav-smd-children .u-nav-item { padding-left: 25px; }
}

/* -- rodapé do rail: quem está logado -- */
.u-rail-user {
  margin-top: auto;
  padding: 18px 22px 0;
  border-top: 1px solid var(--u-rail-linha);
  display: flex;
  align-items: center;
  gap: 10px;
}
.u-rail-avatar {
  width: 32px;
  height: 32px;
  background: var(--u-bg);
  color: var(--u-ink);
  font-weight: 800;
  font-size: 12px;
  display: grid;
  place-items: center;
  flex: none;
}
.u-rail-who { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.u-rail-name {
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.u-rail-role {
  /* A lista completa de perfis também aparece em Minhas áreas. */
  font-size: 10px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--u-rail-rotulo);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.u-rail-out {
  margin-left: auto;
  font-size: 11px;
  color: var(--u-rail-item);
  text-decoration: none;
  flex: none;
}
.u-rail-out:hover { color: var(--u-bg); }

/* ============================================================
   3. Cabeçalho de tela
   ============================================================ */

.u-head {
  padding: 40px var(--u-pad-x) 30px;
  border-bottom: 2px solid var(--u-ink);
}
.u-head-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}
.u-kicker {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--u-teal-texto);
  margin: 0;
}
.u-h1 {
  font-weight: 800;
  font-size: clamp(32px, 6.5vw, 52px);
  line-height: .98;
  letter-spacing: -.04em;
  margin: 16px 0 0;
}
.u-lead {
  font-size: 16px;
  line-height: 1.5;
  color: var(--u-ink-2);
  margin: 14px 0 0;
  max-width: 58ch;
  text-wrap: pretty;
}

/* Selo de somente-leitura. Aparece na visão Gestão, nas telas cuja ação é do
   operador — "a gestão observa a linha; quem age é quem está na bancada". */
.u-readonly {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: 18px;
  padding: 7px 12px;
  border: 2px solid var(--u-ink);
}
.u-readonly::before {
  content: "";
  width: 8px;
  height: 8px;
  background: var(--u-ink);
  display: block;
  flex: none;
}
.u-readonly span {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* ============================================================
   4. Botões — alvo de toque nunca abaixo de 44px
   ============================================================ */

.u-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 20px;
  border: 2px solid var(--u-ink);
  background: transparent;
  color: var(--u-ink);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.u-btn:hover { background: color-mix(in srgb, var(--u-ink) 8%, transparent); color: var(--u-ink); }
.u-btn-solid { background: var(--u-ink); color: var(--u-bg); }
.u-btn-solid:hover { background: #000; color: var(--u-bg); }
.u-btn-primary {
  background: var(--u-teal-campo);
  border-color: var(--u-teal-campo);
  color: var(--u-bg);
}
.u-btn-primary:hover { background: var(--u-teal-600); border-color: var(--u-teal-600); color: var(--u-bg); }
.u-btn-primary:active { background: var(--u-teal-700); border-color: var(--u-teal-700); }
.u-btn-sm { min-height: 40px; padding: 0 16px; }

/* QUANDO O BOTÃO É UM <a> — mesma armadilha do rail, algumas seções acima.
   `.u-app a { color: var(--u-teal-campo) }` tem especificidade (0,1,1) e vence
   `.u-btn-primary` (0,1,0). Num <button> nada acontece, porque a regra global
   só pega <a>; num <a class="u-btn u-btn-primary"> o texto vira teal ESCURO
   sobre o fundo teal do próprio botão e SOME — o botão fica um retângulo
   maciço, sem texto. Relatado com print em 24/08/2026 no "Sim, abrir
   questionário" da /confirmar-equipamento.

   Não é defeito de uma tela: são 6 <a> em 4 templates, e dois deles são
   acesso_negado.html e erro.html — as telas de erro, onde o botão que
   desaparece é justamente o de sair do erro.

   A ORDEM AQUI É LOAD-BEARING. `a.u-btn-primary` EMPATA com `.u-app a` (as duas
   são 1 tipo + 1 classe), e empate se resolve por ordem no arquivo: mover este
   bloco para antes da seção 2 devolve o bug em silêncio. A variante com
   `.u-app` na frente é o cinto de segurança para quem depender só dela.
   Travado por tests/test_contraste_botao_link.py. */
a.u-btn,
.u-app a.u-btn { color: var(--u-ink); }
a.u-btn:hover,
.u-app a.u-btn:hover { color: var(--u-ink); }
a.u-btn-solid, a.u-btn-solid:hover,
a.u-btn-primary, a.u-btn-primary:hover,
.u-app a.u-btn-solid, .u-app a.u-btn-solid:hover,
.u-app a.u-btn-primary, .u-app a.u-btn-primary:hover { color: var(--u-bg); }
.u-btn[disabled] { opacity: .45; cursor: not-allowed; }

/* Grupo segmentado (Hoje / Semana / Mês) — uma moldura, divisores internos. */
.u-seg { display: flex; border: 2px solid var(--u-ink); flex-wrap: wrap; }
.u-seg > * {
  min-height: 40px;
  padding: 0 16px;
  display: inline-flex;
  align-items: center;
  border: 0;
  border-left: 2px solid var(--u-ink);
  background: transparent;
  color: var(--u-ink);
  font: inherit;
  font-size: 13px;
  text-decoration: none;
  cursor: pointer;
}
.u-seg > *:first-child { border-left: 0; }
.u-seg > *:hover { background: color-mix(in srgb, var(--u-ink) 8%, transparent); }
.u-seg > .active,
.u-seg > [aria-selected="true"] {
  background: var(--u-ink);
  color: var(--u-bg);
  font-weight: 600;
}

/* ============================================================
   5. Seção do número principal

   O número principal fica SEMPRE em tinta. O tom (atenção/crítico) vive só no
   selo pequeno abaixo — número em escala de cartaz colorido virava outra marca
   e brigava com o teal.
   ============================================================ */

.u-hero {
  padding: 44px var(--u-pad-x) 40px;
  border-bottom: 2px solid var(--u-ink);
  display: grid;
  grid-template-columns: minmax(0, 1fr) 272px;
  gap: 44px;
  align-items: start;
}
.u-hero-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--u-ink-3);
}
.u-hero-value {
  font-weight: 800;
  font-size: clamp(58px, 13vw, 112px);
  line-height: .85;
  letter-spacing: -.05em;
  margin: 18px 0 0;
  font-variant-numeric: tabular-nums;
  color: var(--u-ink);
}
.u-hero-read {
  font-size: 17px;
  line-height: 1.5;
  color: var(--u-ink-2);
  margin: 22px 0 0;
  max-width: 46ch;
  text-wrap: pretty;
}
.u-tag {
  display: inline-block;
  margin-top: 22px;
  padding: 8px 14px;
  background: var(--u-tone-fill, var(--u-ink));
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* -- coluna direita: quatro números de apoio, sempre quatro, sempre na mesma
      ordem. É o que faz a tela ser aprendida uma vez e servir para todas. -- */
.u-aside {
  border-left: 2px solid var(--u-ink);
  padding-left: 32px;
  display: flex;
  flex-direction: column;
}
.u-aside-item { padding: 16px 0; border-bottom: 1px solid var(--u-rule); }
.u-aside-item:first-child { padding-top: 0; padding-bottom: 16px; }
.u-aside-item:last-child { padding-bottom: 0; border-bottom: 0; }
.u-aside-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--u-tone-fill, var(--u-ink-3));
}
.u-aside-value {
  font-weight: 800;
  font-size: 28px;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  margin-top: 6px;
}
.u-aside-note {
  font-size: 11px;
  color: var(--u-ink-3);
  margin-top: 5px;
  line-height: 1.4;
}

/* ============================================================
   6. Seções genéricas
   ============================================================ */

.u-section {
  padding: var(--u-pad-sec) var(--u-pad-x);
  border-bottom: 2px solid var(--u-ink);
}
.u-section:last-child,
.u-section-end {
  border-bottom: 0;
  padding-bottom: 60px;
}
.u-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 20px;
  flex-wrap: wrap;
}
.u-section-title {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--u-ink-3);
  margin: 0;
}
.u-section-note {
  font-size: 13px;
  color: var(--u-ink-3);
  max-width: 64ch;
  margin: 6px 0 24px;
}

/* ============================================================
   7. Barras de comparação

   CADA LINHA É GRID, NÃO FLEX — e isso não é estilo, é correção.
   Com `flex: 0 1 <pct>%` na barra, o rótulo de largura fixa + o valor + os
   gaps somam mais que a linha; o flex-shrink comprime todas as barras contra a
   mesma folga e o percentual não sobrevive — o MAIOR valor vira a MENOR barra.
   A largura tem de resolver contra uma trilha já assentada.
   ============================================================ */

.u-bars { display: flex; flex-direction: column; gap: 15px; max-width: 860px; }
.u-bar-row {
  display: grid;
  grid-template-columns: 210px minmax(0, 1fr) 64px;
  gap: 16px;
  align-items: center;
}
.u-bar-label { font-size: 15px; }
.u-bar-track { display: block; height: 20px; background: var(--u-track); }
.u-bar-fill { display: block; height: 20px; background: var(--u-ink); }
.u-bar-fill-lead { background: var(--u-teal-campo); }
.u-bar-value {
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* Variante compacta, para duas colunas de barras lado a lado. */
.u-bars-mini { display: flex; flex-direction: column; gap: 16px; }
.u-bars-mini .u-bar-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
}
.u-bars-mini .u-bar-track,
.u-bars-mini .u-bar-fill { height: 12px; }

/* ============================================================
   8. Fila ordenada por urgência
   ============================================================ */

.u-queue { display: flex; flex-direction: column; border-top: 2px solid var(--u-ink); }
.u-queue-row {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 20px 0 20px 20px;
  border-bottom: 1px solid var(--u-rule);
  border-left: 6px solid var(--u-tone, var(--u-ink));
}
.u-queue-value {
  font-weight: 800;
  font-size: 34px;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  width: 92px;
  flex: none;
}
.u-crit > .u-queue-value { color: var(--u-crit); }
.u-queue-text { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 180px; }
.u-queue-title { font-size: 17px; font-weight: 600; }
.u-queue-sub { font-size: 13px; color: var(--u-ink-3); }

/* À direita, UMA das duas coisas: o botão (se o perfil for dono da ação) ou o
   status em texto. NUNCA as duas vazias — quando a ação sai para a Gestão, a
   linha precisa manter a condição escrita, senão as linhas urgentes (que
   traziam botão) ficam mudas e só as saudáveis dizem o status, invertendo a
   leitura da tela inteira. */
.u-queue-status {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  flex: none;
  color: var(--u-tone-fill, var(--u-ink));
}

/* ============================================================
   9. Blocos explicativos

   Toda grade `auto-fit` precisa de row-gap E de padding vertical nas células:
   sem isso, quando ela quebra para duas linhas os textos se encostam sem
   respiro e as bordas viram traço solto no meio da página.
   ============================================================ */

.u-blocks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  column-gap: 24px;
  row-gap: 24px;
}
.u-block { padding: 18px 0 20px; border-top: 2px solid var(--u-ink); }
.u-block-head { display: flex; align-items: center; gap: 9px; }
.u-block-num {
  width: 24px;
  height: 24px;
  flex: none;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 600;
  background: var(--u-teal-campo);
  color: var(--u-bg);
}
.u-block-title { font-size: 15px; font-weight: 600; }
.u-block-text { font-size: 13px; color: var(--u-ink-3); margin-top: 10px; line-height: 1.5; }

/* BLOCO QUE É LINK. 15/08/2026 — os atalhos da home ("Apontar produção",
   "Abrir Almoxarifado") são <a> desde sempre, e o dono disse a coisa exata:
   "não parece um botão". Não parecia mesmo — eram idênticos aos blocos de TEXTO
   explicativo logo acima, e o único sinal de que abriam algo era o cursor, que
   no tablet do chão de fábrica não existe.
   O design não tem sombra nem raio para gastar aqui, então o sinal é o que o
   sistema já usa: a régua de 2px ganha a cor da marca, o título fica em teal e
   entra uma seta que anda no hover. Estático, chapado, e inequívoco. */
a.u-block {
  display: block;
  text-decoration: none;
  color: inherit;
  border-top-color: var(--u-teal-campo);
  padding-right: 16px;
}
a.u-block .u-block-title { color: var(--u-teal-texto); }
a.u-block .u-block-head::after {
  content: "→";
  margin-left: auto;
  font-size: 16px;
  font-weight: 600;
  color: var(--u-teal-texto);
  transition: transform .16s ease;
}
a.u-block:hover {
  background: color-mix(in srgb, var(--u-teal-campo) 7%, transparent);
  color: inherit;
}
a.u-block:hover .u-block-head::after { transform: translateX(4px); }
a.u-block:focus-visible { outline: 2px solid var(--u-teal-campo); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  a.u-block .u-block-head::after { transition: none; }
}

/* ============================================================
   10. Grade de etapas (a linha, etapa por etapa)
   ============================================================ */

.u-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  border-top: 2px solid var(--u-ink);
}
.u-step {
  padding: 16px 16px 20px;
  border-right: 1px solid var(--u-rule);
  border-top: 4px solid var(--u-tone, var(--u-ink));
  color: inherit;
  text-decoration: none;
  display: block;
}
.u-step:hover { background: color-mix(in srgb, var(--u-ink) 4%, transparent); color: inherit; }
.u-step-head { display: flex; align-items: center; gap: 7px; }
.u-step-dot { width: 8px; height: 8px; flex: none; display: block; background: var(--u-tone, var(--u-ink)); }
.u-step-n { font-size: 10px; font-weight: 600; letter-spacing: .12em; color: var(--u-ink-3); }
.u-step-name { display: block; font-size: 14px; font-weight: 600; margin-top: 5px; }
.u-step-value {
  font-weight: 800;
  font-size: 26px;
  letter-spacing: -.02em;
  margin-top: 12px;
  font-variant-numeric: tabular-nums;
}
.u-step-legend { font-size: 11px; color: var(--u-ink-3); margin-top: 4px; line-height: 1.35; }

/* ============================================================
   10b. Gráficos de apoio

   O design novo é tipográfico e quase não usa gráfico — a leitura principal
   mora no número de cartaz e nas barras. Os gráficos que já existiam não foram
   jogados fora (respondem "como veio no tempo", que texto nenhum responde), mas
   desceram de protagonista para apoio: sem cartão, sem sombra, separados só por
   régua, com título na mesma escala dos outros títulos de seção.
   ============================================================ */

.u-charts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  column-gap: 44px;
  row-gap: 36px;
}
.u-charts > div { padding-top: 18px; border-top: 2px solid var(--u-ink); min-width: 0; }
.u-chart-title { font-size: 15px; font-weight: 600; margin: 0 0 4px; }
.u-charts .u-hint { display: block; margin-bottom: 14px; }

/* Grade dos cartões por origem (#testByOrigem, injetado pelo app.js). */
.u-origem-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap: 20px;
}

/* ============================================================
   11. Tabela de detalhe — sempre por último na tela

   `.u-table-wrap` é obrigatório. Sem contêiner de rolagem, uma tabela de 6
   colunas força ~484px de mínimo e estoura o celular na horizontal. É a mesma
   função do `.table-wrap` do app.css, mantida de propósito.
   ============================================================ */

.u-table-wrap { overflow-x: auto; }
.u-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.u-table th {
  padding: 10px 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-align: left;
  color: color-mix(in srgb, var(--u-ink) 60%, transparent);
  border-bottom: 2px solid var(--u-rule);
  white-space: nowrap;
}
.u-table td { padding: 15px 8px; border-bottom: 1px solid var(--u-rule); }
.u-table tbody tr:hover { background: color-mix(in srgb, var(--u-ink) 4%, transparent); }
.u-table .u-num,
.u-table th.u-num { text-align: right; font-variant-numeric: tabular-nums; }
.u-table .u-dim { color: var(--u-ink-3); }
.u-table .u-strong { font-weight: 600; }

.u-badge {
  display: inline-block;
  padding: 4px 10px;
  background: var(--u-tone-fill, var(--u-ink));
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  white-space: nowrap;
}

.u-empty {
  padding: 40px 0 8px;
  color: var(--u-ink-3);
}
.u-empty-title { font-size: 17px; font-weight: 600; color: var(--u-ink); }
.u-empty-desc { font-size: 13px; margin-top: 6px; }

/* ============================================================
   12. Telas de posto (celular / tablet no chão de fábrica)

   NÃO fixe a primeira trilha em px. Com `404px minmax(0,1fr)` a segunda coluna
   colapsa e estoura a página na horizontal.
   Alvos de toque: 52px nos campos, 56px nos botões.
   ============================================================ */

.u-posto {
  padding: 40px var(--u-pad-x) 60px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  column-gap: 44px;
  row-gap: 40px;
  align-items: start;
}
.u-card { border: 2px solid var(--u-ink); background: var(--u-surface); }
.u-card-bar {
  background: var(--u-ink);
  color: var(--u-bg);
  padding: 16px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.u-card-bar b { font-size: 15px; font-weight: 600; }
.u-card-bar-mark { font-size: 10px; letter-spacing: .14em; color: var(--u-rail-rotulo); }
.u-card-body { padding: 22px 20px 26px; display: flex; flex-direction: column; gap: 20px; }

.u-field { display: flex; flex-direction: column; gap: 7px; }
.u-field-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--u-ink-3);
}
.u-control,
.u-app input.u-control,
.u-app select.u-control,
.u-app textarea.u-control {
  min-height: 52px;
  width: 100%;
  display: flex;
  align-items: center;
  padding: 0 14px;
  border: 2px solid var(--u-ink);
  background: var(--u-bg);
  color: var(--u-ink);
  font: inherit;
  font-size: 16px; /* 16px evita o zoom automático do iOS ao focar */
}
.u-app textarea.u-control { padding: 12px 14px; line-height: 1.5; }
.u-hint { font-size: 12px; color: var(--u-ink-3); }

/* Modal compartilhado do leitor de QR (/static/qr_scanner.js).
   O componente nasce no fim do body; sem estas regras ele entra no fluxo da
   página, fica fora da área visível e o vídeo alarga o documento no celular. */
.u-app .qr-camera-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: none;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: 100vw;
  height: 100vh;
  height: 100dvh;
  padding: 16px;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: rgba(26, 27, 27, .82);
}
.u-app .qr-camera-overlay.is-open { display: flex; }
.u-app .qr-camera-modal {
  width: min(540px, 100%);
  max-width: 100%;
  max-height: calc(100vh - 32px);
  max-height: calc(100dvh - 32px);
  overflow: auto;
  background: var(--u-surface);
  border: 2px solid var(--u-ink);
}
.u-app .qr-camera-modal > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  background: var(--u-ink);
  color: var(--u-bg);
}
.u-app .qr-camera-modal > header h3 { margin: 0; font-size: 16px; }
.u-app .qr-camera-modal > header button {
  width: 44px;
  height: 44px;
  flex: none;
  border: 0;
  background: transparent;
  color: var(--u-bg);
  font: inherit;
  font-size: 26px;
  cursor: pointer;
}
.u-app .qr-camera-body { padding: 16px; }
.u-app .qr-camera-area {
  display: flex;
  width: 100%;
  max-width: 100%;
  min-height: min(280px, 50vh);
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: #000;
}
.u-app .qr-camera-area > * { max-width: 100%; }
.u-app .qr-camera-area video {
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
  max-height: 58vh;
  object-fit: contain;
}
.u-app .qr-camera-body > p {
  margin: 12px 0 0;
  text-align: center;
  color: var(--u-ink-3);
  font-size: 13px;
}
.u-app .qr-camera-error {
  padding: 12px 14px;
  border-left: 6px solid var(--u-crit);
  background: var(--u-surface-2);
  color: var(--u-ink);
}
.u-app .qr-camera-actions {
  display: flex;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 12px;
}
.u-app .qr-camera-actions label,
.u-app .qr-camera-area .btn {
  display: inline-flex;
  min-height: 48px;
  align-items: center;
  justify-content: center;
  padding: 0 16px;
  border: 2px solid var(--u-ink);
  color: var(--u-ink);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
}
.u-app .qr-camera-area .btn { border-color: #fff; color: #fff; }
.u-app .qr-camera-actions input {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}
.u-app .qr-camera-placeholder { padding: 20px; color: #fff; text-align: center; }

.u-btn-posto {
  min-height: 56px;
  justify-content: flex-start;
  text-align: left;
  font-size: 16px;
  padding: 0 20px;
}

/* ============================================================
   13. Telas de entrada (login / primeiro acesso) — sem rail
   ============================================================ */

.u-login {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 100vh;
}
.u-login-aside {
  background: var(--u-teal-campo);
  color: var(--u-bg);
  padding: 56px 48px;
  display: flex;
  flex-direction: column;
}
.u-login-aside img { height: 34px; width: auto; display: block; flex: none; }
.u-login-aside .u-rail-rule { height: 26px; background: rgba(238, 244, 243, .45); }
.u-login-aside .u-rail-word { font-size: 20px; }
.u-login-h1 {
  font-weight: 800;
  font-size: clamp(30px, 6vw, 46px);
  line-height: 1.02;
  letter-spacing: -.04em;
  margin: 56px 0 0;
  max-width: 20ch;
}
.u-login-steps {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  border-top: 2px solid rgba(238, 244, 243, .4);
}
.u-login-step {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 15px 0;
  border-bottom: 1px solid rgba(238, 244, 243, .28);
  font-size: 14px;
  color: var(--u-bg);
}
.u-login-step:last-child { border-bottom: 0; }
.u-login-chip {
  width: 22px;
  height: 22px;
  background: var(--u-teal-700);
  color: var(--u-bg);
  font-size: 11px;
  font-weight: 600;
  display: grid;
  place-items: center;
  flex: none;
}
.u-login-step:first-child .u-login-chip {
  background: var(--u-bg);
  color: var(--u-teal-campo);
  font-weight: 700;
}
.u-login-main { display: flex; align-items: center; padding: 56px 48px; }
.u-login-form { width: 100%; max-width: 380px; }
.u-login-h2 { font-weight: 800; font-size: 34px; letter-spacing: -.03em; margin: 0; }
.u-login-sub { font-size: 15px; color: var(--u-ink-3); margin: 12px 0 0; }
.u-login-fields { display: flex; flex-direction: column; gap: 18px; margin-top: 34px; }
.u-login-label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--u-ink-3);
}
.u-app input.u-login-input {
  min-height: 48px;
  width: 100%;
  padding: 0 12px;
  border: 2px solid var(--u-ink);
  background: var(--u-bg);
  color: var(--u-ink);
  font: inherit;
  font-size: 15px;
}
.u-btn-login { min-height: 52px; justify-content: flex-start; text-align: left; font-size: 15px; padding: 0 20px; }

/* ============================================================
   14. Faixa poster (o número que vira manchete)
   ============================================================ */

.u-poster {
  background: var(--u-teal-campo);
  color: var(--u-bg);
  padding: 34px var(--u-pad-x);
  display: flex;
  align-items: center;
  gap: 36px;
  flex-wrap: wrap;
}
.u-poster-value {
  font-weight: 800;
  font-size: clamp(52px, 11vw, 88px);
  line-height: .85;
  letter-spacing: -.05em;
  font-variant-numeric: tabular-nums;
}
.u-poster-text { display: flex; flex-direction: column; gap: 8px; flex: 1; min-width: 260px; }
.u-poster-title { font-weight: 800; font-size: 26px; line-height: 1.1; letter-spacing: -.02em; }
.u-poster-read { font-size: 15px; line-height: 1.45; max-width: 56ch; opacity: .92; }
.u-poster .u-btn {
  min-height: 48px;
  padding: 0 22px;
  border-color: var(--u-bg);
  color: var(--u-bg);
  font-size: 14px;
}
.u-poster .u-btn:hover { background: rgba(238, 244, 243, .14); color: var(--u-bg); }

/* -- Deck: a faixa poster girando entre os problemas (home da gestão) --

   TRÊS DECISÕES QUE NÃO SÃO ESTILO:

   1. Os slides ficam EMPILHADOS NA MESMA CÉLULA de grade (`grid-area: 1/1`), não
      lado a lado com translate. Assim a faixa tem a altura do slide mais alto
      desde o primeiro quadro e NÃO PULA ao trocar — textos de problema têm
      comprimentos diferentes, e uma faixa que muda de altura empurra a página
      inteira a cada 7 segundos.

   2. O inativo usa `visibility: hidden`, não só `opacity: 0`. Opacidade zero
      deixa o botão CLICÁVEL e no Tab: a pessoa alcançaria "Abrir a fila da SMD"
      de um slide invisível e iria para o lugar errado.

   3. A transição é fade + 8px de subida, não deslize horizontal. O sistema é
      tipográfico e chapado; um carrossel deslizante traria a linguagem de outro
      produto. A subida curta lê como página virando, que é o que a faixa é.
      Nada de raio, nada de sombra, nada flutuando — aqui também não. */
.u-poster-wrap { border-bottom: 2px solid var(--u-ink); }
.u-poster-deck { display: grid; }
.u-poster-deck .u-poster { border-bottom: 0; }
.u-poster-slide {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity .32s ease, transform .32s ease, visibility 0s linear .32s;
}
.u-poster-slide[data-ativo="1"] {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity .32s ease, transform .32s ease, visibility 0s;
}

.u-poster-nav {
  background: var(--u-teal-campo);
  color: var(--u-bg);
  padding: 0 var(--u-pad-x) 22px;
  display: flex;
  align-items: center;
  gap: 10px;
}
/* Quadrado, não bolinha: no design nada é redondo. Alvo de toque de 30px de
   altura com a marca visível de 4px — o alvo grande é para o dedo, a marca
   pequena é para o olho. */
.u-poster-tick {
  width: 34px;
  height: 30px;
  padding: 13px 0;
  border: 0;
  background: none;
  cursor: pointer;
  flex: none;
  -webkit-appearance: none;
  appearance: none;
}
.u-poster-tick::before {
  content: "";
  display: block;
  height: 4px;
  background: rgba(238, 244, 243, .4);
}
.u-poster-tick:hover::before { background: rgba(238, 244, 243, .7); }
.u-poster-tick[aria-current="true"]::before { background: var(--u-bg); }
.u-poster-count { margin-left: 6px; font-size: 12px; opacity: .8; }
.u-poster-count b { font-weight: 700; }

/* Tempo até a próxima troca. Responde "vai mudar agora?" ANTES de a pessoa
   estender a mão para o botão de ação do slide. */
.u-poster-progress {
  margin-left: auto;
  width: 120px;
  height: 3px;
  background: rgba(238, 244, 243, .28);
  display: block;
  flex: none;
  overflow: hidden;
}
.u-poster-progress i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--u-bg);
}
.u-poster-progress.is-correndo i { width: 100%; transition: width linear; }
/* Pausado (hover/foco/aba escondida): a barra congela onde está em vez de
   sumir — some seria "acabou", e o que aconteceu foi "esperando você". */
.u-poster-wrap.is-pausado .u-poster-progress i { transition: none; }

@media (max-width: 560px) {
  .u-app .qr-camera-overlay { padding: 8px; align-items: flex-start; }
  .u-app .qr-camera-modal {
    max-height: calc(100vh - 16px);
    max-height: calc(100dvh - 16px);
  }
  .u-app .qr-camera-body { padding: 12px; }
  .u-app .qr-camera-area { min-height: min(220px, 44vh); }
  .u-app .qr-camera-actions { flex-direction: column; }
  .u-app .qr-camera-actions label { width: 100%; }
  .u-app .u-nct-unit { min-width: 0; max-width: 100%; padding: 12px; }
  .u-app .u-nct-unit-grid { grid-template-columns: minmax(0, 1fr); }
  .u-app .u-nct-camera { width: 100%; white-space: normal; }
  .u-app .u-nct-def-field { grid-column: 1; }
  .u-poster-progress { display: none; }  /* sem largura para dizer isso */
}

/* Quem pediu menos movimento não recebe rotação nenhuma — os controles
   continuam, então a informação segue alcançável, só não se move sozinha.
   O JS lê a mesma media query e desliga o temporizador. */
@media (prefers-reduced-motion: reduce) {
  .u-poster-slide { transition: none; }
  .u-poster-progress { display: none; }
}

/* Legenda do semáforo. */
.u-legend { display: flex; align-items: center; gap: 18px; font-size: 11px; color: var(--u-ink-3); flex-wrap: wrap; }
.u-legend > span { display: flex; align-items: center; gap: 6px; }
.u-legend i { width: 10px; height: 10px; display: block; background: var(--u-tone, var(--u-ink)); }

/* ============================================================
   14b. Peças que a migração provou serem gerais

   Tudo aqui nasceu repetido: apareceu como `style=""` inline em três ou mais
   telas durante a portagem. Repetição em três telas não é exceção, é uma peça
   do sistema que faltava — subiu para cá.
   ============================================================ */

/* Selo de tom em contexto compacto (dentro de um bloco, ao lado de um título),
   onde o .u-tag de 22px de margem e 8/14 de padding pesa demais. */
.u-tag-sm {
  margin: 0;
  padding: 3px 8px;
  font-size: 10px;
}

/* Barra de filtros: auditoria, lotes, materiais e usuários têm a mesma.
   `align-items: flex-end` porque os campos têm rótulo em cima e o botão não —
   sem isso o botão flutua na altura do rótulo. */
.u-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  align-items: flex-end;
}

/* Campo de FILTRO ≠ campo de POSTO. Os 52px do .u-control são a medida do dedo
   com luva no chão de fábrica; numa barra de cinco filtros no desktop viram
   peso morto. 44px continua acima do mínimo de alvo de toque. */
.u-control-sm,
.u-app input.u-control-sm,
.u-app select.u-control-sm {
  min-height: 44px;
  font-size: 14px;
}

/* Blocos que carregam formulário precisam de mais trilha que os de texto. */
.u-blocks-wide { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }

/* Aviso/erro em BLOCO. O .u-tag resolve selo de uma palavra; uma frase inteira
   em uppercase com letter-spacing vira grito e fica ilegível. */
.u-notice {
  padding: 14px 18px;
  border-left: 6px solid var(--u-tone, var(--u-ink));
  background: color-mix(in srgb, var(--u-tone, var(--u-ink)) 8%, transparent);
  font-size: 14px;
  line-height: 1.5;
  color: var(--u-ink);
}

/* Lista simples de linhas com valor à direita (ex.: #mfgByEquip). Não é fila
   (não há urgência nem ordem de ação) e não é tabela (uma coluna só de dados). */
.u-rowlist { display: flex; flex-direction: column; border-top: 1px solid var(--u-rule); }
.u-rowlist-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 14px 0;
  border-bottom: 1px solid var(--u-rule);
}
.u-rowlist-sub { font-size: 12px; color: var(--u-ink-3); margin-top: 3px; }

/* Valor de etapa que é PALAVRA e não número: "Acumulando" em 26px estoura a
   célula de 150px da grade .u-steps. */
.u-step-value-word { font-size: 18px; line-height: 1.2; }

/* ============================================================
   15. Ponte com o vocabulário legado (`g-`)

   O `static/app.js` INJETA markup com as classes do styles.css — `.g-pill`,
   `.g-kpi`, `.g-alert`, `.g-right`, `.g-num`, `.g-mono` — e o styles.css é
   carregado pelo base.html em toda tela. Reescrever esses geradores junto com
   o front-end seria mudar duas coisas de uma vez; enquanto isso não acontece,
   uma tela portada precisa que o fragmento vindo do JS não destoe.

   Esta seção é ANDAIME e tem prazo: quando o último gerador do app.js falar
   `u-`, ela sai inteira. Não construa nada novo em cima dela.
   ============================================================ */

/* -- selos de tom: o app.js troca `g-pill-*` por classList em #testYieldTag,
      #testPendTag, #testDivTag. Antes o template dava `badge badge-success`
      (app.css) e o JS somava `g-pill-success` (styles.css): duas famílias que
      não se conheciam, e o selo ficava verde mesmo com yield crítico. -- */
.u-tag.g-pill-success { background: var(--u-ok-fill); }
.u-tag.g-pill-warn    { background: var(--u-warn-fill); }
.u-tag.g-pill-danger  { background: var(--u-crit-fill); }
.u-tag.g-pill-neutral { background: var(--u-ink-3); }

/* -- utilitários de célula que o JS emite dentro da .u-table -- */
.u-table .g-right { text-align: right; }
.u-table .g-num,
.u-table .g-mono { font-variant-numeric: tabular-nums; }

/* -- o seletor de período (_period_picker.html) na linguagem nova: uma
      moldura, divisores internos, canto reto -- */
.u-app .g-period {
  display: inline-flex;
  flex-wrap: wrap;
  background: transparent;
  border: 2px solid var(--u-ink);
  border-radius: 0;
  padding: 0;
  gap: 0;
}
.u-app .g-period-btn {
  min-height: 40px;
  padding: 0 16px;
  display: inline-flex;
  align-items: center;
  border: 0;
  border-left: 2px solid var(--u-ink);
  border-radius: 0;
  background: transparent;
  color: var(--u-ink);
  font: inherit;
  font-size: 13px;
  text-decoration: none;
  cursor: pointer;
}
.u-app .g-period-btn:first-child { border-left: 0; }
.u-app .g-period-btn:hover { background: color-mix(in srgb, var(--u-ink) 8%, transparent); }
.u-app .g-period-btn.active {
  background: var(--u-ink);
  color: var(--u-bg);
  font-weight: 600;
}
.u-app .g-period-range { margin-top: 12px; display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; }
.u-app .g-period-range.hidden { display: none; }
.u-app .g-period-range-label { font-size: 12px; color: var(--u-ink-3); display: flex; flex-direction: column; gap: 6px; }
.u-app .g-period-range .g-input {
  min-height: 40px;
  padding: 0 10px;
  border: 2px solid var(--u-ink);
  border-radius: 0;
  background: var(--u-bg);
  color: var(--u-ink);
  font: inherit;
}
.u-app .g-period-range .g-btn { border-radius: 0; }

/* -- cartões e alertas injetados (#testByOrigem, #testReasons): tiram o raio e
      a sombra, que são o que mais destoa do resto da página -- */
.u-app .g-kpi,
.u-app .g-alert,
.u-app .g-empty,
.u-app .g-pill {
  border-radius: 0;
  box-shadow: none;
}
.u-app .g-kpi { background: var(--u-surface); border: 2px solid var(--u-ink); }
.u-app .g-alerts { display: flex; flex-direction: column; }
.u-app .g-alert { background: transparent; border: 0; border-bottom: 1px solid var(--u-rule); }

/* Estado vazio: no design nada flutua. O `.g-empty` do styles.css vinha como
   cartão centralizado, com fundo, borda tracejada e ícone — três coisas que o
   resto da página não tem. Vira texto alinhado à esquerda, como o resto. */
.u-app .g-empty {
  display: block;
  padding: 24px 0 8px;
  background: transparent;
  border: 0;
  text-align: left;
  color: var(--u-ink-3);
}
.u-app .g-empty-icon { display: none; }
.u-app .g-empty-title { font-size: 17px; font-weight: 600; color: var(--u-ink); }
.u-app .g-empty-desc { font-size: 13px; margin-top: 6px; }

/* Pílulas de origem do lote: eram azul/âmbar/roxo, de outra identidade.
   Origem não é status — por isso ficam em neutros e no teal, e não no
   semáforo: um lote RMA não é "um problema", é outra procedência. */
.u-app .g-pill-origem-novo { background: var(--u-track);  color: var(--u-teal-texto); }
.u-app .g-pill-origem-rma  { background: var(--u-rule);   color: var(--u-ink-2); }
.u-app .g-pill-origem-ret  { background: var(--u-rule);   color: var(--u-ink-2); }
.u-app .g-pill-origem-rtnc { background: var(--u-ink);    color: var(--u-bg); }

/* ============================================================
   16. Responsivo

   O rail deixa de ser lateral e vira uma faixa em cima, com a navegação em
   linha e rolagem horizontal. Os títulos de grupo somem — em linha eles
   custariam mais largura do que informam.
   ============================================================ */

@media (max-width: 880px) {
  .u-rail {
    position: static;
    width: auto;
    height: auto;
    gap: 0;
    padding: 0;
    overflow: visible;
  }
  .u-rail ~ main,
  .u-rail ~ .u-main { margin-left: 0; }
  body:has(> .u-rail) .g-banner-global { margin-left: 0; }

  .u-rail-top { padding: 14px 20px; }
  .u-rail .nav {
    flex-direction: row;
    gap: 0;
    overflow-x: auto;
    border-top: 1px solid var(--u-rail-linha);
  }
  .u-nav-group { flex-direction: row; }
  .u-nav-title { display: none; }
  .u-nav-item {
    border-left: 0;
    border-bottom: 3px solid transparent;
    white-space: nowrap;
  }
  .u-rail .u-nav-item[aria-current="page"] {
    border-left-color: transparent;
    border-bottom-color: var(--u-teal);
  }
  .u-nav-mark { margin-left: 0; }
  .u-rail-user { margin-top: 0; padding: 12px 20px; }

  /* Padding lateral das seções: 44px -> 20px */
  :root { --u-pad-x: 20px; }

  .u-hero,
  .u-login { grid-template-columns: 1fr; row-gap: 28px; }
  .u-aside { border-left: 0; padding-left: 0; }
  .u-login-aside { display: none; }

  .u-bar-row { grid-template-columns: minmax(0, 1fr) 64px; }
  .u-bar-row .u-bar-label { grid-column: 1 / -1; }

  .u-queue-row { flex-wrap: wrap; gap: 12px 20px; }
  .u-queue-text { min-width: 0; }

  .u-step { border-right: 0; }
}

@media (max-width: 560px) {
  .u-hero-value { margin-top: 12px; }
  .u-queue-value { width: auto; min-width: 64px; font-size: 28px; }
}

@media print {
  .u-rail { display: none; }
  .u-rail ~ main,
  .u-rail ~ .u-main { margin-left: 0; }
}

/* Minhas áreas: seleção por URL/aba, independente do perfil principal. */
.u-area-tabs { display:flex; flex-wrap:wrap; gap:8px; margin:16px 0; }
.u-area-tabs a { display:block; padding:10px 14px; border:1px solid var(--u-rule); border-radius:0; color:inherit; text-decoration:none; font-size:14px; }
.u-area-tabs a:hover, .u-area-tabs a[aria-current="page"] { background:var(--u-ink, #172331); color:white; }
.u-area-tabs a:focus-visible { outline:3px solid var(--u-teal-campo); outline-offset:3px; }
.u-area-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr)); gap:18px; margin:24px 0; }
.u-area-card { padding:22px; border:1px solid var(--u-rule); border-top:2px solid var(--u-ink); border-radius:0; min-width:0; }
.u-area-actions { display:flex; flex-wrap:wrap; gap:10px; margin-top:16px; }
.u-area-actions .u-btn { white-space:normal; text-align:left; }
