/* ColetorWeb — identidade visual do e-Millennium.
   ============================================================================

   Os valores abaixo NÃO são preferência: são os tokens do portal, lidos de
   `C:\wts\files\web-apps\main.*.css`, onde 27 variáveis derivam de DOIS
   números — `--primary-color-hue` e `--secondary-color-hue`. Trocar o hue
   re-tematiza o ERP inteiro; hex hard-coded congelaria o roxo de fábrica e a
   tela do coletor ficaria roxa quando o cliente pedisse a identidade dele.

   Por que aqui existe `:root`, se o kit `mln-x-` proíbe:
   a regra do kit existe porque a tela `views-html` vive DENTRO do documento do
   portal — declarar global vazaria para as outras abas. Este PWA é documento
   próprio, então `:root` é o lugar certo. O que NÃO muda é a origem dos
   valores: o hue é o mesmo, e trocá-lo aqui acompanha o ERP.

   Medidos do nativo (não escolhidos): raio 5px (`.mln-button`), densidade 30px
   (`.dialog-window-title`), tipografia relativa em % (o portal usa 120%/110%),
   e as três cores de status idênticas às que `browser.notify()` pinta —
   divergir criaria duas linguagens de "sucesso" no mesmo produto.            */

:root {
  --primary-color-hue: 280;
  --secondary-color-hue: 25;

  /* espelho dos tokens do portal */
  --primary-color: hsl(var(--primary-color-hue), 50%, 50%);
  --accent-color: hsl(var(--primary-color-hue), 97%, 62%);
  --accent-foreground: hsl(var(--primary-color-hue), 36%, 95%);
  --command-color: hsl(var(--primary-color-hue) 30% 30%);
  --command-foreground: hsl(var(--primary-color-hue), 36%, 95%);
  --navbar-color: hsl(var(--primary-color-hue), 41%, 39%);
  --navbar-foreground: var(--command-foreground);
  --text-color: hsl(var(--primary-color-hue), 10%, 25%);
  /* O portal usa 50% de lightness aqui. Num galpão, com texto a 85% do corpo,
     isso dá 4,19:1 contra a superfície — abaixo do mínimo de 4,5:1 para texto
     pequeno. 46% resolve (4,82:1) sem sair do hue do produto: é ajuste de
     legibilidade, não outra identidade. */
  --text-color-dimmed: hsl(var(--primary-color-hue), 8%, 46%);
  --tool-background: hsl(var(--primary-color-hue), 36%, 95%);
  --control-border: hsl(var(--primary-color-hue), 36%, 95%);
  --button-border: hsl(var(--primary-color-hue), 12%, 60%);
  --required-field: hsl(var(--primary-color-hue), 97%, 34%);

  /* superfícies derivadas do mesmo hue, para não introduzir cinza neutro */
  --superficie: hsl(var(--primary-color-hue), 20%, 99%);
  --superficie-2: hsl(var(--primary-color-hue), 30%, 97%);
  --traco: hsl(var(--primary-color-hue), 20%, 88%);

  /* status: os valores que o `notify()` do produto usa */
  --status-ok: #48955a;
  --status-erro: #df4e4e;
  --status-aviso: #c08d00;

  /* Tintas dos avisos em rgba literal, e nao `hsl(from ...)`.
     A sintaxe de cor relativa so' existe em Chrome 111+/Safari 16.4+, e o
     WebView de coletor Android costuma ser bem mais velho que isso — la' a
     regra inteira e' descartada e o aviso perde o fundo, ficando texto solto. */
  --status-ok-fundo: rgba(72, 149, 90, 0.12);
  --status-erro-fundo: rgba(223, 78, 78, 0.12);
  --status-erro-tinta: #8e2f2f;
  --status-aviso-fundo: rgba(192, 141, 0, 0.12);

  /* Token do portal que faltava aqui: sem ele o `var()` caia sempre no
     fallback, que tambem usava `hsl(from ...)` — ou seja, no coletor antigo o
     campo focado ficava sem anel nenhum. */
  --focus-border: inset 0 0 0 2px hsla(var(--primary-color-hue), 97%, 62%, 0.42);

  --raio: 5px;
  --densidade: 30px;

  /* 44px e' o alvo minimo de toque. NAO contradiz a densidade 30px medida no
     portal: aquela e' para desktop com mouse; aqui o dedo esta' de luva. */
  --alvo-toque: 44px;

  /* escala relativa, como o portal (120% / 110% / 130%) */
  --fs-pequeno: 85%;
  --fs-normal: 100%;
  --fs-titulo: 110%;
  --fs-destaque: 120%;
}

* { box-sizing: border-box; }

/* ☠️ `[hidden]` só existe na folha do NAVEGADOR, e qualquer regra de AUTOR que
   declare `display` a vence — origem autor ganha de origem UA, independente de
   especificidade. Como aqui várias classes declaram `display: flex`, esconder
   por `hidden` virava inerte e o elemento continuava na tela. */
[hidden] { display: none !important; }

/* ============================================================================
   Sem rolagem de página: a tela do coletor é uma janela fixa.
   O que cresce é a LISTA, dentro da própria caixa. Se a página rolasse, cada
   bipe empurraria o conteúdo e o operador perderia o campo de leitura de vista.
   ========================================================================== */
html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  overscroll-behavior: none;
}

body {
  background: var(--tool-background);
  color: var(--text-color);
  font: var(--fs-normal)/1.45 system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-text-size-adjust: 100%;
  display: flex;
  flex-direction: column;
}

/* ---------------------------------------------------------------- cabeçalho */

.topo {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 0.35rem;
  min-height: var(--densidade);
  padding: 0.5rem 0.9rem;
  background: var(--navbar-color);
  color: var(--navbar-foreground);
}
.topo strong { font-size: var(--fs-titulo); }
.versao { font-size: 68%; opacity: 0.72; align-self: flex-start; margin-top: 0.15rem; }
/* empurra o prefixo para a ponta direita da faixa */
.topo .prefixo { margin-left: auto; }
.topo .miudo { color: hsl(var(--primary-color-hue), 30%, 82%); }

/* O prefixo do aparelho é o que o operador precisa reconhecer de relance: são
   as duas primeiras posições de todo documento que ele criar. O identificador
   completo e o espaço usado não servem em campo — foram para Catálogo. */
.prefixo {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.6rem; height: 2.1rem;
  padding: 0 0.5rem;
  background: var(--command-foreground);
  color: var(--navbar-color);
  border-radius: var(--raio);
  font-family: ui-monospace, Consolas, monospace;
  font-size: 135%;
  font-weight: 700;
  letter-spacing: 0.06em;
}

/* --------------------------------------------------------------------- abas */

.abas {
  flex: 0 0 auto;
  display: flex;
  background: var(--command-color);
  padding: 0 0.35rem;
  gap: 0.15rem;
}

.abas button {
  flex: 1;
  min-height: var(--alvo-toque);
  padding: 0.5rem 0.4rem;
  background: transparent;
  color: var(--command-foreground);
  border: 0;
  border-bottom: 3px solid transparent;
  border-radius: 0;
  font: inherit;
  font-size: var(--fs-pequeno);
  cursor: pointer;
  opacity: 0.72;
}
.abas button[aria-selected="true"] {
  opacity: 1;
  border-bottom-color: var(--accent-color);
  font-weight: 600;
}
/* ☠️ A regra global `button:hover { background: var(--superficie-2) }` pintava
   a aba de claro, e como o texto da aba é claro, ela SUMIA sob o cursor —
   inclusive a selecionada. O hover da aba tem que clarear a barra, não trocá-la
   por uma superfície de conteúdo. */
.abas button:hover:not(:disabled) {
  background: hsla(var(--primary-color-hue), 60%, 90%, 0.14);
  color: var(--command-foreground);
}
.abas button[aria-selected="true"]:hover { background: hsla(var(--primary-color-hue), 60%, 90%, 0.2); }
.abas button:focus-visible { outline: 2px solid var(--accent-color); outline-offset: -3px; }

/* ------------------------------------------------------------------- painel */

.painel {
  flex: 1 1 auto;
  min-height: 0;              /* deixa o filho rolar em vez de esticar o pai */
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  padding: 0.7rem;
  overflow: hidden;
}

/* A caixa que ROLA é esta, e só ela.
   O `min-height` não é folga estética: sem ele, numa tela baixa (coletor em
   paisagem, 640x380) o flex espremia esta área até ZERO — o operador via o
   campo de leitura e os totais, e nenhuma linha da contagem. Medido. */
.rolavel {
  flex: 1 1 auto;
  min-height: 4.5rem;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

/* -------------------------------------------------------------------- carta */

.carta {
  flex: 0 0 auto;
  background: var(--superficie);
  border: 1px solid var(--traco);
  border-radius: var(--raio);
  padding: 0.7rem 0.8rem;
}
.carta h2 {
  margin: 0 0 0.5rem;
  font-size: var(--fs-pequeno);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-color-dimmed);
  font-weight: 600;
}

.miudo { color: var(--text-color-dimmed); font-size: var(--fs-pequeno); }
.dado { display: flex; justify-content: space-between; align-items: baseline; gap: 0.8rem; padding: 0.3rem 0; border-bottom: 1px solid var(--traco); }
.dado:last-of-type { border-bottom: 0; }
.dado code, .dado span:last-child { overflow-wrap: anywhere; text-align: right; }
.rotulo { color: var(--text-color-dimmed); font-size: var(--fs-pequeno); text-transform: uppercase; letter-spacing: 0.06em; }
code { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; }

/* ---------------------------------------------------------------- controles */

label { display: block; font-size: var(--fs-pequeno); color: var(--text-color-dimmed); margin-bottom: 0.3rem; }

input, select {
  width: 100%;
  min-height: var(--densidade);
  padding: 0.6rem;
  background: var(--superficie);
  color: var(--text-color);
  border: 1px solid var(--button-border);
  border-radius: var(--raio);
  font: inherit;
  font-size: var(--fs-titulo);
}
input:focus, select:focus {
  outline: 0;
  border-color: var(--accent-color);
  box-shadow: var(--focus-border);
}

/* O campo de leitura é o centro da tela; a borda de campo obrigatório é a
   mesma que o portal usa para exigir preenchimento. */
#campo-leitura {
  font-family: ui-monospace, Consolas, monospace;
  font-size: var(--fs-destaque);
  letter-spacing: 0.04em;
  border-color: var(--required-field);
  border-width: 2px;
}
#campo-leitura:disabled { border-color: var(--traco); background: var(--superficie-2); opacity: 0.7; }

button {
  min-height: var(--alvo-toque);
  padding: 0.5rem 0.9rem;
  background: var(--superficie);
  color: var(--text-color);
  border: 1px solid var(--button-border);
  border-radius: var(--raio);
  font: inherit;
  cursor: pointer;
}
button:hover:not(:disabled) { background: var(--superficie-2); }
button:disabled { opacity: 0.45; cursor: not-allowed; }
button:focus-visible { outline: 2px solid var(--accent-color); outline-offset: 1px; }

/* Anatomia dos botões, copiada do nativo (`126.*.css` do portal):
     .mln-button-primary → PREENCHIDO com o acento, sem borda
     .mln-button-accent  → CONTORNO, fundo claro e texto no acento
   A versão anterior invertia os dois.

   ⚠️ Faixa B: o par exato do nativo (`--accent-foreground` sobre
   `--accent-color`) rende 3,45:1 — abaixo do mínimo para texto. A decisão
   desta casa para Faixa B é CORRIGIR preservando a estrutura, como já foi
   feito com o `.panel-heading` azul. Então a anatomia é a do produto e só a
   tinta muda: 4,69:1, ainda dentro do hue. */
/* Botão principal como o ERP faz: roxo do produto com texto BRANCO.
   O lilás vivo (`--accent-color`) com tinta escura, que estava aqui, não
   aparece em botão nenhum do Millennium — lá o acento é realce de estado
   (aba ativa, foco), não fundo de botão. Contraste 6,8:1. */
.primario {
  background: var(--navbar-color);
  border: 1px solid var(--navbar-color);
  color: var(--command-foreground);
  font-weight: 600;
}
.primario:hover:not(:disabled) {
  background: var(--command-color);
  border-color: var(--command-color);
}

.contorno {
  background: var(--superficie);
  border: 1px solid var(--navbar-color);
  color: var(--navbar-color);
  font-weight: 600;
}
.contorno:hover:not(:disabled) { background: var(--superficie-2); }
.largo { width: 100%; }
.discreto { background: transparent; border-color: transparent; color: var(--text-color-dimmed); }
.discreto:hover:not(:disabled) { background: var(--superficie-2); }

.acoes { display: flex; gap: 0.5rem; }

/* ------------------------------------------------------------------- avisos */

/* Um sinal de status por vez.
   A barra de aviso encosta na barra de abas, e a aba ativa já tem o traço
   lilás embaixo dela. Somar a esse traço uma faixa colorida vertical punha
   dois riscos de cores diferentes lado a lado, parecendo enfeite em vez de
   informação. O fundo tingido e a cor do texto já dizem se a leitura passou ou
   foi recusada — e dizem no elemento inteiro, não numa listra de 4px. */
.aviso {
  flex: 0 0 auto;
  padding: 0.5rem 0.9rem;
  font-size: var(--fs-pequeno);
  background: var(--superficie-2);
  border-bottom: 1px solid var(--traco);
  color: var(--text-color);
}
.aviso.ok {
  background: var(--status-ok-fundo);
  border-bottom-color: var(--status-ok);
  color: #2c5c38;
}
.aviso.erro {
  background: var(--status-erro-fundo);
  border-bottom-color: var(--status-erro);
  color: var(--status-erro-tinta);
}

.alerta {
  flex: 0 0 auto;
  margin: 0.5rem 0.7rem 0;
  padding: 0.6rem 0.7rem;
  border-radius: var(--raio);
  border: 1px solid var(--status-aviso);
  background: var(--status-aviso-fundo);
  font-size: var(--fs-pequeno);
}

/* ------------------------------------------------------------------- listas */

.lista { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.3rem; }
.lista li {
  display: flex; justify-content: space-between; align-items: center; gap: 0.7rem;
  padding: 0.5rem 0.6rem;
  background: var(--superficie);
  border: 1px solid var(--traco);
  border-radius: var(--raio);
}
/* ☠️ Sem `min-width: 0` o filho flex NÃO encolhe abaixo do conteúdo — o texto
   empurra a linha e o cartão vaza dos dois lados, cortando o começo do
   documento e o botão da direita. O padrão do flex é `min-width: auto`. */
.lista li > div { min-width: 0; flex: 1 1 auto; overflow-wrap: anywhere; }
.lista li > button { flex: 0 0 auto; }
.lista li.vazio { color: var(--text-color-dimmed); background: transparent; border-style: dashed; justify-content: center; }
/* Cor/estampa/tamanho e o código lido são o que o operador confere contra a
   prateleira — informação, não legenda. Vão na cor de texto cheia. */
.lista li .miudo { color: var(--text-color); }
.lista li.removida { opacity: 0.45; }
.lista li.removida strong, .lista li.removida code { text-decoration: line-through; }

/* Linha de detalhe do SKU: informação de conferência, não legenda. */
.detalhe { font-size: var(--fs-pequeno); color: var(--text-color); display: flex; align-items: baseline; gap: 0.4rem; flex-wrap: wrap; }

/* O TAMANHO é o campo que mais erra na conferência: dois SKUs do mesmo produto
   e da mesma cor diferem só por ele. Ganha peso de etiqueta, não de texto. */
.tam {
  display: inline-block;
  min-width: 2.1rem;
  padding: 0.05rem 0.35rem;
  background: var(--navbar-color);
  color: var(--command-foreground);
  border-radius: var(--raio);
  font-family: ui-monospace, Consolas, monospace;
  font-weight: 700;
  font-size: 105%;
  text-align: center;
  letter-spacing: 0.03em;
}

.quantidade {
  font-size: var(--fs-destaque);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--command-color);
  min-width: 2.2rem;
  text-align: right;
}

/* ------------------------------------------------------------------- totais */

.totais { display: flex; gap: 0.5rem; }
.totais > div {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; gap: 0.05rem;
  padding: 0.45rem;
  background: var(--superficie);
  border: 1px solid var(--traco);
  border-radius: var(--raio);
}
.numero-grande { font-size: 200%; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.05; color: var(--command-color); }

/* --------------------------------------------------- cabeçalho do documento */

.doc-cabecalho {
  display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
  flex: 0 0 auto;
  padding: 0.5rem 0.7rem;
  background: var(--superficie);
  border: 1px solid var(--traco);
  border-radius: var(--raio);
}
/* Ditado por rádio entre o galpão e o escritório: precisa de espaçamento. */
.numero { font-size: var(--fs-destaque); letter-spacing: 0.09em; color: var(--command-color); font-weight: 700; }

.etiqueta {
  white-space: nowrap;
  font-size: 72%;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 0.1rem 0.4rem;
  border-radius: var(--raio);
  border: 1px solid currentColor;
}
.etiqueta.rascunho { color: var(--command-color); }
.etiqueta.concluido { color: var(--status-ok); }
.etiqueta.enviado { color: var(--text-color-dimmed); }

/* --------------------------------------------------------------- sub-abas */

.subabas { display: flex; gap: 0.3rem; flex: 0 0 auto; }
.subabas button {
  flex: 1;
  min-height: var(--alvo-toque);
  padding: 0.35rem;
  font-size: var(--fs-pequeno);
  background: var(--superficie-2);
  border-color: var(--traco);
}
.subabas button[aria-selected="true"] {
  background: var(--superficie);
  border-color: var(--command-color);
  color: var(--command-color);
  font-weight: 600;
}

/* ---------------------------------------------------------------- confirmar */

/* ☠️ A confirmação NÃO pode entrar na coluna de altura fixa.
   Todos os blocos acima da lista são `flex: 0 0 auto`, então numa tela baixa a
   soma estoura, o `.painel` (overflow:hidden) corta o excedente, e o botão
   "Confirmar" fica fora da tela — inalcançável, sem barra de rolagem para
   chegar nele. Sobreposição resolve, e é o comportamento do `browser.msgBox`
   do portal, que é o que ela substitui. */
.confirmacao {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 20;
  margin: 0.7rem;
  border-color: var(--status-aviso);
  border-width: 2px;
  box-shadow: 0 8px 32px hsla(var(--primary-color-hue), 40%, 10%, 0.35);
  max-height: calc(100dvh - 1.4rem);
  overflow-y: auto;
}
.confirmacao .acoes { margin-top: 0.6rem; }
.confirmacao .acoes button { flex: 1; }

/* Fundo do vídeo limitado: sem teto ele empurra a lista para fora da coluna. */
video { max-height: 30vh; object-fit: cover; }

video { width: 100%; margin-top: 0.5rem; border-radius: var(--raio); background: #000; }

@media (prefers-reduced-motion: reduce) { * { transition: none !important; } }

/* ============================================================================
   Tela baixa — coletor em paisagem, ou teclado virtual aberto no celular.
   Compacta o que é moldura para preservar o que é trabalho: a lista da
   contagem. O rótulo do campo sai porque o placeholder diz a mesma coisa.
   ========================================================================== */
@media (max-height: 560px) {
  .painel { gap: 0.4rem; padding: 0.45rem; }
  .carta { padding: 0.45rem 0.55rem; }
  .doc-cabecalho { padding: 0.3rem 0.5rem; }
  .topo { padding: 0.3rem 0.7rem; }
  .topo .miudo { display: none; }
  .abas button { min-height: 2.5rem; }
  .subabas button { min-height: 2.5rem; }

  label[for="campo-leitura"] { display: none; }

  /* Totais deitam na horizontal: mesma informação, um terço da altura. */
  .totais > div { flex-direction: row; align-items: baseline; gap: 0.35rem; padding: 0.25rem 0.5rem; }
  .numero-grande { font-size: 145%; }

  .aviso { padding: 0.35rem 0.7rem; }
}

/* ---------------------------------------------------------------------------
   Estado do backup no cabecalho do documento.

   Cores literais (rgba/hsla), nao `hsl(from ...)`: o WebView do coletor
   Android costuma ser velho demais e descartaria a regra inteira, deixando o
   indicador sem fundo justamente quando ele avisa que a contagem NAO subiu.
   --------------------------------------------------------------------------- */
.envio {
  font-size: 78%;
  padding: 0.1rem 0.45rem;
  border-radius: var(--border-radius, 5px);
  white-space: nowrap;
  font-weight: 600;
}
.envio.em-dia   { background: rgba(72, 149, 90, 0.14);  color: #2f6b3d; }
.envio.pendente { background: rgba(192, 141, 0, 0.16);  color: #8a6500; }
.envio.enviando { background: rgba(192, 141, 0, 0.10);  color: #8a6500; }
.envio.sem-rede,
.envio.recusado { background: rgba(223, 78, 78, 0.14);  color: #a83232; }

@media (prefers-color-scheme: dark) {
  .envio.em-dia   { color: #8fd6a1; }
  .envio.pendente,
  .envio.enviando { color: #e5c05c; }
  .envio.sem-rede,
  .envio.recusado { color: #f0938f; }
}

/* ---------------------------------------------------------------------------
   Tela de acesso.

   Ela cobre a janela inteira, entao ao contrario das outras ela PODE rolar:
   com o teclado virtual aberto num coletor de tela curta, o formulario de
   criar acesso nao cabe, e travar a rolagem aqui esconderia o botao de
   confirmar embaixo do teclado -- exatamente o campo que o operador precisa
   alcancar.
   --------------------------------------------------------------------------- */
.acesso {
  position: fixed;
  inset: 0;
  z-index: 30;
  background: var(--tool-background, #f4eef7);
  overflow-y: auto;
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.acesso .marca {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.2rem 0 0.5rem;
}
.acesso .marca strong { font-size: 118%; color: var(--navbar-color); }
.acesso .marca .miudo { margin-left: auto; }

/* Alvo de toque grande: dedo de luva, e aqui o erro custa uma senha digitada
   de novo com o teclado virtual por cima. */
.acesso input,
.acesso select {
  min-height: var(--alvo-toque);
  font-size: 105%;
}
.acesso button { min-height: var(--alvo-toque); }

/* Ritmo vertical do formulario.

   Medido: do campo "Usuario" ao campo "Senha" ha' 25px, porque no meio cabe o
   rotulo (20px de texto + 5px de respiro). Entre o campo de senha e o botao
   nao havia rotulo nenhum -- e portanto nenhum espaco: o botao encostava no
   campo. Aqui o vao entre grupos passa a ser explicito e igual nos dois casos,
   em vez de ser um efeito colateral da altura do rotulo. */
.acesso .acoes { margin-top: 1.5rem; }

/* O bloco de vinculo aparece depois de "Buscar funcionarios": mesmo respiro,
   senao a lista brota grudada no botao que a trouxe. */
.acesso #ac-vinculo { margin-top: 1.5rem; }

.acesso #acesso-nota { margin-top: auto; padding-top: 0.6rem; }

/* O aviso proprio do painel ocupa a largura da carta e nao empurra o resto
   quando aparece: a altura dele ja' esta reservada pelo gap da coluna. */
.acesso #acesso-aviso { margin: 0; }

/* A faixa de sessao vencida traz acao junto: dizer que venceu sem oferecer o
   caminho de volta so' informa o problema. */
#aviso-sessao .acoes { margin-top: 0.4rem; }

/* ---------------------------------------------------------------------------
   Confirmação da leitura
   ---------------------------------------------------------------------------
   ☠️ O operador está de mãos ocupadas, olhando a prateleira, e volta o olho
   para a tela por uma fração de segundo. Uma linha de texto fina na barra de
   avisos não é vista — foi o que o piloto mostrou. Duas coisas resolvem: o
   número da contagem PISCA, e o produto lido aparece em tamanho de corredor.
   --------------------------------------------------------------------------- */

.totais > div {
  /* A cor entra e sai; sem transição a piscada vira "flash" agressivo. */
  transition: background-color 120ms linear, border-color 120ms linear;
}

/* ☠️ A cor do TEXTO entra no keyframe, não numa regra à parte. Fora dele, a
   regra vale durante toda a animação: na metade apagada o número ficava claro
   sobre fundo claro — invisível justamente no instante em que o operador olha.
   Por isso os filhos herdam, e quem anima é o cartão. */
@keyframes piscar-contagem {
  0%, 100% {
    background: var(--superficie);
    border-color: var(--traco);
    color: var(--command-color);
  }
  50% {
    background: var(--primary-color);
    border-color: var(--primary-color);
    color: var(--accent-foreground);
  }
}

/* 50/50 e não 25/75: com a fase acesa dominando, o cartão parece apenas
   "ligado" e a piscada não é percebida como piscada.
   Duas repetições: uma passa despercebida, três atrasam o próximo bipe. */
.totais > div { color: var(--command-color); }
.totais > div.piscando { animation: piscar-contagem 260ms steps(1, end) 2; }
.totais > div.piscando .numero-grande,
.totais > div.piscando .rotulo { color: inherit; }

.ultima {
  margin-top: 0.5rem;
  padding: 0.6rem 0.75rem;
  border-radius: var(--raio);
  border: 1px solid var(--traco);
  border-left: 5px solid var(--primary-color);
  background: var(--superficie);
}

.ultima-produto {
  font-size: 125%;
  font-weight: 700;
  line-height: 1.15;
  color: var(--command-color);
  /* Descrição de produto é longa e o aparelho é estreito: quebrar é melhor que
     cortar — o operador precisa do nome inteiro para conferir a prateleira. */
  overflow-wrap: anywhere;
}

.ultima-detalhe {
  margin-top: 0.15rem;
  font-size: 95%;
  color: var(--text-color-dimmed);
  font-variant-numeric: tabular-nums;
}

.ultima.piscando {
  background: var(--primary-color);
  border-color: var(--primary-color);
}
.ultima.piscando .ultima-produto,
.ultima.piscando .ultima-detalhe { color: var(--accent-foreground); }

/* Leitura recusada: mesma posição, cor de erro — o olho já está treinado a
   procurar ali, e mudar de lugar faria a recusa passar batida. */
.ultima.recusada { border-left-color: var(--status-erro); }
.ultima.recusada .ultima-produto { color: var(--status-erro-tinta); }

@media (prefers-reduced-motion: reduce) {
  .totais > div.piscando {
    animation: none;
    background: var(--primary-color);
    border-color: var(--primary-color);
    color: var(--accent-foreground);
  }
}

/* Formulário que abre dentro de outra carta (troca de senha no Aparelho). */
.carta.interna {
  margin-top: 0.6rem;
  border-left: 4px solid var(--primary-color);
  background: var(--tool-background);
}
