/* Yanca Perfumaria, sistema visual "A Roseta".
   A malha girih é a estrutura da página, nunca enfeite sobre ela.
   Fundo branco, tinta quase preta, verde profundo como cor da casa e bronze
   como única brasa. Display em didone de verdade, interface em grotesca. */

:root {
  /* ---------- COR ----------
     Marfim sustenta a página, tinta sustenta a autoridade comercial, e o
     verde virou assinatura: ele aparece uma vez, com intenção, em vez de
     voltar como fundo a cada duas seções. Bronze e rosa são brasa, não
     material de construção.

     Proporção de área pretendida: marfim 55, tinta 20, garrafa 15, taupe 7,
     bronze e rosa 3.

     Todo valor de cor da loja nasce aqui. Hexadecimal solto no meio de uma
     regra é como a paleta apodrece: um dia alguém ajusta o token e metade
     da página não acompanha. */
  --marfim: #f7f4ef;          /* o fundo da loja */
  --branco: #ffffff;          /* o cartão, e só ele */
  --taupe: #e7e0d7;           /* o poço da foto, e superfície de apoio */
  --taupe-fundo: #ddd4c8;
  --tinta: #141215;           /* preto quente: tipografia, painel, ação */
  --garrafa: #123b33;         /* o verde da casa, em dose única */

  --texto: #1a1819;
  /* Medido contra a superfície clara mais escura da paleta, que é o taupe
     fundo da faixa de kits: 6.50 no marfim, 5.44 no taupe, 4.86 no taupe
     fundo. Estava em #66605c, que passava nos dois primeiros e reprovava no
     terceiro, com 4.22. Continua a 2.48 de distância do texto principal, que
     é o bastante para ler como secundário. */
  --texto-2: #5c5754;
  --sobre-escuro: #f7f4ef;
  --sobre-escuro-2: rgba(247, 244, 239, 0.76);

  /* O bronze de referência reprova como texto sobre marfim, 3.43. Fica para
     fio, foco e detalhe, onde 3:1 basta. Para texto e para botão existe o
     bronze escuro, medido em 4.57 nos dois sentidos. */
  --bronze: #a97a4f;
  /* Estava em #8f6743, medido só contra o marfim, onde dava 4.57. Só que ele
     também cai em taupe e em taupe fundo, e lá dava 3.83 e 3.42: reprovava nas
     duas superfícies mais escuras. Agora é medido contra a pior delas: 6.22 no
     marfim, 5.21 no taupe e 4.65 no taupe fundo. */
  --bronze-texto: #755436;
  --rosa: #d8b8b5;
  --erro: #9d2b2b;

  --fio: rgba(20, 18, 21, 0.1);
  --fio-forte: rgba(20, 18, 21, 0.26);
  --fio-claro: rgba(247, 244, 239, 0.22);

  --estrela: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 1000'><g fill='none' stroke='%23fff' stroke-width='5'><circle cx='500' cy='500' r='460'/><path d='M500 40 L730 101.63 L898.37 270 L960 500 L898.37 730 L730 898.37 L500 960 L270 898.37 L101.63 730 L40 500 L101.63 270 L270 101.63 Z'/><path d='M577.65 210.22 L712.13 287.87 L789.78 422.35 L789.78 577.65 L712.13 712.13 L577.65 789.78 L422.35 789.78 L287.87 712.13 L210.22 577.65 L210.22 422.35 L287.87 287.87 L422.35 210.22 Z'/><path d='M500 70 L715 872.39 L127.61 285 L930 500 L127.61 715 L715 127.61 L500 930 L285 127.61 L872.39 715 L70 500 L872.39 285 L285 872.39 Z'/></g></svg>");

  /* ---------- TIPOGRAFIA ----------
     Newsreader é serifada editorial desenhada para tela, com eixo óptico:
     ela cresce sem ficar frágil e encolhe sem fechar. Bodoni foi recusada
     por ser exatamente a revista antiga que não se quer, e Fraunces por
     puxar para o artesanal.

     DM Sans opera tudo que é funcional. Faixa de peso de 400 a 700, latin-ext
     para os acentos do português, e desenho geométrico com abertura humanista,
     que é o que segura preço e nome de produto em corpo pequeno.

     A display não pode cair em todo h2 e h3. Ela tem quatro endereços: o
     palco, a campanha, a frase institucional e o convite. */
  --face-display: 'Newsreader', 'Times New Roman', Georgia, serif;
  --face-corpo: 'DM Sans', system-ui, -apple-system, sans-serif;
  --face-leitura: 'DM Sans', system-ui, sans-serif;
  --face-medida: 'DM Sans', system-ui, sans-serif;

  /* Um token por papel, e nenhum título gigante só porque a tela cresceu:
     o teto de cada clamp é o tamanho em que aquele texto ainda serve. */
  --t-hero: clamp(31px, 4vw, 54px);
  --t-editorial: clamp(26px, 3vw, 40px);
  --t-prateleira: clamp(22px, 2.1vw, 29px);
  --t-bloco: clamp(19px, 1.7vw, 23px);
  --t-categoria: 16.5px;
  --t-produto: 15px;
  --t-preco: 19px;
  --t-parcela: 12.5px;
  --t-corpo: 16px;
  --t-apoio: 15px;
  --t-label: 11px;
  --t-cta: 12.5px;
  --t-rodape: 14px;
  --label-espaco: 0.14em;

  --peso-display: 400;
  --tracking-display: -0.018em;
  --entrelinha-display: 1.04;

  --largura: 1400px;
  --gutter: clamp(18px, 3.4vw, 48px);

  --ritmo: clamp(40px, 4.6vw, 64px);
  --ritmo-forte: clamp(56px, 6.2vw, 88px);
  --gap-cartao: 16px;

  --saida: cubic-bezier(0.16, 1, 0.3, 1);
}

/* Transição entre páginas. O navegador faz o cruzamento sozinho na navegação
   comum; quem não suporta simplesmente navega, sem quebrar nada. */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: sumir 0.28s ease both; }
  ::view-transition-new(root) { animation: surgir 0.42s var(--saida) both; }
}
@keyframes sumir { to { opacity: 0; } }
@keyframes surgir { from { opacity: 0; transform: translateY(14px); } }

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scrollbar-color: var(--fio-forte) var(--taupe); scrollbar-width: thin; }

body {
  margin: 0;
  background: var(--marfim);
  color: var(--texto);
  font-family: var(--face-corpo);
  font-size: var(--t-corpo);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

::selection { background: var(--rosa); color: var(--tinta); }
:where(input, textarea) { caret-color: var(--bronze); }
:focus-visible { outline: 2px solid var(--bronze); outline-offset: 2px; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: var(--taupe); }
::-webkit-scrollbar-thumb { background: var(--fio-forte); }
::-webkit-scrollbar-thumb:hover { background: var(--texto-2); }

/* ---------- acessibilidade ----------
   Visível só para leitor de tela. Sem clip-path a caixa de 1px ainda captura
   o cursor em parte dos navegadores. */
.so-leitor {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* Pular para o conteúdo. Fica fora da tela até receber foco, e só então desce.
   Sem ele, quem navega por teclado atravessa o letreiro, o menu inteiro e a
   busca antes de chegar na vitrine, em toda página. */
.pular {
  position: absolute; top: 0; left: var(--gutter); z-index: 95;
  transform: translateY(-120%);
  display: inline-flex; align-items: center; min-height: 44px;
  padding: 0 24px; background: var(--tinta); color: var(--marfim);
  font-size: 11px; font-weight: 600; letter-spacing: var(--label-espaco);
  text-transform: uppercase;
  transition: transform 0.3s var(--saida);
}
.pular:focus-visible { transform: translateY(0); }

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; }

/* O título nasce em sans. A serifada não pode cair sozinha em todo h2 e h3:
   foi assim que ela acabou em "Rosto", "Cabelo" e nos dois portais, onde não
   tem nada a dizer. Ela é convidada nome a nome, logo abaixo. */
h1, h2, h3, h4 {
  font-family: var(--face-corpo);
  font-optical-sizing: auto;
  font-weight: 600;
  letter-spacing: -0.028em;
  line-height: 1.08;
  text-wrap: balance;
  margin: 0;
}

/* Os quatro endereços da display, e nenhum a mais: o palco, a campanha, a
   frase da casa e o convite. São os momentos em que a loja fala por si; o
   resto da página é comércio, e comércio fala em sans. */
.cena__titulo,
#campanha-titulo,
#casa-titulo,
.convite__dizer h2 {
  font-family: var(--face-display);
  font-weight: var(--peso-display);
  font-optical-sizing: auto;
  letter-spacing: var(--tracking-display);
  line-height: var(--entrelinha-display);
}
.marca { font-weight: var(--peso-display); }

.envoltorio { max-width: var(--largura); margin-inline: auto; padding-inline: var(--gutter); }

/* ---------- medida ---------- */

.medida {
  font-family: var(--face-corpo);
  font-size: var(--t-label);
  font-weight: 500;
  letter-spacing: var(--label-espaco);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  color: var(--texto-2);
}
.preco { letter-spacing: -0.015em; font-weight: 600; font-feature-settings: "lnum" 1; }

/* Texto de leitura. Corpo maior, entrelinha mais solta e medida curta: serifa
   pede os três, e é isso que faz o parágrafo parecer escrito e não preenchido. */
.leitura {
  font-family: var(--face-leitura);
  font-optical-sizing: auto;
  font-size: 18px;
  line-height: 1.68;
  letter-spacing: 0.002em;
  max-width: 68ch;
} .faixa-kit p { font-family: var(--face-leitura); font-optical-sizing: auto; line-height: 1.62; }

/* ---------- amarração ---------- */

.amarracao { position: sticky; top: 0; z-index: 60; background: var(--marfim); }

/* A tarja recolhe por grid-template-rows, de 1fr para 0fr, e não por altura:
   animar height ou padding repagina a cada quadro justamente enquanto a pessoa
   rola, que é o pior momento possível para pedir recálculo de layout. */
.aviso-caixa { display: grid; grid-template-rows: 1fr; transition: grid-template-rows 0.45s var(--saida); background: var(--tinta); }
.amarracao.encolhida .aviso-caixa { grid-template-rows: 0fr; }
.aviso {
  background: var(--tinta); color: var(--taupe);
  text-align: center; padding: 9px 16px;
  overflow: hidden; min-height: 0;
}
.aviso .medida { color: rgba(247, 244, 239, 0.82); }

/* ---------- letreiro ----------
   A tarja deixa de ser texto parado e vira letreiro contínuo. É o único
   movimento permanente da página, e é ele que diz de longe que a loja está
   viva. Duas cópias idênticas correndo em sequência fazem o laço não ter
   emenda; a animação é translate puro, então roda na GPU. */
.aviso { display: flex; overflow: hidden; gap: 0; padding-inline: 0; }
/* O único lugar que sobrou para a monoespaçada. Num letreiro que corre, o
   passo igual entre as letras é o que dá o ritmo, e ali ela trabalha em vez
   de posar. */
.letreiro span { font-family: var(--face-medida); font-size: 10.5px; letter-spacing: 0.14em; }
.letreiro { display: flex; flex: none; align-items: center; gap: 44px; padding-right: 44px; white-space: nowrap; }
.letreiro span { display: inline-flex; align-items: center; gap: 12px; }
.letreiro span::after { content: '◆'; font-size: 7px; opacity: 0.55; }
@media (prefers-reduced-motion: no-preference) {
  /* O único lugar que sobrou para a monoespaçada. Num letreiro que corre, o
   passo igual entre as letras é o que dá o ritmo, e ali ela trabalha em vez
   de posar. */
.letreiro span { font-family: var(--face-medida); font-size: 10.5px; letter-spacing: 0.14em; }
.letreiro { animation: correr 38s linear infinite; }
  .aviso:hover /* O único lugar que sobrou para a monoespaçada. Num letreiro que corre, o
   passo igual entre as letras é o que dá o ritmo, e ali ela trabalha em vez
   de posar. */
.letreiro span { font-family: var(--face-medida); font-size: 10.5px; letter-spacing: 0.14em; }
.letreiro { animation-play-state: paused; }
}
@keyframes correr { to { transform: translateX(-100%); } }

/* O contador da sacola pula quando um item entra. */
@keyframes pular { 0%, 100% { transform: scale(1) } 35% { transform: scale(1.55) } }
.sacola__conta.pulando { animation: pular 0.5s var(--saida); }

.amarracao__barra {
  display: flex; align-items: center; gap: clamp(16px, 2.4vw, 36px);
  min-height: 78px; border-bottom: 1px solid var(--fio);
}

/* Assinatura em dois andares, como Sephora e Natura fazem: o nome grande e
   travado, a categoria miúda e muito espacejada embaixo. O espacejamento largo
   também resolve a leitura do nome próprio, que precisa soar YAN ca. */
.marca { display: flex; flex-direction: column; gap: 4px; line-height: 1; white-space: nowrap; }
/* A assinatura fica na sans, e de propósito: logotipo não é título. A
   serifada entrou para a voz editorial da loja, não para trocar a marca, e
   serifar a assinatura mudaria a identidade em vez de refiná-la. */
.marca__nome {
  font-family: var(--face-corpo);
  font-weight: 600; font-size: clamp(19px, 1.85vw, 26px);
  letter-spacing: 0.2em; text-transform: uppercase;
}
.marca__linha {
  font-family: var(--face-corpo); font-size: 11px;
  letter-spacing: 0.34em; text-transform: uppercase; color: var(--texto-2);
}
.rodape .marca__linha { color: rgba(247, 244, 239, 0.6); }

/* ---------- setas dos trilhos ---------- */
.trilho-caixa { position: relative; }
/* As setas saíram de cima do produto. Dentro do trilho elas sempre cobriam
   alguma coisa, porque o trilho ocupa a largura inteira do contêiner e não
   sobra margem onde pousar. No cabeçalho ficam livres, acessíveis e
   alinhadas com a vitrine que comandam. */
.secao__setas { display: flex; gap: 6px; flex: none; }
.seta {
  position: static; z-index: 5;
  width: 46px; height: 46px; display: grid; place-items: center;
  background: var(--branco); border: 1px solid var(--tinta); color: var(--tinta);
  cursor: pointer; transition: background 0.3s ease, color 0.3s ease, opacity 0.3s ease;
}
.seta:hover { background: var(--tinta); color: var(--taupe); }
.seta[disabled] { opacity: 0.25; cursor: default; }
.seta--esq { left: -23px; }
.seta--dir { right: -23px; }
.seta svg { width: 18px; height: 18px; stroke: currentColor; stroke-width: 1.6; fill: none; }
@media (max-width: 1100px) { .seta { display: none; } }

/* ---------- pagamentos no rodapé ---------- */
.pagamentos { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.pagamento {
  border: 1px solid rgba(247, 244, 239, 0.28); padding: 7px 11px;
  font-family: var(--face-corpo); font-size: 11px; letter-spacing: 0.11em; text-transform: uppercase;
  color: rgba(247, 244, 239, 0.78);
}

.navegacao { display: flex; gap: clamp(14px, 1.8vw, 28px); }
.navegacao a {
  font-family: var(--face-corpo); font-size: 11.5px;
  letter-spacing: 0.12em; text-transform: uppercase;
  padding-block: 8px; position: relative;
}
.navegacao a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1.5px;
  background: var(--bronze); transform: scaleX(0); transform-origin: left;
  transition: transform 0.5s var(--saida);
}
.navegacao a:hover::after, .navegacao a[aria-current]::after { transform: scaleX(1); }

.busca { margin-inline: auto; flex: 1 1 240px; max-width: 360px; position: relative; }
/* A caixa de busca era o elemento mais pesado do cabeçalho: retângulo cheio,
   borda em toda a volta, do tamanho da assinatura. Vira campo de papel, sem
   contorno, e só ganha traço quando recebe o cursor ou o foco. Menos moldura
   é a mesma regra que já vale nos cartões. */
.busca input {
  width: 100%; border: 0; border-bottom: 1px solid transparent; background: var(--taupe);
  padding: 12px 14px 12px 40px; font-family: var(--face-corpo); font-size: 14px; color: var(--tinta);
  transition: background 0.3s ease, border-color 0.3s ease;
}
.busca input:hover { background: var(--taupe); }
.busca input:focus { background: var(--branco); border-bottom-color: var(--tinta); outline: none; }
.busca input:focus-visible { outline: 2px solid var(--bronze); outline-offset: 1px; }
.busca input::placeholder { color: var(--texto-2); }
.busca svg { position: absolute; left: 13px; top: 50%; translate: 0 -50%; width: 17px; height: 17px; stroke: var(--texto-2); stroke-width: 1.5; fill: none; }

.ferramentas { display: flex; gap: 2px; align-items: center; }
.ferramenta { display: grid; place-items: center; width: 40px; height: 40px; border: 1px solid transparent; background: none; color: inherit; cursor: pointer; transition: border-color 0.3s ease; }
.ferramenta:hover { border-color: var(--fio-forte); }
.ferramenta svg { width: 19px; height: 19px; stroke: currentColor; stroke-width: 1.4; fill: none; }
.sacola { position: relative; }
.sacola__conta {
  position: absolute; top: 4px; right: 3px; min-width: 16px; height: 16px;
  display: grid; place-items: center; background: var(--tinta); color: var(--branco);
  font-family: var(--face-corpo); font-size: 11px; font-variant-numeric: tabular-nums;
}
.sacola__conta[hidden] { display: none; }

/* O painel da sacola segue a mesma construção da lista de idioma: ancorado no
   botão, fechado por padrão, fora do fluxo. Ele existe para o clique no ícone
   ter resposta, e para a nota sobre o fechamento do pedido ter onde morar. */
.sacola__painel {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 30;
  width: min(300px, calc(100vw - 32px));
  padding: 16px 18px; text-align: left;
  background: var(--branco); border: 1px solid var(--fio);
  box-shadow: 0 22px 40px -22px rgba(20, 18, 21, 0.45);
}
.sacola__painel[hidden] { display: none; }
.sacola__titulo { display: block; margin: 0 0 12px; color: var(--texto-2); }
.sacola__itens { margin: 0; padding: 0; list-style: none; display: grid; gap: 9px; }
.sacola__itens li {
  display: flex; gap: 12px; justify-content: space-between; align-items: baseline;
  font-family: var(--face-corpo); font-size: 14px; line-height: 1.4; color: var(--tinta);
}
.sacola__qtd { flex: none; color: var(--texto-2); font-variant-numeric: tabular-nums; }
.sacola__vazia { margin: 0; font-family: var(--face-corpo); font-size: 14px; color: var(--texto-2); }
.sacola__nota {
  margin: 14px 0 0; padding-top: 13px; border-top: 1px solid var(--fio);
  font-family: var(--face-corpo); font-size: 12.5px; line-height: 1.5; color: var(--texto-2);
}
.sacola__limpar {
  display: flex; align-items: center; justify-content: center;
  width: 100%; min-height: 44px; margin-top: 12px;
  background: none; border: 1px solid var(--fio-forte); cursor: pointer;
  font-family: var(--face-corpo); font-size: 11px; font-weight: 600;
  letter-spacing: var(--label-espaco); text-transform: uppercase; color: var(--tinta);
  transition: background 0.25s ease;
}
.sacola__limpar:hover { background: var(--taupe); }
.sacola__limpar[hidden] { display: none; }

/* ---------- ações ---------- */

/* ---------- CTA principal ----------
   Uma classe só para todo botão que é a ação principal da sua composição:
   palco, campanha, portais, kits, convite. O secundário tem classe própria e
   não entra aqui, e controle de carrossel, filtro e link de rodapé também não.

   O gesto: a seta nasce apagada e recolhida na folga que já está reservada à
   direita, e o texto repousa deslocado meia folga para a direita. No ponteiro
   e no foco o texto volta ao centro, andando cinco pixels, e a seta entra.
   Como a folga existe desde o repouso, nada muda de tamanho e a linha não
   salta. */
.acao {
  --folga: 10px;
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 0;
  min-height: 48px;
  background: var(--tinta); color: var(--sobre-escuro);
  font-family: var(--face-corpo); font-size: var(--t-cta); font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 14px 34px; border: 0; border-radius: 3px; cursor: pointer;
  transition: background 0.3s var(--saida), color 0.3s var(--saida);
}
.acao__texto {
  translate: calc(var(--folga) / 2) 0;
  transition: translate 0.3s var(--saida);
}
.acao__seta {
  width: var(--folga); display: grid; place-items: center;
  opacity: 0; translate: -7px 0;
  transition: opacity 0.3s var(--saida), translate 0.3s var(--saida);
}
.acao:hover .acao__texto,
.acao:focus-visible .acao__texto { translate: 0 0; }
.acao:hover .acao__seta,
.acao:focus-visible .acao__seta { opacity: 1; translate: 0 0; }

/* Sem ponteiro não existe hover, então a seta já nasce visível: esconder
   affordance atrás de um estado que o aparelho não tem é esconder e pronto. */
@media (hover: none) {
  .acao__texto { translate: 0 0; }
  .acao__seta { opacity: 1; translate: 0 0; }
}
@media (prefers-reduced-motion: reduce) {
  .acao__texto, .acao__seta { transition: none; }
  .acao__texto { translate: 0 0; }
  .acao__seta { opacity: 1; translate: 0 0; }
}
/* o brilho atravessa uma vez a cada passagem do cursor, não fica piscando */
.acao:hover { background: var(--garrafa); }
.acao--larga { width: 100%; }
.acao svg { width: 16px; height: 16px; stroke: currentColor; stroke-width: 1.7; fill: none; }

.acao-secundaria {
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  font-family: var(--face-corpo); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 17px 30px; border: 1px solid var(--tinta); background: none; color: var(--tinta); cursor: pointer;
  transition: background 0.35s var(--saida), color 0.35s var(--saida);
}
.acao-secundaria:hover { background: var(--tinta); color: var(--taupe); }
/* Ícone sem medida é ícone que ocupa o que sobrar. Aqui ele tem medida
   própria, e não depende de o pai continuar sendo flex. */
.acao-secundaria svg { width: 16px; height: 16px; flex: none; stroke: currentColor; stroke-width: 1.7; fill: none; }
.acao-secundaria .acao__seta { width: 16px; height: 16px; flex: none; }

/* ---------- benefícios ---------- */

/* Sem grade de tabela. Um fio só em cima, para encostar a faixa no banner,
   e o resto separado por espaço. Quatro células com borda dos quatro lados é
   planilha, não vitrine. */
.beneficios { display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid var(--fio); }
.beneficio { display: flex; gap: 11px; align-items: center; padding: 18px clamp(14px, 1.6vw, 24px); }

.beneficio svg { width: 17px; height: 17px; stroke: var(--tinta); stroke-width: 1.4; fill: none; flex: none; margin-top: 2px; }
.beneficio strong { display: block; font-size: 13px; font-weight: 600; letter-spacing: -0.005em; }
.beneficio span { font-size: 12px; color: var(--texto-2); }

/* ---------- seções ---------- */

.secao { padding-block: var(--ritmo); }
.secao--taupe { background: var(--taupe); }
.secao__cabeca { display: flex; align-items: center; justify-content: flex-start; gap: 16px; margin-bottom: 32px; }
/* Só o link de texto do cabeçalho. O botão de ação tem desenho próprio, e
   herdar sublinhado e padding daqui quebrava a caixa dele. */
.secao__cabeca a:not(.acao):not(.acao-secundaria) { border-bottom: 1px solid var(--fio-forte); padding-bottom: 3px; transition: border-color 0.3s ease, color 0.3s ease; }
.secao__cabeca a:not(.acao):not(.acao-secundaria):hover { border-color: var(--bronze); color: var(--bronze-texto); }

/* ---------- cartão de produto: moldura própria ---------- */

/* A barra de rolagem nativa fica escondida na vitrine. Ela é um controle de
   sistema, com aparência de sistema, e embaixo de uma fileira de perfume ela
   denuncia componente inacabado. A navegação continua inteira: arrasto no
   dedo, roda do mouse, setas e teclado. */
.trilho {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(208px, 1fr);
  gap: var(--gap-cartao); overflow-x: auto;
  padding-bottom: 4px;
  scrollbar-width: none;
}
.trilho::-webkit-scrollbar, .marcas::-webkit-scrollbar { width: 0; height: 0; display: none; }
.marcas { scrollbar-width: none; }
.trilho > * { scroll-snap-align: start; }
.grade { display: grid; grid-template-columns: repeat(auto-fill, minmax(208px, 1fr)); gap: var(--gap-cartao); }


/* O cartão inclina na direção do cursor. Os dois ângulos entram por variável,
   escritos pelo script, então o CSS continua dono da transição e da volta ao
   repouso. Sem cursor, e com movimento reduzido, ele só levanta. */
.peca {
  position: relative; display: flex; flex-direction: column;
  /* Sem borda. Num fundo de papel, o cartão branco já se destaca sozinho, e
     moldura em volta de tudo é o que faz vitrine parecer marketplace. */
  background: var(--branco);
  border: 1px solid transparent;
  padding: 11px 11px 15px;
  transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateZ(0);
  transition: border-color 0.45s var(--saida), box-shadow 0.45s var(--saida), transform 0.6s var(--saida);
}
.peca:hover {
  border-color: var(--fio);
  box-shadow: 0 26px 48px -28px rgba(20, 18, 21, 0.5);
  transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateY(-4px) translateZ(14px);
  transition-duration: 0.14s;
}

/* O reflexo é uma luz que segue o cursor sobre o vidro do ladrilho, não um
   gradiente decorativo: a posição vem do ponteiro e some quando ele sai. */
.peca__retrato::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 2;
  background: radial-gradient(
    circle at var(--luzx, 50%) var(--luzy, 50%),
    rgba(255, 255, 255, 0.55) 0%,
    rgba(255, 255, 255, 0.14) 26%,
    transparent 58%
  );
  opacity: 0; transition: opacity 0.4s var(--saida);
}
.peca:hover .peca__retrato::after { opacity: 1; }
@media (hover: none), (prefers-reduced-motion: reduce) {
  .peca__retrato::after { display: none; }
  .peca { transform: none; }
  .peca:hover { transform: translateY(-3px); }
}

/* Embalagem branca sobre fundo branco nao tem como ser recortada sem comer
   pedaco do produto, e o recorte recusa por isso. Sem recorte, o retangulo
   branco da foto aparece colado no meio do poco bege e parece defeito. Entao
   o poco inteiro fica branco nesses casos: sem emenda, e sem mentir a foto. */
.peca__retrato.peca__retrato--branco { background: var(--branco); }

.peca__retrato {
  position: relative; overflow: hidden;
  /* 3 por 4, em pé, e não quadrado. Numa moldura quadrada o frasco fica com
     metade da altura do cartão e a vitrine parece catálogo de atacado. Em pé
     ele ocupa quase três quartos, que é a proporção que as lojas de
     perfumaria usam porque é a forma do próprio produto. */
  background: var(--taupe); aspect-ratio: 3 / 4;
  display: grid; place-items: center; padding: 12px; margin-bottom: 12px;
}
/* A foto é posicionada, e não dimensionada por porcentagem. Altura em
   porcentagem contra um quadro de altura indefinida não resolve, a imagem
   volta ao tamanho natural e estoura o quadro: é assim que frasco de perfume
   aparece decepado em cima e embaixo numa vitrine.

   mix-blend-mode saiu junto: ele servia para fundir o fundo branco do JPEG
   antigo com o cartão. Com a foto recortada, ele só sujava as partes claras
   do frasco com a cor do fundo. */
.peca__retrato img {
  position: absolute; inset: 4px;
  width: calc(100% - 8px); height: calc(100% - 8px);
  object-fit: contain; object-position: center;
  transition: transform 0.9s var(--saida);
}
/* O zoom de 5,5% saiu: com o produto apoiado numa base, crescer a foto
   inteira arrasta a linha de apoio junto e o frasco perde o chão. O que
   substitui é o levantar, logo abaixo, que é menor e diz mais. */
.peca:hover .peca__retrato:not(.peca__retrato--apoiado) img { transform: scale(1.055); }

/* ---------- faixa de campanha ----------

   A imagem de campanha deixa de morar só no carrossel do topo. Medindo a
   página contra a referência, a nossa estava mais pálida e mais chapada:
   luminância 185 contra 156, variação de tom 65 contra 84, e metade das
   faixas escuras. A causa era estrutural, não de cor: um único momento de
   imagem forte e depois só prateleira sobre papel claro.

   A faixa é de largura total, usa a proporção da própria arte, e por isso
   não corta nem sobra, do mesmo jeito que o palco. */
.faixa-campanha {
  display: block; position: relative;
  width: 100%; overflow: hidden;
  aspect-ratio: var(--razao, 3 / 1);
  background: var(--fundo-faixa, var(--marfim));
}
.faixa-campanha__arte,
.faixa-campanha__arte img {
  display: block; width: 100%; height: 100%;
  object-fit: cover; object-position: center;
}
.faixa-campanha:focus-visible { outline: 3px solid var(--bronze); outline-offset: -6px; }

@media (max-width: 860px) {
  .faixa-campanha {
    aspect-ratio: var(--razao-pe, 1036 / 1519);
    background: var(--fundo-faixa-pe, var(--fundo-faixa, var(--marfim)));
  }
}

/* ---------- o produto apoiado ----------

   O recorte resolveu o fundo e criou outro problema: o frasco ficava
   flutuando. Objeto sem sombra de contato não parece fotografado, parece
   figura colada, e era essa a distância entre o cartão e as artes do palco.
   Não era resolução. Era luz.

   O reflexo está assado na imagem, porque ele pertence ao frasco e anda com
   ele. A sombra não: ela é desenhada aqui, porque sombra que anda junto com o
   objeto nunca deixa o objeto levantar. O compositor exporta duas medidas por
   produto, a largura da base e a altura em que ele apoia, e é delas que a
   elipse abaixo tira o tamanho. Sem isso a sombra de um roll-on de 10ml teria
   a largura da de um frasco de 200ml. */

.peca__retrato--apoiado::before {
  content: '';
  position: absolute;
  z-index: 0;
  left: 50%;
  top: var(--base-altura, 85%);
  width: var(--base-largura, 44%);
  height: calc(var(--base-largura, 44%) * 0.17);
  /* a sombra desliza para o lado oposto ao da luz: é esse desencontro que
     informa que existe uma fonte de luz e, portanto, um volume */
  translate: calc(-50% + var(--sombra-x, 0px)) -50%;
  background: radial-gradient(
    closest-side ellipse at 50% 50%,
    rgba(26, 22, 20, 0.42) 0%,
    rgba(26, 22, 20, 0.22) 46%,
    rgba(26, 22, 20, 0.07) 72%,
    transparent 100%
  );
  filter: blur(0.4px);
  /* Cresce por escala, e não por largura e altura. Animar medida obriga o
     navegador a refazer a conta de layout a cada quadro; escala é composta e
     não toca no layout de ninguém. */
  scale: 1;
  transform-origin: center;
  transition:
    scale 0.5s var(--saida),
    opacity 0.5s var(--saida),
    translate 0.5s var(--saida);
}

/* O poço deixa de ser cor chapada e vira superfície: a luz vem de cima e o
   chão escurece de leve onde o produto apoia. É o mínimo para a sombra ter
   onde cair. */
.peca__retrato--apoiado {
  background-image: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.5) 0%,
    rgba(255, 255, 255, 0) 52%,
    rgba(26, 22, 20, 0.05) 100%
  );
}

/* O momento autoral: a cliente chega perto e o frasco levanta da própria
   sombra. A sombra abre e clareia, porque sombra de objeto afastado do chão é
   maior e mais fraca. É o gesto de pegar um vidro da bancada, e só acontece
   num cartão por vez, sob o ponteiro. Nada se mexe no resto da página. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .peca:hover .peca__retrato--apoiado::before,
  .peca:focus-visible .peca__retrato--apoiado::before {
    scale: 1.26 1.16;
    opacity: 0.62;
  }
  .peca:hover .peca__retrato--apoiado img,
  .peca:focus-visible .peca__retrato--apoiado img {
    transform: translateY(-2.4%) scale(1.012);
  }
}

/* No toque não existe aproximar, existe tocar. Então o mesmo gesto acontece
   no toque: o frasco levanta enquanto o dedo está nele, e assenta ao soltar.
   É resposta ao toque, não enfeite, e por isso continua valendo com movimento
   reduzido, só mais curta. */
@media (hover: none) {
  .peca:active .peca__retrato--apoiado::before {
    scale: 1.22 1.12;
    opacity: 0.6;
  }
  .peca:active .peca__retrato--apoiado img { transform: translateY(-2%); }
}

@media (prefers-reduced-motion: reduce) {
  .peca__retrato--apoiado::before,
  .peca__retrato--apoiado img { transition-duration: 0.12s; }
}


/* Estado sem foto. Todo tema precisa dele, e o padrão da Shopify é um
   quadrado cinza com um ícone de montanha, que faz o produto parecer quebrado.
   Aqui a célula continua sendo ladrilho, com a roseta no lugar do frasco. */
.peca__retrato--vazio { display: grid; place-items: center; gap: 12px; }
.peca__retrato--vazio svg { width: 62%; max-width: 140px; height: auto; stroke: var(--texto-2); stroke-width: 1.4; fill: none; vector-effect: non-scaling-stroke; opacity: 0.55; }
.peca__retrato--vazio span { font-family: var(--face-corpo); font-size: 11px; letter-spacing: 0.11em; text-transform: uppercase; color: var(--texto-2); }

/* Compra rápida: sobe de dentro da foto ao passar o cursor, some ao sair.
   Fica dentro do retrato e não rouba altura do cartão quando está escondida. */
.peca__rapido {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  display: flex; align-items: center; justify-content: center; gap: 9px;
  background: var(--tinta); color: var(--taupe);
  font-family: var(--face-corpo); font-size: 11px; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  padding: 13px 10px; border: 0; cursor: pointer;
  transform: translateY(101%);
  transition: transform 0.45s var(--saida), background 0.3s ease;
}
.peca__rapido svg { width: 14px; height: 14px; stroke: currentColor; stroke-width: 1.7; fill: none; }
.peca__rapido:hover { background: var(--tinta); }
.peca:hover .peca__rapido, .peca:focus-within .peca__rapido { transform: translateY(0); }
/* No toque o botão não some: ele fica. Escondido atrás do cursor, ele
   simplesmente não existia no celular, que é onde a cliente está, e o cartão
   ficava sem nenhuma ação de compra. A referência que o dono da loja apontou
   mostra o botão sempre, e nisso ela está certa.

   Aqui ele fica parado no pé da foto, sem deslizar, e com altura de toque. */
@media (hover: none) {
  .peca__rapido {
    position: static; transform: none;
    min-height: 44px; padding: 12px 10px;
    background: var(--tinta); color: var(--taupe);
  }
  .peca__retrato { margin-bottom: 0; }
  .peca__marca { margin-top: 12px; }
}

.peca__selo {
  position: absolute; top: 22px; left: 22px; z-index: 2;
  background: var(--tinta); color: var(--taupe);
  font-family: var(--face-corpo); font-size: 11px; letter-spacing: 0.11em; text-transform: uppercase;
  padding: 5px 9px;
}
.peca__marca { display: block; margin-bottom: 6px; font-size: var(--t-label); color: var(--texto-2); }
/* Altura fixa de duas linhas no nome. Sem isso o rodapé de cada cartão
   pousa numa altura diferente, e é o desalinhamento de preço entre vizinhos
   que faz fileira de produto parecer bagunça. */
.peca__nome {
  font-family: var(--face-corpo); font-size: var(--t-produto);
  font-weight: 400; line-height: 1.34; letter-spacing: -0.006em;
  color: var(--texto);
  margin: 0 0 12px; min-height: calc(1.34em * 2);
}
.peca__rodape { margin-top: auto; padding-top: 10px; border-top: 1px solid var(--fio); }
.peca__preco { font-family: var(--face-corpo); font-weight: 600; font-size: var(--t-preco); letter-spacing: -0.026em; display: block; }
.peca__parcela { font-family: var(--face-corpo); font-weight: 400; font-size: var(--t-parcela); letter-spacing: 0; text-transform: none; color: var(--texto-2); display: block; margin-top: 4px; }

/* A linha de tamanho, no pe do cartao. Enquanto o preco nao existe, o que a
   cliente precisa saber para comparar dois frascos e o volume, e e ele que
   ocupa esse lugar. Quando o preco chegar, ele entra acima e o tamanho desce
   para uma linha de apoio. */
.peca__medidas {
  display: block; min-height: calc(var(--t-preco) * 1.1);
  font-family: var(--face-corpo); font-size: 13px; font-weight: 500;
  letter-spacing: -0.004em; line-height: 1.35; color: var(--texto-2);
}

/* Cartao sem foto nao e cartao vazio: o poco continua ocupando o lugar que a
   foto vai ocupar, com a roseta da casa apagada no meio. */
.peca__sem-foto {
  display: block; width: 100%; height: 100%;
  background: var(--tinta);
  -webkit-mask: var(--estrela) center / 52% no-repeat;
  mask: var(--estrela) center / 52% no-repeat;
  opacity: 0.12;
}

/* A prateleira grande entra por levas. O botao fecha a grade e separa uma
   leva da outra. */
.colecao__mais { display: flex; justify-content: center; margin-top: var(--ritmo); }
.colecao__mais button { min-width: min(320px, 100%); }

/* ---------- marcas ---------- */

/* Quatro peças inteiras e uma fração clara da quinta. Card cortado por acaso
   parece defeito; fração medida parece convite. */
.marcas {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: calc((100% - 4 * var(--gap-cartao)) / 4.16);
  gap: var(--gap-cartao); overflow-x: auto; padding-bottom: 4px;
}
.marcas > * { scroll-snap-align: start; }

/* O divisor é fixo, então a fração fica sempre em 16% em qualquer largura,
   que é o que se quer. O que não escala é a contagem: 4,16 cartões dentro de
   375px dá uma marca de 78px, que é tira, não cartão. A fração se mantém, a
   contagem cai. */
@media (max-width: 1000px) { .marcas { grid-auto-columns: calc((100% - 3 * var(--gap-cartao)) / 3.16); } }
@media (max-width: 760px)  { .marcas { grid-auto-columns: calc((100% - 2 * var(--gap-cartao)) / 2.16); } }
@media (max-width: 520px)  { .marcas { grid-auto-columns: calc((100% - var(--gap-cartao)) / 1.42); } }

.marca-cartao {
  background: var(--branco); border: 1px solid var(--fio);
  padding: 30px 18px; text-align: center;
  font-family: var(--face-corpo); font-size: var(--t-categoria); font-weight: 500; letter-spacing: -0.014em;
  transition: background 0.4s var(--saida), color 0.4s var(--saida), border-color 0.4s var(--saida);
}
.marca-cartao span { display: block; margin-top: 8px; }
.marca-cartao:hover { background: var(--garrafa); color: var(--taupe); border-color: var(--garrafa); }
.marca-cartao:hover .medida { color: rgba(247, 244, 239, 0.84); }

/* ---------- áreas ---------- */

/* ---------- beleza ----------
   Eram cinco retangulos brancos iguais, com um icone fino em cima e dois
   tercos de nada embaixo: aparencia de painel de sistema, nao de vitrine.

   Agora e composicao. Uma celula de abertura em tipografia pura e cinco
   tiles de tamanhos diferentes, cada um com o proprio campo de cor e a
   geometria da casa cortada em escala grande. Rosto ocupa duas colunas por
   duas linhas, Corpo fica abaixo da abertura, e os tres restantes fecham a
   base.

   So Corpo tem fotografia, e e honesto: das 32 imagens do projeto, as unicas
   de beleza sao as duas brumas da Victoria's Secret e um composto de
   marketing da Aura. Rosto, cabelo, maos e labios nao tem foto no catalogo,
   entao recebem composicao grafica em vez de imagem emprestada. */
.beleza {
  background: var(--marfim);
  padding-block: var(--ritmo-forte);
}
.beleza__grade {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(12px, 1.3vw, 18px);
  grid-template-areas:
    "abre   rosto  rosto"
    "corpo  rosto  rosto"
    "cabelo maos   labios";
}
.beleza__abertura {
  grid-area: abre;
  display: flex; flex-direction: column; justify-content: center;
  padding-right: clamp(0px, 1.6vw, 26px);
}
.beleza__rotulo { display: block; color: var(--bronze-texto); margin-bottom: 14px; }
.beleza__abertura h2 {
  font-family: var(--face-display); font-weight: var(--peso-display);
  font-optical-sizing: auto; letter-spacing: var(--tracking-display);
  line-height: var(--entrelinha-display);
  font-size: var(--t-editorial); margin: 0 0 16px;
}
.beleza__linha {
  font-size: var(--t-apoio); line-height: 1.6; color: var(--texto-2);
  margin: 0 0 26px; max-width: 30ch;
}
/* O embrulho dos tiles some da grade no desktop e so volta a existir como
   caixa no celular, onde vira trilho. */
.beleza__tiles { display: contents; }

.tile {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; flex-direction: column; justify-content: flex-end;
  min-height: 176px; padding: 20px;
  color: var(--texto);
  transition: box-shadow 0.3s var(--saida);
}
.tile--rosto  { grid-area: rosto;  --campo: var(--rosa);       background: var(--campo); min-height: 368px; padding: 28px; }
.tile--corpo  { grid-area: corpo;  --campo: var(--taupe);      background: var(--campo); }
.tile--cabelo { grid-area: cabelo; --campo: var(--garrafa);    background: var(--campo); color: var(--sobre-escuro); }
.tile--maos   { grid-area: maos;   --campo: var(--taupe-fundo); background: var(--campo); }
.tile--labios { grid-area: labios; --campo: var(--tinta);      background: var(--campo); color: var(--sobre-escuro); }

/* A linha da geometria passava por cima da legenda e cortava o texto ao
   meio. O ve da propria cor do tile sobe do pe e devolve campo limpo para a
   leitura, sem escurecer nem clarear a composicao. */
.tile__campo::after {
  content: ''; position: absolute; inset: auto 0 0 0; height: 62%;
  background: linear-gradient(to top, var(--campo) 22%, transparent 100%);
}

/* A geometria entra cortada e em escala grande, cada tile num enquadramento
   diferente: e o que da presenca sem depender de foto que nao existe. */
.tile__campo { position: absolute; inset: 0; z-index: -1; display: block; }
/* Preenchida, a geometria virava adesivo de estrela. Em traco fino ela e a
   mesma linha que ja desenha o fundo dos banners, e le como marca d'agua
   impressa em vez de clip-art. Cada tile pega um pedaco diferente dela. */
.tile__marca {
  position: absolute; height: auto; aspect-ratio: 1;
  fill: none; stroke: currentColor; stroke-width: 3.2;
  vector-effect: non-scaling-stroke; opacity: 0.3;
  transition: scale 0.3s var(--saida), rotate 0.3s var(--saida);
}
.tile--rosto  .tile__marca { width: 118%; right: -30%; top: -34%; opacity: 0.34; }
.tile--corpo  .tile__marca { width: 150%; left: -58%;  bottom: -70%; opacity: 0.26; }
.tile--cabelo .tile__marca { width: 168%; right: -78%; top: -56%; opacity: 0.34; }
.tile--maos   .tile__marca { width: 152%; left: -64%;  top: -60%; opacity: 0.28; }
.tile--labios .tile__marca { width: 176%; right: -70%; bottom: -84%; opacity: 0.34; }

/* Corpo e o unico com produto de verdade: as duas brumas, recortadas, em
   escalas diferentes para nao virarem um par simetrico. */
/* O produto fica ACIMA do véu. O véu existe para proteger a legenda da linha
   da geometria, não para apagar o frasco: passando por cima dele, lavava a
   metade de baixo do produto e o frasco parecia boiar sem apoio. Como o
   produto mora na direita e a legenda na esquerda, os dois não se encostam. */
.tile__frascos { position: absolute; inset: 0; z-index: 1; }
.tile__frascos img {
  position: absolute; bottom: -6%; width: auto; object-fit: contain;
  filter: drop-shadow(0 16px 20px rgba(20, 18, 21, 0.22));
  transition: scale 0.3s var(--saida);
  transform-origin: bottom center;
}
/* Mesma conta do cartão de marca: a altura pedida é a do produto, não a do
   arquivo. A base fica um pouco abaixo da borda, então o reflexo sai do
   quadro e o frasco parece apoiado na aresta do ladrilho. */
.tile__frascos img {
  --p-base: 0.855;
  height: calc(var(--alvo, 70%) / var(--p-alt, 0.8));
  top: calc(104% - (var(--alvo, 70%) / var(--p-alt, 0.8)) * var(--p-base));
  bottom: auto;
}
.tile__frascos img:first-child { --alvo: 56%; right: 30%; }
.tile__frascos img:last-child  { --alvo: 68%; right: 4%; }

.tile__dizer { position: relative; z-index: 1; max-width: 22ch; }
.tile__nome {
  display: block; font-size: var(--t-categoria); font-weight: 600;
  letter-spacing: -0.018em; line-height: 1.16;
}
.tile--rosto .tile__nome { font-size: clamp(20px, 1.9vw, 25px); }
.tile__nota { display: block; margin-top: 5px; font-size: 13px; line-height: 1.45; opacity: 0.74; }
.tile__ir {
  position: absolute; z-index: 1; top: 18px; right: 18px;
  width: 34px; height: 34px; display: grid; place-items: center;
  border: 1px solid currentColor; opacity: 0.4;
  transition: opacity 0.3s var(--saida), translate 0.3s var(--saida);
}
.tile__ir svg { width: 15px; height: 15px; stroke: currentColor; stroke-width: 1.6; fill: none; }

@media (hover: hover) {
  .tile:hover .tile__marca { scale: 1.02; rotate: 2deg; }
  .tile:hover .tile__frascos img { scale: 1.02; }
  .tile:hover .tile__ir { opacity: 1; translate: 3px 0; }
  .tile:hover { box-shadow: inset 0 0 0 1px currentColor; }
}
/* Sem ponteiro o estado clicavel precisa estar visivel desde o comeco. */
@media (hover: none) {
  .tile__ir { opacity: 0.85; }
}
.tile:focus-visible { outline: 2px solid var(--bronze); outline-offset: 3px; }
.tile--cabelo:focus-visible,
.tile--labios:focus-visible { outline-color: var(--rosa); }
.tile:active { scale: 0.995; }

@media (prefers-reduced-motion: reduce) {
  .tile, .tile__marca, .tile__frascos img, .tile__ir { transition: none; }
  .tile:hover .tile__marca, .tile:hover .tile__frascos img { scale: 1; rotate: 0deg; }
  .tile:hover .tile__ir { translate: 0 0; }
  .tile:active { scale: 1; }
}

@media (max-width: 1000px) {
  .beleza__grade {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-template-areas:
      "abre   rosto"
      "corpo  rosto"
      "cabelo maos"
      "labios labios";
  }
  .tile--rosto { min-height: 320px; }
  .tile--labios { min-height: 150px; }
}

@media (max-width: 620px) {
  /* Trilho no celular. A abertura fica acima, os cinco tiles deslizam com
     encaixe, e a fracao do proximo e medida, nao sobra de calculo. */
  .beleza__grade { display: block; }
  .beleza__abertura { padding-right: 0; margin-bottom: 22px; }
  .beleza__linha { max-width: none; }
  .beleza__tiles {
    display: grid; grid-auto-flow: column;
    grid-auto-columns: calc((100% - var(--gap-cartao)) / 1.28);
    gap: var(--gap-cartao);
    overflow-x: auto; scrollbar-width: none;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    padding-bottom: 4px;
  }
  .beleza__tiles::-webkit-scrollbar { width: 0; height: 0; display: none; }
  .tile--rosto, .tile--corpo, .tile--cabelo, .tile--maos, .tile--labios {
    grid-area: auto; min-height: 210px; padding: 18px;
    scroll-snap-align: start;
  }
  .tile--rosto .tile__nome { font-size: var(--t-categoria); }
}

/* ---------- marcas ---------- */

/* Quatro peças inteiras e uma fração clara da quinta. Card cortado por acaso
   parece defeito; fração medida parece convite. */
.marcas {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: calc((100% - 4 * var(--gap-cartao)) / 4.16);
  gap: var(--gap-cartao); overflow-x: auto; padding-bottom: 4px;
}
.marcas > * { scroll-snap-align: start; }

/* O divisor é fixo, então a fração fica sempre em 16% em qualquer largura,
   que é o que se quer. O que não escala é a contagem: 4,16 cartões dentro de
   375px dá uma marca de 78px, que é tira, não cartão. A fração se mantém, a
   contagem cai. */
@media (max-width: 1000px) { .marcas { grid-auto-columns: calc((100% - 3 * var(--gap-cartao)) / 3.16); } }
@media (max-width: 760px)  { .marcas { grid-auto-columns: calc((100% - 2 * var(--gap-cartao)) / 2.16); } }
@media (max-width: 520px)  { .marcas { grid-auto-columns: calc((100% - var(--gap-cartao)) / 1.42); } }

.marca-cartao {
  background: var(--branco); border: 1px solid var(--fio);
  padding: 30px 18px; text-align: center;
  font-family: var(--face-corpo); font-size: var(--t-categoria); font-weight: 500; letter-spacing: -0.014em;
  transition: background 0.4s var(--saida), color 0.4s var(--saida), border-color 0.4s var(--saida);
}
.marca-cartao span { display: block; margin-top: 8px; }
.marca-cartao:hover { background: var(--garrafa); color: var(--taupe); border-color: var(--garrafa); }
.marca-cartao:hover .medida { color: rgba(247, 244, 239, 0.84); }

/* ---------- áreas ---------- */



/* ---------- portais ----------
   Eram dois <div> sem link, com título serifado e nenhuma ação: dois
   retângulos. Agora são dois <a> inteiros, cada um com a marca de doze pontas
   em campo, título curto, texto legível e um botão de verdade.

   Os dois universos têm personalidade diferente, tinta e rosa, e a mesma
   estrutura, que é o que os mantém como par em vez de como dois avulsos. */
.portais { display: grid; grid-template-columns: 1fr 1fr; gap: var(--gap-cartao); }
.portal {
  position: relative; overflow: hidden; isolation: isolate;
  display: flex; flex-direction: column; gap: 18px;
  padding: clamp(28px, 3.4vw, 52px);
  min-height: clamp(280px, 26vw, 340px);
  transition: box-shadow 0.5s var(--saida);
}
.portal__marca {
  position: absolute; z-index: -1; width: 62%; height: auto; aspect-ratio: 1;
  right: -14%; bottom: -22%; fill: currentColor; opacity: 0.07;
  transition: rotate 1.4s var(--saida), scale 1.4s var(--saida);
}
.portal:hover .portal__marca { rotate: 12deg; scale: 1.06; }
.portal__dizer { display: block; }
.portal__rotulo { display: block; margin-bottom: 16px; }
.portal__titulo {
  display: block; font-size: var(--t-bloco); font-weight: 600;
  letter-spacing: -0.026em; line-height: 1.12; margin-bottom: 12px;
}
.portal__texto { display: block; font-size: var(--t-apoio); line-height: 1.6; max-width: 36ch; }
.portal__ir {
  margin-top: auto; align-self: flex-start;
  display: inline-flex; align-items: center; gap: 11px;
  font-size: var(--t-cta); font-weight: 600;
  letter-spacing: var(--label-espaco); text-transform: uppercase;
  padding: 15px 24px; min-height: 48px;
  transition: background 0.35s var(--saida), color 0.35s var(--saida), gap 0.35s var(--saida);
}
.portal__ir svg { width: 17px; height: 17px; stroke: currentColor; stroke-width: 1.6; fill: none; }
.portal:hover .portal__ir { gap: 15px; }
.portal:focus-visible { outline: 2px solid var(--bronze); outline-offset: 3px; }
.portal:active { scale: 0.995; }

.portal--perfumaria { background: var(--tinta); color: var(--sobre-escuro); }
.portal--perfumaria .portal__rotulo { color: var(--bronze); }
.portal--perfumaria .portal__texto { color: var(--sobre-escuro-2); }
.portal--perfumaria .portal__ir { background: var(--sobre-escuro); color: var(--tinta); }
.portal--perfumaria:hover .portal__ir { background: var(--bronze); color: var(--tinta); }
.portal--perfumaria:hover { box-shadow: inset 0 0 0 1px rgba(247, 244, 239, 0.18); }

.portal--beleza { background: var(--rosa); color: var(--texto); }
/* #7a4f4c media 3.75 sobre o rosa do portal, e rótulo de 11px precisa de 4.5.
   O mesmo tom, dois passos mais escuro, chega a 5.36 sem sair da família. */
.portal--beleza .portal__rotulo { color: #5e3a37; }
.portal--beleza .portal__texto { color: #4a3d3c; }
.portal--beleza .portal__ir { background: var(--tinta); color: var(--sobre-escuro); }
.portal--beleza:hover .portal__ir { background: var(--garrafa); }
.portal--beleza:hover { box-shadow: inset 0 0 0 1px rgba(20, 18, 21, 0.14); }

@media (max-width: 760px) {
  .portais { grid-template-columns: 1fr; }
  .portal { min-height: 0; padding: 26px 22px 24px; gap: 14px; }
  .portal__marca { width: 48%; right: -10%; bottom: -18%; }
  .portal__texto { max-width: none; }
}

/* ---------- faixa de kit ---------- */

/* A tinta já é da prateleira de grife e do rodapé. Aqui ela seria o terceiro
   bloco escuro, então a faixa fica clara e o peso vem do botão. */
.faixa-kit { background: var(--taupe-fundo); color: var(--texto); padding-block: var(--ritmo); }
.faixa-kit__grade { display: grid; grid-template-columns: 1fr auto; gap: 32px; align-items: center; }
.faixa-kit h2 { margin-bottom: 14px; }
.faixa-kit p { margin: 0; max-width: 52ch; color: var(--texto-2); }
.faixa-kit .medida { color: var(--texto-2); }
.faixa-kit .acao { background: var(--tinta); }
.faixa-kit .acao:hover { background: var(--garrafa); }

/* ---------- rodapé ---------- */

.rodape { background: var(--tinta); color: var(--taupe); padding-block: 60px 28px; }
.rodape .medida { color: rgba(247, 244, 239, 0.58); }
.rodape__grade { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1fr; gap: 40px; }
.rodape h4 { font-family: var(--face-corpo); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(247, 244, 239, 0.58); margin: 0 0 15px; font-weight: 400; }
.rodape ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; font-size: 14px; }
.rodape a { transition: color 0.3s ease; }
.rodape a:hover { color: var(--bronze); }
.rodape__fim { margin-top: 44px; padding-top: 20px; border-top: 1px solid rgba(247, 244, 239, 0.18); display: flex; justify-content: space-between; gap: 18px; flex-wrap: wrap; }

.assina { display: flex; margin-top: 20px; max-width: 340px; }
.assina input { flex: 1; border: 1px solid rgba(247, 244, 239, 0.3); background: none; color: var(--taupe); padding: 13px 14px; font-family: var(--face-corpo); font-size: 14px; }
.assina input::placeholder { color: rgba(247, 244, 239, 0.5); }
.assina button { background: var(--bronze); color: var(--tinta); border: 0; padding-inline: 20px; cursor: pointer; font-family: var(--face-corpo); font-size: 11px; letter-spacing: 0.11em; text-transform: uppercase; transition: background 0.3s ease; }
.assina button:hover { background: var(--rosa); }
/* A resposta do formulário fica no rodapé, em voz de status, e diz a verdade:
   não existe serviço de e-mail ligado, então o endereço não sai do navegador. */
.assina__aviso {
  margin: 10px 0 0; max-width: 340px;
  font-size: 13px; line-height: 1.5; color: rgba(247, 244, 239, 0.78);
}
.assina__aviso:empty { display: none; }
.assina__aviso[data-erro] { color: var(--rosa); }

/* ---------- respiro ---------- */

@media (max-width: 1100px) {
  .beneficios { grid-template-columns: 1fr 1fr; }
  .rodape__grade { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 860px) {
  .navegacao, .busca { display: none; }
  .amarracao__barra { justify-content: space-between; }
  .faixa-kit__grade { grid-template-columns: 1fr; }
}

@media (max-width: 620px) {
  .grade { grid-template-columns: 1fr 1fr; gap: 12px; }

  .beneficios { grid-template-columns: 1fr; }
  .beneficio + .beneficio { border-top: 1px solid var(--fio); }
  .rodape__grade { grid-template-columns: 1fr; }
}

/* ---------- gaveta de menu (celular) ----------
   Sem isto, quem abre a loja no telefone não tem como navegar nem buscar: o
   menu e a busca somem abaixo de 860px e não sobrava nada no lugar. */

.hamburguer, .busca-movel { display: none; }

@media (max-width: 860px) {
  .hamburguer, .busca-movel { display: grid; }
  .amarracao__barra { gap: 6px; }
  .marca { margin-inline: auto; }
}

.veu {
  position: fixed; inset: 0; z-index: 80;
  background: rgba(20, 18, 21, 0.45);
  opacity: 0; pointer-events: none;
  transition: opacity 0.4s var(--saida);
}
.veu.aberto { opacity: 1; pointer-events: auto; }

.menu-movel {
  position: fixed; inset: 0 auto 0 0; z-index: 90;
  width: min(86vw, 380px);
  background: var(--branco);
  display: flex; flex-direction: column;
  transform: translateX(-101%);
  transition: transform 0.45s var(--saida);
  overflow-y: auto;
}
.menu-movel.aberta { transform: translateX(0); }

.menu-movel__topo { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 18px 22px; border-bottom: 1px solid var(--fio); }
.menu-movel__fechar { width: 40px; height: 40px; display: grid; place-items: center; border: 1px solid var(--fio); background: none; color: var(--tinta); cursor: pointer; }
.menu-movel__fechar svg { width: 17px; height: 17px; stroke: currentColor; stroke-width: 1.6; fill: none; }

.menu-movel__busca { padding: 18px 22px; border-bottom: 1px solid var(--fio); position: relative; }
.menu-movel__busca input { width: 100%; border: 1px solid var(--fio-forte); background: var(--branco); padding: 13px 14px 13px 42px; font-family: var(--face-corpo); font-size: 15px; color: var(--tinta); }
.menu-movel__busca svg { position: absolute; left: 36px; top: 50%; translate: 0 -50%; width: 18px; height: 18px; stroke: var(--texto-2); stroke-width: 1.5; fill: none; }

.menu-movel__lista { list-style: none; margin: 0; padding: 8px 0; }
.menu-movel__lista a {
  display: flex; align-items: center; justify-content: space-between;
  padding: 17px 22px;
  font-family: var(--face-corpo); font-size: 19px; font-weight: 500;
  letter-spacing: -0.022em;
  border-bottom: 1px solid var(--fio);
}
.menu-movel__lista a:active { background: var(--taupe); }
.menu-movel__lista svg { width: 17px; height: 17px; stroke: var(--fio-forte); stroke-width: 1.6; fill: none; }

.menu-movel__pe { margin-top: auto; padding: 22px; background: var(--taupe); display: grid; gap: 13px; }
.menu-movel__pe a { display: flex; align-items: center; gap: 11px; font-size: 14.5px; }
.menu-movel__pe svg { width: 17px; height: 17px; stroke: var(--texto-2); stroke-width: 1.5; fill: none; }

@media (prefers-reduced-motion: reduce) {
  .menu-movel, .veu { transition: none; }
}

/* ---------- palco: o banner do topo ----------
   O topo antigo era título e parágrafo sobre branco, e página de loja que
   abre assim parece blog. Aqui o topo é o que é em toda loja grande: o lugar
   onde a casa fala, com produto grande, chamada e botão.

   O produto vem recortado, sem fundo, então ele flutua sobre o chão da cena
   em vez de aparecer dentro de um quadradinho brigando com o banner. O
   recorte é feito uma vez, no imagens/recortar.py, nunca no navegador. */
.palco {
  position: relative; isolation: isolate; overflow: hidden;
  background: var(--tinta);
}
/* As artes não têm todas a mesma proporção. Num carrossel de flex a altura
   seria a da cena mais alta, e a mais baixa ficaria com faixa embaixo. Aqui
   a altura é a da cena ativa, medida no JavaScript, e muda junto com a
   troca de slide. Sem isso não tem como cumprir as duas coisas ao mesmo
   tempo: preencher tudo e não cortar. */
/* A altura vai na PISTA, não no palco: o leme com as abas e as setas é irmão
   da pista dentro do palco, e altura no palco engolia ele. */
.palco[style*="--altura-palco"] .palco__pista {
  height: var(--altura-palco);
  /* Sem overflow aqui. A pista tem a largura de UMA cena e as outras vivem
     fora dela, à direita, esperando a vez: recortar na pista apaga tudo a
     partir da segunda e deixa só o fundo escuro do palco aparecendo. Quem
     recorta é o palco, que já tem overflow hidden e corta nos dois eixos,
     inclusive a cena mais alta que a ativa. */
}
@media (prefers-reduced-motion: no-preference) {
  /* Sim, isto anima uma medida, e é decisão. Cada banner tem a proporção
     dele, então a altura precisa mudar quando a cliente troca de slide. É um
     elemento só, uma vez por toque dela, e a alternativa, escalar, deformaria
     a arte. Animar não custa mais do que o salto seco custaria em atenção. */
  .palco[style*="--altura-palco"] .palco__pista { transition: height 0.5s var(--saida), translate 0.85s var(--saida); }
}
.palco__pista { align-items: flex-start; }
.palco__pista {
  display: flex;
  translate: calc(var(--i, 0) * -100%) 0;
  transition: translate 0.85s var(--saida);
}
.cena {
  flex: 0 0 100%; position: relative; overflow: hidden;
  display: grid; align-items: center;
  min-height: clamp(470px, 62vh, 660px);
  background: var(--chao); color: var(--sobre);
}
/* ---------- palco em modo banner ----------
   O dono da loja decidiu: o palco mostra os banners dele, inteiros, e só
   eles. Então a cena aqui não tem título, parágrafo nem botão em HTML: o
   banner já traz tudo desenhado dentro, e escrever por cima seria repetir o
   que já está lá e brigar com a arte.

   Por consequência, três coisas que existem para o texto saem: o véu que
   escurecia metade da cena, o filtro que apagava a arte ao rolar, e a altura
   mínima, que aqui vira a proporção do próprio banner. A imagem entra em
   "contain" e nunca é cortada, e a faixa que sobra quando a tela não bate com
   a proporção do banner recebe a cor da borda dele. */
.cena--banner {
  min-height: 0;
  /* A proporção é a da própria arte, e não uma medida da página. Assim o
     banner preenche a cena inteira sem sobrar faixa e sem ser cortado: o
     "cover" abaixo passa a não ter nada para cortar. */
  aspect-ratio: var(--razao, 3 / 1);
  background: var(--fundo-banner, var(--marfim));
}
/* O banner preenche a cena inteira, sem sobra de nenhum lado, no celular e
   no computador. Antes ele entrava em "contain" e a faixa que sobrava quando
   a tela nao batia com a proporcao ficava na cor da borda: some, mas e sobra.
   Em "cover" nao ha sobra em lugar nenhum, e o preco e o corte quando as
   proporcoes nao batem. No deitado elas batem, entao nada e cortado. */
.cena--banner .cena__arte img {
  object-fit: cover;
  object-position: center;
  filter: none;
  animation: none;
}
.cena--banner .cena__grade,
.cena--banner .cena__grade::before { display: none; }

/* O banner inteiro é o link: ele já tem o botão desenhado, e obrigar a
   cliente a acertar um botão que é pixel seria pedir pontaria. */
.cena__inteira { position: absolute; inset: 0; display: block; z-index: 1; }
.cena__inteira:focus-visible { outline: 3px solid var(--bronze); outline-offset: -6px; }

@media (max-width: 860px) {
  /* Em pé, todos os banners entram na mesma altura para o carrossel não
     pular de tamanho ao trocar de slide. Os dois que são mais estreitos que
     os outros ganham faixa lateral na cor da própria borda. */
  .cena--banner {
    aspect-ratio: var(--razao-pe, 1036 / 1519);
    /* O fundo ainda existe por baixo, para o instante antes de a foto
       carregar. Com "cover" ele não aparece depois disso. */
    background: var(--fundo-banner-pe, var(--fundo-banner, var(--marfim)));
  }
}

/* Cada cena traz o próprio chão e a própria brasa. Três variáveis por cena,
   e nada de reescrever o bloco inteiro para trocar de cor. */
.cena--grife  { --chao: radial-gradient(118% 104% at 72% 38%, var(--garrafa) 0%, #0e3b32 44%, #05130f 100%); --sobre: #f6f2eb; --brasa: var(--bronze); --sombra: rgba(0, 0, 0, 0.55); }
.cena--yara   { --chao: radial-gradient(118% 104% at 70% 36%, #fdf1f0 0%, #f6dcdc 46%, #e7bec2 100%); --sobre: #2a1218; --brasa: #a8465c; --sombra: rgba(120, 60, 72, 0.3); }
.cena--arabe  { --chao: radial-gradient(118% 104% at 68% 42%, #4d2c10 0%, #251509 52%, #0e0703 100%); --sobre: #f7eee2; --brasa: #dcab63; --sombra: rgba(0, 0, 0, 0.55); }
.cena--splash { --chao: radial-gradient(118% 104% at 72% 36%, #fffdfd 0%, #fae6ec 48%, #efcad8 100%); --sobre: #2b0f1c; --brasa: #b32f5e; --sombra: rgba(120, 45, 80, 0.26); }
/* A arte do cabelo é clara e o produto fica à direita, então o texto entra
   sobre papel claro e precisa de tinta escura. O véu claro cuida do resto. */
.cena--cabelo { --chao: radial-gradient(118% 104% at 70% 40%, #f8f6f3 0%, #ece7e1 50%, #dcd4ca 100%); --sobre: #201c19; --brasa: var(--bronze-texto); --sombra: rgba(90, 74, 58, 0.22); }
.cena--casa   { --chao: radial-gradient(118% 104% at 70% 38%, #2b2a26 0%, #17160f 52%, #090804 100%); --sobre: #f7f3e9; --brasa: var(--bronze); --sombra: rgba(0, 0, 0, 0.6); }

.cena__grade {
  position: relative; z-index: 1; width: 100%; isolation: isolate;
  display: grid; grid-template-columns: minmax(0, 52%);
  align-items: center;
  padding-block: clamp(40px, 5.5vw, 72px);
}
.cena__titulo {
  font-size: var(--t-hero); margin: 0 0 22px; max-width: 14ch; color: inherit;
}
.cena__dizer p {
  font-family: var(--face-leitura); font-optical-sizing: auto; line-height: 1.6;
  font-size: 17px; margin: 0 0 32px; max-width: 42ch; opacity: 0.82;
}
/* O CTA do palco inverte, e so ele. O botao de tinta funciona no resto da
   loja, que e clara; sobre a arte escura do palco ele some no fundo e passa
   a parecer link solto. Aqui o marfim e o fundo e a tinta e o texto, o que
   tambem resolve as cinco campanhas de uma vez, inclusive as duas de arte
   clara, porque o botao deixa de depender da cor que esta atras.

   Estrutura, cantos, folga da seta e tempo continuam sendo os do componente:
   muda a cor, nao o gesto. */
.cena .acao {
  background: var(--marfim);
  color: var(--tinta);
  box-shadow: inset 0 0 0 1px rgba(20, 18, 21, 0.24);
}
.cena .acao:hover,
.cena .acao:focus-visible {
  background: var(--garrafa);
  color: var(--marfim);
  box-shadow: none;
}
.cena .acao:focus-visible { outline: 2px solid var(--marfim); outline-offset: 2px; }

/* ---------- leme do palco ----------
   Cinco tracinhos não dizem que coleções a loja tem. O leme é uma barra
   própria abaixo da arte, com o nome de cada coleção, a posição em dois
   dígitos e as duas setas. Fora da imagem, ele nunca cobre a fala da campanha
   e nunca precisa de véu para ficar legível. */
.palco__leme {
  background: var(--tinta); color: var(--sobre-escuro);
  border-top: 1px solid rgba(247, 244, 239, 0.1);
}
.palco__leme-grade {
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; min-height: 58px;
}

.palco__abas {
  display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none;
  scroll-behavior: smooth;
  /* Sem min-width zero o trilho de abas se recusa a encolher e passa por
     baixo do contador, que no celular aparecia com meia letra atrás dele. */
  flex: 1 1 auto; min-width: 0;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent 100%);
}
.palco__abas::-webkit-scrollbar { width: 0; height: 0; display: none; }
.palco__aba {
  flex: 0 0 auto; position: relative; cursor: pointer;
  background: none; border: 0; color: rgba(247, 244, 239, 0.62);
  font-family: var(--face-corpo); font-size: var(--t-label);
  font-weight: 500; letter-spacing: var(--label-espaco); text-transform: uppercase;
  padding: 20px 14px 19px; white-space: nowrap;
  transition: color 0.3s ease;
}
.palco__aba:hover { color: var(--sobre-escuro); }
/* O fio da aba ativa cresce da esquerda em vez de aparecer inteiro: é o mesmo
   gesto do link de seção, então a loja continua tendo um vocabulário só. */
.palco__aba::after {
  content: ''; position: absolute; left: 14px; right: 14px; bottom: 0;
  height: 2px; background: var(--bronze);
  scale: 0 1; transform-origin: left; transition: scale 0.4s var(--saida);
}
.palco__aba[aria-selected='true'] { color: var(--branco); }
.palco__aba[aria-selected='true']::after { scale: 1 1; }

.palco__comando { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; padding-left: 8px; background: var(--tinta); }
.palco__conta {
  display: flex; align-items: center; gap: 8px; margin: 0 12px 0 0;
  font-size: 11.5px; font-weight: 500; letter-spacing: 0.08em;
  color: rgba(247, 244, 239, 0.62); font-variant-numeric: tabular-nums;
}
.palco__atual { color: var(--branco); }
.palco__barra { width: 22px; height: 1px; background: rgba(247, 244, 239, 0.34); }
.palco__seta {
  width: 46px; height: 44px; display: grid; place-items: center;
  background: none; border: 1px solid rgba(247, 244, 239, 0.24);
  color: var(--sobre-escuro); cursor: pointer;
  transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}
.palco__seta:hover { background: var(--sobre-escuro); border-color: var(--sobre-escuro); color: var(--tinta); }
.palco__seta svg { width: 19px; height: 19px; stroke: currentColor; stroke-width: 1.6; fill: none; }

/* O nome da coleção também fica dentro da cena, porque é ali que a pessoa
   está olhando quando decide se aquilo interessa. */
.cena__colecao {
  margin: 0 0 14px; font-size: var(--t-label); font-weight: 500;
  letter-spacing: var(--label-espaco); text-transform: uppercase;
  /* O rótulo herdava a brasa de cada cena, e brasa é cor de detalhe, não de
     texto: sobre a arte de grife media 3.30 e sobre a da Yara 4.38, as duas
     reprovando. Agora ele usa a mesma cor que o título da cena já usa, única
     provada contra cada arte, e se diferencia por tamanho e espacejamento em
     vez de cor. O pior caso passou de 3.30 para 11.1. */
  color: var(--sobre);
  opacity: 0.8;
}

@media (prefers-reduced-motion: no-preference) {
  /* O frasco respira. Só o da frente, e só três pixels: banner com produto
     balançando muito vira anúncio de banner, não vitrine. */
  
  
  
  .cena--ativa .cena__dizer > * { animation: subir-cena 0.9s var(--saida) backwards; }
  .cena--ativa .cena__titulo { animation-delay: 0.14s; }
  .cena--ativa .cena__dizer p { animation-delay: 0.26s; }
  .cena--ativa .cena__dizer .acao { animation-delay: 0.38s; }
}
@keyframes boiar { 0%, 100% { translate: 0 0 } 50% { translate: 0 -10px } }
@keyframes girar-selo { to { rotate: 360deg } }
@keyframes subir-cena { from { opacity: 0; translate: 0 22px } }

@media (max-width: 860px) {
  /* No celular o banner continua banner: produto grande em cima, fala embaixo.
     Empilhar é o único jeito honesto; texto sobre o produto em 390px de
     largura não sobra legível nem para um nem para outro. */
  .cena { min-height: 0; }
  .cena__grade {
    grid-template-columns: 1fr;
    padding-block: 26px 52px; text-align: left;
  }
  
  
  
  
  .cena__titulo { font-size: clamp(27px, 7.4vw, 36px); max-width: 100%; }
  .cena__dizer p { font-size: 15.5px; margin-bottom: 24px; }
  /* No celular as setas ficam: são a única forma de voltar sem arrastar
     com precisão, e agora que o leme é barra própria elas não cobrem nada. */
  .palco__leme-grade { min-height: 52px; gap: 10px; }
  .palco__aba { padding: 17px 11px 16px; }
  .palco__aba::after { left: 11px; right: 11px; }
  .palco__conta { margin-right: 6px; }
  .palco__barra { width: 14px; }
}

/* ---------- banners de marca ----------
   O trilho antigo era nome da marca dentro de um retângulo branco, que é
   índice, não vitrine. Aqui cada marca tem o próprio chão e o próprio frasco
   recortado, do jeito que a marca se apresenta na casa dela.

   O nome vem em tipografia, nunca em logotipo: identificar o que a loja
   vende pelo nome é uso comum de revenda, e arquivo de logotipo de marca
   tem regra de uso própria, que se pede a quem distribui. */
.vitrola {
  position: relative; overflow: hidden; isolation: isolate;
  display: grid; align-content: end;
  aspect-ratio: 4 / 5; padding: 20px;
  background: var(--chao); color: var(--sobre);
  transition: box-shadow 0.45s var(--saida);
}
.vitrola:hover { box-shadow: 0 26px 44px -24px rgba(20, 18, 21, 0.55); }
.vitrola__selo {
  position: absolute; inset: -18% -30% 22% -30%; z-index: 0;
  background: var(--brasa); opacity: 0.2;
  -webkit-mask: var(--estrela) center/contain no-repeat;
  mask: var(--estrela) center/contain no-repeat;
}
/* O frasco é posicionado pelo PRODUTO, e não pelo arquivo.

   A foto virou um quadro quadrado com folga em volta do produto, para todos
   apoiarem na mesma linha. Quem posiciona pela altura do arquivo faz o
   produto encolher na proporção da folga, e foi o que aconteceu aqui: o
   frasco da marca virou um objeto pequeno boiando no meio do campo.

   O compositor mede, por produto, a largura e a altura que ele ocupa dentro
   do quadro. Com esses dois números a conta fecha: a imagem cresce até o
   produto ter a altura pedida, e sobe até a base dele cair na linha certa. */
.vitrola__frasco {
  --alvo: 54%;          /* altura que o produto deve ter no cartão */
  --linha: 66%;         /* onde a base dele apoia, a contar do topo */
  --p-base: 0.855;      /* onde o compositor pôs a linha de apoio */
  position: absolute; z-index: 1; left: 50%;
  height: calc(var(--alvo) / var(--p-alt, 0.8));
  top: calc(var(--linha) - (var(--alvo) / var(--p-alt, 0.8)) * var(--p-base));
  width: auto; object-fit: contain; object-position: bottom;
  translate: -50% 0;
  filter: drop-shadow(0 18px 22px rgba(0, 0, 0, 0.42));
  transition: translate 0.5s var(--saida);
}

/* A mesma sombra de contato do cartão de produto, para o frasco apoiar no
   campo da marca em vez de pairar sobre ele. A largura sai da do produto:
   o cartão é 4 por 5, então o que é fração de altura vira 1,25 de largura. */
.vitrola__chao {
  position: absolute; z-index: 0; left: 50%; top: var(--linha, 66%);
  width: calc(var(--alvo, 54%) / var(--p-alt, 0.8) * var(--p-larg, 0.44) * 1.25);
  height: calc(var(--alvo, 54%) / var(--p-alt, 0.8) * var(--p-larg, 0.44) * 0.21);
  translate: -50% -50%;
  background: radial-gradient(closest-side ellipse at 50% 50%,
    rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.26) 48%, transparent 100%);
  pointer-events: none;
  transition: scale 0.5s var(--saida), opacity 0.5s var(--saida);
}
.vitrola:hover .vitrola__chao { scale: 1.2 1.12; opacity: 0.7; }
.vitrola:hover .vitrola__frasco { translate: -50% -8px; }
.vitrola--sem-foto .vitrola__selo { inset: -14% -22% 6% -22%; opacity: 0.26; }
.vitrola__dizer { position: relative; z-index: 2; }
.vitrola__nome {
  display: block; font-family: var(--face-corpo); font-weight: 600;
  letter-spacing: -0.026em; font-size: 20px; line-height: 1.12;
}
.vitrola__frente {
  display: block; margin-top: 7px; opacity: 0.82;
  /* A classe .medida pinta o rótulo com --texto-2, que é cinza de papel claro.
     Sobre o chão escuro da casa isso media 2.03 de contraste: rótulo que existe
     e não se lê. Aqui ele volta para a cor de cima do próprio cartão. */
  color: var(--sobre);
}

/* Cada casa com o chão dela. Duas variáveis por marca e nada mais. */
.vitrola--dior      { --chao: linear-gradient(165deg, #1d2733, #0c1119); --sobre: #f2f0ec; --brasa: #8fa4bd; }
.vitrola--herrera   { --chao: linear-gradient(165deg, #232a4a, #0e1226); --sobre: #f4f1ea; --brasa: #b08a4e; }
.vitrola--lancome   { --chao: linear-gradient(165deg, #f6dde2, #e7b9c4); --sobre: #2a1119; --brasa: #a3243c; }
.vitrola--rabanne   { --chao: linear-gradient(165deg, #f0dcc6, #d9ab7c); --sobre: #2c1b0c; --brasa: #8a5a22; }
.vitrola--ysl       { --chao: linear-gradient(165deg, #232323, #0a0a0a); --sobre: #f5f2ea; --brasa: #b9905a; }
.vitrola--lattafa   { --chao: linear-gradient(165deg, #43280f, #180d05); --sobre: #f6ece0; --brasa: #dcab63; }
.vitrola--armaf     { --chao: linear-gradient(165deg, #3c1220, #150509); --sobre: #f5eaed; --brasa: #c08497; }
.vitrola--alhambra  { --chao: linear-gradient(165deg, #f7e2e4, #e8bfc6); --sobre: #2b1319; --brasa: #9c6070; }
.vitrola--vs        { --chao: linear-gradient(165deg, #f9dde6, #eeaac2); --sobre: #2b0e1a; --brasa: #b32f5e; }
.vitrola--anua      { --chao: linear-gradient(165deg, #e8f0e6, #c9ddc4); --sobre: #16281a; --brasa: #3f7a44; }
.vitrola--medicube  { --chao: linear-gradient(165deg, #e6eef6, #bfd4e8); --sobre: #10202e; --brasa: #2f6ea8; }
.vitrola--adcos     { --chao: linear-gradient(165deg, #f1efe8, #d9d3c4); --sobre: #201f1a; --brasa: #8a7c56; }

/* ---------- a prateleira de grife ----------
   Esta é a seção que tem que convencer, então ela é a única da página com
   chão escuro. Numa página clara, faixa escura é o recurso mais forte que
   existe para dizer onde olhar, e por isso se usa uma vez só.

   O cartão continua branco: produto de grife pede fundo limpo, e branco
   sobre escuro é o que faz o frasco saltar. */
/* Esta era a segunda de três seções verdes. O verde passou a ser assinatura,
   e assinatura que se repete não assina nada: ele ficou só no guia. A grife,
   que é a prateleira que mais precisa de autoridade, ganha tinta, que é a
   cor que sustenta comércio sem virar tema. */
.secao--grife {
  background: var(--tinta);
  color: var(--taupe);
  padding-block: var(--ritmo-forte) var(--ritmo);
}
.secao--grife h2 { color: var(--branco); }
.secao__linha {
  font-family: var(--face-leitura); font-optical-sizing: auto;
  font-size: 16.5px; line-height: 1.6; margin: 14px 0 0; max-width: 54ch;
  color: rgba(247, 244, 239, 0.84);
}
.secao__cabeca--forte { align-items: center; gap: 20px; margin-bottom: 40px; }
.secao--grife .acao-secundaria {
  border-color: rgba(247, 244, 239, 0.5); color: var(--taupe); white-space: nowrap;
}
.secao--grife .acao-secundaria:hover { background: var(--taupe); color: var(--tinta); }
/* O cartão é branco dentro de uma seção escura, então ele precisa devolver
   a cor do texto: herdar a cor clara da seção deixaria nome e preço
   ilegíveis, que é o erro mais caro que existe numa prateleira. */
.secao--grife .peca { background: var(--branco); border-color: transparent; color: var(--tinta); }
.secao--grife .peca .medida { color: var(--texto-2); }
.secao--grife .peca__retrato { background: var(--branco); }
.secao--grife .peca__retrato--vazio {
  background: var(--marfim); border: 1px dashed rgba(20, 18, 21, 0.16);
}
/* Branco sobre bronze mede 3.43 e reprova como texto. O selo passa a tinta
   sobre bronze, que mede 4.95. */
.secao--grife .peca__selo { background: var(--bronze); color: var(--tinta); }

@media (max-width: 860px) {
  .secao__cabeca--forte { flex-direction: column; align-items: flex-start; gap: 20px; margin-bottom: 28px; }
  .secao__linha { font-size: 15.5px; }
}

/* ---------- convite de primeira visita ----------
   Metade arte, metade fala, como fazem as casas grandes. Abre uma vez e
   guarda a resposta: pop-up que volta a cada visita é o jeito mais rápido de
   perder alguém que já estava dentro da loja.

   Nasce com hidden no HTML, então quem entra sem JS nunca vê caixa presa. */
.convite[hidden] { display: none; }
.convite { position: fixed; inset: 0; z-index: 90; display: grid; place-items: center; padding: 20px; }
.convite__veu { position: absolute; inset: 0; background: rgba(9, 22, 19, 0.62); backdrop-filter: blur(3px); }
.convite__caixa {
  position: relative; z-index: 1; width: min(880px, 100%);
  display: grid; grid-template-columns: 0.82fr 1fr;
  background: var(--branco); box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.6);
  max-height: calc(100dvh - 40px); overflow: auto;
}
.convite__arte {
  position: relative; overflow: hidden; display: grid; place-items: center;
  background: radial-gradient(110% 100% at 50% 40%, #1a5046 0%, #123b33 48%, #081d18 100%);
  min-height: 260px;
}
.convite__selo {
  position: absolute; inset: -12%; background: var(--bronze); opacity: 0.2;
  -webkit-mask: var(--estrela) center/contain no-repeat;
  mask: var(--estrela) center/contain no-repeat;
}
.convite__arte img {
  position: relative; z-index: 1; width: auto; height: 76%; max-height: 330px;
  object-fit: contain; filter: drop-shadow(0 26px 30px rgba(0, 0, 0, 0.5));
}
.convite__dizer { position: relative; padding: clamp(28px, 4vw, 46px); align-self: center; }
.convite__fechar {
  position: absolute; top: 14px; right: 14px; width: 36px; height: 36px;
  display: grid; place-items: center; background: none; border: 0; cursor: pointer; color: var(--tinta);
}
.convite__fechar svg { width: 18px; height: 18px; stroke: currentColor; stroke-width: 1.6; fill: none; }
.convite__dizer h2 { font-size: clamp(26px, 2.6vw, 36px); margin: 0 0 14px; }
.convite__dizer > p {
  font-family: var(--face-leitura); font-optical-sizing: auto; line-height: 1.6;
  color: var(--texto-2); margin: 0 0 24px; font-size: 16px;
}
.convite__forma label { display: block; margin-bottom: 8px; color: var(--texto-2); }
.convite__linha { display: grid; grid-template-columns: 1fr auto; gap: 10px; }
.convite__linha input {
  border: 1px solid var(--fio-forte); background: var(--branco); padding: 0 16px; height: 54px;
  font-family: var(--face-corpo); font-size: 15px; color: var(--tinta); min-width: 0;
}
.convite__linha input:focus-visible { outline: 2px solid var(--bronze); outline-offset: 1px; }
.convite__forma .acao { padding-inline: 24px; height: 54px; }
.convite__erro { color: var(--erro); margin: 10px 0 0; font-size: 13.5px; }
.convite__nota { margin: 16px 0 0; color: var(--texto-2); line-height: 1.55; font-size: 12.5px; }

@media (max-width: 720px) {
  .convite__caixa { grid-template-columns: 1fr; }
  .convite__arte { min-height: 190px; }
  .convite__arte img { height: 160px; }
  .convite__linha { grid-template-columns: 1fr; }
}

/* ---------- seletor de idioma ---------- */
.idioma { position: relative; }
.idioma__botao { display: inline-flex; align-items: center; gap: 6px; }
.idioma__sigla { font-size: 11px; letter-spacing: 0.1em; }
.idioma__lista {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 30; min-width: 152px;
  background: var(--branco); border: 1px solid var(--fio);
  box-shadow: 0 22px 40px -22px rgba(20, 18, 21, 0.45);
  display: grid;
}
.idioma__lista[hidden] { display: none; }
.idioma__lista button {
  background: none; border: 0; cursor: pointer; text-align: left;
  padding: 13px 16px; font-family: var(--face-corpo); font-size: 14px; color: var(--tinta);
  transition: background 0.25s ease;
}
.idioma__lista button:hover { background: var(--taupe); }
.idioma__lista button[aria-current='true'] { color: var(--tinta); font-weight: 600; }
@media (max-width: 860px) { .idioma__sigla { display: none; } }
.convite__pronto { margin: 0; font-family: var(--face-leitura); font-size: 16.5px; line-height: 1.6; color: var(--tinta); }

.cena__titulo { text-wrap: balance; }

/* Marca sem foto ainda não é marca vazia: o nome sobe para o meio e ocupa o
   lugar que o frasco vai ocupar quando a foto chegar. Fundo só com geometria
   parece banner que não carregou. */
.vitrola--sem-foto { align-content: center; text-align: center; }
.vitrola--sem-foto .vitrola__nome { font-size: clamp(22px, 2vw, 28px); }
.vitrola--sem-foto .vitrola__frente { margin-top: 10px; }

/* ---------- a arte do banner ----------
   A cena agora é uma imagem, e o texto vive por cima dela. Duas artes por
   cena: a deitada e a em pé. Banner deitado espremido no celular é o erro
   mais comum de loja, porque o assunto da arte fica fora do corte. */
.cena__arte { position: absolute; inset: 0; z-index: 0; display: block; }
.cena__arte img { width: 100%; height: 100%; object-fit: cover; object-position: 66% center; display: block; }

/* O véu existe para a palavra ficar legível por cima de qualquer arte, mesmo
   a que a gente ainda não fez. Ele só escurece o lado do texto, então o
   produto do outro lado continua limpo. */
.cena__grade::before {
  content: ''; position: absolute; inset: -40% -20% -40% -50%; z-index: -1;
  background: linear-gradient(90deg, var(--veu-cena) 0%, var(--veu-cena) 34%, transparent 72%);
}
.cena { --veu-cena: rgba(6, 18, 15, 0.72); }
.cena--claro { --veu-cena: rgba(255, 252, 250, 0.74); }

@media (max-width: 860px) {
  .cena__arte img { object-position: center top; }
  /* No celular o texto desce para o pé da arte, sobre um véu que sobe do
     rodapé: sobrepor o texto no meio taparia justamente o produto. */
  .cena__grade::before {
    inset: auto -20% -10% -20%; height: 72%;
    background: linear-gradient(180deg, transparent 0%, var(--veu-cena) 42%, var(--veu-cena) 100%);
  }
  .cena__grade { align-content: end; min-height: 560px; }
}

@media (max-width: 560px) {
  /* Cabeçalho de celular carrega só o que se usa com o polegar: menu,
     marca, busca e sacola. Conta, favoritos e idioma estão todos dentro da
     gaveta, e empilhar sete ícones em 430px joga a sacola para fora da tela,
     que é o único deles que não pode faltar. */
  .idioma,
  .ferramentas > .ferramenta[aria-label='Minha conta'],
  .ferramentas > .ferramenta[aria-label='Favoritos'] { display: none; }
  .ferramentas { gap: 4px; }
}

@media (max-width: 380px) {
  /* Em 320 a assinatura em corpo cheio, mais três alvos de 44 e as folgas,
     somam mais do que a tela. A assinatura encolhe, que é o único elemento
     ali que ainda se lê menor. */
  .amarracao__barra { gap: 8px; }
  .marca__nome { font-size: 17px; letter-spacing: 0.14em; }
  .marca__linha { font-size: 8.5px; letter-spacing: 0.2em; }
  .ferramentas { gap: 0; }
}
.menu-movel__idioma { display: grid; gap: 10px; padding: 20px 0 4px; border-top: 1px solid var(--fio); }
.menu-movel__idioma .medida { color: var(--texto-2); }
.menu-movel__idioma > div { display: flex; gap: 8px; }
.menu-movel__idioma button {
  flex: 1; padding: 12px 10px; cursor: pointer; background: none;
  border: 1px solid var(--fio-forte); color: var(--tinta);
  font-family: var(--face-corpo); font-size: 14px;
}
.menu-movel__idioma button[aria-current='true'] { border-color: var(--tinta); color: var(--tinta); font-weight: 600; }

/* ---------- rastro ----------
   O único momento com autoria da página, e ele vem do produto: perfume deixa
   rastro. Ao rolar, a arte do banner não sai junto com a página. Ela demora,
   deriva mais devagar que a fala e escurece, do jeito que um rastro se
   dissipa atrás de quem passou. A fala sobe mais rápido e some antes, e é
   essa diferença de velocidade entre as duas camadas que dá a profundidade.

   Tudo por linha do tempo de rolagem do próprio CSS: nenhum ouvinte de
   scroll, nenhum quadro calculado em JavaScript, e o navegador resolve na
   composição. Onde a linha do tempo não existe, a página fica parada e
   inteira, que é o estado correto para uma vitrine. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* A linha do tempo é nomeada no palco e usada lá de dentro. Pedir view()
       direto na arte não funciona: a cena e o palco têm overflow hidden, e
       isso os torna contêineres de rolagem, então a medição passaria a ser
       contra um elemento que não rola e a animação ficaria parada no zero. */
    .palco { view-timeline: --palco block; }
    .cena__arte img {
      animation: rastro linear both;
      animation-timeline: --palco;
      animation-range: exit 0% exit 100%;
    }
    .cena--claro .cena__arte img { animation-name: rastro-claro; }
    .cena__dizer {
      animation: rastro-fala linear both;
      animation-timeline: --palco;
      animation-range: exit 0% exit 72%;
    }

  }
}
/* O rastro agora e so luz. Qualquer deriva, por menor que seja, e uma camada
   andando em velocidade diferente da pagina, e e disso que vem a sensacao de
   nadar. A arte escurece e dessatura ao sair, que da a mesma profundidade sem
   mover um pixel. A fala continua saindo por opacidade, sem subir junto. */
@keyframes rastro {
  to { filter: brightness(0.52) saturate(0.76); }
}
@keyframes rastro-claro {
  to { filter: brightness(1.06) saturate(0.64) opacity(0.6); }
}
@keyframes rastro-fala { to { opacity: 0; } }

/* A régua existe sempre, mesmo sem linha do tempo de rolagem. */
.secao__cabeca { position: relative; padding-bottom: 22px; }
/* Régua curta, não linha atravessando a página. Ela marca o começo da seção
   como um traço editorial e não como divisória de tabela, e continua se
   desenhando ao chegar, que é o gesto que já estava aprovado. */
.secao__cabeca::after {
  content: ''; position: absolute; left: 0; bottom: 0; width: 72px; height: 1px;
  background: currentColor; opacity: 0.34; transform-origin: left center;
}

/* A régua era presa à linha do tempo da rolagem: o traço andava a cada pixel
   rolado. Movimento contínuo ligado ao dedo é o que dá sensação de página viva
   demais. Agora é gesto único, disparado junto com a entrada do cabeçalho, e
   quem rola de volta não o vê desfazer.

   Sem JavaScript a régua já nasce inteira, porque o estado escondido só existe
   quando o script marca o elemento. */
@media (prefers-reduced-motion: no-preference) {
  [data-entra].secao__cabeca::after { scale: 0 1; }
  [data-entra].secao__cabeca.dentro::after {
    scale: 1 1;
    transition: scale 0.5s var(--saida) 0.1s;
  }
}

/* ---------- duas vozes de título ----------
   Serifada em nove títulos seguidos não é editorial, é papel de parede: se
   tudo tem o mesmo peso, nada tem hierarquia. A serifada fica reservada aos
   quatro momentos em que a loja fala por si (palco, guia, casa e convite) e
   a prateleira passa a falar em sans, menor e mais apertada. O salto entre
   as duas é que produz a leitura de revista com preço. */
.secao__cabeca h2,
.faixa-kit h2 {
  font-family: var(--face-corpo);
  font-weight: 600;
  font-size: var(--t-prateleira);
  letter-spacing: -0.028em;
  line-height: 1.06;
}
.secao { padding-block: var(--ritmo-forte) var(--ritmo); }

/* ==================================================================
   VIDRO E LUZ
   Perfume é vidro e luz, então todo efeito da loja sai desses dois
   materiais. É o que faz um punhado de efeitos ler como um sistema em
   vez de uma sacola de truques: a luz sempre vem do cursor, o vidro
   sempre desbota a borda, e nada entra por opacidade solta.
   ================================================================== */

/* ---------- fio de progresso ----------
   Um fio de bronze embaixo do cabeçalho cresce com a página. Diz onde a
   pessoa está numa loja longa, e custa zero JavaScript. */
.amarracao { position: sticky; }
.amarracao::after {
  content: ''; position: absolute; left: 0; bottom: -1px; height: 2px; width: 100%;
  background: linear-gradient(90deg, var(--bronze), var(--bronze));
  transform-origin: left center; scale: 0 1;
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .amarracao::after {
      animation: progresso linear both;
      animation-timeline: scroll(root block);
    }
  }
}
@keyframes progresso { to { scale: 1 1; } }

/* ---------- vidro na ponta do trilho ----------
   O trilho desbota do lado em que ainda há produto escondido. A medida vem
   do próprio script das setas, então a borda só aparece quando é verdade. */
.trilho, .marcas {
  --desbota-esq: 0px; --desbota-dir: 52px;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 var(--desbota-esq),
    #000 calc(100% - var(--desbota-dir)), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 var(--desbota-esq),
    #000 calc(100% - var(--desbota-dir)), transparent 100%);
  transition: -webkit-mask-image 0.4s var(--saida), mask-image 0.4s var(--saida);
}

/* As setas só aparecem quando o ponteiro entra na faixa. Seta permanente
   sobre o produto rouba o primeiro cartão a viagem inteira. */
@media (hover: hover) {
  .trilho-caixa .seta { opacity: 0; transition: opacity 0.3s ease, background 0.3s ease, color 0.3s ease; }
  .trilho-caixa:hover .seta,
  .trilho-caixa:focus-within .seta { opacity: 1; }
  .trilho-caixa .seta:disabled { opacity: 0 !important; }
}

/* ---------- ímã no botão ----------
   O botão principal se aproxima do cursor antes do clique. É o gesto que
   diz "sou eu que você quer" sem precisar piscar nem crescer. */

.acao:active { scale: 0.99; }

/* ---------- cabeçalho de prateleira que gruda ----------
   Enquanto o trilho passa, o nome da prateleira fica. Em loja com muita
   fileira, é o que impede a pessoa de esquecer o que está olhando. */
@media (min-width: 861px) {
  /* O fundo precisa ser opaco e igual ao da seção, senão o cartão passa por
     baixo do título enquanto rola. Na faixa escura o fundo é gradiente e não
     tem cor chapada que sirva, então lá o título não gruda: melhor não grudar
     do que grudar com remendo. */
  .secao__cabeca {
    position: sticky; top: 78px; z-index: 6;
    background: var(--marfim); padding-top: 10px;
  }
  .secao--taupe .secao__cabeca { background: var(--taupe); }
  /* A faixa escura não gruda e, principalmente, não herda o fundo de papel:
     texto branco sobre papel é ilegível. */
  .secao--grife .secao__cabeca { position: static; padding-top: 0; background: transparent; }
}

/* ---------- o nome do produto se sublinha ---------- */
.peca__nome { background-image: linear-gradient(var(--bronze), var(--bronze)); background-repeat: no-repeat; background-position: 0 100%; background-size: 0 1px; transition: background-size 0.45s var(--saida); }
.peca:hover .peca__nome { background-size: 100% 1px; }


/* ---------- o bloco que conversa ----------
   A página inteira fala de produto. Este bloco fala com a pessoa, e por isso
   ele é o único em forma de pergunta. Também quebra a monotonia de cabeçalho
   mais fileira repetida quatro vezes, que é o que faz página de loja cansar
   antes do rodapé. */
.guia { background: var(--garrafa); color: var(--taupe); padding-block: var(--ritmo-forte); }
.guia__grade {
  display: grid; grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(32px, 5vw, 80px); align-items: center;
}
.guia__dizer h2 {
  color: var(--branco); font-size: var(--t-editorial);
  letter-spacing: -0.042em; line-height: 1.04; margin: 0 0 18px; text-wrap: balance;
}
.guia__dizer p {
  font-family: var(--face-leitura); font-optical-sizing: auto;
  font-size: 16.5px; line-height: 1.62; margin: 0; max-width: 40ch;
  color: rgba(247, 244, 239, 0.84);
}
.guia__rotas { list-style: none; margin: 0; padding: 0; display: grid; }
.guia__rotas li + li { border-top: 1px solid rgba(247, 244, 239, 0.2); }
.guia__rotas a {
  display: grid; grid-template-columns: 1fr auto; align-items: center;
  column-gap: 24px; padding: clamp(20px, 2.2vw, 30px) 0;
  /* translate, não padding: padding repagina a linha inteira a cada quadro,
     e isso acontece justamente enquanto o cursor está em cima. */
  transition: translate 0.4s var(--saida);
}
.guia__pergunta {
  grid-column: 1; display: block;
  font-family: var(--face-corpo); font-weight: 600;
  letter-spacing: -0.026em; font-size: var(--t-bloco); line-height: 1.22;
}
.guia__resposta {
  grid-column: 1; display: block; margin-top: 8px;
  font-family: var(--face-leitura); font-optical-sizing: auto;
  font-size: 15px; line-height: 1.55; max-width: 52ch;
  color: rgba(247, 244, 239, 0.8);
}
.guia__seta {
  grid-column: 2; grid-row: 1 / -1; display: grid; place-items: center;
  width: 44px; height: 44px; border: 1px solid rgba(247, 244, 239, 0.3);
  transition: background 0.35s var(--saida), border-color 0.35s var(--saida),
    translate 0.35s var(--saida);
}
.guia__seta svg { width: 18px; height: 18px; stroke: currentColor; stroke-width: 1.5; fill: none; }
.guia__rotas a:hover .guia__seta { background: var(--rosa); border-color: var(--rosa); translate: 5px 0; color: var(--tinta); }
.guia__rotas a:hover .guia__pergunta { color: var(--rosa); }
@media (hover: hover) { .guia__rotas a:hover { translate: 10px 0; } }

@media (max-width: 860px) {
  .guia__grade { grid-template-columns: 1fr; gap: 28px; }
  .guia__resposta { font-size: 14.5px; }
  .guia__seta { width: 38px; height: 38px; }
}

/* ---------- área de toque ----------
   O dedo não tem ponta fina. Toda coisa clicável precisa de 44px de altura
   real, mesmo quando o desenho dela é um fio de 3px: aumenta a área, não o
   desenho. Isso se faz com padding mais background-clip, nunca engordando
   o elemento visível. */
@media (max-width: 860px) {


  /* O hambúrguer e o fechar do menu vinham com 33 e 31 de largura porque a
     regra só valia para .ferramenta genérica. O favorito parava em 43, um
     pixel abaixo do mínimo, que reprova igual a quarenta. */
  .ferramenta, .hamburguer, .busca-movel, .menu-movel__fechar { width: 44px; height: 44px; min-width: 44px; }

  /* Links de TEXTO ganham altura de toque sem ganhar altura visual: o padding
     entra e a margem negativa devolve o espaço ao layout.

     O botão de ação fica de fora. Ele já tem 17px de padding em cima e em
     baixo, então o alvo dele nunca foi o problema; o que a regra fazia era
     trocar o display dele para inline-block, e aí a seta, que é um span sem
     tamanho próprio dentro de um flex, deixava de ser item de flex e crescia
     até 168px. O botão "Ver a prateleira inteira" virava um quadrado vazio
     de 230 por 214 em toda tela abaixo de 860px. */
  .secao__cabeca a:not(.acao):not(.acao-secundaria),
  .rodape a:not(.acao):not(.acao-secundaria),
  .rodape__lista a,
  .marca {
    display: inline-block;
    padding-block: 14px;
    margin-block: -14px;
  }
  .menu-movel__pe a { padding-block: 12px; }
  .rodape__lista li + li { margin-top: 4px; }
}

/* No desktop o alvo pode ser menor, mas o foco de teclado nunca pode sumir
   atrás de um elemento grudado. */
:focus-visible { scroll-margin-block: 120px; }

/* ---------- a casa ----------
   A loja nunca dizia quem era. Uma frase só, grande, em papel, sem ícone e
   sem caixa: numa página cheia de produto, o silêncio em volta é o que faz
   a voz da casa ser ouvida. O texto é o diferencial real registrado no
   PRODUCT.md, não promessa inventada. */
.casa { padding-block: calc(var(--ritmo-forte) * 1.1); border-top: 1px solid var(--fio); }
.casa__grade { max-width: 58ch; margin-inline: auto; text-align: center; }
.casa__marca { display: block; color: var(--bronze-texto); margin: 0 0 22px; }
.casa h2 {
  font-size: clamp(25px, 3vw, 40px);
  letter-spacing: -0.04em; line-height: 1.1; margin: 0 0 22px;
  text-wrap: balance;
}
.casa__texto {
  font-family: var(--face-leitura); font-optical-sizing: auto;
  font-size: 17px; line-height: 1.68; margin: 0; color: var(--texto-2);
  max-width: 52ch; margin-inline: auto;
}
@media (max-width: 860px) {
  .casa { padding-block: var(--ritmo-forte); }
  .casa__texto { font-size: 15.5px; }
}

/* ---------- estado de indisponibilidade ----------
   "Preço a definir" era nota interna vazando para a vitrine. "Em breve" é
   estado de loja, e é verdade: o produto ainda não está à venda. Ele ocupa a
   mesma altura do preço para o rodapé dos cartões continuar alinhado. */
/* Sem preço, o rodapé do cartão não finge um preço apagado: ele oferece o
   que a loja realmente pode oferecer hoje. Fica na mesma altura do preço para
   o rodapé dos vizinhos continuar alinhado, mas com peso e traço de ação, não
   de valor desativado. */
.peca__avisar {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--face-corpo); font-size: 13px; font-weight: 500;
  letter-spacing: -0.004em; color: var(--tinta);
  min-height: calc(var(--t-preco) * 1.1);
  border-bottom: 1px solid currentColor; padding-bottom: 2px;
  transition: color 0.3s ease;
}
.peca:hover .peca__avisar { color: var(--bronze-texto); }

/* O frasco respira mais dentro do poço: produto encostado na borda pesa, e
   peso é o oposto do que uma vitrine de perfume quer transmitir. */
.peca__retrato img { inset: 17px; width: calc(100% - 34px); height: calc(100% - 34px); }

/* ---------- âncora sob cabeçalho grudado ----------
   Sem isso, clicar em "Kits" leva à seção mas o cabeçalho cobre o título, e
   a pessoa acha que o link está errado. */
:where(#importados, #arabes, #beleza, #marcas, #kits) { scroll-margin-top: 96px; }

/* ---------- a caixa do cartão e o favorito ----------
   O cartão continua sendo um link inteiro, fácil de acertar. O favorito é
   irmão dele, e não filho: botão dentro de âncora é HTML inválido, e
   navegador e leitor de tela resolvem isso cada um de um jeito errado. */
.peca-caixa { position: relative; display: grid; }
.trilho > .peca-caixa, .grade > .peca-caixa { scroll-snap-align: start; }

.favorito {
  position: absolute; top: 10px; right: 10px; z-index: 3;
  width: 44px; height: 44px; display: grid; place-items: center;
  background: rgba(255, 255, 255, 0.86); border: 0; cursor: pointer;
  color: var(--texto-2);
  opacity: 0; translate: 0 -4px;
  transition: opacity 0.35s var(--saida), translate 0.35s var(--saida),
    color 0.3s ease, background 0.3s ease;
}
.favorito svg { width: 18px; height: 18px; stroke: currentColor; stroke-width: 1.5; fill: none; }
.favorito:hover { color: var(--bronze); background: var(--branco); }
.favorito[aria-pressed='true'] { opacity: 1; translate: 0 0; color: var(--bronze); }
.favorito[aria-pressed='true'] svg { fill: var(--bronze); stroke: var(--bronze); }
.peca-caixa:hover .favorito,
.peca-caixa:focus-within .favorito { opacity: 1; translate: 0 0; }

/* No toque não existe hover, então o favorito fica sempre visível e no
   tamanho do dedo. Esconder ação atrás de hover no celular é escondê-la. */
@media (hover: none) {
  .favorito { opacity: 1; translate: 0 0; width: 44px; height: 44px; background: rgba(255, 255, 255, 0.92); }
}

/* ---------- acabamento do cartão no hover ----------
   Quatro coisas pequenas ao mesmo tempo, nenhuma delas grande: a foto se
   aproxima, o poço clareia, o nome se sublinha e a compra rápida sobe. */
.peca__retrato img { transition: transform 0.9s var(--saida); }
.peca:hover .peca__retrato img { transform: scale(1.045); }
.peca__retrato { transition: background 0.5s var(--saida); }
.peca:hover .peca__retrato { background: var(--taupe-fundo); }

/* ---------- entrada ao rolar ----------
   Três gestos, não um. Sobe para o que é informação, entra de lado para o que
   é editorial, e cresce quase nada para o que é produto. A mesma entrada
   repetida em toda seção é papel de parede, não ritmo.

   O estado escondido depende do atributo que o script escreve, então a página
   sem JavaScript nasce inteira visível. Vitrine escondida por animação que não
   rodou é venda perdida. */
@media (prefers-reduced-motion: no-preference) {
  /* Um gesto so, e curto.

     Antes eram tres: subir, vir de lado e escalar. Com onze elementos visiveis
     de uma vez, cada um chegando de uma direcao diferente ao longo de 850ms
     mais ate 540ms de escada, a pagina nunca ficava parada. Lido de perto isso
     e exatamente uma onda, e o movimento lateral e o que faz tudo parecer
     desenquadrado, porque um vizinho chega pela esquerda enquanto o outro sobe.

     Agora e sempre a mesma subida de nove pixels, em 420ms. Curto o bastante
     para ja ter terminado quando o olho chega, e igual para todo mundo, que e
     o que deixa a fileira assentar em vez de balancar. */
  [data-entra] { opacity: 0; translate: 0 9px; will-change: opacity, translate; }

  /* Area grande so aparece, nao anda. Uma prateleira inteira subindo nove
     pixels e um bloco de meia tela se deslocando, e bloco grande em movimento
     chama muito mais atencao do que peca pequena. O cabecalho e os itens
     miudos continuam subindo, que e o que da o sentido de chegada. */
  [data-entra].trilho-caixa,
  [data-entra].campanha__palco,
  [data-entra].portal { translate: none; }

  [data-entra].dentro {
    opacity: 1; translate: 0 0; will-change: auto;
    transition:
      opacity 0.42s var(--saida),
      translate 0.42s var(--saida);
    transition-delay: calc(var(--i, 0) * var(--passo, 0ms));
  }
}

/* ---------- microinterações ----------
   Pequenas, curtas e com função: cada uma responde a um gesto e nenhuma
   acontece sozinha. */
.seta, .palco__seta { transition: background 0.3s ease, color 0.3s ease, border-color 0.3s ease, scale 0.25s var(--saida); }
.seta:active, .palco__seta:active { scale: 0.94; }

/* Link de seção: o traço cresce da esquerda em vez de acender inteiro. */
.secao__cabeca a:not(.acao):not(.acao-secundaria) {
  border-bottom: 0;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat; background-position: 0 100%; background-size: 100% 1px;
  transition: background-size 0.4s var(--saida), color 0.3s ease;
}
.secao__cabeca a:not(.acao):not(.acao-secundaria):hover { background-size: 0 1px; color: var(--bronze-texto); }

/* A ação principal responde ao toque antes de responder ao clique. */
.acao:active { scale: 0.985; }

/* O botão de compra rápida chega deslizando de baixo, não piscando. */
.peca__rapido { transition: translate 0.42s var(--saida), background 0.3s ease; }

/* ---------- cabeçalho de seção com controles ---------- */
.secao__cabeca { gap: 16px; }
.secao__cabeca > a, .secao__cabeca > .acao-secundaria { margin-left: auto; }
.secao__cabeca > .acao-secundaria + .secao__setas,
.secao__cabeca > a + .secao__setas { margin-left: 0; }
.secao__cabeca > div:first-child { flex: 1 1 auto; min-width: 0; }
.secao__setas { align-self: center; }
.seta:disabled { opacity: 0.25; cursor: default; }
.seta:not(:disabled):hover { background: var(--tinta); color: var(--marfim); }
.secao--grife .seta { border-color: rgba(247, 244, 239, 0.42); color: var(--taupe); background: none; }
.secao--grife .seta:not(:disabled):hover { background: var(--taupe); color: var(--garrafa); }

/* ---------- marca sem fotografia ----------
   Não é card vazio esperando imagem: é uma composição tipográfica própria, no
   mesmo sistema das outras. O nome ocupa o centro, a geometria da casa dá o
   fundo e o rótulo embaixo fecha, na mesma posição dos cards com frasco.
   Quando a foto oficial chegar, ela entra e o card troca de composição sem
   trocar de sistema. */
.vitrola--sem-foto {
  align-content: stretch;
  grid-template-rows: 1fr auto;
  text-align: left;
}
.vitrola--sem-foto .vitrola__selo { inset: -6% -16% 16% -16%; opacity: 0.3; }
.vitrola--sem-foto::before {
  content: attr(data-marca);
  grid-row: 1; align-self: center; justify-self: center;
  position: relative; z-index: 2;
  font-family: var(--face-corpo); font-weight: 600;
  font-size: clamp(22px, 2.1vw, 30px); line-height: 1.08;
  letter-spacing: -0.015em; text-align: center; padding: 0 14px;
  max-width: 90%;
}
.vitrola--sem-foto .vitrola__nome { display: none; }
.vitrola--sem-foto .vitrola__dizer { grid-row: 2; }

/* ---------- Avise-me quando chegar ----------
   Link, não botão: ele não pode competir com o nome do produto. O traço
   cresce da esquerda e a seta anda um passo, e é só isso. */
.peca__avisar {
  border-bottom: 0; padding-bottom: 3px;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat; background-position: 0 100%;
  background-size: 0 1px;
  transition: background-size 0.45s var(--saida), color 0.3s ease;
}
.peca__avisar::after {
  content: ''; width: 12px; height: 1px; background: currentColor;
  position: relative; opacity: 0; translate: -5px 0;
  transition: opacity 0.35s var(--saida), translate 0.35s var(--saida);
}
.peca:hover .peca__avisar,
.peca:focus-visible .peca__avisar { background-size: 100% 1px; }
.peca:hover .peca__avisar::after,
.peca:focus-visible .peca__avisar::after { opacity: 1; translate: 0 0; }

/* Sem hover o estado tem que existir mesmo assim, senão no celular o link
   parece texto morto. */
@media (hover: none) {
  .peca__avisar { background-size: 100% 1px; }
  .peca__avisar::after { opacity: 1; translate: 0 0; }
}


/* ---------- encaixe só onde ele serve ----------
   O scroll-snap ajuda o arrasto com o dedo, mas cancela a rolagem suave que
   as setas pedem, e no computador a seta é o controle principal. Então ele
   vale para ponteiro grosso, que é dedo, e fica fora do ponteiro fino. */
@media (pointer: coarse) {
  .trilho, .marcas { scroll-snap-type: x proximity; }
  .trilho > *, .marcas > * { scroll-snap-align: start; }
}

/* ==================================================================
   CAMPANHA
   A promessa da loja aparecia cinco vezes em texto. Aqui ela acontece
   uma vez, em tamanho de campanha: um frasco grande, os três andares
   escritos, e o link para a página onde o resto está.

   É o único bloco da home onde a serifada cresce fora do palco, e é de
   propósito: campanha é a segunda voz editorial, não uma prateleira. */
.campanha {
  background: var(--taupe);
  padding-block: calc(var(--ritmo-forte) * 1.05);
  overflow: hidden;
}
.campanha__grade {
  display: grid; grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  gap: clamp(32px, 5vw, 76px); align-items: center;
}

/* O frasco flutua sobre a marca de doze pontas, que fica em água: ela dá
   fundo à foto recortada sem virar moldura nem caixa. */
/* Altura medida em vez de proporção: com proporção o palco se estica ao
   conteúdo e o bloco ganha 200px de vazio abaixo do texto. */
.campanha__palco { position: relative; display: grid; place-items: center;
  height: clamp(320px, 38vw, 540px); min-height: 0; }
.campanha__marca {
  position: absolute; inset: 0; width: 100%; height: 100%;
  fill: var(--tinta); stroke: none; opacity: 0.05;
  rotate: -8deg;
}
/* Altura em medida, não em percentual nem em auto. Percentual depende de o pai
   ter altura resolvida na hora em que o navegador mede a foto, e nem todo
   renderizador chega lá na mesma ordem: num render de página inteira a foto
   voltava ao tamanho natural e vazava por baixo da seção. Auto era pior: antes
   de a foto carregar a caixa media 0x0 e a imagem aparecia estourando de nada.
   Com altura fixa e a proporção vinda dos atributos, o lugar já está guardado. */
.campanha__frasco {
  position: relative; width: auto; height: clamp(280px, 33vw, 470px);
  max-width: 76%; object-fit: contain;
  filter: drop-shadow(0 38px 46px rgba(20, 18, 21, 0.24));
  transition: translate 0.9s var(--saida);
}
.campanha:hover .campanha__frasco { translate: 0 -10px; }

.campanha__rotulo { display: block; color: var(--bronze-texto); margin-bottom: 14px; }
.campanha h2 {
  font-size: var(--t-editorial); letter-spacing: -0.038em; line-height: 1.02;
  margin: 0 0 clamp(24px, 3vw, 36px); max-width: 17ch;
}

/* Três andares, e o fio entre eles é o que resta de moldura. A medida
   fica na coluna estreita, para o nome das notas começar sempre no mesmo
   ponto e a lista ler como ficha, não como parágrafo. */
.campanha__andares { list-style: none; margin: 0 0 clamp(28px, 3vw, 38px); padding: 0; }
.campanha__andares li {
  display: grid; grid-template-columns: 84px minmax(0, 1fr);
  gap: 4px 18px; align-items: baseline;
  padding: 16px 0; border-top: 1px solid var(--fio);
}
.campanha__andares li:last-child { border-bottom: 1px solid var(--fio); }
.campanha__andares .medida { color: var(--texto-2); }
.campanha__andares strong {
  font-family: var(--face-corpo); font-weight: 500; font-size: 16px;
  letter-spacing: -0.012em;
}
.campanha__nota {
  grid-column: 2; font-family: var(--face-leitura); font-optical-sizing: auto;
  font-size: 14px; line-height: 1.55; color: var(--texto-2);
}

@media (max-width: 900px) {
  .campanha__grade { grid-template-columns: 1fr; gap: 28px; }
  .campanha__palco { height: clamp(260px, 56vw, 380px); }
  .campanha h2 { max-width: none; }
}
@media (max-width: 480px) {
  .campanha__andares li { grid-template-columns: 1fr; gap: 3px; }
  .campanha__nota { grid-column: 1; }
}

/* ==================================================================
   PASSAGEM
   A virada da perfumaria para a beleza. A mídia nasce centrada em 72%
   da largura útil e abre até a borda conforme a seção atravessa a tela.

   Quem move é uma linha do tempo de rolagem do próprio CSS. Não existe
   ouvinte, não existe preventDefault, não existe scrollTo, não existe
   trava: o navegador lê a posição da seção e resolve a interpolação no
   compositor. Onde essa linha do tempo não existir, o bloco fica no
   estado final, que é a composição bonita, e um caminho de reserva em
   JavaScript assume com rAF e ouvinte passivo.

   O trilho é alto e o miolo é sticky. A faixa usada é `contain`, que é
   exatamente o trecho em que o trilho cobre a tela inteira, ou seja o
   tempo em que o sticky está preso. */
.passagem {
  background: var(--marfim);
  padding-block: var(--ritmo) 0;
}
.passagem__trilho {
  height: 200vh;
  view-timeline-name: --passagem;
  view-timeline-axis: block;
}
.passagem__fixo {
  position: sticky; top: 0;
  height: 100vh; min-height: 520px;
  display: grid; place-items: center;
  overflow: hidden;
}

/* Estado final por padrão: sem linha do tempo e sem script, é isto que
   se vê. Nada de bloco preso num meio-termo. */
.passagem__midia {
  position: absolute; inset: 0;
  margin: 0; overflow: hidden; width: 100%; height: 100%;
}
.passagem__midia img {
  width: 100%; height: 100%; object-fit: cover; object-position: center;
}

@keyframes passagem-abrir {
  from { width: 72%; height: 66%; border-radius: 4px; }
  to   { width: 100%; height: 100%; border-radius: 0; }
}
@keyframes passagem-recuar {
  from { translate: 0 0; opacity: 1; }
  to   { translate: 0 -18px; opacity: 0.66; }
}

@media (prefers-reduced-motion: no-preference) {
  .passagem__midia {
    position: absolute; inset: auto;
    animation: passagem-abrir linear both;
    animation-timeline: --passagem;
    animation-range: contain 0% contain 100%;
  }
  /* A fala sobe pouco e perde um terço da opacidade. Percurso curto de
     propósito: texto atravessando a tela é o que embrulha o estômago de
     quem rola. */
  .passagem__dizer {
    animation: passagem-recuar linear both;
    animation-timeline: --passagem;
    animation-range: contain 0% contain 100%;
  }
}

/* Reserva para quem não tem linha do tempo de rolagem: o script escreve
   --abre e estas regras passam a valer. */
.passagem[data-reserva] .passagem__midia {
  position: absolute; inset: auto;
  animation: none;
  width: calc(72% + 28% * var(--abre, 0));
  height: calc(66% + 34% * var(--abre, 0));
  border-radius: calc(4px - 4px * var(--abre, 0));
}
.passagem[data-reserva] .passagem__dizer {
  animation: none;
  translate: 0 calc(-18px * var(--abre, 0));
  opacity: calc(1 - 0.34 * var(--abre, 0));
}

.passagem__dizer {
  position: relative; z-index: 2;
  width: min(var(--largura), 100%);
  padding-inline: var(--gutter);
  text-align: center;
  color: var(--texto);
}
.passagem__rotulo { display: block; color: var(--bronze-texto); margin-bottom: 16px; }
.passagem h2 {
  font-family: var(--face-display); font-weight: var(--peso-display);
  font-optical-sizing: auto; letter-spacing: var(--tracking-display);
  line-height: var(--entrelinha-display);
  font-size: var(--t-editorial); margin: 0 0 14px;
}
.passagem__linha {
  font-size: var(--t-apoio); line-height: 1.6; color: var(--texto-2);
  margin: 0 auto 28px; max-width: 42ch;
}
/* A fala fica sobre a foto, então ela leva o próprio véu de marfim em
   vez de depender da cor da imagem embaixo. */
.passagem__dizer::before {
  content: ''; position: absolute; z-index: -1;
  inset: -34px -24px;
  background: radial-gradient(60% 72% at 50% 50%, rgba(247, 244, 239, 0.94) 0%, rgba(247, 244, 239, 0.78) 58%, rgba(247, 244, 239, 0) 100%);
}

@media (max-width: 760px) {
  /* No celular o sticky de tela inteira briga com a barra do navegador,
     que entra e sai e muda a altura no meio do gesto. Aqui a seção vira
     bloco comum: a mídia é quase integral, não há trilho, não há linha do
     tempo, e o texto não se mexe. */
  .passagem { padding-block: var(--ritmo); }
  .passagem__trilho { height: auto; view-timeline-name: none; }
  .passagem__fixo {
    position: static; height: auto; min-height: 0;
    display: block; overflow: visible;
  }
  .passagem__midia,
  .passagem[data-reserva] .passagem__midia {
    position: relative; inset: auto; animation: none;
    width: 94%; height: auto; aspect-ratio: 16 / 11;
    margin-inline: auto; border-radius: 3px;
  }
  .passagem__dizer,
  .passagem[data-reserva] .passagem__dizer {
    animation: none; translate: none; opacity: 1;
    margin-top: 26px; text-align: left;
  }
  .passagem__dizer::before { display: none; }
  .passagem__linha { margin-inline: 0; }
}

@media (prefers-reduced-motion: reduce) {
  /* Composição final, parada. Nada ligado à rolagem. */
  .passagem__trilho { height: auto; view-timeline-name: none; }
  .passagem__fixo { position: static; height: auto; min-height: 0; overflow: visible; }
  .passagem__midia,
  .passagem[data-reserva] .passagem__midia {
    position: relative; inset: auto; animation: none;
    width: 100%; height: auto; aspect-ratio: 24 / 10; border-radius: 0;
  }
  .passagem__dizer,
  .passagem[data-reserva] .passagem__dizer {
    animation: none; translate: none; opacity: 1; margin-top: 26px;
  }
  .passagem__dizer::before { display: none; }
}

/* ---------- o frasco ganha o cartão ----------
   Medindo a referência que o dono da loja apontou contra a nossa prateleira,
   lado a lado e no tamanho real, a diferença não era cor nem efeito: era
   tamanho de produto. O frasco dela ocupa a largura inteira do cartão. O
   nosso estava afundado três vezes: 11px de padding do cartão, mais 12px do
   poço, mais 17px de recuo da imagem. Quarenta pixels de margem em volta de
   um frasco de duzentos, com cinco colunas em vez de quatro. O resultado é
   miniatura dentro de moldura, que lê como catálogo.

   Aqui a foto encosta na borda do cartão e o texto é que recebe o respiro.
   Quatro colunas e um naco da quinta, para a fileira continuar dizendo que
   tem mais produto do lado. */
.trilho {
  grid-auto-columns: calc((100% - 4 * var(--gap-cartao)) / 4.2);
}
.grade { grid-template-columns: repeat(auto-fill, minmax(264px, 1fr)); }
@media (max-width: 1080px) { .trilho { grid-auto-columns: calc((100% - 3 * var(--gap-cartao)) / 3.2); } }
@media (max-width: 820px)  { .trilho { grid-auto-columns: calc((100% - 2 * var(--gap-cartao)) / 2.3); }
                             .grade  { grid-template-columns: repeat(auto-fill, minmax(208px, 1fr)); } }
@media (max-width: 540px)  { .trilho { grid-auto-columns: calc((100% - var(--gap-cartao)) / 1.42); } }

.peca { padding: 0 0 16px; }
.peca__retrato { padding: 0; margin-bottom: 14px; }
.peca__retrato img { inset: 10px; width: calc(100% - 20px); height: calc(100% - 20px); }
/* O texto fica com o recuo que a foto devolveu, e não encostado na borda. */
.peca__marca, .peca__nome, .peca__rodape, .peca__avisar { padding-left: 14px; padding-right: 14px; }
.peca__selo { top: 12px; left: 12px; }
/* No toque o botão fica sempre visível, e no PÉ da foto.
   Ele estava `position: static` dentro de um poço `place-items: center`, ou
   seja: um botão de 149px parado no meio do frasco, tapando o produto que o
   cartão existe para mostrar. Continuar absoluto e só desligar o deslize
   devolve a barra inteira rente à base, que é onde a referência põe a dela. */
@media (hover: none) {
  .peca__rapido {
    position: absolute; left: 0; right: 0; bottom: 0;
    transform: none; min-height: 44px; padding: 12px 10px;
  }
  .peca__retrato { margin-bottom: 14px; }
  .peca__marca { margin-top: 0; }
}

/* ---------- profundidade na rolagem das faixas ----------
   A faixa de campanha é a única imagem grande no meio da página, e imagem
   grande parada no meio de prateleira lê como anúncio colado. Aqui a arte
   anda mais devagar que a página enquanto passa, e a diferença de velocidade
   é o que dá profundidade: a faixa vira janela, não adesivo.

   É animação de rolagem do próprio CSS, sem JavaScript e sem ouvinte de
   scroll, então ela roda na linha de composição e não disputa a thread
   principal com o resto da loja. Onde o navegador não tem `view()`, a arte
   fica parada e a faixa continua inteira: o @supports garante que nada é
   escondido à espera de um efeito que não vai acontecer.

   Dez por cento de curso ao longo da passagem inteira. Pouco o bastante para
   a pessoa sentir e não ver, que é a diferença entre profundidade e onda. */
@keyframes faixa-profundidade {
  from { translate: 0 -5%; }
  to   { translate: 0 5%; }
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .faixa-campanha__arte img {
      /* 12% de folga cobre os 5% de curso de cada lado sem nunca descobrir
         a borda da arte dentro da faixa. */
      scale: 1.12;
      animation: faixa-profundidade linear both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
      will-change: translate;
    }
  }
}

/* ---------- transição entre páginas ----------
   Navegar numa loja é trocar de prateleira, não trocar de site. O corte seco
   entre duas páginas que compartilham cabeçalho, papel e tipografia desfaz
   essa sensação a cada clique.

   `navigation: auto` é a transição de documento do próprio navegador: ela não
   atrasa a navegação, não depende de JavaScript e não deixa página em branco
   se algo falhar, porque quem orquestra é o navegador e não um temporizador
   nosso. Sem suporte, a troca é a de sempre.

   O cabeçalho ganha nome próprio para ficar parado durante a troca, em vez de
   piscar junto com o corpo. É ele que diz à pessoa que ela continua na mesma
   loja. */
@view-transition { navigation: auto; }

@media (prefers-reduced-motion: no-preference) {
  .amarracao { view-transition-name: cabecalho; }
  ::view-transition-group(cabecalho) { animation-duration: 0.01s; }

  /* O frasco é o mesmo objeto nas duas páginas, então ele não deve sumir e
     renascer: ele cresce do cartão para o retrato. O nome é escrito pelo
     script no cartão que foi clicado, e só nele, porque dois elementos com o
     mesmo nome cancelam a transição inteira. */
  ::view-transition-group(frasco) {
    animation-duration: 0.42s;
    animation-timing-function: var(--saida);
  }
  ::view-transition-old(root),
  ::view-transition-new(root) { animation-duration: 0.3s; }
}

/* ---------- cena editorial com frasco ----------
   O palco de banner mostra arte pronta. Esta variante mostra PRODUTO: um
   frasco só, grande, sobre chão de cor, com nome, marca e um caminho para
   comprar. É a forma que a referência usa e que o enfileirado não alcança,
   porque nove produtos lado a lado em 375px não vendem nenhum.

   O frasco é posicionado, não dimensionado por porcentagem, pela mesma conta
   que o cartão de marca já usa: `--alvo` é a altura que o PRODUTO deve ter na
   tela, `--p-alt` é quanto do arquivo o produto ocupa, então a altura do
   arquivo é a divisão das duas. Sem isso, um frasco com folga no arquivo
   aparece menor que um sem folga, e a fileira fica desalinhada. */
/* As duas medidas moram na CENA, e nao no frasco: a sombra e irma do frasco,
   nao filha, entao declarar nele deixaria a sombra com o valor de reserva e
   as duas sairiam de lugares diferentes. */
.cena--frasco {
  min-height: clamp(520px, 72vh, 720px);
  --alvo: 58%;          /* altura do produto na cena */
  --linha: 74%;         /* onde ele apoia */
}
.cena--frasco .cena__grade { grid-template-columns: minmax(0, 46%); }
.cena--frasco .cena__grade::before { display: none; }

.cena__frasco {
  position: absolute; z-index: 0;
  right: 9%;
  width: auto;
  height: calc(var(--alvo) / var(--p-alt, 0.85));
  top: calc(var(--linha) - (var(--alvo) / var(--p-alt, 0.85)) * var(--p-base, 0.855));
  object-fit: contain;
  filter: drop-shadow(0 28px 34px var(--sombra, rgba(0, 0, 0, 0.5)));
}

/* A sombra de contato é elíptica e fica no CSS, não assada no pixel, para
   poder acompanhar o frasco quando ele se mexe. Mesma decisão do cartão. */
.cena__chao {
  position: absolute; z-index: 0; left: auto; right: 9%;
  top: var(--linha, 74%);
  width: calc(var(--alvo, 58%) * 0.52);
  height: calc(var(--alvo, 58%) * 0.085);
  translate: 0 -50%;
  background: radial-gradient(closest-side ellipse at 50% 50%,
    var(--sombra, rgba(0, 0, 0, 0.5)) 0%,
    color-mix(in srgb, var(--sombra, rgba(0,0,0,0.5)) 55%, transparent) 48%,
    transparent 100%);
  pointer-events: none;
}

/* O frasco respira ao entrar, uma vez só e curto: sobe dois por cento e
   assenta. Não é flutuação contínua, que é o que transforma vitrine em
   protetor de tela. */
@media (prefers-reduced-motion: no-preference) {
  .cena--frasco .cena__frasco {
    animation: frasco-assenta 0.9s var(--saida) both;
  }
}
@keyframes frasco-assenta {
  from { opacity: 0; translate: 0 3%; }
  to   { opacity: 1; translate: 0 0; }
}

@media (max-width: 860px) {
  /* Em pé o frasco vai para o centro, na metade de cima, e o texto fica
     embaixo dele. Lado a lado não cabe: frasco à direita num celular deixa
     metade da tela vazia e a outra metade apertada.

     A primeira versão punha os dois no meio e o texto caía EM CIMA do
     frasco, com o pé do frasco ainda passando por baixo da barra de abas.
     Agora a cena ancora o texto no pé, o frasco apoia aos 60% e a barra de
     abas tem folga reservada. */
  .cena--frasco {
    min-height: clamp(620px, 84vh, 820px);
    align-items: end;
    --alvo: 40%; --linha: 60%;
  }
  .cena--frasco .cena__grade {
    grid-template-columns: minmax(0, 100%);
    padding-block: 0 78px;
  }
  .cena__frasco { right: auto; left: 50%; translate: -50% 0; }
  .cena__chao   { right: auto; left: 50%; translate: -50% -50%; }
  /* O véu não entra aqui. Ele existe para a palavra ficar legível sobre
     fotografia qualquer, e a 72% de verde escuro ele apagava o frasco.
     Pior: a cena clara tem texto ESCURO, e o véu escuro por baixo dele
     inverteria o contraste em vez de salvar. Aqui o fundo é gradiente
     nosso, o texto fica abaixo do frasco e cada cena já traz a cor de
     texto provada contra o próprio chão. Medido adiante. */
  .cena--frasco .cena__grade::before { display: none; }
  @media (prefers-reduced-motion: no-preference) {
    .cena--frasco .cena__frasco { animation-name: frasco-assenta-pe; }
  }
  @keyframes frasco-assenta-pe {
    from { opacity: 0; translate: -50% 3%; }
    to   { opacity: 1; translate: -50% 0; }
  }
}

/* O botão da cena precisa de contorno próprio.

   Ele é marfim, o que funciona sobre chão escuro: 18 de contraste contra a
   cena árabe e 17 contra a de grife. Sobre a cena clara, porém, marfim sobre
   rosa pálido mede 1.36, e a regra para contorno de controle é 3. Na prática
   o botão deixava de ter forma e virava palavra solta no meio do fundo.

   A linha usa a cor de texto da própria cena, que já é provada contra aquele
   chão. Em cena escura ela é marfim sobre marfim e desaparece, que é o certo,
   porque lá o botão já se resolve sozinho. Entra como sombra interna para não
   empurrar o texto um pixel quando aparece. */
.cena--frasco .acao {
  /* 38% media 1.76 e continuava reprovando: misturada sobre o marfim do
     botao a linha clareava demais. A 70% ela da 4.7 contra o rosa palido
     e continua invisivel sobre chao escuro, que e o que se quer. */
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--sobre) 70%, transparent);
}
