/* ============================================================================
   BLISS SORVETES E AÇAÍ — direção "Azul de Praia" (2026-09-09, 7ª rodada)

   Pedido do cliente, não escolha nossa. Bruno, por áudio em 08/09, olhando a
   versão escura anterior:
     "Tá muito escuro. Eu acho que o fundo pode ser um fundo azul —
      esse contraste que é nosso é azul com amarelo."
   e, mostrando o site do Split Açaí na tela:
     "Olha a linguagem, uma linguagem mais divertida. Uma fonte mais divertida."

   O azul não foi inventado: #0060a8 saiu por amostragem das fotos do carrinho
   e do freezer da própria Bliss. O dourado saiu do logo. Ver DESIGN.md.

   Tipografia do Fontshare (licença livre para uso comercial), auto-hospedada em
   assets/fontes/ para não depender do CDN deles:
     Chubbo   — display pesada de terminais macios; é a "fonte divertida"
     Switzer  — grotesk suíço, legível em corpo pequeno e em número
   ========================================================================== */

@font-face { font-family: "Chubbo"; src: url("fontes/chubbo-500.woff2") format("woff2"); font-weight: 500; font-display: swap; font-style: normal; }
@font-face { font-family: "Chubbo"; src: url("fontes/chubbo-700.woff2") format("woff2"); font-weight: 700; font-display: swap; font-style: normal; }
@font-face { font-family: "Switzer"; src: url("fontes/switzer-400.woff2") format("woff2"); font-weight: 400; font-display: swap; font-style: normal; }
@font-face { font-family: "Switzer"; src: url("fontes/switzer-500.woff2") format("woff2"); font-weight: 500; font-display: swap; font-style: normal; }
@font-face { font-family: "Switzer"; src: url("fontes/switzer-700.woff2") format("woff2"); font-weight: 700; font-display: swap; font-style: normal; }

:root {
  /* --- cor por papel, não por nome bonito --- */
  --azul: #0060a8;          /* o mundo — amostrado do carrinho de praia */
  /* O roxo-açaí saiu a pedido do cliente (09/09): as faixas alternadas passam a
     ser "um azul um pouco diferente". Medido: #003a68 dá 1,79:1 contra o azul
     principal — separação visível sem virar outra cor — e 11,2:1 com o creme. */
  --azul-fundo: #003a68;    /* faixas, rodapé e blocos alternados */
  /* Tinta escura para texto SOBRE o amarelo (9,6:1). Antes esse papel era do
     roxo; com ele fora, precisa de token próprio — o azul principal sobre o
     amarelo mede só 4,13:1 e reprova em corpo pequeno. */
  --tinta: #012845;
  --creme: #fdfaf5;         /* tinta */
  /* Opacidade do texto MEDIDA contra o azul, não escolhida no olho. O azul da
     marca é claro, então sobra pouca margem: creme a 78% dava 4,43:1 e reprovava
     o mínimo de 4,5; a 56% dava 3,03. Agora 85% (4,96) e 80% (4,57). A hierarquia
     entre corpo e apoio passa a vir de tamanho e peso, não de apagar o texto. */
  --creme-md: color-mix(in srgb, var(--creme) 85%, transparent);
  --creme-fr: color-mix(in srgb, var(--creme) 80%, transparent);
  --amarelo: #ffc629;       /* o "amarelo" que o Bruno nomeou — títulos grandes */
  /* Mesmo amarelo, clareado até passar 4.5:1 sobre o azul (medido: 4.82). O
     #ffc629 dá 4.13 e serve a partir de 24px, mas reprova em rótulo de 11px.
     Dois tons em vez de um porque o critério muda com o tamanho da letra. */
  --amarelo-texto: #ffdb70;
  --dourado: #e3b04c;       /* dourado do logo — selo e assinatura */
  --vitrine: #fbf8f3;       /* painel claro onde a foto de produto vive */
  --vitrine-tinta: #16324a;
  --fio: color-mix(in srgb, var(--creme) 20%, transparent);
  --fio-forte: color-mix(in srgb, var(--creme) 36%, transparent);

  --fonte-display: "Chubbo", "Trebuchet MS", Verdana, sans-serif;
  --fonte-corpo: "Switzer", "Segoe UI", system-ui, sans-serif;

  --largura: 1240px;
  --margem: clamp(1.15rem, 5vw, 5.5rem);
  --respiro: clamp(5rem, 11vw, 10rem);
  --altura: 78px;   /* do cabeçalho — no :root porque o hero também lê */
  --raio: 14px;            /* canto macio: é a mesma curva dos terminais do Chubbo */
  --curva: cubic-bezier(0.16, 1, 0.3, 1);

  /* CONTRATO DE MOTION — três movimentos, cada um com função declarada.
     1 HIERARQUIZAR  entrada do hero, ordena a leitura na chegada
     2 ORIENTAR      reveal por seção, mostra o que entrou na tela
     3 RESPONDER     hover e foco, confirma que o elemento é acionável
     Três tempos porque seção não tem toda o mesmo papel: o mesmo fade em tudo
     é o que denuncia página gerada. Impacto → leitura → pausa. */
  /* Véus e realces derivados da paleta — não são cores novas, são a MESMA
     tinta em opacidade padronizada. Literal solto aqui vira drift: quando o
     fundo mudar, o véu tem que mudar junto, e color-mix garante isso. */
  --veu-forte: color-mix(in srgb, var(--azul) 94%, transparent);
  --veu-medio: color-mix(in srgb, var(--azul) 72%, transparent);
  --veu-modal: color-mix(in srgb, #06243d 78%, var(--azul));
  --ouro-fraco: color-mix(in srgb, var(--dourado) 8%, transparent);
  --creme-vidro: color-mix(in srgb, var(--creme) 5%, transparent);

  --t-rapido: 420ms;
  --t-base: 640ms;
  --t-lento: 940ms;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; overflow-x: clip; }
body { overflow-x: clip; }   /* contém o painel do menu fora da tela */
body {
  margin: 0;
  background: var(--azul);
  color: var(--creme);
  font-family: var(--fonte-corpo);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img, picture, video, svg { display: block; max-width: 100%; }
picture { height: 100%; }   /* picture é inline por padrão e não repassa altura */
a { color: inherit; text-decoration: none; }
button, input, select { font: inherit; color: inherit; }
figure, p, h1, h2, h3, h4, dl, dd, ul { margin: 0; padding: 0; }
ul { list-style: none; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.pular {
  position: fixed; z-index: 200; top: 0.5rem; left: 0.5rem;
  padding: 0.8rem 1.1rem; background: var(--amarelo); color: var(--tinta);
  font-weight: 700; transform: translateY(-160%); transition: transform 180ms ease;
}
.pular:focus { transform: translateY(0); }
:focus-visible { outline: 2px solid var(--dourado); outline-offset: 3px; }

/* --- tipografia ---------------------------------------------------------- */
/* Os títulos vão em CAIXA ALTA e no peso 700 do Chubbo. É o que dá o tom que o
   Bruno chamou de "divertido": letra gorda, terminal macio, bloco compacto. A
   caixa alta some com as descendentes, então o line-height desce para 0.88 sem
   as linhas se tocarem — em caixa mista isso colaria. */
.display-1 {
  font-family: var(--fonte-display); font-weight: 700;
  font-size: clamp(2.7rem, 6.6vw, 5.6rem); line-height: 0.88;
  letter-spacing: -0.015em; text-transform: uppercase; text-wrap: balance;
}
.display-2 {
  font-family: var(--fonte-display); font-weight: 700;
  font-size: clamp(2.05rem, 4.4vw, 3.6rem); line-height: 0.92;
  letter-spacing: -0.012em; text-transform: uppercase; text-wrap: balance;
}
.display-3 {
  font-family: var(--fonte-display); font-weight: 700;
  font-size: clamp(1.4rem, 2.3vw, 1.95rem); line-height: 1.05;
  letter-spacing: -0.008em; text-transform: uppercase;
}
.rotulo {
  font-family: var(--fonte-corpo); font-size: 0.68rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--amarelo-texto);
}
.lede { font-size: clamp(1rem, 1.25vw, 1.14rem); color: var(--creme-md); max-width: 52ch; }
.miudo { font-size: 0.78rem; color: var(--creme-fr); }
/* Destaque dentro do título. Sem `font-style: italic`: só os pesos normais do
   Chubbo são servidos, e o navegador sintetizaria um itálico falso, inclinando
   as hastes sem redesenhar a letra. O destaque fica no amarelo — que é
   literalmente o contraste que o cliente nomeou: azul com amarelo. */
.enfase { color: var(--amarelo); }

/* --- botões -------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  min-height: 52px; padding: 0.9rem 1.6rem; border: 1px solid transparent;
  border-radius: var(--raio); font-size: 0.82rem; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase; cursor: pointer;
  transition: background 220ms var(--curva), color 220ms var(--curva),
              border-color 220ms var(--curva), transform 220ms var(--curva);
}
/* Tinta roxo-açaí sobre o amarelo: 11,3:1. O par anterior era azul sobre
   dourado, que media 3,3:1 e reprovava até para texto grande. */
.btn-ouro { background: var(--amarelo); color: var(--tinta); }
.btn-ouro:hover { background: var(--amarelo-texto); transform: translateY(-2px); }
.btn-fio { border-color: var(--fio-forte); color: var(--creme); }
.btn-fio:hover { border-color: var(--creme); background: var(--creme-vidro); }
.elo {
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-size: 0.82rem; font-weight: 600; color: var(--amarelo-texto);
  border-bottom: 1px solid color-mix(in srgb, var(--dourado) 40%, transparent); padding-bottom: 2px;
}
.elo span { transition: transform 200ms var(--curva); }
.elo:hover span { transform: translateX(4px); }

/* O cabeçalho é fixo depois da rolagem, então um pulo por âncora aterrissa com
   o topo da seção escondido atrás dele. `scroll-margin-top` reserva essa altura
   no destino do salto, sem mexer no layout. */
[id] { scroll-margin-top: calc(var(--altura) + 1.5rem); }

.faixa { width: 100%; max-width: var(--largura); margin-inline: auto; padding-inline: var(--margem); }
.secao { padding-block: var(--respiro); }

/* --- cabeçalho ----------------------------------------------------------- */
.cabecalho {
  position: absolute; z-index: 100; top: 0; left: 0; width: 100%;
  transition: box-shadow 260ms ease;
}
/* O fundo mora num pseudo-elemento: `backdrop-filter` no próprio header o
   transformaria em bloco de contenção, e o painel `position: fixed` do menu
   mobile passaria a ser posicionado em relação a ele, esticando o documento. */
.cabecalho::before {
  position: absolute; z-index: -1; inset: 0; content: "";
  background: transparent; backdrop-filter: blur(10px);
  border-bottom: 1px solid transparent;
  transition: background 260ms ease, border-color 260ms ease;
}
.cabecalho.rolou { position: fixed; }
.cabecalho.rolou::before {
  background: color-mix(in srgb, var(--azul) 86%, transparent); border-bottom-color: var(--fio);
}
.cabecalho__inner {
  max-width: var(--largura); margin-inline: auto; padding: 0 var(--margem);
  height: var(--altura); display: flex; align-items: center; gap: 2rem;
}
.marca { display: flex; align-items: center; gap: 0.7rem; margin-right: auto; }
.marca img { width: 40px; height: 40px; border-radius: 50%; }
.marca b { font-family: var(--fonte-display); font-size: 1.3rem; font-weight: 700; letter-spacing: -0.01em; }
.marca small { display: block; font-size: 0.6rem; letter-spacing: 0.19em; text-transform: uppercase; color: var(--creme-fr); }
.menu { display: flex; gap: 1.9rem; }
.menu a { position: relative; font-size: 0.83rem; font-weight: 500; padding-block: 0.35rem; }
.menu a::after {
  position: absolute; right: 0; bottom: 0; left: 0; height: 1px; content: "";
  background: var(--dourado); transform: scaleX(0); transform-origin: right;
  transition: transform 280ms var(--curva);
}
.menu a:hover::after, .menu a:focus-visible::after { transform: scaleX(1); transform-origin: left; }

/* Menu suspenso (Sabores e Eventos). Abre com hover e com foco de teclado; Esc
   fecha (script.js). O painel usa a mesma "vitrine" clara dos cards de produto,
   com tinta escura por cima: contraste alto sem introduzir cor nova. */
.menu { align-items: center; }
.menu-item { position: relative; }
.menu-item > a { display: block; }
.menu-drop {
  position: absolute; z-index: 110; top: 100%; left: -1.1rem; min-width: 15.5rem;
  margin-top: 0.7rem; padding: 0.55rem; display: grid; gap: 0.1rem;
  background: var(--vitrine); color: var(--tinta); border-radius: var(--raio);
  box-shadow: 0 18px 40px -12px color-mix(in srgb, #000 55%, transparent);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity 200ms ease, transform 260ms var(--curva), visibility 0s 200ms;
}
/* Ponte invisível sobre a folga entre o link e o painel, para o hover não cair. */
.menu-drop::before { position: absolute; right: 0; bottom: 100%; left: 0; height: 0.9rem; content: ""; }
.menu-item:hover .menu-drop, .menu-item:focus-within .menu-drop {
  opacity: 1; visibility: visible; transform: none; transition-delay: 0s;
}
.menu .menu-drop a {
  display: block; padding: 0.7rem 0.95rem; border-radius: 8px;
  font-size: 0.84rem; font-weight: 600; color: var(--tinta);
  transition: background 160ms ease, box-shadow 160ms ease;
}
.menu .menu-drop a::after { display: none; }
.menu .menu-drop a:hover, .menu .menu-drop a:focus-visible {
  background: color-mix(in srgb, var(--amarelo) 24%, var(--vitrine));
  box-shadow: inset 3px 0 0 var(--amarelo);
}
.menu .menu-drop .menu-drop__todos {
  margin-top: 0.45rem; border-radius: 0 0 8px 8px;
  border-top: 1px solid color-mix(in srgb, var(--tinta) 16%, transparent);
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
}
.menu-movel__sub { display: grid; padding: 0.3rem 0 0.7rem 1rem; border-bottom: 1px solid var(--fio); }
.menu-movel .menu-movel__sub a {
  border: 0; padding-block: 0.5rem; font-family: var(--fonte-corpo);
  font-size: 1.05rem; font-weight: 500; color: var(--creme-md);
}
@media (prefers-reduced-motion: reduce) {
  .menu-drop { transition: none; transform: none; }
}
.cabecalho .btn { min-height: 44px; padding: 0.6rem 1.15rem; font-size: 0.72rem; }
.hamburguer {
  display: none; width: 44px; height: 44px; padding: 0; border: 1px solid var(--fio-forte);
  border-radius: var(--raio); background: transparent; cursor: pointer;
  flex-direction: column; align-items: center; justify-content: center; gap: 5px;
}
.hamburguer i { display: block; width: 17px; height: 1px; background: currentColor; transition: transform 240ms var(--curva), opacity 200ms; }
.cabecalho.aberto .hamburguer i:first-child { transform: translateY(3px) rotate(45deg); }
.cabecalho.aberto .hamburguer i:last-child { transform: translateY(-3px) rotate(-45deg); }
.menu-movel {
  position: fixed; z-index: 90; inset: var(--altura) 0 0; display: grid;
  align-content: start; gap: 0.2rem; padding: 2rem var(--margem);
  background: var(--azul); overflow-y: auto;
  transform: translateX(100%); visibility: hidden;
  transition: transform 380ms var(--curva), visibility 0s 380ms;
}
.cabecalho.aberto .menu-movel { transform: translateX(0); visibility: visible; transition-delay: 0s; }
.menu-movel a {
  font-family: var(--fonte-display); font-size: 1.9rem; font-weight: 500;
  padding-block: 0.75rem; border-bottom: 1px solid var(--fio);
}

/* --- hero ---------------------------------------------------------------- */
/* HERO EM DUAS FAIXAS, com banner rotativo.
   O Bruno pediu o rotativo em 10/09. Isso obrigou a tirar o texto de cima da
   foto: com uma imagem só dava para escolher uma com espaço vazio à esquerda,
   mas com cinco cada uma tem composição própria — na do morango o picolé está à
   esquerda, na do chocolate o pote fica no centro. Texto sobreposto só funciona
   quando TODAS têm o mesmo espaço negativo. Num bloco de cor ao lado, qualquer
   composição serve e a comida chega inteira. */
/* FOTO NA LARGURA TODA (pedido do Bruno em 11/09: "sem foto em tudo").
   O quadrado de produto não pode sangrar sozinho: num hero 2:1 ele seria
   escalado pela largura e perderia metade da altura — o picolé cortado de
   novo. Então as fotos do desktop são versões 2400x1200 montadas aqui mesmo
   (scripts de geração no histórico): o quadrado inteiro fica na METADE
   DIREITA, e a metade esquerda é a mesma foto ampliada e desfocada. O produto
   chega inteiro, e o lado do texto deixa de ser um retângulo de cor chapada.
   A altura também subiu: a 88vh/780px o hero terminava antes da dobra na tela
   dele e deixava uma tira da faixa seguinte aparecendo. */
.hero { position: relative; display: grid; grid-template-columns: minmax(0, 0.94fr) minmax(0, 1.06fr);
        min-height: min(96vh, 1000px); background: var(--azul); overflow: hidden; }
.hero__foto { grid-column: 1 / -1; grid-row: 1; position: relative; }
.hero__palco { position: absolute; inset: 0; }
/* Os cinco slides ficam empilhados; o crossfade é só opacidade, sem mexer no
   fluxo. `visibility` acompanha para o leitor de tela não anunciar cinco fotos. */
.hero__slide { position: absolute; inset: 0; margin: 0; opacity: 0; visibility: hidden; }
.hero__slide[data-ativo] { opacity: 1; visibility: visible; }
.js .hero__slide { transition: opacity var(--t-lento) var(--curva), visibility 0s var(--t-lento); }
.js .hero__slide[data-ativo] { transition: opacity var(--t-lento) var(--curva), visibility 0s 0s; }
.hero__slide picture { display: block; height: 100%; }
.hero__slide img { width: 100%; height: 100%; object-fit: cover; }
/* Sem JS nada some: a primeira aparece e as demais ficam fora do fluxo. */
.hero__veu {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    /* O texto exige fundo praticamente opaco: com 88% de azul sobre uma foto
       clara o lede cai para 4,3:1 e reprova. A coluna de texto termina em ~42%
       da largura (coluna do grid a 47%, menos a margem), então o véu fica
       sólido até 44% e só some em 66% — antes do produto, que nas fotos largas
       está centrado em 75%. Com a parada sólida em 36%, o véu já estava em
       ~86% onde a manchete terminava e o rótulo amarelo perdia o contraste. */
    linear-gradient(90deg,
      var(--azul) 0%, var(--azul) 44%,
      color-mix(in srgb, var(--azul) 72%, transparent) 56%,
      color-mix(in srgb, var(--azul) 26%, transparent) 62%,
      transparent 66%),
    /* chão para o menu: o cabeçalho é transparente no topo da página e a metade
       direita dele cai sobre a foto. Com banner rotativo não dá para contar com
       o fundo de UMA foto — a do morango é clara e engolia o texto branco. */
    linear-gradient(180deg, color-mix(in srgb, var(--azul) 66%, transparent) 0%,
                    color-mix(in srgb, var(--azul) 26%, transparent) 10%, transparent 19%);
}
.hero__conteudo { grid-column: 1; grid-row: 1; position: relative; z-index: 2; display: flex; align-items: center;
                  padding-block: clamp(3rem, 6vw, 4.5rem); padding-top: calc(var(--altura) + clamp(2rem, 4vw, 3rem)); }
/* Largura em rem, NUNCA em ch: `ch` resolve contra a fonte DESTE elemento, que
   herda o corpo de 16px, enquanto a headline dentro dele tem ~75px. Um `21ch`
   aqui virava uma coluna de 194px e quebrava o título uma palavra por linha. */
/* A manchete que o cliente escreveu é longa ("Picolé, sorvete e açaí direto da
   nossa fábrica, pertinho de você"). No corpo anterior ela quebrava em sete
   linhas de caixa alta e virava um paredão. Coluna um pouco mais larga e corpo
   menor trazem para quatro ou cinco linhas, sem perder o peso do Chubbo. */
.hero__texto { max-width: 38rem; }
/* Entrelinha 1,04 e não 0,94: em caixa alta o Chubbo já vem com ombro curto,
   e quatro linhas coladas viravam um bloco maciço. */
.hero .display-1 { margin-top: 1.35rem; font-size: clamp(1.95rem, 3.3vw, 3rem); line-height: 1.04; }
/* Creme cheio, não o creme a 85%: o chão do texto deixou de ser cor chapada
   e ganhou o desfoque da foto por baixo — o tom mais forte devolve a folga de
   contraste que a textura consome. */
.hero__lede { margin-top: 1.8rem; font-size: 1.02rem; line-height: 1.7; max-width: 40ch; color: var(--creme); }
.hero__acoes { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-top: 2.8rem; }

/* Pontos do banner: cantinho da foto, discretos — o hero já tem dois botões e
   não pode ganhar um terceiro ponto de disputa. */
/* Canto ESQUERDO: o direito é território fixo do botão do WhatsApp, que cobria
   os pontos em qualquer janela com menos de ~1050px de altura. */
.hero__pontos { position: absolute; z-index: 3; left: var(--margem); bottom: clamp(1rem, 2vw, 1.6rem);
                display: flex; gap: 1rem; }
.hero__pontos button {
  position: relative;
  width: 9px; height: 9px; padding: 0; border: 0; border-radius: 50%;
  background: var(--creme); opacity: 0.42; cursor: pointer;
  box-shadow: 0 1px 4px color-mix(in srgb, var(--tinta) 60%, transparent);
  transition: opacity 220ms, transform 220ms, background 220ms;
}
.hero__pontos button[aria-current="true"] { opacity: 1; background: var(--amarelo); transform: scale(1.3); }
/* Área de toque de 25px (WCAG 2.5.8) sem mudar o ponto visual de 9px. O vão de
   1rem entre os pontos impede que as áreas de dois vizinhos se sobreponham. */
.hero__pontos button::before, .trilho__pontos button::before { position: absolute; inset: -8px; content: ""; }

/* Prova logo abaixo do hero: fatos secos, sem card nem sombra. */
.fatos { border-block: 1px solid var(--fio); background: var(--azul-fundo); }
.fatos__grade {
  max-width: var(--largura); margin-inline: auto; padding-inline: var(--margem);
  display: grid; grid-template-columns: repeat(4, 1fr);
}
.fato { padding: 1.9rem 1.4rem 1.9rem 0; border-left: 1px solid var(--fio); padding-left: 1.4rem; }
.fato:first-child { border-left: 0; padding-left: 0; }
.fato b { display: block; font-family: var(--fonte-display); font-size: clamp(1.35rem, 2.3vw, 1.9rem); font-weight: 500; }
.fato span { display: block; margin-top: 0.35rem; font-size: 0.68rem; letter-spacing: 0.11em; text-transform: uppercase; color: var(--creme-fr); }

/* --- manifesto: o compasso lento da página -------------------------------- */
/* Respiro menor: o vão de antes era em cima e dos lados ao mesmo tempo. */
.manifesto { padding-block: clamp(4.5rem, 9vw, 8rem); }
/* A seção não tem imagem por decisão: entre o hero fotográfico e o palco de
   fotos da fábrica, uma pausa só de tipografia é o que devolve peso às fotos
   que vêm depois. O vão que o cliente viu em 11/09 sumiu porque a frase deixou
   de ser uma coluna estreita e passou a ocupar a largura inteira da faixa. */
.manifesto__frase {
  font-family: var(--fonte-display); font-weight: 700;
  /* Caixa alta como todo display do site: uma seção em caixa baixa leria como
     descuido, não como escolha. O que diferencia aqui é a escala e o vazio ao
     redor, não uma regra tipográfica à parte. */
  font-size: clamp(1.95rem, 5.9vw, 4.6rem); line-height: 0.94;
  letter-spacing: -0.012em; text-transform: uppercase; text-wrap: balance;
  margin: clamp(1rem, 2vw, 1.6rem) 0 0;
}
/* Palavra apagada é estado de script, nunca do HTML: sem JS a frase chega
   inteira. `opacity` e nada mais — cor animada repinta o texto a cada quadro. */
.js .manifesto__frase .palavra { opacity: 0.22; transition: opacity var(--t-base) var(--curva); }
.js .manifesto__frase .palavra--aceso { opacity: 1; }
.manifesto__frase .enfase { text-shadow: 0 0 48px color-mix(in srgb, var(--amarelo) 34%, transparent); }

/* Fio dourado: a assinatura rara da identidade, aqui como régua entre a frase
   e o corpo. Fino e esmaecendo — não é borda de caixa. */
.manifesto__fio { height: 1px; margin-top: clamp(2.4rem, 5vw, 4rem);
                  background: linear-gradient(90deg, var(--dourado), color-mix(in srgb, var(--dourado) 18%, transparent) 46%, transparent 78%); }

/* Corpo recuado à direita: a frase manda, o texto responde. Duas colunas
   curtas leem melhor que uma linha de 1240px de largura. */
.manifesto__colunas { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
                      gap: clamp(1.4rem, 3.5vw, 3.2rem); max-width: 58rem;
                      margin: clamp(2rem, 4vw, 3rem) 0 0 auto; }
.manifesto__colunas .lede { margin: 0; }

/* --- a fábrica: processo numerado + fotografia ---------------------------- */
.fabrica__grade { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: clamp(2.5rem, 6vw, 6rem); align-items: start; }
.fabrica__texto .display-2 { margin-top: 1rem; }
.fabrica__texto .lede { margin-top: 1.4rem; }
.passos { margin-top: 2.6rem; border-top: 1px solid var(--fio); }
/* Cada passo ocupa cerca de um terço de tela. Não é respiro decorativo: é o
   percurso de que o palco fixo precisa para grudar. Com o padding curto de
   antes, a coluna de texto media 1015px contra 646px de foto — o palco prendia
   por 369px e soltava antes de trocar a segunda imagem. */
.passo { display: grid; grid-template-columns: 2.9rem 1fr; gap: 1rem; align-content: center;
         min-height: clamp(190px, 27vh, 280px); padding: 1.6rem 0; border-bottom: 1px solid var(--fio); }
/* 27vh e não 32vh: encurtar um pouco o passo tira ~290px de vazio somado nos
   quatro e ainda deixa percurso de sobra para o palco fixo trocar a foto
   (a coluna de texto continua ~700px mais alta que a da imagem). */
/* Corpo maior sem mexer no percurso: o vão entre um passo e outro é o que o
   palco fixo usa para grudar, então a sensação de espaço solto se resolve
   enchendo melhor cada passo, não encurtando a distância entre eles. */
.passo i { font-family: var(--fonte-display); font-style: normal; font-weight: 700;
           font-size: 1.05rem; color: var(--amarelo-texto); }
.passo h3 { font-family: var(--fonte-display); font-size: clamp(1.2rem, 1.5vw, 1.45rem);
            font-weight: 500; margin-bottom: 0.45rem; }
.passo p { font-size: clamp(0.94rem, 1.05vw, 1.02rem); line-height: 1.62; color: var(--creme-md); }
.foto-quadro { position: relative; overflow: hidden; border-radius: var(--raio); background: var(--azul-fundo); }
/* O <picture> preenche o quadro por posicionamento absoluto, e nao por
   `height: 100%`: altura percentual so resolve quando o pai tem altura
   DEFINIDA, e este quadro e dimensionado por `min-height`. Com height:100% a
   foto parava na altura natural e sobrava um vao de fundo embaixo dela, com a
   legenda flutuando fora da imagem. */
.foto-quadro picture { position: absolute; inset: 0; height: auto; }
.foto-quadro img { width: 100%; height: 100%; object-fit: cover; transition: transform 1s var(--curva); }
.foto-quadro:hover img { transform: scale(1.03); }
/* Sem zoom na foto da fachada: o cliente pediu a imagem inteira, e um
   scale de 3% come exatamente as bordas que ele quer ver. */
.fabrica__grade .foto-quadro:hover img { transform: none; }
.foto-quadro figcaption {
  position: absolute; right: 0; bottom: 0; left: 0; padding: 2.5rem 1.4rem 1.2rem;
  background: linear-gradient(0deg, color-mix(in srgb, var(--azul) 92%, transparent), transparent);
  font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--creme-md);
}
/* --- palco fixo: a mídia gruda e troca junto com o texto -------------------
   É a mecânica que a Apple usa nas páginas de produto e o que dá o ar de
   "premium": em vez de foto e texto rolarem juntos, a foto para no lugar e
   TROCA conforme cada passo entra na leitura. Aqui ela sai de graça porque a
   seção já tinha quatro passos — cada um ganhou a sua imagem.

   `align-items: start` no grid é o que permite o sticky funcionar: com o
   `stretch` padrão a coluna teria a altura toda e não sobraria percurso. */
.fabrica__grade { align-items: start; }
.palco {
  position: sticky; top: calc(var(--altura) + 2rem);
  aspect-ratio: 4 / 5; border-radius: var(--raio); overflow: hidden;
  background: var(--azul-fundo);
}
.palco__foto { position: absolute; inset: 0; margin: 0; opacity: 0; visibility: hidden; }
.palco__foto[data-ativo] { opacity: 1; visibility: visible; }
.js .palco__foto { transition: opacity var(--t-lento) var(--curva), visibility 0s var(--t-lento),
                               transform var(--t-lento) var(--curva); transform: scale(1.04); }
.js .palco__foto[data-ativo] { transition: opacity var(--t-lento) var(--curva), visibility 0s 0s,
                               transform 1400ms var(--curva); transform: scale(1); }
.palco picture { display: block; height: 100%; }
.palco img { width: 100%; height: 100%; object-fit: cover; }
/* Cópia da foto dentro de cada passo (ver iniciarPalco): só aparece no celular. */
.passo > .palco__foto { display: none; }

/* O passo em leitura acende; os outros recuam. É o que amarra o texto à foto —
   sem isso a troca da imagem pareceria aleatória. */
/* Recuam só o número e o título. O parágrafo apagado a 42% media 2,05:1 contra
   o azul, ilegível; a hierarquia se mantém pelo número amarelo e pela foto. */
.js .passo i, .js .passo h3 { transition: opacity 420ms var(--curva); }
.js .passo:not([data-ativo]) i, .js .passo:not([data-ativo]) h3 { opacity: 0.42; }

/* --- vitrine: onde a página acende --------------------------------------- */
/* A fotografia de produto da Bliss é de estúdio, fundo branco. Num site escuro
   isso costuma ser tratado como problema; aqui é o recurso: cada painel claro
   é uma vitrine acesa, e a grade inteira lê como um freezer iluminado. */
.vitrine-cabeca { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: clamp(1.5rem, 5vw, 5rem); align-items: end; margin-bottom: clamp(2.5rem, 5vw, 4rem); }
/* Mesma gramática dos cards do catálogo: soltos, com canto macio e elevação no
   hover. A grade de 1px que havia aqui colava os quatro painéis numa tabela — e
   esta seção é justamente a porta de entrada do catálogo, então as duas
   precisam parecer a mesma coisa. */
.vitrine-grade { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(0.9rem, 1.6vw, 1.4rem); }
.vitrine-item {
  position: relative; display: flex; flex-direction: column; overflow: hidden;
  background: var(--azul-fundo); border: 1px solid var(--fio); border-radius: var(--raio);
  transition: transform 420ms var(--curva), box-shadow 420ms var(--curva), border-color 420ms var(--curva);
}
.vitrine-item:hover, .vitrine-item:focus-visible {
  transform: translateY(-6px); border-color: color-mix(in srgb, var(--amarelo) 55%, transparent);
  box-shadow: 0 22px 44px -20px color-mix(in srgb, var(--tinta) 82%, transparent);
}
/* Os quatro quadros SANGRAM (`cover`), sem respiro branco interno. Os dois
   packshots já foram normalizados em 4/3, a mesma razão do quadro, então cover
   não corta nada neles; as duas fotos de cena são retrato e ganham um corte que
   uma cena aguenta. Com `contain` a fileira ficava desigual — dois painéis
   brancos com o produto pequeno no meio, dois sangrando de ponta a ponta. */
.vitrine-item__luz { aspect-ratio: 4 / 3; overflow: hidden; background: var(--vitrine); }
.vitrine-item__luz img { width: 100%; height: 100%; object-fit: cover; transition: transform 700ms var(--curva); }
.vitrine-item:hover .vitrine-item__luz img { transform: scale(1.05); }
.vitrine-item__pe { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1.15rem 1.2rem 1.3rem; }
.vitrine-item__rot { display: block; }
.vitrine-item__pe h3 { font-family: var(--fonte-display); font-size: 1.25rem; font-weight: 500; color: var(--creme); }
/* Seletor no elemento certo: `.vitrine-item__pe span` alcançava também o span
   que embrulha o h3, e o título herdava a cor apagada do rótulo. */
.vitrine-item__sub { display: block; font-size: 0.65rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--creme-fr); }
.vitrine-item__seta { color: var(--amarelo-texto); font-size: 1.1rem; transition: transform 260ms var(--curva); }
.vitrine-item:hover .vitrine-item__seta { transform: translate(4px, -4px); }

/* --- onde a Bliss pode estar: quatro momentos --------------------------- */
/* "Na sua casa" é o único dos quatro títulos que cabe numa linha só, e ficava
   desalinhado dos vizinhos. A quebra é forçada aqui e desligada em coluna
   única (ver o media de 640px), onde não há vizinho com quem alinhar. */
/* Sem número, sem ícone, sem card com sombra: a lista é o conteúdo. Um filete
   à esquerda marca cada momento — é o mesmo recurso dos passos, o que mantém as
   duas listas da página falando a mesma língua. */
.momentos { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px;
            margin-top: clamp(2.5rem, 5vw, 3.5rem); background: var(--fio); }
.momento { padding: clamp(1.6rem, 2.4vw, 2.2rem) clamp(1.2rem, 2vw, 1.8rem); background: var(--azul); }
.momento h3 { color: var(--amarelo); }
.momento p { margin-top: 0.7rem; font-size: 0.92rem; color: var(--creme-md); }

/* --- convites: evento e representante ----------------------------------- */
.convites { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1.5rem, 3vw, 2.5rem); }
.convite { padding: clamp(1.8rem, 3vw, 2.6rem); border: 1px solid var(--fio); border-radius: var(--raio);
           background: var(--azul-fundo); }
.convite .display-3 { margin-top: 0.7rem; }
.convite .lede { margin-top: 1rem; font-size: 0.95rem; }
.convite .btn { margin-top: 1.6rem; }

/* --- eventos: coverflow ---------------------------------------------------
   Substitui a fila com scroll-snap que havia aqui. NÃO é um quarto movimento no
   contrato: é o mesmo movimento 3 (RESPONDER) — só acontece quando a pessoa
   arrasta, clica ou usa as setas, nunca sozinho.

   A matemática veio de um componente React que o Pablo trouxe; aqui ela roda em
   JS puro porque o site não tem build. O que a versão em React resolve e uma
   fila de CSS não: o giro e o recuo caem com a RAIZ da distância, então o
   segundo card ainda se lê em vez de fechar de lado.
   ------------------------------------------------------------------------- */
.eventos-cabeca { margin-bottom: 2.4rem; }
/* As setas ficam nas LATERAIS do carrossel, não no cabeçalho da seção: ali elas
   caem onde a mão já está indo e ganham a relação direta com o arco de fotos.
   z-index acima de 100 porque a capa central chega a esse valor em `pintar()`. */
.trilho-area { position: relative; }
.trilho-seta {
  position: absolute; top: 50%; z-index: 200; transform: translateY(-50%);
  display: grid; place-items: center;
  width: 52px; height: 52px; padding: 0;
  border: 1px solid color-mix(in srgb, var(--creme) 30%, transparent); border-radius: 50%;
  background: color-mix(in srgb, var(--tinta) 62%, transparent);
  color: var(--creme); font-size: 1.15rem; line-height: 1; cursor: pointer;
  transition: background 200ms var(--curva), color 200ms var(--curva),
              border-color 200ms var(--curva), transform 200ms var(--curva);
}
.trilho-seta:hover {
  background: var(--amarelo); color: var(--tinta); border-color: var(--amarelo);
  transform: translateY(-50%) scale(1.06);
}
.trilho-seta--ant { left: 0; }
.trilho-seta--prox { right: 0; }
/* Centro das CAPAS, não da área: os pontos ficam dentro de .trilho-area e
   empurravam o 50% uns 19px para baixo. */
.js .trilho-area { --capa: clamp(190px, 26vw, 330px); }
.js .trilho-seta { top: calc(var(--capa) * 1.25 / 2); }

/* Sem JS o bloco continua sendo uma fila que rola — nenhuma foto some. */
.trilho { display: flex; gap: 1rem; overflow-x: auto; padding-bottom: 1rem; scrollbar-width: none; }
.trilho::-webkit-scrollbar { display: none; }
.trilho figure { position: relative; flex: 0 0 min(78vw, 340px); overflow: hidden; border-radius: 18px; background: var(--azul-fundo); }
.trilho img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }

/* --- com JS: o palco 3D --- */
.js .trilho {
  display: block; position: relative; overflow: visible;
  height: calc(var(--capa) * 1.25);
  perspective: calc(var(--capa) * 3);
  cursor: grab; touch-action: pan-y; outline: none;
}
.js .trilho:active { cursor: grabbing; }
.js .trilho:focus-visible { outline: 2px solid var(--amarelo); outline-offset: 12px; }
/* O palco preserva a profundidade; sem isto o rotateY vira um achatamento. */
.js .trilho__palco { position: relative; height: 100%; transform-style: preserve-3d; user-select: none; }
.js .trilho figure {
  position: absolute; left: 50%; top: 0; flex: none;
  width: var(--capa); height: 100%;
  border-radius: 18px; overflow: hidden;
  box-shadow: 0 26px 60px -18px color-mix(in srgb, var(--tinta) 78%, transparent);
  will-change: transform, opacity;
}
.js .trilho picture { display: block; height: 100%; }
.js .trilho img { height: 100%; aspect-ratio: auto; }

/* A legenda só aparece no card do meio: nos vizinhos ela vem inclinada junto
   com a face e fica ilegível. Fica no próprio card, não num bloco separado,
   para o texto continuar dentro da figura quando o JS não roda. */
.trilho figcaption {
  position: absolute; right: 0; bottom: 0; left: 0; padding: 3.4rem 1.1rem 1.1rem;
  background: linear-gradient(0deg, color-mix(in srgb, var(--azul-fundo) 96%, transparent), transparent);
}
.js .trilho figcaption { opacity: 0; transition: opacity 320ms var(--curva); }
.js .trilho figure[data-ativo] figcaption { opacity: 1; }
.trilho figcaption em { display: block; font-style: normal; font-size: 0.63rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--amarelo-texto); margin-bottom: 0.35rem; }
.trilho figcaption b { font-weight: 500; font-size: 0.88rem; }

.trilho__pontos { display: flex; justify-content: center; gap: 1rem; margin-top: 1.8rem; }
.trilho__pontos button {
  position: relative;
  width: 9px; height: 9px; padding: 0; border: 0; border-radius: 50%;
  background: var(--creme); opacity: 0.3; cursor: pointer;
  transition: opacity 220ms, transform 220ms;
}
.trilho__pontos button[aria-current="true"] { opacity: 1; background: var(--amarelo); transform: scale(1.25); }

.patrocinio { display: flex; flex-wrap: wrap; align-items: center; gap: 0.9rem; margin-top: 2rem; padding-top: 1.6rem; border-top: 1px solid var(--fio); font-size: 0.78rem; color: var(--creme-fr); }
.patrocinio b { color: var(--creme); font-weight: 600; }

/* --- prova: nota do Google + mapa ---------------------------------------- */
.prova { background: var(--azul-fundo); }
.prova__grade { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
.notas { display: flex; flex-wrap: wrap; gap: 2.5rem; margin-top: 2.2rem; }
.nota b { display: block; font-family: var(--fonte-display); font-size: 2rem; font-weight: 500; color: var(--amarelo-texto); }
.nota span { font-size: 0.72rem; letter-spacing: 0.09em; text-transform: uppercase; color: var(--creme-fr); }
.mapa { position: relative; border-radius: var(--raio); overflow: hidden; border: 1px solid var(--fio); }
.mapa iframe { width: 100%; height: clamp(320px, 40vw, 440px); border: 0; filter: grayscale(1) invert(0.92) hue-rotate(190deg) contrast(0.86); }
.mapa__cartao { padding: 1.3rem 1.4rem; background: var(--azul); border-top: 1px solid var(--fio); }
.mapa__cartao small { display: block; font-size: 0.62rem; letter-spacing: 0.15em; text-transform: uppercase; color: var(--amarelo-texto); margin-bottom: 0.4rem; }
.mapa__cartao b { display: block; font-family: var(--fonte-display); font-size: 1.15rem; font-weight: 500; }
.mapa__cartao span { font-size: 0.8rem; color: var(--creme-fr); }

/* --- revenda ------------------------------------------------------------- */
.revenda__grade { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: clamp(2rem, 5vw, 5rem); align-items: center; }
.revenda__grade .foto-quadro { aspect-ratio: 3 / 4; }
.revenda__grade .display-2 { margin-top: 0.9rem; }
.revenda__grade .lede { margin-top: 1.2rem; }
.revenda__grade ul { display: grid; gap: 0.75rem; margin: 1.8rem 0 2.2rem; }
.revenda__grade li { position: relative; padding-left: 1.5rem; font-size: 0.9rem; color: var(--creme-md); }
.revenda__grade li::before { position: absolute; left: 0; top: 0.62em; width: 6px; height: 6px; border: 1px solid var(--dourado); border-radius: 50%; content: ""; }
.revenda__acoes { display: flex; flex-wrap: wrap; align-items: center; gap: 1.4rem; }

/* --- fechamento ---------------------------------------------------------- */
.fechamento { text-align: center; padding-block: clamp(6rem, 12vw, 11rem); border-top: 1px solid var(--fio); }
.fechamento .lede { margin-inline: auto; margin-top: 1.3rem; }
.fechamento__dados { display: flex; flex-wrap: wrap; justify-content: center; gap: 2.5rem; margin: 3rem 0; }
.fechamento__dados div { text-align: center; }
.fechamento__dados dt { font-size: 0.63rem; letter-spacing: 0.15em; text-transform: uppercase; color: var(--amarelo-texto); margin-bottom: 0.4rem; }
.fechamento__dados dd { font-size: 0.9rem; color: var(--creme-md); max-width: 30ch; }
.fechamento__acoes { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 1.4rem; }

/* --- rodapé -------------------------------------------------------------- */
.rodape { padding: 3rem var(--margem); border-top: 1px solid var(--fio); background: var(--azul-fundo); }
.rodape__inner { max-width: var(--largura); margin-inline: auto; display: flex; flex-wrap: wrap; align-items: center; gap: 1.5rem 2.5rem; }
.rodape nav { display: flex; flex-wrap: wrap; gap: 1.5rem; margin-left: auto; font-size: 0.82rem; }
.rodape nav a:hover { color: var(--amarelo-texto); }
.rodape small { flex-basis: 100%; font-size: 0.7rem; color: var(--creme-fr); }

/* --- botão flutuante do WhatsApp ----------------------------------------- */
.zap {
  position: fixed; z-index: 140; right: 1.1rem; bottom: 1.1rem;
  width: 56px; height: 56px; display: grid; place-items: center; border-radius: 50%;
  background: #23a559; color: #fff; box-shadow: 0 6px 22px rgba(0,0,0,.4);
  transition: transform 200ms var(--curva);
}
.zap:hover { transform: scale(1.06); }
/* Com o menu mobile aberto o círculo cobria o último item da lista. */
body:has(.cabecalho.aberto) .zap { display: none; }

/* ============================== CATÁLOGO ================================== */
.cat-topo { padding: calc(var(--altura) + clamp(4rem, 8vw, 7rem)) var(--margem) clamp(2.5rem, 4vw, 3.5rem); border-bottom: 1px solid var(--fio); }
.cat-topo__inner { max-width: var(--largura); margin-inline: auto; }
.cat-topo .lede { margin-top: 1.2rem; }
/* Frase de apoio do catálogo. `em` sem itálico: o Chubbo só tem peso normal e o
   navegador falsificaria a inclinação; o destaque é o amarelo, como em .enfase. */
.cat-frase {
  margin-top: 1.4rem; max-width: 22ch;
  font-family: var(--fonte-display); font-weight: 700; text-transform: uppercase;
  font-size: clamp(1.4rem, 2.6vw, 2.1rem); line-height: 1.02; letter-spacing: -0.008em;
}
.cat-frase em { font-style: normal; color: var(--amarelo); }
/* Fecho do catálogo: pergunta a quem não achou o produto. Três colunas no
   desktop (título · texto · botão), empilha no celular. */
.cat-fecho { padding: clamp(3.5rem, 7vw, 6rem) var(--margem); background: var(--azul-fundo); border-top: 1px solid var(--fio); }
.cat-fecho__inner {
  max-width: var(--largura); margin-inline: auto; display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) auto; align-items: center; gap: clamp(1.5rem, 4vw, 3.5rem);
}
.cat-fecho .display-3 { margin-top: 0.7rem; font-size: clamp(1.7rem, 3.4vw, 2.8rem); line-height: 0.98; }
@media (max-width: 900px) {
  .cat-fecho__inner { grid-template-columns: 1fr; justify-items: start; }
}
/* `top: var(--altura)` e não 0: no catálogo o cabeçalho é fixo, e uma barra
   pegajosa colada no topo da janela ficava metade escondida atrás dele — o
   campo de busca sumia por completo. */
.barra {
  position: sticky; top: var(--altura); z-index: 60; padding: 1rem var(--margem);
  background: var(--veu-forte); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--fio);
}
.barra__inner { max-width: var(--largura); margin-inline: auto; display: grid; gap: 0.8rem; }
.busca { position: relative; }
.busca input {
  width: 100%; padding: 0.85rem 1rem 0.85rem 2.6rem; border: 1px solid var(--fio-forte);
  border-radius: var(--raio); background: var(--creme-vidro); font-size: 0.9rem;
}
.busca input::placeholder { color: var(--creme-fr); }
.busca input:focus { border-color: var(--amarelo-texto); }
/* O "outline: none" que havia aqui vencia o :focus-visible global e o campo
   principal do catálogo ficava sem foco visível para quem navega por teclado. */
.busca input:focus-visible { outline: 2px solid var(--amarelo-texto); outline-offset: 2px; }
.busca svg { position: absolute; left: 0.9rem; top: 50%; transform: translateY(-50%); color: var(--creme-fr); }
.filtros { display: flex; gap: 0.4rem; overflow-x: auto; scrollbar-width: none; }
.filtros::-webkit-scrollbar { display: none; }
.filtros button {
  flex: 0 0 auto; padding: 0.55rem 0.95rem; border: 1px solid var(--fio-forte);
  border-radius: var(--raio); background: transparent; cursor: pointer;
  font-size: 0.74rem; font-weight: 600; white-space: nowrap;
  transition: background 200ms, color 200ms, border-color 200ms;
}
.filtros button:hover { border-color: var(--creme); }
.filtros button[aria-pressed="true"] { background: var(--amarelo); border-color: var(--amarelo); color: var(--tinta); }
.publico { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; font-size: 0.72rem; color: var(--creme-fr); }
.publico button {
  padding: 0.4rem 0.8rem; border: 1px solid var(--fio); border-radius: var(--raio);
  background: transparent; cursor: pointer; font-size: 0.72rem; font-weight: 600;
}
.publico button[aria-pressed="true"] { border-color: var(--amarelo); color: var(--amarelo-texto); }

.cat-resultados { padding: clamp(2rem, 4vw, 3rem) var(--margem) var(--respiro); min-height: 70vh; }
.cat-resultados__inner { max-width: var(--largura); margin-inline: auto; }
.cat-contagem { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: 1.6rem; font-size: 0.76rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--creme-fr); }
/* Catálogo em cards soltos, não em tabela colada. A grade de 1px que havia aqui
   dava ar de planilha; com espaço entre os cards cada produto vira um objeto e a
   página respira — é o que separa uma listagem de um catálogo. */
.cat-grade { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(0.9rem, 1.6vw, 1.4rem); }
.cartao {
  position: relative; display: flex; flex-direction: column; overflow: hidden;
  background: var(--azul-fundo); text-align: left; border: 1px solid var(--fio);
  border-radius: var(--raio); padding: 0; cursor: pointer;
  transition: transform 420ms var(--curva), box-shadow 420ms var(--curva), border-color 420ms var(--curva);
}
/* O card sobe um pouco e ganha sombra: a mesma gramática do coverflow, que já
   usa profundidade para dizer "isto é um objeto que responde". */
.cartao:hover, .cartao:focus-within {
  transform: translateY(-6px); border-color: color-mix(in srgb, var(--amarelo) 55%, transparent);
  box-shadow: 0 22px 44px -20px color-mix(in srgb, var(--tinta) 82%, transparent);
}
/* Entrada escalonada ao filtrar: os cards chegam em cascata em vez de piscarem
   todos juntos. O atraso é calculado no JS por posição na grade. */
.js .cartao { animation: cartao-entra 520ms var(--curva) both; animation-delay: var(--atraso, 0ms); }
@keyframes cartao-entra { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .js .cartao { animation: none; }
}
.cartao__luz { aspect-ratio: 4 / 3; display: grid; place-items: center; padding: 1rem; background: var(--vitrine); overflow: hidden; }
.cartao__luz img { width: 100%; height: 100%; object-fit: contain; transition: transform 620ms var(--curva); }
.cartao__luz img.cena { object-fit: cover; }
.cartao:hover .cartao__luz img { transform: scale(1.05); }
/* Produto sem foto própria recebe cartão tipográfico em vez de emprestar a foto
   de outro sabor — decisão registrada em lista-fotos-para-produzir.md. */
.cartao__semfoto { display: grid; place-items: center; gap: 0.4rem; width: 100%; height: 100%; background: var(--vitrine); color: var(--vitrine-tinta); }
.cartao__semfoto b { font-family: var(--fonte-display); font-size: 1.5rem; font-weight: 500; }
.cartao__semfoto span { font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase; opacity: 0.8; }
.cartao__corpo { display: flex; flex-direction: column; gap: 0.4rem; padding: 1.1rem 1.15rem 1.3rem; flex: 1; }
.cartao__tag { font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--amarelo-texto); }
.cartao h3 { font-family: var(--fonte-display); font-size: 1.15rem; font-weight: 500; line-height: 1.12; }
/* A ação do card é o botão dentro do título; o ::after estica a área clicável
   sobre o card inteiro, e o anel de foco vai para o card. */
.cartao__abrir { padding: 0; border: 0; background: none; text-align: left; line-height: inherit; cursor: pointer; }
.cartao__abrir::after { position: absolute; inset: 0; z-index: 1; content: ""; }
@supports selector(:has(*)) { .cartao__abrir:focus-visible { outline: none; } }
.cartao:has(.cartao__abrir:focus-visible) { outline: 2px solid var(--dourado); outline-offset: 3px; }
.cartao__desc { font-size: 0.78rem; color: var(--creme-fr); }
.cartao__preco { margin-top: auto; padding-top: 0.7rem; font-size: 0.82rem; font-weight: 600; }
.cartao__preco small { display: block; font-size: 0.62rem; font-weight: 400; letter-spacing: 0.1em; text-transform: uppercase; color: var(--creme-fr); }
.cat-vazio { padding: 4rem 0; text-align: center; }
.cat-vazio p { color: var(--creme-md); }
.cat-noscript { display: grid; gap: 1.6rem; justify-items: start; }
.cat-noscript ul { display: grid; gap: 0.5rem; }
.cat-noscript li { font-size: 0.9rem; color: var(--creme-md); }

/* diálogo de produto */
.dialogo { position: relative; width: min(920px, 94vw); padding: 0; border: 1px solid var(--fio-forte); border-radius: var(--raio); background: var(--azul); color: var(--creme); }
.dialogo::backdrop { background: var(--veu-modal); backdrop-filter: blur(4px); }
.dialogo__grade { display: grid; grid-template-columns: 1fr 1fr; }
.dialogo__luz { display: grid; place-items: center; padding: 2rem; background: var(--vitrine); min-height: 320px; }
.dialogo__luz img { max-height: 340px; width: auto; object-fit: contain; }
.dialogo__corpo { padding: clamp(1.5rem, 3vw, 2.4rem); }
.dialogo__corpo h2 { font-family: var(--fonte-display); font-size: clamp(1.8rem, 3vw, 2.4rem); font-weight: 500; line-height: 1.02; margin: 0.6rem 0 0.8rem; }
.dialogo__variantes { display: grid; gap: 0.4rem; margin: 1.4rem 0; max-height: 240px; overflow-y: auto; }
.dialogo__variantes label { display: flex; align-items: center; gap: 0.7rem; padding: 0.7rem 0.85rem; border: 1px solid var(--fio); border-radius: var(--raio); font-size: 0.82rem; cursor: pointer; }
.dialogo__variantes label:has(input:checked) { border-color: var(--dourado); background: var(--ouro-fraco); }
.dialogo__variantes input { accent-color: var(--amarelo-texto); }
.dialogo__fechar { position: absolute; top: 0.8rem; right: 0.8rem; z-index: 2; width: 40px; height: 40px; border: 1px solid var(--fio-forte); border-radius: var(--raio); background: var(--veu-medio); cursor: pointer; }
.dialogo .btn { width: 100%; }
.dialogo__nota { margin-top: 0.9rem; font-size: 0.68rem; color: var(--creme-fr); }

/* ============================== MOTION ==================================== */
/* Estado escondido aplicado por JS: sem script, ou com "reduzir movimento"
   ligado, a página chega inteira visível. Só opacity e transform. */
.js [data-rev] { --d: var(--t-base); --y: 26px; }
/* Foto entra subindo E abrindo de um leve zoom. É o mesmo recurso das páginas
   de produto da Apple: a imagem "assenta" no lugar em vez de aparecer. O zoom é
   de 4% — acima disso vira efeito, e o cliente já reprovou motion chamativo. */
.js [data-rev="media"] { --d: var(--t-lento); --y: 34px; }
.js [data-rev="media"].rev-pend img { transform: scale(1.04); }
.js [data-rev="media"] img { transition: transform 1200ms var(--curva); }
.js [data-rev="media"].rev-in img { transform: scale(1); }
.js [data-rev="quieto"] { --d: var(--t-lento); --y: 10px; }
.js [data-rev].rev-pend { opacity: 0.01; transform: translateY(var(--y)); }
.js [data-rev].rev-in { opacity: 1; transform: none; transition: opacity var(--d) var(--curva), transform var(--d) var(--curva); }
.js [data-rev-grupo] { --d: var(--t-base); --y: 20px; --passo: 80ms; }
.js [data-rev-grupo].rev-pend > * { opacity: 0.01; transform: translateY(var(--y)); }
.js [data-rev-grupo].rev-in > * { opacity: 1; transform: none; transition: opacity var(--d) var(--curva), transform var(--d) var(--curva); }
.js [data-rev-grupo].rev-in > *:nth-child(2) { transition-delay: var(--passo); }
.js [data-rev-grupo].rev-in > *:nth-child(3) { transition-delay: calc(var(--passo) * 2); }
.js [data-rev-grupo].rev-in > *:nth-child(4) { transition-delay: calc(var(--passo) * 3); }
.js [data-rev-grupo].rev-in > *:nth-child(5) { transition-delay: calc(var(--passo) * 4); }
/* Entrada do hero: o único movimento que roda sem a pessoa pedir, e por isso o
   mais curto da página. Não toca na foto — ela é o LCP e aparece pintada. */
.js .hero__texto { --d: var(--t-rapido); --y: 14px; --passo: 90ms; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important; scroll-behavior: auto !important;
  }
}

/* ============================== RESPONSIVO ================================ */
@media (max-width: 1080px) {
  .vitrine-grade, .cat-grade { grid-template-columns: repeat(3, 1fr); }
  .fatos__grade { grid-template-columns: repeat(2, 1fr); }
  .fato:nth-child(3) { border-left: 0; padding-left: 0; }
}

@media (max-width: 900px) {
  .menu, .cabecalho__inner > .btn { display: none; }
  .hamburguer { display: flex; }
  /* A foto começa ABAIXO do cabeçalho. Sangrando por baixo dele, o topo da taça
     ficava escondido atrás da barra — a fruta cortada de novo. Aqui o cabeçalho
     ganha chão escuro próprio e a fotografia aparece inteira. */
  .hero { min-height: 0; height: auto; display: block; padding-top: var(--altura); }
  .hero__foto { position: relative; inset: auto; aspect-ratio: 1 / 1; }
  .hero__palco { position: absolute; inset: 0; }
  /* No celular o véu quase desaparece. O texto vem ABAIXO da foto e o cabeçalho
     fica sobre azul sólido (a foto começa depois dele), então não há nada para
     proteger — e o véu que existia aqui lavava a comida de azul, que é o oposto
     do que o cliente pediu. Sobra uma dissolução curta na base, só para a
     imagem não terminar num corte reto contra o fundo. */
  .hero__veu {
    background: linear-gradient(0deg, var(--azul) 0%,
                color-mix(in srgb, var(--azul) 34%, transparent) 6%, transparent 16%);
  }
  .hero__conteudo { padding: 0 0 clamp(2.5rem, 8vw, 3.5rem); margin-top: 0; }
  .hero .display-1 { font-size: clamp(2.1rem, 8.6vw, 2.9rem); }
  /* No celular os botões sobem para antes do lede: com a foto quadrada e o
     título em quatro linhas, o CTA caía abaixo da dobra e a primeira tela não
     tinha nenhuma ação. A foto não foi recortada — o cliente já reprovou foto
     cortada. */
  .hero__texto { max-width: none; display: flex; flex-direction: column; }
  .hero__lede { order: 1; }
  .hero__acoes { margin-top: 1.6rem; }
  .fabrica__grade, .prova__grade, .revenda__grade, .vitrine-cabeca { grid-template-columns: 1fr; }
  .manifesto__colunas { grid-template-columns: 1fr; margin-left: 0; }
  .momentos { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .convites { grid-template-columns: 1fr; }
  /* No celular cada passo mostra a sua cópia da foto (ver iniciarPalco) e o
     palco some. Em coluna única o palco caía depois dos quatro textos, e quem
     rolava só chegava nele com a quarta foto no ar — foi o que o cliente viu em
     11/09. O palco não sai mais do DOM: girar um tablet de retrato para
     paisagem volta a mostrá-lo, em vez de empilhar as fotos sobre o texto. */
  .palco { display: none; }
  /* 4:5, a proporção nativa dos arquivos: em 4:3 o recorte pegava uma faixa do
     meio e a máquina virava um emaranhado de canos. O cliente já reclamou de
     foto cortada uma vez — aqui não se corta nada. */
  .passo > .palco__foto { display: block; position: relative; grid-column: 1 / -1; margin-top: 1.1rem;
                        aspect-ratio: 4 / 5; border-radius: var(--raio); overflow: hidden;
                        opacity: 1; visibility: visible; transform: none; }
  /* As regras de preenchimento eram `.palco picture`/`.palco img`; fora do
     palco a imagem voltava a valer a altura do atributo (1250px) e o quadro
     mostrava só a tira de cima. */
  .passo .palco__foto picture { display: block; height: 100%; }
  .passo .palco__foto img { width: 100%; height: 100%; object-fit: cover; }
  .passo { min-height: 0; }
  .js .passo:not([data-ativo]) i, .js .passo:not([data-ativo]) h3 { opacity: 1; }
  .revenda__grade { gap: 2rem; }
  .revenda__grade .foto-quadro { aspect-ratio: 4 / 3; }
  .dialogo__grade { grid-template-columns: 1fr; }
  .dialogo__luz { min-height: 220px; max-height: 34vh; }
}

@media (max-width: 640px) {
  .vitrine-grade, .cat-grade { grid-template-columns: repeat(2, 1fr); }
  .momentos { grid-template-columns: 1fr; }
  /* Em coluna única o título tem largura de sobra: a quebra forçada viraria
     um degrau solto. Só `display: none` desliga um <br> (`inline` já é o
     padrão dele e não mudava nada); o espaço entre as palavras vem do HTML. */
  .quebra-larga { display: none; }
  .fatos__grade { grid-template-columns: 1fr; }
  .fato { border-left: 0; padding-left: 0; border-top: 1px solid var(--fio); padding-block: 1.3rem; }
  .fato:first-child { border-top: 0; }
  .hero__acoes .btn { width: 100%; }
  .fechamento__dados { gap: 1.8rem; }
  .rodape nav { margin-left: 0; }
  .cartao__desc { display: none; }
  .trilho figure { flex-basis: 84vw; }              /* só no fallback sem JS */
  .trilho-seta { width: 44px; height: 44px; font-size: 1rem; }
  .trilho-seta--ant { left: -0.4rem; }
  .trilho-seta--prox { right: -0.4rem; }
  .js .trilho-area { --capa: clamp(180px, 62vw, 260px); }
}
