/* ==========================================================================
   Mercado do Mar — componentes
   Depende de tokens.css, que deve ser carregado ANTES deste arquivo.
   Nenhum valor bruto de cor, corpo ou espaço aqui — sempre var().
   ========================================================================== */

/* --------------------------------------------------------------------------
   RESET
   -------------------------------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
/* Rolagem suave nas ÂNCORAS (o menu leva para #bolsas, #sobre). A inércia da
   roda do mouse é outra coisa e mora no site.js — este scroll-behavior não
   alcança a roda, só o salto programático.
   scroll-padding-top é o que impede a âncora de parar embaixo da barra fixa. */
html{-webkit-text-size-adjust:100%;scroll-padding-top:var(--h-header);scrollbar-gutter:stable}
@media(prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}
body{
  margin:0;
  background:var(--bg);
  color:var(--fg);
  font-family:var(--font-body);
  font-size:var(--text-body);
  line-height:var(--lh-body);
  font-variation-settings:var(--vf-body-clean);
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img,video{display:block;max-width:100%;height:auto}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
a{color:inherit;text-decoration:none}
h1,h2,h3,h4,p{margin:0}
ul{margin:0;padding:0;list-style:none}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:var(--r-sm)}

/* --------------------------------------------------------------------------
   TIPOGRAFIA
   font-optical-sizing:none é obrigatório no display — 'auto' mapeia opsz para
   o tamanho renderizado em px, o que é imprevisível em zoom, SVG e impressão.
   O opsz mora no preset, travado.
   -------------------------------------------------------------------------- */
.h1,.h2,.h3{font-family:var(--font-display);font-optical-sizing:none}

.h1{font-size:var(--text-h1);line-height:var(--lh-h1);letter-spacing:var(--ls-h1);
  font-variation-settings:var(--vf-display-h1)}
.h2{font-size:var(--text-h2);line-height:var(--lh-h2);letter-spacing:var(--ls-h2);
  font-variation-settings:var(--vf-display-h2)}
.h3{font-size:var(--text-h3);line-height:var(--lh-h3);letter-spacing:var(--ls-h3);
  font-variation-settings:var(--vf-display-h3)}

/* Ysabeau SC em caixa alta. O padding-left compensa o espaço órfão que o tracking
   cria depois da última letra — sem ele nada centraliza de verdade. */
.eyebrow{
  display:block;font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-eyebrow);line-height:var(--lh-eyebrow);
  letter-spacing:var(--tracking-caps-lg);
  padding-left:var(--tracking-caps-lg);
  text-transform:uppercase;color:var(--fg-muted);
}
/* Ysabeau SC é a família VERSALETE: o desenho já é versalete de verdade,
   com acentuadas dedicadas. Digite normalmente — nada de text-transform,
   nada de font-variant:small-caps. */
.smallcaps{font-family:var(--font-badge);font-variation-settings:var(--vf-badge);
  font-size:var(--text-badge);letter-spacing:var(--tracking-caps-md)}

/* Script: NUNCA tracking (quebra as ligações), NUNCA caixa alta. */
.script{font-family:var(--font-script);font-size:var(--text-script);
  line-height:var(--lh-script);font-weight:400;
  letter-spacing:0;text-transform:none}
.script--lg{font-size:var(--text-script-lg);line-height:var(--lh-script-lg)}

/* A script embutida em outra fonte: o <em> vira Courgette, nunca itálico.
   As regras invioláveis moram AQUI, num lugar só — assim um contexto novo
   não tem como esquecer que script não leva tracking nem caixa alta. */
.hero__title em,.intro__text em,.sea__quote em,.cta__title em,
.shop-head__title em,.ft__ethos em{
  font-family:var(--font-script);font-style:normal;
  font-weight:400;                    /* peso unico: acima disso vira falso-negrito */
  letter-spacing:0;text-transform:none;display:inline-block;
}

.lead{font-size:var(--text-body-lg);line-height:var(--lh-body-lg);
  color:var(--fg-muted);max-width:var(--maxw-prose)}
.micro-caps{font-size:var(--text-micro);line-height:var(--lh-micro);
  letter-spacing:var(--tracking-caps-md);padding-left:var(--tracking-caps-md);
  text-transform:uppercase;font-variation-settings:var(--vf-body-engraved)}

/* --------------------------------------------------------------------------
   LAYOUT
   -------------------------------------------------------------------------- */
.wrap{width:100%;max-width:var(--maxw);margin:0 auto;padding-inline:var(--gutter)}
.section{padding-block:var(--sp-section)}
/* seção que segue logo abaixo de uma barra ou cabeçalho: topo encurtado */
.section--tight{padding-top:clamp(2rem,6vh,3.5rem)}
/* seção com sangria lateral: corta na largura do corpo, que é a janela MENOS
   a barra de rolagem — é o que o 100vw da conta da sangria não sabe */
.section--bleed{overflow-x:clip}
.divider{height:1px;background:var(--line);border:0;margin:0}
/* Fora de vista, dentro da árvore. clip-path e não display:none nem
   visibility:hidden — esses dois tiram o elemento do leitor de tela também,
   que é justamente quem precisa dele. width/height 1px porque `0` faz alguns
   leitores pularem o nó. */
.visualmente-oculto{position:absolute;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap}

/* --------------------------------------------------------------------------
   SUPERFÍCIES DA MARCA
   Nenhuma foi inventada: cada uma é um elemento físico das bolsas traduzido
   em CSS. Documentadas no capítulo 05 do design-system.html.

   Disciplina de uso — "um gesto por composição":
   o GRÃO é substrato (papel) e pode ir em qualquer lugar; a LISTRA e o VICHY
   são gesto, e só entram onde NÃO há foto nem ilustração competindo.
   -------------------------------------------------------------------------- */
.tex-grain,.tex-stripe,.tex-wash{position:relative}
/* o conteúdo tem que subir acima das camadas ::before/::after */
.tex-stripe > *,.tex-wash > *{position:relative;z-index:2}
.tex-grain::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;opacity:.5;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
}
/* a lona ticking das bolsas — currentColor define a intensidade */
.tex-stripe::before{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:0;
  background-image:repeating-linear-gradient(90deg,transparent 0 7px,currentColor 7px 8px);
}
/* aguada de guache — o fundo lavado dos painéis pintados */
.tex-wash::before{
  content:"";position:absolute;inset:-20%;pointer-events:none;z-index:0;
  background-image:
    radial-gradient(ellipse 55% 45% at 18% 78%,color-mix(in srgb, var(--c-azul-aguada) 22%, transparent) 0%,transparent 62%),
    radial-gradient(ellipse 45% 55% at 82% 22%,color-mix(in srgb, var(--c-salmao) 16%, transparent) 0%,transparent 60%);
}
/* Intensidade da listra por contexto. currentColor sobre fundo escuro seria
   creme puro — forte demais; a listra tem que ser percebida, não lida. */
.cta.tex-stripe::before{color:color-mix(in srgb, var(--c-creme) 5.5%, transparent)}
.ft.tex-stripe::before{color:color-mix(in srgb, var(--c-creme) 5%, transparent)}

/* --------------------------------------------------------------------------
   REVEAL ON SCROLL
   Gated por .js (classe posta inline no <head>): sem JS, ou se o JS quebrar
   antes de rodar, o conteúdo aparece. A página nunca fica em branco.
   -------------------------------------------------------------------------- */
.js .reveal{opacity:0;transform:translateY(28px);filter:blur(3px);
  transition:opacity var(--dur-slow) var(--ease),
             transform var(--dur-slow) var(--ease),
             filter var(--dur-slow) var(--ease)}
.js .reveal.is-in{opacity:1;transform:none;filter:none}
.reveal[data-d="1"]{transition-delay:var(--stagger-reveal)}
.reveal[data-d="2"]{transition-delay:calc(var(--stagger-reveal) * 2)}
.reveal[data-d="3"]{transition-delay:calc(var(--stagger-reveal) * 3)}
.reveal[data-d="4"]{transition-delay:calc(var(--stagger-reveal) * 4)}


/* --------------------------------------------------------------------------
   BOTÕES E LINKS
   -------------------------------------------------------------------------- */
.btn{
  display:inline-flex;align-items:center;gap:.6em;
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  text-transform:uppercase;
  /* compensa o espaco orfao que o tracking cria depois da ultima letra:
     sem isto o rotulo assenta visivelmente a esquerda do centro */
  padding:.95em 1.9em .95em calc(1.9em + var(--tracking-caps-md));
  /* o padding em em dava 43,9px — raspando no piso, e raspando é o mesmo que
     depender de o corpo da fonte nunca mudar. O piso vira piso. */
  min-height:var(--alvo-toque);
  border-radius:var(--r-pill);
  border:var(--border) solid currentColor;
  transition:background var(--dur-base) var(--ease),
             color var(--dur-base) var(--ease),
             border-color var(--dur-base) var(--ease);
}
.btn__arrow{transition:transform var(--dur-base) var(--ease)}
.btn:hover .btn__arrow{transform:translateX(4px)}
.btn--solid{background:var(--bg-invert);color:var(--fg-invert);border-color:var(--bg-invert)}
.btn--solid:hover{background:var(--accent);border-color:var(--accent);color:var(--fg-on-accent)}
.btn--ghost:hover{background:var(--bg-invert);color:var(--fg-invert)}

.tlink{
  position:relative;
  display:inline-flex;align-items:center;gap:.45em;
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  text-transform:uppercase;
  padding-bottom:.35em;border-bottom:var(--border) solid var(--line);
  transition:border-color var(--dur-base) var(--ease);
}
/* O alvo media 24,7px de altura. Aqui NÃO dá para crescer por padding: o fio
   é border-bottom, e mais padding-bottom afasta o fio da palavra — o alvo
   passaria e o desenho quebraria. A área de toque vira uma camada invisível
   centrada na palavra, e o fio fica onde está. */
.tlink::after{content:'';position:absolute;left:0;right:0;
  top:50%;transform:translateY(-50%);
  height:var(--alvo-toque)}
.tlink:hover{border-color:var(--accent)}
.tlink__arrow{transition:transform var(--dur-base) var(--ease)}
.tlink:hover .tlink__arrow{transform:translateX(4px)}

/* --------------------------------------------------------------------------
   BARRA DE AVISO
   Fica ACIMA do header e rola junto com a página — não é fixa. Sai da tela
   e não volta, como manda o gênero.
   -------------------------------------------------------------------------- */
.ann{
  position:relative;z-index:calc(var(--z-header) + 1);
  display:flex;align-items:center;justify-content:center;gap:var(--sp-4);
  background:var(--bg-invert);color:var(--fg-invert);
  padding:.7em var(--gutter);
}
.ann[hidden]{display:none}
.ann__t{font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-micro);letter-spacing:var(--tracking-caps-sm);
  padding-left:var(--tracking-caps-sm);text-transform:uppercase;text-align:center}
.ann__x{position:absolute;right:var(--gutter);display:grid;place-items:center;
  width:1.6rem;height:1.6rem;line-height:0;opacity:.65;
  transition:opacity var(--dur-fast) var(--ease)}
.ann__x:hover{opacity:1}

/* --------------------------------------------------------------------------
   HEADER — barra sólida
   Era overlay transparente sobre o hero escuro. Com mídia em movimento por
   baixo isso não se sustenta: o contraste muda quadro a quadro. Barra sólida
   resolve, e é o que a referência faz.
   -------------------------------------------------------------------------- */
.hdr{
  position:sticky;top:0;z-index:var(--z-header);
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;
  /* padding vertical curto: quem define a altura da barra é o wordmark de
     duas linhas, não o respiro. Sem isso a barra passa de 110px. */
  padding:.6rem var(--gutter);
  background:var(--bg);color:var(--fg);
  border-bottom:var(--border) solid var(--line);
  transition:transform var(--dur-base) var(--ease),opacity var(--dur-base) var(--ease);
}
.hdr.is-hidden{transform:translateY(-100%);opacity:0;pointer-events:none}
/* O padding vertical não muda nada do que se vê — o botão continua com a
   altura da letra — mas leva a área clicável de 24px para 44px. Margem
   negativa devolve o espaço, senão a barra do topo cresce junto. */
.hdr__menu{display:inline-flex;align-items:center;gap:.7em;justify-self:start;
  padding-block:.7rem;margin-block:-.7rem;
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  text-transform:uppercase;transition:opacity var(--dur-fast) var(--ease)}
.hdr__menu:hover{opacity:.6}
.hdr__menu svg{display:block}
/* O wordmark vetorizado na barra. É um bloco de DUAS linhas (1,60:1), o que
   muda a conta: a 64px de altura ele fica com 102px de largura, e cada letra
   de MERCADO recebe ~14,6px — o mesmo que o texto em Fraunces que ele
   substituiu. Abaixo de ~54px as letras caem para menos de 12px e o lettering
   vira mancha. Por isso a barra cede altura e economiza no padding.
   No celular o logo desce mais, a pedido do proprietário (06/10), para menu, conta e cesta caberem sem
   cortar o nome: 48px até 820px e 40px até 480px, na mesma proporção. A 40px cada letra de MERCADO tem
   ~9px de largura, mas a tela do celular (2× ou 3×) dá a ela 18 a 27 pixels de verdade, e o desenho
   continua nítido. O que resolveria de vez é o lockup de uma linha para o cabeçalho, que ainda não
   existe (Branding/logo/LEIA-ME.md, limite 2). */
.hdr__logo{justify-self:center;display:block;line-height:0}
.hdr__logo img{display:block;height:4rem;width:auto}
@media(max-width:820px){.hdr__logo img{height:3rem}}
@media(max-width:480px){.hdr__logo img{height:2.5rem}}
.hdr__nav{display:flex;align-items:center;justify-self:end;gap:clamp(1rem,2.5vw,2.2rem)}
/* so existe acima de 820px. O alvo tem 44 x 44px, o piso do dedo (tela de toque grande tambem cai
   aqui): o padding leva os 22,1 da letra a 44 de altura, e a margem negativa devolve o espaco, para a
   barra nao crescer — quem manda na altura dela e o wordmark; "Loja" (39px) ganha a largura minima */
.hdr__link{display:inline-block;padding-block:.7rem;margin-block:-.7rem;min-inline-size:var(--alvo-toque);text-align:center;
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge);font-size:var(--text-caption);
  letter-spacing:var(--tracking-caps-md);text-transform:uppercase;opacity:.75;
  transition:opacity var(--dur-fast) var(--ease)}
.hdr__link:hover{opacity:1}
.hdr__pill{border:var(--border) solid var(--line);border-radius:var(--r-pill);
  /* .78em em vez de .6em: a pílula media 40px de altura e o piso de toque é
     44. O padding-left extra é a compensação do espaço órfão do tracking —
     sem ele o rótulo assenta visivelmente à esquerda dentro da pílula. */
  padding:.78em 1.25em .78em calc(1.25em + var(--tracking-caps-md));
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  text-transform:uppercase;
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease),
             border-color var(--dur-fast) var(--ease)}
.hdr__pill:hover{background:var(--bg-invert);color:var(--fg-invert);border-color:var(--bg-invert)}
/* Rotulo "em breve" no lugar do link de conta que ainda nao existe. Nao e
   <a>: link que nao leva a lugar nenhum e pior do que texto. */
/* Nao usa opacity para parecer inativo: a 0,5 o rotulo media 2,83:1 e o
   "em breve" 2,1:1. Rotulo inativo continua sendo TEXTO e tem que passar.
   Quem sinaliza a espera e a cor de apoio mais o corpo menor do "em breve",
   nao o apagamento. */
.hdr__link--soon{color:var(--fg-muted);opacity:1;cursor:default}
.hdr__link--soon i{font-style:normal;font-size:.82em;opacity:1}
@media(max-width:720px){.hdr__link--soon{display:none}}

/* A CESTA — icone com o contador dentro do proprio quadro.
   O alvo tem 44px por padding, e a margem negativa devolve o espaco para a
   barra do topo nao crescer junto: quem manda na altura dela e o wordmark. */
.hdr__cesta{position:relative;display:grid;place-items:center;
  padding:.75rem;
  /* A margem negativa NAO pode passar da calha. Ela e .75rem — 12px fixos —
     e a calha e 3.5vw, que abaixo de ~343px de tela fica menor que isso: em
     320 da 11,2, e o alvo saia 0,8px para fora da janela. Isso vira 1px de
     rolagem lateral, e 1px de rolagem lateral faz a pagina balançar de lado
     no toque. Amarrada ao menor dos dois, ela encosta na borda e para ali. */
  margin-block:-.75rem;
  margin-inline:calc(-1 * min(var(--sp-3), var(--gutter)));
  transition:opacity var(--dur-fast) var(--ease)}
.hdr__cesta:hover{opacity:.6}
.hdr__bag{position:relative}
.hdr__bag-n{
  /* Encostado no canto do ICONE, dentro do alvo de toque — antes ele nascia
     fora da pilula e metade dele ficava alem do desenho. */
  position:absolute;top:.35rem;right:.3rem;min-width:1.4em;height:1.4em;
  /* padding-bottom .1em: mesmo com line-height:1 o algarismo assentava .05em abaixo
     do centro (a Commissioner tem mais ascendente que descendente; a fonte reserva,
     igual). Medido pela altura de maiúscula: 0,58px abaixo → 0,03px; na reserva,
     0,65 → 0,10. Só aqui, não em todo símbolo. */
  display:none;place-items:center;padding:0 .35em .1em;
  background:var(--accent);color:var(--fg-on-accent);
  border-radius:var(--r-pill);font-family:var(--font-body);
  font-size:var(--text-micro);font-variation-settings:var(--vf-body-price);
  /* line-height:1 é obrigatório: sem ele o número herda o 1.65 do corpo, a
     caixa de linha fica bem mais alta que o dígito e o place-items centra a
     CAIXA, não o algarismo — que então assenta alto. */
  letter-spacing:0;line-height:1;
  font-variant-numeric:tabular-nums;
}
.hdr__bag-n.is-on{display:grid}
@media(max-width:820px){
  .hdr__link{display:none}
  /* Sem sessão, "Entrar" fica à vista ao lado da cesta (pedido do proprietário, 06/10): alvo de 44px por
     padding, com a margem negativa devolvendo a altura à barra; o logo segue centrado porque a coluna da
     esquerda (menu) e a da direita (Entrar + cesta) cabem no 1fr de cada lado até 320px. Com sessão, o link
     vira o menu da conta (conta-cabecalho.css) e o JS o esconde. */
  .hdr__nav .hdr__link[data-conta="cabecalho"]{display:inline-flex;align-items:center;
    min-block-size:var(--alvo-toque);padding-block:0;margin-block:0;padding-inline:.2em;opacity:1}
  /* Ordem no celular (06/10): menu | logo | cesta | conta no extremo direito. A cesta deixa de encostar na
     borda (a margem negativa passa para a conta), e o vão entre cesta e conta é pequeno. */
  .hdr__nav{gap:var(--sp-2)}
  .hdr__nav .hdr__cesta{order:1;margin-inline:0}
  .hdr__nav [data-conta="cabecalho"],.hdr__nav .conta-menu{order:2}
  .hdr__nav .hdr__link[data-conta="cabecalho"]{margin-inline-end:calc(-.2em)}
  .hdr__menu span{display:none}   /* sobra só o ícone */
  .hdr__logo{font-size:1rem}
  /* Sem o rótulo sobra o ícone de 15x11 e o alvo caía para 27x33 — o
     controle principal de navegação do celular, abaixo do piso, e num
     canto onde o polegar chega torto.

     Não precisa de margem negativa no bloco, ao contrário do desktop: quem
     manda na altura da barra é o wordmark, que aqui tem 46,4px e já é mais
     alto que o alvo. Na linha a margem é a mesma da cesta, para os dois
     alvos encostarem na borda da tela com a mesma folga — antes o da
     esquerda parava 12px antes e a barra ficava torta no toque, não no olho. */
  .hdr__menu{
    display:grid;place-items:center;
    inline-size:var(--alvo-toque);block-size:var(--alvo-toque);
    padding:0;margin-block:0;
    /* o menor dos dois pelo mesmo motivo da cesta: abaixo de ~343px a calha
       fica menor que a margem e o alvo sai da janela */
    margin-inline-start:calc(-1 * min(var(--sp-3), var(--gutter)));
  }
}

/* --------------------------------------------------------------------------
   MENU EM TELA CHEIA
   O campo salmão é FORMA, não superfície de leitura longa — por isso é o único
   lugar do sistema onde o acento pode ser protagonista de área. O texto por
   cima é tinta preta (5,76:1). Creme sobre salmão dá 2,3:1 e some.
   -------------------------------------------------------------------------- */
.menu{
  position:fixed;inset:0;z-index:calc(var(--z-header) + 10);
  background:var(--accent);color:var(--c-tinta);
  display:flex;flex-direction:column;overflow-y:auto;overscroll-behavior:contain;
  /* transform em vez de clip-path: roda no compositor, é mais leve, e se a
     transição não puder rodar o estado final ainda é alcançado. */
  transform:translateY(-100%);
  transition:transform .48s cubic-bezier(.55,0,.75,.4);
}
.menu[hidden]{display:none}
.menu.is-open{transform:translateY(0);
  transition-duration:.72s;transition-timing-function:cubic-bezier(.22,1,.32,1)}

/* A chapa desce e o CONTEÚDO entra atrás dela, com 90ms de atraso e um
   deslocamento curto. É o que tira a brutalidade: sozinha, a chapa chega
   inteira de uma vez e o olho não tem para onde ir. Em duas camadas, a cor
   chega primeiro e o texto assenta depois — o mesmo princípio da cascata.
   Ao FECHAR o atraso é zero e o tempo é curto: sair tem que ser mais rápido
   do que entrar, senão parece que a página travou. */
.menu__bar,.menu__body{
  opacity:0;transform:translateY(-1.1rem);
  transition:opacity var(--dur-fast) var(--ease-menu),
             transform var(--dur-fast) var(--ease-menu);
}
.menu.is-open .menu__bar,.menu.is-open .menu__body{
  opacity:1;transform:none;
  transition-duration:var(--dur-base);transition-delay:140ms;
}
@media(prefers-reduced-motion:reduce){
  .menu,.menu__bar,.menu__body{transition:none!important}
}

.menu__bar{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;
  padding:.6rem var(--gutter);border-bottom:1px solid color-mix(in srgb, var(--c-tinta) 18%, transparent)}
/* Fechar e Cesta mediam 21,8 e 19,8 de altura. Aqui o min-height não precisa
   de media query nem de margem negativa: quem manda na altura da barra do
   menu é o wordmark a 4rem, que é mais alto que o alvo — a barra não cresce. */
.menu__close{display:inline-flex;align-items:center;gap:.7em;justify-self:start;
  min-height:var(--alvo-toque);
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  padding-left:var(--tracking-caps-md);
  text-transform:uppercase;transition:opacity var(--dur-fast) var(--ease)}
.menu__close:hover{opacity:.6}
.menu__close svg{display:block}
.menu__logo{justify-self:center;display:block;line-height:0}
/* a logo é azul no arquivo; sobre salmão o azul dá 4,16:1 e só passa em corpo
   grande — a 64px de altura ela é exatamente isso, corpo grande */
.menu__logo img{display:block;height:4rem;width:auto}
/* a barra do menu cobre o header: o logo tem de ficar do MESMO tamanho que o
   do header em cada largura, senão ele cresce ao abrir (46→64px no celular) */
@media(max-width:820px){.menu__logo img{height:3.4rem}}
@media(max-width:480px){.menu__logo img{height:2.9rem}}
.menu__cesta{justify-self:end;
  display:inline-flex;align-items:center;min-height:var(--alvo-toque);
  font-family:var(--font-badge);
  font-variation-settings:var(--vf-badge-sm);font-size:var(--text-caption);
  letter-spacing:var(--tracking-caps-md);padding-left:var(--tracking-caps-md);
  text-transform:uppercase;transition:opacity var(--dur-fast) var(--ease)}
.menu__cesta:hover{opacity:.6}

.menu__body{flex:1;display:flex;flex-wrap:wrap;
  gap:clamp(2rem,5vw,4rem) clamp(2rem,6vw,6rem);
  justify-content:space-between;align-items:flex-start;
  padding:clamp(2.5rem,7vh,4.5rem) var(--gutter) clamp(2rem,5vh,3.5rem)}

/* As colunas precisam de piso de largura. Antes eram minmax(0,14rem) dentro de
   um 1fr, e o 1fr encolheu: cada coluna foi para ~50px e toda palavra virou
   uma linha. Piso em rem resolve, e o wrap cuida do resto. */
.menu__cols{display:flex;flex-wrap:wrap;gap:clamp(2rem,5vw,4.5rem)}
.menu__col{flex:0 0 auto;min-width:11rem}
.menu__h{font-family:var(--font-badge);font-variation-settings:var(--vf-badge-lg);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-lg);
  padding-left:var(--tracking-caps-lg);text-transform:uppercase;
  /* .84 e nao .7: sobre o campo salmao, a tinta cheia da 5,76:1 e a .7 caia
     para 3,62. O piso de 4,5 pede .84 — a sobrancelha continua recuada, so
     para de recuar abaixo do que se le. */
  margin-bottom:1.2em;opacity:.84;white-space:nowrap}
.menu__h--gap{margin-top:2.6em}
.menu__list{padding-inline-start:.75rem}
.menu__list li{margin-bottom:.5em}
.menu__list a,.menu__soon{
  display:inline-block;font-family:var(--font-body);
  font-variation-settings:var(--vf-body-medium);
  font-size:clamp(1.05rem,1.6vw,1.45rem);line-height:1.25;
  letter-spacing:0;text-transform:none;white-space:nowrap;
  transition:opacity var(--dur-fast) var(--ease),transform var(--dur-fast) var(--ease);
}
.menu__list a:hover{opacity:.55;transform:translateX(4px)}
/* No celular o menu É a navegação — não há mais nada na barra do topo além
   dele. E era onde estavam os piores alvos: 21px de altura, oito deles.

   Só no celular porque o corpo do link é clamp(1.05rem, 1.6vw, 1.45rem): a
   partir de ~1120px de tela ele já cresce sozinho para além do piso AA. É o
   piso do dedo que falta aqui, não o da régua.

   A margem do <li> sai junto: com ela as linhas ficariam a 52px, e o que a
   coluna quer é uma lista lida de cima a baixo, não itens soltos. */
@media(max-width:820px){
  .menu__list li{margin-bottom:0;position:relative}
  .menu__list a{padding-block:calc((var(--alvo-toque) - 1.25em) / 2)}
  /* "Início" tem 41,8px de largura e mais nenhum tinha problema — mas o
     conserto não é esticar a palavra até 44. Numa lista de navegação de
     celular quem devia responder é a LINHA, e o <li> já é a largura da
     coluna. A camada invisível cobre o <li> inteiro: o desenho não muda,
     o hover continua sendo a palavra andando 4px, e o dedo acerta em
     qualquer lugar da faixa. */
  .menu__list a::after{content:'';position:absolute;inset:0}
}
/* 07/10 (rodada no celular): o menu cabia em ~1030px (visitante) e ~1160px (com conta) numa tela de 812;
   Conta e redes ficavam abaixo da dobra. No celular as duas colunas do computador voltam lado a lado (o piso
   de 11rem as empilhava) e o ar vertical encolhe; cada linha continua com 44px de alvo. Tela muito baixa
   (paisagem, zoom) segue rolando: o menu nunca corta item. */
@media(max-width:520px){
  .menu__body{padding-top:clamp(1.25rem,3vh,2rem);row-gap:var(--sp-6)}
  .menu__cols{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:1rem;row-gap:0;width:100%}
  .menu__col{min-width:0}
  .menu__h{margin-bottom:.6em}
  .menu__h--gap{margin-top:1.6em}
  .menu__list{padding-inline-start:.5rem}
}
@media(max-height:560px){.menu__body{padding-top:1rem}.menu__h--gap{margin-top:1.4em}}
/* Aqui NAO pode ser opacidade, e o projeto ja resolveu isso uma vez no
   .hdr__link--soon: rotulo inativo continua sendo TEXTO e tem que passar.
   Medido sobre o campo salmao, a .42 "Bones" dava 2,11:1 e o "em breve"
   1,94:1 — e o piso de 4,5 so e alcancado a partir de .84, que e perto
   demais do cheio para ainda ler como inativo. Ou seja: neste fundo nao
   existe opacidade que sirva para as duas coisas.

   Entao quem sinaliza a espera e o PESO (500 -> 400) mais a etiqueta EM
   BREVE, que ja estava ali e e o unico sinal que nao custa legibilidade.
   O cursor e a falta de hover fecham. */
.menu__soon{opacity:1;font-variation-settings:var(--vf-body-clean);cursor:default}
.menu__soon i{font-style:normal;font-size:max(.44em,.6875rem);letter-spacing:var(--tracking-caps-sm);
  text-transform:uppercase;opacity:1;margin-left:.8em;vertical-align:baseline}

/* mídia à direita, como na referência: duas peças retrato lado a lado */
.menu__media{display:flex;gap:var(--sp-2);flex:0 0 auto;align-self:flex-start}
.menu__card{position:relative;display:block;overflow:hidden;border-radius:var(--r-sm);
  width:clamp(9rem,15vw,16.5rem);
  /* isolation confina o blend do rótulo à foto DESTE card. Sem ela o
     mix-blend-mode procura o backdrop no stacking context de cima e o rótulo
     passa a inverter contra o campo salmão do menu, não contra a imagem. */
  isolation:isolate}
.menu__card img{width:100%;aspect-ratio:3/4;object-fit:cover;
  transition:transform var(--dur-zoom) var(--ease)}
.menu__card:hover img{transform:scale(1.04)}
/* Rótulo em `difference`: ele inverte o que está por baixo em vez de tapar.
   Sobre foto clara escurece, sobre foto escura clareia — sempre se lê, e sem
   a tarja de sombra, que era um remendo. A sombra saiu por isso.
   NÃO é `overlay`: overlay multiplica o escuro e clareia o claro, sem inverter,
   e sobre foto de meio-tom o texto some. */
.menu__cap{position:absolute;top:.7rem;left:.7rem;right:.7rem;
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-micro);letter-spacing:var(--tracking-caps-sm);
  text-transform:uppercase;color:var(--c-creme);
  mix-blend-mode:difference}
/* Sem suporte a blend o rótulo sumiria sobre foto clara: devolve a sombra. */
@supports not (mix-blend-mode:difference){
  .menu__cap{text-shadow:0 1px 10px color-mix(in srgb, var(--c-azul-profundo) 55%, transparent)}
}
/* Contraste alto pedido pelo sistema. `difference` produz contraste que não dá
   para medir nem garantir — aqui o rótulo volta a ser tinta chapada sobre tarja. */
@media(prefers-contrast:more){
  .menu__cap{mix-blend-mode:normal;background:color-mix(in srgb, var(--c-azul-profundo) 78%, transparent);
    padding:.25rem .4rem;border-radius:var(--r-sm)}
}
@media(max-width:820px){.menu__media{width:100%;order:2}}
@media(max-width:520px){.menu__card{width:calc(50% - var(--sp-2))}}

/* trava o scroll do fundo enquanto o menu está aberto */
body.menu-aberto{overflow:hidden}

/* --------------------------------------------------------------------------
   HERO
   A dobra é SÓ a foto: full-bleed, sem véu, sem gradiente, sem filtro.

   Volta a ser `cover`. A tentativa de mostrar a foto inteira (aspect-ratio do
   arquivo + contain) funcionava na conta e não no olho: sobrava faixa de creme
   dos dois lados e a peça virava um quadro pendurado, não uma capa. A saída
   veio do arquivo, não do CSS — a foto nova tem 2,25:1 contra 1,79:1 da antiga,
   com margem de estúdio de sobra nas laterais. `cover` come essa margem
   (6,8% de cada lado em 1600x900) e não encosta na bolsa.

   Por que não há texto em cima dela: a luminância da foto foi amostrada em
   todos os cantos onde o bloco caberia. A listra branca da lona leva branco
   puro (L=1,00) para dentro de qualquer retângulo grande o bastante para a
   manchete — inclusive no topo à esquerda, que parece céu limpo mas já pega
   o ombro da bolsa. Creme reprova no pixel claro, azul reprova no escuro.
   Não existe canto que sirva. Ou volta o véu, ou o texto desce. Desceu.
   -------------------------------------------------------------------------- */
/* A foto INTEIRA, nunca cortada. A caixa carrega a proporção do arquivo
   (2400x1340), então em largura cheia a altura sai sozinha e não sobra nem
   falta nada. O teto é a dobra — a tela menos a barra do topo, que é a altura
   que o header cobra e por isso é ela que compensa. Quando o teto pega (tela
   muito larga), `contain` deita a foto no meio da moldura creme em vez de
   comer as beiradas: some faixa, nunca some peça. */
/* TELA DIVIDIDA. O texto saiu de cima da foto e ganhou painel proprio.

   Foi tentado de tudo com o texto por cima: veu de baixo, sombra de lado,
   foto esticada, bloco no meio, bloco embaixo. Todos custavam a mesma coisa —
   ou o texto ficava ilegivel (1,00:1 na listra branca da lona), ou a sombra
   cobria a peca, ou o corte comia a foto para abrir margem. O problema nunca
   foi a calibragem: e que esta foto e um estudio limpo com o produto no meio,
   e foto assim nao tem canto morto onde encaixar manchete.

   Lado a lado resolve os tres de uma vez: a foto entra SEM filtro, sem veu e
   sem esticar, e o texto ganha uma coluna de verdade em vez de uma canaleta
   de 20rem onde a manchete quebrava em quatro linhas. */
.hero{
  position:relative;
  /* O teto de 46vw e o que da AR para a peca. So com a dobra, o painel da foto
     ficava 1,07:1 e a bolsa — que ocupa 44,5%% da largura do arquivo — encostava
     nas duas bordas com 1,8%% de folga. Amarrando a altura a largura, a
     proporcao do painel fica constante (1,34:1) em qualquer tela e sobra 7%%
     de cada lado. A dobra continua como limite maximo, para tela baixa. */
  min-height:min(calc(100svh - var(--h-header)), 46vw);
  display:grid;
  background:var(--bg);color:var(--fg);
}
@media(min-width:900px){
  /* 44/56: o texto pede menos largura do que a foto, e a foto e deitada.
     Meio a meio deixaria a coluna do texto larga demais para a medida de
     leitura e a foto estreita demais para caber a bolsa sem cortar. */
  .hero{grid-template-columns:minmax(0,38fr) minmax(0,62fr)}
  .hero__block{order:-1}
}

/* A foto, limpa. Nenhum ::after, nenhum filter, nenhum object-position
   deslocado: ela ocupa o painel dela e ponto. */
/* No empilhado a altura vem da PROPORCAO, nao de svh. Com 46svh o painel
   ficava quadrado, e num painel 1:1 a foto de 2,25:1 mostra so 44,4%% da
   largura — exatamente o tamanho da bolsa, que saia cortada por 0,2%%.
   Em 5:4 sobram 5,5%% de cada lado. */
.hero__media{position:relative;overflow:hidden;aspect-ratio:5/4}
@media(min-width:900px){.hero__media{aspect-ratio:auto}}
.hero__media video,.hero__media img{width:100%;height:100%;object-fit:cover}

/* O bloco agora tem coluna de verdade. justify-content:center centra na
   vertical; align-items:flex-start mantem o texto encostado a esquerda, que e
   o que da o ar editorial — centrar os dois eixos viraria cartaz. */
.hero__block{
  display:flex;flex-direction:column;align-items:flex-start;justify-content:center;
  gap:1.5rem;
  padding:clamp(2.5rem,7vh,4.5rem) clamp(1.5rem,4vw,4rem);
  padding-left:max(var(--gutter),clamp(1.5rem,4vw,4rem));
}
@media(max-width:899px){
  /* a altura da abertura vem do conteúdo: respiro de leitura em cima, menor embaixo, e a seção do nome
     (.intro) encosta mais, para numa tela alta (375×812) o começo de "Mercado porque cabe de tudo" já
     aparecer sem rolar (pedido do proprietário, 06/10) */
  .hero__block{padding-block:clamp(1.75rem,5vh,2.75rem) clamp(1.25rem,3.5vh,2rem)}
  .section.intro{padding-top:clamp(2.25rem,5vh,3.5rem)}
}

/* Manchete de campanha. Não é o nome da marca — o wordmark mora no header. */
.hero__title{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h1);
  font-size:clamp(2rem,3.6vw,3.4rem);line-height:1.04;letter-spacing:-.02em;
  max-width:13ch;text-wrap:balance}
.hero__line{color:var(--fg-muted);font-size:var(--text-body-lg);
  line-height:1.5;max-width:34ch}
@media(max-width:600px){
  .hero__block{gap:1.15rem}
  .hero__line{font-size:var(--text-body)}
}
/* sobre AZUL o quente que passa é o salmão — 4,17:1, e só porque é ≥24px */
/* sobre CREME o quente que passa e o coral, e so porque a manchete e >=24px */
.hero__title em{font-size:.72em;--pal-em:.72;color:var(--accent-text);
  transform:translateY(.06em)}
/* botão salmão: aqui o quente é FORMA (chapado), com a letra em azul */
.hero .btn--solid{background:var(--accent);border-color:var(--accent);color:var(--fg-on-accent)}
.hero .btn--solid:hover{background:var(--bg-invert);border-color:var(--bg-invert);color:var(--fg-invert)}
@media(max-height:700px){.hero{--hero-shift:2vh}}
@media(max-height:600px){.hero{--hero-shift:1vh}}

/* --------------------------------------------------------------------------
   INTRO EDITORIAL
   -------------------------------------------------------------------------- */
.intro{text-align:center}
.intro .eyebrow{margin-bottom:1.4em}
.intro__text{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:"opsz" 48,"wght" 400;
  font-size:clamp(1.5rem,3.2vw,2.6rem);line-height:1.42;letter-spacing:-.01em;
  max-width:22ch;margin-inline:auto}
.intro__text em{font-size:1.15em;color:var(--accent-text)}

/* --------------------------------------------------------------------------
   CARROSSEL
   O track NÃO translada como bloco. Cada card recebe --card-x e os
   transition-delay por nth-child fazem os cards chegarem em CASCATA.
   -------------------------------------------------------------------------- */
.band__grid{display:grid;gap:clamp(2rem,4vw,3.5rem)}
@media(min-width:1200px){
  .band__grid{grid-template-columns:minmax(16rem,22rem) 1fr;align-items:start;
    gap:clamp(2.5rem,5vw,5rem)}
}
.band__intro{display:flex;flex-direction:column;align-items:flex-start;gap:1.1em}

/* Trilho de percurso do carrossel, na coluna do texto.
   Não é barra de progresso: é a MINIATURA da fila. A largura do fio quente
   diz que fatia dos produtos cabe na tela, e a posição diz onde ela está —
   por isso `left` e `width` vêm do JS em porcentagem, calculados sobre o
   mesmo par (viewport / conteúdo) que move os cards. Uma barra que só
   enchesse mentiria sobre quantos produtos faltam. */
.band__rail{position:relative;width:100%;height:var(--border);
  background:var(--line);overflow:hidden;margin-top:.4em}
.band__rail i{position:absolute;top:0;bottom:0;
  width:var(--rail-w,100%);
  left:calc(var(--rail-p,0) * (100% - var(--rail-w,100%)));
  background:var(--accent);
  transition:left var(--dur-carousel) var(--ease)}
@media(prefers-reduced-motion:reduce){.band__rail i{transition:none}}

/* Fio que sai da sobrancelha e corre até o fim da coluna: ancora o bloco de
   texto, que sem ele flutuava sozinho num vão largo. */
.eyebrow--rule{display:flex;align-items:center;gap:var(--sp-4);width:100%}
.eyebrow--rule::after{content:"";flex:1;height:var(--border);background:var(--line)}
/* coluna estreita: a medida de leitura encurta junto */
.band__intro .lead{max-width:30ch}
/* A SANGRIA À DIREITA
   O carrossel tem que ser cortado PELA MOLDURA da janela, não parar a 300px
   dela com creme sobrando — aquele naco vazio é o que denunciava a diferença
   para a referência. --bleed é a distância da borda interna do .wrap até a
   borda da janela: com o wrap centrado e travado em --maxw isso dá
   (100vw - maxw)/2 + gutter; abaixo de --maxw o wrap já encosta e sobra só o
   gutter. O max() cobre os dois casos sem media query.
   100vw conta a barra de rolagem, então a sangria passa uns 7px da moldura —
   invisível, porque o que passa é justamente o que estava sendo cortado, e o
   overflow-x:hidden do body impede que isso vire rolagem lateral. */
.band__carousel{position:relative;min-width:0;
  --bleed:max(var(--gutter),calc((100vw - var(--maxw)) / 2 + var(--gutter)))}
.band__arrows{display:flex;gap:var(--sp-2);justify-content:flex-end;margin-bottom:var(--sp-5)}
@media(min-width:1200px){
  /* as setas acompanham a sangria, mas param um gutter antes: seta encostada
     na moldura lê como corte, não como acabamento */
  .band__arrows{margin-right:calc(var(--bleed) * -1);padding-right:var(--gutter)}
}
.band__arrow{
  width:2.9rem;height:2.9rem;display:grid;place-items:center;
  border:var(--border) solid var(--line);border-radius:var(--r-circle);color:var(--fg);
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease),
             border-color var(--dur-fast) var(--ease),opacity var(--dur-fast) var(--ease);
}
.band__arrow:hover:not(:disabled){background:var(--bg-invert);color:var(--fg-invert);
  border-color:var(--bg-invert)}
.band__arrow:disabled{opacity:.28;cursor:not-allowed}

/* o viewport precisa de clientWidth útil — o JS mede por ele */
.band__viewport{overflow:hidden;margin-inline:calc(var(--gutter) * -1);
  padding-inline:var(--gutter)}
@media(min-width:1200px){
  .band__viewport{margin-right:calc(var(--bleed) * -1);margin-left:0;
    padding-left:0;padding-right:0}
}
/* A largura do card sai da FILA, não de um clamp em vw.
   --mostra é quantos cabem na janela do carrossel: 3,4 significa três inteiros
   mais um pedaço do quarto — o pedaço é o que diz "tem mais" sem precisar de
   seta. Como a conta é sobre 100% da pista (e não sobre a largura da tela), o
   card cresce junto com o vão: em monitor largo a foto fica grande de verdade,
   que é o que ela merece, em vez de travar num teto de 19rem. */
.band__track{--gap-card:clamp(1rem,2vw,1.75rem);--mostra:1.3;--vaos:1;
  display:flex;column-gap:var(--gap-card);touch-action:pan-y;cursor:grab}
.band__track:active{cursor:grabbing}
/* --vaos é a parte inteira de --mostra (quantos vãos aparecem na janela).
   Escrito à mão em vez de round(down,…) — dois números por breakpoint custam
   menos que depender de uma função nova para uma conta que nunca muda. */
.band__track > *{flex:0 0 calc((100% - var(--vaos) * var(--gap-card)) / var(--mostra))}
@media(min-width:620px){.band__track{--mostra:2.35;--vaos:2}}
@media(min-width:1200px){.band__track{--mostra:3.4;--vaos:3}}

.band__track .shop-card{
  transform:translateX(var(--card-x,0px));
  transition:transform var(--dur-carousel) var(--ease);
}
.band__track .shop-card:nth-child(1){transition-delay:0ms}
.band__track .shop-card:nth-child(2){transition-delay:45ms}
.band__track .shop-card:nth-child(3){transition-delay:90ms}
.band__track .shop-card:nth-child(4){transition-delay:135ms}
.band__track .shop-card:nth-child(5){transition-delay:180ms}
.band__track .shop-card:nth-child(6){transition-delay:225ms}
.band__track .shop-card:nth-child(7){transition-delay:270ms}
.band__track .shop-card:nth-child(8){transition-delay:315ms}
.band__track .shop-card:nth-child(n+9){transition-delay:360ms}

/* --------------------------------------------------------------------------
   CARD DE PRODUTO — usado no carrossel E no grid da loja
   -------------------------------------------------------------------------- */
.shop-card{display:flex;flex-direction:column;min-width:0}
/* Sem esta linha o filtro da loja não filtra NADA. O JS marca o card com o
   atributo `hidden`, e `[hidden]{display:none}` mora na folha do navegador —
   qualquer regra de autor que declare `display` ganha dela por especificidade.
   O `.shop-card{display:flex}` logo acima é essa regra. Vale para todo
   componente que use `hidden`: .ann, .menu e .cesta já têm a guarda. */
.shop-card[hidden]{display:none}
.shop-card__media{position:relative;aspect-ratio:4/5;overflow:hidden;
  background:var(--bg-surface);border-radius:var(--r-sm)}
.shop-card__media img{width:100%;height:100%;object-fit:cover;
  transition:transform var(--dur-zoom) var(--ease),opacity var(--dur-linha) var(--ease)}
.shop-card:hover .shop-card__media img{transform:scale(1.04)}
/* segunda imagem opcional — degrada sozinha nos produtos com uma foto só */
.shop-card__media-alt{position:absolute;inset:0;opacity:0}
.shop-card:hover .shop-card__media-alt{opacity:1}
/* Branco sobre o campo quente. Sobre o Salmão Vivo daria 3,10:1 — reprova para
   texto pequeno. Sobre o Coral Queimado dá 4,55:1 e passa, mantendo o mesmo
   campo quente, só um tom mais fundo. */
.shop-card__badge{
  position:absolute;top:.85rem;left:.85rem;
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);font-size:var(--text-micro);
  letter-spacing:var(--tracking-caps-sm);text-transform:uppercase;
  padding:.5em .9em .5em calc(.9em + var(--tracking-caps-sm));
  background:var(--c-coral);color:var(--c-branco-selo);border-radius:var(--r-pill);
}
.shop-card__body{display:flex;flex-direction:column;gap:.35em;padding-top:1.05rem}
.shop-card__cat{font-family:var(--font-badge);font-variation-settings:var(--vf-badge);font-size:var(--text-micro);
  letter-spacing:var(--tracking-caps-sm);padding-left:var(--tracking-caps-sm);
  text-transform:uppercase;color:var(--fg-muted)}
.shop-card__title{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h3);
  font-size:1.25rem;line-height:1.15;letter-spacing:-.01em}
/* O alvo do nome não precisa mais crescer por padding: o link estica uma
   camada sobre o card inteiro (ver "O CARD INTEIRO ABRE A PEÇA" no fim deste
   arquivo), e o card é bem maior que qualquer piso. */
.shop-card__tags{font-size:var(--text-body-sm);color:var(--fg-muted)}
.shop-card__foot{display:flex;align-items:center;justify-content:space-between;
  gap:var(--sp-4);margin-top:.7em;padding-top:.8em;border-top:var(--border) solid var(--line)}
/* preço e parcelamento empilhados, alinhados à esquerda */
.shop-card__prices{display:flex;flex-direction:column;gap:.1em;min-width:0}
.shop-card__price{font-variation-settings:var(--vf-body-price);
  font-size:var(--text-body-lg);font-variant-numeric:tabular-nums;line-height:1.15}
.shop-card__inst{font-size:var(--text-caption);color:var(--fg-muted);
  font-variant-numeric:tabular-nums;line-height:1.3}
.shop-card__add{
  /* 2,75rem = 44px: o piso de alvo de toque. Estava em 2,5rem (40px), que
     passa no mínimo da norma mas erra no polegar — e este é o botão que
     coloca a peça na cesta, o único da grade. */
  width:2.75rem;height:2.75rem;flex:0 0 auto;
  /* grid + place-items centra a CAIXA do filho. Com o "+" em texto isso não
     bastava: a caixa do glifo tem folga desigual em cima e embaixo, e o sinal
     assentava alto. Em SVG o desenho é simétrico e o centro é o centro. */
  display:grid;place-items:center;line-height:0;
  border:var(--border) solid var(--fg);border-radius:var(--r-circle);
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease),
             border-color var(--dur-fast) var(--ease),opacity var(--dur-fast) var(--ease);
}
.shop-card__add svg{display:block}
.shop-card__add:hover:not(:disabled){background:var(--accent);border-color:var(--accent)}
.shop-card__add.is-added{background:var(--bg-invert);color:var(--fg-invert)}
.shop-card__add:disabled{opacity:.3;cursor:not-allowed}
.shop-card--soldout .shop-card__media,.shop-card--na-cesta .shop-card__media{opacity:.5}
.shop-card--soldout .shop-card__badge,.shop-card--na-cesta .shop-card__badge{background:var(--bg-surface);color:var(--fg-muted)}
/* O selo nasce VAZIO e só aparece quando tem estado para contar ("Na cesta",
   "Esgotado"). Antes vinha escrito "Peça única" em todos: cinco selos iguais
   na mesma tela, dizendo a mesma coisa que o texto da página já dizia quatro
   vezes. Toda peça é única — é fato de marca, não informação de card, e o
   lugar dele é a nota da compra, na PDP. */
.shop-card__badge:empty{display:none}

/* --------------------------------------------------------------------------
   PRODUTO — tela dividida
   NÃO é metade e metade. A coluna da esquerda tem o tamanho da FOTO: a peça
   entra inteira, na proporção em que foi fotografada, e quem absorve a sobra
   das telas largas é a direita. É a direita que compensa a esquerda — nunca
   a foto que se ajusta ao vão.
   -------------------------------------------------------------------------- */
.pdp{display:grid;min-height:calc(100svh - var(--h-header))}
@media(min-width:900px){.pdp{grid-template-columns:auto 1fr}}

/* ---- esquerda: a foto, inteira ----
   A largura sai da ALTURA: altura útil x 4/5, que é a proporção em que as
   sete fotos de produto foram tiradas (todas 0,800 exatos — conferido).
   O min() é o freio: sem ele, numa tela mais alta que larga a foto engoliria
   o painel. Quando o freio pega, `contain` deita a foto no meio da lona em
   vez de cortá-la — a mancha some, a peça nunca.
   object-fit:contain é regra, não acaso: chegando uma foto de proporção
   diferente ela entra inteira do mesmo jeito. */
.pdp__vitrine{position:relative;background:var(--bg-surface);overflow:hidden;
  aspect-ratio:4/5}
@media(min-width:900px){
  .pdp__vitrine{--pdp-h:calc(100svh - var(--h-header));
    width:min(calc(var(--pdp-h) * 4 / 5), 46vw);
    align-self:center}
}
.pdp__fotos{position:absolute;inset:0}
.pdp__foto{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;
  opacity:0;transition:opacity var(--dur-foto) var(--ease)}
.pdp__foto.is-on{opacity:1}

/* ---- passar as fotos: miniaturas sobre a própria foto ----
   Some sozinho quando só existe uma foto — a régua é o :has(), sem JS.
   A miniatura ativa não muda de tamanho (isso empurraria as vizinhas):
   muda o anel e a opacidade. */
.pdp__pontos{position:absolute;left:0;right:0;bottom:clamp(1rem,3vh,1.75rem);
  z-index:2;display:flex;justify-content:center;gap:.5rem;padding-inline:1rem}
.pdp__pontos:has(.pdp__ponto:only-child){display:none}
.pdp__ponto{width:clamp(2.75rem,4.5vw,3.5rem);aspect-ratio:4/5;padding:0;border:0;
  border-radius:var(--r-sm);overflow:hidden;cursor:pointer;background:var(--bg-surface);
  box-shadow:0 0 0 var(--border) var(--line), 0 6px 18px color-mix(in srgb, var(--c-azul-profundo) 18%, transparent);
  opacity:.62;transition:opacity var(--dur-fast) var(--ease),
    box-shadow var(--dur-fast) var(--ease)}
.pdp__ponto img{width:100%;height:100%;object-fit:cover;display:block}
.pdp__ponto:hover{opacity:.85}
.pdp__ponto.is-on{opacity:1;
  box-shadow:0 0 0 2px var(--accent), 0 6px 18px color-mix(in srgb, var(--c-azul-profundo) 22%, transparent)}
.pdp__ponto:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* ---- direita: campo desbotado + ficha centrada ----
   A ficha centra verticalmente, então não sobra vão morto embaixo. */
/* O respiro vertical daqui é o que decide se a linha inteira cabe na tela: se
   a ficha + padding passar de 100svh - header, a linha cresce, a foto (que
   tem largura fixa vinda daquela mesma conta) para de encher a coluna e
   aparece faixa de lona em cima e embaixo. 6vh cabe; 8vh estourava por 9px. */
/* Sobre o campo desfocado a cor de APOIO não sobrevive, e isso é medição, não
   impressão: --fg-muted (#2C6195) dá 1,78:1 na nota e 2,2–2,8:1 nos rótulos
   da ficha, contra o fundo real amostrado numa chapa sem texto. Sete de dez
   textos do painel reprovavam.

   E não adianta subir o véu: para levar #2C6195 a 4,5:1 o creme teria que ir
   a ~80%, e a 80% não há mais campo, há creme. A conta é fechada — o campo
   visível e essa cor de texto não cabem juntos.

   Então aqui a hierarquia deixa de ser cor e passa a ser corpo e caixa: o
   rótulo da ficha já é 10px em caixa alta com tracking contra 14px de corpo
   normal do valor. Isso separa os dois sem depender de contraste que o fundo
   não sustenta. Sobre creme, --fg-muted continua sendo --fg-muted. */
.pdp__painel{--fg-muted:var(--c-tinta);
  position:relative;display:flex;align-items:center;overflow:hidden;
  padding:clamp(2.5rem,6vh,4rem) clamp(1.5rem,5vw,4rem);min-height:70svh}
@media(min-width:900px){.pdp__painel{min-height:calc(100svh - var(--h-header))}}

.pdp__campo{position:absolute;inset:0;z-index:0}
.pdp__campo img,.pdp__campo video{width:100%;height:100%;object-fit:cover;
  transform:scale(1.25);filter:blur(64px) saturate(.72) brightness(1.12)}
.pdp__campo::after{content:"";position:absolute;inset:0;
  background:color-mix(in srgb, var(--c-creme) 58%, transparent)}

.pdp__ficha{position:relative;z-index:2;width:100%;max-width:26rem;
  margin-inline:auto}
.pdp__cat{font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-micro);letter-spacing:var(--tracking-caps-sm);
  padding-left:var(--tracking-caps-sm);text-transform:uppercase;
  color:var(--fg-muted);margin-bottom:.9em}
.pdp__nome{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h1);
  font-size:clamp(2rem,4vw,3rem);line-height:1;letter-spacing:-.02em}
.pdp__preco{font-variation-settings:var(--vf-body-price);
  font-size:var(--text-body-lg);font-variant-numeric:tabular-nums;margin-top:.5em}
.pdp__parcela{font-size:var(--text-caption);color:var(--fg-muted);
  font-variant-numeric:tabular-nums;margin-top:.15em}
/* A frase de apoio fica no azul do texto; a Courgette continua. O coral reprovava duas vezes:
   abaixo de 60rem a frase tem 20px (coral só vale de 24px para cima) e, no computador, o fundo
   real atrás dela é a mancha rosada da ficha (mediana 3,95:1; 10% do fundo abaixo de 3:1). */
.pdp__tag{font-family:var(--font-script);font-weight:400;
  font-size:var(--text-script);color:var(--fg);margin-top:1.1em}
.pdp__desc{margin-top:1.4em;max-width:38ch;color:var(--fg-muted)}

.pdp__specs{margin-top:2em;border-top:var(--border) solid var(--line)}
.pdp__specs > div{display:flex;justify-content:space-between;gap:var(--sp-4);
  padding:.7em 0;border-bottom:var(--border) solid var(--line)}
.pdp__specs dt{font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-micro);letter-spacing:var(--tracking-caps-sm);
  text-transform:uppercase;color:var(--fg-muted)}
.pdp__specs dd{margin:0;font-size:var(--text-body-sm);text-align:right}

/* o card de compra existe só pelos dados: título e foto ficam fora de vista,
   mas continuam no DOM porque o toast lê o nome e a imagem dali */
.pdp__compra{display:block}
.pdp__compra .shop-card__title,
.pdp__compra .shop-card__media{position:absolute;width:1px;height:1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap}

.pdp__add.pdp__add{
  /* line-height:1.2 é correção, não ajuste: este botão herda o .shop-card__add,
     que zera o line-height para o "+" em SVG centrar na bolinha. Aqui dentro
     tem TEXTO, e com entrelinha zero a caixa colapsava — 30px de altura em vez
     de 46, abaixo do piso de toque, com o rótulo boiando por cima do padding.

     O min-height é a trava disso: o padding em em resolvia no corpo do
     desktop e caía para 42px no celular, onde o rótulo é menor. Botão
     principal da página não pode depender do corpo da fonte para passar. */
  width:100%;height:auto;min-height:var(--alvo-toque);
  margin-top:2.2em;padding:1.15em 1.6em;line-height:1.2;
  border:0;
  background:var(--bg-invert);color:var(--fg-invert);border-radius:var(--r-pill);
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  padding-left:calc(1.6em + var(--tracking-caps-md));
  text-transform:uppercase;
  transition:background var(--dur-base) var(--ease),color var(--dur-base) var(--ease);
}
.pdp__add.pdp__add:hover:not(:disabled){background:var(--accent);color:var(--fg-on-accent);
  border:0}
.pdp__add.pdp__add:disabled{background:var(--c-coral);color:var(--c-branco-selo);cursor:default;opacity:1}
.pdp__nota{margin-top:1em;font-size:var(--text-caption);color:var(--fg-muted);
  text-align:center}

/* --------------------------------------------------------------------------
   VÍDEO DO MAR
   -------------------------------------------------------------------------- */
/* Tamanho do Palmer: a secao toma a TELA INTEIRA e o texto assenta no rodape.
   Estava em 82svh com a frase no centro geometrico — sobrava campo igual em
   cima e embaixo, e campo simetrico nao pesa, so ocupa. Ancorando embaixo, o
   vazio vira o de cima, que e o que faz a frase respirar. */
.sea{position:relative;min-height:100svh;display:flex;align-items:flex-end;
  overflow:hidden;background:var(--bg-invert)}

/* PARALAXE — a mídia é maior que a seção e desliza dentro dela.
   A folga vertical (--paralaxe-folga) é a mesma dos dois lados, e o JS nunca
   translada mais que ela: por isso a borda da mídia não aparece em tela
   nenhuma. Sem JS, ou com movimento reduzido, fica parada e centrada — que é
   exatamente o que o inset negativo já entrega sozinho. */
.sea{--paralaxe-folga:12%}
.sea__media{position:absolute;left:0;right:0;
  top:calc(var(--paralaxe-folga) * -1);bottom:calc(var(--paralaxe-folga) * -1);
  will-change:transform}
.sea__media video,.sea__media img{width:100%;height:100%;object-fit:cover}
/* O motion já contém a tipografia: preservar o quadro inteiro em toda largura. */
.sea.sea--motion{display:block;min-height:0;background:var(--c-creme)}
.sea__motion{width:100%;max-width:1920px;margin-inline:auto;aspect-ratio:16/9}
.sea__motion video{width:100%;height:100%;object-fit:contain}
/* O veu tem que ser PESADO aqui, e a medicao diz por que: o video e agua com
   brilho de sol, e brilho de sol e branco puro. A 50%% de alfa a citacao media
   2,59:1 e o paragrafo 2,56:1 — reprovam os dois. Amostrei cinco instantes do
   video, nao um quadro so, porque o brilho anda.
   E gradiente, nao chapado: em cima o texto nao chega, entao ali a agua pode
   aparecer mais. A rampa fecha antes do bloco de texto, que assenta embaixo. */
.sea__media::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,
    color-mix(in srgb, var(--c-azul-profundo) 46%, transparent) 0%,
    color-mix(in srgb, var(--c-azul-profundo) 58%, transparent) 32%,
    color-mix(in srgb, var(--c-azul-profundo) 76%, transparent) 58%,
    color-mix(in srgb, var(--c-azul-profundo) 80%, transparent) 100%)}

/* A medida da citação mora AQUI, não no .sea__inner.
   Estava em `max-width:24ch` no pai — e `ch` resolve contra o corpo do
   ELEMENTO, que ali é o texto de 17px. Dava uma caixa de ~204px segurando
   letra de 51px: uma palavra por linha. No filho, o ch conta na escala certa. */
.sea__inner{position:relative;z-index:2;width:100%;color:var(--fg-invert);
  display:grid;gap:clamp(1.4rem,3vw,2.4rem);
  padding:0 var(--gutter) clamp(2.5rem,8vh,5rem)}
@media(min-width:900px){
  .sea__inner{grid-template-columns:minmax(0,1.2fr) minmax(0,1fr);
    align-items:end;gap:clamp(2rem,6vw,6rem)}
}
/* Segunda coluna, no molde da referencia: a frase da o golpe, esta explica.
   Nao leva script nem quente — uma ideia forte por bloco. */
/* 82%, e nao os 72% de --fg-invert-muted: aqui o fundo e IMAGEM, nao chapado.
   Medido no pior pixel da coluna direita, com o veu real por cima, o muted
   padrao dava 4,19:1 e reprovava; a 82% da 4,91:1. O token global continua
   valendo onde o fundo e azul chapado. */
.sea__apoio{color:color-mix(in srgb, var(--c-creme) 82%, transparent);
  font-size:var(--text-body-lg);line-height:1.55;max-width:44ch}
.sea__quote{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:"opsz" 72,"wght" 400;
  font-size:clamp(2rem,5vw,4.2rem);line-height:1.12;letter-spacing:-.02em;
  max-width:16ch;text-wrap:balance}
/* --pal-em repete a escala do font-size acima. É o que a máscara da entrada
   palavra a palavra usa para devolver a folga da descendente em pixel. */
/* O "mao" era SALMAO na letra, e sobre a imagem media 2,16:1 — reprovava ate a
   regua de texto grande (3:1). E nao adianta subir o veu: para levar o salmao a
   3:1 ele teria que ir a 94%, e a 94% nao ha mais foto, ha azul chapado.
   Vale aqui a mesma saida do hover do rodape: a letra vai a creme (5,85:1) e o
   salmao vira FIO embaixo da palavra, que e o que a regra pede dele.
   O fio e text-decoration para acompanhar a forma da palavra, e o offset sai de
   conta, nao de gosto: a mascara da entrada (.pal) corta em
   .18em / --pal-em = .161em abaixo da base. Com offset .1em o fio terminava a
   .155em e sobravam 0,43px — folga de subpixel e o mesmo que folga nenhuma.
   A .07em ele termina a .125em e sobram .036em, que escalam junto com a fonte
   (2,7px na tela grande, 1,3px no celular) e ainda deixam a mascara fazer o
   trabalho dela, que e salvar descendente. */
.sea__quote em{font-size:1.12em;--pal-em:1.12;color:var(--fg-invert);
  text-decoration:underline;text-decoration-color:var(--c-salmao);
  text-decoration-thickness:.055em;text-underline-offset:.07em;
  /* skip-ink AUTO, nao none: a palavra enfatizada hoje e "Igualzinha", que tem
     descendente no "g", e o fio passa a .07em da base — dentro do caminho dele.
     Com `none` o fio riscava o "g" e ainda seguia por baixo da virgula, que o
     initPalavras gruda dentro do <em>. Com `auto` ele abre nos dois e para na
     letra, que e o comportamento tipografico correto do sublinhado. */
  text-decoration-skip-ink:auto}

/* --------------------------------------------------------------------------
   ENTRADA PALAVRA A PALAVRA
   Cada palavra sobe de dentro da própria máscara, uma atrás da outra. O JS só
   fatia e numera; a curva e o atraso moram aqui.

   O par padding-bottom / margin-bottom negativo é o que salva a descendente:
   sem ele o `overflow:hidden` da máscara corta o pé do "g" e do "p" e o texto
   fica com a barriga raspada. O padding abre a caixa, a margem devolve o
   espaço para o entrelinha não crescer.
   -------------------------------------------------------------------------- */
.pal{display:inline-block;overflow:hidden;vertical-align:bottom;
  padding-bottom:.18em;margin-bottom:-.18em}
/* A script embutida já é inline-block (regra compartilhada lá em cima) e vem
   maior que o texto ao redor. Duas caixas inline-block com alinhamentos
   diferentes na mesma linha não encostam: a palavra em Courgette assentava
   2px abaixo das vizinhas. Alinhar pelo mesmo `bottom` da máscara corrige a
   maior parte — sobra 1,1px, que é a folga da descendente: `.18em` medido no
   corpo MAIOR da script dá 1,1px a mais em pixel. Dividir pela escala da
   script devolve a mesma folga absoluta e as bases coincidem.
   Cada contexto declara a própria escala junto do font-size (--pal-em). */
[data-palavras] em{vertical-align:bottom}
[data-palavras] em .pal{
  padding-bottom:calc(.18em / var(--pal-em,1));
  margin-bottom:calc(.18em / var(--pal-em,1) * -1)}
.js [data-palavras] .pal__i{display:inline-block;transform:translateY(115%);
  transition:transform var(--dur-slow) var(--ease)}
.js [data-palavras].is-in .pal__i{transform:none}
@media(prefers-reduced-motion:reduce){
  .js [data-palavras] .pal__i{transform:none;transition:none}
}

/* --------------------------------------------------------------------------
   SOBRE
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   SOBRE — grade escalonada
   Texto centrado em cima, fila de cinco fotos embaixo. O que faz a fila
   parecer fotografia espalhada na mesa, e não galeria, são duas coisas:
   larguras diferentes (as das pontas menores, a do meio maior) e alturas de
   partida diferentes. Alinhadas pelo topo viraria vitrine de loja.
   -------------------------------------------------------------------------- */
.sobre__intro{display:flex;flex-direction:column;align-items:center;
  text-align:center;gap:1.1em;max-width:58ch;margin-inline:auto}
.sobre__intro .lead{max-width:none}

/* A fila soma MAIS que 100% de propósito: o excedente é o corte das pontas
   pela moldura, que é o que diz "isso continua". Quem corta é o
   .section--bleed lá em cima — na largura do corpo, não do 100vw. */
.sobre__grade{display:flex;justify-content:center;align-items:flex-start;
  gap:clamp(.6rem,1.4vw,1.4rem);
  margin-top:clamp(2.5rem,6vw,4.5rem);margin-bottom:clamp(2rem,5vw,3.5rem)}
.sobre__foto{margin:0;flex:0 0 auto;aspect-ratio:4/5;overflow:hidden;
  border-radius:var(--r-sm);background:var(--bg-surface)}
.sobre__foto img{width:100%;height:100%;object-fit:cover;display:block}

/* larguras e desníveis, do canto para o centro */
.sobre__foto:nth-child(1){flex-basis:17%;margin-top:clamp(2rem,5vw,4.5rem)}
.sobre__foto:nth-child(2){flex-basis:22%;margin-top:clamp(.75rem,2vw,1.75rem)}
.sobre__foto:nth-child(3){flex-basis:28%;margin-top:0}
.sobre__foto:nth-child(4){flex-basis:22%;margin-top:clamp(1rem,2.6vw,2.4rem)}
.sobre__foto:nth-child(5){flex-basis:17%;margin-top:clamp(2.4rem,5.6vw,5rem)}

/* No estreito o escalonamento não cabe: cinco fotos em fila viram cinco selos.

   Era fita rolável, e a fita cobrava caro: três das cinco fotos ficavam atrás
   de um gesto lateral que muita gente não faz. Numa seção que existe para
   mostrar a peça EM USO, esconder 60% dela é o oposto do trabalho.

   Vira grade de 12 colunas, e o que ela guarda do desenho do desktop é o que
   fazia aquela fila parecer fotografia espalhada na mesa: largura diferente
   em cada foto e altura de partida diferente. Alinhadas pelo topo e todas do
   mesmo tamanho, viram catálogo.

   O VAZIO É PARTE DA COMPOSIÇÃO, não sobra. Por isso as fotos não preenchem a
   linha: uma encosta na borda, a outra para antes, e o vão entre as duas é
   tão desenhado quanto elas. É o que as referências fazem — a diferença entre
   grade de fotos e mural é justamente quanto branco sobra entre uma e outra.

   Duas encostam na moldura (1 e 4 à esquerda, 2 e 5 à direita) porque o corte
   diz "isso continua" — o mesmo que o .section--bleed faz no desktop. */
@media(max-width:760px){
  .sobre__grade{
    display:grid;grid-template-columns:repeat(12,1fr);
    column-gap:0;row-gap:clamp(2rem,7vw,3.5rem);
    align-items:start;
    overflow:visible;
    padding-inline:0;margin-inline:calc(var(--gutter) * -1)}
  .sobre__foto{flex:none}
  /* faixa 1 — meia largura à esquerda, um terço mais baixo à direita */
  .sobre__foto:nth-child(1){grid-area:1/1/2/7;  margin-top:0}
  .sobre__foto:nth-child(2){grid-area:1/9/2/13; margin-top:13vw}
  /* faixa 2 — uma só, e é a maior da página: a peça inteira, sem competição */
  .sobre__foto:nth-child(3){grid-area:2/3/3/11; margin-top:3vw}
  /* faixa 3 — espelha a primeira, mas a da direita NÃO sangra: é a foto em
     que a bolsa tem MERCADO DO MAR escrito, e cortar o nome da marca é
     acidente, não corte. Quem sangra à direita é a 2, onde o corte cai em
     mar aberto e não custa nada. */
  .sobre__foto:nth-child(4){grid-area:3/1/4/6;  margin-top:0}
  .sobre__foto:nth-child(5){grid-area:3/7/4/12; margin-top:12vw}
}

.sobre__fecho{display:flex;flex-direction:column;align-items:center;
  text-align:center;gap:1.4em;max-width:56ch;margin-inline:auto}
.sobre__fecho p{color:var(--fg-muted)}
/* a script fecha a frase; sobre creme o quente que passa é o coral, e este
   trecho tem 20px — por isso ele NÃO é colorido, só muda de letra */
.sobre__fecho em{font-family:var(--font-script);font-style:normal;font-weight:400;
  letter-spacing:0;text-transform:none;font-size:max(1.25rem, 1.15em);color:var(--fg)}

/* --------------------------------------------------------------------------
   CTA DE FECHAMENTO
   -------------------------------------------------------------------------- */
.cta{position:relative;background:var(--bg-invert);color:var(--fg-invert);
  text-align:center;padding-block:clamp(6rem,18vh,11rem);overflow:hidden}
.cta__title{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h1);text-transform:uppercase;
  font-size:clamp(2.4rem,8vw,6.5rem);line-height:.92;letter-spacing:-.025em}
/* --accent-text-invert e --accent são a MESMA cor; o nome é que muda o que a
   regra promete. Aqui o quente é letra, e o token invert é o que declara que
   isso foi conferido contra o azul (4,16:1) e que só vale acima de 24px —
   este título tem 83px. */
.cta__title em{font-size:.8em;--pal-em:.8;color:var(--accent-text-invert)}
/* No celular (06/10): "Vê as outras" numa linha e "da banca" embaixo, centrado, na mesma letra script e no
   mesmo coral; o corpo cede um pouco para as duas linhas respirarem em 320. O computador fica como está. */
@media(max-width:600px){
  .cta__title{font-size:clamp(2.2rem,11vw,3rem);line-height:.95}
  .cta__title em{display:block;margin-top:.12em}
}
.cta__sub{margin:1.5em auto 2.2em;max-width:40ch;color:var(--fg-invert-muted)}
.cta .btn{border-color:var(--fg-invert)}
.cta .btn:hover{background:var(--accent);border-color:var(--accent);color:var(--fg-on-accent)}

/* --------------------------------------------------------------------------
   FOOTER
   -------------------------------------------------------------------------- */
.ft{background:var(--bg-invert);color:var(--fg-invert);
  padding:clamp(3rem,8vh,5rem) 0 var(--sp-6);border-top:var(--border) solid var(--line-invert)}
.ft__top{display:grid;gap:2.5rem;padding-bottom:2.8rem;
  border-bottom:var(--border) solid var(--line-invert)}
@media(min-width:820px){.ft__top{grid-template-columns:1.2fr 1fr;gap:var(--sp-8)}}
.ft__mark{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h3);text-transform:uppercase;
  font-size:1.5rem;letter-spacing:-.01em;margin-bottom:.5em}
.ft__ethos{color:var(--fg-invert-muted);max-width:34ch}
/* corpo pequeno: sobe o opsz para a script engrossar e não sumir */
/* 1.2em dava 20,4px e o salmão ali reprova (4,16:1, e a régua dos quentes só
   libera a partir de 24px). 1.45em põe a script em 24,7px — passa pelo tamanho,
   sem tirar a cor, que é o que dá o gesto da assinatura. */
/* max() e obrigatorio: so com 1.45em a script media 24,7px no desktop e
   caia para 23px no celular, cruzando o piso do quente sem avisar (4,16:1
   contra 4,5 exigidos). O piso trava isso em qualquer largura. */
.ft__ethos em{font-size:max(var(--text-quente-min), 1.45em);--pal-em:1.45;
  color:var(--accent-text-invert)}
.ft__news-h{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h3);font-size:1.25rem;margin-bottom:.4em}
.ft__note{color:var(--fg-invert-muted);font-size:var(--text-body-sm)}
.ft__form{display:flex;gap:var(--sp-2);margin-top:1.1rem;flex-wrap:wrap}
.ft__input{flex:1 1 12rem;min-width:0;background:transparent;color:var(--fg-invert);
  border:var(--border) solid color-mix(in srgb, var(--c-creme) 32%, transparent);border-radius:var(--r-pill);
  min-height:var(--alvo-toque);
  padding:.85em 1.3em;font-family:var(--font-body);font-size:var(--text-body-sm)}
.ft__input::placeholder{color:color-mix(in srgb, var(--c-creme) 45%, transparent)}
.ft__submit{font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);font-size:var(--text-caption);
  letter-spacing:var(--tracking-caps-md);text-transform:uppercase;
  padding:.85em 1.5em .85em calc(1.5em + var(--tracking-caps-md));
  min-height:var(--alvo-toque);
  border-radius:var(--r-pill);
  background:var(--accent);color:var(--fg-on-accent);
  transition:opacity var(--dur-fast) var(--ease)}
.ft__submit:hover{opacity:.85}
/* Retorno de formulário é informação, não enfeite: em salmão dava 4,16:1 num
   corpo de 15px. Creme dá 11,25:1 — e mensagem de estado não deve depender de
   cor para ser entendida de qualquer jeito. */
.ft__status{margin-top:.7rem;font-size:var(--text-body-sm);color:var(--fg-invert);
  min-height:1.2em}
.ft__cols{display:grid;gap:var(--sp-6);padding-block:2.8rem;
  grid-template-columns:repeat(auto-fit,minmax(9rem,1fr))}
.ft__col h3,.ft__col h4{font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);font-size:var(--text-micro);
  letter-spacing:var(--tracking-caps-sm);padding-left:var(--tracking-caps-sm);
  text-transform:uppercase;color:var(--fg-invert-muted);margin-bottom:1em}   /* 55% dava 4,49:1 em 10–11px; o token dá 6,58:1 */
.ft__col li{margin-bottom:.55em}
.ft__col a,.ft__col p{color:color-mix(in srgb, var(--c-creme) 85%, transparent);font-size:var(--text-body-sm);
  transition:color var(--dur-fast) var(--ease),
             text-decoration-color var(--dur-fast) var(--ease);
  text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.28em;
  text-decoration-color:transparent}
/* Estes oito eram os menores alvos da página: 27x16,7. Deitado, um link de
   texto puro tem a altura da letra e mais nada.

   inline-block e não flex: com flex o navegador desenha o sublinhado na caixa
   do contêiner e o text-underline-offset deixa de valer — o fio de hover, que
   é onde o salmão vira forma, sairia do lugar.

   Dois degraus de propósito. No desktop o ponteiro não precisa de 44, e o
   ritmo apertado da coluna é desenho; ali basta limpar o piso AA de 24px.
   No celular, onde o dedo é o único apontador, vale o piso cheio — e aí a
   margem do <li> sai, senão as linhas ficam a 53px uma da outra. */
.ft__col a{display:inline-block;position:relative;padding-block:.16rem}
@media(max-width:820px){
  .ft__col li{margin-bottom:0}
  .ft__col a{padding-block:calc((var(--alvo-toque) - 1.65em) / 2)}
  /* "Início" tem 27px de largura, e alargar a caixa levaria o sublinhado
     junto — o fio de hover é do tamanho da palavra, de propósito. Mesma
     saída do .tlink: a área de toque é uma camada invisível. */
  .ft__col a::after{content:'';position:absolute;top:0;bottom:0;left:0;
    width:max(100%, var(--alvo-toque))}
}
/* O hover era salmão na LETRA: 4,16:1 num corpo de 15px, reprova.
   Agora a letra vai a creme cheio (11,25:1) e o salmão faz o que a marca pede
   dele — vira forma, aqui o fio embaixo da palavra. */
.ft__col a:hover{color:var(--fg-invert);text-decoration-color:var(--accent)}
/* Tres colunas de largura igual, nao space-between. Com tres itens de
   comprimentos muito diferentes o space-between joga o do meio para onde
   sobra espaco, e a frase da marca deixa de estar no centro da pagina —
   fica no centro do VAO, que e outra coisa. */
.ft__legal{display:grid;grid-template-columns:repeat(3,1fr);gap:.8rem 2rem;
  align-items:baseline;
  padding-top:1.8rem;border-top:var(--border) solid var(--line-invert);
  /* 50% dava 3,98:1 num corpo de 13px e reprovava. 62% sobe para 5,0:1 e a
     linha continua sendo o sussurro do rodape, nao um segundo paragrafo. */
  font-size:var(--text-caption);color:color-mix(in srgb, var(--c-creme) 62%, transparent)}
.ft__legal > :nth-child(2){text-align:center}
.ft__legal > :nth-child(3){text-align:right}
/* O credito e o unico link da linha: sublinhado so no hover, como o resto
   do rodape, e a letra sobe para creme cheio para nao virar dois cinzas. */
.ft__by a{color:inherit;text-decoration:underline;text-underline-offset:.28em;
  text-decoration-color:transparent;
  transition:color var(--dur-fast) var(--ease),text-decoration-color var(--dur-fast) var(--ease)}
.ft__by a:hover{color:var(--fg-invert);text-decoration-color:var(--accent)}
/* 109x14 na auditoria — o menor alvo do site. Mesmo remedio dos outros links
   do rodape: camada invisivel, porque alargar a caixa levaria o sublinhado
   junto e o fio de hover e do tamanho da palavra de proposito. */
.ft__by a{position:relative;display:inline-block}
.ft__by a::after{content:"";position:absolute;left:0;right:0;
  top:50%;transform:translateY(-50%);height:var(--alvo-toque)}
@media(max-width:720px){
  /* empilhado, centrado: tres colunas de 33% viram tres colunas de nada */
  .ft__legal{grid-template-columns:1fr;text-align:center}
  .ft__legal > :nth-child(3){text-align:center}
}

/* --------------------------------------------------------------------------
   LOJA — cabeçalho, barra de filtros, grid
   -------------------------------------------------------------------------- */
.shop-head{padding-top:clamp(7rem,16vh,10rem);padding-bottom:clamp(2rem,6vh,3.5rem);
  text-align:center;background:var(--bg)}
.shop-head__title{margin-block:.35em .4em}
.shop-head__title em{font-size:1.1em;color:var(--accent-text)}
.shop-head__lead{margin-inline:auto;text-align:center}
/* Celular (06/10): a abertura da loja perde o vão artificial sob o cabeçalho (eram ~130 px) e usa os tokens da
   casa; os intervalos até a barra de filtros e até a primeira foto encurtam sem apertar os controles de 44 px. */
@media(max-width:820px){
  .shop-head{padding-top:var(--sp-6);padding-bottom:var(--sp-5)}
  .shop-bar{gap:var(--sp-3);padding-block:var(--sp-4)}
  .shop-bar-wrap + .section--tight{padding-top:var(--sp-5)}
}

/* mesmo recuo do grid, para a barra e a primeira foto compartilharem a borda */
.shop-bar-wrap{padding-inline:var(--sp-2)}
@media(max-width:600px){.shop-bar-wrap{padding-inline:var(--sp-4)}}

.shop-bar{display:flex;flex-wrap:wrap;gap:1.2rem;align-items:center;
  justify-content:space-between;padding-block:1.2rem;
  border-block:var(--border) solid var(--line)}
.shop-bar__cats{display:flex;flex-wrap:wrap;gap:var(--sp-2)}
.shop-cat{
  display:inline-flex;align-items:center;gap:.45em;
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge);font-size:var(--text-caption);
  letter-spacing:var(--tracking-caps-sm);text-transform:uppercase;
  padding:.6em 1.1em .6em calc(1.1em + var(--tracking-caps-sm));
  border:var(--border) solid var(--line);border-radius:var(--r-pill);
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease),
             border-color var(--dur-fast) var(--ease);
}
.shop-cat:hover{border-color:var(--fg-muted)}
.shop-cat[aria-pressed="true"]{background:var(--bg-invert);color:var(--fg-invert);
  border-color:var(--bg-invert)}
.shop-cat .n{font-family:var(--font-body);font-size:.72em;opacity:.6;
  letter-spacing:0;font-variant-numeric:tabular-nums}
.shop-sort{display:flex;align-items:center;gap:var(--sp-2)}
.shop-sort__lbl{font-family:var(--font-badge);font-variation-settings:var(--vf-badge);font-size:var(--text-caption);
  letter-spacing:var(--tracking-caps-sm);text-transform:uppercase;color:var(--fg-muted)}
.shop-sort select{font-family:var(--font-body);font-size:var(--text-body-sm);color:var(--fg);
  background:transparent;border:var(--border) solid var(--line);
  border-radius:var(--r-pill);padding:.55em 2.6em .55em 1em;cursor:pointer;
  appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='m1 1 5 5 5-5' stroke='%2312315f' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 1em center}
/* No celular a barra de filtro e o unico jeito de reduzir uma grade de cinco,
   e as pilhas mediam 35,5 e o seletor 34,7. Aqui a caixa E o desenho: a
   pilula pode crescer, entao cresce por min-height mesmo, sem camada.

   Dois degraus como no rodape: no desktop estes sao alvos de ponteiro, ja
   limpam o piso AA de 24px, e a pilula e menor que o botao DE PROPOSITO —
   filtro e controle secundario. Engordar tudo para 44 achataria essa
   hierarquia num lugar onde ela nao atrapalha ninguem. */
@media(max-width:820px){
  .shop-cat,.shop-sort select{min-height:var(--alvo-toque)}
}

/* --------------------------------------------------------------------------
   GRID DA LOJA — full-bleed, três colunas, foto grande
   A vitrine é a foto. Sai do contêiner de 1400px de propósito: com --maxw a
   imagem encolhe para ~280px e o produto vira miniatura de catálogo.
   Aqui cada peça ocupa um terço da tela inteira.
   -------------------------------------------------------------------------- */
.shop-grid{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:var(--sp-2);            /* fio fino, não calha: as fotos quase se tocam */
  padding-inline:var(--sp-2);
}
@media(max-width:960px){.shop-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:600px){.shop-grid{grid-template-columns:1fr;gap:var(--sp-4)}}

/* a foto manda: retrato alto, sem raio, encostando no fio */
.shop-grid .shop-card__media{aspect-ratio:3/4;border-radius:0}
.shop-grid .shop-card__media img{transition:transform var(--dur-zoom-longo) var(--ease),opacity var(--dur-linha) var(--ease)}
.shop-grid .shop-card:hover .shop-card__media img{transform:scale(1.03)}

/* o texto recua. Em foto desse tamanho, categoria e ficha técnica viram ruído:
   sobram nome, preço e a ação. */
.shop-grid .shop-card__body{padding:1rem .35rem 0;gap:.15em}
.shop-grid .shop-card__cat,
.shop-grid .shop-card__tags{display:none}
.shop-grid .shop-card__foot{margin-top:.35em;padding-top:0;border-top:0;align-items:flex-start}
.shop-grid .shop-card__title{font-size:clamp(1.1rem,1.5vw,1.45rem)}
@media(max-width:600px){
  .shop-grid .shop-card__body{padding-inline:var(--sp-2)}
}

.shop-empty{padding:var(--sp-8) 0;text-align:center;color:var(--fg-muted)}
.shop-empty:not([hidden]){display:flex;flex-direction:column;align-items:center;gap:var(--sp-4)}
.shop-empty__limpar{min-height:var(--alvo-toque);padding:.6em 1.3em;border:var(--border) solid currentColor;border-radius:var(--r-pill);
  color:var(--fg);font-family:var(--font-body);font-size:var(--text-body-sm);cursor:pointer}
.shop-empty__limpar:hover{background:var(--bg-invert);color:var(--fg-invert)}
.shop-empty__limpar[hidden]{display:none}

/* --------------------------------------------------------------------------
   NOTIFICAÇÃO DE SACOLA
   -------------------------------------------------------------------------- */
.toast{
  position:fixed;right:var(--gutter);bottom:var(--sp-5);z-index:var(--z-toast);
  display:flex;align-items:center;gap:.9rem;
  background:var(--bg-invert);color:var(--fg-invert);
  padding:.8rem 1.2rem .8rem .8rem;border-radius:var(--r-md);
  box-shadow:var(--shadow-toast);
  transform:translateY(140%);opacity:0;pointer-events:none;
  transition:transform var(--dur-linha) var(--ease),opacity var(--dur-linha) var(--ease);
  max-width:min(22rem,calc(100vw - 2 * var(--gutter)));
}
.toast.is-on{transform:none;opacity:1;pointer-events:auto;cursor:pointer}   /* à vista, o toque abre a cesta (A6) */
.toast img{width:3rem;height:3.6rem;object-fit:cover;border-radius:var(--r-sm);flex:0 0 auto}
/* Este rótulo era salmão: 4,16:1 sobre o azul, e ele tem 11px. A regra dos
   quentes vale a partir de 24px — abaixo disso o quente é forma, não letra.
   Creme dá 11,25:1 e o salmão continua na composição, como o fio do toast. */
.toast__t{font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);font-size:var(--text-micro);
  letter-spacing:var(--tracking-caps-sm);padding-left:var(--tracking-caps-sm);
  text-transform:uppercase;color:var(--fg-invert)}
.toast__n{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h3);font-size:1rem;line-height:1.2}

/* --------------------------------------------------------------------------
   CAMPO DE FORMULÁRIO — nasce aqui porque a página de conta precisou dele,
   mas é componente de sistema: rótulo em versalete, fio embaixo, sem caixa.
   Sem caixa de propósito — a marca é impressa, e ficha de papel tem linha,
   não moldura.
   -------------------------------------------------------------------------- */
.field{display:flex;flex-direction:column;gap:.45em}
.field__label{font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-micro);letter-spacing:var(--tracking-caps-sm);
  padding-left:var(--tracking-caps-sm);text-transform:uppercase;color:var(--fg-muted)}
.field__input{
  width:100%;background:transparent;color:var(--fg);
  font-family:var(--font-body);font-variation-settings:var(--vf-body-clean);
  font-size:var(--text-body);line-height:1.4;
  /* .7em de piso: com o rótulo em cima, o campo inteiro passa dos 44px */
  padding:.7em 0;border:0;border-bottom:var(--border) solid var(--line);
  border-radius:0;
  transition:border-color var(--dur-fast) var(--ease)}
.field__input::placeholder{color:color-mix(in srgb, var(--c-azul-mare) 55%, transparent)}
.field__input:focus{outline:0;border-bottom-color:var(--fg)}
.field__input:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:var(--r-sm)}
/* erro junto ao campo (Confirmar senha): o texto fica logo abaixo e o fio do campo fica em lacre */
.field__erro{margin:0;font-size:var(--text-body-sm);line-height:1.45;color:var(--c-lacre)}.field__ajuda{margin:0;font-size:var(--text-body-sm);line-height:1.45;color:var(--fg-muted)}
.field__input[aria-invalid="true"]{border-bottom-color:var(--c-lacre)}

/* Caixa de marcar: o quadrado é desenhado, não o nativo — o nativo não aceita
   a cor da marca em navegador nenhum de forma confiável. O input continua no
   DOM (só sai de vista), então teclado e leitor de tela seguem funcionando. */
.check,.auth-consent{display:flex;align-items:flex-start;gap:.65em;cursor:pointer;
  font-size:var(--text-body-sm);color:var(--fg-muted);line-height:1.45}
.check input,.auth-consent input{position:absolute;width:1px;height:1px;opacity:0}
.check__box{flex:none;width:1.15em;height:1.15em;margin-top:.15em;
  border:var(--border) solid var(--fg-muted);border-radius:var(--r-sm);
  display:grid;place-items:center;
  transition:background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)}
.check__box::after{content:"";width:.42em;height:.72em;margin-top:-.14em;
  border:solid var(--fg-on-accent);border-width:0 2px 2px 0;transform:rotate(45deg) scale(0);
  transition:transform var(--dur-fast) var(--ease)}
.check input:checked + .check__box,.auth-consent input:checked + .check__box{
  background:var(--accent);border-color:var(--accent)}
.check input:checked + .check__box::after,
.auth-consent input:checked + .check__box::after{transform:rotate(45deg) scale(1)}
.check input:focus-visible + .check__box,
.auth-consent input:focus-visible + .check__box{outline:2px solid var(--accent);outline-offset:3px}

/* --------------------------------------------------------------------------
   CONTA — entrar e criar
   Molde do BJK: card flutuante em duas colunas, foto à esquerda que se cruza
   com a outra quando a aba troca, formulário à direita, e os dois formulários
   dividindo a mesma célula de grid para o card nunca mudar de altura.

   O que NÃO veio junto foi o raio de 1,8rem do card. O DS desta marca tem
   2px e 4px, e ponto: ela é impressa, não material. Card com canto redondo
   grande é linguagem de app, e aqui viraria o único elemento arredondado da
   casa inteira.
   -------------------------------------------------------------------------- */
.auth-body{min-height:100svh;margin:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:clamp(1rem,3vw,2.5rem);position:relative;overflow-x:hidden;background:var(--bg)}

/* Fundo: a MESMA foto do card, desfocada e ampliada. Não é enfeite — é o que
   impede o card de flutuar sobre creme chapado, que deixaria a página com
   cara de formulário solto. */
.auth-bg{position:fixed;inset:-10vw;z-index:0}
.auth-bg__layer{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;background:center/cover no-repeat;
  /* 52px de blur nao e enfeite: e o que transforma video em CAMPO DE COR.
     Menos que isso e o olho tenta ler a imagem e o card vira legenda dela. */
  filter:blur(52px) saturate(1.06);transform:scale(1.18);opacity:0;
  transition:opacity var(--dur-slow) var(--ease);will-change:opacity}
.auth-bg__layer.is-shown{opacity:1}
.auth-bg::after{content:"";position:absolute;inset:0;
  background:color-mix(in srgb, var(--c-azul-profundo) 34%, transparent)}

.auth-card{position:relative;z-index:1;width:100%;max-width:64rem;
  display:grid;grid-template-columns:1.02fr 1fr;
  background:var(--bg);border:var(--border) solid var(--line);
  border-radius:var(--r-md);overflow:hidden;
  box-shadow:0 24px 70px color-mix(in srgb, var(--c-azul-profundo) 26%, transparent)}

/* Botões de canto. Alvo de 44px porque são os únicos controles de saída. */
.auth-corner{width:2.75rem;height:2.75rem;flex:none;display:grid;place-items:center;
  border:var(--border) solid color-mix(in srgb, var(--c-azul-profundo) 20%, transparent);
  border-radius:var(--r-circle);color:var(--fg);
  background:color-mix(in srgb, var(--c-creme) 78%, transparent);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  transition:background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease),
             transform var(--dur-fast) var(--ease)}
.auth-corner svg{width:1.1rem;height:1.1rem}
.auth-close{position:absolute;top:clamp(1rem,2vw,1.5rem);right:clamp(1rem,2vw,1.5rem);z-index:6}
.auth-close:hover{background:var(--bg);border-color:var(--fg);transform:rotate(90deg)}
.auth-return:hover{background:var(--bg);border-color:var(--fg);transform:translateX(-3px)}

/* ---- esquerda: as duas fotos ---- */
/* A coluna vira duas faixas: a foto em cima, LIMPA, e a copy embaixo numa
   chapa azul. Antes a copy morava sobre a foto com um veu por baixo dela.
   O veu saiu por decisao de projeto, e sem ele a medicao foi impiedosa:
   1,10:1 na sobrancelha, 1,15:1 no titulo, 1,17:1 na linha — o texto nao
   fica dificil, fica invisivel, porque a foto e ceu claro exatamente na
   altura em que ele assentava.
   A chapa resolve os dois lados: a foto nao recebe nada por cima e o texto
   ganha fundo proprio. E idioma de legenda impressa, que e a casa da marca. */
.auth-visual{position:relative;overflow:hidden;min-height:34rem;
  display:flex;flex-direction:column}
.auth-visual__moldura{position:relative;flex:1;min-height:0;overflow:hidden}
.auth-visual__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transform:scale(1.06);
  transition:opacity var(--dur-slow) var(--ease),transform var(--dur-zoom-longo) var(--ease);
  will-change:opacity,transform}
.auth-visual__img.is-shown{opacity:1;transform:scale(1)}
/* SEM VEU sobre a foto — decisao de quem manda, com o numero na mao: o
   titulo cai para ~2,3:1 e a linha de apoio para ~2,0:1 sobre o ceu claro
   da foto. Fica assim ate a proxima leitura. Se voltar, o gradiente que
   funcionava era 14%% no topo, 40%% no meio e 84%% no pe. */
.auth-visual__top{position:absolute;top:clamp(1rem,2vw,1.5rem);left:clamp(1rem,2vw,1.5rem);
  z-index:6;display:flex;align-items:center;gap:1rem}
/* O WORDMARK, fora do card. Dentro dele disputava a esquina com a seta de
   voltar e lia como enfeite da foto; aqui assina a pagina.
   O negativo ja vem em creme — nada de filtro para inverter. */
.auth-marca{position:fixed;z-index:3;
  top:clamp(1.25rem,3vw,2.25rem);left:clamp(1.25rem,3vw,2.25rem);
  display:inline-flex;align-items:center}
.auth-marca img{height:var(--h-logo-min);width:auto;
  /* a sombra existe porque o fundo e video: o campo muda de claro para
     escuro conforme a agua anda, e sem ela o wordmark some nos quadros
     claros. E sombra de contato, nao tarja: 18%% de alfa e 10px de raio. */
  filter:drop-shadow(0 2px 10px color-mix(in srgb, var(--c-azul-profundo) 55%, transparent))}
.auth-visual__copy{position:relative;z-index:2;flex:none;
  background:var(--bg-invert);color:var(--fg-invert);
  padding:clamp(1.4rem,2.6vw,2rem) clamp(1.5rem,3vw,2.4rem)}
.auth-visual__eyebrow{font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-micro);letter-spacing:var(--tracking-caps-sm);
  padding-left:var(--tracking-caps-sm);text-transform:uppercase;
  color:var(--fg-invert-muted);margin-bottom:.9em}
.auth-visual__title{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h2);
  font-size:clamp(1.75rem,3vw,2.6rem);line-height:1.06;letter-spacing:-.015em}
.auth-visual__title em{font-family:var(--font-script);font-style:normal;font-weight:400;
  letter-spacing:0;text-transform:none;font-size:max(var(--text-quente-min), .86em);color:var(--accent-text-invert)}
.auth-visual__note{color:var(--fg-invert-muted);font-size:var(--text-body-sm);
  line-height:1.5;max-width:32ch;margin-top:1em}

/* ---- direita: o painel ---- */
.auth-panel{padding:clamp(1.4rem,2.4vw,2.2rem);display:flex;flex-direction:column}
/* O botao do Google e o divisor somaram ~110px ao painel e a pagina passou
   a rolar. O respiro do cabecalho e o primeiro a ceder: ele e o que menos
   custa, porque o titulo ja tem peso proprio. */
.auth-head{margin:clamp(.9rem,2vw,1.4rem) 0 clamp(.9rem,1.8vw,1.3rem)}
.auth-head h1{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h2);
  font-size:clamp(1.6rem,2.6vw,2.2rem);line-height:1.06;letter-spacing:-.015em;
  transition:opacity var(--dur-fast) var(--ease),transform var(--dur-fast) var(--ease)}
.auth-head p{color:var(--fg-muted);font-size:var(--text-body-sm);line-height:1.5;margin-top:.7em;
  transition:opacity var(--dur-fast) var(--ease),transform var(--dur-fast) var(--ease)}
.auth-head.is-swapping h1,.auth-head.is-swapping p{opacity:0;transform:translateY(10px)}

/* As abas. A pílula que desliza é o único elemento com --r-pill aqui, e isso
   é coerente: no sistema o pill é sempre CONTROLE, nunca contêiner. */
.auth-tabs{position:relative;display:flex;gap:.25rem;padding:.3rem;
  background:color-mix(in srgb, var(--c-azul-profundo) 6%, transparent);
  border-radius:var(--r-pill);margin-bottom:clamp(1rem,1.8vw,1.3rem)}
.auth-tabs__thumb{position:absolute;top:.3rem;bottom:.3rem;left:.3rem;
  width:calc((100% - .85rem) / 2);border-radius:var(--r-pill);background:var(--bg);
  box-shadow:0 2px 9px color-mix(in srgb, var(--c-azul-profundo) 14%, transparent);
  z-index:0;transition:transform var(--dur-base) var(--ease-menu)}
.auth-tabs.is-criar .auth-tabs__thumb{transform:translateX(calc(100% + .25rem))}
.auth-tab{position:relative;z-index:1;flex:1;
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  padding-left:var(--tracking-caps-md);text-transform:uppercase;
  padding-block:1em;border:0;border-radius:var(--r-pill);background:none;  /* 1em = 44px de alvo */
  color:var(--fg-muted);cursor:pointer;
  transition:color var(--dur-fast) var(--ease)}
.auth-tab.is-active{color:var(--fg)}

/* Os dois formulários na MESMA célula: o bloco fica da altura do maior e o
   card não pula de tamanho quando a aba troca. */
.auth-forms{display:grid}
.auth-form{grid-area:1 / 1;align-self:start;display:flex;flex-direction:column;
  gap:clamp(1rem,2vw,1.3rem)}
/* O inativo sai por VISIBILITY, nunca pelo atributo hidden. hidden tira o
   formulario do layout, e ai a celula volta a ter a altura do formulario
   ativo: o card pulava 23px ao trocar de aba, que e exatamente o defeito que
   a celula compartilhada existe para evitar. visibility mantem a caixa,
   tira do foco e do leitor de tela. O delay segura a saida ate a animacao
   terminar. */
.auth-form:not(.is-active){visibility:hidden;pointer-events:none;overflow:hidden;
  transition:visibility 0s var(--dur-base)}
/* overflow:hidden só no inativo: os filhos dele esperam a vez 18px abaixo (a cascata), e sem o corte esse
   deslocamento invisível alongava a rolagem do card quando o Criar conta, maior, é o inativo (06/10) */
.auth-form.is-active{visibility:visible}
/* cada filho entra em degrau — mesmo princípio da cascata do carrossel */
.js .auth-form > *{opacity:0;transform:translateY(18px);
  transition:opacity var(--dur-base) var(--ease),transform var(--dur-base) var(--ease)}
.js .auth-form.is-active > *{opacity:1;transform:none}
.js .auth-form.is-active > *:nth-child(1){transition-delay:60ms}
.js .auth-form.is-active > *:nth-child(2){transition-delay:130ms}
.js .auth-form.is-active > *:nth-child(3){transition-delay:200ms}
.js .auth-form.is-active > *:nth-child(4){transition-delay:270ms}
.js .auth-form.is-active > *:nth-child(5){transition-delay:340ms}

/* CONTINUAR COM O GOOGLE. Segue as diretrizes oficiais do botão (Sign in with
   Google Branding Guidelines, tema claro): fundo #FFFFFF, fio de 1px #747775,
   texto #1F1F1F em Google Sans Medium 14/20, 12px antes do G, 10px entre G e
   texto, 12px depois; G colorido de 18px, sem recolorir. É a única peça fora da
   paleta e da tipografia da loja, de propósito: marca de terceiro não se adapta.
   Escondido por padrão (hidden): só a sessão o mostra, e só com o provedor
   confirmado pelo Identity. A fonte é carregada pela sessão nessa hora. */
.auth-google{display:flex;align-items:center;justify-content:center;gap:10px;
  width:100%;min-height:var(--alvo-toque,44px);padding:0 12px;
  background:#FFFFFF;color:#1F1F1F;border:1px solid #747775;border-radius:var(--r-pill);
  font-family:'Google Sans',Roboto,Arial,sans-serif;font-weight:500;font-size:14px;line-height:20px;
  letter-spacing:.25px;text-transform:none;cursor:pointer;
  transition:background var(--dur-fast) var(--ease)}
.auth-google:hover{background:#F8F9FA}
.auth-google[aria-busy="true"]{cursor:progress}
.auth-google svg{flex:none;width:18px;height:18px}
.auth-google[hidden],.auth-ou[hidden]{display:none}

/* o ou com fio dos dois lados: e regua, nao rotulo */
.auth-ou{display:flex;align-items:center;gap:.9em;margin:clamp(.8rem,1.5vw,1rem) 0;
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-micro);letter-spacing:var(--tracking-caps-sm);
  padding-left:var(--tracking-caps-sm);text-transform:uppercase;color:var(--fg-muted)}
.auth-ou::before,.auth-ou::after{content:"";flex:1;height:var(--border);background:var(--line)}

.auth-row{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}
.auth-link{font-size:var(--text-body-sm);color:var(--fg-muted);
  text-decoration:underline;text-underline-offset:.28em;
  text-decoration-color:color-mix(in srgb, var(--c-azul-mare) 45%, transparent);
  transition:color var(--dur-fast) var(--ease),text-decoration-color var(--dur-fast) var(--ease)}
.auth-link:hover{color:var(--fg);text-decoration-color:var(--accent)}
button.auth-link{font:inherit;font-size:var(--text-body-sm);background:none;border:0;padding:0;cursor:pointer;position:relative}
.auth-form .btn{width:100%;justify-content:center;margin-top:.3rem}
/* o link de troca é o último filho de cada formulário: o gap do formulário já o separa do botão */
.auth-switch{font-size:var(--text-body-sm);color:var(--fg-muted);text-align:center;margin-top:0}
.auth-switch button{background:none;border:0;padding:0;color:var(--fg);font:inherit;position:relative;
  text-decoration:underline;text-underline-offset:.28em;cursor:pointer}
button.auth-link::after,.auth-switch button::after{content:"";position:absolute;left:-.35em;right:-.35em;top:50%;height:var(--alvo-toque);transform:translateY(-50%)} /* alvo de 44 px, invisível */
.auth-status{font-size:var(--text-body-sm);color:var(--fg-muted);text-align:center;
  margin-top:1rem;min-height:1.4em}

/* Empilhado: a manchete sai do painel e vai para CIMA da foto. Isso devolve
   ~10rem de altura e é o que faz o card inteiro caber na tela do telefone. */
@media(max-width:860px){
  .auth-body{padding:.75rem}
  .auth-card{grid-template-columns:1fr;max-width:30rem}
  /* No empilhado a chapa da copy divide a coluna com a foto, e sem uma altura
     propria a foto sobrava com 112px — virava faixa, nao imagem. Aqui ela
     ganha proporcao e a coluna cresce; a pagina rola uns 90px, e rolar numa
     tela de login e normal. Espremer a foto para caber nao e. */
  .auth-visual{min-height:0}
  /* A foto ganha altura pela ALTURA da tela (um quinto dela, entre 6,5 e 12rem), e não pela proporção: é
     o que cede primeiro para o formulário caber inteiro; o recorte continua centrado na bolsa (object-fit). */
  .auth-visual__moldura{aspect-ratio:auto;flex:none;height:clamp(6.5rem,20svh,12rem)}
  /* a chapa azul "Seu lugar na banca", mais compacta: mesma identidade, menos respiro */
  .auth-visual__copy{padding:.85rem 1.1rem .95rem}
  .auth-visual__note{font-size:var(--text-caption);line-height:1.4;margin-top:.45em}
  .auth-close{display:none}          /* na pilha a seta já basta */
  .auth-visual__top{left:auto;right:clamp(1rem,2vw,1.5rem)}
  /* o card toma a tela inteira no empilhado; nao sobra canto para a marca */
  .auth-marca{display:none}
  .auth-visual__eyebrow,.auth-head{display:none}
  .auth-visual__title{font-size:1.45rem}
  .auth-panel{padding:1rem 1.1rem 1.1rem}
  /* rótulos, campos e ações mais juntos; letras e alvos de 44px iguais */
  .auth-tabs{margin-bottom:.75rem}
  .auth-form{gap:.7rem}
  .field{gap:.3em}
  .auth-form .btn{margin-top:.15rem}
  /* Entrar e Criar conta do MESMO tamanho (decisão do proprietário, 06/10): os dois formulários seguem na mesma
     célula também no empilhado, e o card tem sempre a altura do Criar conta, que é o maior. Ao trocar de aba,
     topo, largura, altura e foto não se movem. "Primeira vez?" / "Já é da freguesia?" vivem dentro de cada
     formulário, logo abaixo do botão; o Entrar fica com espaço livre embaixo, e isso é o combinado. */
  .auth-status{margin-top:.5rem;min-height:0}
  .auth-status:empty{display:none}
}
/* Tela baixa de celular: a área decorativa cede primeiro (foto menor, nota da chapa guardada); os campos,
   as letras e os alvos não mudam. Abaixo disso a página rola, e rolar é permitido. */
@media(max-width:860px) and (max-height:720px){
  .auth-visual__moldura{height:clamp(4.5rem,13svh,7rem)}
  .auth-visual__note{display:none}
  .auth-visual__copy{padding:.7rem 1.1rem .8rem}
}
@media(max-width:860px) and (max-height:600px){
  .auth-visual__moldura{display:none}   /* abaixo de 600px de altura a foto sai; o Criar conta ainda cabe */
  .auth-body{padding:.5rem}
}

/* O subtítulo do Criar conta ocupa duas linhas e o do Entrar, uma. Sem reservar
   as duas linhas nas DUAS abas, o cabeçalho cresce na troca e as abas e os
   formulários pulam uma linha — o defeito que a célula compartilhada existe para
   evitar. No empilhado o cabeçalho some, então a regra é só do computador. */
@media(min-width:861px){
  .auth-head p{min-height:3em}
}
/* Tela baixa de computador (notebook). Com o Confirmar senha, o botão de Criar
   conta ficava 40px abaixo da borda em 1280x720. Cedem só os respiros entre
   blocos: corpo e painel no piso do próprio clamp, cabeçalho, abas e o gap dos
   formulários. Letras, campos de 44px e abas de 44px ficam iguais. 900px é a
   altura que a tela inteira pede sem compactar: acima dela nada muda. */
@media(min-width:861px) and (max-height:900px){
  .auth-body{padding-block:1rem}
  .auth-panel{padding-block:1.4rem}
  .auth-head{margin:.5rem 0 .875rem}
  .auth-tabs{margin-bottom:.875rem}
  .auth-form{gap:.875rem}   /* o link de troca é filho do formulário: o gap já o separa do botão */
}

/* --------------------------------------------------------------------------
   ONDA  [data-onda]
   A frase nao entra e para: ela ONDULA em looping, letra a letra. Cada letra
   corre a mesma animacao com a fase deslocada, e o que se ve e uma crista
   atravessando o texto.

   Os atrasos sao todos NEGATIVOS de proposito. Com atraso positivo a letra
   fica parada esperando a vez, e numa frase de 45 letras a ultima so comecaria
   2,7s depois — a primeira volta sairia torta. Negativo, todas ja nascem em
   pontos diferentes do ciclo e a onda esta formada no primeiro quadro.

   O sinal define a direcao: `(i - n)` faz a crista viajar da esquerda para a
   direita, no sentido da leitura. Trocar para `-i` inverte.
   -------------------------------------------------------------------------- */
@keyframes mdm-onda{
  0%,100%{transform:translateY(0)}
  50%    {transform:translateY(-0.16em)}
}
.onda__l{display:inline-block;white-space:pre}
.js [data-onda] .onda__l{
  animation:mdm-onda var(--dur-onda) ease-in-out infinite;
  animation-delay:calc((var(--i) - var(--n)) * var(--onda-passo));
  will-change:transform}
@media(prefers-reduced-motion:reduce){
  .js [data-onda] .onda__l{animation:none}
}

/* --------------------------------------------------------------------------
   MOVIMENTO REDUZIDO
   -------------------------------------------------------------------------- */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;
    transition-duration:.01ms !important;scroll-behavior:auto !important}
  .js .reveal{opacity:1;transform:none;filter:none}
}

/* o nome do produto leva para a página da peça */
.shop-card__title a{display:inline-block;transition:opacity var(--dur-fast) var(--ease)}
.shop-card__title a:hover{opacity:.6}

/* --------------------------------------------------------------------------
   WORDMARK EM CASCATA — rodapé
   As letras não aparecem: elas SOBEM. Estão sempre lá, deitadas embaixo de um
   corte, e o scroll só decide quanto de cada uma já emergiu.
   -------------------------------------------------------------------------- */
.casc{margin-top:clamp(2.5rem,7vh,4rem)}
/* line-height:0 não é enfeite: um <svg> inline herda o vão de descida do texto
   e sobra uma fresta de 3–4px por onde as letras aparecem antes da hora. */
.casc-mask{display:block;overflow:hidden;line-height:0}
.casc-mark{display:block;width:100%;height:auto;color:var(--fg-invert)}
/* transform-box:fill-box é a linha inteira. Sem ela, um transform num path de
   SVG usa o sistema de coordenadas do viewBox: translateY(90%) viraria 90% da
   altura do canvas e o rotate giraria em torno do canto do desenho — as letras
   varreriam a tela num arco. Com fill-box cada letra usa a caixa dela mesma,
   e o transform-origin põe o pivô no meio da própria base. */
.casc-mark [data-l]{transform-box:fill-box;transform-origin:50% 100%;
  will-change:transform}

@media(prefers-reduced-motion:reduce){
  .casc-mark [data-l]{transform:none !important}
}

/* --------------------------------------------------------------------------
   PRELOADER — O REGISTRO
   Duas chapas do MESMO wordmark entram fora de posição e convergem. O
   carregamento acaba no instante em que elas entram em registro.

   Por que máscara e não <img>: o arquivo é um só. Como mask-image, o mesmo
   SVG vira qualquer cor — duas chapas, um asset, zero duplicação.

   mix-blend-mode:multiply é o que faz a sobreposição parecer tinta e não
   camada: onde o lacre cruza o azul o resultado escurece, como escureceria
   no papel. Sem isso, a chapa de cima simplesmente tapa a de baixo.

   A chapa quente é o LACRE, não o salmão. Salmão em letra dá 2,71:1 sobre
   creme e a regra dura da paleta o proíbe; o lacre é a cor designada para
   selo e carimbo, que é exatamente o que esta animação encena.
   -------------------------------------------------------------------------- */
.pre-cover{display:none}
.pre,.pre body{overflow:hidden}
.pre .pre-cover{overflow:hidden;
  display:grid;place-items:center;
  position:fixed;inset:0;z-index:var(--z-pre);
  background:var(--bg);
  transition:opacity var(--dur-registro) var(--ease);
}
.pre-cover.is-out{opacity:0;pointer-events:none}

/* OS ADESIVOS — as cinco ilustracoes da marca, espalhadas.

   Antes era UMA delas grande atras do nome. Espalhado e pequeno le melhor, e
   resolve o problema que a folha unica tinha: uma imagem grande atras de um
   wordmark grande e uma disputa; marcas pequenas na periferia sao moldura.

   O movimento e STOP MOTION, nao animacao: cada adesivo aparece de uma vez,
   sem transicao nenhuma. E deliberado que seja outro registro do movimento
   da capa — o registro das chapas e maquina, liso e continuo; os adesivos
   sao mao, discretos e irregulares. Um de cada vez, nunca os dois ao mesmo
   tempo: enquanto os adesivos entram, as chapas so derivam; quando o
   assentamento comeca, os adesivos ja pararam.

   Quantos apareceram E o progresso. Nao ha barra: a folha se enchendo diz
   quanto falta.

   O arquivo ja vem sem papel — o fundo foi retirado por abertura morfologica
   e o alfa e de verdade. Por isso nao ha blend nenhum aqui: nao ha retangulo
   para esconder, e sobre creme o multiply so escureceria a meia-tinta. */
.pre-adesivos{
  position:absolute;inset:0;pointer-events:none;z-index:0;
  /* Os dois botoes da peca, juntos e num lugar so. Nao subiram para
     tokens.css porque nao sao do sistema: sao medida interna da capa, e
     tokens.css e arquivo compartilhado com a outra sessao. Ajuste ao vivo:
       document.querySelector('.pre-adesivos').style.setProperty('--adesivo-op', .9) */
  --adesivo-lado:clamp(52px, 6.4vw, 96px);
  --adesivo-op:1;
}
.pre-adesivo{
  position:absolute;
  /* As cinco tem proporcao diferente — 0,53 na lagosta, 0,98 no mexilhao.
     Amarrar pela LARGURA daria ao mexilhao o dobro da massa da lagosta.
     Amarrando os dois tetos, o que se iguala e o maior lado, que e a leitura
     certa de "adesivo do mesmo tamanho". O --peso vem medido no JS. */
  width:auto;height:auto;
  max-width:calc(var(--adesivo-lado) * var(--peso,1));
  max-height:calc(var(--adesivo-lado) * var(--peso,1));
  opacity:0;
  /* sem transition de proposito: stop motion e corte seco */
}
.pre-adesivo.is-on{opacity:var(--adesivo-op,.72)}
.pre-reg{
  position:relative;
  width:min(62vw,660px);
  aspect-ratio:1.6/1;                 /* a proporção medida no vetor */
  transition:transform var(--dur-registro) var(--ease);
  will-change:transform;
}
/* As chapas são <img> de verdade, não máscara CSS.

   Havia aqui um mask-image apontando para o mesmo SVG, recolorido por
   background. Funciona no Chromium — verificado renderizando em Chrome e
   Edge — mas é a dependência mais frágil da peça: quando a máscara não
   resolve, por qualquer motivo, o elemento não fica errado, ele SOME, e
   sobra a capa creme vazia. Falha silenciosa, indistinguível de "não
   carregou", e impossível de diagnosticar de longe.

   Duas imagens custam 12,5 KB a mais e não têm como falhar pela metade. */
.pre-plate{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain;
  mix-blend-mode:multiply;
  will-change:transform;
}

/* Sem movimento: a capa não encena nada. Fica a chapa azul parada e sai. */
@media(prefers-reduced-motion:reduce){
  .pre-plate--lacre{display:none}
  .pre-plate{transform:none !important}
  /* os adesivos aparecem todos de uma vez, no primeiro quadro. Com redução
     de movimento nada deve chegar em sequência — mas a moldura fica. */
  .pre-adesivo{opacity:var(--adesivo-op,.72)}
  .pre-reg{transition:none}
  .pre .pre-cover{overflow:hidden;transition-duration:var(--dur-fast)}
}

/* --------------------------------------------------------------------------
   CAMPO DA PDP — OS CLIMAS
   O vídeo desfocado continua sendo a FORMA. O que varia é a LUZ: cada clima é
   uma receita de filtro mais uma camada de cor em soft-light por cima.

   Por que em CSS e não com mais vídeos: o campo-direita.mp4 é placeholder de
   terceiro e não pode ir ao ar. Amarrar a variação a arquivos novos seria
   construir em cima do que vai ser trocado — e ainda dependeria de produzir
   cinco vídeos. Aqui a variação é gratuita e sobrevive à troca do vídeo.

   Nenhuma cor crua: tudo sai da paleta via color-mix sobre os tokens.
   -------------------------------------------------------------------------- */
.pdp__campo{
  --f-sat:.72; --f-bri:1.12; --f-hue:0deg;
  /* sem clima nao ha o que frear: as cores nascem transparentes */
  --veu:.58; --clima-op:1;
  --p1:22% 78%; --p2:78% 24%; --p3:50% 50%;
  /* SEM clima o campo é exatamente o que era antes: só o vídeo desfocado sob
     o véu. As cores nascem transparentes de propósito — a camada existe mas
     não pinta nada até um clima ser aplicado. Assim o componente degrada
     para o estado original em vez de para um estado novo. */
  --k1:transparent; --k2:transparent; --k3:transparent;
}
.pdp__campo img,.pdp__campo video{
  filter:blur(var(--blur-campo)) saturate(var(--f-sat))
         brightness(var(--f-bri)) hue-rotate(var(--f-hue));
}
/* A camada de clima fica ACIMA do véu, não abaixo. Embaixo ela existia mas
   não aparecia: o véu de creme a 58% lavava a cor toda e os cinco climas
   liam como cinco cremes. Em multiply o creme do véu vira o papel e o clima
   vira a tinta — que é a mecânica certa para uma marca impressa.
   z-index 3 é seguro: .pdp__campo tem z-index 0 e cria contexto de
   empilhamento, então nada aqui dentro passa por cima da ficha. */
/* --clima-op é freio, e nasceu de uma medição, não de gosto. Com o multiply
   solto o campo chegava a #A17F72 embaixo da nota, e ali o texto de apoio
   dava 1,78:1. Amortecer o multiply devolve piso sem devolver o problema que
   levou a camada para cima do véu — os cinco climas continuam distintos,
   só param de escurecer sem limite. */
.pdp__campo::before{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  mix-blend-mode:multiply;opacity:var(--clima-op,1);
  background:
    radial-gradient(ellipse 62% 54% at var(--p1),var(--k1) 0%,transparent 66%),
    radial-gradient(ellipse 48% 58% at var(--p2),var(--k2) 0%,transparent 62%),
    radial-gradient(ellipse 90% 70% at var(--p3),var(--k3) 0%,transparent 78%);
}
.pdp__campo::after{background:color-mix(in srgb,var(--c-creme) calc(var(--veu)*100%),transparent);z-index:2}
/* Com o vídeo do mar o campo escurece (mediana do fundo de ~205 para ~140) e a
   ficha perdia contraste: preço 3,98:1, medidas 3,68:1. Com o véu em .8, medido
   com o vídeo tocando nos cinco climas, preço, medidas, rótulos e descrição ficam
   em 6,2:1 ou mais (pede 4,5:1). Vale para qualquer clima: duas classes vencem o
   --veu dele. A frase em coral segue abaixo de 3:1, como já estava sem vídeo. */
.pdp__campo.is-video{--veu:.8}

/* MARÉ — a referência da água com reflexo quente quebrando na superfície */
/* --clima-op aparece só em DOIS dos cinco, e o valor é resolvido, não chutado.

   Como se acha: renderiza o campo sem texto com o multiply em 0 e em 1. A
   opacidade só interpola entre os dois (R = B(1-o) + Mo), então dá para varrer
   o `o` de cada clima contra as caixas de texto do painel e achar o maior que
   ainda segura 4,6:1. A base B não depende de onde as manchas caem — só a
   camada ::before tem manchas — então serve uma base por clima.

   Duas armadilhas que mudaram a resposta, as duas descobertas errando:

   1. As manchas se movem. O respira() sorteia p1/p2/p3 em intervalos largos
      (x 12–34, 66–88, 38–62), e resolver numa posição dava número que não
      valia na seguinte: 0,46 media 4,61:1 numa carga e 4,10:1 na outra. Aqui
      o `o` é o que segura 4,6:1 em SETE posições, quatro delas nos extremos.

   2. A caixa de amostra pegava os FIOS das linhas da ficha, que são mais
      escuros que o campo. Estava medindo borda e chamando de fundo de texto,
      e por isso amortecendo três climas que não precisavam: sol, sombra e
      salmoura passam com o multiply inteiro. Só maré e conserva escurecem o
      bastante para precisar de freio.

   Se o vídeo do campo trocar, estes números têm que ser refeitos: descrevem a
   relação entre ESTE vídeo e a ficha, não uma constante. O andaime está em
   Branding/mobile-retrato.html (#fantasma=1&clima=&climaop=&manchas=). */
.campo--mare{--clima-op:.54;--f-sat:.78;--f-bri:1.10;--f-hue:-6deg;--veu:.56;
  --k1:color-mix(in srgb,var(--c-azul-mare) 72%,transparent);
  --k2:color-mix(in srgb,var(--c-salmao) 50%,transparent);
  --k3:color-mix(in srgb,var(--c-azul-aguada) 58%,transparent)}
/* SOL — Super-8 estourado: amarelo desbotado, pouca saturação, muita luz */
.campo--sol{--f-sat:.48;--f-bri:1.30;--f-hue:-16deg;--veu:.50;
  --k1:color-mix(in srgb,var(--c-amarelo) 58%,transparent);
  --k2:color-mix(in srgb,var(--c-salmao) 38%,transparent);
  --k3:color-mix(in srgb,var(--c-lona) 60%,transparent)}
/* SOMBRA — a areia com a sombra da palmeira: neutro quente, mais contraste */
.campo--sombra{--f-sat:.34;--f-bri:1.04;--f-hue:8deg;--veu:.46;
  --k1:color-mix(in srgb,var(--c-lona) 78%,transparent);
  --k2:color-mix(in srgb,var(--c-tinta) 17%,transparent);
  --k3:color-mix(in srgb,var(--c-creme) 55%,transparent)}
/* SALMOURA — aguada fria e pálida, quase sem cor */
.campo--salmoura{--f-sat:.30;--f-bri:1.20;--f-hue:-2deg;--veu:.62;
  --k1:color-mix(in srgb,var(--c-azul-aguada) 68%,transparent);
  --k2:color-mix(in srgb,var(--c-verde) 40%,transparent);
  --k3:color-mix(in srgb,var(--c-creme) 62%,transparent)}
/* CONSERVA — a lata: quente, coral e creme, o mais saturado dos cinco */
.campo--conserva{--clima-op:.61;--f-sat:.86;--f-bri:1.06;--f-hue:6deg;--veu:.52;
  --k1:color-mix(in srgb,var(--c-coral) 50%,transparent);
  --k2:color-mix(in srgb,var(--c-amarelo) 44%,transparent);
  --k3:color-mix(in srgb,var(--c-salmao) 46%,transparent)}

/* Sem color-mix o campo cai no vídeo desfocado puro — que é exatamente o
   estado anterior, e continua bonito. Nada quebra. */
@supports not (background:color-mix(in srgb,red 50%,transparent)){
  .pdp__campo::before{display:none}
  .pdp__campo::after{background:color-mix(in srgb, var(--c-creme) 58%, transparent)}
}
/* --------------------------------------------------------------------------
   A CESTA — a gaveta

   O que ela NÃO tem, e o porquê, porque as duas ausências são decisão:

   - Sem seletor de quantidade. Toda peça é única (data-stock="1"): um
     "− 01 un. +" só sabe dizer 1 e existe para ser recusado. No lugar dele a
     linha diz PEÇA ÚNICA, que é justamente a informação que o seletor
     esconderia atrás de um controle morto.
   - Sem cupom e sem código de vendedor. Campo de desconto numa banca de
     cinco peças a preço fixo promete um desconto que não existe, e campo que
     nunca aceita nada custa mais confiança do que rende.

   O CEP fica: saber para onde vai é informação real, e quem compra quer o
   número antes de decidir.

   Gaveta pela direita e não folha inteira: a cesta é um aparte, não um
   destino. Ela some e a página continua onde estava.
   -------------------------------------------------------------------------- */
.cesta{position:fixed;inset:0;z-index:calc(var(--z-header) + 20)}
.cesta[hidden]{display:none}
.cesta__veu{position:absolute;inset:0;
  background:color-mix(in srgb, var(--c-azul-profundo) 42%, transparent);
  opacity:0;transition:opacity var(--dur-base) var(--ease-menu)}
.cesta.is-open .cesta__veu{opacity:1}

/* A mesma --ease-menu da chapa do menu, pelo mesmo motivo: a expo-out da
   marca chega batendo num painel do tamanho da tela. */
.cesta__painel{
  position:absolute;inset-block:0;inset-inline-end:0;
  width:min(27rem,100%);
  display:flex;flex-direction:column;
  background:var(--bg);color:var(--fg);
  box-shadow:var(--shadow-toast);
  transform:translateX(101%);
  transition:transform var(--dur-base) var(--ease-menu);
}
.cesta.is-open .cesta__painel{transform:none}
@media(prefers-reduced-motion:reduce){
  .cesta__veu,.cesta__painel{transition:none}
}

.cesta__topo{display:grid;grid-template-columns:auto 1fr auto;align-items:baseline;
  gap:var(--sp-3);padding:var(--sp-5) var(--gutter) var(--sp-4);
  border-bottom:var(--border) solid var(--line)}
.cesta__tit{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h3);font-size:1.5rem;line-height:1.1}
.cesta__conta{font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-sm);
  text-transform:uppercase;color:var(--fg-muted)}
/* alinhado pelo topo e não pela baseline: o X é ícone, não letra */
.cesta__x{align-self:start;display:grid;place-items:center;
  inline-size:var(--alvo-toque);block-size:var(--alvo-toque);
  margin-inline-end:calc(-1 * min(var(--sp-3),var(--gutter)));
  margin-block-start:calc(var(--sp-2) * -1);
  transition:opacity var(--dur-fast) var(--ease)}
.cesta__x:hover{opacity:.6}

.cesta__corpo{flex:1;overflow-y:auto;overscroll-behavior:contain;
  padding-inline:var(--gutter)}
/* A19 (07/10): tela baixa (celular deitado, 375px de altura). O pé (CEP, entrega, total e "Fechar compra") media
   334px: a lista de peças ficava com ZERO de altura e o botão terminava abaixo da tela. Aqui o painel inteiro rola,
   na ordem peças → entrega → total → botão. Até 700px de altura (também computador baixo e celular em pé com o
   teclado aberto), porque com as opções de entrega à vista o pé passa de 400px; em telas altas, nada muda. */
@media(max-height:700px){
  .cesta__painel{overflow-y:auto;overscroll-behavior:contain}
  .cesta__corpo{flex:none;overflow:visible}
}

/* Duas colunas, e a lixeira sai do fluxo. Em tres colunas ela comia a
   terceira em TODAS as linhas, e o rotulo "embalagem pra presente" quebrava
   em duas — sobrava faixa vazia debaixo do icone e faltava largura no texto. */
.cesta__item{position:relative;display:grid;grid-template-columns:4.75rem 1fr;
  gap:var(--sp-4);align-items:start;
  padding-block:var(--sp-5);border-bottom:var(--border) solid var(--line)}
.cesta__item:last-child{border-bottom:0}
/* a sombra da peça que saiu: não recebe toque; o deslize para a direita não abre rolagem lateral */
.cesta__item.is-saindo{pointer-events:none}
.cesta__itens{overflow-x:clip}
.cesta__foto{width:100%;aspect-ratio:4/5;object-fit:cover;
  border-radius:var(--r-sm);background:var(--bg-surface)}
.cesta__nome{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h3);font-size:1.125rem;line-height:1.2;
  padding-inline-end:var(--alvo-toque)}
.cesta__preco{margin-top:.3em;font-variation-settings:var(--vf-body-price);
  font-variant-numeric:tabular-nums}
/* PEÇA ÚNICA é o que substitui o seletor de quantidade — e diz mais que ele */
.cesta__unica{margin-top:.5em;font-family:var(--font-badge);
  font-variation-settings:var(--vf-badge-sm);font-size:var(--text-micro);
  letter-spacing:var(--tracking-caps-sm);padding-left:var(--tracking-caps-sm);
  text-transform:uppercase;color:var(--fg-muted)}
/* quantidade (06/10): "− n +" com alvo de toque; indisponível e o aviso de ajuste no tom do erro */
.cesta__qtd{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-2);margin-top:var(--sp-2)}
.cesta__qtd-b{display:grid;place-items:center;inline-size:var(--alvo-toque);block-size:var(--alvo-toque);
  border:var(--border) solid var(--line);border-radius:var(--r-pill);background:var(--bg);color:var(--fg);
  font-size:1.15rem;line-height:1;cursor:pointer}
.cesta__qtd-b:hover:not(:disabled){border-color:currentColor}
.cesta__qtd-b:disabled{opacity:.4;cursor:default}
.cesta__qtd-n{min-inline-size:1.6em;text-align:center;font-variant-numeric:tabular-nums;font-weight:600}
.cesta__qtd-max{flex-basis:100%;font-size:var(--text-caption);color:var(--fg-muted)}
.cesta__indisponivel,.cesta__ajuste{margin-top:.5em;font-size:var(--text-body-sm);color:var(--c-lacre)}
/* aviso de peça indisponível no topo do pé: texto, não alerta piscando; fio lacre à esquerda marca o vínculo com o rótulo do item */
.cesta__aviso-disp{margin:0 0 var(--sp-4);padding-left:.75em;border-left:2px solid var(--c-lacre);
  font-size:var(--text-body-sm);line-height:1.45;color:var(--fg)}
.cesta__aviso-disp[hidden]{display:none}
.cesta__brinde{display:flex;align-items:center;gap:.6em;
  margin-top:var(--sp-2);min-height:var(--alvo-toque);
  font-size:var(--text-body-sm);color:var(--fg-muted);cursor:pointer}
.cesta__brinde input{inline-size:1.1rem;block-size:1.1rem;accent-color:var(--accent);
  margin:0;flex:none}
.cesta__tirar{position:absolute;inset-block-start:var(--sp-4);inset-inline-end:0;
  display:grid;place-items:center;
  inline-size:var(--alvo-toque);block-size:var(--alvo-toque);
  margin-inline-end:calc(var(--sp-3) * -1);
  color:var(--fg-muted);transition:color var(--dur-fast) var(--ease)}
.cesta__tirar:hover{color:var(--accent)}

.cesta__vazia{display:none;flex-direction:column;align-items:flex-start;
  gap:var(--sp-4);padding-block:var(--sp-8)}
.cesta__vazia p{color:var(--fg-muted)}
.cesta.is-vazia .cesta__vazia{display:flex}
.cesta.is-vazia .cesta__pe{display:none}

.cesta__pe{padding:var(--sp-5) var(--gutter);
  border-top:var(--border) solid var(--line);background:var(--bg-surface)}
.cesta__rot{display:block;font-family:var(--font-badge);
  font-variation-settings:var(--vf-badge-sm);font-size:var(--text-micro);
  letter-spacing:var(--tracking-caps-sm);padding-left:var(--tracking-caps-sm);
  text-transform:uppercase;color:var(--fg-muted);margin-bottom:.6em}
.cesta__linha{display:flex;flex-wrap:wrap;gap:var(--sp-2)}
.cesta__campo{flex:1 1 10rem;min-width:0;min-height:var(--alvo-toque);
  padding:.7em 1.1em;background:var(--bg);color:var(--fg);
  border:var(--border) solid var(--line);border-radius:var(--r-pill);
  font-family:var(--font-body);font-size:var(--text-body-sm);
  font-variant-numeric:tabular-nums}
.cesta__campo::placeholder{color:color-mix(in srgb,var(--fg-muted) 62%,transparent)}
.cesta__campo:focus-visible{border-color:var(--accent)}
.cesta__calc{flex:none;min-height:var(--alvo-toque);
  padding:.7em 1.2em .7em calc(1.2em + var(--tracking-caps-sm));
  border:var(--border) solid currentColor;border-radius:var(--r-pill);
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-sm);
  text-transform:uppercase;
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease)}
.cesta__calc:hover{background:var(--bg-invert);color:var(--fg-invert)}
.cesta__resposta{margin-top:.7em;min-height:1.4em;
  font-size:var(--text-body-sm);color:var(--fg-muted)}
.cesta__resposta.is-erro{color:var(--c-lacre)}
/* estimativa de entrega (revisão de 06/10): carregando, opções, sem entrega e erro com "Tentar de novo" */
.cesta__msg{margin:0}
.cesta__resposta.is-carregando .cesta__msg::before{content:"";display:inline-block;width:.8em;height:.8em;margin-right:.5em;
  vertical-align:-.08em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;
  animation:cesta-gira .8s linear infinite}
@keyframes cesta-gira{to{transform:rotate(1turn)}}
@media (prefers-reduced-motion:reduce){.cesta__resposta.is-carregando .cesta__msg::before{animation:none;border-right-color:currentColor;opacity:.5}}
.cesta__opcoes{list-style:none;margin:0;padding:0;color:var(--fg)}
.cesta__opcao{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:var(--sp-3);align-items:baseline;
  padding:.55em 0;border-bottom:var(--border) solid var(--line)}
.cesta__opcao:first-child{padding-top:0}
.cesta__op-nome{font-weight:600;overflow-wrap:anywhere}
.cesta__op-prazo{grid-column:1;color:var(--fg-muted);font-size:var(--text-caption)}
.cesta__op-preco{grid-column:2;grid-row:1 / span 2;align-self:center;font-variant-numeric:tabular-nums;white-space:nowrap}
.cesta__nota{margin:.6em 0 0;font-size:var(--text-caption);color:var(--fg-muted)}
.cesta__repetir{margin-top:.5em;min-height:var(--alvo-toque);padding:.5em 1.1em;
  border:var(--border) solid currentColor;border-radius:var(--r-pill);color:var(--fg);
  font-family:var(--font-body);font-size:var(--text-body-sm);cursor:pointer}
.cesta__repetir:hover{background:var(--bg-invert);color:var(--fg-invert)}
.cesta__entrar{display:inline-flex;align-items:center;min-height:var(--alvo-toque);margin-top:.3em;color:var(--fg);
  text-decoration:underline;text-underline-offset:.2em}

.cesta__soma{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;
  gap:var(--sp-4);margin-top:var(--sp-5);padding-top:var(--sp-4);
  border-top:var(--border) solid var(--line)}
.cesta__soma span{font-family:var(--font-badge);
  font-variation-settings:var(--vf-badge-sm);font-size:var(--text-caption);
  letter-spacing:var(--tracking-caps-sm);text-transform:uppercase;color:var(--fg-muted)}
.cesta__soma strong{font-size:var(--text-price);
  font-variation-settings:var(--vf-body-price);font-variant-numeric:tabular-nums}

.cesta__ir{display:flex;align-items:center;justify-content:center;
  width:100%;min-height:var(--alvo-toque);margin-top:var(--sp-4);
  padding:1em 1.6em 1em calc(1.6em + var(--tracking-caps-md));line-height:1.2;
  background:var(--bg-invert);color:var(--fg-invert);border-radius:var(--r-pill);
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  text-transform:uppercase;
  transition:background var(--dur-base) var(--ease),color var(--dur-base) var(--ease)}
.cesta__ir:hover{background:var(--accent);color:var(--fg-on-accent)}

/* No celular a gaveta toma a tela toda: 27rem em 375px deixaria uma faixa de
   16px do site atrás, que não mostra nada e ainda convida a um toque perdido. */
@media(max-width:520px){
  .cesta__painel{width:100%}
  .cesta__item{grid-template-columns:4rem 1fr}
}

/* --------------------------------------------------------------------------
   FECHAR COMPRA — checkout.html

   Cabeçalho curto e sem navegação: numa página de fechamento cada link é uma
   porta de saída. Fica só o de volta, que é honesto ter.

   Duas colunas no desktop com o resumo grudado, uma coluna no celular com o
   resumo EM CIMA. No celular o resumo embaixo obrigaria a rolar o formulário
   inteiro para conferir o que se está comprando — e é justamente antes de
   digitar o endereço que essa dúvida aparece.
   -------------------------------------------------------------------------- */
.ck-hdr{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;
  gap:var(--sp-3);padding:.6rem var(--gutter);
  border-bottom:var(--border) solid var(--line);background:var(--bg)}
.ck-hdr__voltar{display:inline-flex;align-items:center;gap:.6em;justify-self:start;
  min-height:var(--alvo-toque);
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  text-transform:uppercase;transition:opacity var(--dur-fast) var(--ease)}
.ck-hdr__voltar:hover{opacity:.6}
.ck-hdr__logo{justify-self:center;display:block;line-height:0}
.ck-hdr__logo img{display:block;height:4rem;width:auto}
/* no celular, o mesmo logo menor do cabeçalho da loja (.hdr__logo) */
@media(max-width:820px){.ck-hdr__logo img{height:3rem}}
@media(max-width:480px){
  .ck-hdr__logo img{height:2.5rem}
  .ck-hdr__voltar span{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap} /* fora da vista, não da leitura: é o nome do link */
  .ck-hdr__voltar{inline-size:var(--alvo-toque);justify-content:center;
    margin-inline-start:calc(-1 * min(var(--sp-3),var(--gutter)))}
}
.ck-hdr__selo{justify-self:end;font-family:var(--font-badge);
  font-variation-settings:var(--vf-badge-sm);font-size:var(--text-micro);
  letter-spacing:var(--tracking-caps-sm);padding-left:var(--tracking-caps-sm);
  text-transform:uppercase;color:var(--fg-muted)}
@media(max-width:600px){.ck-hdr__selo{display:none}}

.ck{padding-block:clamp(2rem,6vh,4rem) clamp(3rem,8vh,6rem)}
.ck__grade{display:grid;gap:clamp(2.5rem,6vw,4rem)}
@media(min-width:900px){
  .ck__grade{grid-template-columns:1fr 22rem;align-items:start}
  .ck__form{order:1}
  /* Grudado, mas com teto: com 8 pecas o resumo passava de 1100px numa tela
     de 900 e o TOTAL — a unica linha que a pessoa quer ver enquanto digita —
     ficava permanentemente fora do corte. Quem rola e a lista; as contas
     ficam ancoradas no pe do cartao. Com 5 pecas isso nunca aparecia.

     O teto desconta 8rem e nao 2x --sp-5 porque precisa valer nos DOIS
     estados: preso no topo (a 24px) e solto na rolagem 0, onde o cartao
     comeca ~97px abaixo por causa da barra. Com o teto justo ficava certo
     preso e cortado 49px antes de rolar — e antes de rolar e exatamente
     quando a pessoa procura o total. */
  .ck__resumo{order:2;position:sticky;top:var(--sp-5);
    display:flex;flex-direction:column;
    max-height:calc(100svh - 8rem)}
  .ck__itens{overflow-y:auto;min-height:0;overscroll-behavior:contain}
  .ck__contas{flex:none}
}

.ck__h1{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h2);
  font-size:clamp(1.75rem,5vw,2.5rem);line-height:1.05;margin-bottom:var(--sp-6)}

.ck__bloco{padding-block:var(--sp-6);border-top:var(--border) solid var(--line)}
.ck__bloco:first-of-type{border-top:0;padding-top:0}
/* Sem sessão, o botão "Entrar ou criar conta" vem logo antes da entrega local, que é o primeiro
   bloco e por isso perdia o fio e o respiro de cima: o título encostava no botão (~7px). Aqui o
   bloco volta ao ritmo dos outros (respiro, fio, respiro). Vem depois da regra acima de propósito. */
.ck__acesso + .ck__bloco{margin-top:var(--sp-6);padding-top:var(--sp-6);border-top:var(--border) solid var(--line)}
.ck__h2{display:flex;align-items:center;gap:.7em;
  font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h3);font-size:1.25rem;
  margin-bottom:var(--sp-5)}
/* Numerar AQUI é o contrário de numerar as seções da home: ali a numeração
   prometia um percurso que a página não cumpria; aqui o percurso existe de
   verdade, tem ordem obrigatória e a pessoa quer saber onde está nele. */
.ck__n{display:grid;place-items:center;inline-size:1.6em;block-size:1.6em;
  border-radius:var(--r-circle);background:var(--bg-invert);color:var(--fg-invert);
  font-family:var(--font-body);font-size:.62em;
  font-variation-settings:var(--vf-body-price);flex:none;
  /* line-height:1: herdado (1.7), a caixa de linha ficava maior que o círculo e o
     algarismo assentava 1px abaixo do centro (5% do diâmetro). Com 1: 0,05px
     (Commissioner) e 0,13px (fonte reserva). O mesmo motivo do .hdr__bag-n. */
  line-height:1}

.ck__campo{margin-bottom:var(--sp-4)}
.ck__campo label{display:block;margin-bottom:.45em;
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-micro);letter-spacing:var(--tracking-caps-sm);
  padding-left:var(--tracking-caps-sm);text-transform:uppercase;color:var(--fg-muted)}
.ck__opt{text-transform:none;letter-spacing:0;opacity:.7}
.ck__campo input,.ck__campo select{
  inline-size:100%;min-height:var(--alvo-toque);
  padding:.7em 1.1em;background:var(--bg);color:var(--fg);
  border:var(--border) solid var(--line);border-radius:var(--r-md);
  font-family:var(--font-body);font-size:var(--text-body);
  transition:border-color var(--dur-fast) var(--ease)}
.ck__campo input:focus-visible,.ck__campo select:focus-visible{border-color:var(--accent)}
.ck__campo input.is-erro,.ck__campo select.is-erro{border-color:var(--c-lacre)}
.ck__erro{min-height:0;margin-top:.35em;font-size:var(--text-body-sm);color:var(--c-lacre)}
.ck__erro:empty{margin-top:0}

.ck__par{display:grid;gap:0 var(--sp-4)}
@media(min-width:560px){
  .ck__par{grid-template-columns:1fr 1fr}
  /* CEP e numero sao campos de formato curto: um 1fr faria uma caixa de 500px
     para 8 digitos, e caixa larga demais sugere que cabe mais coisa nela */
  .ck__par--cep{grid-template-columns:11rem 8rem;justify-content:start}
  .ck__par--cidade{grid-template-columns:1fr 6rem}
}

.ck__escolhas{display:grid;gap:var(--sp-2)}
.ck__escolhas.is-erro{outline:var(--border) solid var(--c-lacre);
  outline-offset:var(--sp-2);border-radius:var(--r-md)}
.ck__escolha{display:grid;grid-template-columns:auto 1fr auto;
  align-items:center;gap:var(--sp-3);
  min-height:var(--alvo-toque);padding:var(--sp-3) var(--sp-4);
  border:var(--border) solid var(--line);border-radius:var(--r-md);
  cursor:pointer;transition:border-color var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease)}
.ck__escolha:hover{border-color:var(--fg-muted)}
.ck__escolha:has(input:checked){border-color:var(--fg);background:var(--bg-surface)}
.ck__escolha:has(input:focus-visible){outline:2px solid var(--accent);outline-offset:2px}
.ck__escolha input{inline-size:1.15rem;block-size:1.15rem;
  accent-color:var(--accent);margin:0;flex:none}
.ck__escolha-n{display:block}
.ck__escolha-d{display:block;font-size:var(--text-body-sm);color:var(--fg-muted)}
.ck__escolha-v{font-variation-settings:var(--vf-body-price);
  font-variant-numeric:tabular-nums;white-space:nowrap}

.ck__nota{margin-top:var(--sp-3);font-size:var(--text-body-sm);color:var(--fg-muted)}

.ck__enviar{display:flex;align-items:center;justify-content:center;
  inline-size:100%;min-height:var(--alvo-toque);margin-top:var(--sp-6);
  padding:1.05em 1.6em 1.05em calc(1.6em + var(--tracking-caps-md));line-height:1.2;
  background:var(--bg-invert);color:var(--fg-invert);border-radius:var(--r-pill);
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  text-transform:uppercase;
  transition:background var(--dur-base) var(--ease),color var(--dur-base) var(--ease)}
.ck__enviar:hover:not(:disabled){background:var(--accent);color:var(--fg-on-accent)}
.ck__enviar:disabled{opacity:1;background:var(--bg-surface);color:var(--fg-muted);
  cursor:default}
.ck__saida{margin-top:var(--sp-4);font-size:var(--text-body-sm);color:var(--fg-muted)}
.ck__saida.is-erro{color:var(--c-lacre)}

/* estado do pagamento (campo `payment` do backend): mesma caixa das escolhas */
.ck__estado{margin-top:var(--sp-5);padding:var(--sp-4);
  border:var(--border) solid var(--line);border-radius:var(--r-md);background:var(--bg-surface)}
.ck__estado[hidden]{display:none}
.ck__estado-t{margin:0;font-size:var(--text-body)}
.ck__estado--erro .ck__estado-t{color:var(--c-lacre)}
.ck__estado--ok .ck__estado-t{color:var(--c-verde)}
.ck__estado-d{margin:var(--sp-2) 0 0;font-size:var(--text-body-sm);color:var(--fg-muted)}
.ck__estado-r{margin:var(--sp-3) 0 0;font-size:var(--text-body-sm);color:var(--fg-muted);
  font-variant-numeric:tabular-nums}
.ck__estado .ck__enviar{margin-top:var(--sp-4);text-decoration:none}

/* ---- resumo ---- */
.ck__resumo{padding:var(--sp-5);background:var(--bg-surface);border-radius:var(--r-md)}
.ck__h2--resumo{font-size:1.125rem;margin-bottom:var(--sp-4)}
.ck__item{display:grid;grid-template-columns:3.25rem 1fr auto;gap:var(--sp-3);
  align-items:start;padding-block:var(--sp-3);
  border-bottom:var(--border) solid var(--line)}
.ck__item:last-child{border-bottom:0}
.ck__item img{inline-size:100%;aspect-ratio:4/5;object-fit:cover;
  border-radius:var(--r-sm);background:var(--bg)}
.ck__item-n{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h3);font-size:1rem;line-height:1.2}
.ck__item-u{margin-top:.25em;font-family:var(--font-badge);
  font-variation-settings:var(--vf-badge-sm);font-size:var(--text-micro);
  letter-spacing:var(--tracking-caps-sm);text-transform:uppercase;color:var(--fg-muted)}
.ck__item-p{font-variation-settings:var(--vf-body-price);
  font-variant-numeric:tabular-nums;white-space:nowrap}

.ck__vazio{display:flex;flex-direction:column;align-items:flex-start;gap:var(--sp-4)}
.ck__vazio p{color:var(--fg-muted)}

.ck__contas{margin-top:var(--sp-4);padding-top:var(--sp-4);
  border-top:var(--border) solid var(--line)}
.ck__contas > div{display:flex;align-items:baseline;justify-content:space-between;
  gap:var(--sp-4);margin-bottom:.5em}
.ck__contas dt{font-family:var(--font-badge);
  font-variation-settings:var(--vf-badge-sm);font-size:var(--text-caption);
  letter-spacing:var(--tracking-caps-sm);text-transform:uppercase;color:var(--fg-muted)}
.ck__contas dd{margin:0;font-variant-numeric:tabular-nums}
.ck__contas-total{margin-top:var(--sp-3);padding-top:var(--sp-3);
  border-top:var(--border) solid var(--line)}
.ck__contas-total dt{color:var(--fg)}
.ck__contas-total dd{font-size:var(--text-price);
  font-variation-settings:var(--vf-body-price)}

.ck-ft{padding:var(--sp-6) var(--gutter);text-align:center;
  border-top:var(--border) solid var(--line)}
.ck-ft p{font-size:var(--text-body-sm);color:var(--fg-muted)}
/* links de ajuda do rodapé do checkout: no corpo e na cor da linha legal (como o "Cookies"), alvo de 44 px */
.ck-ft__links{display:flex;flex-wrap:wrap;justify-content:center;gap:0 1.2em;margin-top:.4em;font-size:var(--text-caption)}
.ck-ft__links a{display:inline-flex;align-items:center;min-height:var(--alvo-toque);color:var(--fg-muted);text-decoration:underline;text-underline-offset:.2em}
.ck-ft__links a:hover{color:var(--fg)}

/* No celular o resumo sobe: conferir o que se compra é a dúvida que aparece
   ANTES de digitar endereço, não depois. */
@media(max-width:899px){
  .ck__form{order:2}
  .ck__resumo{order:1}
}

/* --------------------------------------------------------------------------
   O CARD INTEIRO ABRE A PEÇA

   Sem tocar no markup dos 17 cards: o link do nome estica uma camada
   invisível sobre o card todo. É o padrão de "link esticado", e resolve dois
   problemas de uma vez — a foto passa a ser clicável, que é onde o dedo vai
   primeiro, e o alvo deixa de ser o nome (23px de altura) para ser o card.

   Por isso o padding de toque que o nome tinha some daqui: ele existia para
   levar um link de 23px ao piso de 44, e agora o alvo é o card inteiro.

   O "+" precisa de camada própria por cima, senão o card engole o clique
   dele — e ele é o único botão da grade.
   -------------------------------------------------------------------------- */
.shop-card{position:relative}
.shop-card__title a::after{content:"";position:absolute;inset:0;z-index:1}
.shop-card__add{position:relative;z-index:2}

/* --------------------------------------------------------------------------
   TROCA DE PÁGINA — fade, e a foto viaja

   `navigation:auto` faz o navegador tirar uma chapa da página que sai e outra
   da que entra e cruzar as duas. Não é JS: é o compositor, então não trava
   com a página ocupada carregando.

   E como a caixa da foto tem o MESMO nome de transição nos dois documentos, o
   navegador para de cruzar aquele pedaço e o MORFA: a foto do card cresce até
   virar a vitrine da peça. As duas caixas são 4:5, então o morfismo não
   distorce nada.

   O nome é posto no clique, num card só — nome de transição tem que ser
   único no documento, e a loja tem dezessete.

   Onde não houver suporte, a navegação acontece do jeito de sempre. Nada
   depende disto para funcionar.
   -------------------------------------------------------------------------- */
@view-transition{navigation:auto}
/* 07/10 (rodada no celular): a foto morfava inteira enquanto a página que saía e a que entrava desbotavam AO
   MESMO TEMPO; no meio, foto cheia sobre uma página pela metade (abrir: a foto "chegava antes"; fechar: a ficha
   sumia e a foto ficava sozinha). Agora a página que sai fica INTEIRA por baixo e a nova surge por cima, no
   mesmo tempo e na mesma curva da foto: nunca há foto sem página em volta. */
::view-transition-group(peca){animation-duration:var(--dur-base);animation-timing-function:var(--ease-menu)}
::view-transition-old(root){animation:none}
/* a entrada é uma animação NOSSA (só opacidade): a do navegador traz junto a soma das camadas (plus-lighter),
   que com a de baixo inteira estoura a tela para branco no meio da troca */
::view-transition-new(root){animation:mdm-vt-entra var(--dur-base) var(--ease-menu) both;mix-blend-mode:normal}
@keyframes mdm-vt-entra{from{opacity:0}to{opacity:1}}
/* a foto não deve piscar durante o morfismo: só a caixa se move */
::view-transition-old(peca),::view-transition-new(peca){
  animation:none;mix-blend-mode:normal;height:100%;overflow:clip}

.pdp__vitrine{view-transition-name:peca}

@media(prefers-reduced-motion:reduce){
  @view-transition{navigation:none}
}

/* --------------------------------------------------------------------------
   FECHAR A PEÇA

   A PDP passa a se comportar como camada sobre a loja: entra em fade com a
   foto morfando, e sai por um × no canto. Quem está comparando dezessete
   peças únicas abre e fecha muitas vezes — o custo de cada ida e volta é o
   que decide se a pessoa vê três peças ou dez.

   Fica ACIMA do header (que é sticky) porque é o controle da camada, não da
   navegação — e porque no celular a barra some ao rolar, e o × não pode sumir
   junto: a saída tem que estar sempre no mesmo lugar.

   Fundo próprio e não só o ícone: ele pousa ora sobre foto clara, ora sobre o
   campo desfocado, que muda de cor a cada peça. Ícone solto some num dos dois
   climas — e um botão de sair que some é o pior lugar para economizar.
   -------------------------------------------------------------------------- */
.pdp{position:relative}
.pdp__fechar{
  position:fixed;z-index:calc(var(--z-header) + 5);
  inset-block-start:calc(var(--h-header) + var(--sp-3));
  inset-inline-end:var(--gutter);
  display:grid;place-items:center;
  inline-size:var(--alvo-toque);block-size:var(--alvo-toque);
  border-radius:var(--r-circle);
  background:var(--bg);color:var(--fg);
  box-shadow:0 2px 12px color-mix(in srgb, var(--c-azul-profundo) 16%, transparent);
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease),
             transform var(--dur-fast) var(--ease);
}
.pdp__fechar:hover{background:var(--bg-invert);color:var(--fg-invert)}
.pdp__fechar:active{transform:scale(.94)}
/* no celular a barra do topo tem 66px, não 84,2 — o token é a régua do
   desktop e aqui deixaria o × flutuando longe demais do canto */
@media(max-width:820px){
  .pdp__fechar{inset-block-start:calc(4.2rem + var(--sp-2))}
}

/* --------------------------------------------------------------------------
   A MARÉ — modal de newsletter

   Referência: split de foto + formulário (Oishii). Abre pelo QUERO SABER do
   CTA da loja; sem JS o mesmo botão continua levando ao formulário do rodapé
   (href="#newsForm"), então nada depende do modal existir.

   O argumento do cadastro é o produto: peça única esgota no dia, quem assina
   fica sabendo antes — e leva 5% na primeira compra. Os 5% são AUTOMAÇÃO da
   ferramenta de e-mail (cupom no boas-vindas), não código do site: aqui só
   se promete o que a ferramenta vai cumprir.
   -------------------------------------------------------------------------- */
.news{position:fixed;inset:0;z-index:calc(var(--z-header) + 30);
  display:grid;place-items:center;padding:var(--gutter)}
.news[hidden]{display:none}
.news__veu{position:absolute;inset:0;
  background:color-mix(in srgb, var(--c-azul-profundo) 42%, transparent);
  opacity:0;transition:opacity var(--dur-base) var(--ease-menu)}
.news.is-open .news__veu{opacity:1}

/* mesma --ease-menu das outras chapas grandes; a expo-out da marca é para
   card pequeno, e chapa do tamanho da tela chega batendo */
.news__painel{position:relative;display:grid;overflow:hidden;
  width:min(52rem, 100%);max-height:calc(100svh - var(--sp-6));
  background:var(--bg);color:var(--fg);
  border-radius:var(--r-md);box-shadow:var(--shadow-toast);
  opacity:0;transform:translateY(14px);
  transition:opacity var(--dur-base) var(--ease-menu),
             transform var(--dur-base) var(--ease-menu)}
.news.is-open .news__painel{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){.news__veu,.news__painel{transition:none}}
@media(min-width:700px){.news__painel{grid-template-columns:1fr 1.15fr}}

.news__x{position:absolute;z-index:2;inset-block-start:var(--sp-2);
  inset-inline-end:var(--sp-2);display:grid;place-items:center;
  inline-size:var(--alvo-toque);block-size:var(--alvo-toque);
  border-radius:var(--r-circle);background:var(--bg);color:var(--fg);
  box-shadow:0 2px 12px color-mix(in srgb, var(--c-azul-profundo) 16%, transparent);
  transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease)}
.news__x:hover{background:var(--bg-invert);color:var(--fg-invert)}

/* a foto: coluna cheia no largo, faixa curta no empilhado. No largo o img é
   absoluto dentro da célula — é o que deixa a ALTURA do painel ser ditada
   pelo formulário, com a foto acompanhando sem esticar a caixa. */
.news__foto{background:var(--bg-surface)}
.news__foto img{width:100%;height:100%;object-fit:cover;display:block}
@media(min-width:700px){
  .news__foto{position:relative}
  .news__foto img{position:absolute;inset:0}
}
@media(max-width:699px){
  .news__foto{height:clamp(120px, 24svh, 210px)}
}

.news__corpo{padding:clamp(1.5rem, 4.5vw, 2.75rem);overflow-y:auto;min-height:0;
  overscroll-behavior:contain}
.news__olho{font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  padding-left:var(--tracking-caps-md);text-transform:uppercase;
  color:var(--fg-muted);margin-bottom:1em}
.news__tit{font-family:var(--font-display);font-optical-sizing:none;
  font-variation-settings:var(--vf-display-h2);
  font-size:clamp(1.6rem, 4.6vw, 2.1rem);line-height:1.08;margin-bottom:.5em}
.news__sub{color:var(--fg-muted);margin-bottom:var(--sp-5);max-width:34ch}
.news__sub strong{color:var(--fg);font-variation-settings:var(--vf-body-bold);
  font-weight:400}

.news__campo{margin-bottom:var(--sp-4)}
.news__campo label{display:block;margin-bottom:.45em;
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-micro);letter-spacing:var(--tracking-caps-sm);
  padding-left:var(--tracking-caps-sm);text-transform:uppercase;
  color:var(--fg-muted)}
.news__opt{text-transform:none;letter-spacing:0;opacity:.7}
.news__campo input{inline-size:100%;min-height:var(--alvo-toque);
  padding:.7em 1.1em;background:var(--bg);color:var(--fg);
  border:var(--border) solid var(--line);border-radius:var(--r-md);
  font-family:var(--font-body);font-size:var(--text-body);
  transition:border-color var(--dur-fast) var(--ease)}
.news__campo input:focus-visible{border-color:var(--accent)}

.news__ir{display:flex;align-items:center;justify-content:center;
  inline-size:100%;min-height:var(--alvo-toque);margin-top:var(--sp-2);
  padding:1em 1.6em 1em calc(1.6em + var(--tracking-caps-md));line-height:1.2;
  background:var(--bg-invert);color:var(--fg-invert);border-radius:var(--r-pill);
  font-family:var(--font-badge);font-variation-settings:var(--vf-badge-sm);
  font-size:var(--text-caption);letter-spacing:var(--tracking-caps-md);
  text-transform:uppercase;
  transition:background var(--dur-base) var(--ease),color var(--dur-base) var(--ease)}
.news__ir:hover{background:var(--accent);color:var(--fg-on-accent)}

.news__status{margin-top:var(--sp-3);min-height:1.4em;
  font-size:var(--text-body-sm);color:var(--fg-muted)}
.news__status.is-erro{color:var(--c-lacre)}
.news__fino{margin-top:var(--sp-4);font-size:var(--text-caption);
  color:var(--fg-muted)}

/* R-5: texto ampliado pode ocupar mais de uma linha, sem empurrar a loja para fora da tela. */
.shop-sort{min-width:0;max-width:100%;flex-wrap:wrap}
/* A48 (Dev 2, 14/10): sem 'flex:1 1 12rem' — com ele o 'Ordenar' quebrava em duas linhas com texto NORMAL */
.shop-sort select{min-width:0;max-width:100%}
@media(max-width:480px){
 .hdr{grid-template-columns:minmax(0,1fr) auto minmax(0,1fr)}
 .hdr__logo img{height:40px;max-width:24vw;object-fit:contain}
 .hdr__nav{min-width:0;max-width:100%;justify-self:stretch;justify-content:flex-end;flex-wrap:wrap}
 .hdr__nav .hdr__link[data-conta="cabecalho"],.hdr__nav .conta-menu{min-width:0;max-width:100%;overflow-wrap:anywhere;white-space:normal}
 /* A48 P2 (14/10): com a linha quebrada (texto 200%) a cesta fica no alto e a margem negativa (.75rem) passava o
    respiro da barra (.6rem) — 5 px cortados no topo. Limitada ao respiro, ela encosta na borda e para ali. */
 .hdr__nav .hdr__cesta{margin-block:-.6rem}
}

@media(max-width:480px){
 .ft__top{grid-template-columns:minmax(0,1fr)}
 .ft__top>*{min-width:0}
 .ft__news-h,.ft__ethos{overflow-wrap:anywhere}
 .ft__input{max-width:100%}
}

@media(max-width:480px){.ft__col a{max-width:100%;overflow-wrap:anywhere}}
/* SP-2: ajuda visível desde o início, junto ao campo de criação ou troca. */
#c-senha-ajuda,#n-senha-ajuda{font-size:.875rem;line-height:1.6;max-width:62ch;margin-top:.5rem;overflow-wrap:anywhere;color:var(--fg)}

/* Acesso: caminho de atendimento permanente, sem recuperação automática. */
.auth-support{font-size:1rem;line-height:1.6;margin:1rem 0 0;overflow-wrap:anywhere}
.auth-support a{display:inline-flex;align-items:center;min-height:44px;text-underline-offset:.2em}
.auth-support a:focus-visible{outline:3px solid currentColor;outline-offset:3px}
.conta-main .estado{grid-template-columns:minmax(0,1fr)}.conta-main .estado>*{min-width:0;max-width:100%;overflow-wrap:anywhere}.conta-main .estado__acoes .cbtn{white-space:normal;max-width:100%;overflow-wrap:anywhere}

/* Cesta e checkout: manter nome, valor e controles dentro da área com texto ampliado. */
.cesta__topo{grid-template-columns:minmax(0,auto) minmax(0,1fr) auto}
.cesta__tit,.cesta__conta{min-width:0;overflow-wrap:anywhere}
.cesta__item{grid-template-columns:min(4.75rem,30%) minmax(0,1fr)}
.cesta__item>*{min-width:0}
.cesta__nome,.cesta__brinde{overflow-wrap:anywhere}
.ck__grade>*{min-width:0}
.ck__resumo>*{min-width:0;max-width:100%}
.ck__item>div{min-width:0;overflow-wrap:anywhere}
.ck__contas>div{flex-wrap:wrap}
.ck__contas dt,.ck__contas dd{min-width:0;max-width:100%;overflow-wrap:anywhere}
@media(max-width:35.99rem){
  .cesta__x,.cesta__tirar{margin-inline-end:0}
  .ck__item{grid-template-columns:min(3.25rem,25%) minmax(0,1fr)}
  .ck__item-p{grid-column:2;justify-self:end;max-width:100%;white-space:normal;overflow-wrap:anywhere}
  .ck__escolha{grid-template-columns:auto minmax(0,1fr)}
  .ck__escolha>span{min-width:0;overflow-wrap:anywhere}
  .ck__escolha-v{grid-column:2;justify-self:end;max-width:100%;white-space:normal;overflow-wrap:anywhere}
}
