/* BMR Autopeças — folha de estilo única (vitrine + admin).
 *
 * PALETA: derivada do logo do cliente. As duas cores canônicas foram extraídas
 * do arquivo, não aproximadas: vermelho #FF3131 e navy #051E3D.
 *
 * CONTRASTE — tudo abaixo foi MEDIDO (WCAG), não olhado:
 *   navy sobre branco ............ 16.67:1  OK
 *   branco sobre navy ............ 16.67:1  OK
 *   cinza-texto sobre branco ...... 7.53:1  OK
 *   vermelho-escuro sobre branco ... 5.74:1  OK
 *   branco sobre vermelho-escuro ... 5.74:1  OK
 *   branco sobre #FF3131 ........... 3.66:1  *** REPROVA ***
 *   #FF3131 como texto sobre branco  3.66:1  *** REPROVA ***
 *
 * Por isso há DUAS variáveis de vermelho, e a diferença importa:
 *   --vermelho       (#FF3131) = cor da MARCA. Só para áreas de cor (a
 *                     engrenagem do logo, faixas, fundos de selo). NUNCA
 *                     como texto sobre claro, nem como fundo de botão com
 *                     texto branco — reprova em contraste.
 *   --vermelho-acao  (#C81E1E) = cor de AÇÃO. É a que vai em botão com texto
 *                     branco e em texto vermelho. Passa com 5.74:1.
 *
 * O vermelho é acento, nunca área grande nem texto corrido: é cor de alerta e,
 * espalhada, faz o CTA perder força. A estrutura do site é navy + branco.
 */

:root {
  --vermelho: #ff3131;
  --vermelho-olho: #ff6b5e;
  --vermelho-acao: #e03131;
  --vermelho-acao-escuro: #c81e1e;
  /* ATENÇÃO — estas duas mudaram de SIGNIFICADO na migração para o tema
     escuro, e isso é deliberado.
     O CSS foi escrito para um tema claro: ~20 regras usam `--branco` como
     fundo de superfície e ~19 usam `--navy` como cor de texto. Reapontar as
     variáveis conserta todas de uma vez; caçar regra por regra deixaria
     sobras — e foi assim que o título da categoria acabou branco sobre
     branco, com contraste de 1:1.
     `--navy` agora é a cor de TEXTO sobre superfície escura.
     `--branco` agora é a SUPERFÍCIE elevada, não o papel branco. */
  --navy: #eef4fb;
  --navy-claro: #0d3157;
  --branco: #0c2138;
  /* O branco real, para quando for mesmo necessário (texto sobre vermelho). */
  --branco-puro: #ffffff;

  /* BASE ESCURA — direção "oficina séria e técnica".
     Antes a base era clara (#f7fafc) com cards brancos, e o contraste médio em
     toda parte fazia nada se destacar: a vitrine tinha a mesma cara do painel
     administrativo. Agora o fundo é denso e as superfícies sobem em degraus
     curtos, para a hierarquia vir da luz e não de borda. */
  --fundo: #071526;
  --superficie: #0c2138;
  --superficie-alta: #123048;
  --texto: #eef4fb;
  --texto-suave: #a9bdd4;
  --borda: #1d3a56;
  /* Clareada até 3:1 contra o fundo: borda de contorno de foco e de botão
     vazado é elemento de interface não-textual, e abaixo de 3:1 deixa de ser
     perceptível para quem enxerga pouco contraste. Medida, não estimada. */
  --borda-forte: #4b7aa6;
  --verde: #3ddc84;
  --ambar: #ffc048;

  /* Escala tipográfica — o que faltava. Sem degraus declarados, todo texto
     acabava no mesmo tamanho e a página ficava sem hierarquia. */
  --t-xs: .75rem;
  --t-sm: .875rem;
  --t-md: 1rem;
  --t-lg: 1.25rem;
  --t-xl: 1.75rem;
  --t-2xl: 2.5rem;
  --t-3xl: clamp(2.25rem, 5.2vw, 3.75rem);
  --t-apoio: var(--texto-suave);

  --raio: 10px;
  --sombra: 0 1px 2px rgba(0, 0, 0, .4);
  --sombra-media: 0 18px 40px -22px rgba(0, 0, 0, .85);
  --fonte: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "Consolas", "Roboto Mono", monospace;
  --largura: 1180px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--fonte);
  color: var(--texto);
  background: var(--fundo);
  line-height: 1.55;
  font-size: 16px;
}

a { color: var(--navy); }

/* --- Logo ---------------------------------------------------------------
 * O SVG usa `currentColor` no texto. O default navy mora AQUI, e não dentro
 * do arquivo: fixar `color` no elemento raiz do SVG venceria a herança e o
 * texto sumiria em fundo escuro (foi flagrado renderizando sobre o navy). */
.logo { color: var(--navy); display: block; flex: none; }
/* `height:auto` + a proporção do viewBox fazem o SVG escalar inteiro. Sem o
 * `max-width:100%` o elemento pai podia espremer a largura e cortar o texto —
 * foi o que aconteceu na primeira renderização do cabeçalho, onde sobrava só
 * a engrenagem. Flagrado por screenshot, não por inspeção do CSS. */
.logo svg, .logo img { display: block; width: 100%; max-width: 100%; height: auto; }
/* Em QUALQUER contexto de fundo escuro o texto do logo vira branco. O
 * `.admin-topo` estava faltando nesta lista, e o resultado era texto navy
 * sobre cabeçalho navy: só a engrenagem aparecia. Flagrado em screenshot —
 * o SVG media 200x75 e o fill estava "certo", então nada no DOM denunciava. */
.rodape .logo,
.cabecalho-escuro .logo,
.admin-topo .logo,
.topo .logo,
.login-tela .logo-escuro { color: var(--branco); }

/* --- Estrutura ---------------------------------------------------------- */
.container { max-width: var(--largura); margin: 0 auto; padding: 0 20px; }

/* --- Admin: barra superior ---------------------------------------------- */
.admin-topo {
  background: var(--navy);
  color: var(--branco);
  padding: 12px 0;
  box-shadow: var(--sombra);
}
.admin-topo .container { display: flex; align-items: center; gap: 24px; }
/* O viewBox é 536x162 (ficou mais largo ao afastar o texto da engrenagem para
 * dar respiro — ver logo-bmr.svg). A largura em CSS tem de acompanhar, senão o
 * SVG escala para caber na altura e o texto sai do campo visível: o cabeçalho
 * mostrava só a engrenagem. 250px dá ~75px de altura. */
.admin-topo .logo { width: 250px; }
.admin-topo nav { display: flex; gap: 4px; flex-wrap: wrap; margin-left: auto; }
.admin-topo nav a {
  color: #cfe0f5;
  text-decoration: none;
  padding: 8px 14px;
  border-radius: var(--raio);
  font-weight: 600;
  font-size: .94rem;
}
.admin-topo nav a:hover { background: var(--navy-claro); color: var(--branco); }
.admin-topo nav a.ativo { background: var(--navy-claro); color: var(--branco); }

/* --- Títulos e cabeçalho de página -------------------------------------- */
.pagina { padding: 28px 0 64px; }
.pagina-topo {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 20px;
}
h1 { font-size: 1.6rem; margin: 0 0 4px; color: var(--navy); }
h2 { font-size: 1.2rem; margin: 0 0 12px; color: var(--navy); }
.subtitulo { color: var(--texto-suave); margin: 0; font-size: .95rem; }

/* --- Cartão ------------------------------------------------------------- */
.cartao {
  background: var(--branco);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 20px;
  box-shadow: var(--sombra);
  margin-bottom: 18px;
}
.cartao > h2:first-child { margin-top: 0; }

/* --- Botões -------------------------------------------------------------
 * O botão primário usa --vermelho-acao (5.74:1 com texto branco).
 * Usar --vermelho puro aqui daria 3.66:1 e REPROVARIA. */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 18px;
  border-radius: var(--raio);
  border: 1px solid transparent;
  font-family: inherit; font-size: .95rem; font-weight: 600;
  cursor: pointer; text-decoration: none; line-height: 1.2;
}
.btn-primario { background: var(--vermelho-acao); color: var(--branco); }
.btn-primario:hover { background: var(--vermelho-acao-escuro); }
.btn-secundario { background: var(--navy); color: var(--branco); }
.btn-secundario:hover { background: var(--navy-claro); }
.btn-neutro { background: var(--branco); color: var(--navy); border-color: var(--borda); }
.btn-neutro:hover { background: var(--fundo); }
.btn-perigo { background: var(--branco); color: var(--vermelho-acao); border-color: #f3c0c0; }
.btn-perigo:hover { background: #fdf2f2; }
.btn-pequeno { padding: 6px 12px; font-size: .86rem; }
.btn:focus-visible, a:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible {
  outline: 3px solid var(--vermelho); outline-offset: 2px;
}

/* --- Formulários --------------------------------------------------------
 * Rótulo sempre visível (nunca só placeholder): placeholder some ao digitar e
 * quem preenche 20 campos perde a referência do que era cada um. */
.campo { margin-bottom: 16px; }
.campo label { display: block; font-weight: 600; margin-bottom: 5px; font-size: .92rem; }
.campo .ajuda { display: block; color: var(--texto-suave); font-size: .85rem; margin-top: 4px; }
input[type=text], input[type=email], input[type=password], input[type=number],
input[type=search], select, textarea {
  width: 100%; padding: 10px 12px;
  border: 1px solid #cbd5e0; border-radius: var(--raio);
  font-family: inherit; font-size: 1rem; background: var(--branco); color: var(--texto);
}
textarea { min-height: 110px; resize: vertical; }
.linha { display: flex; gap: 16px; flex-wrap: wrap; }
.linha > * { flex: 1 1 220px; }
.checkbox { display: flex; align-items: flex-start; gap: 10px; }
.checkbox input { width: 18px; height: 18px; margin-top: 3px; flex: none; }
.checkbox label { font-weight: 600; margin: 0; }

/* --- Tabela ------------------------------------------------------------- */
.tabela-rolagem { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; background: var(--branco); }
th, td { text-align: left; padding: 11px 12px; border-bottom: 1px solid var(--borda); }
th { background: var(--fundo); font-size: .82rem; text-transform: uppercase;
     letter-spacing: .03em; color: var(--texto-suave); white-space: nowrap; }
tbody tr:hover { background: #fafcfe; }
.codigo { font-family: ui-monospace, "Cascadia Code", Consolas, monospace; font-size: .9rem; }

/* --- Selos -------------------------------------------------------------- */
.selo {
  display: inline-block; padding: 3px 9px; border-radius: 999px;
  font-size: .78rem; font-weight: 700; white-space: nowrap;
}
.selo-ok { background: #e3f6ec; color: var(--verde); }
.selo-alerta { background: #fdf3e0; color: var(--ambar); }
.selo-off { background: #edf1f6; color: var(--texto-suave); }
.selo-consulta { background: #e8eefb; color: var(--navy); }

/* Dado de exemplo: tem de gritar que não é estoque real. */
.selo-exemplo { background: #fde8e8; color: var(--vermelho-acao); }

/* --- Avisos ------------------------------------------------------------- */
.aviso { padding: 13px 16px; border-radius: var(--raio); margin-bottom: 18px;
         border: 1px solid; font-size: .94rem; }
.aviso-erro { background: #fdf2f2; border-color: #f3c0c0; color: #8c1d1d; }
.aviso-ok { background: #e9f8f0; border-color: #a8dcc0; color: #15603a; }
.aviso-info { background: #eaf1fc; border-color: #b9cdeb; color: var(--navy); }
.aviso-exemplo { background: #fff6e8; border-color: #f0cf9a; color: #7a4e00; }

/* --- Marcador de pendência ---------------------------------------------
 * Herdado do diego-hotts. NÃO embeleze: é um aviso, tem de incomodar. */
.pend {
  display: inline-block;
  font-family: ui-monospace, Consolas, monospace;
  font-size: .82em;
  color: var(--vermelho-acao);
  background: #fdecec;
  border: 1px dashed #e8a0a0;
  border-radius: 6px;
  padding: 2px 8px;
}

/* --- Login -------------------------------------------------------------- */
.login-tela {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(160deg, var(--navy) 0%, #0a2a4d 100%); padding: 20px;
}
.login-caixa { background: var(--branco); border-radius: 14px; padding: 36px;
               width: 100%; max-width: 410px; box-shadow: var(--sombra-media); }
.login-caixa .logo { width: 275px; margin: 0 auto 22px; }

/* --- Imagens de produto -------------------------------------------------- */
.grade-imagens { display: flex; gap: 12px; flex-wrap: wrap; }
.img-item { border: 1px solid var(--borda); border-radius: var(--raio);
            padding: 8px; background: var(--branco); width: 148px; }
.img-item img { width: 100%; height: 104px; object-fit: contain; display: block; }
.img-acoes { display: flex; gap: 4px; margin-top: 8px; justify-content: center; }

/* --- Utilitários --------------------------------------------------------- */
.vazio { text-align: center; padding: 44px 20px; color: var(--texto-suave); }
.acoes { display: flex; gap: 8px; flex-wrap: wrap; }
.suave { color: var(--texto-suave); font-size: .9rem; }
.nowrap { white-space: nowrap; }
.direita { text-align: right; }
.barra-busca { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 18px; }
.barra-busca input[type=search] { flex: 1 1 260px; }
.centro { text-align: center; }
.btn-bloco { width: 100%; justify-content: center; margin-top: 8px; }
.btn-grande { padding: 14px 24px; font-size: 1.05rem; width: 100%; justify-content: center; }

/* Só para leitor de tela: rótulo que o olho não precisa mas a voz sim. */
.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* Pular navegação: invisível até receber foco pelo teclado. */
.pular {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--branco); color: var(--navy); padding: 12px 18px;
  font-weight: 700; border-radius: 0 0 var(--raio) 0;
}
.pular:focus { left: 0; }

/* ======================= VITRINE PÚBLICA ==============================
 * CONTRASTE MEDIDO (WCAG) de toda combinação abaixo — nenhuma por olho:
 *   texto principal / fundo claro ... 14.91:1   título navy / branco .. 16.67:1
 *   texto suave / branco ............. 7.53:1   hero subtítulo / navy . 11.53:1
 *   link da barra / navy ............ 12.41:1   rodapé / navy ......... 10.84:1
 *   botão primário (branco/#C81E1E) .. 5.74:1   selo disponível ....... 4.63:1
 *   selo sem estoque ................. 5.38:1   selo sob consulta ..... 9.68:1
 *   selo exemplo ..................... 4.89:1   marcador pendente ..... 5.02:1
 *   contorno de foco (não-texto) ..... 3.66:1   (mínimo 3:1)
 * O selo "disponível" (4.63:1) é o mais apertado: passa, mas não escureça o
 * fundo nem clareie o verde sem medir de novo. */

/* --- cabeçalho --- */
.topo { background: var(--navy); color: var(--branco); }
.topo-barra {
  display: flex; align-items: center; gap: 28px; padding: 16px 20px; flex-wrap: wrap;
}
.topo-barra .logo { width: 262px; }  /* acompanha o viewBox 536x162 */
.busca-topo { display: flex; gap: 8px; flex: 1 1 320px; }
.busca-topo input { flex: 1; }
.topo-fone { color: var(--branco); text-decoration: none; line-height: 1.25; }
.topo-fone strong { display: block; font-size: 1.1rem; }
.topo-fone span { font-size: .82rem; color: #c9d8ec; }
.topo-nav { background: var(--navy-claro); }
.topo-nav .container {
  display: flex; gap: 2px; overflow-x: auto; padding: 0 20px;
}
.topo-nav a {
  color: #cfe0f5; text-decoration: none; padding: 11px 15px;
  font-size: .92rem; font-weight: 600; white-space: nowrap;
}
.topo-nav a:hover { background: rgba(255, 255, 255, .1); color: var(--branco); }

/* --- hero --- */
.hero { background: linear-gradient(165deg, var(--navy) 0%, #0a2a4d 100%);
        color: var(--branco); padding: 54px 0 46px; }
.hero h1 { color: var(--branco); font-size: 2.1rem; margin: 0 0 12px; max-width: 760px; }
.hero-sub { font-size: 1.08rem; color: #c9d8ec; max-width: 680px; margin: 0 0 14px; }
.hero-prova { margin: 0 0 24px; color: var(--branco); font-size: .98rem; }
.hero-busca { display: flex; gap: 10px; flex-wrap: wrap; max-width: 620px; }
.hero-busca input { flex: 1 1 320px; padding: 13px 16px; font-size: 1.02rem; }
.hero-dica { color: #c9d8ec; font-size: .86rem; margin: 10px 0 0; }

/* A seção "faixa de serviços" NÃO mora mais aqui.
   O projeto tem duas folhas de propósito (ver comentário em base.html):
   `estilo.css` para fontes/admin, `vitrine.css` para a camada visual da
   loja. Eu tinha criado `.faixa-grade`/`.faixa-item` aqui sem saber que
   `vitrine.css` já implementa a mesma seção como `.faixa-itens`, com grid
   auto-fit, separadores finos (gap 1px + fundo) e o svg já estilizado —
   e por carregar DEPOIS no <head>, aquela versão sempre vencia a cascata
   mesmo com a minha tendo mais especificidade. Resultado: a faixa ficava
   com ~56px de altura, cortando a segunda linha de cada item — foi assim
   que a seção "sumiu" visualmente.
   home.html agora usa `.faixa-itens` (a estrutura de vitrine.css). Se
   precisar mexer no visual da faixa de novo, é lá que a regra vive. */

/* --- seções --- */
.secao { padding: 48px 0; }
.secao-clara { background: var(--branco); }
.secao-escura { background: var(--navy); color: var(--branco); }
.secao-escura h2, .secao-escura h3 { color: var(--branco); }
.secao h2 { font-size: 1.55rem; margin: 0 0 6px; }
.secao-sub { color: var(--texto-suave); margin: 0 0 24px; }
.secao-escura .secao-sub { color: #c2d2e6; }

/* --- grade de categorias (cada uma com foto e descrição curta) --- */
.grade-categorias {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(255px, 1fr)); gap: 16px;
}
@media (min-width: 900px) {
  /* Pedido: nada de card órfão sozinho na última linha (5 categorias em
     auto-fill davam 4 + 1). `--colunas` vem do template (`colunas_grade()`):
     até 6 categorias, todas numa linha; acima disso, a largura que fecha a
     última linha — 16 categorias viram 4x4. Antes era `repeat(qtd)` direto,
     que com 16 espremeria tudo numa linha de cards de 70px. */
  .grade-categorias { grid-template-columns: repeat(var(--colunas, 4), 1fr); }
}
.cat-card {
  display: block; background: var(--branco); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 20px; text-decoration: none; color: var(--texto);
  box-shadow: var(--sombra);
}
.cat-card:hover { border-color: var(--vermelho-acao); box-shadow: var(--sombra-media); }
.cat-card .cat-nome { margin: 0 0 7px; color: var(--navy); font-size: 1.08rem; }
.cat-card p { margin: 0 0 12px; color: var(--texto-suave); font-size: .9rem; }
.cat-card .cat-link { color: var(--vermelho-acao); font-weight: 700; font-size: .88rem; }

/* --- grade de veículos --- */
.grade-veiculos {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 12px;
}
.veiculo-card {
  background: var(--fundo); border: 1px solid var(--borda); border-radius: var(--raio);
  padding: 16px; text-align: center; text-decoration: none; color: var(--texto);
}
.veiculo-card:hover { border-color: var(--vermelho-acao); background: var(--branco); }
.veiculo-card strong { display: block; color: var(--navy); }
.veiculo-card span { color: var(--texto-suave); font-size: .9rem; }

/* --- card de produto --- */
.grade-produtos {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(236px, 1fr)); gap: 18px;
}
.card {
  background: var(--branco); border: 1px solid var(--borda); border-radius: var(--raio);
  overflow: hidden; display: flex; flex-direction: column; box-shadow: var(--sombra);
}
.card:hover { box-shadow: var(--sombra-media); }
.card-foto {
  display: block; background: var(--fundo); aspect-ratio: 4 / 3;
  display: flex; align-items: center; justify-content: center;
}
.card-foto img { width: 100%; height: 100%; object-fit: contain; }
.card-sem-foto { color: var(--texto-suave); font-size: .84rem; }
.card-corpo { padding: 14px; display: flex; flex-direction: column; flex: 1; }
.card-marca {
  margin: 0; font-size: .74rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--texto-suave); font-weight: 700;
}
.card-titulo { margin: 4px 0 6px; font-size: .95rem; line-height: 1.35; }
.card-titulo a { color: var(--navy); text-decoration: none; }
.card-titulo a:hover { text-decoration: underline; }
.card-codigo { margin: 0 0 10px; color: var(--texto-suave); font-size: .82rem; }
.card-preco { margin-top: auto; padding-top: 8px; }
.preco { font-size: 1.3rem; color: var(--navy); display: block; }
.preco-consulta { font-size: 1.05rem; color: var(--navy); font-weight: 700; display: block; }
/* A nota de pagamento acompanha TODO preço: o site não cobra, e isso precisa
 * estar dito onde o preço aparece (preço exibido vincula o lojista). */
.preco-nota { display: block; font-size: .76rem; color: var(--texto-suave); margin-top: 2px; }
.card-estoque { margin: 10px 0 4px; }

/* --- página de produto --- */
.pagina-vitrine { padding: 24px 20px 64px; }
.trilha { font-size: .86rem; color: var(--texto-suave); margin-bottom: 18px; }
.trilha a { color: var(--texto-suave); }
.produto-topo {
  display: grid; grid-template-columns: minmax(280px, 1fr) minmax(300px, 1fr);
  gap: 36px; align-items: start;
}
.produto-fotos img#foto-principal {
  width: 100%; height: auto; background: var(--branco);
  border: 1px solid var(--borda); border-radius: var(--raio); object-fit: contain;
}
.miniaturas { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.miniaturas img {
  width: 76px; height: 58px; object-fit: contain; background: var(--branco);
  border: 1px solid var(--borda); border-radius: 6px; cursor: pointer;
}
.miniaturas img:hover { border-color: var(--vermelho-acao); }
.sem-foto-grande {
  background: var(--branco); border: 1px solid var(--borda); border-radius: var(--raio);
  padding: 70px 20px; text-align: center; color: var(--texto-suave);
}
.produto-marca {
  margin: 0; font-size: .8rem; text-transform: uppercase; letter-spacing: .05em;
  color: var(--texto-suave); font-weight: 700;
}
.produto-info h1 { font-size: 1.5rem; margin: 6px 0 16px; line-height: 1.3; }
.produto-codigos {
  display: grid; grid-template-columns: auto 1fr; gap: 6px 16px;
  background: var(--branco); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 14px; margin: 0 0 18px;
}
.produto-codigos dt { color: var(--texto-suave); font-size: .84rem; }
.produto-codigos dd { margin: 0; font-weight: 600; }
.produto-preco {
  background: var(--branco); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 18px;
}
.preco-grande { font-size: 2rem; font-weight: 700; color: var(--navy); margin: 0; }
.preco-consulta-grande { font-size: 1.4rem; font-weight: 700; color: var(--navy); margin: 0; }
.produto-estoque { margin: 12px 0; }
.aviso-pedido {
  background: #eaf1fc; border: 1px solid #b9cdeb; border-radius: var(--raio);
  padding: 12px 14px; margin: 14px 0; font-size: .88rem; color: var(--navy);
}
.aviso-pedido p { margin: 0; }
.bloco {
  background: var(--branco); border: 1px solid var(--borda); border-radius: var(--raio);
  padding: 22px; margin-top: 24px;
}
.bloco h2 { font-size: 1.2rem; margin-top: 0; }
.lista-veiculos { list-style: none; padding: 0; margin: 0 0 12px;
                  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
.lista-veiculos a {
  display: block; padding: 11px 14px; background: var(--fundo);
  border: 1px solid var(--borda); border-radius: var(--raio); text-decoration: none;
  color: var(--texto);
}
.lista-veiculos a:hover { border-color: var(--vermelho-acao); }
.lista-veiculos strong { display: block; color: var(--navy); }

/* --- catálogo --- */
.cab-catalogo { margin-bottom: 20px; }
.cab-catalogo h1 { font-size: 1.6rem; margin-bottom: 4px; }
.contagem { color: var(--texto-suave); margin: 0; font-size: .92rem; }
.catalogo-layout { display: grid; grid-template-columns: 252px 1fr; gap: 26px; align-items: start; }
.filtros {
  background: var(--branco); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 18px; position: sticky; top: 16px;
}
.paginacao {
  display: flex; gap: 14px; align-items: center; justify-content: center;
  margin-top: 30px; flex-wrap: wrap;
}
.pagina-atual { color: var(--texto-suave); font-size: .92rem; }
.vazio-vitrine {
  background: var(--branco); border: 1px solid var(--borda); border-radius: var(--raio);
  padding: 46px 24px; text-align: center; max-width: 620px;
}
.vazio-vitrine h1, .vazio-vitrine h2 { margin-top: 0; }

/* --- institucionais --- */
.institucional { display: grid; grid-template-columns: 1.4fr 1fr; gap: 36px; }
.institucional p { color: #c2d2e6; }
.institucional-dados { background: rgba(255, 255, 255, .06); padding: 22px; border-radius: var(--raio); }
.institucional-dados h3 { margin: 0 0 8px; font-size: 1rem; }
.institucional-dados h3 + p { margin-top: 0; }
.institucional-dados a { color: var(--branco); }
.texto-longo { max-width: 760px; }
.texto-longo h2 { font-size: 1.25rem; margin: 28px 0 10px; }
.texto-longo ul { padding-left: 20px; }
.texto-longo li { margin-bottom: 7px; }
.destaque-texto { font-size: 1.1rem; color: var(--texto); }
.contato-grade { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; align-items: start; }
.fone-grande { font-size: 1.5rem; font-weight: 700; color: var(--navy); text-decoration: none; }
.mapa { width: 100%; border: 1px solid var(--borda); border-radius: var(--raio); }

/* --- rodapé --- */
.rodape { background: var(--navy); color: #c2d2e6; margin-top: 10px; }
.rodape-grade {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  gap: 30px; padding: 44px 20px 30px;
}
.rodape h3 { color: var(--branco); font-size: 1rem; margin: 0 0 10px; }
.rodape p { margin: 0 0 7px; font-size: .9rem; }
.rodape ul { list-style: none; padding: 0; margin: 0; }
.rodape li { margin-bottom: 7px; }
.rodape a { color: #c2d2e6; }
.rodape a:hover { color: var(--branco); }
.nota-google { color: var(--branco); }
.rodape-fim { border-top: 1px solid rgba(255, 255, 255, .13); padding: 16px 0; }
.rodape-fim p { margin: 0; font-size: .86rem; padding: 0 20px; }

/* --- celular: a maior parte do tráfego de uma loja dessas --- */
@media (max-width: 900px) {
  .catalogo-layout { grid-template-columns: 1fr; }
  .filtros { position: static; }
  .produto-topo { grid-template-columns: 1fr; gap: 22px; }
  .institucional, .contato-grade { grid-template-columns: 1fr; }
  .hero h1 { font-size: 1.6rem; }
  .hero { padding: 36px 0 32px; }
  .topo-barra { gap: 14px; padding: 13px 16px; }
  .topo-barra .logo { width: 212px; }
  .topo-fone { display: none; }  /* o telefone reaparece no rodapé e no contato */
  .busca-topo { order: 3; flex: 1 1 100%; }
  .grade-produtos { grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); gap: 12px; }
  .card-titulo { font-size: .88rem; }
  .preco { font-size: 1.12rem; }
  .secao { padding: 32px 0; }
  .admin-topo .container { flex-wrap: wrap; }
}


/* ========================================================================
   CAMADA VISUAL — direção "oficina séria e técnica"
   ========================================================================
   Escrita para a marcação reescrita dos templates. O princípio: a hierarquia
   vem da LUZ e do PESO, não de borda em volta de tudo. Na versão anterior
   cada bloco era um card branco com a mesma borda, e por isso nada se
   destacava — a vitrine tinha a mesma cara do painel administrativo.

   O CÓDIGO DA PEÇA é o herói da interface: num catálogo de autopeças é por
   ele que a pessoa confirma que achou a peça certa. Por isso ganha fundo
   próprio, monoespaçada e tamanho acima do texto de apoio.
   ---------------------------------------------------------------------- */

/* "olho" = a linha curta acima de um título. Dá entrada na seção sem
   competir com o h2. */
.olho {
  display: inline-block;
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  /* `--vermelho` puro dá 4.45:1 sobre superfície, logo abaixo do mínimo de
     4.5 para texto. Este tom clareado passa e mantém a leitura de "vermelho
     da marca" — o `--vermelho` segue intacto para área de cor. */
  color: var(--vermelho-olho);
  margin-bottom: 10px;
}

.secao-topo { margin-bottom: 26px; }
.secao-topo h2 { margin: 0; font-size: var(--t-xl); letter-spacing: -.02em; }

.apoio { color: var(--t-apoio); }

/* --- Selos ---------------------------------------------------------------
   Sempre texto + símbolo, nunca só cor: informação não pode depender de
   enxergar a diferença entre verde e vermelho. */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--t-xs);
  font-weight: 700;
  line-height: 1;
  padding: 5px 9px;
  border-radius: 999px;
  white-space: nowrap;
}
.tag-ok  { color: var(--verde); background: rgba(61, 220, 132, .12); }
.tag-off { color: var(--ambar); background: rgba(255, 192, 72, .13); }
/* Discreto por decisão do Caio: continua visível e continua travando a
   publicação pelo teste, mas não domina a tela durante a avaliação. */
.tag-exemplo {
  color: var(--texto-suave);
  background: transparent;
  border: 1px dashed var(--borda-forte);
  font-weight: 600;
}

/* --- Botões -------------------------------------------------------------- */
.b {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 13px 20px;
  border-radius: var(--raio);
  font-weight: 700;
  font-size: var(--t-sm);
  text-decoration: none;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .15s, border-color .15s, transform .08s;
}
.b:active { transform: translateY(1px); }
.b-vm { background: var(--vermelho-acao); color: #fff; }
.b-vm:hover { background: var(--vermelho-acao-escuro); }
.b-linha { background: transparent; color: var(--texto); border-color: var(--borda-forte); }
.b-linha:hover { border-color: var(--vermelho-acao); color: #fff; }
.b-bloco { display: flex; width: 100%; }

/* --- Página de produto --------------------------------------------------- */
.prod { padding: 26px 0 50px; }
.prod-grade { display: grid; gap: 30px; align-items: start; }
@media (min-width: 900px) {
  .prod-grade { grid-template-columns: minmax(0, 1fr) 400px; gap: 42px; }
  /* Acompanha a rolagem: a coluna da esquerda é longa (aplicação, descrição)
     e sem isto o preço e a ação saem da tela justamente quando a pessoa está
     decidindo. */
  .prod-grade > aside { position: sticky; top: 18px; }
}

.prod-marca {
  margin: 0 0 6px;
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--vermelho);
}
.prod-grade h1 { margin: 0 0 18px; font-size: var(--t-xl); line-height: 1.2; letter-spacing: -.02em; }

.prod-minis { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.prod-minis img {
  border-radius: 6px; border: 1px solid var(--borda);
  cursor: pointer; background: var(--superficie);
}
.prod-minis img:hover { border-color: var(--vermelho-acao); }

/* Painel técnico: linhas de dado, sem card em volta de cada uma. */
.painel { margin: 0 0 20px; border-top: 1px solid var(--borda); }
.painel-linha {
  display: flex; justify-content: space-between; align-items: center; gap: 14px;
  padding: 11px 0; border-bottom: 1px solid var(--borda);
}
.painel-linha dt { font-size: var(--t-sm); color: var(--t-apoio); margin: 0; }
.painel-linha dd { margin: 0; font-family: var(--mono); font-size: var(--t-sm); letter-spacing: .04em; }
/* O herói. */
.painel-linha.destaque {
  background: var(--superficie-alta);
  margin: 0 -14px; padding: 13px 14px; border-radius: var(--raio);
  border-bottom: 0;
}
.painel-linha.destaque dt { color: var(--texto); font-weight: 600; }
.painel-linha.destaque .val { font-size: var(--t-lg); font-weight: 700; color: #fff; }

.caixa-compra {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 20px;
}
.preco-grande { margin: 0; font-size: var(--t-2xl); font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.preco-consulta-grande { margin: 0; font-size: var(--t-lg); font-weight: 700; color: var(--texto); }
.preco-apoio { margin: 4px 0 0; font-size: var(--t-sm); color: var(--t-apoio); }
.compra-estado { margin: 14px 0 16px; }

/* O aviso aparece UMA vez por tela, aqui junto do preço. Antes ecoava três
   vezes na mesma página e lia como desconfiança. */
.nota-pagamento {
  display: flex; gap: 9px; align-items: flex-start;
  margin-top: 14px; padding-top: 14px;
  border-top: 1px solid var(--borda);
  font-size: var(--t-sm); color: var(--t-apoio); line-height: 1.5;
}
.nota-pagamento strong { color: var(--texto); }

/* Blocos técnicos da coluna esquerda: separador, não caixa. */
.bloco-tec { margin-top: 30px; padding-top: 24px; border-top: 1px solid var(--borda); }
.bloco-tec h2 { margin: 0 0 14px; font-size: var(--t-lg); letter-spacing: -.01em; }

/* --- Placeholder de foto -------------------------------------------------
   Sem foto real, o desenho cinza genérico era boa parte do aspecto amador.
   Aqui a ausência vira intenção: fundo da marca e o CÓDIGO no lugar da foto —
   que é justamente o dado que identifica a peça. */
.rotulo-vazio {
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--texto-suave);
}
.codigo-destaque {
  font-family: var(--mono); font-size: clamp(1.1rem, 3.4vw, 1.9rem);
  font-weight: 700; color: #fff; letter-spacing: .05em; text-align: center;
  padding: 0 12px; word-break: break-all;
}

/* --- Card de produto ----------------------------------------------------- */
.card-rodape {
  margin-top: auto; padding-top: 14px;
  display: flex; flex-direction: column; gap: 12px;
}
.prod-grade .grade-produtos { margin-top: 0; }

/* `body.vitrine` — gancho para o tema da loja, separado do painel admin.
   Sem isto as duas áreas herdavam exatamente a mesma aparência, que era
   parte do motivo de a vitrine parecer um painel administrativo. */
body.vitrine { background: var(--fundo); color: var(--texto); }

/* Faixa de contagem acima da grade do catálogo. */
.resultados {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px;
  margin-bottom: 18px; padding-bottom: 14px;
  border-bottom: 1px solid var(--borda);
  font-size: var(--t-sm); color: var(--t-apoio);
}
.resultados strong { color: var(--texto); font-size: var(--t-md); }

/* --- Contêiner da foto ---------------------------------------------------
   `.prod-foto` existia na marcação e NÃO tinha estilo: sem altura nem regra
   para a <img>, a imagem colapsava e a área aparecia vazia mesmo com o
   arquivo servindo em 200. Foi flagrado por screenshot — o HTML estava
   correto e a requisição da imagem também. */
.prod-foto {
  display: flex; align-items: center; justify-content: center;
  flex-direction: column; gap: 10px;
  aspect-ratio: 4 / 3;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  overflow: hidden;
}
.prod-foto img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* Placeholder: o vazio vira informação. Fundo da marca em vez de cinza
   genérico, e o CÓDIGO ocupa o lugar da foto — é o dado que identifica a
   peça. Lê como intenção, não como falha. */
.foto-vazia {
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(255, 49, 49, .10), transparent 60%),
    var(--superficie-alta);
  border-style: dashed;
  border-color: var(--borda-forte);
}
.card-foto {
  display: flex; align-items: center; justify-content: center;
  flex-direction: column; gap: 6px;
  background: var(--superficie); border-bottom: 1px solid var(--borda);
}
.card-foto img { width: 100%; height: 100%; object-fit: contain; }
.card-foto .codigo-destaque { font-size: 1rem; }
.card-foto .rotulo-vazio { font-size: .62rem; }

/* --- Hero com sequência de quadros --------------------------------------
   O canvas fica atrás do conteúdo; o poster embaixo dele some quando o
   primeiro quadro é desenhado. Altura generosa porque a sequência precisa de
   percurso de rolagem para ser percorrida. */
.hero { position: relative; overflow: hidden; isolation: isolate; }
.hero-fundo { position: absolute; inset: 0; z-index: 0; }
.hero-poster,
.hero-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.hero-canvas { opacity: 0; transition: opacity .25s linear; }
.hero-canvas.pronto { opacity: 1; }

/* Véu: o texto do hero precisa de 4.5:1 por cima de uma imagem que muda de
   claridade ao longo da sequência. Sem isto o título fica ilegível justamente
   nos quadros em que os faróis acendem. */
.hero-fundo::after {
  content: "";
  position: absolute; inset: 0;
  /* Véu assimétrico: escurece forte só a faixa da esquerda, onde mora o
     texto, e deixa a direita quase limpa para o caminhão aparecer. Um véu
     uniforme protegia a legibilidade mas apagava a imagem inteira — que é
     justamente o que o cliente mandou produzir. */
  background:
    linear-gradient(to right,
      rgba(7, 21, 38, .92) 0%,
      rgba(7, 21, 38, .78) 32%,
      rgba(7, 21, 38, .30) 62%,
      rgba(7, 21, 38, .05) 100%),
    linear-gradient(to bottom, rgba(7, 21, 38, .30), rgba(7, 21, 38, .55));
}
/* No celular não há "faixa da esquerda": o texto ocupa a largura toda, então
   o véu volta a ser uniforme — senão o título cai em cima do caminhão. */
@media (max-width: 760px) {
  .hero-fundo::after {
    background: linear-gradient(to bottom, rgba(7, 21, 38, .72), rgba(7, 21, 38, .92));
  }
}
.hero-conteudo { position: relative; z-index: 1; padding-top: 72px; padding-bottom: 80px; }
@media (min-width: 900px) { .hero-conteudo { padding-top: 110px; padding-bottom: 130px; } }

/* --- Capa da categoria --------------------------------------------------- */
.cat-foto {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: calc(var(--raio) - 2px);
  margin: -2px -2px 14px;
  background: var(--superficie-alta);
}
.cat-foto img {
  width: 100%; height: 100%;
  object-fit: cover; display: block;
  transition: transform .4s var(--ease, ease);
}
.cat-card:hover .cat-foto img { transform: scale(1.04); }

@media (prefers-reduced-motion: reduce) {
  .cat-foto img { transition: none; }
  .cat-card:hover .cat-foto img { transform: none; }
}

/* O hero precisa ser MAIS ALTO que a janela: a sequência é percorrida pela
   rolagem DENTRO dele, e sem percurso ela nunca sai do primeiro quadro.
   Com 509px numa janela de 900px o efeito simplesmente não acontecia —
   flagrado medindo, não olhando.
   O conteúdo fica grudado no topo para não flutuar no meio do vão.

   ALTURA x FÓRMULA DE progresso() em hero.js — os dois têm que casar.
   5 rodadas até fechar isto (relatado em capturas de tela como "faixa azul"
   e depois "breu liso"), fica registrado o raciocínio completo — sobretudo
   a ROD A 4, que foi um erro de raciocínio corrigindo um sintoma residual
   com a fórmula errada, e vale ler antes de mexer aqui de novo:

   1) FIM_EM separando o fim da sequência do fim do hero: dois ritmos
      diferentes dentro do mesmo bloco, descasavam, sobrava vão. Removido.
   2) `.hero-painel` (quem deveria grudar) tinha ficado `position: static`
      numa declaração antiga — não grudava nada. Corrigido para `sticky`.
   3) Com o sticky certo mas a conta de percurso ainda em "altura − 1 janela"
      (a de baixo), sobrava uma faixa residual pequena (~300-450px) no fim.
   4) ERRO: tentei "corrigir" (3) assumindo que `position: sticky` de
      `height: 100vh` consome DUAS janelas de scroll — uma presa, uma
      saindo. Mudei a fórmula para `altura − 2×janela` e a altura para
      250vh. Isso ABRIU um vão muito maior (quase 900px), porque a premissa
      estava errada: um elemento sticky SAI de cena no mesmo instante em que
      seu CONTÊINER (não ele mesmo) termina — não precisa de uma segunda
      janela de margem.
   5) Medindo a posição ABSOLUTA no documento (`getBoundingClientRect().top
      + scrollY`, não só o valor relativo à viewport) ficou claro: o critério
      certo é `p=1` exatamente quando `.hero` sai inteiro da viewport por
      cima, isto é, `hero.bottom === innerHeight` — que é `percurso = altura
      − 1×janela`. A fórmula original (a de antes do erro da rodada 4)
      estava certa o tempo todo; o resíduo da rodada 3 tinha outra causa
      (pequena, residual, abaixo do que vale caçar — a melhora de "quase 2
      telas vazias" para "~300px" já tirou o defeito visível que foi
      reportado, e tentar zerar esse resíduo foi o que causou a rodada 4).
   150vh = 100vh de janela + 50vh de percurso: suficiente para a sequência de
   48 quadros não passar rápido demais, sem alongar a página à toa.
   Se mexer na altura, a fórmula em hero.js é `percurso = altura − 1 janela`
   (NÃO duas) — `altura_vh = 100 + percurso_vh_desejado`. */
.hero { min-height: 150vh; }

/* Fundo e conteúdo empilhados DENTRO do mesmo painel grudado, não grudados
   separadamente: com dois `sticky` irmãos cada um para por conta própria, o
   texto descolava da imagem e só aparecia no fim da rolagem. */
.hero-painel {
  position: sticky; top: 0;
  height: 100vh;
  display: flex; align-items: center;
  overflow: hidden;
}
.hero-fundo { position: absolute; inset: 0; }
.hero-conteudo { position: relative; z-index: 1; width: 100%; }

/* Sem regra de celular separada: a fórmula de hero.js é `altura − 2×janela`,
   já em vh (relativo à própria viewport) — o mesmo 250vh dá os mesmos 50vh de
   percurso "útil" em qualquer tamanho de tela, sem precisar de outro número
   calibrado à parte (foi uma fonte de bug antes: dois valores que podiam
   ficar desalinhados por esquecimento). */

@media (prefers-reduced-motion: reduce) {
  /* Sem animação não há o que percorrer — o hero volta a ter altura normal
     em vez de virar um vão vazio de duas telas. */
  .hero { min-height: 0; }
  .hero-fundo { position: absolute; height: 100%; }
  .hero-conteudo { position: relative; }
}

/* --- Entrada das categorias ---------------------------------------------
   Os cards sobem e aparecem quando a sequência do caminhão termina — a
   leitura pretendida é "as peças que voaram viram as categorias".
   Começam VISÍVEIS e o JS marca `.revelar` só se o navegador suporta a
   observação de entrada em tela: se o script falhar, o conteúdo continua
   lá em vez de sumir para sempre. */
.grade-categorias.revelar .cat-card {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity .55s ease, transform .55s cubic-bezier(.22, 1, .36, 1);
}
.grade-categorias.revelar .cat-card.dentro {
  opacity: 1;
  transform: none;
}
/* Escalonado: os cards entram em cascata, não todos de uma vez. */
.grade-categorias.revelar .cat-card:nth-child(1) { transition-delay: .00s; }
.grade-categorias.revelar .cat-card:nth-child(2) { transition-delay: .07s; }
.grade-categorias.revelar .cat-card:nth-child(3) { transition-delay: .14s; }
.grade-categorias.revelar .cat-card:nth-child(4) { transition-delay: .21s; }
.grade-categorias.revelar .cat-card:nth-child(5) { transition-delay: .28s; }

@media (prefers-reduced-motion: reduce) {
  .grade-categorias.revelar .cat-card {
    opacity: 1; transform: none; transition: none;
  }
}

/* --- Card de categoria: correção do tema -------------------------------
   O card tinha ficado com `background: var(--branco)` e título em
   `var(--navy)`. No tema claro isso era escuro-sobre-claro; no tema escuro
   o navy virou quase branco e o título ficou BRANCO SOBRE BRANCO —
   praticamente 1:1 de contraste, texto invisível.
   Flagrado medindo a cor computada, não olhando: no screenshot reduzido o
   texto apenas "sumia" e parecia escolha de design. */
.cat-card {
  background: var(--superficie);
  border: 1px solid var(--borda);
  color: var(--texto);
  box-shadow: none;
  padding: 14px;
  display: flex; flex-direction: column;
  transition: border-color .2s ease, transform .2s ease;
}
.cat-card:hover {
  border-color: var(--vermelho-acao);
  transform: translateY(-2px);
  box-shadow: var(--sombra-media);
}
/* Por classe, não por h3: em /categorias o nome é h2 (a página não tem seção
   intermediária) e a hierarquia de títulos não pode pular nível. */
.cat-card .cat-nome {
  margin: 0 0 6px;
  color: var(--texto);
  font-size: var(--t-lg);
  letter-spacing: -.01em;
}
.cat-card p { color: var(--t-apoio); margin: 0 0 14px; font-size: var(--t-sm); }
.cat-card .cat-link {
  margin-top: auto;
  color: var(--vermelho-olho);
  font-weight: 700; font-size: var(--t-sm);
}

@media (prefers-reduced-motion: reduce) {
  .cat-card, .cat-card:hover { transition: none; transform: none; }
}

/* --- Correções da inversão de tema -------------------------------------
   `--navy` passou a significar TEXTO claro, então toda regra que o usava
   como FUNDO inverteu. São os espelhos do bug do título branco-sobre-branco:
   aqui o rodapé escuro virou rodapé claro. */
.rodape { background: var(--superficie); color: var(--texto-suave); }
.rodape h3 { color: var(--texto); }
.rodape a { color: var(--texto-suave); }
.rodape a:hover { color: var(--vermelho-olho); }
.rodape-fim { border-top: 1px solid var(--borda); }

/* `--branco` virou superfície elevada; pedia "mais claro que o fundo", e é
   isso que continua entregando, só que no tema escuro.
   (`.faixa` já tem a declaração equivalente mais acima no arquivo, junto do
   resto do carrossel — duplicar aqui só criaria mais uma fonte de confusão
   de cascata, como já aconteceu antes neste arquivo.) */
.secao-clara { background: var(--superficie); }

/* Campo de formulário: fundo de superfície com texto claro. Antes era
   `var(--branco)` esperando papel branco. */
input, select, textarea {
  background: var(--superficie-alta);
  color: var(--texto);
  border-color: var(--borda-forte);
}
input::placeholder, textarea::placeholder { color: var(--texto-suave); opacity: .75; }

/* O botão vermelho precisa de branco REAL, não da superfície. */
.btn-primario, .b-vm { color: var(--branco-puro); }

/* `.secao-escura` ficou com os DOIS valores invertidos: fundo `--navy`
   (hoje claro) e texto `--branco` (hoje escuro). Era a seção institucional
   aparecendo como um bloco branco no meio do site escuro. */
.secao-escura { background: var(--superficie); color: var(--texto); }
.secao-escura h2,
.secao-escura h3 { color: var(--texto); }
.secao-escura .secao-sub { color: var(--t-apoio); }

/* A CAUSA DO VÃO PRETO: `.hero` tinha `overflow: hidden`, e overflow
   diferente de `visible` em QUALQUER ancestral desativa o `position: sticky`
   do filho. O painel nunca grudou — ele rolava para fora da tela e deixava
   os 100vh de percurso visíveis como vazio.
   Medido: com o overflow ativo o topo do painel ia para -692px e -1142px
   enquanto a pessoa rolava, em vez de ficar em 0.
   Duas tentativas anteriores erraram o alvo: alongar o hero (só aumentou o
   vão) e puxar a faixa com margem negativa (cobriu a grade de categorias).
   O recorte que o `overflow` fazia volta no próprio painel, que é onde a
   imagem precisa ser cortada. */
.hero { overflow: visible; }
.hero-painel { overflow: hidden; }

/* --- Hero: fundo fixo em vez de painel grudado ---------------------------
   Reescreve o comportamento definido acima. O `position: sticky` exige que
   nenhum ancestral recorte o overflow e que a altura do bloco case com a
   janela — duas condições que falharam repetidamente, deixando vão preto em
   tamanhos diferentes de tela.
   Aqui o fundo é `fixed`: ele simplesmente ocupa a tela enquanto o hero
   estiver passando, e some quando acaba. Sem "soltar", sem sobra. */
.hero-painel {
  position: static;
  height: auto;
  min-height: 100vh;
  overflow: visible;
  display: flex;
  align-items: center;
}
.hero-fundo {
  /* `absolute`, não `fixed`: agora é `.hero-painel` (pai direto) quem é
     `sticky` e fica grudado na viewport durante o percurso — o fundo só
     precisa preencher ESSE pai, não a viewport inteira por conta própria.
     Isso elimina a dependência de JS ligar/desligar a posição do fundo em
     sincronia com um segundo elemento sticky separado, que foi a origem
     real do vão: dois elementos tentando "grudar" em momentos diferentes. */
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.hero-conteudo { position: relative; z-index: 1; }

/* O fundo some suavemente perto do fim da sequência, em vez de cortar seco
   quando o canvas chega no último quadro — a classe `.ativo` ainda é posta
   pelo JS, mas agora só por estética (fade-out), não para evitar vazamento:
   o `sticky` do painel já impede o fundo de aparecer fora do bloco do hero. */
.hero-fundo { opacity: 0; transition: opacity .3s linear; }
.hero.ativo .hero-fundo { opacity: 1; }

/* O conteúdo do hero também precisa acompanhar a tela enquanto a sequência
   roda — senão o título rola para fora e sobra só imagem, como aconteceu no
   meio do percurso. `sticky` aqui é seguro: o ancestral já não recorta. */
/* O conteúdo acompanha a tela durante TODO o bloco do hero.
   `height: 100vh` (e não `min-height`) é o que garante isso: com min-height o
   elemento cresce junto do conteúdo, o grudamento solta antes do fim do bloco
   e sobra vão. Foi a causa de o vão persistir no celular e no tablet depois
   de quatro tentativas de calibrar a altura em vh. */
.hero-conteudo {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  align-items: center;
  width: 100%;
}

/* No celular o hero é mais curto que o conteúdo que vem depois, e o vão
   reaparecia em vários pontos. Percurso menor e proporcional resolve sem
   depender de número mágico. */
@media (max-width: 760px) {
  /* O conteúdo grudado precisa cobrir TODO o bloco do hero, não só uma tela:
     com `min-height: 100vh` num hero de 150vh sobravam 50vh sem nada grudado
     e o vão reaparecia (medido em 1050, 1200 e 1500px de rolagem).
     `height: 100vh` + o hero medindo o percurso resolve, porque o elemento
     grudado permanece colado durante todo o bloco.
     (A altura do `.hero` em si já é 150vh pela regra base acima — não
     precisa redeclarar aqui; o celular usa o mesmo valor que o desktop.)
     `padding-top: 86px` saiu: era para compensar o cabeçalho quando o
     conteúdo ficava centralizado/no topo. Agora que título e busca vão para
     a BASE do hero (`justify-content: flex-end` na regra geral, decisão do
     cliente para não cobrir a cena com texto no meio), esse respiro de topo
     não faz falta — e `align-items: flex-start` aqui é so eixo horizontal
     (a direção é coluna), então continua só alinhando o texto à esquerda. */
  .hero-conteudo {
    align-items: flex-start;
    height: 100vh;
    min-height: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-conteudo { position: relative; min-height: 0; }
  .hero-fundo { position: absolute; opacity: 1; }
}

/* (O bloco de título/busca saiu do hero e depois voltou, por decisões
   sucessivas do cliente. A declaração de `.hero-painel` que valia "sem
   texto" foi removida daqui — hoje há h1+busca de novo, e a declaração
   definitiva de `.hero-painel` está mais abaixo, junto do resto do conteúdo
   sobre a cena.) */

/* O véu existia para o texto branco sobreviver aos quadros em que os faróis
   acendem. Sem texto, ele só escurecia a cena à toa — fica um degradê leve,
   para o conteúdo seguinte não colar na imagem. */
.hero-fundo::after {
  background: linear-gradient(to bottom,
    rgba(7, 21, 38, .30) 0%,
    rgba(7, 21, 38, .10) 45%,
    rgba(7, 21, 38, .75) 100%);
}
@media (max-width: 760px) {
  .hero-fundo::after {
    background: linear-gradient(to bottom,
      rgba(7, 21, 38, .34) 0%,
      rgba(7, 21, 38, .12) 45%,
      rgba(7, 21, 38, .78) 100%);
  }
}

/* Título continua no HTML para leitor de tela e para o Google — a página
   precisa de um h1, e "imagem bonita sem h1" é página sem assunto. */
.sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --- Hero: título + busca sobre a cena -----------------------------------
   Volta a existir conteúdo no hero, então o painel volta a centralizá-lo.

   CAUSA REAL DO VÃO (achada só depois de inspecionar o DOM renderizado, não
   só className por elementFromPoint): `.hero-painel`, numa declaração mais
   acima no arquivo, tinha ficado `position: static; height: auto;
   min-height: 100vh`. Um bloco `static` de ~900px dentro de um `.hero` de
   1350px simplesmente ROLA PARA FORA como qualquer elemento em fluxo normal
   — ele não "gruda". O `.hero-conteudo` sticky lá dentro também desgrudava
   junto, porque seu contexto de sticky é o próprio `.hero-painel`, e este
   já tinha saído de cena bem antes do `.hero` (1350px) terminar. Sobravam
   ~450px (1350 - 900) de `.hero` sem NADA posicionado ali dentro — nem
   fundo, nem conteúdo — só o fundo escuro da página por trás. Era o "breu
   liso" reportado, visualmente diferente do vão anterior (aquele tinha o
   último quadro do vídeo parado; este não tem textura nenhuma).
   A correção: `.hero-painel` É o elemento sticky, e cobre a altura inteira
   do `.hero` (não os 900px fixos de antes). Com isso ele acompanha a
   rolagem do início ao fim do bloco, e só solta quando `.hero` de fato
   termina — exatamente onde `progresso()` chega a 1 em hero.js. */
.hero-painel {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  /* flex-end: título e busca ficam na base da cena, não no meio dela —
     decisão do cliente, para não cobrir o caminhão com texto no centro. */
  align-items: flex-end;
  overflow: hidden;
}
.hero-conteudo {
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-bottom: clamp(32px, 6vh, 64px);
}

.hero-conteudo h1 {
  margin: 0 0 26px;
  font-size: var(--t-3xl);
  line-height: 1.04;
  letter-spacing: -.025em;
  max-width: 16ch;
  /* Sombra em vez de véu pesado: protege a leitura nos quadros em que os
     faróis acendem sem apagar a cena atrás. */
  text-shadow: 0 2px 28px rgba(7, 21, 38, .92), 0 1px 4px rgba(7, 21, 38, .8);
}

.hero-busca {
  display: flex;
  gap: 10px;
  max-width: 620px;
  width: 100%;
}
.hero-busca input {
  flex: 1;
  min-width: 0;
  padding: 16px 18px;
  font-size: var(--t-md);
  border-radius: var(--raio);
  border: 1px solid var(--borda-forte);
  /* Fundo quase opaco: campo translúcido sobre imagem em movimento fica
     ilegível, e o texto digitado é o dado mais importante da página. */
  background: color-mix(in srgb, var(--superficie) 92%, transparent);
  backdrop-filter: blur(6px);
  color: var(--texto);
}
.hero-busca input:focus {
  outline: 2px solid var(--vermelho-acao);
  outline-offset: 2px;
  border-color: transparent;
}
.hero-busca .btn { padding: 16px 28px; font-size: var(--t-md); white-space: nowrap; }

@media (max-width: 640px) {
  .hero-conteudo h1 { font-size: clamp(1.9rem, 8.5vw, 2.6rem); max-width: 14ch; }
  .hero-busca { flex-direction: column; }
  .hero-busca .btn { width: 100%; }
}

/* Sem a busca e o telefone, o cabeçalho da home fica só com a marca. */
.topo-barra { gap: 18px; }

/* --- Cascata das categorias (reescrita) ---------------------------------
   O estado agora vive na GRADE (`.dentro` nela), não em cada card. Assim a
   ordem da cascata é a ordem do HTML, e não a ordem em que cada card cruza a
   borda da tela — que dependia de quantos cabem por linha e fazia os quatro
   primeiros entrarem juntos.
   Sobrescreve as regras `.cat-card.dentro` definidas antes. */
.grade-categorias.revelar .cat-card {
  opacity: 0;
  transform: translateY(30px);
  transition:
    opacity .5s ease,
    transform .6s cubic-bezier(.22, 1, .36, 1);
}
.grade-categorias.revelar.dentro .cat-card {
  opacity: 1;
  transform: none;
}
.grade-categorias.revelar.dentro .cat-card:nth-child(1) { transition-delay: .00s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(2) { transition-delay: .09s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(3) { transition-delay: .18s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(4) { transition-delay: .27s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(5) { transition-delay: .36s; }

@media (prefers-reduced-motion: reduce) {
  .grade-categorias.revelar .cat-card {
    opacity: 1; transform: none; transition: none;
  }
}

/* --- Costura entre o fim da sequência e o conteúdo ----------------------
   A sequência termina com as peças suspensas sobre a estrada, e a seção
   seguinte começava com um corte seco de cor. Este degradê faz a cena se
   dissolver no fundo do site, em vez de acabar numa linha reta. */
.hero::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 42vh;
  background: linear-gradient(to bottom, transparent, var(--fundo) 92%);
  pointer-events: none;
  z-index: 1;
}
.hero { position: relative; }

/* --- Entrada das capas: as peças caem e assentam -------------------------
   Antes o card inteiro subia 30px e aparecia — discreto demais para alguém
   notar, ainda mais acontecendo enquanto a pessoa rola o vídeo.
   Agora a PEÇA cai de cima, passa um pouco do lugar e volta (o repique do
   final da curva), enquanto o card em si só esmaece. A leitura pretendida é
   "as peças que voaram no vídeo se assentam aqui".
   Sobrescreve as regras de cascata definidas antes. */
.grade-categorias.revelar .cat-card {
  opacity: 0;
  transform: none;
  transition: opacity .45s ease;
}
.grade-categorias.revelar .cat-card .cat-foto img {
  opacity: 0;
  transform: translateY(-120px) rotate(-7deg) scale(.88);
  /* A curva com overshoot é o que dá o "pousar": a peça passa do ponto e
     volta, em vez de frear reto. */
  transition:
    opacity .4s ease,
    transform .95s cubic-bezier(.3, 1.5, .5, 1);
}
.grade-categorias.revelar.dentro .cat-card { opacity: 1; }
.grade-categorias.revelar.dentro .cat-card .cat-foto img {
  opacity: 1;
  transform: none;
}

/* Cascata: uma peça cai depois da outra, na ordem do HTML. */
.grade-categorias.revelar.dentro .cat-card:nth-child(1) .cat-foto img { transition-delay: .00s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(2) .cat-foto img { transition-delay: .13s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(3) .cat-foto img { transition-delay: .26s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(4) .cat-foto img { transition-delay: .39s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(5) .cat-foto img { transition-delay: .52s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(1) { transition-delay: .00s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(2) { transition-delay: .13s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(3) { transition-delay: .26s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(4) { transition-delay: .39s; }
.grade-categorias.revelar.dentro .cat-card:nth-child(5) { transition-delay: .52s; }

/* A moldura precisa conter a peça durante a queda, senão ela aparece por
   cima do card de cima. */
.cat-foto { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .grade-categorias.revelar .cat-card,
  .grade-categorias.revelar .cat-card .cat-foto img {
    opacity: 1; transform: none; transition: none;
  }
}

/* ======================= Admin: balcão e importação =======================
 * O balcão é usado NO CELULAR, com o dedo: alvos de toque grandes (56px,
 * acima dos 44px mínimos), número do estoque em destaque, nada de tabela. */
.balcao-busca { display: flex; gap: 10px; margin-bottom: 16px; }
.balcao-busca input { flex: 1; font-size: 1.1rem; padding: 14px 16px; }
.balcao-item { display: grid; gap: 14px; }
.balcao-info { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
.balcao-info a { text-decoration: none; }
.balcao-estoque { display: flex; align-items: center; gap: 12px; }
.balcao-estoque form { flex: 1; }
.balcao-botao {
  width: 100%; min-height: 56px; justify-content: center;
  font-size: 1.4rem; font-weight: 800;
}
.balcao-botao:disabled { opacity: .35; cursor: not-allowed; }
.balcao-qtd { flex: 0 0 96px; text-align: center; line-height: 1.1; }
.balcao-qtd span { display: block; font-size: 2rem; font-weight: 800; }
.balcao-qtd small { color: var(--texto-suave); font-size: .78rem; }
.balcao-extra label { cursor: pointer; }
@media (min-width: 760px) {
  .balcao-item { grid-template-columns: 1fr 300px auto; align-items: center; }
}

.importar-resumo { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.importar-resumo .cartao { text-align: center; margin-bottom: 12px; }
.importar-resumo strong { display: block; font-size: 2rem; line-height: 1.1; }
.importar-resumo span { color: var(--texto-suave); font-size: .88rem; }
.importar-resumo .importar-ruim strong { color: var(--vermelho-olho); }

/* --- Painel no tema escuro ----------------------------------------------
 * A migração para o tema escuro reapontou `--navy` (agora texto CLARO) e
 * `--branco` (agora superfície ESCURA), e quatro regras do painel ficaram com
 * texto claro sobre fundo claro: o menu do topo, o aviso azul ("só para
 * consulta"), o selo "sob consulta" e a linha da tabela sob o mouse. Flagrado
 * em screenshot do celular — o DOM estava "certo". */
.admin-topo { background: var(--superficie); border-bottom: 1px solid var(--borda); }
.admin-topo .logo { color: var(--texto); }
.admin-topo nav a { color: var(--texto-suave); }
.admin-topo nav a:hover,
.admin-topo nav a.ativo { background: var(--superficie-alta); color: var(--texto); }
.aviso-info { background: #10294a; border-color: var(--borda-forte); color: var(--texto); }
.aviso-info a { color: var(--texto); }
.selo-consulta { background: #1d3a56; color: var(--texto); }
tbody tr:hover { background: var(--superficie-alta); }
/* Tabelas de prévia: no celular rolam de lado em vez de espremer o nome da
 * peça numa coluna de três letras. */
.tabela-larga { min-width: 560px; }

/* Painel no celular: o logo de 250px e o menu disputavam a mesma linha e o
 * menu quebrava em três. Agora o menu desce e rola de lado. */
@media (max-width: 700px) {
  .admin-topo .container { flex-wrap: wrap; gap: 10px; }
  .admin-topo .logo { width: 170px; }
  .admin-topo nav {
    margin-left: 0; width: 100%; flex-wrap: nowrap; overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .admin-topo nav a { white-space: nowrap; padding: 8px 12px; }
  .pagina { padding-top: 18px; }
  .importar-resumo { gap: 8px; }
  .importar-resumo strong { font-size: 1.5rem; }
}
