/* ============================================================================
   COFFEE BLEND — DESIGN SYSTEM · 03. COMPONENTES
   ----------------------------------------------------------------------------
   Cada componente consome só token semântico (--cb-bg, --cb-fg, --cb-btn-*).
   Consequência: trocar a classe de esquema no ancestral repinta tudo, sem
   escrever uma linha de CSS nova. É a mesma mecânica do tema de referência.

   Ordem: marquee · header · botões · selos · hero · produto · benefícios ·
          carrossel · accordion · comparativo · formulário · barra de compra ·
          rodapé.
   ============================================================================ */

/* ===========================================================================
   MARQUEE — faixa de avisos em movimento contínuo
   =========================================================================== */
.cb-marquee {
  --cb-marquee-duration: 28s;
  display: flex;
  overflow: hidden;
  user-select: none;
  padding-block: var(--cb-space-2xs);
  border-block-end: var(--cb-border-thin) solid var(--cb-line);
}

.cb-marquee__track {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--cb-space-md);
  padding-inline-end: var(--cb-space-md);
  /* min-width:100% + space-around: em telas largas os itens se distribuem em
     vez de deixar um vão no fim da trilha, e o loop de -100% segue contínuo. */
  min-width: 100%;
  justify-content: space-around;
  animation: cb-marquee-scroll var(--cb-marquee-duration) linear infinite;
}

/* A segunda cópia da trilha é aria-hidden no HTML e existe só para o loop
   não deixar buraco. */
.cb-marquee:hover .cb-marquee__track {
  animation-play-state: paused;
}

.cb-marquee__item {
  display: flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  flex-shrink: 0;
  font-size: var(--cb-text-xs);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
}

.cb-marquee__item::after {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background-color: currentColor;
  opacity: 0.55;
}

@keyframes cb-marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-100%); }
}

@media (prefers-reduced-motion: reduce) {
  .cb-marquee { overflow-x: auto; }
  .cb-marquee__track { animation: none; }
}

/* ===========================================================================
   HEADER
   Barra interna arredondada flutuando sobre uma sarjeta fina — o gesto do
   tema de referência, aqui com a barra em Amarelo Blend.
   =========================================================================== */
.cb-header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--cb-layer-header);
  padding: var(--cb-mosaic-gap);
}

.cb-header__bar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-2xs) var(--cb-space-sm);
  /* Menu e ícones caem na mesma linha vertical do conteúdo da página: a
     margem do site enquanto ela manda, e a sobra do container de 1440
     quando a tela é mais larga que ele. O `- mosaic-gap` desconta o
     respiro que o .cb-header já dá em volta da barra. */
  padding-inline: max(
    calc(var(--cb-gutter) - var(--cb-mosaic-gap)),
    calc((100% - var(--cb-width-page)) / 2)
  );
  border-radius: var(--cb-radius-sm);
  background-color: var(--cb-bg);
  color: var(--cb-fg);
  box-shadow: var(--cb-shadow-sm);
}

/* A altura da marca e a área clicável são coisas diferentes: o logo tem 30px
   de altura ótica, mas o link precisa do alvo de toque inteiro. */
.cb-header__logo {
  --cb-header-logo-height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--cb-touch-target);
}

.cb-header__logo img,
.cb-header__logo svg {
  height: var(--cb-header-logo-height);
  width: auto;
}

.cb-header__col {
  display: flex;
  align-items: center;
  gap: var(--cb-space-2xs);
}

.cb-header__col--end {
  justify-content: flex-end;
}

/* Navegação desktop */
.cb-nav {
  display: none;
  align-items: center;
  gap: var(--cb-space-md);
}

.cb-nav__link {
  position: relative;
  padding-block: var(--cb-space-3xs);
  /* Sem isto "Onde encontrar" parte em duas linhas quando a barra aperta, e a
     altura do header pula junto. */
  white-space: nowrap;
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  text-transform: uppercase;
  text-decoration: none;
}

.cb-nav__link::after {
  content: '';
  position: absolute;
  inset-block-end: 0;
  inset-inline: 0;
  height: 2px;
  background-color: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--cb-duration-base) var(--cb-ease-out);
}

.cb-nav__link:hover::after,
.cb-nav__link[aria-current='page']::after {
  transform: scaleX(1);
}

/* Botão-ícone (menu, conta, carrinho) */
.cb-icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  min-width: var(--cb-touch-target);
  min-height: var(--cb-touch-target);
  border-radius: var(--cb-radius-xs);
  color: inherit;
  text-decoration: none;
  transition: opacity var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-icon-button:hover {
  opacity: 0.7;
}

.cb-icon-button svg {
  width: var(--cb-icon-md);
  height: var(--cb-icon-md);
}

/* Contador do carrinho */
.cb-cart-count {
  position: absolute;
  inset-block-start: 4px;
  inset-inline-end: 2px;
  min-width: 18px;
  height: 18px;
  padding-inline: 4px;
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-accent);
  color: var(--cb-bg);
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-bold);
  line-height: 18px;
  text-align: center;
}

@media (min-width: 1024px) {
  .cb-header__logo { --cb-header-logo-height: 38px; }
}

/* Os três links entram só quando cabem de verdade. A 1024 eles não cabiam:
   a coluna da esquerda estourava o terço dela e empurrava o logo 43 px para
   fora do centro — a barra ficava visivelmente torta. Nada se perde nessa
   faixa porque o hambúrguer está sempre lá, com o menu inteiro. */
@media (min-width: 1200px) {
  .cb-nav { display: flex; }
}

/* --- Drawer de menu mobile ------------------------------------------------ */
.cb-drawer {
  width: min(88vw, 380px);
  max-width: none;
  height: 100dvh;
  max-height: none;
  margin: 0 0 0 auto;
  padding: 0;
  border: 0;
  background-color: var(--cb-bg);
  color: var(--cb-fg);
}

.cb-drawer::backdrop {
  background-color: rgb(36 18 9 / 0.5);
}

.cb-drawer__inner {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-lg);
  height: 100%;
  padding: var(--cb-space-md);
  overflow-y: auto;
}

.cb-drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-sm);
}

.cb-drawer__list {
  display: flex;
  flex-direction: column;
  list-style: none;
  padding: 0;
  margin: 0;
}

.cb-drawer__link {
  display: block;
  padding-block: var(--cb-space-xs);
  border-block-end: var(--cb-border-thin) solid var(--cb-line);
  font-size: var(--cb-text-h4);
  font-weight: var(--cb-weight-bold);
  text-decoration: none;
}

.cb-drawer__foot {
  margin-block-start: auto;
}

/* ===========================================================================
   BOTÕES
   Primário = pílula com o gradiente café da marca.
   Secundário = pílula vazada.

   Todo rótulo vai dentro de `.cb-button__label`:

     <button class="cb-button"><span class="cb-button__label">Comprar</span></button>

   Não é capricho. Os estados de ocupado e concluído precisam esconder o
   rótulo e desenhar por cima; sem um elemento para segurar o texto, o JS
   teria de reescrever `textContent` — que era o que apagava o ícone SVG.
   Com a camada, o botão nunca perde o conteúdo original e volta ao normal
   sozinho.
   =========================================================================== */
.cb-button {
  --cb-button-done: 'Adicionado';
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--cb-space-2xs);
  min-height: var(--cb-touch-target);
  padding: var(--cb-space-xs) var(--cb-space-lg);
  border: var(--cb-border-thin) solid var(--cb-btn-border);
  border-radius: var(--cb-radius-pill);
  background: var(--cb-btn-bg);
  color: var(--cb-btn-fg);
  font-family: var(--cb-font-brand);
  font-size: var(--cb-text-body);
  font-weight: var(--cb-weight-bold);
  line-height: 1.2;
  letter-spacing: var(--cb-tracking-body);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    background var(--cb-duration-base) var(--cb-ease-out),
    color var(--cb-duration-base) var(--cb-ease-out),
    border-color var(--cb-duration-base) var(--cb-ease-out),
    box-shadow var(--cb-duration-base) var(--cb-ease-out),
    transform var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-button__label {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  transition: opacity var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-button:hover {
  background: var(--cb-btn-bg-hover);
  color: var(--cb-btn-fg-hover);
  border-color: var(--cb-btn-border-hover);
  box-shadow: var(--cb-shadow-button);
}

/* Afunda em vez de saltar: o botão responde ao dedo como uma tecla. */
.cb-button:active {
  transform: translateY(1px) scale(0.99);
  box-shadow: none;
}

.cb-button[disabled],
.cb-button[aria-disabled='true'] {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

/* LINK-BOTÃO DESLIGADO ("Em breve").

   Não é o botão de sempre esmaecido: é outra peça, clara e tracejada, para
   ler de longe que ali ainda não se compra. Esmaecer o degradê marrom
   deixava o rótulo ilegível — e no WordPress pior ainda, porque o tema
   carrega `a:not([href]):not([tabindex]) { color: inherit }`, que escurecia
   a letra sobre o marrom. Este seletor pesa o mesmo que o do tema e vem
   depois, então a cor daqui vale.

   <a> não tem o `disabled` do <button>: sem href ele já não leva a lugar
   nenhum, e o pointer-events tira o hover e o cursor de link. */
a.cb-button[aria-disabled='true'] {
  pointer-events: none;
  opacity: 1;
  border: var(--cb-border-thin) dashed rgb(var(--cb-fg-rgb) / 0.4);
  background: rgb(var(--cb-fg-rgb) / 0.06);
  color: var(--cb-fg-muted);
  box-shadow: none;
}

a.cb-button[aria-disabled='true'] .cb-button__pip {
  display: none;
}

/* --- Estado: ocupado ------------------------------------------------------
   Marcar com data-state="loading" e aria-busy="true". O clique é bloqueado
   no CSS, não só no JS — se o JS demorar, o duplo clique não passa. */
.cb-button[data-state='loading'] {
  cursor: progress;
  pointer-events: none;
}

.cb-button[data-state='loading'] .cb-button__label,
.cb-button[data-state='done'] .cb-button__label {
  opacity: 0;
}

.cb-button::after {
  content: '';
  position: absolute;
  inset: 0;
  width: 1.15em;
  height: 1.15em;
  margin: auto;
  border: 2px solid currentColor;
  border-block-start-color: transparent;
  border-radius: 50%;
  opacity: 0;
}

.cb-button[data-state='loading']::after {
  opacity: 1;
  animation: cb-spin 0.6s linear infinite;
}

/* --- Estado: concluído ----------------------------------------------------
   O texto sai da custom property, então dá para variar por contexto:
   `style="--cb-button-done: 'No carrinho'"`. */
.cb-button[data-state='done'] {
  pointer-events: none;
}

.cb-button[data-state='done']::before {
  content: '✓  ' var(--cb-button-done);
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  animation: cb-pop var(--cb-duration-base) var(--cb-ease-bounce);
}

@keyframes cb-spin {
  to { transform: rotate(360deg); }
}

@keyframes cb-pop {
  from { opacity: 0; transform: scale(0.9); }
  to { opacity: 1; transform: scale(1); }
}

.cb-button--secondary {
  border-color: var(--cb-btn2-border);
  background: var(--cb-btn2-bg);
  color: var(--cb-btn2-fg);
}

.cb-button--secondary:hover {
  background: var(--cb-btn2-bg-hover);
  color: var(--cb-btn2-fg-hover);
  border-color: var(--cb-btn2-border-hover);
}

.cb-button--ghost {
  border-color: transparent;
  background: transparent;
  color: var(--cb-fg);
  padding-inline: var(--cb-space-xs);
}

.cb-button--ghost:hover {
  background: rgb(var(--cb-fg-rgb) / 0.08);
  color: var(--cb-fg);
  border-color: transparent;
}

.cb-button--lg {
  min-height: 56px;
  padding: var(--cb-space-sm) var(--cb-space-xl);
  font-size: clamp(1rem, 0.93rem + 0.32vw, 1.125rem);
}

.cb-button--sm {
  min-height: 38px;
  padding: var(--cb-space-3xs) var(--cb-space-sm);
  font-size: var(--cb-text-sm);
}

.cb-button--block {
  display: flex;
  width: 100%;
}

/* Quadrado, só ícone — usado no stepper e nas ações de linha do carrinho. */
.cb-button--icon {
  width: var(--cb-touch-target);
  min-width: var(--cb-touch-target);
  padding: 0;
}

/* --- Pílula com pastilha ---------------------------------------------------
   A assinatura de botão da referência: rótulo à esquerda e a seta dentro de
   um disco escuro encaixado na ponta. O disco carrega a direção, então o
   rótulo não precisa de "→" nem de "saiba mais" — fica só o verbo.

   O recuo à direita é menor que o da esquerda de propósito: o disco já
   ocupa a margem óptica daquele lado.
--------------------------------------------------------------------------- */
.cb-button--pip {
  padding-inline-end: 5px;
  gap: var(--cb-space-xs);
}

.cb-button__pip {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background-color: var(--cb-btn-fg);
  color: var(--cb-btn-bg-solid, var(--cb-bg));
  flex-shrink: 0;
  transition:
    transform var(--cb-duration-base) var(--cb-ease-bounce),
    background-color var(--cb-duration-base) var(--cb-ease-out);
}

.cb-button__pip svg {
  width: 16px;
  height: 16px;
}

.cb-button--pip:hover .cb-button__pip {
  transform: translateX(2px);
}

/* A pastilha some junto com o rótulo nos estados de ocupado e concluído. */
.cb-button[data-state='loading'] .cb-button__pip,
.cb-button[data-state='done'] .cb-button__pip {
  opacity: 0;
}

.cb-button--lg .cb-button__pip {
  width: 40px;
  height: 40px;
}

.cb-button--lg.cb-button--pip {
  padding-inline-end: 8px;
}

.cb-button__icon {
  flex-shrink: 0;
  width: var(--cb-icon-sm);
  height: var(--cb-icon-sm);
}

/* ===========================================================================
   SELOS E PÍLULAS
   =========================================================================== */
.cb-pill-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-2xs);
}

.cb-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-3xs);
  padding: var(--cb-space-3xs) var(--cb-space-sm);
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-yellow-500);
  color: var(--cb-coffee-600);
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
  line-height: 1.4;
  white-space: nowrap;
}

.cb-pill--outline {
  background-color: transparent;
  border: var(--cb-border-thin) solid currentColor;
  color: var(--cb-fg);
}

/* Selo de canto — o "Mais Vendido" preso no topo do cartão. */
.cb-badge {
  display: inline-flex;
  align-items: center;
  padding: var(--cb-space-3xs) var(--cb-space-xs);
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-coffee-600);
  color: var(--cb-cream-200);
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  text-transform: uppercase;
  line-height: 1.4;
}

.cb-badge--accent {
  background-color: var(--cb-yellow-500);
  color: var(--cb-coffee-600);
}

.cb-badge--danger {
  background-color: var(--cb-danger);
  color: var(--cb-white);
}

/* Etiqueta de canto viva — o retângulo de canto arredondado do card
   econômico da UI V2. */
.cb-corner-tag {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  padding: 6px 18px 7px 14px;
  border-end-end-radius: 2rem;
  background-color: var(--cb-coffee-500);
  color: var(--cb-white);
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-bold);
  line-height: 1.2;
}

/* ===========================================================================
   HERO
   Imagem sangrando + conteúdo ancorado embaixo. Mobile: a imagem ocupa a
   parte de cima e o texto senta sobre uma base sólida.
   =========================================================================== */
.cb-hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 78svh;
  border-radius: var(--cb-radius-sm);
  overflow: hidden;
  isolation: isolate;
}

.cb-hero__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.cb-hero__media img,
.cb-hero__media picture {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

/* --- Hero sobre arte clara -------------------------------------------------
   A arte oficial é bege com o produto à direita e vazio à esquerda: o texto
   entra escuro sobre claro e o scrim sai de cena. Manter a máscara aqui só
   sujaria um fundo que já foi feito para receber texto.

   No mobile a arte é vertical e o produto ocupa o topo, então o conteúdo
   desce para a base e ganha um véu claro — sem ele, o texto cairia sobre a
   parte fotografada.
--------------------------------------------------------------------------- */
.cb-hero--light {
  --cb-fg-heading: var(--cb-coffee-600);
}

/* A arte mobile põe o produto no terço de cima e deixa o resto liso, de
   propósito, para o texto entrar embaixo. Duas condições para respeitar
   esse enquadramento:

     · altura suficiente para a foto caber — sem isso o `cover` come o pote;
     · âncora no topo, para o corte (quando houver) sair do vazio de baixo,
       nunca do produto.

   Foi exatamente isso que quebrou antes: com o hero medindo só o conteúdo,
   a imagem era espremida e o pote saía cortado no topo. */
.cb-hero--light {
  /* O hero não tem a tela inteira: acima dele moram o marquee e a barra do
     topo, abaixo mora a barra de abas. Descontar essa moldura é o que
     mantém o CTA acima da dobra — a régua do hero é "o botão aparece sem
     rolar", não uma fração bonita de svh. */
  --cb-hero-chrome: 190px; /* marquee 35 + header 70 + abas 58 + respiro */
  min-height: calc(100svh - var(--cb-hero-chrome));
}

/* Conteúdo mais compacto no mobile: cada pixel economizado aqui é pixel
   devolvido para a foto do produto. */
.cb-hero--light .cb-hero__content {
  gap: var(--cb-space-2xs);
  padding-block: var(--cb-space-md) var(--cb-space-md);
}

.cb-hero--light .cb-hero__media img {
  object-position: top center;
}

/* Véu curto e só na base: garante o contraste do texto caso a arte estique
   em telas muito baixas, sem sujar o vazio que já é liso. */
.cb-hero--light .cb-hero__content {
  /* O véu precisa cobrir o BLOCO INTEIRO, não só o pé dele. Com o corte em
     30% o título ficava na parte translúcida e caía por cima do pote —
     legível na foto atual, ilegível na próxima que alguém subir pelo painel.
     Sólido até 70%, esmaecendo depois: quem lê nunca depende da foto. */
  background: linear-gradient(
    to top,
    rgb(245 234 220 / 0.97) 70%,
    rgb(245 234 220 / 0.86) 88%,
    rgb(245 234 220 / 0) 100%
  );
}

@media (min-width: 768px) {
  /* No desktop a arte é horizontal: produto à direita, vazio à esquerda.
     O texto ocupa a metade lisa e dispensa qualquer véu. */
  .cb-hero--light {
    min-height: 0;
  }

  .cb-hero--light .cb-hero__media img {
    object-position: center;
  }

  .cb-hero--light .cb-hero__content {
    background: none;
    max-width: 46%;
  }

  /* No celular o texto senta na base da foto e o `flex-end` do .cb-hero é o
     certo. Aqui a arte é horizontal e o texto mora na metade vazia: colado
     na base ele fica com um vão enorme em cima e quase nada embaixo. */
  .cb-hero--light {
    justify-content: center;
  }
}

.cb-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--cb-overlay-image);
}

.cb-hero__content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--cb-space-md);
  padding: var(--cb-space-lg) var(--cb-pad-inline) var(--cb-space-xl);
  max-width: 40rem;
}

.cb-hero__title {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-display);
  line-height: var(--cb-leading-display);
  letter-spacing: var(--cb-tracking-display);
  max-width: 18ch;
}

.cb-hero__sub {
  color: var(--cb-fg);
  font-size: clamp(1rem, 0.9rem + 0.45vw, 1.375rem);
  line-height: var(--cb-leading-snug);
  max-width: 34ch;
}

/* --- Marca d'água do hero -------------------------------------------------
   A palavra gigante atrás da cena, como na referência. Lá ela é recortada
   pelas pessoas; sem máscara de recorte, opacidade baixa entrega o mesmo
   efeito de profundidade sem exigir PNG com alfa.
   Puramente decorativa — aria-hidden no HTML.
--------------------------------------------------------------------------- */
.cb-hero__watermark {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 38%;
  z-index: -1;
  color: var(--cb-cream-200);
  font-family: var(--cb-font-heading);
  /* Uma palavra, não a marca inteira: "coffee blend" a este corpo transborda
     e chega cortada dos dois lados, virando ruído. Cortar palavra é o efeito;
     cortar a marca é acidente. */
  font-size: clamp(4rem, 15vw, 13rem);
  font-weight: var(--cb-weight-bold);
  line-height: 0.8;
  letter-spacing: -0.045em;
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0.16;
  user-select: none;
  pointer-events: none;
}

/* --- Cartão flutuante sobre a foto ---------------------------------------
   Atalho de compra direto do hero. Só no desktop: no mobile ele cobriria o
   rosto na foto e brigaria com o CTA principal, que já está logo abaixo.
--------------------------------------------------------------------------- */
.cb-float-card {
  display: none;
}

@media (min-width: 1024px) {
  .cb-float-card {
    position: absolute;
    z-index: var(--cb-layer-raised);
    display: flex;
    align-items: center;
    gap: var(--cb-space-2xs);
    width: 15rem;
    padding: var(--cb-space-2xs);
    border-radius: var(--cb-radius-md);
    background-color: rgb(var(--cb-bg-rgb) / 0.92);
    color: var(--cb-fg);
    backdrop-filter: blur(6px);
    box-shadow: var(--cb-shadow-md);
    transition: transform var(--cb-duration-base) var(--cb-ease-out);
  }

  .cb-float-card:hover {
    transform: translateY(-3px);
  }

  /* Alturas diferentes, como na referência: dois cartões na mesma linha
     leem como barra de UI; escalonados, leem como etiqueta sobre a cena.
     Ambos ficam na faixa média, longe dos rostos no topo da foto. */
  .cb-float-card--start {
    inset-block-start: 20%;
    inset-inline-start: var(--cb-space-xl);
  }

  .cb-float-card--end {
    inset-block-start: 52%;
    inset-inline-end: var(--cb-space-xl);
  }

  .cb-float-card__media {
    width: 46px;
    height: 46px;
    border-radius: var(--cb-radius-sm);
    object-fit: cover;
    flex-shrink: 0;
    background-color: rgb(var(--cb-fg-rgb) / 0.06);
  }

  .cb-float-card__text {
    min-width: 0;
    flex: 1;
  }

  .cb-float-card__name {
    display: block;
    font-size: var(--cb-text-xs);
    font-weight: var(--cb-weight-bold);
    line-height: 1.2;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .cb-float-card__price {
    display: block;
    color: var(--cb-accent);
    font-size: var(--cb-text-sm);
    font-weight: var(--cb-weight-bold);
  }

  .cb-float-card .cb-add-round {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
  }

  .cb-float-card .cb-add-round svg {
    width: 15px;
    height: 15px;
  }
}

@media (min-width: 1024px) {
  .cb-hero {
    min-height: 82svh;
  }

  /* No desktop o texto vai para a esquerda, então a máscara também: a lateral
     garante o contraste e a vertical, mais leve, fecha a base. */
  .cb-hero__scrim {
    background:
      linear-gradient(to top, rgb(36 18 9 / 0.5) 0%, rgb(36 18 9 / 0) 55%),
      var(--cb-overlay-image-side);
  }

  .cb-hero__content {
    /* Vertical igual em cima e embaixo: com 2xl/3xl o bloco ficava baixo
       mesmo depois de centralizado. */
    padding: var(--cb-space-2xl);
    gap: var(--cb-space-md);
  }
}

/* ===========================================================================
   CARTÃO DE PRODUTO (kit)
   Mídia · selo · título · preço de/por · desconto · preço unitário · CTA.
   =========================================================================== */
.cb-product-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--cb-space-md);
}

.cb-product {
  display: flex;
  flex-direction: column;
  position: relative;
  border-radius: var(--cb-radius-md);
  overflow: hidden;
  background-color: var(--cb-bg);
  color: var(--cb-fg);
  transition:
    transform var(--cb-duration-base) var(--cb-ease-out),
    box-shadow var(--cb-duration-base) var(--cb-ease-out);
}

.cb-product:hover {
  transform: translateY(-4px);
  box-shadow: var(--cb-shadow-lg);
}

/* Kit em destaque: anel de contraste em vez de mudar a cor de fundo, para
   não brigar com o esquema da seção. */
.cb-product--featured {
  outline: var(--cb-border-thick) solid var(--cb-accent);
  outline-offset: -2px;
}

.cb-product__media {
  position: relative;
  aspect-ratio: 4 / 3;
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
}

/* O link em volta da foto precisa ser um bloco de altura cheia — sem isso o
   `height: 100%` da imagem se mede contra um <a> inline de altura zero e a
   foto some. */
.cb-product__media > a {
  display: block;
  width: 100%;
  height: 100%;
}

.cb-product__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cb-product__badge {
  position: absolute;
  inset-block-start: var(--cb-space-2xs);
  inset-inline-start: var(--cb-space-2xs);
  z-index: var(--cb-layer-raised);
}

.cb-product__body {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-xs);
  flex: 1;
  padding: var(--cb-space-md);
}

.cb-product__title {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-h3);
  font-weight: var(--cb-weight-bold);
  line-height: var(--cb-leading-heading);
}

.cb-product__prices {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-3xs);
}

.cb-product__compare {
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-sm);
}

.cb-product__compare s {
  text-decoration-thickness: 1px;
}

.cb-product__price-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--cb-space-2xs);
}

.cb-product__price {
  color: var(--cb-accent);
  font-size: clamp(1.5rem, 1.2rem + 1.3vw, 2rem);
  font-weight: var(--cb-weight-bold);
  line-height: 1;
}

.cb-product__discount {
  padding: 2px var(--cb-space-2xs);
  border-radius: var(--cb-radius-xs);
  background-color: var(--cb-yellow-500);
  color: var(--cb-coffee-600);
  font-size: var(--cb-text-xs);
  font-weight: var(--cb-weight-bold);
}

.cb-product__unit {
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-sm);
}

/* Empurra o CTA para a base, alinhando os botões entre cartões de alturas
   diferentes. */
.cb-product__cta {
  margin-block-start: auto;
  padding-block-start: var(--cb-space-2xs);
}

/* --- Variante compacta ----------------------------------------------------
   O cartão da referência: a foto domina, e o rodapé é uma linha só —
   nome e preço à esquerda, botão redondo à direita. Serve para grade de
   catálogo, onde o que decide é a imagem. O cartão cheio (com de/por,
   desconto e seletor de sabor) continua sendo o da home, onde o que decide
   é a comparação.
--------------------------------------------------------------------------- */
.cb-product--compact .cb-product__media {
  aspect-ratio: 1 / 1;
  /* A foto encosta nas bordas do cartão, como na referência: sem moldura,
     a imagem é que sustenta o cartão. */
  margin: var(--cb-space-2xs) var(--cb-space-2xs) 0;
  border-radius: var(--cb-radius-sm);
  overflow: hidden;
}

/* O selo vai para o topo DIREITO — no cartão compacto o canto esquerdo é
   onde o olho entra, e o selo ali roubaria a leitura da foto. */
.cb-product--compact .cb-product__badge {
  inset-inline: auto var(--cb-space-2xs);
  inset-block-start: var(--cb-space-2xs);
}

/* Rodapé em uma linha: identidade e preço à esquerda, ação à direita. */
.cb-product--compact .cb-product__body {
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-2xs);
  padding: var(--cb-space-sm);
}

.cb-product--compact .cb-product__title {
  font-size: var(--cb-text-h4);
  text-transform: uppercase;
  letter-spacing: var(--cb-tracking-heading);
}

.cb-product--compact .cb-product__prices {
  gap: 0;
}

.cb-product--compact .cb-product__price-row {
  gap: var(--cb-space-3xs);
  align-items: baseline;
}

.cb-product--compact .cb-product__price {
  font-size: var(--cb-text-body);
  color: var(--cb-fg);
}

.cb-product--compact .cb-product__compare {
  font-size: var(--cb-text-xs);
}

.cb-product--compact .cb-product__compare s {
  opacity: 0.75;
}

/* Sabor no cartão compacto: entre a foto e o rodapé, encostado nas laterais
   do cartão para não parecer um terceiro bloco. */
.cb-product__flavors {
  padding: var(--cb-space-2xs) var(--cb-space-sm) 0;
}

.cb-product--compact .cb-flavor {
  font-size: var(--cb-text-2xs);
  padding-inline-end: var(--cb-space-2xs);
}

.cb-product--compact .cb-flavor__swatch {
  width: 22px;
  height: 22px;
}

/* Barra de ferramentas da grade de kits */
.cb-kits-toolbar {
  display: flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  flex-shrink: 0;
}

.cb-kits-toolbar .cb-select {
  width: auto;
  min-height: 40px;
  border-radius: var(--cb-radius-pill);
  padding-inline: var(--cb-space-sm);
}

.cb-kits-note {
  margin-block-start: var(--cb-space-md);
  text-align: center;
}

/* Arte de ativo (os ícones da marca), no bloco de benefício */
.cb-benefit__art {
  width: 84px;
  height: auto;
  margin-block-end: var(--cb-space-2xs);
}

/* Selo com marcador — o "● FUN / ● FRESH" da referência. */
.cb-badge--dot::before {
  content: '';
  width: 6px;
  height: 6px;
  margin-inline-end: 5px;
  border-radius: 50%;
  background-color: currentColor;
}

/* --- Seletor de sabor -----------------------------------------------------
   Rádio nativo, escondido mas focável — teclado, leitor de tela e o
   agrupamento por `name` vêm de graça. Um <div> com clique não teria nada
   disso e ainda quebraria o envio do formulário no Woo.
--------------------------------------------------------------------------- */
.cb-flavors {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-2xs);
  padding: 0;
  margin: 0;
  border: 0;
}

.cb-flavor {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  padding: 3px var(--cb-space-xs) 3px 3px;
  border: var(--cb-border-thin) solid var(--cb-line);
  border-radius: var(--cb-radius-pill);
  cursor: pointer;
  font-size: var(--cb-text-xs);
  font-weight: var(--cb-weight-bold);
  line-height: 1.2;
  transition:
    border-color var(--cb-duration-fast) var(--cb-ease-out),
    background-color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-flavor:hover {
  background-color: rgb(var(--cb-fg-rgb) / 0.05);
}

/* Fora do fluxo visual, dentro do fluxo de foco. */
.cb-flavor input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.cb-flavor__swatch {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

.cb-flavor:has(input:checked) {
  border-color: var(--cb-accent);
  background-color: rgb(var(--cb-fg-rgb) / 0.07);
}

.cb-flavor:has(input:focus-visible) {
  outline: var(--cb-focus-width) solid var(--cb-accent);
  outline-offset: 2px;
}

@media (min-width: 768px) {
  .cb-product-grid { grid-template-columns: repeat(2, 1fr); }
  .cb-product-grid--3 { grid-template-columns: repeat(3, 1fr); }
}

@media (min-width: 1024px) {
  .cb-product-grid--4 { grid-template-columns: repeat(4, 1fr); }
  .cb-product__body { padding: var(--cb-space-md) var(--cb-space-md) var(--cb-space-md); }
}

/* ===========================================================================
   BENEFÍCIO — ícone/número + texto curto
   =========================================================================== */
.cb-benefit {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  padding: var(--cb-space-md);
  border-radius: var(--cb-radius-md);
  background-color: var(--cb-bg);
  color: var(--cb-fg);
  height: 100%;
}

.cb-benefit__figure {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: var(--cb-radius-pill);
  background-color: rgb(var(--cb-fg-rgb) / 0.1);
  color: var(--cb-fg-heading);
  margin-block-end: var(--cb-space-2xs);
}

.cb-benefit__figure svg {
  width: var(--cb-icon-lg);
  height: var(--cb-icon-lg);
}

.cb-benefit__title {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-h4);
  font-weight: var(--cb-weight-bold);
  line-height: var(--cb-leading-heading);
}

.cb-benefit__text {
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-sm);
  line-height: var(--cb-leading-body);
  max-width: 34ch;
}

/* Métrica grande (ex.: "20g de proteína"). */
.cb-metric {
  display: block;
  color: var(--cb-fg-heading);
  font-size: clamp(2.5rem, 1.6rem + 3.8vw, 4.5rem);
  font-weight: var(--cb-weight-bold);
  line-height: 0.95;
  letter-spacing: var(--cb-tracking-display);
}

/* ===========================================================================
   CARROSSEL — scroll-snap nativo, sem biblioteca
   =========================================================================== */
.cb-carousel {
  position: relative;
}

.cb-carousel__track {
  display: flex;
  gap: var(--cb-space-sm);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  /* Sangra até a borda no mobile e reserva a sarjeta como respiro
     do primeiro/último item. */
  margin-inline: calc(var(--cb-pad-inline) * -1);
  padding-inline: var(--cb-pad-inline);
  padding-block-end: var(--cb-space-2xs);
}

.cb-carousel__track::-webkit-scrollbar {
  display: none;
}

.cb-carousel__item {
  flex: 0 0 auto;
  width: clamp(200px, 68vw, 280px);
  scroll-snap-align: start;
  border-radius: var(--cb-radius-md);
  overflow: hidden;
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
}

/* Cartão de depoimento é mais largo que uma mídia vertical. */
.cb-carousel__item--wide {
  width: clamp(260px, 82vw, 380px);
  background-color: transparent;
}

.cb-carousel__item video,
.cb-carousel__item > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cb-carousel__nav {
  display: none;
  gap: var(--cb-space-2xs);
  justify-content: flex-end;
  margin-block-start: var(--cb-space-sm);
}

.cb-carousel__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--cb-touch-target);
  height: var(--cb-touch-target);
  border: var(--cb-border-thin) solid var(--cb-line);
  border-radius: var(--cb-radius-pill);
  color: var(--cb-fg);
  transition:
    background-color var(--cb-duration-fast) var(--cb-ease-out),
    opacity var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-carousel__button:hover {
  background-color: rgb(var(--cb-fg-rgb) / 0.08);
}

.cb-carousel__button[disabled] {
  opacity: 0.35;
  cursor: not-allowed;
}

.cb-carousel__button svg {
  width: var(--cb-icon-md);
  height: var(--cb-icon-md);
}

/* Botão de play sobre o pôster do depoimento. */
.cb-play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--cb-white);
}

.cb-play::before {
  content: '';
  position: absolute;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background-color: rgb(36 18 9 / 0.55);
  backdrop-filter: blur(2px);
  transition: transform var(--cb-duration-base) var(--cb-ease-bounce);
}

.cb-play:hover::before {
  transform: scale(1.08);
}

.cb-play svg {
  position: relative;
  width: 28px;
  height: 28px;
}

@media (min-width: 1024px) {
  .cb-carousel__track {
    margin-inline: 0;
    padding-inline: 0;
  }

  .cb-carousel__item {
    width: clamp(240px, 22vw, 320px);
  }

  .cb-carousel__nav {
    display: flex;
  }
}

/* ===========================================================================
   ACCORDION / FAQ
   <details> nativo, com abertura animada por grid-template-rows.
   =========================================================================== */
.cb-faq {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-3xs);
}

.cb-faq__item {
  border-radius: var(--cb-radius-sm);
  background-color: rgb(var(--cb-fg-rgb) / 0.07);
  overflow: hidden;
  transition: background-color var(--cb-duration-base) var(--cb-ease-out);
}

.cb-faq__item[open] {
  background-color: rgb(var(--cb-fg-rgb) / 0.12);
}

.cb-faq__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-sm) var(--cb-space-md);
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-h4);
  font-weight: var(--cb-weight-bold);
  line-height: var(--cb-leading-heading);
  cursor: pointer;
  list-style: none;
}

.cb-faq__summary::-webkit-details-marker {
  display: none;
}

.cb-faq__icon {
  flex-shrink: 0;
  width: var(--cb-icon-md);
  height: var(--cb-icon-md);
  transition: transform var(--cb-duration-base) var(--cb-ease-out);
}

.cb-faq__item[open] .cb-faq__icon {
  transform: rotate(90deg);
}

.cb-faq__panel-inner {
  padding: 0 var(--cb-space-md) var(--cb-space-md);
}

.cb-faq__panel-inner > * {
  color: var(--cb-fg);
  max-width: 64ch;
}

/* Abertura animada de `<details>`.
   `height: auto` só é interpolável porque :root declara
   `interpolate-size: allow-keywords` (ver tokens.css).

   Duas decisões deliberadas:

   1. `height`, não `block-size`. As propriedades lógicas ainda não interpolam
      para `auto` no Chrome — com `block-size` a transição simplesmente não sai
      do lugar.

   2. `content-visibility` FORA da transition, mesmo sendo a receita que
      circula por aí. Transicioná-lo com `allow-discrete` amarra a visibilidade
      do conteúdo ao término da animação: se a animação não avançar — aba em
      segundo plano, throttling, renderer ocupado — o painel fica preso em
      `hidden` e o accordion nunca abre. Um item de FAQ não pode falhar assim.
      Fora da transition, ele alterna na hora: a abertura desliza e, no pior
      caso, o conteúdo só aparece sem animar.

   3. O estado aberto é `height: auto` ESTÁTICO e a animação parte de 0 via
      `@starting-style` — não o contrário. Declarar `height: 0` no estado
      fechado e contar com a transição para chegar em `auto` faz do painel
      refém da animação: transição congelada, painel fechado. Invertido, o
      pior caso é abrir sem deslizar. Falha segura.

   O custo é o fechamento não acompanhar o colapso. O `overflow: hidden` do
   pseudo mascara isso e a abertura — que é o que o usuário olha — fica limpa.
   Sem suporte a interpolate-size, abre em salto, sem quebrar nada. */
@supports (interpolate-size: allow-keywords) {
  .cb-faq__item::details-content {
    overflow: hidden;
    transition: height var(--cb-duration-slow) var(--cb-ease-out);
  }

  .cb-faq__item[open]::details-content {
    height: auto;
  }

  @starting-style {
    .cb-faq__item[open]::details-content {
      height: 0;
    }
  }
}

/* ===========================================================================
   TABELA COMPARATIVA — "nós vs. eles"
   =========================================================================== */
.cb-compare {
  width: 100%;
  border-radius: var(--cb-radius-md);
  overflow: hidden;
  background-color: var(--cb-bg);
  font-size: var(--cb-text-sm);
}

.cb-compare th,
.cb-compare td {
  padding: var(--cb-space-xs);
  border-block-end: var(--cb-border-thin) solid var(--cb-line);
  text-align: center;
  vertical-align: middle;
}

.cb-compare thead th {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-xs);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  text-transform: uppercase;
}

.cb-compare tbody th {
  color: var(--cb-fg);
  font-weight: var(--cb-weight-medium);
  text-align: start;
}

.cb-compare tbody tr:last-child th,
.cb-compare tbody tr:last-child td {
  border-block-end: 0;
}

/* Coluna da marca em destaque, do topo à base. */
.cb-compare__own {
  background-color: rgb(var(--cb-fg-rgb) / 0.07);
}

.cb-compare__yes { color: var(--cb-success); }
.cb-compare__no { color: var(--cb-danger); }

.cb-compare__yes svg,
.cb-compare__no svg {
  width: var(--cb-icon-md);
  height: var(--cb-icon-md);
  margin-inline: auto;
}

@media (min-width: 768px) {
  .cb-compare {
    font-size: var(--cb-text-body);
  }

  .cb-compare th,
  .cb-compare td {
    padding: var(--cb-space-sm);
  }
}

/* ===========================================================================
   FORMULÁRIO
   =========================================================================== */
.cb-field {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-3xs);
}

.cb-field__label {
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
}

.cb-input,
.cb-select,
.cb-textarea {
  width: 100%;
  min-height: var(--cb-touch-target);
  padding: var(--cb-space-2xs) var(--cb-space-xs);
  border: var(--cb-border-thin) solid var(--cb-field-border);
  border-radius: var(--cb-radius-xs);
  background-color: var(--cb-field-bg);
  color: var(--cb-field-fg);
  font-size: var(--cb-text-body);
  transition: border-color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-input::placeholder,
.cb-textarea::placeholder {
  color: var(--cb-field-placeholder);
}

.cb-input:focus,
.cb-select:focus,
.cb-textarea:focus {
  border-color: var(--cb-accent);
}

.cb-textarea {
  min-height: 7rem;
  padding-block: var(--cb-space-2xs);
  resize: vertical;
}

/* Seletor de quantidade */
.cb-quantity {
  display: inline-flex;
  align-items: center;
  border: var(--cb-border-thin) solid var(--cb-field-border);
  border-radius: var(--cb-radius-pill);
  overflow: hidden;
}

.cb-quantity__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--cb-touch-target);
  height: var(--cb-touch-target);
  color: var(--cb-fg);
  font-size: var(--cb-text-h4);
  line-height: 1;
}

.cb-quantity__button:hover {
  background-color: rgb(var(--cb-fg-rgb) / 0.08);
}

.cb-quantity__input {
  width: 3rem;
  border: 0;
  background: transparent;
  color: var(--cb-fg);
  font-weight: var(--cb-weight-bold);
  text-align: center;
  -moz-appearance: textfield;
}

.cb-quantity__input::-webkit-outer-spin-button,
.cb-quantity__input::-webkit-inner-spin-button {
  appearance: none;
  margin: 0;
}

/* ===========================================================================
   BARRA DE COMPRA FIXA — aparece no mobile ao rolar a PDP
   =========================================================================== */
.cb-buybar {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: var(--cb-layer-sticky);
  display: flex;
  align-items: center;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-2xs) var(--cb-pad-inline);
  padding-block-end: max(var(--cb-space-2xs), env(safe-area-inset-bottom));
  background-color: var(--cb-bg);
  color: var(--cb-fg);
  box-shadow: 0 -4px 20px rgb(36 18 9 / 0.18);
  transform: translateY(100%);
  transition: transform var(--cb-duration-slow) var(--cb-ease-out);
}

.cb-buybar[data-visible='true'] {
  transform: translateY(0);
}

.cb-buybar__info {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
}

.cb-buybar__price {
  color: var(--cb-accent);
  font-size: var(--cb-text-h4);
  font-weight: var(--cb-weight-bold);
}

.cb-buybar__label {
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
}

.cb-buybar .cb-button {
  margin-inline-start: auto;
}

@media (min-width: 1024px) {
  .cb-buybar { display: none; }
}

/* ===========================================================================
   TÍTULO COM ASSINATURA
   O gesto central da referência: caixa alta pesada com uma palavra manuscrita
   atravessando, em cor de acento.

     <h2 class="cb-headline">
       Quanto maior o kit, <b>menor a dose</b>
       <em class="cb-headline__script">sem mistério</em>
     </h2>

   A assinatura é inline-block, não absolute. Absolute sairia do fluxo e no
   mobile atropelaria a linha de baixo — inline ela empurra o texto e o
   título continua respirando sozinho em qualquer largura.
   =========================================================================== */
.cb-headline__script {
  display: inline-block;
  font-family: var(--cb-font-script);
  font-style: normal;
  font-weight: 700;
  /* em, não rem: acompanha o tamanho do título que a hospeda */
  font-size: 0.78em;
  line-height: 0.8;
  color: var(--cb-accent);
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
  transform: rotate(-4deg) translateY(0.06em);
  transform-origin: left center;
  margin-inline-start: 0.18em;
}

/* Sobre lâmina escura a assinatura ganha o amarelo; sobre clara, o caramelo.
   Vem de --cb-accent, então cada esquema já resolve — nada a fazer aqui. */

/* ===========================================================================
   SOBRELINHA EM PÍLULA
   O rótulo de seção da referência: pílula clara com bolinha antes.
   =========================================================================== */
.cb-eyebrow--pill {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  padding: var(--cb-space-3xs) var(--cb-space-sm);
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-yellow-500);
  color: var(--cb-coffee-600);
}

.cb-eyebrow--pill::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background-color: currentColor;
}

/* ===========================================================================
   CABEÇALHO DE SEÇÃO EM LINHA
   Título à esquerda, controles à direita. No mobile empilha e os controles
   somem — dedo rola o carrossel, seta é coisa de mouse.
   =========================================================================== */
.cb-section-head--row {
  align-items: flex-start;
  text-align: start;
}

.cb-section-head--row > * {
  margin-inline: 0;
}

@media (min-width: 768px) {
  .cb-section-head--row {
    flex-direction: row;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--cb-space-lg);
  }

  .cb-section-head--row .cb-section-head__text {
    display: flex;
    flex-direction: column;
    gap: var(--cb-space-xs);
  }
}

/* ===========================================================================
   BOTÃO CIRCULAR DE COMPRA
   O add-to-cart redondo no canto do cartão. Mesmos estados do .cb-button
   (spinner e ✓) porque herda o mesmo contrato de data-state.
   =========================================================================== */
.cb-add-round {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--cb-touch-target);
  height: var(--cb-touch-target);
  border: var(--cb-border-thin) solid var(--cb-btn-border);
  border-radius: 50%;
  background: var(--cb-btn-bg);
  color: var(--cb-btn-fg);
  cursor: pointer;
  transition:
    background var(--cb-duration-base) var(--cb-ease-out),
    transform var(--cb-duration-fast) var(--cb-ease-bounce),
    box-shadow var(--cb-duration-base) var(--cb-ease-out);
}

.cb-add-round:hover {
  background: var(--cb-btn-bg-hover);
  color: var(--cb-btn-fg-hover);
  transform: scale(1.08);
  box-shadow: var(--cb-shadow-button);
}

.cb-add-round:active {
  transform: scale(0.96);
}

.cb-add-round svg {
  width: 18px;
  height: 18px;
}

.cb-add-round[data-state='loading'] {
  pointer-events: none;
}

.cb-add-round[data-state='loading'] svg,
.cb-add-round[data-state='done'] svg {
  opacity: 0;
}

.cb-add-round::after {
  content: '';
  position: absolute;
  inset: 0;
  width: 16px;
  height: 16px;
  margin: auto;
  border: 2px solid currentColor;
  border-block-start-color: transparent;
  border-radius: 50%;
  opacity: 0;
}

.cb-add-round[data-state='loading']::after {
  opacity: 1;
  animation: cb-spin 0.6s linear infinite;
}

.cb-add-round[data-state='done'] {
  pointer-events: none;
}

.cb-add-round[data-state='done']::before {
  content: '✓';
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-weight: var(--cb-weight-bold);
  animation: cb-pop var(--cb-duration-base) var(--cb-ease-bounce);
}

/* ===========================================================================
   DEPOIMENTO
   Foto grande, aspas, texto, autor com nota.
   =========================================================================== */
.cb-testimonial {
  display: flex;
  flex-direction: column;
  height: 100%;
  margin: 0;
  border-radius: var(--cb-radius-md);
  overflow: hidden;
  background-color: var(--cb-bg);
  color: var(--cb-fg);
}

.cb-testimonial__media {
  /* 3/2 e não 4/3: somada a título, texto e assinatura, a foto mais alta
     empurrava o cartão para perto de 510 px — e quem paga por isso é o
     cartão SEM foto, que fica com o mesmo tamanho e nada para preencher. */
  aspect-ratio: 3 / 2;
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
}

.cb-testimonial__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cb-testimonial__body {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  flex: 1;
  padding: var(--cb-space-md);
}

/* Miniatura do kit + nota, na mesma linha: antes de ler a frase a pessoa já
   sabe QUAL kit foi avaliado e com quantas estrelas. */
.cb-testimonial__cabeca {
  display: flex;
  align-items: center;
  gap: var(--cb-space-2xs);
}

.cb-testimonial__kit {
  width: 38px;
  height: 38px;
  border-radius: var(--cb-radius-xs);
  /* contain, não cover: em 44 px o corte central da foto do kit devolvia um
     retângulo de fundo sem produto nenhum. Inteiro e pequeno se reconhece;
     cortado e grande, não. */
  object-fit: contain;
  padding: 3px;
  flex-shrink: 0;
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
}

.cb-testimonial__estrelas {
  display: inline-flex;
  gap: 1px;
  font-size: var(--cb-ui-label);
  line-height: 1;
}

.cb-star {
  color: var(--cb-gold-500);
}

.cb-star--vazia {
  /* 0.22 sumia contra o creme do cartão e a nota 4 lia como 4 estrelas de 4.
     A estrela que falta só informa se der para vê-la. */
  color: rgb(var(--cb-fg-rgb) / 0.32);
}

/* A manchete do cartão. É o que se lê primeiro numa fileira que passa rápido —
   e o que permite ao texto ser longo sem custar a atenção de quem só varre. */
.cb-testimonial__titulo {
  margin: 0;
  font-size: var(--cb-ui-body);
  font-weight: var(--cb-weight-bold);
  line-height: 1.25;
  letter-spacing: var(--cb-tracking-heading);
  text-wrap: balance;
}

/* UM tamanho para todo depoimento, com ou sem foto. A variante sem foto
   subia para 20 px porque precisava preencher a altura que a fileira impunha;
   na grade cada cartão tem a altura do próprio conteúdo, e o que sobrou foi
   dois corpos de texto diferentes lado a lado na mesma seção. */
.cb-testimonial__quote {
  margin: 0;
  font-size: var(--cb-ui-label);
  line-height: var(--cb-leading-body);
  text-wrap: pretty;
}

/* Dobrado em quatro linhas. -webkit-box é o que faz o line-clamp funcionar —
   por isso o quote deixou de ser flex quando o título assumiu as aspas. */
.cb-testimonial__quote--dobrada {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  overflow: hidden;
}

.cb-testimonial__mais {
  align-self: flex-start;
  padding: 0;
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.cb-testimonial__mais:hover {
  color: var(--cb-fg);
}

.cb-testimonial__author {
  display: flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  margin-block-start: auto;
  padding-block-start: var(--cb-space-xs);
}

.cb-testimonial__avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
  background-color: rgb(var(--cb-fg-rgb) / 0.1);
}

/* Sem foto do cliente, iniciais. Melhor que um avatar genérico de banco de
   imagem, que todo mundo reconhece como falso. */
.cb-testimonial__avatar--initial {
  display: grid;
  place-items: center;
  background-color: var(--cb-coffee-400);
  color: var(--cb-cream-100);
  font-size: var(--cb-text-xs);
  font-weight: var(--cb-weight-bold);
  letter-spacing: 0.02em;
}

.cb-testimonial__quem {
  min-width: 0;
}

.cb-testimonial__name {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: var(--cb-ui-label);
  font-weight: var(--cb-weight-bold);
  line-height: 1.2;
}

/* O selo afirma que existe compra confirmada por trás. Some junto com o texto
   quando a avaliação não tiver pedido — ver js/depoimentos.js. */
.cb-testimonial__selo {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  color: var(--cb-green-600);
}

.cb-testimonial__role {
  display: block;
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-2xs);
}

/* ===========================================================================
   BLOCO DE INGREDIENTES
   Duas colunas — imagem grande de um lado, argumento do outro — com uma tira
   de três miniaturas fechando o texto. É o "fresh starts with fresh
   ingredients" da referência.
   =========================================================================== */
.cb-ingredients {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--cb-space-lg);
  align-items: center;
}

.cb-ingredients__figure {
  border-radius: var(--cb-radius-md);
  overflow: hidden;
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
}

.cb-ingredients__figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  aspect-ratio: 4 / 5;
}

.cb-ingredients__body {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-md);
}

.cb-ingredients__strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--cb-space-2xs);
  list-style: none;
  padding: 0;
  margin: 0;
}

.cb-ingredients__strip img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--cb-radius-sm);
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
}

.cb-ingredients__caption {
  display: block;
  margin-block-start: var(--cb-space-3xs);
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
  text-align: center;
}

@media (min-width: 1024px) {
  .cb-ingredients {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: var(--cb-space-2xl);
  }
}

/* ===========================================================================
   NEWSLETTER
   =========================================================================== */
.cb-newsletter {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-md);
}

.cb-newsletter__form {
  display: flex;
  gap: var(--cb-space-2xs);
  width: 100%;
  max-width: 34rem;
}

.cb-newsletter__form .cb-input {
  border-radius: var(--cb-radius-pill);
  padding-inline: var(--cb-space-md);
}

@media (min-width: 768px) {
  .cb-newsletter {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--cb-space-xl);
  }
}

/* ===========================================================================
   WORDMARK CORTADO
   A marca gigante sangrando na base do rodapé. Decorativa: aria-hidden no
   HTML, porque um leitor de tela lendo "COFFEE BLEND" solto no fim da página
   não ajuda ninguém.
   =========================================================================== */
.cb-wordmark {
  overflow: hidden;
  /* Recorta pouco mais da metade da altura da letra — o corte é o efeito. */
  height: 0.52em;
  font-size: clamp(4rem, 19vw, 17rem);
  line-height: 0.78;
  user-select: none;
  pointer-events: none;
}

.cb-wordmark__text {
  display: block;
  color: var(--cb-fg-heading);
  font-family: var(--cb-font-heading);
  font-weight: var(--cb-weight-bold);
  letter-spacing: -0.04em;
  text-align: center;
  white-space: nowrap;
  opacity: 0.22;
}

/* ===========================================================================
   PDP — PÁGINA DE PRODUTO
   Uma página serve os quatro kits: o JS troca conteúdo, nunca layout.
   =========================================================================== */
.cb-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-3xs);
  list-style: none;
  padding: 0;
  margin: 0 0 var(--cb-space-md);
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
}

/* padding vertical engorda o alvo de toque sem afastar os itens da trilha */
.cb-breadcrumb a {
  display: inline-block;
  padding-block: var(--cb-space-3xs);
  color: inherit;
  text-decoration: none;
}

.cb-breadcrumb a:hover {
  text-decoration: underline;
}

.cb-breadcrumb li + li::before {
  content: '/';
  margin-inline-end: var(--cb-space-3xs);
  opacity: 0.5;
}

.cb-pdp {
  display: grid;
  /* minmax(0, 1fr) e não 1fr: o mínimo de `1fr` é o min-content do item, e a
     galeria não encolhia abaixo dos 534 px da foto — a página inteira rolava
     de lado no celular. O breakpoint de 1024 px abaixo já fazia certo; era só
     o mobile que ficava de fora. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--cb-space-lg);
}

@media (min-width: 1024px) {
  .cb-pdp {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: var(--cb-space-2xl);
    align-items: start;
  }

  /* A coluna de compra acompanha a rolagem da galeria — o botão nunca some
     de vista numa página longa. */
  .cb-pdp__buy {
    position: sticky;
    top: calc(var(--cb-touch-target) + var(--cb-space-lg));
  }
}

/* --- Galeria --------------------------------------------------------------
   Miniaturas em coluna no desktop, faixa rolável no mobile.
--------------------------------------------------------------------------- */
.cb-gallery {
  display: flex;
  flex-direction: column-reverse;
  gap: var(--cb-space-2xs);
}

.cb-gallery__main {
  aspect-ratio: 1 / 1;
  border-radius: var(--cb-radius-md);
  overflow: hidden;
  background-color: rgb(var(--cb-fg-rgb) / 0.05);
}

.cb-gallery__main img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cb-gallery__thumbs {
  display: flex;
  gap: var(--cb-space-2xs);
  overflow-x: auto;
  scrollbar-width: none;
  list-style: none;
  padding: 0;
  margin: 0;
}

.cb-gallery__thumbs::-webkit-scrollbar {
  display: none;
}

.cb-gallery__thumb {
  flex: 0 0 auto;
  width: 68px;
  aspect-ratio: 1 / 1;
  padding: 0;
  border: var(--cb-border-thick) solid transparent;
  border-radius: var(--cb-radius-sm);
  overflow: hidden;
  background-color: rgb(var(--cb-fg-rgb) / 0.05);
  cursor: pointer;
  transition: border-color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-gallery__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cb-gallery__thumb[aria-current='true'] {
  border-color: var(--cb-accent);
}

@media (min-width: 768px) {
  .cb-gallery {
    flex-direction: row;
    align-items: flex-start;
  }

  .cb-gallery__thumbs {
    flex-direction: column;
    overflow-x: visible;
    flex: 0 0 auto;
  }

  /* O item flex é a <div> sem classe que embrulha a foto e os pontos, não o
     `.cb-gallery__main` lá dentro. Enquanto a imagem estava no fluxo ela dava
     largura ao conjunto e ninguém percebeu; com a imagem absoluta, a coluna
     colapsou para 54 px. */
  .cb-gallery > div {
    flex: 1;
    min-width: 0;
  }

  .cb-gallery__main {
    flex: 1;
    min-width: 0;
  }
}

/* --- Caixa de compra ------------------------------------------------------- */
.cb-buybox {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-md);
}

.cb-buybox__title {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-h1);
  line-height: var(--cb-leading-display);
}

.cb-buybox__price-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--cb-space-2xs);
}

.cb-buybox__price {
  color: var(--cb-accent);
  font-size: clamp(2rem, 1.5rem + 2vw, 2.75rem);
  font-weight: var(--cb-weight-bold);
  line-height: 1;
}

.cb-buybox__compare {
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-body);
}

.cb-buybox__installment {
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-sm);
}

.cb-buybox__field-label {
  display: block;
  margin-block-end: var(--cb-space-2xs);
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
}

.cb-buybox__actions {
  display: flex;
  gap: var(--cb-space-2xs);
  align-items: center;
}

.cb-buybox__actions .cb-button {
  flex: 1;
}

/* --- Seletor de kit --------------------------------------------------------
   Lista de rádios com preço e economia visíveis: a comparação acontece sem
   sair da página.
--------------------------------------------------------------------------- */
.cb-kits {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  padding: 0;
  margin: 0;
  border: 0;
}

.cb-kit {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--cb-space-xs);
  padding: var(--cb-space-xs) var(--cb-space-sm);
  border: var(--cb-border-thin) solid var(--cb-line);
  border-radius: var(--cb-radius-sm);
  cursor: pointer;
  transition:
    border-color var(--cb-duration-fast) var(--cb-ease-out),
    background-color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-kit:hover {
  background-color: rgb(var(--cb-fg-rgb) / 0.04);
}

.cb-kit:has(input:checked) {
  border-color: var(--cb-accent);
  border-width: var(--cb-border-thick);
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
  /* Compensa o filete que engrossou, senão a linha "pula" ao ser marcada. */
  padding: calc(var(--cb-space-xs) - 1px) calc(var(--cb-space-sm) - 1px);
}

.cb-kit:has(input:focus-visible) {
  outline: var(--cb-focus-width) solid var(--cb-accent);
  outline-offset: 2px;
}

.cb-kit input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.cb-kit__mark {
  width: 18px;
  height: 18px;
  border: var(--cb-border-thick) solid var(--cb-line);
  border-radius: 50%;
  flex-shrink: 0;
}

.cb-kit:has(input:checked) .cb-kit__mark {
  border-color: var(--cb-accent);
  background:
    radial-gradient(circle, var(--cb-accent) 0 42%, transparent 43%);
}

.cb-kit__name {
  display: block;
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
  line-height: 1.25;
}

.cb-kit__meta {
  display: block;
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
}

.cb-kit__price {
  text-align: end;
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
  white-space: nowrap;
}

.cb-kit__save {
  display: block;
  color: var(--cb-success);
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-bold);
}

/* --- Selos de confiança ----------------------------------------------------- */
.cb-trust {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--cb-space-2xs);
  list-style: none;
  padding: var(--cb-space-sm) 0 0;
  margin: 0;
  border-block-start: var(--cb-border-thin) solid var(--cb-line);
}

.cb-trust li {
  display: flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  /* Frete grátis, envio em 24 h e compra segura são argumentos de venda, não
     rodapé: em 12 px ninguém lia o que estava logo abaixo do botão. */
  font-size: var(--cb-ui-body);
  line-height: 1.3;
}

.cb-trust svg {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  color: var(--cb-accent);
}

/* ===========================================================================
   LOCALIZADOR DE PONTOS DE VENDA
   =========================================================================== */
.cb-finder__controls {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-sm);
  margin-block-end: var(--cb-space-lg);
}

.cb-finder__search {
  display: flex;
  gap: var(--cb-space-2xs);
  width: 100%;
  max-width: 30rem;
}

.cb-finder__search .cb-input {
  border-radius: var(--cb-radius-pill);
  padding-inline: var(--cb-space-md);
}

/* --- Abas de região -------------------------------------------------------
   Botão, não link: troca de recorte no lugar, sem navegar. `aria-pressed`
   comunica o estado — é alternador, não navegação, e leitor de tela precisa
   saber a diferença.
--------------------------------------------------------------------------- */
.cb-region-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-2xs);
  list-style: none;
  padding: 0;
  margin: 0;
}

.cb-region {
  display: inline-flex;
  align-items: center;
  min-height: 38px;
  padding: var(--cb-space-3xs) var(--cb-space-md);
  border: var(--cb-border-thin) solid var(--cb-line);
  border-radius: var(--cb-radius-pill);
  color: var(--cb-fg);
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
  cursor: pointer;
  transition:
    background-color var(--cb-duration-fast) var(--cb-ease-out),
    border-color var(--cb-duration-fast) var(--cb-ease-out),
    color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-region:hover {
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
}

.cb-region[aria-pressed='true'] {
  background-color: var(--cb-coffee-600);
  border-color: var(--cb-coffee-600);
  color: var(--cb-cream-200);
}

/* --- Atalhos de cidade ----------------------------------------------------- */
.cb-city-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-3xs);
  list-style: none;
  padding: 0;
  margin: 0;
}

.cb-city {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-3xs);
  min-height: var(--cb-touch-target);
  padding: 2px var(--cb-space-2xs);
  border: var(--cb-border-thin) solid transparent;
  border-radius: var(--cb-radius-pill);
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
  color: var(--cb-fg);
  font-size: var(--cb-text-xs);
  cursor: pointer;
  transition: background-color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-city:hover {
  background-color: rgb(var(--cb-fg-rgb) / 0.12);
}

.cb-city[aria-pressed='true'] {
  border-color: var(--cb-accent);
  background-color: rgb(var(--cb-fg-rgb) / 0.12);
  font-weight: var(--cb-weight-bold);
}

.cb-city__count {
  padding-inline: 5px;
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-yellow-500);
  color: var(--cb-coffee-600);
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-bold);
}

/* --- Lista de pontos ------------------------------------------------------- */
.cb-store-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--cb-space-sm);
  list-style: none;
  padding: 0;
  margin: 0;
}

.cb-store-list--empty {
  display: block;
}

.cb-store {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-3xs);
  padding: var(--cb-space-md);
  border-radius: var(--cb-radius-md);
  background-color: var(--cb-bg);
  color: var(--cb-fg);
  transition: box-shadow var(--cb-duration-base) var(--cb-ease-out);
}

.cb-store:hover {
  box-shadow: var(--cb-shadow-md);
}

.cb-store__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--cb-space-2xs);
  flex-wrap: wrap;
}

.cb-store__name {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-h4);
  font-weight: var(--cb-weight-bold);
  line-height: 1.2;
}

.cb-store__type {
  padding: 2px var(--cb-space-2xs);
  border-radius: var(--cb-radius-pill);
  background-color: rgb(var(--cb-fg-rgb) / 0.08);
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-2xs);
  white-space: nowrap;
}

.cb-store__address {
  color: var(--cb-fg);
  font-size: var(--cb-text-sm);
}

.cb-store__city {
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
}

.cb-store__actions {
  display: flex;
  align-items: center;
  gap: var(--cb-space-sm);
  flex-wrap: wrap;
  margin-block-start: var(--cb-space-2xs);
}

.cb-store__phone {
  /* É um link `tel:` ao lado de um botão de 44 px: com 29 px de altura o
     dedo acertava o botão do mapa em vez do telefone. */
  display: inline-flex;
  align-items: center;
  min-height: var(--cb-touch-target);
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-sm);
  text-decoration: none;
  padding-block: var(--cb-space-3xs);
}

.cb-store__phone:hover {
  color: var(--cb-fg);
  text-decoration: underline;
}

/* --- Nenhum resultado -----------------------------------------------------
   O vazio não é beco: quem não achou a cidade ainda pode comprar no site ou
   virar lojista. Duas saídas, nenhuma frustração.
--------------------------------------------------------------------------- */
.cb-store-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--cb-space-2xs);
  padding: var(--cb-space-2xl) var(--cb-space-md);
  border-radius: var(--cb-radius-md);
  background-color: rgb(var(--cb-fg-rgb) / 0.05);
  text-align: center;
}

.cb-store-empty__title {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-h3);
  font-weight: var(--cb-weight-bold);
  max-width: 24ch;
}

.cb-store-empty__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--cb-space-2xs);
  margin-block-start: var(--cb-space-sm);
}

@media (min-width: 768px) {
  .cb-store-list {
    grid-template-columns: repeat(2, 1fr);
  }

  .cb-finder__controls {
    gap: var(--cb-space-md);
  }
}

@media (min-width: 1024px) {
  .cb-store-list {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* ===========================================================================
   CARRINHO
   O drawer reaproveita `.cb-drawer` (largura, backdrop, `<dialog>` nativo) e
   só troca o miolo por cabeça fixa / corpo rolável / rodapé fixo.
   As mesmas classes de linha e de resumo servem a carrinho.html — um
   componente, dois lugares.
   =========================================================================== */
.cb-cart__inner {
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  height: 100%;
  max-height: 100dvh;
}

.cb-cart__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-md);
  border-block-end: var(--cb-border-thin) solid var(--cb-line);
}

.cb-cart__title {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-h3);
  font-weight: var(--cb-weight-bold);
}

.cb-cart__count {
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-regular);
}

/* O corpo é o único que rola; cabeça e rodapé ficam presos. */
.cb-cart__body {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--cb-space-md);
}

.cb-cart__foot {
  padding: var(--cb-space-md);
  padding-block-end: max(var(--cb-space-md), env(safe-area-inset-bottom));
  border-block-start: var(--cb-border-thin) solid var(--cb-line);
  background-color: var(--cb-bg);
}

/* --- Progresso do frete grátis -------------------------------------------
   Puxa o pedido para cima mostrando o quanto falta. O valor vem do
   catálogo (CBCatalog.FRETE_GRATIS), nunca escrito à mão aqui. */
.cb-freeship {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  padding: var(--cb-space-xs) var(--cb-space-md);
  background-color: rgb(var(--cb-fg-rgb) / 0.05);
}

.cb-freeship__text {
  font-size: var(--cb-text-sm);
  line-height: 1.3;
}

.cb-freeship__text b {
  color: var(--cb-fg-heading);
}

.cb-freeship__bar {
  height: 6px;
  border-radius: var(--cb-radius-pill);
  background-color: rgb(var(--cb-fg-rgb) / 0.14);
  overflow: hidden;
}

.cb-freeship__fill {
  height: 100%;
  width: 0;
  border-radius: inherit;
  background-color: var(--cb-accent);
  transition: width var(--cb-duration-slow) var(--cb-ease-out);
}

.cb-freeship[data-complete='true'] .cb-freeship__fill {
  background-color: var(--cb-green-600);
}

/* --- Linha de item -------------------------------------------------------- */
.cb-cart-lines {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-md);
  list-style: none;
  padding: 0;
  margin: 0;
}

.cb-cart-line {
  display: grid;
  grid-template-columns: 72px 1fr;
  gap: var(--cb-space-sm);
  padding-block-end: var(--cb-space-md);
  border-block-end: var(--cb-border-thin) solid var(--cb-line);
}

.cb-cart-lines > .cb-cart-line:last-child {
  padding-block-end: 0;
  border-block-end: 0;
}

.cb-cart-line__media {
  aspect-ratio: 1 / 1;
  border-radius: var(--cb-radius-sm);
  overflow: hidden;
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
}

.cb-cart-line__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cb-cart-line__body {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  min-width: 0;
}

.cb-cart-line__top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--cb-space-2xs);
}

.cb-cart-line__name {
  display: inline-block;
  padding-block: var(--cb-space-3xs);
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-body);
  font-weight: var(--cb-weight-bold);
  line-height: 1.2;
  text-decoration: none;
}

.cb-cart-line__meta {
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
}

.cb-cart-line__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-2xs);
  margin-block-start: var(--cb-space-3xs);
}

.cb-cart-line__price {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-body);
  font-weight: var(--cb-weight-bold);
  white-space: nowrap;
}

/* Botão de remover: discreto até o hover, para não competir com o stepper. */
.cb-cart-line__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin: -6px -6px 0 0;
  border-radius: var(--cb-radius-xs);
  color: var(--cb-fg-muted);
  transition:
    color var(--cb-duration-fast) var(--cb-ease-out),
    background-color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-cart-line__remove:hover {
  color: var(--cb-danger);
  background-color: rgb(var(--cb-fg-rgb) / 0.08);
}

.cb-cart-line__remove svg {
  width: 16px;
  height: 16px;
}

/* Linha saindo: some antes do estado ser regravado. */
.cb-cart-line[data-removing='true'] {
  opacity: 0.4;
  pointer-events: none;
  transition: opacity var(--cb-duration-base) var(--cb-ease-out);
}

/* --- Stepper compacto (dentro da linha) ----------------------------------- */
.cb-stepper {
  display: inline-flex;
  align-items: center;
  border: var(--cb-border-thin) solid var(--cb-line);
  border-radius: var(--cb-radius-pill);
  overflow: hidden;
}

.cb-stepper__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  color: var(--cb-fg);
  font-size: var(--cb-text-body);
  line-height: 1;
  transition: background-color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-stepper__button:hover {
  background-color: rgb(var(--cb-fg-rgb) / 0.08);
}

.cb-stepper__button svg {
  width: 12px;
  height: 12px;
}

.cb-stepper__value {
  min-width: 2rem;
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* --- Resumo --------------------------------------------------------------- */
.cb-cart-summary {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  margin-block-end: var(--cb-space-sm);
}

.cb-cart-summary__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--cb-space-sm);
  font-size: var(--cb-text-sm);
}

.cb-cart-summary__row--total {
  padding-block-start: var(--cb-space-2xs);
  border-block-start: var(--cb-border-thin) solid var(--cb-line);
  font-size: var(--cb-text-h4);
  font-weight: var(--cb-weight-bold);
}

.cb-cart-summary__row--total dd {
  color: var(--cb-accent);
}

.cb-cart-summary__row--save dd {
  color: var(--cb-success);
  font-weight: var(--cb-weight-bold);
}

/* Linha do Pix: vem DEPOIS do total, e por isso precisa de um respiro para
   não se ler como parte dele. Verde igual ao da economia — é o mesmo tipo de
   informação: dinheiro que fica no bolso de quem compra. */
.cb-cart-summary__row--pix {
  margin-block-start: var(--cb-space-3xs, 2px);
}

.cb-cart-summary__row--pix dd {
  color: var(--cb-success);
  font-weight: var(--cb-weight-bold);
}

.cb-cart-summary dt,
.cb-cart-summary dd {
  margin: 0;
}

.cb-cart-summary dd {
  font-variant-numeric: tabular-nums;
}

.cb-cart__note {
  margin-block-start: var(--cb-space-2xs);
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
  text-align: center;
}

/* --- Vazio ---------------------------------------------------------------- */
.cb-cart-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--cb-space-sm);
  padding-block: var(--cb-space-2xl);
  text-align: center;
}

.cb-cart-empty__icon {
  color: var(--cb-fg-muted);
  opacity: 0.5;
}

.cb-cart-empty__icon svg {
  width: 48px;
  height: 48px;
}

.cb-cart-empty__title {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-h3);
  font-weight: var(--cb-weight-bold);
}

/* ===========================================================================
   RODAPÉ
   =========================================================================== */
.cb-footer__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--cb-space-lg);
}

.cb-footer__brand {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-md);
}

.cb-footer__logo {
  height: 44px;
  width: auto;
}

.cb-footer__social {
  display: flex;
  gap: var(--cb-space-sm);
}

.cb-footer__title {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  text-transform: uppercase;
  margin-block-end: var(--cb-space-2xs);
}

.cb-footer__list {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  list-style: none;
  padding: 0;
  margin: 0;
}

/* padding vertical em vez de gap maior: engorda o alvo de toque de 21px para
   ~33px sem afastar visualmente os itens da lista. */
.cb-footer__list a {
  display: inline-block;
  padding-block: var(--cb-space-3xs);
  color: var(--cb-fg);
  font-size: var(--cb-text-sm);
  text-decoration: none;
  transition: opacity var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-footer__list a:hover {
  opacity: 0.7;
}

.cb-payments {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-2xs);
  list-style: none;
  padding: 0;
  margin: 0;
}

.cb-payments li {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 26px;
  min-width: 40px;
  padding-inline: var(--cb-space-3xs);
  border: var(--cb-border-thin) solid var(--cb-line);
  border-radius: var(--cb-radius-xs);
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-bold);
  letter-spacing: 0.02em;
}

.cb-footer__legal {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  padding-block-start: var(--cb-space-md);
  margin-block-start: var(--cb-space-lg);
  border-block-start: var(--cb-border-thin) solid var(--cb-line);
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
}

@media (min-width: 768px) {
  .cb-footer__grid {
    grid-template-columns: 1.4fr 1fr 1fr;
    gap: var(--cb-space-xl);
  }
}

@media (min-width: 1024px) {
  .cb-footer__grid {
    grid-template-columns: 1.6fr 1fr 1fr 1.2fr;
  }

  .cb-footer__legal {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

/* ===========================================================================
   CASCA DE APLICATIVO (mobile)
   ---------------------------------------------------------------------------
   O alvo é a sensação de app nativo sem virar app: barra de abas presa na
   base, folha que sobe de baixo, respeito às safe areas e resposta imediata
   ao toque.

   Três decisões que separam "site em tela pequena" de "parece app":

   1. A navegação mora na base, ao alcance do polegar — não no topo.
   2. O que é modal SOBE, não desliza da lateral. Lateral é padrão de menu;
      de baixo é padrão de ação.
   3. Nada encosta na borda física: `env(safe-area-inset-*)` em tudo que
      toca o limite da tela, senão o home indicator do iPhone come o botão.
   =========================================================================== */

/* --- Barra de abas ---------------------------------------------------------
   Só no mobile. No desktop a navegação do topo já resolve e uma barra presa
   na base viraria estorvo.
--------------------------------------------------------------------------- */
.cb-tabbar {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: var(--cb-layer-sticky);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  padding-block: var(--cb-space-3xs);
  padding-block-end: max(var(--cb-space-3xs), env(safe-area-inset-bottom));
  background-color: rgb(var(--cb-bg-rgb) / 0.92);
  color: var(--cb-fg);
  border-block-start: var(--cb-border-thin) solid var(--cb-line);
  /* O desfoque é o que faz a barra parecer material de sistema, e não uma
     tarja opaca colada por cima do conteúdo. */
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
}

.cb-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 50px;
  padding-block: var(--cb-space-3xs);
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-medium);
  line-height: 1;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-tab:hover,
.cb-tab:active {
  color: var(--cb-fg-muted);
}

.cb-tab__icon {
  position: relative;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
}

.cb-tab__icon svg {
  width: 24px;
  height: 24px;
}

.cb-tab[aria-current='page'] {
  color: var(--cb-fg-heading);
  font-weight: var(--cb-weight-bold);
}

/* Resposta imediata ao dedo: o alvo afunda no toque, como no iOS. */
.cb-tab:active .cb-tab__icon {
  transform: scale(0.88);
  transition: transform 90ms var(--cb-ease-out);
}

.cb-tab__badge {
  position: absolute;
  inset-block-start: -3px;
  inset-inline-end: -6px;
  min-width: 17px;
  height: 17px;
  padding-inline: 4px;
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-danger);
  color: var(--cb-white);
  font-size: 10px;
  font-weight: var(--cb-weight-bold);
  line-height: 17px;
  text-align: center;
}

/* A barra cobre a base: o conteúdo precisa de chão embaixo para o rodapé e
   os últimos botões não ficarem inalcançáveis. */
body {
  padding-block-end: calc(58px + env(safe-area-inset-bottom));
}

@media (min-width: 1024px) {
  .cb-tabbar { display: none; }
  body { padding-block-end: 0; }
}

/* --- Folha inferior --------------------------------------------------------
   No mobile o drawer do carrinho sobe de baixo, com pegador e cantos
   arredondados no topo. Empurra a decisão para perto do polegar e devolve o
   gesto natural de fechar (arrastar para baixo, aqui via botão/backdrop).
--------------------------------------------------------------------------- */
@media (max-width: 1023px) {
  .cb-cart {
    width: 100%;
    max-width: none;
    height: auto;
    max-height: 88dvh;
    margin: auto 0 0;
    border-start-start-radius: var(--cb-radius-lg);
    border-start-end-radius: var(--cb-radius-lg);
  }

  .cb-cart__inner {
    max-height: 88dvh;
    padding-block-start: var(--cb-space-2xs);
  }

  /* Pegador: o sinal universal de "isto é uma folha e pode ser arrastada". */
  .cb-cart__inner::before {
    content: '';
    display: block;
    width: 36px;
    height: 4px;
    margin: 0 auto var(--cb-space-2xs);
    border-radius: var(--cb-radius-pill);
    background-color: rgb(var(--cb-fg-rgb) / 0.22);
  }

  .cb-cart[open] {
    animation: cb-sheet-up var(--cb-duration-slow) var(--cb-ease-out);
  }
}

@keyframes cb-sheet-up {
  from { transform: translateY(14%); opacity: 0.6; }
  to { transform: translateY(0); opacity: 1; }
}

/* --- Toque -----------------------------------------------------------------
   Sem realce azul do WebKit e sem seleção acidental de texto ao segurar um
   controle. Duas marcas de "site" que denunciam na hora.
--------------------------------------------------------------------------- */
.cb-button,
.cb-add-round,
.cb-tab,
.cb-region,
.cb-city,
.cb-flavor,
.cb-kit,
.cb-stepper__button,
.cb-icon-button {
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  user-select: none;
}

/* --- Header que encolhe ----------------------------------------------------
   Ao descer, a barra do topo perde altura e o logo diminui — o conteúdo
   ganha tela, como na navigation bar do iOS. Controlado por data-scrolled,
   escrito por js/appshell.js.
--------------------------------------------------------------------------- */
@media (max-width: 1023px) {
  .cb-header__bar {
    transition:
      padding var(--cb-duration-base) var(--cb-ease-out),
      box-shadow var(--cb-duration-base) var(--cb-ease-out);
  }

  .cb-header[data-scrolled='true'] .cb-header__bar {
    padding-block: 2px;
    box-shadow: var(--cb-shadow-md);
  }

  .cb-header[data-scrolled='true'] .cb-header__logo {
    --cb-header-logo-height: 24px;
  }

  .cb-header__logo img {
    transition: height var(--cb-duration-base) var(--cb-ease-out);
  }
}

/* ===========================================================================
   OFERTA NO CARRINHO (order bump · cross-sell · downsell)
   ---------------------------------------------------------------------------
   Fica DENTRO do corpo rolável, logo abaixo das linhas — não no rodapé fixo.
   Encostada no botão de finalizar, viraria obstáculo entre o cliente e a
   compra; abaixo da lista, é convite que ele encontra ao revisar o pedido.
   =========================================================================== */
.cb-offer {
  display: grid;
  grid-template-columns: 56px 1fr;
  gap: var(--cb-space-2xs) var(--cb-space-sm);
  margin-block-start: var(--cb-space-md);
  padding: var(--cb-space-sm);
  border: var(--cb-border-thin) dashed var(--cb-accent);
  border-radius: var(--cb-radius-md);
  background-color: rgb(var(--cb-fg-rgb) / 0.04);
  animation: cb-offer-in var(--cb-duration-slow) var(--cb-ease-out);
}

@keyframes cb-offer-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

.cb-offer__media {
  width: 56px;
  height: 56px;
  border-radius: var(--cb-radius-sm);
  object-fit: cover;
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
}

.cb-offer__title {
  color: var(--cb-fg-heading);
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
  line-height: 1.25;
}

.cb-offer__text {
  margin-block-start: 2px;
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
  line-height: 1.35;
}

/* O botão ocupa a largura inteira na linha de baixo: alvo generoso no
   polegar e nenhuma disputa de espaço com o texto. */
.cb-offer__cta {
  grid-column: 1 / -1;
  width: 100%;
}

/* O downsell é consolo, não empurrão: some o tracejado de urgência. */
.cb-offer--downsell {
  border-style: solid;
  border-color: var(--cb-line);
}

/* ===========================================================================
   CARTÃO CLICÁVEL — link estendido
   ---------------------------------------------------------------------------
   O cartão inteiro leva à página do produto; só os controles escapam. A
   técnica é um pseudo-elemento do link do título esticado sobre o cartão:

     · para o leitor de tela existe UM link, com o nome do produto — e não
       um link na foto e outro no título, que fazem a leitura repetir;
     · para o dedo, o alvo é o cartão inteiro;
     · sabor e "Levar agora" sobem de camada e continuam clicáveis.

   Alternativa descartada: `<a>` envolvendo tudo. Botão dentro de link é
   HTML inválido e o clique no botão dispararia a navegação junto.
   =========================================================================== */
.cb-product {
  position: relative;
}

.cb-product__title a::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
}

.cb-product__title a {
  color: inherit;
  text-decoration: none;
}

/* Tudo que é ação própria fica acima da camada do link. */
.cb-product__flavors,
.cb-product__cta,
.cb-product .cb-add-round,
.cb-product__badge {
  position: relative;
  z-index: 2;
}

/* O cartão inteiro responde ao ponteiro, não só o texto. */
.cb-product:has(.cb-product__title a:hover) {
  transform: translateY(-4px);
  box-shadow: var(--cb-shadow-lg);
}

/* Foco de teclado no link precisa aparecer no CARTÃO, senão o anel some
   atrás da foto e ninguém sabe onde está. */
.cb-product:has(.cb-product__title a:focus-visible) {
  outline: var(--cb-focus-width) solid var(--cb-accent);
  outline-offset: 3px;
}

.cb-product__title a:focus-visible {
  outline: none;
}

/* ===========================================================================
   CARTÃO DE PRODUTO — padrão de aplicativo
   ---------------------------------------------------------------------------
   Cinco gestos da referência, na paleta da marca:

     1. DOIS PAINÉIS  mídia e corpo são blocos separados, com respiro entre
        eles — não um cartão único dividido por linha. O olho lê "foto" e
        "informação" como coisas distintas.
     2. PREÇO É O BOTÃO  em vez de "Comprar" + preço soltos, uma pílula
        vazada com ícone de sacola e o valor dentro. Uma decisão, um alvo.
     3. SELO NA JUNÇÃO  o badge cavalga a divisa entre os painéis. É o que
        costura os dois e dá o ar de composição, não de empilhamento.
     4. AÇÃO CIRCULAR  botão redondo flutuando no canto da foto.
     5. TIPOGRAFIA DE UI  --cb-ui-*: menor, mais pesada, tracking apertado.
   =========================================================================== */
.cb-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
}

/* --- Painel da mídia -------------------------------------------------------- */
.cb-card__media {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: var(--cb-radius-lg);
  overflow: hidden;
  background-color: var(--cb-cream-300);
}

.cb-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Ação circular sobre a foto (favoritar) */
.cb-card__fav {
  position: absolute;
  inset-block-start: var(--cb-space-2xs);
  inset-inline-end: var(--cb-space-2xs);
  z-index: 3;
  display: grid;
  place-items: center;
  /* 38 px era menor que o alvo de toque que o próprio sistema define, e num
     cartão cheio de área clicável quem erra o dedo abre o produto sem
     querer em vez de favoritar. */
  width: var(--cb-touch-target);
  height: var(--cb-touch-target);
  border-radius: 50%;
  background-color: var(--cb-white);
  color: var(--cb-coffee-600);
  box-shadow: var(--cb-shadow-sm);
  cursor: pointer;
  transition: transform var(--cb-duration-fast) var(--cb-ease-bounce);
}

.cb-card__fav svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
}

.cb-card__fav:active {
  transform: scale(0.88);
}

.cb-card__fav[aria-pressed='true'] svg {
  fill: currentColor;
  stroke: currentColor;
}

/* --- Selo cavalgando a divisa ---------------------------------------------
   `bottom: 0` + `translateY(50%)` deixa metade em cada painel. É o detalhe
   que costura os dois blocos.
--------------------------------------------------------------------------- */
.cb-card__badge {
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 50%;
  z-index: 3;
  transform: translate(-50%, 50%);
  padding: 5px var(--cb-space-sm);
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-yellow-500);
  color: var(--cb-coffee-600);
  font-size: var(--cb-ui-caption);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-ui-tracking);
  line-height: 1.35;
  white-space: nowrap;
  box-shadow: var(--cb-shadow-sm);
}

/* --- Painel do corpo -------------------------------------------------------- */
.cb-card__body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--cb-space-2xs);
  flex: 1;
  padding: var(--cb-space-md) var(--cb-space-sm) var(--cb-space-sm);
  border-radius: var(--cb-radius-lg);
  background-color: var(--cb-white);
  text-align: center;
}

.cb-card__title {
  color: var(--cb-coffee-600);
  font-size: var(--cb-ui-title);
  font-weight: var(--cb-weight-bold);
  line-height: var(--cb-ui-leading);
  letter-spacing: var(--cb-ui-tracking);
  text-wrap: balance;
}

.cb-card__title a {
  color: inherit;
  text-decoration: none;
}

/* O link do título cobre o cartão inteiro — mesma técnica do link estendido:
   um alvo grande para o dedo e um só link para o leitor de tela. */
.cb-card__title a::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
}

.cb-card__meta {
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-caption);
  line-height: 1.3;
}

.cb-card__compare {
  color: var(--cb-mud-400);
  font-size: var(--cb-ui-caption);
}

/* --- O preço É o botão -----------------------------------------------------
   Pílula vazada, ícone de sacola, valor dentro. Some o par redundante
   "R$ 169,90" + botão "Comprar": um alvo, uma decisão.
--------------------------------------------------------------------------- */
.cb-price-button {
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--cb-space-2xs);
  width: 100%;
  min-height: 46px;
  margin-block-start: auto;
  padding-inline: var(--cb-space-md);
  border: 1.5px solid var(--cb-coffee-600);
  border-radius: var(--cb-radius-pill);
  background-color: transparent;
  color: var(--cb-coffee-600);
  font-family: var(--cb-font-brand);
  font-size: var(--cb-ui-price);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-ui-tracking);
  line-height: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition:
    background-color var(--cb-duration-base) var(--cb-ease-out),
    color var(--cb-duration-base) var(--cb-ease-out),
    transform var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-price-button svg {
  width: 19px;
  height: 19px;
  flex-shrink: 0;
}

.cb-price-button:hover {
  background-color: var(--cb-coffee-600);
  color: var(--cb-cream-200);
}

.cb-price-button:active {
  transform: scale(0.985);
}

/* Modo link (home): o mesmo botão, só que é um <a> que leva à página do
   kit. O ícone de seta vai DEPOIS do texto — é para onde a pessoa vai. */
.cb-price-button--link {
  padding-inline: var(--cb-space-sm);
  font-size: var(--cb-text-sm);
  white-space: nowrap;            /* "Comprar o kit · R$ 219,00" numa linha só */
  text-decoration: none;
}

.cb-price-button--link svg {
  transition: transform var(--cb-duration-fast, 0.15s) ease;
}

.cb-price-button--link:hover svg {
  transform: translateX(3px);
}

/* O aviso de sabor que substitui as pastilhas clicáveis no modo link.
   Não é controle — é o recado de que a escolha existe e acontece na página
   do kit. Por isso é texto miúdo e sem borda: pastilha com cara de botão
   que não faz nada frustra mais que a falta dela. */
.cb-card__sabores {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--cb-space-3xs);
  margin: 0;
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-sm);
}

.cb-card__sabores .cb-flavor__swatch {
  width: 22px;
  height: 22px;
}

.cb-card__sabores .cb-flavor__swatch + .cb-flavor__swatch {
  margin-inline-start: -8px;      /* as duas bolinhas encostadas, como par */
  box-shadow: 0 0 0 2px var(--cb-bg);
}

.cb-card__sabores span {
  margin-inline-start: var(--cb-space-2xs);
}

/* Preenchido: usado quando o cartão já é o destaque da grade. */
.cb-price-button--solid {
  background-color: var(--cb-coffee-600);
  color: var(--cb-cream-200);
}

.cb-price-button--solid:hover {
  background-color: var(--cb-coffee-700);
  color: var(--cb-cream-200);
}

/* Estados: reaproveitam a mecânica do botão padrão. */
.cb-price-button[data-state='loading'] .cb-price-button__label,
.cb-price-button[data-state='loading'] svg {
  opacity: 0;
}

.cb-price-button[data-state='loading']::after {
  content: '';
  position: absolute;
  inset: 0;
  width: 1.1em;
  height: 1.1em;
  margin: auto;
  border: 2px solid currentColor;
  border-block-start-color: transparent;
  border-radius: 50%;
  animation: cb-spin 0.6s linear infinite;
}

.cb-price-button[data-state='done'] {
  background-color: var(--cb-success);
  border-color: var(--cb-success);
  color: var(--cb-white);
}

.cb-price-button[data-state='done'] .cb-price-button__label::before {
  content: '✓  ';
}

/* Rendimento no cartão — achado 2 da auditoria de conversão.
   Fica logo abaixo do preço riscado e acima do sabor: é informação de
   DECISÃO, não detalhe técnico, e precisa ser lida antes de a pessoa escolher
   qualquer coisa. Discreta na cor, firme no peso — não compete com o preço,
   mas não passa despercebida. */
.cb-card__yield {
  margin-block: calc(var(--cb-space-3xs) * -1) 0;
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-caption);
  font-weight: var(--cb-weight-medium);
  letter-spacing: var(--cb-ui-tracking);
}

/* O preço no Pix. Verde de "você ganha", não marrom de rodapé: ele é um
   argumento de venda, e o motivo de estar aqui é justamente ter ficado
   escondido atrás do seletor de pagamento até agora. */
.cb-card__pix {
  margin-block: 2px 0;
  color: var(--cb-success);
  font-size: var(--cb-ui-label);
  font-weight: var(--cb-weight-bold);
}

.cb-card__pix span {
  font-weight: var(--cb-weight-medium);
  opacity: 0.85;
}

/* A conta da dose INTENSA — a que corresponde aos 20 g da manchete. Ela é a
   mais cara das duas, e é por isso que precisa estar visível: esconder o
   número que confirma a promessa é o que abre a brecha entre o preço e o
   claim. Fica logo abaixo da outra, sem competir com ela. */
.cb-card__yield--forte {
  margin-block-start: 2px;
  color: var(--cb-fg-muted);
  font-weight: var(--cb-weight-regular);
}

.cb-card__yield-nota {
  display: block;
  font-size: var(--cb-text-2xs);
  opacity: 0.8;
}

/* A dose em que os números valem, colada nos números do mosaico. Ver achado
   3: 20 g e 200 mg só existem na porção de 30 g. */
.cb-ativos-nota {
  margin-block-start: var(--cb-space-sm);
  max-width: var(--cb-measure-body);
  line-height: 1.35;
}

/* --- Grade / prateleira ------------------------------------------------------
   No mobile os cartões deixam de ser grade e viram PRATELEIRA que desliza.

   Não é preferência: com duas colunas num iPhone o cartão fica com 167 px, e
   as duas pastilhas de sabor precisam de 162 px só elas — sobram 151 px de
   corpo. Elas empilhavam, o cartão crescia, e mesmo assim só apareciam dois
   dos quatro kits por vez. Ou seja, a grade nem entregava a comparação que a
   seção promete: quem compara é a linha "R$ 179,00 por pote", não ver os
   quatro juntos.

   Deslizando, o cartão ganha ~68 vw (uns 260 px), as pastilhas voltam a caber
   lado a lado e o gesto é o de qualquer prateleira de app. A partir de 768 px
   volta a ser grade, onde há largura de sobra.
--------------------------------------------------------------------------- */
.cb-card-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--cb-space-sm);
}

@media (max-width: 767px) {
  .cb-card-grid {
    display: flex;
    gap: var(--cb-space-sm);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    /* Sem isto, deslizar até o fim da prateleira encadeia no scroll da página
       — no iOS vira o gesto de voltar. */
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;

    /* Sangria: a prateleira corre de borda a borda como em app, mas o
       primeiro cartão nasce alinhado com o texto da seção. O padding recria
       a margem que o negativo tirou, e o scroll-padding faz o encaixe parar
       no mesmo lugar. */
    margin-inline: calc(var(--cb-space-md) * -1);
    padding-inline: var(--cb-space-md);
    scroll-padding-inline-start: var(--cb-space-md);

    /* Espaço para a sombra e para o selo que cavalga a borda do cartão. */
    padding-block: var(--cb-space-3xs);
  }

  .cb-card-grid::-webkit-scrollbar { display: none; }

  .cb-card-grid > * {
    flex: 0 0 68vw;
    max-width: 300px;
    scroll-snap-align: start;
  }
}

@media (min-width: 768px) {
  .cb-card-grid { grid-template-columns: repeat(3, 1fr); }
}

@media (min-width: 1024px) {
  .cb-card-grid { grid-template-columns: repeat(4, 1fr); }
  .cb-card__title { font-size: var(--cb-ui-title); }
}

/* GRADES DE TRÊS E DE DOIS.

   A vitrine deixou de ser uma fileira de quatro: os três potes ficam em
   cima, em três colunas largas, e os sachês descem para o bloco "para
   provar", em duas. As colunas do bloco de baixo têm a MESMA largura das de
   cima — o texto ocupa o lugar da primeira coluna e os dois cartões caem
   embaixo da segunda e da terceira —, então a página lê como uma grade só,
   e não como duas listas de tamanhos diferentes. */
@media (min-width: 768px) {
  .cb-card-grid--3 { grid-template-columns: repeat(3, 1fr); }
  .cb-card-grid--2 { grid-template-columns: repeat(2, 1fr); }
}

/* --- Bloco "quer provar antes?" ---------------------------------------------
   Os sachês, abaixo dos potes e com menos peso: título menor, uma linha
   separando, e o texto ao lado dos cartões no desktop em vez de um cabeçalho
   de seção inteiro. Quem decide o destaque da página é a grade de cima. */
.cb-prove {
  display: grid;
  gap: var(--cb-space-md);
  margin-block-start: var(--cb-space-xl);
  padding-block-start: var(--cb-space-xl);
  border-block-start: var(--cb-border-thin) solid var(--cb-line);
}

.cb-prove__texto > * + * {
  margin-block-start: var(--cb-space-2xs);
}

.cb-prove__titulo {
  font-size: var(--cb-text-h3);
}

@media (min-width: 1024px) {
  .cb-prove {
    /* As mesmas três colunas e o mesmo vão da grade de cima: o texto fica na
       primeira e a grade dos sachês ocupa as outras duas, então cada cartão
       daqui cai exatamente embaixo de um pote. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: var(--cb-space-sm);
    align-items: center;
  }

  .cb-prove > .cb-card-grid {
    grid-column: 2 / -1;
  }

  .cb-prove__texto {
    padding-inline-end: var(--cb-space-lg);
  }
}

/* Em telas estreitas o cartão fica com duas colunas: aperta a tipografia
   para o nome não quebrar em quatro linhas. */
@media (max-width: 400px) {
  .cb-card__title { font-size: var(--cb-ui-title-sm); }
  .cb-price-button { font-size: var(--cb-ui-title-sm); min-height: 42px; }
  .cb-card__body { padding-inline: var(--cb-space-2xs); }
}

/* Sabor dentro do cartão de app: compacto, centralizado, sem moldura de
   fieldset — vira um par de pastilhas discretas sob o nome. */
.cb-card .cb-flavors {
  justify-content: center;
  gap: 4px;
  padding: 0;
  border: 0;
  margin: 0;
}

.cb-card .cb-flavor {
  position: relative;
  z-index: 2;
  gap: 4px;
  padding: 2px 8px 2px 2px;
  font-size: var(--cb-ui-caption);
}

.cb-card .cb-flavor__swatch {
  width: 20px;
  height: 20px;
}

/* --- Correções do cartão de app --------------------------------------------
   O selo cavalga a divisa entre os painéis, então nada no caminho pode
   recortá-lo. Em vez de mover o selo para fora (e ter de calcular onde fica
   a divisa), tiro o recorte do PAINEL e deixo a FOTO se arredondar sozinha:
   o painel para de cortar, a foto continua com o canto certo, e o selo
   escapa naturalmente. Uma linha a menos e nenhuma conta.
--------------------------------------------------------------------------- */
.cb-card__media {
  overflow: visible;
}

.cb-card__media img {
  border-radius: var(--cb-radius-lg);
}

/* Em dois cartões por linha não cabe "Caramelo salgado" escrito. O sabor
   vira só a bolinha; o nome fica no aria-label, no title e na página do
   produto. Bolinha basta para reconhecer — é o que a referência faz. */
.cb-card .cb-flavors {
  gap: 6px;
  flex-wrap: nowrap;
  justify-content: center;
  padding: 0;
  border: 0;
  margin: 0;
}

/* Bolinha + nome. O curto ("Caramelo") cabe em dois cartões por linha; o
   completo ("Caramelo salgado") fica no aria-label, no title e na página do
   produto. Só a bolinha era econômico demais: sabor é a primeira coisa que a
   pessoa quer saber, e cor de swatch não se lê. */
.cb-card .cb-flavor {
  position: relative;
  z-index: 2;
  gap: 5px;
  padding: 2px 9px 2px 2px;
  font-size: var(--cb-ui-caption);
  line-height: 1.2;
}

.cb-flavor__name { white-space: nowrap; }

.cb-card .cb-flavor__swatch {
  width: 22px;
  height: 22px;
  margin: 0;
}

/* ===========================================================================
   LINHA DE CARRINHO — padrão de aplicativo
   ---------------------------------------------------------------------------
   Mesma gramática do cartão: a miniatura é um painel à parte e o conteúdo é
   outro. Ganhos concretos sobre a linha antiga (foto colada no texto com um
   filete embaixo):

     · a foto vira âncora visual da linha, e o dedo tem um alvo maior;
     · o preço em pílula repete o "preço é botão" da grade, então o mesmo
       elemento significa a mesma coisa em toda a loja;
     · quantidade como dropdown ocupa um terço do stepper e some com a
       ambiguidade de "− 1 +" em lista longa.
   =========================================================================== */
.cb-line {
  display: grid;
  grid-template-columns: 84px 1fr;
  gap: var(--cb-space-2xs);
  align-items: stretch;
}

.cb-line__media {
  aspect-ratio: 1 / 1;
  border-radius: var(--cb-radius-md);
  overflow: hidden;
  background-color: var(--cb-cream-300);
}

.cb-line__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cb-line__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--cb-space-2xs);
  padding: var(--cb-space-2xs) var(--cb-space-sm);
  border-radius: var(--cb-radius-md);
  background-color: var(--cb-white);
  min-width: 0;
}

.cb-line__name {
  color: var(--cb-coffee-600);
  font-size: var(--cb-ui-title-sm);
  font-weight: var(--cb-weight-bold);
  line-height: var(--cb-ui-leading);
  letter-spacing: var(--cb-ui-tracking);
  text-decoration: none;
  /* Duas linhas no máximo: nome longo não pode empurrar os controles para
     fora da linha. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.cb-line__row {
  display: flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  flex-wrap: wrap;
}

/* Preço em pílula — o mesmo sinal do botão-preço da grade. Aqui é rótulo,
   não botão: sem cursor, sem hover. */
.cb-line__price {
  display: inline-flex;
  align-items: center;
  padding: 4px var(--cb-space-sm);
  border: 1.5px solid var(--cb-coffee-600);
  border-radius: var(--cb-radius-pill);
  color: var(--cb-coffee-600);
  font-size: var(--cb-ui-body);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-ui-tracking);
  white-space: nowrap;
}

.cb-line__variant {
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-caption);
  line-height: 1.3;
}

.cb-line__actions {
  display: flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  margin-inline-start: auto;
}

/* Quantidade como dropdown compacto */
.cb-qty-select {
  display: inline-flex;
  align-items: center;
  height: var(--cb-touch-target);
  padding-inline: var(--cb-space-2xs) var(--cb-space-3xs);
  border: 0;
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-cream-300);
  color: var(--cb-coffee-600);
  font-family: var(--cb-font-brand);
  font-size: var(--cb-ui-body);
  font-weight: var(--cb-weight-bold);
  cursor: pointer;
  appearance: none;
  /* seta desenhada no próprio fundo: um elemento a menos no DOM */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5' stroke='%23542915' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 6px center;
  background-size: 12px;
  padding-inline-end: 22px;
}

/* Lixeira em círculo */
.cb-line__remove {
  display: grid;
  place-items: center;
  width: var(--cb-touch-target);
  height: var(--cb-touch-target);
  flex-shrink: 0;
  border-radius: 50%;
  background-color: var(--cb-cream-300);
  color: var(--cb-coffee-500);
  cursor: pointer;
  transition:
    background-color var(--cb-duration-fast) var(--cb-ease-out),
    color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-line__remove svg { width: 16px; height: 16px; }

.cb-line__remove:hover {
  background-color: var(--cb-danger);
  color: var(--cb-white);
}

.cb-line[data-removing='true'] {
  opacity: 0.4;
  pointer-events: none;
  transition: opacity var(--cb-duration-base) var(--cb-ease-out);
}

.cb-lines {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  list-style: none;
  padding: 0;
  margin: 0;
}

/* ===========================================================================
   PDP — padrão de aplicativo
   ---------------------------------------------------------------------------
   Quatro peças da referência: abas em pílula no topo, pontinhos na galeria,
   escolha do kit em pílulas e barra de compra fixa com o preço-botão.
   =========================================================================== */

/* --- Abas em pílula --------------------------------------------------------
   Rolam na horizontal quando não cabem. `scroll-snap` faz cada aba parar
   alinhada, como a barra de categorias de um app.
--------------------------------------------------------------------------- */
.cb-pills {
  display: flex;
  gap: var(--cb-space-2xs);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  list-style: none;
  padding: 0 0 var(--cb-space-2xs);
  margin: 0 calc(var(--cb-pad-inline) * -1) var(--cb-space-md);
  padding-inline: var(--cb-pad-inline);
}

.cb-pills::-webkit-scrollbar { display: none; }

.cb-pill-tab {
  flex: 0 0 auto;
  scroll-snap-align: start;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: var(--cb-touch-target);
  padding-inline: var(--cb-space-md);
  border: 0;
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-white);
  color: var(--cb-coffee-600);
  font-family: var(--cb-font-brand);
  font-size: var(--cb-ui-label);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-ui-tracking);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--cb-duration-fast) var(--cb-ease-out),
              color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-pill-tab__count {
  color: var(--cb-mud-500);
  font-weight: var(--cb-weight-medium);
}

.cb-pill-tab[aria-selected='true'] {
  background-color: var(--cb-coffee-600);
  color: var(--cb-cream-200);
}

.cb-pill-tab[aria-selected='true'] .cb-pill-tab__count {
  color: rgb(245 234 220 / 0.7);
}

/* --- Pontinhos da galeria --------------------------------------------------- */
.cb-dots {
  display: flex;
  justify-content: center;
  gap: 6px;
  padding-block-start: var(--cb-space-2xs);
  list-style: none;
  margin: 0;
}

.cb-dot {
  width: 6px;
  height: 6px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: rgb(var(--cb-fg-rgb) / 0.22);
  cursor: pointer;
  transition: width var(--cb-duration-base) var(--cb-ease-out),
              background-color var(--cb-duration-base) var(--cb-ease-out);
}

/* O ponto ativo alonga em vez de só mudar de cor — o mesmo sinal que o iOS
   usa em paginação, e legível mesmo para quem não distingue as duas cores. */
.cb-dot[aria-current='true'] {
  width: 18px;
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-coffee-600);
}

/* --- Escolha do kit em pílulas ---------------------------------------------
   Substitui a lista de rádios no mobile: ocupa uma linha, é tocável e mostra
   as quatro opções de uma vez.
--------------------------------------------------------------------------- */
.cb-choice {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-2xs);
  padding: 0;
  border: 0;
  margin: 0;
}

.cb-choice__option {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  /* Centrado na vertical: as opções COM selo têm três linhas e as sem selo
     têm duas, e sem isto as de duas linhas encostavam no topo enquanto as
     outras preenchiam — a fileira inteira ficava desalinhada. */
  justify-content: center;
  gap: 1px;
  min-height: 52px;
  padding: var(--cb-space-2xs) var(--cb-space-md);
  border-radius: var(--cb-radius-md);
  /* Contorno em TODAS as opções: sem ele, as não escolhidas eram só uma
     mancha um tom acima do fundo creme e não pareciam clicáveis — só a
     selecionada tinha forma. A borda é o que diz "isto é um botão". */
  border: var(--cb-border-thin) solid rgb(var(--cb-fg-rgb) / 0.18);
  background-color: var(--cb-cream-300);
  color: var(--cb-coffee-600);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--cb-duration-fast) var(--cb-ease-out),
              color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-choice__option input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.cb-choice__name {
  /* Um ponto acima do resto do controle: é o que a pessoa lê para escolher
     entre as quatro opções. */
  font-size: var(--cb-ui-body);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-ui-tracking);
  white-space: nowrap;
}

.cb-choice__meta {
  font-size: var(--cb-ui-caption);
  opacity: 0.72;
  white-space: nowrap;
}

.cb-choice__option:has(input:checked) {
  border-color: var(--cb-coffee-600);
  background-color: var(--cb-coffee-600);
  color: var(--cb-cream-200);
}

/* Passar o dedo/mouse já mostra que responde. */
.cb-choice__option:hover:not(:has(input:checked)) {
  border-color: rgb(var(--cb-fg-rgb) / 0.42);
  background-color: var(--cb-cream-200);
}

.cb-choice__option:has(input:focus-visible) {
  outline: var(--cb-focus-width) solid var(--cb-accent);
  outline-offset: 2px;
}

/* --- Barra de compra fixa ---------------------------------------------------
   Preço antigo riscado à esquerda, preço-botão à direita. Fica sobre a barra
   de abas no mobile — a decisão de compra vem antes da navegação.
--------------------------------------------------------------------------- */
.cb-buybar-app {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: calc(var(--cb-layer-sticky) + 1);
  display: flex;
  align-items: center;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-2xs) var(--cb-pad-inline);
  padding-block-end: max(var(--cb-space-2xs), env(safe-area-inset-bottom));
  background-color: rgb(var(--cb-bg-rgb) / 0.94);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  border-block-start: var(--cb-border-thin) solid var(--cb-line);
  transform: translateY(110%);
  transition: transform var(--cb-duration-slow) var(--cb-ease-out);
}

.cb-buybar-app[data-visible='true'] {
  transform: translateY(0);
}

.cb-buybar-app__compare {
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-body);
  text-decoration: line-through;
  white-space: nowrap;
}

.cb-buybar-app .cb-price-button {
  margin-inline-start: auto;
  width: auto;
  min-width: 62%;
  background-color: var(--cb-coffee-600);
  color: var(--cb-cream-200);
}

/* Com a barra de compra em cena, a de abas sai: duas barras empilhadas
   comem metade da tela e competem pelo polegar. */
body:has(.cb-buybar-app[data-visible='true']) .cb-tabbar {
  transform: translateY(100%);
  transition: transform var(--cb-duration-slow) var(--cb-ease-out);
}

.cb-tabbar {
  transition: transform var(--cb-duration-slow) var(--cb-ease-out);
}

@media (min-width: 1024px) {
  .cb-buybar-app { display: none; }
}

/* --- Painéis de conteúdo da PDP --------------------------------------------- */
.cb-panel[hidden] { display: none; }

/* A linha de controles não pode quebrar conforme o tamanho do texto — duas
   linhas do carrinho ficavam com alturas diferentes só porque um sabor tem
   nome mais curto que o outro. Agora nada quebra: a variante encolhe e corta
   com reticências, e os controles ficam sempre ancorados à direita. */
.cb-line__row {
  flex-wrap: nowrap;
  /* Só preço e controles aqui. Sem texto disputando espaço, `nowrap` deixou
     de custar informação — as ações vão para a direita e o preço fica onde
     está, em qualquer largura. */
  justify-content: space-between;
}

/* `.cb-line__variant` não vive mais dentro de `.cb-line__row` — o flex que
   o encolhia saiu junto. Ver o comentário em cart-ui.js. */

.cb-line__price,
.cb-line__actions {
  flex: 0 0 auto;
}

/* ===========================================================================
   PDP — CORREÇÕES DE HIERARQUIA
   ---------------------------------------------------------------------------
   O diagnóstico da versão anterior, medido na página:

     · o seletor de sabor ficava a 1025 px do topo — mais de uma tela inteira
       de rolagem antes de a pessoa descobrir que existe caramelo salgado;
     · as abas de conteúdo ocupavam a primeira dobra e "Como tomar" quebrava
       em duas linhas;
     · a galeria comia 453 px + miniaturas, sobrando nada para a decisão;
     · as pílulas de kit quebravam com "3 potes" órfão numa segunda linha.

   As quatro coisas eram a mesma doença: conteúdo de apoio disputando espaço
   com a decisão de compra.
   =========================================================================== */

/* --- Sabor em destaque, colado na galeria ---------------------------------- */
.cb-flavor-pick {
  margin-block-start: var(--cb-space-md);
}

.cb-flavor-pick__label {
  margin-block-end: var(--cb-space-2xs);
  color: var(--cb-coffee-600);
  font-size: var(--cb-ui-title-sm);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-ui-tracking);
}

.cb-flavor-pick__label span {
  color: var(--cb-mud-500);
  font-weight: var(--cb-weight-regular);
}

/* Gramatura e doses do sabor escolhido. Fica abaixo das pastilhas porque é
   consequência da escolha, não outro campo a preencher. */
.cb-flavor-pick__spec {
  margin-block-start: var(--cb-space-2xs);
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-caption);
  font-weight: var(--cb-weight-medium);
  letter-spacing: var(--cb-ui-tracking);
}

/* Pastilhas grandes: aqui o sabor é a decisão, não um detalhe. */
.cb-flavors--big {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--cb-space-2xs);
  padding: 0;
  border: 0;
  margin: 0;
}

/* A COMBINAÇÃO OCUPA A LINHA INTEIRA. O nome dela é longo ("2 Caramelo +
   1 Avelã") e ela carrega duas bolinhas em vez de uma — em meia coluna o
   texto quebra. Em linha cheia ela também é a que mais chama atenção, que é
   o que se quer da opção que a pessoa não imaginou que existia. */
/* Composição fixa (Mix de sachês): uma pastilha só, que informa em vez de
   pedir escolha. Sem cursor de clique e sem hover — não há o que trocar. */
.cb-flavors--fixo .cb-flavor {
  grid-column: 1 / -1;
  cursor: default;
}

.cb-flavors--fixo .cb-flavor:hover {
  background-color: var(--cb-white);
}

.cb-flavors--big .cb-flavor--misto {
  grid-column: 1 / -1;
}

/* Duas bolinhas encostadas, como moedas empilhadas: lê como "vem os dois"
   sem precisar do texto. A segunda monta na primeira porque lado a lado elas
   roubariam a largura do rótulo. */
.cb-flavor--misto .cb-flavor__swatch + .cb-flavor__swatch {
  margin-inline-start: -14px;
  box-shadow: 0 0 0 2px var(--cb-bg);
}

.cb-flavors--big .cb-flavor {
  justify-content: flex-start;
  gap: var(--cb-space-2xs);
  padding: var(--cb-space-2xs);
  border-radius: var(--cb-radius-md);
  background-color: var(--cb-white);
  font-size: var(--cb-ui-label);
  font-weight: var(--cb-weight-bold);
  line-height: 1.2;
}

.cb-flavors--big .cb-flavor__swatch {
  width: 40px;
  height: 40px;
  flex-shrink: 0;
}

.cb-flavors--big .cb-flavor:has(input:checked) {
  outline: var(--cb-border-thick) solid var(--cb-coffee-600);
  outline-offset: -2px;
}

/* --- Galeria mais contida no mobile ---------------------------------------
   A foto não precisa de meia tela para vender: 62svh deixa o preço e o sabor
   entrarem na mesma dobra.
--------------------------------------------------------------------------- */
@media (max-width: 767px) {
  .cb-gallery__main {
    max-height: 62svh;
  }

  /* Com os pontinhos abaixo, as miniaturas viram redundância no mobile. */
  .cb-gallery__thumbs {
    display: none;
  }
}

/* --- Kit em grade, não em fila que quebra ---------------------------------
   `flex-wrap` deixava "3 potes" órfão numa segunda linha. Grade de duas
   colunas dá quatro opções alinhadas em dois pares.
--------------------------------------------------------------------------- */
.cb-choice {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--cb-space-2xs);
}

.cb-choice__option {
  padding-inline: var(--cb-space-2xs);
}

@media (min-width: 768px) {
  .cb-choice { grid-template-columns: repeat(4, 1fr); }
}

/* --- Abas de conteúdo, agora fora da dobra de compra ----------------------- */
.cb-pills {
  margin-block-end: 0;
}

.cb-pill-tab {
  white-space: nowrap;
}

/* O breadcrumb serve à navegação em desktop; no mobile ocupa uma linha
   inteira acima da dobra para quem, na maioria das vezes, chegou direto de
   um anúncio e vai voltar pelo gesto do sistema. */
@media (max-width: 767px) {
  .cb-breadcrumb { display: none; }
}

/* Sabor e tamanho são a mesma decisão — variantes do mesmo produto — então
   moram juntos na coluna de compra, nesta ordem: nome, avaliação, preço,
   sabor, tamanho. Antes o sabor ficava dentro da galeria e, no desktop
   (galeria em linha), virava uma terceira coluna flutuando no vazio.

   A ordem também importa: quem chega precisa saber QUE produto é antes de
   escolher sabor. Subir o seletor para o topo respondia "tem qual sabor?"
   antes de "o que é isto?", que é a pergunta errada primeiro. */
}

/* ===========================================================================
   PDP — MÉTRICAS, AVALIAÇÕES E LEVE JUNTO
   =========================================================================== */

/* --- Estrelas --------------------------------------------------------------
   Uma peça só, usada no resumo e em cada avaliação. O preenchimento é uma
   máscara por porcentagem: 4,9 mostra a quinta estrela quase cheia em vez de
   arredondar para 5 — arredondar seria mentir por um décimo.
--------------------------------------------------------------------------- */
.cb-stars {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-3xs);
}

.cb-stars__track {
  position: relative;
  display: inline-block;
  font-size: var(--cb-ui-body);
  line-height: 1;
  letter-spacing: 1px;
  color: rgb(var(--cb-fg-rgb) / 0.2);
}

.cb-stars__track::before { content: '\2605\2605\2605\2605\2605'; }

.cb-stars__fill {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  overflow: hidden;
  white-space: nowrap;
  color: var(--cb-gold-500);
}

.cb-stars__fill::before { content: '\2605\2605\2605\2605\2605'; }

.cb-stars__count {
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-caption);
}

.cb-stars--lg .cb-stars__track { font-size: 1.25rem; }

/* --- Resumo das avaliações -------------------------------------------------- */
.cb-rating {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--cb-space-md);
  align-items: center;
  padding: var(--cb-space-md);
  border-radius: var(--cb-radius-md);
  background-color: var(--cb-white);
  margin-block-end: var(--cb-space-md);
}

.cb-rating__score {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.cb-rating__number {
  color: var(--cb-coffee-600);
  font-size: 2.25rem;
  font-weight: var(--cb-weight-bold);
  line-height: 1;
}

.cb-rating__total {
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-caption);
  white-space: nowrap;
}

.cb-rating__bars {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.cb-bar {
  display: grid;
  grid-template-columns: 12px 1fr 26px;
  align-items: center;
  gap: var(--cb-space-2xs);
  font-size: var(--cb-ui-caption);
  color: var(--cb-mud-500);
}

.cb-bar__track {
  /* <span> é inline por padrão e ignora height — a barra nascia sem altura
     e o preenchimento não aparecia. */
  display: block;
  height: 6px;
  border-radius: var(--cb-radius-pill);
  background-color: rgb(var(--cb-fg-rgb) / 0.1);
  overflow: hidden;
}

.cb-bar__fill {
  display: block;
  height: 100%;
  border-radius: inherit;
  background-color: var(--cb-gold-500);
}

/* --- Avaliação individual --------------------------------------------------- */
.cb-review-list {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  list-style: none;
  padding: 0;
  margin: 0;
}

.cb-review {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-3xs);
  padding: var(--cb-space-md);
  border-radius: var(--cb-radius-md);
  background-color: var(--cb-white);
}

.cb-review__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--cb-space-2xs);
  flex-wrap: wrap;
}

.cb-review__who {
  color: var(--cb-coffee-600);
  font-size: var(--cb-ui-title-sm);
  font-weight: var(--cb-weight-bold);
}

.cb-review__detail,
.cb-review__date {
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-caption);
  font-weight: var(--cb-weight-regular);
}

.cb-review__text {
  color: var(--cb-coffee-600);
  font-size: var(--cb-ui-body);
  line-height: 1.45;
  max-width: none;
}

.cb-review__foot {
  display: flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  flex-wrap: wrap;
  margin-block-start: 2px;
}

.cb-review__tag {
  padding: 2px var(--cb-space-2xs);
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-cream-300);
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-caption);
}

.cb-review__verified {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  color: var(--cb-success);
  font-size: var(--cb-ui-caption);
  font-weight: var(--cb-weight-bold);
}

/* Aviso de dado de exemplo — visível de propósito. Avaliação inventada que
   escapa para produção é publicidade enganosa; o aviso sai junto com os
   dados falsos, não antes. */
.cb-review-warning {
  display: flex;
  gap: var(--cb-space-2xs);
  padding: var(--cb-space-sm) var(--cb-space-md);
  border: var(--cb-border-thin) dashed var(--cb-danger);
  border-radius: var(--cb-radius-md);
  background-color: rgb(243 2 2 / 0.05);
  color: var(--cb-coffee-700);
  font-size: var(--cb-ui-caption);
  line-height: 1.4;
  margin-block-end: var(--cb-space-md);
}

/* --- LEVE JUNTO — order bump na página de produto --------------------------
   Diferente do order bump do carrinho: lá a oferta é subir de tamanho, aqui
   é levar outro item. Fica ANTES do botão principal, porque somar ao pedido
   se decide enquanto ele está sendo montado — depois do "adicionar" a
   atenção já foi embora.
--------------------------------------------------------------------------- */
.cb-together {
  margin-block-start: var(--cb-space-md);
}

.cb-together__title {
  margin-block-end: var(--cb-space-2xs);
  color: var(--cb-coffee-600);
  font-size: var(--cb-ui-label);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  text-transform: uppercase;
}

.cb-together__list {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  list-style: none;
  padding: 0;
  margin: 0;
}

.cb-together__item {
  display: grid;
  grid-template-columns: 54px 1fr auto;
  align-items: center;
  gap: var(--cb-space-2xs);
  padding: var(--cb-space-2xs);
  border-radius: var(--cb-radius-md);
  background-color: var(--cb-white);
}

.cb-together__media {
  width: 54px;
  height: 54px;
  border-radius: var(--cb-radius-sm);
  object-fit: cover;
  background-color: var(--cb-cream-300);
}

.cb-together__name {
  display: block;
  color: var(--cb-coffee-600);
  font-size: var(--cb-ui-label);
  font-weight: var(--cb-weight-bold);
  line-height: 1.2;
}

.cb-together__price {
  display: block;
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-caption);
}

.cb-together__add {
  min-height: var(--cb-touch-target);
  padding-inline: var(--cb-space-md);
  border: 1.5px solid var(--cb-coffee-600);
  border-radius: var(--cb-radius-pill);
  background: transparent;
  color: var(--cb-coffee-600);
  font-family: var(--cb-font-brand);
  font-size: var(--cb-ui-caption);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  text-transform: uppercase;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--cb-duration-fast) var(--cb-ease-out),
              color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-together__add:hover {
  background-color: var(--cb-coffee-600);
  color: var(--cb-cream-200);
}

.cb-together__add[data-state='done'] {
  background-color: var(--cb-success);
  border-color: var(--cb-success);
  color: var(--cb-white);
}

/* --- Galeria vertical de fotos --------------------------------------------- */
.cb-photostack {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--cb-space-2xs);
  list-style: none;
  padding: 0;
  margin: 0;
}

.cb-photostack img {
  width: 100%;
  border-radius: var(--cb-radius-md);
  object-fit: cover;
  aspect-ratio: 4 / 3;
  background-color: var(--cb-cream-300);
}

@media (min-width: 768px) {
  .cb-photostack { grid-template-columns: repeat(2, 1fr); }
  .cb-photostack li:first-child { grid-column: 1 / -1; }
  .cb-photostack li:first-child img { aspect-ratio: 21 / 9; }
}

/* Link do resumo de estrelas no topo da PDP: leva à seção de avaliações. */
.cb-rating-link {
  display: inline-flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  text-decoration: none;
}

.cb-rating-link:hover .cb-stars__count {
  text-decoration: underline;
}

.cb-pdp__desc {
  color: var(--cb-coffee-600);
  font-size: var(--cb-ui-body);
  line-height: 1.5;
  max-width: 48ch;
}

/* O selo do produto é pílula, não faixa: dentro de um .cb-stack (flex column,
   align-items: stretch por padrão) ele esticava na largura toda e virava
   barra. `align-self: start` devolve o tamanho do conteúdo. */
.cb-buybox [data-pdp-badge] {
  align-self: start;
}

/* Selo de desconto ao lado do preço na PDP. Antes herdava de .cb-product,
   componente que a página já não usa — dependência invisível que quebraria
   no dia em que aquele bloco fosse removido. */
.cb-buybox__off {
  padding: 3px var(--cb-space-2xs);
  border-radius: var(--cb-radius-xs);
  background-color: var(--cb-yellow-500);
  color: var(--cb-coffee-600);
  font-size: var(--cb-ui-caption);
  font-weight: var(--cb-weight-bold);
  white-space: nowrap;
}

/* As duas pastilhas somam 162px. Isso empilhava no mobile porque o cartão
   tinha 167px de largura — grade de duas colunas — e sobravam 151px de
   corpo.

   Com a prateleira deslizante o cartão passou a ~260px e elas voltaram a
   caber lado a lado, que era sempre o desenho certo: sabor é UMA escolha
   entre duas, e escolha lado a lado se lê de relance. O empilhamento era
   remendo da largura, não decisão — sumiu junto com a causa.

   O piso de 300px cobre o iPhone SE (320px de tela → cartão de 218px): ainda
   sobra margem sobre os 162px das pastilhas. */


/* ===========================================================================
   WHATSAPP FLUTUANTE
   Sobe acima da barra de abas no mobile: sobrepor a navegação para oferecer
   atendimento troca um problema por outro. No desktop não há barra de abas,
   então ele desce para o canto.
   =========================================================================== */
/* ===========================================================================
   SUPORTE FLUTUANTE
   No computador é uma pílula que já diz o que é — rótulo escondido atrás de
   hover só se descobre por acidente, e quem precisa de ajuda não vai passar o
   mouse para descobrir. No celular vira círculo, porque ali o espaço é o que
   falta e o verde do WhatsApp já é reconhecido sozinho.
   =========================================================================== */
.cb-whatsapp {
  position: fixed;
  inset-inline-end: var(--cb-space-sm);
  inset-block-end: calc(58px + env(safe-area-inset-bottom) + var(--cb-space-2xs));
  z-index: var(--cb-layer-sticky);

  display: flex;
  align-items: center;
  padding: 3px;
  border-radius: var(--cb-radius-pill);

  background-color: #25d366;
  color: #fff;
  /* Duas sombras: uma curta que assenta o botão e uma longa e esverdeada
     que o descola do fundo sem virar mancha cinza. */
  box-shadow:
    0 2px 6px rgb(0 0 0 / 0.16),
    0 10px 26px rgb(37 211 102 / 0.34);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition:
    box-shadow var(--cb-duration-base) var(--cb-ease-out),
    transform var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-whatsapp:hover,
.cb-whatsapp:active {
  color: #fff;
}

.cb-whatsapp__icone {
  position: relative;
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 50px;
  height: 50px;
}

.cb-whatsapp__icone svg {
  width: 29px;
  height: 29px;
}

/* Anel que pulsa devagar: diz "tem gente do outro lado" sem piscar na cara
   de quem está lendo. */
.cb-whatsapp__pulso {
  position: absolute;
  inset: 5px;
  border-radius: 50%;
  border: 2px solid rgb(255 255 255 / 0.85);
  opacity: 0;
  animation: cb-whatsapp-pulso 2.8s var(--cb-ease-out) infinite;
  pointer-events: none;
}

@keyframes cb-whatsapp-pulso {
  0%   { transform: scale(0.92); opacity: 0.55; }
  70%  { transform: scale(1.5);  opacity: 0; }
  100% { transform: scale(1.5);  opacity: 0; }
}

/* No celular só o círculo. O rótulo continua no HTML para o leitor de tela. */
.cb-whatsapp__texto {
  display: none;
}

@media (min-width: 768px) {
  .cb-whatsapp__texto {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-inline: var(--cb-space-3xs) var(--cb-space-sm);
    white-space: nowrap;
    line-height: 1.2;
  }

  .cb-whatsapp__texto b {
    font-size: var(--cb-ui-label);
    font-weight: var(--cb-weight-bold);
  }

  .cb-whatsapp__texto small {
    font-size: var(--cb-text-2xs);
    opacity: 0.92;
  }

  .cb-whatsapp:hover {
    transform: translateY(-2px);
    box-shadow:
      0 4px 10px rgb(0 0 0 / 0.18),
      0 16px 34px rgb(37 211 102 / 0.44);
  }

  .cb-whatsapp:active {
    transform: translateY(0);
  }
}

.cb-whatsapp:focus-visible {
  outline: var(--cb-focus-width) solid var(--cb-fg);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .cb-whatsapp { transition-duration: 1ms; }
  .cb-whatsapp__pulso { animation: none; }
}

.cb-whatsapp[hidden] { display: none; }


/* Com a barra de compra da PDP em cena, o botão sobe junto — senão fica
   escondido atrás dela. */
body:has(.cb-buybar-app[data-visible='true']) .cb-whatsapp {
  inset-block-end: calc(58px + env(safe-area-inset-bottom) + var(--cb-space-sm));
}

/* Sem a barra de abas do celular, o botão desce para a margem normal. A
   largura NÃO se fixa aqui: quem manda no tamanho é o conteúdo (ícone +
   rótulo). Uma versão anterior deixou `width: 58px` nesta regra, e o pill
   nunca abria — o rótulo existia, media 129 px e ficava fora da caixa. */
@media (min-width: 1024px) {
  .cb-whatsapp {
    inset-block-end: var(--cb-space-md);
  }
}

/* Dados da empresa no rodapé: legíveis, não escondidos. É informação que o
   cliente procura para se convencer de que a loja existe. */
.cb-footer__company {
  margin-block-end: var(--cb-space-2xs);
  line-height: 1.6;
}


/* ===========================================================================
   TEXTO CORRIDO — páginas institucionais
   Política, garantia e prazo são páginas para LER, não para escanear. Elas
   pedem o oposto do resto do site: medida curta, entrelinha larga, hierarquia
   por espaço em vez de por cor.

   Existem porque eu tinha reaproveitado `.cb-footer__title` aqui — rótulo de
   coluna de rodapé, caixa alta e apertado. Funcionava no rodapé e colava os
   títulos nos parágrafos aqui.
   =========================================================================== */
.cb-prose {
  max-width: 62ch;
  font-size: var(--cb-text-base);
  line-height: 1.65;
}

.cb-prose > * + * {
  margin-block-start: var(--cb-space-sm);
}

/* O espaço ANTES do título é maior que o depois: é ele que agrupa o título
   com o texto que ele governa, em vez de deixá-lo boiando entre dois blocos. */
.cb-prose h2 {
  margin-block: var(--cb-space-lg) var(--cb-space-2xs);
  color: var(--cb-coffee-600);
  font-size: var(--cb-text-h3, 1.375rem);
  font-weight: var(--cb-weight-bold);
  line-height: 1.25;
  letter-spacing: -0.01em;
}

.cb-prose h2:first-child {
  margin-block-start: var(--cb-space-md);
}

.cb-prose ul,
.cb-prose ol {
  margin-block: var(--cb-space-xs);
  padding-inline-start: var(--cb-space-md);
}

.cb-prose li + li {
  margin-block-start: var(--cb-space-2xs);
}

.cb-prose ul { list-style: disc; }
.cb-prose ol { list-style: decimal; }

.cb-prose a {
  color: var(--cb-coffee-600);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

.cb-prose b { font-weight: var(--cb-weight-bold); }

/* A data de atualização fecha a página e é o que dá procedência a um
   documento legal. */
.cb-prose__meta {
  margin-block-start: var(--cb-space-lg);
  padding-block-start: var(--cb-space-sm);
  border-block-start: var(--cb-border-thin) solid var(--cb-line);
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-caption);
}

/* ===========================================================================
   TABELA NUTRICIONAL EM TEXTO — a que se LÊ
   A do carrossel é imagem: boa de folhear, mas no celular a fonte dela cai
   para uns 8 px. Esta é HTML, no corpo do site, com número alinhado à direita
   para a coluna bater na vírgula. Em tela estreita ela rola dentro da própria
   caixa em vez de espremer as colunas — texto de rótulo espremido vira texto
   ilegível, e a página inteira não pode ganhar rolagem lateral por causa de
   uma tabela.
   =========================================================================== */
.cb-nutri {
  width: 100%;
  margin-block-start: var(--cb-space-sm);
  border-collapse: collapse;
  font-size: var(--cb-ui-label);
  line-height: 1.4;
}

.cb-nutri__caption {
  margin-block-end: var(--cb-space-2xs);
  color: var(--cb-fg-muted);
  font-size: var(--cb-ui-caption);
  text-align: start;
}

.cb-nutri th,
.cb-nutri td {
  padding-block: var(--cb-space-2xs);
  border-block-end: var(--cb-border-thin) solid var(--cb-line);
  text-align: end;
  /* Espaço de sobra à esquerda do número para a coluna não colar no rótulo
     quando o nome do nutriente é longo. */
  padding-inline-start: var(--cb-space-sm);
  white-space: nowrap;
}

.cb-nutri tbody th,
.cb-nutri thead th:first-child {
  padding-inline-start: 0;
  font-weight: var(--cb-weight-medium);
  text-align: start;
  white-space: normal;
}

.cb-nutri thead th {
  border-block-end: var(--cb-border-thick) solid var(--cb-fg);
  font-weight: var(--cb-weight-bold);
}

/* "Nutriente" existe para o leitor de tela ter um cabeçalho de coluna; na
   tela ele só repetiria o que a primeira coluna já mostra. */
.cb-nutri thead th:first-child {
  color: transparent;
}

/* Açúcares dentro de carboidratos, saturadas dentro de gorduras: o recuo é o
   que diz que uma linha faz parte da anterior. */
.cb-nutri tbody .cb-nutri__filha th {
  padding-inline-start: var(--cb-space-sm);
  font-weight: var(--cb-weight-regular);
}

.cb-nutri__nota {
  margin-block-start: var(--cb-space-xs);
  color: var(--cb-fg-muted);
  font-size: var(--cb-ui-caption);
  line-height: 1.5;
}

/* ===========================================================================
   RÓTULO NA PDP — ingredientes, alérgenos e advertência
   Texto regulado tem que ser LEGÍVEL, não "conforme". Alérgeno e advertência
   de cafeína ganham peso e cor de alerta porque são o tipo de informação em
   que a pessoa decide não comprar — e isso é o resultado certo quando ela
   tem alergia.
   =========================================================================== */
.cb-rotulo__ingredientes {
  margin-block-start: var(--cb-space-sm);
  font-size: var(--cb-ui-body);
  line-height: 1.55;
}

.cb-rotulo__aviso {
  margin-block-start: var(--cb-space-2xs);
  font-size: var(--cb-ui-label);
  line-height: 1.5;
}

.cb-rotulo__aviso--forte {
  font-weight: var(--cb-weight-bold);
  /* Cor do esquema, não do café: este bloco vive numa seção de fundo escuro,
     e `--cb-coffee-600` ali era marrom sobre marrom. */
  color: var(--cb-fg);
}

/* O carrinho explicando que juntou potes soltos num kit. Tom de boa notícia,
   não de alerta: é dinheiro que a pessoa deixou de gastar. */
.cb-cart__juntou {
  margin-block-end: var(--cb-space-sm);
  padding: var(--cb-space-xs) var(--cb-space-sm);
  border-radius: var(--cb-radius-sm);
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
  color: var(--cb-fg);
  font-size: var(--cb-ui-label);
  line-height: 1.45;
}

/* Aviso no lugar do botão de finalizar, enquanto o checkout do B4You não está
   integrado. Discreto, mas não escondido: quem chegou até o carrinho merece
   saber por que não dá para concluir. */
.cb-cart__pendente {
  margin-block: var(--cb-space-sm);
  padding: var(--cb-space-xs);
  border: var(--cb-border-thin) dashed var(--cb-line);
  border-radius: var(--cb-radius-sm);
  color: var(--cb-mud-500);
  font-size: var(--cb-ui-label);
  text-align: center;
}

/* ===========================================================================
   FAIXA DE VÍDEOS — marquee de cartões verticais
   ---------------------------------------------------------------------------
   O mesmo gesto da faixa de avisos lá em cima, em outra escala: trilha
   duplicada e translateX(-50%), que cai exatamente sobre o cartão gêmeo e
   fecha o loop sem costura visível.

   A animação anda o CONTAINER, não o scroll — por isso a faixa não rouba o
   gesto de rolagem vertical da página no celular.
   =========================================================================== */
.cb-videos {
  --cb-videos-duracao: 49s;
  --cb-videos-largura: clamp(160px, 44vw, 232px);
  display: flex;
  gap: var(--cb-space-sm);
  overflow: hidden;
  /* Sangra até a borda da tela: cartão cortado no canto é o que avisa que a
     faixa continua. A faixa mora DIRETO na <section>, fora do container, e
     estas margens cancelam o padding dela — uma por breakpoint, espelhando
     .cb-section em base.css. Com 50vw a barra de rolagem entraria na conta e
     abriria scroll horizontal na página inteira. */
  margin-inline: calc(var(--cb-pad-inline) * -1);
  padding-block: var(--cb-space-3xs);
  /* Desbota nas duas pontas em vez de cortar seco. */
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.cb-videos__track {
  display: flex;
  flex-shrink: 0;
  gap: var(--cb-space-sm);
  margin: 0;
  padding: 0 0 0 var(--cb-space-sm);
  list-style: none;
  animation: cb-videos-scroll var(--cb-videos-duracao) linear infinite;
}

.cb-videos:hover .cb-videos__track,
.cb-videos:focus-within .cb-videos__track,
.cb-videos[data-tocando='true'] .cb-videos__track {
  animation-play-state: paused;
}

@keyframes cb-videos-scroll {
  from { transform: translateX(0); }
  /* -50% e não -100%: a trilha é uma das DUAS metades da faixa. */
  to   { transform: translateX(-50%); }
}

.cb-video {
  flex: 0 0 auto;
  width: var(--cb-videos-largura);
}

/* O quadro é quem tem a forma; o botão e o cartão de produto moram dentro.
   Antes o próprio botão era o quadro — e um <a> não pode viver dentro de um
   <button>: é markup inválido, e o navegador desmancha a árvore sozinho. */
.cb-video__quadro {
  position: relative;
  width: 100%;
  aspect-ratio: 9 / 16;
  border-radius: var(--cb-radius-md);
  overflow: hidden;
  background-color: var(--cb-coffee-700);
  transition: transform var(--cb-duration-base) var(--cb-ease-out);
}

.cb-video__quadro:hover,
.cb-video__quadro:focus-within {
  transform: translateY(-4px);
}

.cb-video__abrir {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  cursor: pointer;
}

.cb-video__capa {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Escurece só a base, onde mora o título. O rosto no meio do quadro fica
   intacto — é ele que faz alguém querer abrir. */
.cb-video__abrir::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 55%;
  background: linear-gradient(to top, rgb(28 14 7 / 0.85), transparent);
  pointer-events: none;
}

.cb-video__etiqueta {
  position: absolute;
  inset-block-start: var(--cb-space-2xs);
  inset-inline-start: var(--cb-space-2xs);
  z-index: 1;
  padding: 5px var(--cb-space-2xs);
  border-radius: var(--cb-radius-pill);
  background-color: rgb(28 14 7 / 0.72);
  backdrop-filter: blur(4px);
  color: var(--cb-cream-100);
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
}

.cb-video__play {
  position: absolute;
  /* 42% e não 50%: a metade de baixo passou a ser do cartão de produto, e o
     play centrado ficava encostado nele. */
  inset-block-start: 42%;
  inset-inline-start: 50%;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background-color: rgb(247 240 230 / 0.92);
  color: var(--cb-coffee-600);
  transform: translate(-50%, -50%);
  transition: transform var(--cb-duration-base) var(--cb-ease-bounce);
}

.cb-video__quadro:hover .cb-video__play,
.cb-video__abrir:focus-visible .cb-video__play {
  transform: translate(-50%, -50%) scale(1.12);
}

.cb-video__play svg {
  width: 20px;
  height: 20px;
  /* O triângulo tem o peso visual à esquerda; 2px devolvem o centro óptico. */
  margin-inline-start: 2px;
}

/* ---------------------------------------------------------------------------
   CARTÃO DE PRODUTO SOBRE O VÍDEO
   O que o vídeo mostra, com preço e caminho para a página do kit. Ocupou o
   lugar do título: o título já é dito pelo próprio vídeo, e a saída para a
   compra não existia em lugar nenhum.
--------------------------------------------------------------------------- */
.cb-video__produto {
  position: absolute;
  inset: auto 6px 6px;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px;
  border-radius: var(--cb-radius-sm);
  background-color: rgb(247 240 230 / 0.94);
  backdrop-filter: blur(6px);
  color: var(--cb-coffee-700);
  text-decoration: none;
  transition: background-color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-video__produto:hover,
.cb-video__produto:active {
  color: var(--cb-coffee-700);
}

.cb-video__produto:hover {
  background-color: var(--cb-cream-100);
}

.cb-video__produto-foto {
  width: 34px;
  height: 34px;
  flex-shrink: 0;
  border-radius: var(--cb-radius-xs);
  object-fit: contain;
  background-color: rgb(36 18 9 / 0.06);
}

.cb-video__produto-texto {
  flex: 1;
  min-width: 0;
}

.cb-video__produto-nome {
  display: block;
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-bold);
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cb-video__produto-preco {
  display: block;
  font-size: var(--cb-ui-label);
  font-weight: var(--cb-weight-bold);
  line-height: 1.25;
}

.cb-video__produto-pip {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  border-radius: 50%;
  background-color: var(--cb-coffee-600);
  color: var(--cb-cream-100);
}

.cb-video__produto-pip svg {
  width: 15px;
  height: 15px;
}

/* No player o cartão fica ABAIXO do vídeo, não por cima: sobreposto, ele
   cobriria os controles do YouTube, que moram exatamente ali embaixo. */
.cb-video-modal__produto:empty { display: none; }

.cb-video-modal__produto .cb-video__produto {
  position: static;
  margin-block-start: var(--cb-space-2xs);
  padding: var(--cb-space-2xs);
  border-radius: var(--cb-radius-md);
  background-color: var(--cb-cream-100);
}


@media (min-width: 768px) {
  .cb-videos { margin-inline: calc(var(--cb-space-xl) * -1); }
}

@media (min-width: 1024px) {
  .cb-videos {
    margin-inline: calc(var(--cb-space-2xl) * -1);
    --cb-videos-largura: clamp(200px, 17vw, 260px);
  }
}

/* Sem animação, a faixa vira um carrossel que a pessoa empurra com o dedo. */
@media (prefers-reduced-motion: reduce) {
  .cb-videos {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }

  .cb-videos::-webkit-scrollbar { display: none; }

  .cb-videos__track { animation: none; }

  /* A cópia do loop não serve a quem rola no dedo: seriam catorze cartões
     para sete vídeos. */
  .cb-videos__track[aria-hidden='true'] { display: none; }

  .cb-video { scroll-snap-align: center; }

  .cb-video__abrir:hover { transform: none; }
}

/* ===========================================================================
   PLAYER DO VÍDEO — <dialog> nativo
   O quadro é 9:16 e o limite é a ALTURA da janela, não a largura: um vídeo
   vertical dimensionado pela largura estoura a tela no desktop.
   =========================================================================== */
.cb-video-modal {
  /* As duas medidas moram no PAI porque o palco e a faixa do X são irmãos, e
     variável CSS desce para filho — não atravessa para o lado.

     Um vídeo 9:16 dimensionado pela LARGURA estoura a tela no desktop; o
     limite tem que sair da altura disponível. Descontados: o padding do modal
     (2×16), a faixa do botão (44) e o respiro entre eles (4). */
  --cb-video-modal-altura: calc(100dvh - 32px - var(--cb-touch-target) - 4px);
  --cb-video-modal-largura: calc(var(--cb-video-modal-altura) * 9 / 16);
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--cb-space-3xs);
  padding: var(--cb-space-sm);
  border: 0;
  background-color: transparent;
  overscroll-behavior: contain;
}

.cb-video-modal::backdrop {
  background-color: rgb(28 14 7 / 0.86);
  backdrop-filter: blur(6px);
}

/* Faixa própria para o X. Entra na conta da altura do palco logo abaixo, que
   é o que impede o botão de ser empurrado para fora da tela. */
.cb-video-modal__topo {
  display: flex;
  justify-content: flex-end;
  width: min(100%, var(--cb-video-modal-largura));
  flex: 0 0 auto;
}

.cb-video-modal__palco {
  width: min(100%, var(--cb-video-modal-largura));
  aspect-ratio: 9 / 16;
  max-height: var(--cb-video-modal-altura);
  flex: 0 1 auto;
}

.cb-video-modal__quadro {
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: var(--cb-radius-md);
  background-color: var(--cb-coffee-900);
}

.cb-video-modal__fechar {
  display: grid;
  place-items: center;
  width: var(--cb-touch-target);
  height: var(--cb-touch-target);
  border-radius: 50%;
  background-color: rgb(247 240 230 / 0.14);
  color: var(--cb-cream-100);
  cursor: pointer;
  transition: background-color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-video-modal__fechar:hover {
  background-color: rgb(247 240 230 / 0.26);
}

.cb-video-modal__fechar svg {
  width: var(--cb-icon-md);
  height: var(--cb-icon-md);
}

/* ===========================================================================
   INSTAGRAM — grade do feed + chamada para seguir
   ---------------------------------------------------------------------------
   No WordPress o miolo da grade vira o shortcode do plugin de feed. Por isso
   o estilo mora no CONTAINER e não em cada post: o markup que o plugin cospe
   não vai ter as classes daqui, mas vai herdar grade, raio e proporção.
   =========================================================================== */
.cb-instagram {
  display: grid;
  gap: var(--cb-space-sm);
}

.cb-instagram__grade {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--cb-space-2xs);
}

/* Vale para o post do protótipo E para o que o plugin de feed injetar. */
.cb-instagram__post,
.cb-instagram__grade > a,
.cb-instagram__grade li {
  position: relative;
  display: block;
  aspect-ratio: 1;
  border-radius: var(--cb-radius-sm);
  overflow: hidden;
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
  list-style: none;
}

.cb-instagram__grade img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--cb-duration-slow) var(--cb-ease-out);
}

.cb-instagram__post:hover img,
.cb-instagram__post:focus-visible img {
  transform: scale(1.05);
}

.cb-instagram__chamada {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--cb-space-xs);
  padding-block-start: var(--cb-space-2xs);
  text-align: center;
}

.cb-instagram__selo {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--cb-radius-md);
  border: var(--cb-border-thin) solid var(--cb-line);
  color: var(--cb-fg);
}

.cb-instagram__selo svg {
  width: var(--cb-icon-md);
  height: var(--cb-icon-md);
}

.cb-instagram__arroba {
  margin: 0;
  margin-inline-end: auto;
  font-size: var(--cb-ui-title);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-heading);
}

@media (max-width: 599px) {
  /* Centrado no celular: com o botão embaixo, o @ empurrado para a esquerda
     fica torto em vez de alinhado. */
  .cb-instagram__arroba { margin-inline-end: 0; width: 100%; }
}

/* ===========================================================================
   ESTADO ATIVO NA NAVEGAÇÃO
   O sublinhado do ::after já existe para o hover — no item da página atual ele
   fica aberto, e o acento marca a posição sem depender só da cor.
   =========================================================================== */
.cb-nav__link[aria-current='page'] {
  color: var(--cb-accent);
}

.cb-nav__link[aria-current='page']::after {
  transform: scaleX(1);
}

.cb-drawer__link[aria-current='page'] {
  color: var(--cb-accent);
}

/* Segundo grupo do drawer: pós-venda. Fica visualmente abaixo do primeiro em
   peso, não só em posição — quem está comprando não deve tropeçar em "trocas
   e devoluções" com o mesmo destaque de "comprar". */
.cb-drawer__list--apoio {
  margin-block-start: var(--cb-space-sm);
  padding-block-start: var(--cb-space-sm);
  border-block-start: var(--cb-border-thin) solid var(--cb-line);
}

.cb-drawer__list--apoio .cb-drawer__link {
  font-size: var(--cb-ui-body);
  font-weight: var(--cb-weight-medium);
  text-transform: none;
  letter-spacing: var(--cb-tracking-body);
  color: var(--cb-fg-muted);
}

.cb-drawer__list--apoio .cb-drawer__link:hover,
.cb-drawer__list--apoio .cb-drawer__link[aria-current='page'] {
  color: var(--cb-fg);
}

/* ===========================================================================
   LOGIN — painel e figura
   ---------------------------------------------------------------------------
   Duas colunas no desktop, uma no celular. A figura é decorativa e SOME antes
   de virar uma faixa espremida: foto de 90 px de altura não ambienta nada e
   ainda empurra o formulário para baixo da dobra.

   Os seletores miram tanto as classes daqui quanto as que o WooCommerce
   imprime (.woocommerce-form-row, .woocommerce-form-login__submit), porque no
   plugin o miolo passa a ser markup dele.
   =========================================================================== */
.cb-login {
  display: grid;
  min-height: 70vh;
}

.cb-login__painel {
  display: grid;
  place-items: center;
  padding: var(--cb-space-2xl) var(--cb-pad-inline);
}

.cb-login__caixa {
  width: 100%;
  max-width: 27rem;
}

.cb-login__caixa .cb-lead {
  margin-block-end: var(--cb-space-lg);
}

.cb-login__form,
.cb-login__caixa form {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-sm);
}

.cb-login__linha {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-2xs);
}

.cb-login__lembrar {
  display: flex;
  align-items: center;
  gap: var(--cb-space-3xs);
  font-size: var(--cb-ui-body);
  cursor: pointer;
}

.cb-login__esqueci {
  font-size: var(--cb-ui-body);
  color: var(--cb-fg-muted);
}

.cb-login__esqueci:hover {
  color: var(--cb-fg);
}

.cb-login__troca {
  margin-block-start: var(--cb-space-lg);
  padding-block-start: var(--cb-space-sm);
  border-block-start: var(--cb-border-thin) solid var(--cb-line);
  font-size: var(--cb-ui-body);
  color: var(--cb-fg-muted);
}

/* Nasce vazio e sem caixa: só ganha corpo quando o js escreve dentro. */
.cb-login__maquete {
  margin: 0;
  font-size: var(--cb-ui-label);
  color: var(--cb-mud-500);
}

.cb-login__maquete[data-visivel='true'] {
  padding: var(--cb-space-2xs);
  border: var(--cb-border-thin) dashed var(--cb-line);
  border-radius: var(--cb-radius-sm);
}

.cb-login__figura {
  display: none;
}

@media (min-width: 900px) {
  .cb-login {
    grid-template-columns: 1fr 1fr;
  }

  .cb-login__figura {
    display: block;
    position: relative;
    background-color: var(--cb-coffee-400);
  }

  .cb-login__figura img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}



/* ===========================================================================
   MURAL DE DEPOIMENTOS — grade em colunas
   ---------------------------------------------------------------------------
   Era um carrossel: mostrava quatro e escondia os outros doze atrás das setas.
   Numa seção cuja mensagem é "muita gente aprovou", esconder o volume derruba
   justamente o argumento.

   `columns` e não `grid`: com cartões de alturas diferentes — uns com foto,
   outros só texto — o grid deixaria buraco embaixo do mais curto de cada
   linha. Em colunas eles se encaixam, que é o empilhamento da referência.

   O preço é a ordem de leitura: as colunas enchem de cima para baixo, então
   o segundo cartão fica ABAIXO do primeiro, não ao lado. Para depoimento
   independente isso não custa nada — e é por isso que não serve para lista
   numerada nem para passo a passo.
   =========================================================================== */
.cb-depoimentos__grade {
  columns: 1;
  column-gap: var(--cb-space-sm);
  margin: 0;
  padding: 0;
  list-style: none;
}

.cb-depoimentos__item {
  /* Sem isto o navegador parte um cartão ao meio entre duas colunas. */
  break-inside: avoid;
  margin-block-end: var(--cb-space-sm);
}

/* Dezesseis cartões empurrariam o FAQ e o rodapé para longe de quem só rola a
   página. A grade nasce cortada e o botão revela o resto. O corte é por
   ORDEM, não por altura: assim nenhum cartão aparece pela metade. */
.cb-depoimentos__grade[data-limitado] > .cb-depoimentos__item:nth-child(n + 10) {
  display: none;
}

.cb-depoimentos__rodape {
  display: flex;
  justify-content: center;
  margin-block-start: var(--cb-space-md);
}

@media (min-width: 600px) {
  .cb-depoimentos__grade { columns: 2; }
}

@media (min-width: 1024px) {
  .cb-depoimentos__grade { columns: 3; }
}

/* No mural os cartões já têm a altura do próprio conteúdo — o height:100% do
   componente só fazia sentido dentro do carrossel, onde a fileira mandava. */
.cb-depoimentos__item .cb-testimonial {
  height: auto;
}

/* ===========================================================================
   STORIES DE PRODUTO — fileira de círculos
   ---------------------------------------------------------------------------
   O anel colorido não é enfeite: é o que diz "tem coisa nova aqui" sem uma
   palavra. Por isso ele APAGA depois de assistido — um anel que fica aceso
   para sempre deixa de informar em duas visitas.

   Rola no dedo em vez de andar sozinho, ao contrário da faixa de vídeos do
   meio da página: aqui o alvo é pequeno e fica no caminho do polegar.
   =========================================================================== */
.cb-stories {
  --cb-story-tamanho: 62px;
  /* ⚠️ SÓ NO CELULAR, e não por preguiça de adaptar. No desktop o hero é
     dimensionado pelo CONTEÚDO (738 px), não pelo min-height — descontar
     chrome não encolhe nada. A fileira empurraria o botão de compra para
     fora da primeira dobra, e a régua declarada deste hero, três blocos
     acima, é "o botão aparece sem rolar". Os mesmos sete vídeos continuam
     na faixa grande do meio da página, que no desktop é onde eles rendem.

     Se um dia o hero couber com folga, é só apagar este display:none e
     somar a altura da fileira em --cb-hero-chrome. */
  display: none;
  overflow-x: auto;
  scrollbar-width: none;
  padding-block: var(--cb-space-2xs);
  background-color: var(--cb-bg);
}

.cb-stories::-webkit-scrollbar { display: none; }

.cb-stories:empty { display: none; }

ul.cb-stories__track {
  display: flex;
  gap: var(--cb-space-sm);
  margin: 0;
  padding-inline: var(--cb-pad-inline);
  list-style: none;
}

.cb-stories__item { flex: 0 0 auto; }

.cb-story {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  width: calc(var(--cb-story-tamanho) + 12px);
  cursor: pointer;
}

/* O anel é o FUNDO do quadrado; o padding é o que deixa a cor aparecer em
   volta da capa, e a borda interna separa uma da outra. */
.cb-story__anel {
  display: block;
  width: var(--cb-story-tamanho);
  height: var(--cb-story-tamanho);
  padding: 2.5px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--cb-yellow-500), var(--cb-coffee-400));
  transition: transform var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-story:hover .cb-story__anel,
.cb-story:focus-visible .cb-story__anel {
  transform: scale(1.06);
}

.cb-story[data-visto='true'] .cb-story__anel {
  background: rgb(var(--cb-fg-rgb) / 0.2);
}

.cb-story__capa {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--cb-bg);
  background-color: var(--cb-coffee-700);
}

.cb-story__rotulo {
  max-width: 100%;
  overflow: hidden;
  color: var(--cb-fg);
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-medium);
  line-height: 1.2;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cb-story[data-visto='true'] .cb-story__rotulo {
  color: var(--cb-fg-muted);
}

@media (max-width: 767px) {
  .cb-stories { display: flex; }
}

/* ===========================================================================
   STORIES DENTRO DO HERO — a versão discreta
   ---------------------------------------------------------------------------
   Mudaram de lugar: saíram de cima do hero para logo depois do botão. Isso
   muda o papel deles. Em cima eram a primeira coisa da página e podiam pesar;
   aqui embaixo são o "tem mais, se você quiser" — e o que pesa depois do CTA
   compete com ele.

   Daí o desenho ser mais seco que o de cima: círculo menor, anel de um traço
   fino em vez do gradiente, e nenhum rótulo. A capa já diz o que é, e sete
   legendas embaixo do botão de compra viram uma parede de texto.

   Não é `display: none` no desktop como a fileira antiga era: dentro do hero
   ela cabe nos dois, e no desktop as capas ficam do lado do texto em vez de
   roubar o alto da tela.
   =========================================================================== */
.cb-stories--hero {
  --cb-story-tamanho: 44px;
  display: flex;
  margin-block-start: var(--cb-space-sm);
  /* Sangra até a borda direita do cartão: fileira que termina antes do fim
     da caixa não parece ter mais nada para o lado. O padding devolve o
     alinhamento do primeiro item com o texto acima. */
  margin-inline: calc(var(--cb-space-md) * -1);
  padding-inline: var(--cb-space-md);
  padding-block: 0;
  background-color: transparent;
  /* Encaixa cada capa no lugar ao soltar o dedo — o gesto fica com a
     mesma firmeza do carrossel do hero, em vez de parar no meio. */
  scroll-snap-type: x proximal;
  scroll-padding-inline-start: var(--cb-space-md);
  overscroll-behavior-inline: contain;
}

.cb-stories--hero .cb-stories__track {
  gap: var(--cb-space-xs);
  padding-inline: 0;
}

.cb-stories--hero .cb-stories__item { scroll-snap-align: start; }

.cb-stories--hero .cb-story {
  width: var(--cb-story-tamanho);
  gap: 0;
}

/* Traço fino no lugar do gradiente: o anel continua dizendo "isto abre", sem
   virar um segundo ponto de cor logo abaixo do botão. */
.cb-stories--hero .cb-story__anel {
  padding: 1.5px;
  background: rgb(var(--cb-fg-rgb) / 0.28);
}

.cb-stories--hero .cb-story[data-visto='true'] .cb-story__anel {
  background: rgb(var(--cb-fg-rgb) / 0.12);
}

.cb-stories--hero .cb-story__capa { border-width: 1.5px; }

/* O rótulo sai da TELA, não da árvore: quem usa leitor de tela continua
   ouvindo qual vídeo é cada capa. Esconder com `display: none` calaria o
   único texto que identifica o item. */
.cb-stories--hero .cb-story__rotulo {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Os pontinhos do carrossel de FOTOS são `position: absolute` no rodapé do
   hero. Com a fileira encostando neles, os dois passam a ler como um bloco
   só — e os pontos controlam a foto de fundo, não os vídeos. O respiro é o
   que separa uma coisa da outra. Só no celular: no desktop já sobram 131 px
   entre os dois. */
@media (max-width: 767px) {
  .cb-stories--hero { margin-block-end: var(--cb-space-lg); }
}

/* A fileira saiu de cima do hero, então ele não cede mais altura por ela. */
@media (max-width: 767px) {
  .cb-hero--light {
    --cb-hero-chrome: 190px; /* marquee 35 + header 70 + abas 58 + respiro */
  }
}

/* ===========================================================================
   ABA DE AÇÃO — o botão central da barra de baixo
   ---------------------------------------------------------------------------
   Sobe acima da barra e ganha cor cheia porque não é um destino como os
   outros: é a ação principal. Tratá-lo como as demais abas o esconderia no
   meio de quatro ícones iguais, que é o oposto do que ele existe para fazer.
   =========================================================================== */
.cb-tab--acao {
  position: relative;
}

.cb-tab--acao .cb-tab__icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-block-start: -18px;   /* sobe metade para fora da barra */
  border-radius: 50%;
  border: 3px solid var(--cb-bg);
  background-color: var(--cb-coffee-600);
  color: var(--cb-cream-100);
  box-shadow: var(--cb-shadow-sm);
}

.cb-tab--acao .cb-tab__icon svg {
  width: 22px;
  height: 22px;
}

/* ===========================================================================
   COMPRA RÁPIDA — folha de montagem do pedido
   ---------------------------------------------------------------------------
   Sobe de baixo no celular e vira caixa centrada a partir de 600 px. O limite
   de altura é dvh e não vh: no Safari do iPhone a barra de endereço entra na
   conta de vh, e o rodapé com o botão de confirmar ficava escondido atrás
   dela — justamente o botão que fecha a compra.
   =========================================================================== */
.cb-rapida {
  width: 100%;
  max-width: 34rem;
  max-height: 88dvh;
  margin: auto auto 0;
  padding: 0;
  border: 0;
  border-radius: var(--cb-radius-lg) var(--cb-radius-lg) 0 0;
  background-color: var(--cb-bg);
  color: var(--cb-fg);
  overflow: hidden;
}

.cb-rapida[open] {
  display: flex;
  flex-direction: column;
}

.cb-rapida::backdrop {
  background-color: rgb(28 14 7 / 0.55);
}

.cb-rapida__topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-md);
  border-block-end: var(--cb-border-thin) solid var(--cb-line);
}

.cb-rapida__titulo {
  margin: 0;
  font-size: var(--cb-ui-title);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-heading);
}

.cb-rapida__apoio {
  margin: 2px 0 0;
  color: var(--cb-fg-muted);
  font-size: var(--cb-ui-label);
}

/* A lista é o único pedaço que rola: topo e rodapé ficam presos, que é o que
   mantém o total e o botão de confirmar sempre à vista. */
ul.cb-rapida__lista {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  margin: 0;
  padding: var(--cb-space-2xs) var(--cb-space-md);
  list-style: none;
}

/* Foto, nome e preço na primeira linha; as pastilhas de sabor na segunda,
   alinhadas com o texto. Numa linha só elas não cabem: o kit de 3 potes tem
   quatro opções, e duas delas são "2 Caramelo + 1 Avelã". */
.cb-rapida__linha {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) auto;
  align-items: center;
  column-gap: var(--cb-space-2xs);
  row-gap: var(--cb-space-2xs);
  padding-block: var(--cb-space-sm);
  border-block-end: var(--cb-border-thin) solid var(--cb-line);
}

.cb-rapida__linha:last-child { border-block-end: 0; }

.cb-rapida__foto {
  width: 56px;
  height: 56px;
  flex-shrink: 0;
  border-radius: var(--cb-radius-xs);
  object-fit: contain;
  background-color: rgb(var(--cb-fg-rgb) / 0.05);
}

.cb-rapida__info {
  flex: 1;
  min-width: 0;
}

.cb-rapida__nome {
  margin: 0;
  font-size: var(--cb-ui-body);
  font-weight: var(--cb-weight-bold);
  line-height: 1.2;
}

.cb-rapida__resumo {
  margin: 1px 0 0;
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-2xs);
}

.cb-rapida__sabores {
  grid-column: 2 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

/* A pastilha é a mesma .cb-flavor dos cartões, num tamanho de lista. O
   position: relative prende o rádio escondido dentro dela — solto, ele
   posiciona pela folha inteira e o foco por teclado rola a lista para o
   lugar errado. */
.cb-rapida__sabores .cb-flavor {
  position: relative;
  gap: 6px;
  min-height: 34px;
  padding: 3px var(--cb-space-2xs) 3px 3px;
  background-color: var(--cb-bg);
  font-size: var(--cb-text-2xs);
  white-space: nowrap;
}

.cb-rapida__sabores .cb-flavor:has(input:checked) {
  border-color: var(--cb-coffee-600);
  box-shadow: inset 0 0 0 1px var(--cb-coffee-600);
  background-color: rgb(var(--cb-fg-rgb) / 0.06);
}

.cb-rapida__sabores .cb-flavor__bolinhas {
  display: inline-flex;
  align-items: center;
}

.cb-rapida__sabores .cb-flavor__swatch {
  width: 26px;
  height: 26px;
}

.cb-rapida__sabores .cb-flavor--misto .cb-flavor__swatch + .cb-flavor__swatch {
  margin-inline-start: -10px;
}

/* Quantos daquele sabor já estão no pedido. Só aparece com um ou mais. */
.cb-rapida__conta {
  display: inline-grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  padding-inline: 4px;
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-coffee-600);
  color: var(--cb-white);
  font-size: 11px;
  font-weight: var(--cb-weight-bold);
  line-height: 1;
}

.cb-rapida__conta[hidden] { display: none; }

@media (max-width: 479px) {
  /* No celular a faixa de sabores começa na borda, embaixo da foto: os 64px
     da coluna da foto são o que faz "2 Caramelo + 1 Avelã" caber sem
     quebrar a lista em três linhas. */
  .cb-rapida__sabores { grid-column: 1 / -1; }
}

.cb-rapida__lado {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  flex-shrink: 0;
}

.cb-rapida__preco {
  margin: 0;
  font-size: var(--cb-ui-label);
  font-weight: var(--cb-weight-bold);
  white-space: nowrap;
}

.cb-rapida__passo {
  display: flex;
  align-items: center;
  gap: 2px;
  border: var(--cb-border-thin) solid var(--cb-line);
  border-radius: var(--cb-radius-pill);
}

.cb-rapida__btn {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  color: var(--cb-fg);
  font-size: var(--cb-ui-title);
  line-height: 1;
  cursor: pointer;
}

.cb-rapida__btn:hover:not([disabled]) {
  background-color: rgb(var(--cb-fg-rgb) / 0.08);
}

.cb-rapida__btn[disabled] {
  opacity: 0.3;
  cursor: not-allowed;
}

.cb-rapida__qtd {
  min-width: 1.4rem;
  font-size: var(--cb-ui-label);
  font-weight: var(--cb-weight-bold);
  text-align: center;
}

.cb-rapida__rodape {
  padding: var(--cb-space-sm) var(--cb-space-md)
           calc(var(--cb-space-md) + env(safe-area-inset-bottom));
  border-block-start: var(--cb-border-thin) solid var(--cb-line);
}

.cb-rapida__total {
  margin: 0 0 var(--cb-space-2xs);
  font-size: var(--cb-ui-body);
  font-weight: var(--cb-weight-bold);
  text-align: center;
}

@media (min-width: 600px) {
  .cb-rapida {
    margin: auto;
    border-radius: var(--cb-radius-lg);
    max-height: 82dvh;
  }
}

/* ============================================================================
   PÁGINA DE PRODUTO — blocos da página de vendas
   As seções abaixo do buybox são as mesmas para os quatro kits. O que varia
   entre pote e sachê é só o trecho marcado com [data-cb-formato], que
   js/pdp.js liga e desliga — o CSS não sabe da diferença.
   ============================================================================ */

/* Garantia ----------------------------------------------------------------
   Borda tracejada porque este bloco NÃO é um botão: se tivesse a mesma borda
   sólida dos cartões de compra, competiria com o "Levar agora" logo acima,
   e a promessa de devolução vale justamente por estar em segundo plano. */
.cb-garantia {
  display: flex;
  align-items: center;
  gap: var(--cb-space-sm);
  padding: var(--cb-space-sm);
  border: 1.5px dashed var(--cb-coffee-300);
  border-radius: var(--cb-radius-md);
  background-color: rgba(var(--cb-fg-rgb), 0.02);
}

.cb-garantia__selo {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background-color: var(--cb-yellow-400);
  color: var(--cb-coffee-800);
}

.cb-garantia__selo svg {
  width: 22px;
  height: 22px;
}

.cb-garantia__titulo {
  margin: 0;
  font-weight: var(--cb-weight-bold);
  font-size: var(--cb-text-sm);
  color: var(--cb-fg-heading);
}

.cb-garantia__texto {
  margin: 2px 0 0;
  font-size: var(--cb-ui-body);
  color: var(--cb-fg-muted);
  line-height: var(--cb-leading-snug);
}

/* Stories dentro da oferta ------------------------------------------------
   A fileira do topo da home é escondida no desktop porque empurraria o botão
   de compra para fora da dobra. Aqui ela vive DENTRO da caixa de compra: não
   disputa altura com nada e por isso aparece em qualquer largura. */
.cb-stories--oferta {
  --cb-story-tamanho: 54px;
  display: flex;
  background-color: transparent;
  padding-block: 0;
  margin-inline: calc(var(--cb-space-2xs) * -1);
}

.cb-stories--oferta ul.cb-stories__track {
  gap: var(--cb-space-xs);
  padding-inline: var(--cb-space-2xs);
}

.cb-stories--oferta .cb-story__rotulo {
  font-size: var(--cb-text-2xs);
}

/* Passos ------------------------------------------------------------------ */
.cb-passos {
  display: grid;
  gap: var(--cb-space-xl);
  align-items: center;
}

@media (min-width: 900px) {
  .cb-passos {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
    gap: var(--cb-space-2xl);
  }

  /* Título centralizado sobre uma lista alinhada à esquerda fica torto —
     na coluna, os dois compartilham a mesma margem. */
  .cb-passos__texto .cb-section-head {
    text-align: left;
    margin-inline: 0;
  }
}

.cb-passos__lista {
  display: grid;
  gap: var(--cb-space-sm);
  margin: var(--cb-space-lg) 0 0;
  padding: 0;
  list-style: none;
}

.cb-passo {
  position: relative;
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr);
  gap: var(--cb-space-sm);
  align-items: start;
}

/* A linha tracejada nasce do número e morre no próximo — por isso mora no
   item e não num pseudo do <ol>: o último passo não pode ter rabo solto. */
.cb-passo::before {
  content: '';
  position: absolute;
  left: 18px;
  top: 38px;
  bottom: calc(var(--cb-space-sm) * -1);
  border-left: 2px dashed var(--cb-coffee-300);
}

.cb-passo:last-child::before { display: none; }

.cb-passo__num {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background-color: var(--cb-coffee-600);
  color: var(--cb-white);
  font-family: var(--cb-font-heading);
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
}

.cb-passo__cartao {
  padding: var(--cb-space-sm) var(--cb-space-md);
  border: 1px solid var(--cb-line);
  border-radius: var(--cb-radius-md);
  background-color: var(--cb-white);
}

.cb-passo__cartao p {
  margin: 0;
  font-size: var(--cb-text-sm);
  line-height: var(--cb-leading-snug);
}

.cb-passo__selo {
  display: inline-block;
  margin-bottom: 6px;
  padding: 4px 10px;
  border-radius: var(--cb-radius-xs);
  background-color: var(--cb-yellow-400);
  color: var(--cb-coffee-800);
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  text-transform: uppercase;
}

.cb-passos__figura {
  margin: 0;
}

.cb-passos__figura img {
  width: 100%;
  height: auto;
  border-radius: var(--cb-radius-lg);
  object-fit: cover;
}

@media (min-width: 900px) {
  /* A foto é retrato (720×900) e sozinha ficava 150 px mais alta que os três
     passos, deixando a coluna da esquerda com um vazio embaixo. Recortar pelo
     topo mantém as duas colunas terminando juntas. */
  .cb-passos__figura img {
    max-height: 560px;
    object-position: center 35%;
  }
}

.cb-passos__legenda {
  margin-top: var(--cb-space-xs);
  font-size: var(--cb-text-xs);
  color: var(--cb-fg-muted);
  text-align: center;
}

/* Órbita — benefícios em volta da foto -------------------------------------
   No mobile a foto vem PRIMEIRO (order: -1) e os dois grupos descem juntos:
   empilhar na ordem do HTML deixaria dois bullets, foto, mais dois bullets,
   que lido de cima a baixo parece duas seções diferentes. */
.cb-orbita {
  display: grid;
  gap: var(--cb-space-lg);
  align-items: center;
}

@media (min-width: 900px) {
  .cb-orbita {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr) minmax(0, 1fr);
    gap: var(--cb-space-xl);
    /* stretch e não center: com as colunas centradas, os dois bullets
       ficavam agrupados na altura do meio e abriam um vazio no topo do
       tamanho da foto. Esticando, eles se distribuem AO LADO dela — que é
       o que faz a seção parecer uma órbita e não uma legenda. */
    align-items: stretch;
  }

  .cb-orbita__coluna {
    justify-content: space-evenly;
  }
}

.cb-orbita__coluna {
  display: grid;
  gap: var(--cb-space-md);
  margin: 0;
  padding: 0;
  list-style: none;
}

.cb-orbita__item {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  gap: var(--cb-space-xs);
  align-items: start;
}

.cb-orbita__item b {
  display: block;
  font-size: var(--cb-text-sm);
  color: var(--cb-fg-heading);
}

.cb-orbita__item p {
  margin: 2px 0 0;
  font-size: var(--cb-text-xs);
  color: var(--cb-fg-muted);
  line-height: var(--cb-leading-snug);
}

.cb-orbita__check {
  width: 20px;
  height: 20px;
  margin-top: 2px;
  color: var(--cb-green-600);
}

.cb-orbita__figura {
  margin: 0;
  order: -1;
}

@media (min-width: 900px) {
  .cb-orbita__figura { order: 0; }

  /* Alinha o texto para a foto no meio: sem isso as duas colunas ficam
     coladas na imagem de um lado e soltas do outro. */
  .cb-orbita > .cb-orbita__coluna:first-child { text-align: right; }
  .cb-orbita > .cb-orbita__coluna:first-child .cb-orbita__item {
    grid-template-columns: minmax(0, 1fr) 20px;
  }
  .cb-orbita > .cb-orbita__coluna:first-child .cb-orbita__check { order: 2; }
}

/* Sem recorte: a arte já vem sem fundo e num círculo perderia o respingo,
   que é justamente o que ela tem de bom. */
.cb-orbita__figura img {
  width: 100%;
  height: auto;
}

/* Nota do comparativo ----------------------------------------------------- */
.cb-compare-nota {
  margin-top: var(--cb-space-sm);
  max-width: var(--cb-measure-body);
}

/* Cabeçalho de seção centralizado ---------------------------------------- */
.cb-section-head--center {
  text-align: center;
  margin-inline: auto;
  max-width: var(--cb-measure-heading);
}


/* ===========================================================================
   PRÉ-CARREGAMENTO
   Fica no HTML e não é criado por script de propósito: o CSS é
   render-blocking, então esta tela já está na PRIMEIRA pintura — antes de
   qualquer JS rodar, que é justamente quando a página ainda não tem nada
   para mostrar.
   =========================================================================== */
.cb-splash {
  position: fixed;
  inset: 0;
  z-index: var(--cb-layer-splash);
  display: grid;
  grid-template-rows: 1fr auto;
  /* Mesmo esquema do header: as três versões do logo têm a palavra "coffee"
     em branco, então fundo claro engolia metade da marca. */
  background-color: var(--cb-bg);
  opacity: 1;
  transition: opacity 450ms var(--cb-ease-out);
}

.cb-splash[data-saindo='true'] {
  opacity: 0;
  pointer-events: none;
}

.cb-splash__marca {
  display: grid;
  place-items: center;
  padding: var(--cb-space-lg);
}

.cb-splash__marca img {
  width: min(46vw, 220px);
  height: auto;
}

/* O número embaixo, grande, como assinatura — não compete com a marca. */
.cb-splash__conta {
  margin: 0;
  padding: var(--cb-space-lg);
  color: var(--cb-fg);
  font-size: clamp(3rem, 12vw, 7rem);
  font-weight: var(--cb-weight-bold);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* Sem JS o splash cobriria a página para sempre. A regra abaixo só existe
   dentro do <noscript>, que é a única forma de saber que o JS não vai vir. */
.cb-sem-js .cb-splash {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .cb-splash {
    transition-duration: 1ms;
  }
}


/* ===========================================================================
   PDP · FAIXA DE MARCA E AÇÕES
   No celular o breadcrumb some e sobrava um vazio entre o header e a foto.
   Aqui entram quem assina o produto e as duas ações de página de produto:
   salvar e compartilhar.
   =========================================================================== */
.cb-pdp-topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-sm);
  margin-block-end: var(--cb-space-xs);
}

/* Uma linha só antes da foto. Antes eram três empilhadas — breadcrumb
   sozinho, depois marca e ações, e só então o produto —, o que empurrava a
   foto para baixo e deixava o "3 potes" do caminho flutuando sozinho a meia
   tela do título que diz a mesma coisa.

   No desktop manda o caminho; no celular ele já está escondido e quem ocupa
   o lugar é a marca. Nunca os dois ao mesmo tempo: seriam duas etiquetas
   dizendo de onde a pessoa veio, lado a lado. */
.cb-pdp-topo .cb-breadcrumb {
  margin: 0;
}

@media (min-width: 768px) {
  .cb-pdp-topo__marca {
    display: none;
  }
}

@media (max-width: 767.98px) {
  .cb-pdp-topo .cb-breadcrumb {
    display: none;
  }
}

.cb-pdp-topo__marca {
  margin: 0;
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  text-transform: uppercase;
}

.cb-pdp-topo__acoes {
  display: flex;
  gap: var(--cb-space-3xs);
}

.cb-pdp-topo__acao {
  display: grid;
  place-items: center;
  width: var(--cb-touch-target);
  height: var(--cb-touch-target);
  border-radius: 50%;
  background-color: var(--cb-white);
  color: var(--cb-fg);
  box-shadow: var(--cb-shadow-sm);
  cursor: pointer;
  transition:
    transform var(--cb-duration-fast) var(--cb-ease-bounce),
    color var(--cb-duration-fast) var(--cb-ease-out);
}

.cb-pdp-topo__acao svg {
  width: 21px;
  height: 21px;
  fill: none;
}

.cb-pdp-topo__acao:hover { transform: scale(1.06); }

/* Salvo: o coração preenche, que é o sinal que todo mundo já conhece. */
.cb-pdp-topo__acao[aria-pressed='true'] {
  color: var(--cb-danger);
}

.cb-pdp-topo__acao[aria-pressed='true'] svg {
  fill: currentColor;
}

/* O produto começa mais alto. A primeira seção da PDP herdava o padding
   cheio de seção — que existe para separar UMA seção da anterior. Aqui não há
   anterior: só o header, que já dá o respiro. Eram 135 px de nada entre a
   barra e o breadcrumb antes de a foto aparecer. */
.cb-pdp-secao {
  padding-block-start: var(--cb-space-md);
}

@media (min-width: 768px) {
  .cb-pdp-secao {
    padding-block-start: var(--cb-space-lg);
  }
}


/* --- Selo de economia na escada de kits ---------------------------------
   A escada de preços só convence quando a economia está NO botão. Sem isto
   a pessoa teria que comparar "R$ 179,00/un" com "R$ 219,00" de cabeça, na
   hora de decidir — e não compara: fica no de sempre.
   ----------------------------------------------------------------------- */
/* Dentro do botão, não flutuando por cima: numa grade de 2x2 o selo
   absoluto pousava em cima da opção da linha anterior. */
.cb-choice__selo {
  /* flex + place-items em vez de line-height: o texto de 10 px dentro de uma
     pílula de 2 px de padding não centraliza sozinho na vertical, e ficava
     encostado no topo. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: center;
  min-height: 20px;
  margin-block-end: 3px;
  padding: 0 var(--cb-space-2xs);
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-yellow-300);
  color: var(--cb-coffee-700);
  /* 10 px era menor que qualquer texto do site. Este selo carrega o número
     que faz subir de kit — não pode ser o menor da página. */
  font-size: var(--cb-text-2xs);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  line-height: 1.5;
  white-space: nowrap;
}

/* O melhor não pode ficar igual aos outros, senão a escada não tem topo. */
.cb-choice__selo--top {
  background-color: var(--cb-coffee-600);
  color: var(--cb-cream-100);
}




/* --- Simulador de prazo de entrega -------------------------------------- */
.cb-frete {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-3xs);
  padding: var(--cb-space-xs);
  border-radius: var(--cb-radius-md);
  background-color: rgb(var(--cb-fg-rgb) / 0.04);
}

.cb-frete__rotulo {
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
}

.cb-frete__linha {
  display: flex;
  gap: var(--cb-space-3xs);
}

.cb-frete__campo {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--cb-space-3xs) var(--cb-space-2xs);
  border: var(--cb-border-thin) solid var(--cb-line);
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-white);
  font-size: var(--cb-text-sm);
}

.cb-frete__campo:focus-visible {
  outline: 2px solid var(--cb-fg);
  outline-offset: 1px;
}

.cb-frete__saida {
  margin: 0;
  font-size: var(--cb-text-sm);
  line-height: 1.35;
}

.cb-frete__saida[data-estado='ok'] { color: var(--cb-success); }
.cb-frete__saida[data-estado='erro'] { color: var(--cb-fg-muted); }


/* ===========================================================================
   HERO · CARROSSEL
   Os slides ficam empilhados no mesmo lugar e trocam por opacidade. O texto
   mora por cima, então deslizar de lado arrastaria o olho para longe do
   botão bem na hora da decisão.
   =========================================================================== */
.cb-hero__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 700ms var(--cb-ease-out);
}

.cb-hero__slide[data-ativo='true'] {
  opacity: 1;
}

/* Sem JS nenhum slide recebe data-ativo e o hero ficaria vazio. */
.cb-hero__slide:first-child {
  opacity: 1;
}

.cb-hero__slide[data-ativo='true'] ~ .cb-hero__slide:first-child {
  opacity: 0;
}

.cb-hero__slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cb-hero__pontos {
  position: absolute;
  inset-block-end: var(--cb-space-xs);
  inset-inline: 0;
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: var(--cb-space-3xs);
}

.cb-hero__ponto {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: rgb(255 255 255 / 0.55);
  box-shadow: 0 0 0 1px rgb(36 18 9 / 0.18);
  cursor: pointer;
  transition:
    width var(--cb-duration-base) var(--cb-ease-out),
    background-color var(--cb-duration-base) var(--cb-ease-out);
}

/* O ativo vira pílula em vez de mudar só de cor: a diferença de FORMA
   sobrevive a foto clara, foto escura e daltonismo. */
.cb-hero__ponto[aria-selected='true'] {
  width: 22px;
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-coffee-600);
}

/* O alvo de toque é maior que o ponto: 8 px é bonito de ver e impossível de
   acertar com o dedo. */
.cb-hero__ponto::before {
  content: '';
  position: absolute;
  width: var(--cb-touch-target);
  height: var(--cb-touch-target);
  translate: -50% -50%;
  inset-block-start: 50%;
  inset-inline-start: 50%;
}

.cb-hero__ponto {
  position: relative;
}

@media (prefers-reduced-motion: reduce) {
  .cb-hero__slide {
    transition-duration: 1ms;
  }
}


/* Véu do texto quando o hero vira carrossel. Só entra com mais de uma foto:
   a arte original reserva o vazio à esquerda e dispensa véu, mas a segunda
   foto que alguém subir pelo painel provavelmente não reserva nada. */
@media (min-width: 768px) {
  /* O véu é do HERO, não da caixa de texto: a caixa é centrada na vertical e
     não chega às bordas, então pintá-la desenhava uma linha horizontal
     atravessando a foto onde o bloco começava. */
  .cb-hero[data-carrossel='true']::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background: linear-gradient(
      to right,
      rgb(245 234 220 / 0.94) 0%,
      rgb(245 234 220 / 0.86) 34%,
      rgb(245 234 220 / 0) 64%
    );
    pointer-events: none;
  }

  /* O texto sobe acima do véu; a foto fica embaixo dos dois. */
  .cb-hero[data-carrossel='true'] .cb-hero__content {
    position: relative;
    z-index: 1;
  }
}


/* ===========================================================================
   ASSINATURA — ainda desligada
   Existe na página antes de existir no sistema, de propósito: mostra para
   onde o produto vai e mede interesse. O estado desligado é EXPLÍCITO — selo
   escrito, cursor de bloqueado e o motivo logo abaixo. Botão apagado sem
   explicação lê como página quebrada.
   =========================================================================== */
.cb-assinatura {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-3xs);
}

.cb-assinatura__botao {
  display: flex;
  align-items: center;
  gap: var(--cb-space-2xs);
  width: 100%;
  padding: var(--cb-space-2xs) var(--cb-space-xs);
  border: var(--cb-border-thin) dashed var(--cb-line-strong, var(--cb-line));
  border-radius: var(--cb-radius-pill);
  background-color: transparent;
  color: var(--cb-fg);
  text-align: start;
}

/* Tracejado + opacidade: a borda diz "ainda não é sólido" sem depender de
   cor, que some em daltonismo e em tela ruim. */
.cb-assinatura__botao[disabled] {
  opacity: 0.72;
  cursor: not-allowed;
}

.cb-assinatura__icone {
  display: grid;
  place-items: center;
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background-color: var(--cb-yellow-300);
  color: var(--cb-coffee-700);
}

.cb-assinatura__icone svg {
  width: 19px;
  height: 19px;
}

.cb-assinatura__texto {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
}

.cb-assinatura__texto b {
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
}

.cb-assinatura__texto small {
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-xs);
  line-height: 1.3;
}

.cb-assinatura__selo {
  flex-shrink: 0;
  padding: 2px var(--cb-space-3xs);
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-cream-300);
  color: var(--cb-fg-muted);
  font-size: 10px;
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
}

.cb-assinatura__nota {
  margin: 0;
  line-height: 1.35;
}


/* ===========================================================================
   FAIXA DE COOKIES
   Embaixo, acima de tudo, e sem cobrir a tela: modal que trava a página para
   pedir cookie é o tipo de coisa que faz a pessoa fechar a aba.
   =========================================================================== */
.cb-cookies {
  position: fixed;
  inset-block-end: 0;
  inset-inline: 0;
  z-index: var(--cb-layer-cookies);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-xs);
  padding: var(--cb-space-xs) var(--cb-gutter);
  background-color: var(--cb-bg);
  color: var(--cb-fg);
  box-shadow: 0 -6px 24px rgb(36 18 9 / 0.24);
  translate: 0 100%;
  transition: translate 300ms var(--cb-ease-out);
}

.cb-cookies[data-visivel='true'] {
  translate: 0 0;
}

.cb-cookies__texto {
  flex: 1 1 22rem;
  min-width: 0;
}

.cb-cookies__titulo {
  margin: 0 0 2px;
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
}

.cb-cookies__linha {
  margin: 0;
  font-size: var(--cb-text-xs);
  line-height: 1.4;
  opacity: 0.86;
}

.cb-cookies__linha a {
  text-decoration: underline;
}

/* ===========================================================================
   NO CELULAR A FAIXA ENCOLHE — ela estava tapando o botão de compra
   ---------------------------------------------------------------------------
   Medido: 153 px de faixa caindo exatamente sobre o "Quero meu Coffee Blend",
   que vive entre 565 e 639 px numa tela de 844. Somados o header fixo e a
   barra de baixo, um terço da tela estava ocupado antes de a pessoa fazer
   qualquer coisa — e a parte ocupada era justamente o CTA.

   O que encolhe é o CONTINENTE, não o conteúdo: o título sai (a faixa já se
   anuncia sozinha), o texto fica em duas linhas com reticências, e os botões
   sobem para a mesma linha. O link "Como usamos" continua clicável, e os dois
   botões continuam do mesmo tamanho — esconder o "não" para caber seria
   trocar um problema por um pior.
   =========================================================================== */
@media (max-width: 767px) {
  .cb-cookies {
    gap: var(--cb-space-3xs);
    padding-block: var(--cb-space-3xs);
  }

  /* O título repete o que a faixa já diz por existir. */
  .cb-cookies__titulo { display: none; }

  .cb-cookies__texto { flex: 1 1 100%; }

  .cb-cookies__linha {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    font-size: var(--cb-text-2xs);
    line-height: 1.35;
  }

  .cb-cookies__acoes { flex: 1 1 100%; }

  /* Metade da faixa cada um: continuam iguais, e a linha inteira vira alvo. */
  .cb-cookies__acoes .cb-button { flex: 1 1 0; }
}

/* Os dois botões do MESMO tamanho, lado a lado. Recusar precisa custar o
   mesmo clique que aceitar — esconder o "não" é padrão enganoso. */
.cb-cookies__acoes {
  display: flex;
  flex: 0 0 auto;
  gap: var(--cb-space-3xs);
}

.cb-cookies__acoes .cb-button {
  flex: 1 1 auto;
  justify-content: center;
  white-space: nowrap;
}

@media (max-width: 599.98px) {
  .cb-cookies {
    /* Empilha acima da barra de abas: as duas são fixas na base, e sem isto
       a barra cobre justamente os botões de escolha. A altura da barra é
       medida por js/consentimento.js e chega em --cb-cookies-base, porque
       ela varia com a safe-area do aparelho. */
    inset-block-end: var(--cb-cookies-base, 0px);
    flex-direction: column;
    align-items: stretch;
  }

  .cb-cookies__acoes .cb-button {
    flex: 1 1 0;
  }

  /* Em coluna o texto herdava `flex: 1 1 22rem` e esticava, abrindo um vão
     enorme entre a frase e os botões. Empilhado ele ocupa só o que precisa. */
  .cb-cookies__texto {
    flex: 0 0 auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cb-cookies {
    transition-duration: 1ms;
  }
}


/* ===========================================================================
   HERO EM TELA CURTA
   Com a barra do Safari aberta sobra ~660 px de altura; descontando marquee,
   header, stories e abas, o hero fica com ~382 px. O bloco de texto pede 318
   e não sobrava foto: o título caía em cima do pote e ficava ilegível — que
   é como a primeira dobra aparecia no iPhone, embora estivesse boa na tela
   cheia do simulador.

   A saída é tirar peso do TEXTO, não altura da foto: o subtítulo é apoio,
   enquanto manchete, avaliação e botão são a decisão. Some abaixo de 780 px
   de altura — que pega qualquer iPhone com a barra do Safari aberta — e
   volta assim que houver espaço.
   =========================================================================== */
/* ===========================================================================
   NO CELULAR A FOTO SAI DE TRÁS DO TEXTO
   ---------------------------------------------------------------------------
   O hero foi desenhado com a foto de fundo e o texto por cima — funciona no
   desktop, onde a foto é larga e o texto ocupa a coluna da esquerda, sobre
   uma área calma da imagem.

   No celular não existe área calma. Medido num iPhone com a barra do Safari
   aberta (750 px úteis): a foto ocupava os 560 px do hero e o texto começava
   em 364 — bem em cima do pote e dos selos. O resultado é o que se vê no
   aparelho: "H·FORM NUTRITION" sumindo dentro da embalagem e "200 mg de
   cafeína natural" atravessando a manchete.

   A tentativa anterior foi tirar peso do texto — o subtítulo sumia abaixo de
   780 px de altura. Não resolveu porque o problema nunca foi o tamanho do
   texto: era ele e a foto disputarem o mesmo espaço. Some o subtítulo e a
   manchete continua sobre o pote.

   Agora eles EMPILHAM: a foto ocupa uma faixa própria em cima, com altura
   previsível, e o texto vem abaixo em fundo sólido. A foto ganha o produto
   inteiro visível, o texto ganha contraste total, e a soma vira uma conta que
   dá para fechar em vez de uma sobreposição que dá para torcer.
   =========================================================================== */
@media (max-width: 767.98px) {
  .cb-hero {
    /* A altura passa a ser a SOMA das partes, não uma fração da tela. */
    min-height: 0;
    justify-content: flex-start;

    /* SEM CAIXA. Com margem lateral e cantos arredondados, a foto virava um
       retângulo colado sobre o creme — e um degradê só na base não resolve
       isso, porque o que denuncia a caixa são as bordas dos LADOS. Aqui ela
       sangra de borda a borda e perde o raio: deixa de ser um objeto sobre o
       fundo e passa a ser o topo da tela. */
    margin-inline: calc(var(--cb-mosaic-gap) * -1);
    border-radius: 0;
    /* O recorte CONTINUA: o degradê vive dentro da própria foto (é um
       ::after dela), então nunca encostaria nesta borda. Tirar o recorte
       daqui só deixou os slides do carrossel vazarem e criou 27 px de
       rolagem lateral na página — foi o que a auditoria pegou. */
  }

  /* O conteúdo recupera a margem que o hero devolveu. */
  .cb-hero__content {
    padding-inline: var(--cb-pad-inline);
  }

  /* Sai do fundo e entra no fluxo. Os slides continuam absolutos dentro
     dela, então o carrossel não muda. */
  .cb-hero__media {
    position: relative;
    inset: auto;
    z-index: 0;
    width: 100%;
    /* Larga o bastante para o pote e o copo caberem sem corte, curta o
       bastante para sobrar dobra para a manchete e o botão. */
    aspect-ratio: 4 / 3;
  }

  /* O véu existia para dar contraste ao texto SOBRE a foto. Sem sobreposição
     ele só escurece a imagem à toa. */
  .cb-hero::after,
  .cb-hero__veu {
    display: none;
  }

  /* A FOTO DISSOLVE NO FUNDO em vez de terminar numa linha reta.
     Empilhar resolveu a legibilidade e criou uma emenda dura entre a imagem e
     o creme do texto — duas superfícies encostadas, com uma régua no meio.
     Este degradê faz a base da foto virar o próprio fundo, e a emenda
     desaparece.

     22% e não mais: o selo "200 mg de cafeína natural" fica a ~76% da altura
     da foto, e um degradê mais alto começaria a apagá-lo. O que se dissolve é
     a mesa vazia embaixo do pote, que é o que não faz falta. */
  .cb-hero__media::after {
    content: '';
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    /* Alto o bastante para o olho não achar onde começa. Um degradê curto
       ainda lê como emenda — só muda a espessura da régua. */
    height: 34%;
    z-index: 1;
    pointer-events: none;
    /* As paradas intermediárias importam: a rampa linear do CSS concentra a
       mudança no meio e deixa um contorno visível nas pontas. Estas fazem a
       opacidade subir devagar no começo e fechar cedo no fim. */
    background: linear-gradient(
      to bottom,
      rgb(var(--cb-bg-rgb) / 0) 0%,
      rgb(var(--cb-bg-rgb) / 0.08) 26%,
      rgb(var(--cb-bg-rgb) / 0.32) 48%,
      rgb(var(--cb-bg-rgb) / 0.68) 68%,
      rgb(var(--cb-bg-rgb) / 0.92) 84%,
      rgb(var(--cb-bg-rgb) / 1) 94%
    );
  }

  .cb-hero__content {
    position: relative;
    z-index: 1;
    background-color: var(--cb-bg);
    padding-block: var(--cb-space-sm);
  }

  /* OS PONTINHOS VOLTAM PARA A FOTO. Eles são `position: absolute` presos ao
     rodapé do hero — que, empilhado, passou a ser o fim do TEXTO: iam parar
     atrás da barra de baixo, a 290 px da imagem que comandam. Aqui eles saem
     do absoluto e sobem sobre a base da foto, que é onde um controle de
     carrossel se procura. */
  .cb-hero__pontos {
    position: relative;
    inset: auto;
    margin-block-start: calc(var(--cb-space-md) * -1);
    padding-block-end: var(--cb-space-3xs);
  }

  /* Sobre a foto, e não mais sobre o creme do conteúdo. */
  .cb-hero__ponto {
    background-color: rgb(255 255 255 / 0.6);
    box-shadow: 0 1px 3px rgb(36 18 9 / 0.35);
  }

  .cb-hero__ponto[aria-current='true'] {
    background-color: var(--cb-white);
  }

  /* A fileira de vídeos encosta menos no botão e sobra folga até a barra de
     baixo — medido: ela terminava em 682 com a barra começando em 680. */
  .cb-stories--hero {
    margin-block-start: var(--cb-space-xs);
    margin-block-end: var(--cb-space-xs);
  }
}

/* Em tela curta o subtítulo continua saindo: com a foto ocupando faixa
   própria, ele é o que sobra entre a manchete e o botão — e manchete,
   avaliação e botão são a decisão. */
@media (max-width: 767.98px) and (max-height: 780px) {
  .cb-hero--light .cb-hero__sub {
    display: none;
  }

  .cb-hero--light .cb-hero__content {
    gap: var(--cb-space-3xs);
    padding-block: var(--cb-space-2xs);
  }

  /* Manchete um ponto menor: são três linhas, e cada uma custa foto. */
  .cb-hero--light .cb-hero__title {
    font-size: clamp(1.75rem, 8vw, 2.25rem);
  }
}


/* O "/porção" é unidade, não valor: menor e mais leve, para o preço ser o
   que o olho pega ao comparar as quatro opções. */
.cb-choice__meta small {
  font-size: 0.82em;
  opacity: 0.75;
}


/* ===========================================================================
   ALVO DE TOQUE NO CELULAR
   A auditoria achou dezenas de links e botões entre 29 e 38 px de altura. O
   mínimo confortável para dedo é 44 px (WCAG 2.5.5): abaixo disso a pessoa
   erra o alvo — no rodapé é irritante, num botão de compra é venda perdida.

   O ALVO cresce, o desenho não: padding e min-height em vez de fonte maior,
   para a aparência continuar a mesma e só a área clicável aumentar.
   =========================================================================== */
@media (max-width: 767.98px) {
  /* `.cb-footer` NÃO existe — o rodapé é <footer class="cb-scheme-espresso">
     e os blocos usam .cb-footer__algo. Mirar na classe do bloco é o que
     funciona aqui. */
  .cb-footer__list a,
  .cb-footer__legal a,
  .cb-drawer__link {
    display: inline-flex;
    align-items: center;
    min-height: var(--cb-touch-target);
  }

  .cb-button--sm {
    min-height: var(--cb-touch-target);
  }
}


/* O selo invisível que só reserva a linha: some da leitura, mantém a altura,
   e é isso que faz o nome do kit começar na mesma altura nas quatro opções. */
.cb-choice__selo--vazio {
  background: none;
  pointer-events: none;
}


/* ===========================================================================
   O TEMPLATE MANDA NO TAMANHO DA IMAGEM
   `aspect-ratio` sozinho CEDE quando o conteúdo pede mais altura: uma foto
   1120×1400 dentro de uma caixa 1:1 de 278 px empurrava a caixa para 348 e o
   cartão ficava mais alto que os vizinhos na mesma fileira. `height: 100%`
   não segura, porque o pai não tem altura fixa para os 100% resolverem.

   Com a imagem em `position: absolute`, ela sai do fluxo e passa a obedecer a
   caixa — qualquer arquivo, de qualquer proporção, encaixa no formato que o
   template pede. É o que permite subir foto sem pensar em tamanho.
   =========================================================================== */
/* `.cb-hero__media` fica de FORA desta lista: ele já é `position: absolute`
   (é o fundo do hero, atrás do texto), e forçá-lo a `relative` o tirava do
   lugar — o hero ficava sem foto nenhuma. Só entram aqui os containers que
   são caixa de conteúdo no fluxo normal. */
.cb-card__media,
.cb-gallery__main,
.cb-gallery__thumbs li,
.cb-together__item .cb-together__media {
  position: relative;
  /* `width: 100%` é obrigatório junto com a imagem absoluta logo abaixo: sem
     conteúdo no fluxo, o container não tem de onde tirar largura e colapsa —
     a foto principal da galeria virou um quadrado de 54 px. */
  width: 100%;
}

/* `.cb-card__media` FICA DE FORA do recorte, e não por esquecimento: o selo
   amarelo do cartão é montado na borda de baixo da foto com
   `translateY(50%)`, metade para dentro e metade para fora. Recortar o
   container corta o selo ao meio — foi o que aconteceu quando esta regra
   listava os quatro juntos. Lá em cima ele já resolve isso com
   `overflow: visible` e o arredondamento na própria <img>; aqui é só não
   desfazer. */
.cb-gallery__main,
.cb-gallery__thumbs li,
.cb-together__item .cb-together__media {
  overflow: hidden;
}

.cb-card__media > img,
.cb-card__media > picture > img,
.cb-gallery__main > img,
.cb-gallery__thumbs li > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ============================================================================
   ASSINATURA
   ----------------------------------------------------------------------------
   Só o que a página de assinatura precisa e não existia. Tudo que já tinha nome
   na casa (botão, selo, faq, cabeçalho de seção) foi reaproveitado — classe
   nova só onde havia forma nova.

   Mobile-first, como o resto: a coluna única é o padrão e o desktop é o
   acréscimo, não o contrário.
   ========================================================================== */

/* --- Abertura --------------------------------------------------------------- */
.cb-assina-hero__grid {
  display: grid;
  gap: var(--cb-space-lg);
}

.cb-assina-hero__acoes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cb-space-sm);
  margin-block-start: var(--cb-space-md);
}

/* Os selos são fato, não enfeite: ficam em linha e quebram sozinhos no celular. */
.cb-assina-hero__selos {
  display: flex;
  flex-wrap: wrap;
  gap: var(--cb-space-2xs) var(--cb-space-md);
  margin-block-start: var(--cb-space-md);
  padding: 0;
  list-style: none;
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-sm);
}

.cb-assina-hero__selos li {
  display: flex;
  align-items: center;
  gap: var(--cb-space-3xs);
}

.cb-assina-hero__selos li::before {
  content: "";
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
  background: var(--cb-accent);
}

.cb-assina-hero__foto {
  margin: 0;
  aspect-ratio: 4 / 3;
  border-radius: var(--cb-radius-lg);
  overflow: hidden;
}

.cb-assina-hero__foto img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* --- Os três planos --------------------------------------------------------- */
.cb-planos {
  display: grid;
  gap: var(--cb-space-md);
}

.cb-plano {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--cb-bg);
  border: var(--cb-border-thin) solid var(--cb-line);
  border-radius: var(--cb-radius-lg);
  overflow: hidden;
}

/* O plano do meio é o que a marca quer empurrar; ele ganha borda de destaque,
   não um "mais vendido" inventado. */
.cb-plano--destaque {
  border-color: var(--cb-accent);
  box-shadow: var(--cb-shadow-md);
}

.cb-plano__selo {
  position: absolute;
  inset-block-start: var(--cb-space-sm);
  inset-inline-start: var(--cb-space-sm);
  z-index: 1;
}

.cb-plano__foto {
  margin: 0;
  aspect-ratio: 1 / 1;
  background: rgb(var(--cb-fg-rgb) / 0.04);
}

.cb-plano__foto img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.cb-plano__corpo {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  padding: var(--cb-space-md);
}

.cb-plano__nome {
  margin: 0;
  font-size: var(--cb-text-h4);
  font-weight: var(--cb-weight-bold);
}

.cb-plano__preco {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 0.2em;
  color: var(--cb-accent);
  font-variant-numeric: tabular-nums;
}

.cb-plano__preco span {
  font-size: var(--cb-text-h2);
  font-weight: var(--cb-weight-bold);
  line-height: 1;
}

.cb-plano__preco small {
  font-size: var(--cb-text-sm);
  color: var(--cb-fg-muted);
}

/* A conta por pote é o que compara os planos entre si, e a âncora do avulso é
   o que compara a assinatura com não assinar. As duas na mesma linha. */
.cb-plano__pote {
  margin: 0;
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-sm);
}

.cb-plano__lista {
  margin: var(--cb-space-2xs) 0 var(--cb-space-sm);
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-3xs);
  font-size: var(--cb-text-sm);
}

.cb-plano__lista li {
  display: flex;
  gap: var(--cb-space-2xs);
}

.cb-plano__lista li::before {
  content: "✓";
  color: var(--cb-success);
  font-weight: var(--cb-weight-bold);
}

.cb-plano__corpo .cb-button {
  margin-block-start: auto;
}

.cb-planos__nota {
  margin-block-start: var(--cb-space-md);
  text-align: center;
}

/* --- Brindes ---------------------------------------------------------------- */
.cb-brindes {
  display: grid;
  gap: var(--cb-space-lg);
}

.cb-regua {
  margin: var(--cb-space-md) 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-sm);
}

.cb-regua__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--cb-space-sm);
  align-items: start;
  padding-block-start: var(--cb-space-sm);
  border-block-start: var(--cb-border-thin) solid rgb(255 255 255 / 0.18);
}

.cb-regua__item:first-child {
  padding-block-start: 0;
  border-block-start: 0;
}

.cb-regua__marca {
  padding: 0.25rem 0.7rem;
  border-radius: var(--cb-radius-pill);
  background: var(--cb-yellow-500);
  color: var(--cb-coffee-600);
  font-size: var(--cb-text-xs);
  font-weight: var(--cb-weight-bold);
  white-space: nowrap;
}

.cb-regua__texto {
  margin: 0;
  font-size: var(--cb-text-sm);
}

/* A condição dos 6 meses fica num bloco próprio: é a letra miúda, e letra
   miúda escondida no meio do texto é o que gera reclamação depois. */
.cb-brindes__regra {
  margin-block-start: var(--cb-space-md);
  padding: var(--cb-space-sm);
  border-radius: var(--cb-radius-md);
  background: rgb(255 255 255 / 0.08);
}

.cb-brindes__foto {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
}

.cb-brindes__foto img {
  display: block;
  width: 100%;
  height: auto;                 /* sem isto o height="1100" do HTML achata a foto */
  border-radius: var(--cb-radius-lg);
}

/* --- Três passos ------------------------------------------------------------ */
.cb-passos {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--cb-space-md);
  counter-reset: passo;
}

.cb-passos__item {
  display: flex;
  flex-direction: column;
  gap: var(--cb-space-2xs);
  padding: var(--cb-space-md);
  background: var(--cb-bg);
  border-radius: var(--cb-radius-lg);
}

.cb-passos__numero {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background: var(--cb-yellow-500);
  color: var(--cb-coffee-600);
  font-weight: var(--cb-weight-bold);
}

.cb-passos__titulo {
  margin: 0;
  font-size: var(--cb-text-h4);
}

/* --- Fechamento -------------------------------------------------------------- */
.cb-assina-fecho__inner {
  display: grid;
  gap: var(--cb-space-md);
  align-items: center;
}

/* --- Desktop ----------------------------------------------------------------- */
@media (min-width: 62rem) {
  .cb-assina-hero__grid {
    grid-template-columns: 1.05fr 0.95fr;
    align-items: center;
    gap: var(--cb-space-2xl);
  }

  .cb-planos {
    grid-template-columns: repeat(3, 1fr);
    align-items: stretch;
  }

  .cb-brindes {
    grid-template-columns: 1.1fr 0.9fr;
    align-items: center;
    gap: var(--cb-space-2xl);
  }

  .cb-passos {
    grid-template-columns: repeat(3, 1fr);
  }

  .cb-assina-fecho__inner {
    grid-template-columns: 1fr auto;
    gap: var(--cb-space-xl);
  }
}

/* ===========================================================================
   POPUP DO CUPOM — cadastro em troca do desconto de primeira compra
   ---------------------------------------------------------------------------
   Cartão centrado no celular, com a foto em faixa no topo; a partir de 48rem
   a foto vai para o lado e ocupa a altura inteira. A foto nunca é o que
   rola: quem rola é o corpo, para o botão de fechar e o selo ficarem no
   lugar com o teclado do celular aberto.

   Altura em dvh pelo mesmo motivo da compra rápida: em vh a barra de
   endereço do Safari entra na conta e o botão de enviar some atrás dela.
   =========================================================================== */
.cb-cupom {
  width: calc(100% - 2 * var(--cb-space-sm));
  max-width: 26rem;
  max-height: 94dvh;
  margin: auto;
  padding: 0;
  border: 0;
  border-radius: var(--cb-radius-lg);
  background-color: var(--cb-bg);
  color: var(--cb-fg);
  box-shadow: var(--cb-shadow-lg);
  overflow: hidden;
}

.cb-cupom[open] {
  display: flex;
  flex-direction: column;
  animation: cb-cupom-entra 0.28s var(--cb-ease-out);
}

.cb-cupom::backdrop {
  background-color: rgb(28 14 7 / 0.62);
}

@keyframes cb-cupom-entra {
  from { opacity: 0; transform: translateY(12px) scale(0.98); }
}

@media (prefers-reduced-motion: reduce) {
  .cb-cupom[open] { animation: none; }
}

.cb-cupom__foto {
  position: relative;
  flex-shrink: 0;
  height: 8.5rem;
  background-color: var(--cb-coffee-800);
}

/* height: 100% e não só largura — a <img> traz width/height no HTML, e sem
   isto o atributo vira altura fixa e a foto estica. */
.cb-cupom__foto img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 58%;
}

/* O número do desconto, no canto da foto. Repete o título de propósito: é o
   que se lê antes de qualquer palavra. */
.cb-cupom__selo {
  position: absolute;
  inset-inline-start: var(--cb-space-sm);
  inset-block-end: calc(-1 * var(--cb-space-md));
  display: grid;
  place-content: center;
  width: 4.75rem;
  height: 4.75rem;
  margin: 0;
  border-radius: 50%;
  background-color: var(--cb-yellow-500);
  color: var(--cb-coffee-600);
  font-size: var(--cb-text-xs);
  font-weight: var(--cb-weight-bold);
  letter-spacing: var(--cb-tracking-wide);
  line-height: 1;
  text-align: center;
  box-shadow: var(--cb-shadow-md);
  transform: rotate(-8deg);
}

.cb-cupom__selo b {
  display: block;
  font-size: 1.5rem;
  letter-spacing: var(--cb-tracking-heading);
}

.cb-cupom__fechar.cb-icon-button {
  position: absolute;
  inset-block-start: var(--cb-space-2xs);
  inset-inline-end: var(--cb-space-2xs);
  z-index: 1;
  border-radius: 50%;
  background-color: var(--cb-bg);
  box-shadow: var(--cb-shadow-sm);
}

.cb-cupom__fechar svg {
  width: 20px;
  height: 20px;
}

.cb-cupom__corpo {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--cb-space-lg) var(--cb-space-md) var(--cb-space-md);
}

.cb-cupom__sobre {
  margin: 0 0 var(--cb-space-2xs);
}

.cb-cupom__titulo {
  margin: 0;
  font-size: clamp(1.625rem, 1.3rem + 1.6vw, 2.125rem);
  line-height: 1.05;
}

/* "10% OFF" não quebra no meio, e a letra de mão desce para a linha dela:
   solta ao lado, a largura do cartão decidia onde o título partia. */
.cb-cupom__titulo b {
  white-space: nowrap;
}

.cb-cupom__titulo .cb-headline__script {
  display: block;
  width: fit-content;
  margin: 0.18em 0 0;
}

.cb-cupom__apoio {
  margin: var(--cb-space-2xs) 0 0;
  color: var(--cb-fg-muted);
  font-size: var(--cb-ui-body);
  line-height: 1.4;
}

.cb-cupom__form {
  display: grid;
  gap: var(--cb-space-xs);
  margin-block-start: var(--cb-space-sm);
}

.cb-cupom__form .cb-field__label {
  font-size: var(--cb-text-xs);
}

/* 16px cravados: abaixo disso o Safari do iPhone dá zoom na página ao focar
   o campo, e o popup sai do quadro. */
.cb-cupom__form .cb-input {
  border-radius: var(--cb-radius-sm);
  background-color: var(--cb-white);
  font-size: 1rem;
}

.cb-cupom__form .cb-input[aria-invalid="true"] {
  border-color: var(--cb-danger);
}

.cb-cupom__form .cb-button {
  margin-block-start: var(--cb-space-3xs);
}

.cb-cupom__erro {
  margin: 0;
  color: var(--cb-danger);
  font-size: var(--cb-text-xs);
  font-weight: var(--cb-weight-medium);
}

.cb-cupom__erro--geral {
  text-align: center;
}

/* Fora da vista e fora do foco, mas dentro do formulário: é o que separa
   gente de robô. display:none não serve — muito robô pula campo escondido. */
.cb-cupom__mel {
  position: absolute;
  inset-inline-start: -200vw;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.cb-cupom__aviso {
  margin: var(--cb-space-xs) 0 0;
  color: var(--cb-fg-muted);
  font-size: var(--cb-text-2xs);
  line-height: 1.45;
  text-align: center;
}

.cb-cupom__aviso a {
  color: inherit;
  text-decoration: underline;
}

/* "Agora não" do tamanho de um botão, não de um rodapé: recusar tem que ser
   tão fácil quanto aceitar. */
.cb-cupom__depois {
  display: block;
  min-height: var(--cb-touch-target);
  margin: var(--cb-space-3xs) auto 0;
  padding-inline: var(--cb-space-sm);
  border: 0;
  background: none;
  color: var(--cb-fg);
  font: inherit;
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

/* --- Cupom entregue ---------------------------------------------------------- */
.cb-cupom__codigo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--cb-space-xs);
  margin-block: var(--cb-space-md);
  padding: var(--cb-space-xs) var(--cb-space-xs) var(--cb-space-xs) var(--cb-space-md);
  border: var(--cb-border-thick) dashed var(--cb-coffee-600);
  border-radius: var(--cb-radius-md);
  background-color: var(--cb-white);
}

.cb-cupom__codigo output {
  font-size: clamp(1.25rem, 1rem + 1.4vw, 1.625rem);
  font-weight: var(--cb-weight-bold);
  letter-spacing: 0.08em;
  overflow-wrap: anywhere;
}

.cb-cupom__copiar {
  flex-shrink: 0;
  min-height: var(--cb-touch-target);
  padding-inline: var(--cb-space-sm);
  border: 0;
  border-radius: var(--cb-radius-pill);
  background-color: var(--cb-yellow-500);
  color: var(--cb-coffee-600);
  font: inherit;
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-bold);
  cursor: pointer;
}

.cb-cupom__copiar:hover {
  background-color: var(--cb-yellow-400);
}

.cb-cupom :focus-visible {
  outline: var(--cb-focus-width) solid var(--cb-coffee-600);
  outline-offset: 2px;
}

@media (min-width: 48rem) {
  .cb-cupom {
    max-width: 50rem;
  }

  .cb-cupom[open] {
    flex-direction: row;
  }

  .cb-cupom__foto {
    flex: 0 0 44%;
    height: auto;
    min-height: 31rem;
  }

  .cb-cupom__foto img {
    position: absolute;
    inset: 0;
    object-position: 50% 50%;
  }

  .cb-cupom__selo {
    inset-inline-start: auto;
    inset-inline-end: var(--cb-space-md);
    inset-block-end: var(--cb-space-md);
    width: 6rem;
    height: 6rem;
    font-size: var(--cb-text-sm);
  }

  .cb-cupom__selo b {
    font-size: 2rem;
  }

  .cb-cupom__corpo {
    flex: 1;
    align-self: center;
    max-height: 94dvh;
    padding: var(--cb-space-xl);
  }

  .cb-cupom__fechar.cb-icon-button {
    inset-block-start: var(--cb-space-xs);
    inset-inline-end: var(--cb-space-xs);
    box-shadow: none;
  }
}

/* --- Carrinho: lembrete do cupom --------------------------------------------- */
.cb-cart__cupom {
  margin: var(--cb-space-xs) 0;
  padding: var(--cb-space-2xs) var(--cb-space-xs);
  border: var(--cb-border-thin) dashed var(--cb-line);
  border-radius: var(--cb-radius-sm);
  font-size: var(--cb-text-sm);
  line-height: 1.35;
  text-align: center;
}

/* --- Newsletter: resposta do envio ------------------------------------------- */
.cb-newsletter__form {
  flex-wrap: wrap;
}

.cb-newsletter__form .cb-input {
  flex: 1 1 12rem;
}

.cb-newsletter__aviso {
  flex-basis: 100%;
  margin: 0;
  font-size: var(--cb-text-sm);
  font-weight: var(--cb-weight-medium);
}
