/* economizecupom — folha única, sem build. Mobile-first.
 *
 * CLARO, e só. `color-scheme: light` trava o tema mesmo com o sistema no
 * escuro: site de cupom vive de parecer confiável, e fundo escuro lê como
 * spam nesse nicho. Não é preferência de gosto, é o padrão do mercado
 * (Cuponomia, Pelando, Promobit, Méliuz — todos claros).
 *
 * Cupom COM código é uma LISTA de linhas, não um grid de cards. Quem procura
 * cupom varre a página atrás do maior desconto: linha de altura uniforme com
 * o número sempre na mesma coluna faz essa varredura acontecer no reflexo.
 * A identidade visual é o TICKET: picote tracejado, furos nas bordas e o
 * canhoto com o número — o objeto físico "cupom" traduzido pra interface.
 *
 * Oferta SEM código é outra coisa: um PRODUTO com foto e preço, não um
 * ticket pra copiar. Essas viram um GRID de cards (ver `.cupons-grid` /
 * `.cupom-grid`) — estante de produto, não fileira de linhas. */

:root {
  color-scheme: light;

  --bg:          #f6f8f7;
  --superficie:  #ffffff;
  --superficie-2:#f0f4f2;
  --borda:       #e2e8e4;
  --borda-forte: #c6d2ca;
  --texto:       #0c1b17;
  --texto-fraco: #56675f;
  --tinta:       #0d2a4f;   /* navy da marca (a metade azul da etiqueta): rodapé, modal, contrastes */

  --verde:       #00994f;
  --verde-forte: #007a3f;
  --verde-escuro:#045c33;
  --verde-luz:   #e3f6ec;
  --lima:        #c8f169;   /* acento elétrico: grifos, marquee, detalhes */
  --lima-tinta:  #3c5a00;

  --vermelho:    #d92d20;
  --ouro:        #8a5a00;
  --ouro-luz:    #ffefc2;

  /* Fallback pra loja sem plataforma conhecida. */
  --loja-cor:    #64748b;
  --loja-tinta:  #475569;
  --loja-suave:  #f1f5f9;
  --loja-chip-texto: #ffffff;

  --fonte-display: "Bricolage Grotesque", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --fonte-corpo: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --raio:   16px;
  --sombra: 0 1px 2px rgba(12, 27, 23, .05);
  --sombra-alta: 0 2px 6px rgba(12, 27, 23, .06), 0 18px 36px -16px rgba(12, 27, 23, .28);

  /* Sombras do card de cupom: presença clara no repouso, e a versão alta pro
   * cupom apontado por deep link (`.cupom:target`) — o hover não mexe mais
   * no card, ver `.cupom`.
   * SÓ difusa, sem camada de contato: a sombra de contato desenha uma linha
   * escura colada na borda de baixo, que passa por trás da boca dos furos do
   * picote e suja o recorte. A difusa (offset alto, blur grande, spread
   * negativo) cai bem abaixo da borda e o furo fica limpo. */
  --cupom-sombra: 0 12px 24px -14px rgba(12, 27, 23, .20);
  --cupom-sombra-alta: 0 22px 40px -18px rgba(12, 27, 23, .32);
}

/* ---- cores das lojas ----
 * NÃO existe classe por loja aqui de propósito. Com dezenas de lojas,
 * `.loja--magalu { ... }` significaria um deploy por loja nova. As quatro
 * variáveis chegam num atributo `style` inline, calculadas em PHP a partir
 * de `lojas.cor` e `lojas.cor_texto` (ver Html::estiloDaLoja).
 * O que está no :root é só o fallback de loja sem cor cadastrada. */

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--texto);
  font: 16px/1.55 var(--fonte-corpo);
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--verde-forte); }

.wrap { width: min(1060px, 100% - 2rem); margin-inline: auto; }

/* Seção que sangra até as bordas da tela mesmo dentro de um .wrap
 * (o main é .wrap; hero e marquee pintam a faixa inteira). */
.sangra { margin-inline: calc(50% - 50vw); }

/* Trava lateral. O `clip` no body sozinho não segura: quem manda na rolagem é
 * o viewport, e ele só recebe o overflow do ELEMENTO RAIZ — no celular a
 * página continuava deslizando de lado sobre o que o marquee (rotate+scale) e
 * o `50vw` do .sangra estouram.
 *
 * `hidden` no html de propósito, e não `clip`: a propagação de `hidden` pro
 * viewport é antiga e universal, enquanto a de `clip` é recente e é
 * justamente a que falha em Safari mais velho. Como o valor propaga, o html
 * NÃO vira container de rolagem — o `position: sticky` do topo continua
 * grudando na tela. O `clip` no body fica como segunda camada: corta a
 * pintura sem criar rolagem (`hidden` no body, esse sim, mataria o sticky). */
html { overflow-x: hidden; }
body { overflow-x: clip; }

.pular { position: absolute; left: -9999px; }
.pular:focus {
  left: 1rem; top: .5rem; z-index: 100;
  background: var(--superficie); padding: .5rem .75rem; border-radius: 8px;
}
:focus-visible { outline: 3px solid var(--verde); outline-offset: 2px; }

/* Entrada suave dos cards. O estado "escondido" só existe com JS ativo
 * (html.js), senão a página sem JS nasceria invisível.
 *
 * Tudo em :where() (especificidade zero): sem isso, `html.js .surge--visto`
 * ganha de qualquer `.card:hover { transform }` e mata o lift de hover de
 * todo card que entra animado — e o shorthand `transition` daqui atropela as
 * transições próprias do card. Em troca, cada card .surge precisa incluir
 * opacity/transform na PRÓPRIA lista de transition pra entrada animar. */
html:where(.js) :where(.surge) {
  opacity: 0; transform: translateY(14px);
  transition: opacity .5s ease, transform .5s cubic-bezier(.2, .7, .3, 1);
}
html:where(.js) :where(.surge--visto) { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.js .surge { opacity: 1; transform: none; transition: none; }
}

/* ============ topo ============ */

.topo {
  position: sticky; top: 0; z-index: 20;
  background: rgba(255, 255, 255, .92);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  backdrop-filter: blur(14px) saturate(1.4);
  border-bottom: 1px solid var(--borda);
  transition: box-shadow .25s;
}
/* Estado "rolado" (classe posta pelo app.js): ganha sombra pra descolar do
 * conteúdo que passa por baixo. */
.topo--rolado { box-shadow: 0 10px 30px -18px rgba(12, 27, 23, .35); }

.topo__linha { display: flex; align-items: center; gap: .85rem; padding: .62rem 0; }

.marca {
  display: inline-flex; align-items: center; gap: .6rem;
  flex: none;
  font-family: var(--fonte-display);
  font-size: 1.28rem; font-weight: 700; letter-spacing: -.03em;
  text-decoration: none; color: var(--texto);
}
.marca strong { color: var(--verde); font-weight: 800; }
/* A marca é a arte real (etiqueta navy + cupom verde), não um ícone colorível:
 * é raster porque o desenho tem volume e sombra que um SVG chapado perderia.
 * O srcset 2x cobre retina; width/height reservam o espaço antes de carregar. */
.marca__mark { width: 47px; height: 38px; flex: none; transition: transform .25s cubic-bezier(.3, 1.6, .5, 1); }
.marca:hover .marca__mark { transform: rotate(-8deg) scale(1.06); }

/* Tagline embaixo do nome: transforma o logo em promessa. */
.marca__texto { display: inline-block; line-height: 1.05; }
.marca__tag {
  display: block;
  font-family: var(--fonte-corpo);
  font-size: .62rem; font-weight: 650; letter-spacing: .14em;
  text-transform: uppercase; color: var(--texto-fraco);
  margin-top: .2rem;
}

.topo__busca-principal {
  flex: 1 1 380px;
  min-width: 240px;
  max-width: 560px;
  margin-inline: auto;
}

.menu { display: flex; gap: .25rem; flex: none; align-items: center; }
.menu__item {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .5rem .8rem; border-radius: 999px;
  font-size: .88rem; font-weight: 650; text-decoration: none;
  color: var(--texto-fraco); border: 1px solid transparent;
  background: transparent;
  transition: transform .15s, box-shadow .15s, border-color .15s,
              background .15s, color .15s;
}
/* Ícones do WhatsApp/Telegram ao lado de "Grupos" no menu — cor da PRÓPRIA
   marca (não currentColor: o link muda de cinza pra branco pra preto
   conforme hover/atual, e os ícones precisam continuar reconhecíveis nos
   três estados, não sumir junto). */
.menu__icones { display: inline-flex; align-items: center; gap: .3rem; }
.menu__icones .btn-grupo__icone { width: .92rem; height: .92rem; }
.menu__icones .btn-grupo__icone:first-child { color: #25d366; }
.menu__icones .btn-grupo__icone:last-child { color: #29a9eb; }

/* Ponto na cor da loja: identifica a marca sem precisar carregar logo.
   Continua aqui porque o admin ainda usa; no site quem manda é .marca-loja. */
.menu__ponto {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--loja-cor); flex: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--loja-cor) 18%, transparent);
  transition: box-shadow .15s;
}
/* No hover o chip veste a própria loja: fundo pálido e tinta da marca —
 * as variáveis já chegam inline em cada item (Html::estiloDaLoja). */
.menu__item:hover {
  background: var(--verde-luz); color: var(--verde-escuro);
  border-color: color-mix(in srgb, var(--verde) 18%, transparent);
  transform: translateY(-1px); box-shadow: var(--sombra);
}
.menu__item:hover .menu__ponto {
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--loja-cor) 28%, transparent);
}
/* Navy da marca, não o quase-preto de texto: o item ativo é a única peça
 * escura do topo, e vestindo a mesma tinta do rodapé ele fecha a página em
 * vez de parecer um botão de outro sistema. */
.menu__item--atual {
  background: var(--tinta); color: #fff; border-color: var(--tinta);
}
.menu__item--atual:hover {
  background: var(--tinta); color: #fff; border-color: var(--tinta);
  transform: none; box-shadow: none;
}
/* ---- topo no celular: navegação em cima, busca embaixo ---- */
@media (max-width: 719px) {
  .topo__linha { flex-wrap: wrap; gap: .55rem; padding: .55rem 0 .65rem; align-items: center; }
  .marca { font-size: 1.15rem; }
  .marca__mark { width: 40px; height: 32px; }
  .topo__busca-principal {
    order: 3;
    flex: none;
    width: 100%;
    min-width: 0;
    max-width: none;
    margin: 0;
  }

  .menu {
    order: 2;
    width: 100%;
    margin-left: 0;
    flex-wrap: nowrap;
    gap: .2rem;
    background: var(--superficie-2);
    border-radius: 12px;
    padding: .22rem;
    overflow: visible;
  }
  .menu__item {
    flex: 1 1 0;
    justify-content: center;
    padding: .48rem .3rem;
    border-radius: 9px;
    font-size: .84rem;
  }
  .menu__item:hover { transform: none; box-shadow: none; }
}

@media (max-width: 380px) {
  .marca { gap: .45rem; font-size: 1.05rem; }
  .marca__tag { display: none; }
  .menu__item { padding-inline: .45rem; }
}

/* ============ marca da loja (logo ou monograma) ============ */

/* Emitido por Html::marcaDaLoja(). A logo real vive num quadro BRANCO, sempre:
 * logo de loja é desenhada pra fundo claro e muitas têm texto escuro — sobre a
 * própria cor da marca, metade delas sumiria. O quadro também é o que mantém a
 * linha uniforme quando as logos têm proporções diferentes (a da Amazon é
 * larga, a do ML é quadrada): o `contain` encaixa dentro da mesma caixa. */
.marca-loja {
  --h: 26px;
  display: inline-grid; place-items: center; flex: none;
  width: var(--h); height: var(--h); border-radius: 7px;
  overflow: hidden;
  background: #fff; border: 1px solid var(--borda);
}
.marca-loja__img {
  display: block; width: 100%; height: 100%;
  object-fit: contain; padding: 2px;
}

/* Sem logo cadastrada: iniciais na cor da própria loja. */
.marca-loja--mono {
  background: var(--loja-cor); color: var(--loja-chip-texto);
  border-color: transparent;
  font-family: var(--fonte-display);
  font-weight: 800; letter-spacing: -.02em; line-height: 1;
  font-size: .72rem;
}

/* Sobre superfície já colorida (o ticket do hero), o monograma inverte:
   fundo branco e as iniciais na tinta escura da marca. */
.marca-loja--claro.marca-loja--mono {
  background: #fff; color: var(--loja-tinta);
}

.marca-loja--xs { --h: 20px; border-radius: 6px; }
.marca-loja--xs.marca-loja--mono { font-size: .58rem; }

/* Meio-termo pro tile compacto: o --md ocupa altura demais quando a marca
   fica AO LADO do nome em vez de acima dele. */
.marca-loja--sm { --h: 28px; border-radius: 8px; }
.marca-loja--sm.marca-loja--mono { font-size: .74rem; }

.marca-loja--md { --h: 38px; border-radius: 10px; }
.marca-loja--md.marca-loja--mono { font-size: 1rem; }

.marca-loja--lg { --h: 60px; border-radius: 14px; }
.marca-loja--lg.marca-loja--mono { font-size: 1.6rem; }
.marca-loja--lg .marca-loja__img { padding: 6px; }

/* --- placa do tiquete do hero ---
 * Aqui a logo substitui o nome, então ela não pode ser um quadradinho de 20px:
 * wordmark deitado espremido em quadrado vira borrão. A caixa fixa só a ALTURA
 * e solta a largura, e mantém o fundo branco — o tiquete é pintado com a cor da
 * marca, e sobre ela as logos de tinta escura (Amazon, C&A) sumiriam. */
/* flex e não o inline-grid herdado: em grid a imagem é esticada pela faixa da
 * coluna em vez de seguir a própria proporção. A placa não tem largura
 * própria — quem manda é a imagem, e ela se ajusta. */
.marca-loja--tiquete {
  --h: 34px;
  display: flex; align-items: center; justify-content: center;
  width: auto; height: var(--h); min-width: 0;
  padding-inline: .3rem; border-radius: 8px; border-color: transparent;
}
/* A ALTURA é o valor fixo e a largura vem da proporção; o contrário (altura
 * automática limitada por max-height) fica circular dentro de uma placa cuja
 * largura depende justamente da imagem, e o navegador resolve o impasse
 * espremendo a logo — a de 300x69 saía com 40px de largura.
 *
 * min/max-width são os batentes: o teto é a metade do tiquete (212px de
 * largura mínima, ~80px por coluna depois do padding e do vão do picote) e o
 * piso reserva espaço antes de a logo chegar do CDN, pra placa não nascer
 * colapsada. Com `object-fit: contain` os dois só acrescentam margem em volta
 * da logo, nunca a deformam. */
.marca-loja--tiquete .marca-loja__img {
  flex: none;
  height: calc(var(--h) - 8px); width: auto;
  min-width: 44px; max-width: 70px;
  padding: 0;
}

/* --- faixa: altura fixa, largura livre ---
 * Logo de loja no mundo real é wordmark deitado (a da Amazon é 3,3:1, a do
 * Magalu 2,6:1). Espremida num quadrado de 20px vira borrão ilegível — medido,
 * não suposto. Então onde a marca é o assunto (tile e topo da loja) a caixa
 * solta a largura e some: sem moldura, sem fundo, a logo deitada no card.
 *
 * O monograma NÃO acompanha: sem logo, o quadrado colorido continua sendo a
 * melhor forma, então ele reconquista largura e fundo logo abaixo. */
/* Nada de dimensão fixa aqui: a logo é limitada por max-height E max-width,
 * com width/height em auto. Assim o navegador encaixa a imagem inteira na
 * proporção dela — wordmark largo bate no limite de largura e perde altura
 * sozinho, em vez de estourar a caixa e ser cortado pelo overflow. */
.marca-loja--faixa {
  --larg: 150px;
  width: auto; height: auto; max-width: var(--larg);
  /* Reserva a altura antes da imagem chegar: sem isso a caixa nasce com zero
     de altura e o tile pula quando a logo carrega. */
  min-height: var(--h);
  overflow: visible;
  background: none; border: 0; border-radius: 0;
  justify-items: start; align-items: center;
}
/* max-width em px e não em %: o pai tem largura automática (depende deste
   filho), e uma porcentagem contra largura indefinida colapsa a imagem a 0. */
.marca-loja--faixa .marca-loja__img {
  width: auto; height: auto;
  max-height: var(--h); max-width: var(--larg);
  padding: 0;
}
/* Sem logo, o monograma retoma o quadrado: é a melhor forma pra duas letras. */
.marca-loja--faixa.marca-loja--mono {
  width: var(--h); height: var(--h);
  background: var(--loja-cor); border-radius: 10px;
  justify-items: center;
}
.marca-loja--lg.marca-loja--faixa { --larg: 210px; }
.marca-loja--lg.marca-loja--faixa.marca-loja--mono { border-radius: 14px; }
.marca-loja--lg.marca-loja--faixa.marca-loja--mono { width: 60px; border-radius: 14px; }

/* ============ marca da categoria (emoji) ============ */

/* Emitido por Html::categoryMark(). Sem logo pra cair de volta como as lojas
 * têm — o emoji É a marca, então não carrega caixa nem fundo: só o glifo,
 * do tamanho que o contexto pedir. */
.marca-categoria {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; line-height: 1;
}
.marca-categoria--xs { font-size: 1rem; }
.marca-categoria--sm { font-size: 1.35rem; }
.marca-categoria--md { font-size: 1.75rem; }
.marca-categoria--lg { font-size: 2.75rem; }

/* ============ hero ============ */

/* O hero sai do .wrap pra pintar a faixa inteira: gradientes suaves de menta
 * e lima sobre o claro — vivo sem virar "dark spam". */
.hero-faixa {
  position: relative; overflow: clip;
  background:
    radial-gradient(560px 320px at 12% -10%, color-mix(in srgb, var(--lima) 34%, transparent), transparent 70%),
    radial-gradient(640px 400px at 88% 0%, color-mix(in srgb, var(--verde) 14%, transparent), transparent 72%),
    radial-gradient(520px 360px at 55% 110%, color-mix(in srgb, var(--ouro-luz) 55%, transparent), transparent 70%),
    var(--bg);
}
/* Pontilhado de fundo: textura de "papel picotado", quase subliminar. */
.hero-faixa::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(color-mix(in srgb, var(--texto) 9%, transparent) 1px, transparent 1.5px);
  background-size: 22px 22px;
  mask-image: linear-gradient(to bottom, rgba(0,0,0,.9), transparent 75%);
  -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,.9), transparent 75%);
}

.hero {
  position: relative;
  display: grid; gap: 2rem;
  padding: 3rem 0 2.4rem;
}
@media (min-width: 880px) {
  .hero { grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr); align-items: center; padding: 4.2rem 0 3.2rem; }
}

/* Mesma composição, ~30% menos altura — pra uma página como /grupos-de-
   -promocoes/, onde o cabeçalho é só contexto e o conteúdo (os cards) que
   importa vem logo abaixo. Escala padding e o tamanho do h1 juntos; o resto
   (olho, chips, texto) já era modesto o bastante pra não precisar encolher. */
/* Sem .hero__arte (não tem ilustração pra por do lado), então cancela a
   segunda coluna do .hero base — sem isso, o grid de 2 colunas reserva ~40%
   de espaço morto à direita, vazio, só porque o hero base espera uma coluna
   de arte que aqui nunca existe. */
.hero--compacto { padding: 2.1rem 0 1.7rem; gap: 1.4rem; grid-template-columns: 1fr; }
@media (min-width: 880px) {
  .hero--compacto { padding: 2.9rem 0 2.2rem; grid-template-columns: 1fr; }
}
/* Especificidade dobrada (.hero.hero--compacto, não só .hero--compacto): a
   regra genérica `.hero h1` vem DEPOIS desta no arquivo e tem a mesma
   especificidade de uma classe + elemento — sem o reforço aqui, ela vencia
   no empate por ordem de origem e o h1 "compacto" saía do tamanho do hero
   normal (maior), estourando a margem direita em telas estreitas. */
.hero.hero--compacto h1 { margin-bottom: .56rem; font-size: clamp(1.7rem, 5.3vw, 2.9rem); }
.hero--compacto .hero__texto { max-width: 62ch; }

.hero__atalhos { grid-column: 1 / -1; position: relative; z-index: 2; }
@media (min-width: 880px) { .hero__atalhos { margin-top: .3rem; } }

.hero__olho {
  display: inline-flex; align-items: center; gap: .5rem; width: fit-content;
  margin: 0 0 1.1rem; padding: .34rem .8rem .34rem .6rem;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: 999px; box-shadow: var(--sombra);
  font-size: .78rem; font-weight: 750; color: var(--verde-escuro);
  text-transform: uppercase; letter-spacing: .06em;
}
/* Bolinha pulsando: sinal de "vivo hoje", que é a objeção nº1 de site de cupom. */
.pulso {
  width: 8px; height: 8px; border-radius: 50%; background: var(--verde);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--verde) 60%, transparent);
  animation: pulsa 2.2s ease-out infinite;
}
@keyframes pulsa {
  70%  { box-shadow: 0 0 0 7px rgba(0, 153, 79, 0); }
  100% { box-shadow: 0 0 0 0 rgba(0, 153, 79, 0); }
}
@media (prefers-reduced-motion: reduce) { .pulso { animation: none; } }

.hero h1 {
  margin: 0 0 .8rem;
  font-family: var(--fonte-display);
  font-size: clamp(2.4rem, 7.5vw, 4.1rem);
  line-height: .98; letter-spacing: -.03em; font-weight: 800;
  text-wrap: balance;
}
/* Grifo de marca-texto lima, levemente torto — o "carimbo" do site. */
.hero h1 em {
  font-style: normal; position: relative; display: inline-block;
  padding-inline: .08em; z-index: 0; color: var(--verde-escuro);
}
.hero h1 em::before {
  content: ""; position: absolute; inset: .12em -.06em -.02em;
  background: var(--lima); border-radius: .18em;
  transform: rotate(-1.6deg); z-index: -1;
}

.hero__texto { margin: 0; color: var(--texto-fraco); font-size: 1.08rem; max-width: 54ch; }
/* Negrito estratégico (ver /grupos-de-promocoes/): cor volta pro texto forte
   também, não só o peso — sem isso o <strong> ficava cinza-claro em negrito,
   que lê como "mais grosso", não como "mais importante". */
.hero__texto strong { color: var(--texto); font-weight: 800; }

.hero__acoes { display: flex; gap: .7rem; flex-wrap: wrap; margin-top: 1.5rem; }
.btn-hero {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .85rem 1.5rem; border-radius: 999px;
  background: var(--verde); color: #fff; text-decoration: none;
  font-family: var(--fonte-display); font-weight: 750; font-size: 1.02rem; letter-spacing: -.01em;
  box-shadow: 0 3px 0 var(--verde-escuro), 0 14px 26px -12px rgba(0, 153, 79, .55);
  transition: transform .15s, box-shadow .15s, background .15s;
}
.btn-hero:hover { background: var(--verde-forte); transform: translateY(-2px); }
.btn-hero:active { transform: translateY(2px); box-shadow: 0 0 0 var(--verde-escuro); }
.btn-hero--fantasma {
  background: var(--superficie); color: var(--texto);
  box-shadow: none; border: 1px solid var(--borda-forte);
}
.btn-hero--fantasma:hover { background: var(--superficie); border-color: var(--texto); }

.hero__chips {
  display: flex; align-items: center; gap: .45rem; flex-wrap: wrap;
  margin-top: 1rem;
}
.hero__chips-label {
  color: var(--texto-fraco);
  font-size: .78rem; font-weight: 750; letter-spacing: .08em;
  text-transform: uppercase;
  margin-right: .15rem;
}
.hero__chip {
  display: inline-flex; align-items: center;
  min-height: 36px;
  padding: .38rem .75rem;
  border: 1px solid var(--borda);
  border-radius: 999px;
  background: rgba(255, 255, 255, .72);
  color: var(--texto);
  text-decoration: none;
  font-size: .9rem; font-weight: 650;
  box-shadow: var(--sombra);
  transition: background .15s, border-color .15s, color .15s, transform .15s;
}
.hero__chip:hover {
  background: var(--verde-luz);
  border-color: color-mix(in srgb, var(--verde) 30%, var(--borda));
  color: var(--verde-escuro);
  transform: translateY(-1px);
}

/* --- a pilha de tickets decorativa --- */

.hero__arte { position: relative; min-height: 300px; display: none; }
@media (min-width: 880px) { .hero__arte { display: block; } }

/* Duas metades em volta do picote, como um ingresso de verdade: a marca de um
 * lado, o número do outro. As colunas são 1fr 1fr porque o picote é desenhado
 * fixo em 50% — com colunas de larguras diferentes o tracejado cairia em cima
 * do conteúdo em vez de separar as duas metades. */
.tiquete {
  position: absolute;
  display: grid; grid-template-columns: 1fr 1fr; align-items: center;
  gap: 1rem;
  min-width: 212px; padding: .9rem 1.1rem;
  background: var(--loja-cor); color: var(--loja-chip-texto);
  border-radius: 14px;
  /* drop-shadow e não box-shadow: o filtro roda DEPOIS da máscara, então a
   * sombra contorna os furos em vez de ser cortada por eles. */
  filter: drop-shadow(0 16px 20px color-mix(in srgb, var(--loja-cor) 45%, rgba(12, 27, 23, .3)));
  /* Furos de ticket nas laterais: a máscara divide o ticket em duas metades
   * e cava um semicírculo na borda externa de cada uma. */
  -webkit-mask:
    radial-gradient(circle 9px at 0 50%, transparent 98%, #000) left  / 51% 100% no-repeat,
    radial-gradient(circle 9px at 100% 50%, transparent 98%, #000) right / 51% 100% no-repeat;
  mask:
    radial-gradient(circle 9px at 0 50%, transparent 98%, #000) left  / 51% 100% no-repeat,
    radial-gradient(circle 9px at 100% 50%, transparent 98%, #000) right / 51% 100% no-repeat;
  animation: flutua 7s ease-in-out infinite;
}
/* Metade esquerda: só a marca, centralizada na sua própria coluna. Sem logo
 * cadastrada, o par monograma + nome empilha aqui — duas iniciais sozinhas não
 * dizem que loja é. */
.tiquete__marca {
  display: flex; flex-direction: column; align-items: center; gap: .3rem;
  min-width: 0;
}
.tiquete__loja {
  font-size: .64rem; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  text-align: center; line-height: 1.15; opacity: .85;
}

/* Metade direita: o número é o argumento, então ele fica grande e a unidade
 * vira legenda embaixo. */
.tiquete__valor {
  display: flex; flex-direction: column; align-items: flex-start; gap: .15rem;
}
.tiquete__numero {
  font-family: var(--fonte-display);
  font-size: 2.1rem; font-weight: 800; line-height: .9; letter-spacing: -.03em;
}
.tiquete__unidade {
  font-size: .68rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  opacity: .85;
}
.tiquete__picote {
  position: absolute; inset: .55rem auto .55rem 50%;
  border-left: 2px dashed color-mix(in srgb, var(--loja-chip-texto) 45%, transparent);
}
.tiquete--1 { top: 4%;  right: 34%; transform: rotate(-7deg); animation-delay: 0s; }
.tiquete--2 { top: 34%; right: 2%;  transform: rotate(4deg);  animation-delay: -2.3s; }
.tiquete--3 { top: 62%; right: 40%; transform: rotate(-3deg); animation-delay: -4.1s; }
/* Sem 4ª loja no destaque, os três respiram; com ela, encaixa no vão. */
.tiquete--4 { top: 82%; right: 6%;  transform: rotate(6deg);  animation-delay: -5.2s; scale: .85; }

@keyframes flutua {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -14px; }
}
@media (prefers-reduced-motion: reduce) { .tiquete { animation: none; } }

/* Tesourinha seguindo o picote — puro enfeite. */
.hero__tesoura {
  position: absolute; top: 20%; right: 26%;
  font-size: 1.5rem; transform: rotate(90deg);
  filter: grayscale(1) opacity(.4);
}

/* --- números reais do banco, em faixa --- */

.hero__numeros {
  display: flex; flex-wrap: wrap; gap: 0; margin: 0 0 2.6rem;
  border: 1px solid var(--borda); border-radius: var(--raio);
  overflow: hidden; background: var(--superficie); box-shadow: var(--sombra-alta);
  position: relative; z-index: 1;
}
.numero-hero {
  flex: 1 1 33%; min-width: 130px; padding: 1.05rem 1.3rem;
  border-right: 1px solid var(--borda);
}
.numero-hero:last-child { border-right: 0; }
.numero-hero dt {
  font-size: .72rem; font-weight: 650; color: var(--texto-fraco);
  text-transform: uppercase; letter-spacing: .07em;
}
.numero-hero dd {
  margin: .15rem 0 0;
  font-family: var(--fonte-display);
  font-size: 2.1rem; font-weight: 800;
  letter-spacing: -.04em; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.numero-hero--destaque dd { color: var(--verde-forte); }

/* No celular o `min-width: 130px` não cabia três vezes em 343px: dois números
 * ficavam lado a lado e o terceiro caía sozinho ocupando a faixa inteira —
 * uma barra visivelmente torta. Três colunas iguais mantêm a faixa retangular.
 * (Depois das regras de dt/dd de propósito: @media não muda especificidade,
 * então quem vem por último é quem vale.) */
@media (max-width: 599px) {
  .hero__numeros { display: grid; grid-template-columns: repeat(3, 1fr); }
  .numero-hero { min-width: 0; padding: .85rem .7rem; }
  /* Duas linhas reservadas no rótulo: "cupons no ar" quebra em duas e "lojas"
     não — sem a altura fixa os três números caem em alturas diferentes. */
  .numero-hero dt { font-size: .64rem; letter-spacing: .04em; line-height: 1.3; min-height: 2.6em; }
  .numero-hero dd { font-size: 1.6rem; }
}

/* ============ marquee ============ */

/* Letreiro contínuo — energia de "promoção rolando agora". O conteúdo é
 * duplicado no HTML (aria-hidden na cópia) pro loop fechar sem buraco. */
.marquee {
  overflow: hidden; white-space: nowrap;
  background: var(--tinta); color: var(--lima);
  border-block: 3px solid var(--lima);
  transform: rotate(-1deg) scale(1.02);
  margin-block: .4rem 2.2rem;
}
.marquee__trilho {
  display: inline-flex; align-items: center;
  padding-block: .55rem;
  /* --marquee-duracao vem do HTML, proporcional à quantidade de itens. */
  animation: desfila var(--marquee-duracao, 55s) linear infinite;
}
.marquee:hover .marquee__trilho { animation-play-state: paused; }
.marquee__item {
  display: inline-flex; align-items: center; gap: 1.4rem;
  padding-inline: .7rem;
  font-family: var(--fonte-display);
  font-size: .95rem; font-weight: 750; letter-spacing: .14em; text-transform: uppercase;
}
.marquee__item::after { content: "✦"; font-size: .8em; opacity: .7; }
@keyframes desfila { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .marquee__trilho { animation: none; }
  .marquee { transform: none; }
}

/* ---- cabeçalho de seção ---- */

.secao-cabecalho {
  display: flex; align-items: center; gap: .7rem;
  margin: 2.6rem 0 1.1rem;
}
.secao-cabecalho .secao-titulo { margin: 0; }
/* "Ver todas →" encostado na direita: com só os destaques na home, o índice
   completo precisa de uma porta visível em cada seção. */
.secao-link {
  margin-left: auto; flex: none;
  font-size: .85rem; font-weight: 750; color: var(--verde-forte);
  text-decoration: none;
}
.secao-link:hover { text-decoration: underline; }
.secao-navegacao + .secao-navegacao .secao-cabecalho { margin-top: 2rem; }
.secao-contagem {
  font-size: .75rem; font-weight: 750; color: var(--verde-escuro);
  background: var(--verde-luz); border: 1px solid color-mix(in srgb, var(--verde) 35%, transparent);
  padding: .12rem .55rem; border-radius: 999px;
  font-variant-numeric: tabular-nums;
}
.secao-titulo {
  font-family: var(--fonte-display);
  font-size: clamp(1.35rem, 3vw, 1.7rem); font-weight: 800; letter-spacing: -.025em;
  margin: 2.6rem 0 1.1rem;
}

.migalhas { font-size: .84rem; color: var(--texto-fraco); padding-top: 1rem; }
.migalhas a { color: var(--texto-fraco); }

/* ---- cabeçalho da página de loja ---- */

.loja-topo {
  position: relative; overflow: hidden;
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 1rem;
  margin: .8rem 0 .5rem; padding: 1.6rem 1.6rem 1.6rem 1.9rem;
  background:
    radial-gradient(420px 220px at 90% -30%, color-mix(in srgb, var(--loja-cor) 16%, transparent), transparent 70%),
    var(--loja-suave);
  border: 1px solid color-mix(in srgb, var(--loja-cor) 35%, transparent);
  border-radius: calc(var(--raio) + 4px);
}
.loja-topo__faixa {
  position: absolute; inset: 0 auto 0 0; width: 7px; background: var(--loja-cor);
}
/* A marca fica centrada na altura do bloco, não colada na base como o resto. */
.loja-topo .marca-loja { align-self: center; box-shadow: var(--sombra); }
.loja-topo .marca-categoria { align-self: center; }
.loja-topo__texto { flex: 1 1 320px; min-width: 0; }
.loja-topo__chip {
  display: inline-block; margin-bottom: .55rem;
  background: var(--loja-cor); color: var(--loja-chip-texto);
  font-size: .7rem; font-weight: 800; letter-spacing: .09em; text-transform: uppercase;
  padding: .24rem .65rem; border-radius: 6px;
}
.loja-topo h1 {
  margin: 0 0 .35rem;
  font-family: var(--fonte-display);
  font-size: clamp(1.6rem, 4.5vw, 2.3rem);
  letter-spacing: -.03em; font-weight: 800; line-height: 1.08;
}
.loja-topo__resumo { margin: 0; color: var(--texto-fraco); font-size: .95rem; }

.loja-topo__numeros { display: flex; gap: 1.6rem; margin: 0; }
.loja-topo__numeros dt {
  font-size: .68rem; font-weight: 650; color: var(--texto-fraco);
  text-transform: uppercase; letter-spacing: .06em;
}
.loja-topo__numeros dd {
  margin: .05rem 0 0;
  font-family: var(--fonte-display);
  font-size: 1.7rem; font-weight: 800;
  letter-spacing: -.04em; line-height: 1; color: var(--loja-tinta);
  font-variant-numeric: tabular-nums;
}
.loja-topo__numeros .numero--data { font-size: 1.2rem; }

/* No celular o padding de 1.9rem à esquerda jogava o título para 48px da borda
 * enquanto a migalha ao lado começava em 16px — dois recuos diferentes na
 * mesma coluna. Aqui o bloco encolhe e volta a alinhar com o resto da página. */
@media (max-width: 719px) {
  .loja-topo {
    gap: .7rem;
    padding: 1.15rem 1.1rem 1.15rem 1.35rem;
    border-radius: var(--raio);
  }
  .loja-topo__faixa { width: 6px; }
  .loja-topo .marca-loja--lg { --h: 46px; }
  .loja-topo .marca-loja--lg.marca-loja--faixa.marca-loja--mono { width: 46px; border-radius: 12px; font-size: 1.25rem; }
  .loja-topo .marca-categoria--lg { font-size: 2.1rem; }
  .loja-topo__chip { margin-bottom: .4rem; }
  .loja-topo__numeros { gap: 1.4rem; }
  .loja-topo__numeros dd { font-size: 1.45rem; }
}

.vazio {
  background: var(--superficie-2); border: 1px dashed var(--borda-forte);
  border-radius: var(--raio); padding: 2.25rem 1.5rem; color: var(--texto-fraco);
  text-align: center; line-height: 1.7;
}
.vazio strong { color: var(--texto); }

/* ============ grade de lojas ============ */

.lojas-grid {
  display: grid; gap: .9rem; margin: 0 0 .5rem;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  position: relative; z-index: 1;
}
.loja-tile {
  position: relative; overflow: hidden;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 1.2rem 1.25rem 1.1rem 1.5rem;
  text-decoration: none; color: var(--texto); box-shadow: var(--sombra);
  display: flex; flex-direction: column; gap: .2rem;
  /* opacity/transform = entrada do .surge; o lift de hover usa translate/rotate
   * (propriedades independentes) pra não brigar com o transform da entrada. */
  transition: opacity .5s ease, transform .5s cubic-bezier(.2, .7, .3, 1),
              translate .18s cubic-bezier(.2, .8, .3, 1.2),
              rotate .18s cubic-bezier(.2, .8, .3, 1.2),
              box-shadow .18s, border-color .18s;
}
/* Faixa grossa da cor da loja: identifica a marca de relance, sem logo. */
.loja-tile__faixa { position: absolute; inset: 0 auto 0 0; width: 7px; background: var(--loja-cor); }
/* Glow da própria marca no canto — cada tile já "veste" a loja. */
.loja-tile::after {
  content: ""; position: absolute; right: -40px; top: -40px;
  width: 130px; height: 130px; border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--loja-cor) 16%, transparent), transparent);
  pointer-events: none;
}
.loja-tile:hover {
  translate: 0 -4px; rotate: -.4deg;
  border-color: color-mix(in srgb, var(--loja-cor) 55%, var(--borda));
  box-shadow: var(--sombra-alta);
}
/* A marca ocupa a própria linha: com logo deitada não sobra largura pro nome
   ao lado, e empilhado o tile fica igual pra logo e pra monograma. */
.loja-tile__cabeca { display: flex; align-items: center; margin-bottom: .6rem; }
.loja-tile__nome { font-family: var(--fonte-display); font-weight: 800; font-size: 1.2rem; letter-spacing: -.02em; }
/* A logo levanta junto com o card — reforça que o tile inteiro é um alvo. */
.loja-tile .marca-loja { transition: transform .18s cubic-bezier(.2, .8, .3, 1.4); }
.loja-tile:hover .marca-loja { transform: rotate(-4deg) scale(1.08); }
.loja-tile__total { font-size: .87rem; color: var(--texto-fraco); }
.loja-tile__total strong { color: var(--loja-tinta); font-weight: 800; }
.loja-tile__seta {
  margin-top: .65rem; font-size: .83rem; font-weight: 750; color: var(--verde-forte);
  transition: translate .18s;
}
.loja-tile:hover .loja-tile__seta { translate: 4px 0; }

/* Loja sem cupom vigente: fica na lista (o link pode estar num post antigo),
   mas visualmente recuada pra não competir com quem tem cupom. */
.loja-tile--vazia { opacity: .62; box-shadow: none; }
.loja-tile--vazia .loja-tile__total { font-style: italic; }

/* ---- variante categoria ----
   O emoji fica ao LADO do nome em vez de acima — sem a marca empilhada, o
   card fica bem mais baixo, e a grade cabe mais colunas por linha (ver
   .lojas-grid--categorias). Mesma ideia de .loja-tile--compacto, mas pra
   grade cheia de /categorias/. */
.loja-tile--categoria {
  flex-direction: row; align-items: center; gap: .8rem;
  padding: .85rem 1.1rem .85rem 1.3rem;
}
.loja-tile--categoria .loja-tile__corpo {
  display: flex; flex-direction: column; gap: .15rem; min-width: 0;
}
.loja-tile--categoria .loja-tile__nome { overflow-wrap: anywhere; }
.loja-tile--categoria .marca-categoria {
  transition: transform .18s cubic-bezier(.2, .8, .3, 1.4);
}
.loja-tile--categoria:hover .marca-categoria { transform: scale(1.14) rotate(-6deg); }

/* Home compact grid combines both: a bit tighter still so the emoji row
   doesn't grow taller than the store tiles sharing the same grid. */
.loja-tile--compacto.loja-tile--categoria {
  padding: .65rem .85rem .65rem 1rem; gap: .6rem;
}
.loja-tile--compacto.loja-tile--categoria .loja-tile__nome { font-size: .95rem; }
.loja-tile--compacto.loja-tile--categoria .loja-tile__total { font-size: .78rem; }

/* ---- variante compacta ----
   A home mostra DUAS grades (categoria e loja). No tamanho cheio, a segunda
   nasceria abaixo da dobra e ninguém saberia que existe. Aqui a marca vai ao
   LADO do nome em vez de acima, o que corta a altura quase pela metade e
   deixa caber cinco por linha em vez de três. */
.lojas-grid--compacta {
  gap: .6rem;
  grid-template-columns: repeat(auto-fill, minmax(158px, 1fr));
}
.loja-tile--compacto {
  padding: .7rem .8rem .75rem 1.05rem;
  gap: .1rem;
}
.loja-tile--compacto .loja-tile__faixa { width: 5px; }
.loja-tile--compacto .loja-tile__cabeca {
  flex-direction: column; align-items: flex-start;
  gap: .35rem; margin-bottom: .3rem; min-width: 0;
}
.loja-tile--compacto .loja-tile__nome {
  font-size: .95rem; line-height: 1.2;
  /* Nome longo ("Casa e Cozinha", "Mercado Livre") não pode empurrar a
     largura do grid — quebra em duas linhas e o card acompanha. */
  min-width: 0; overflow-wrap: anywhere;
}
.loja-tile--compacto .loja-tile__total { font-size: .78rem; }
/* O glow acompanha o card menor, senão vaza pela borda. */
.loja-tile--compacto::after { width: 88px; height: 88px; right: -28px; top: -28px; }
/* Sem "Ver cupons →": num card deste tamanho é ruído, e o card inteiro já é
   o alvo de clique. */
.loja-tile--compacto .loja-tile__seta { display: none; }

@media (max-width: 520px) {
  .lojas-grid--compacta { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
}

/* Grade cheia de /categorias/: o card de categoria é mais baixo que o de
   loja (emoji ao lado, não empilhado), então cabe coluna mais estreita —
   mais células visíveis de uma vez sem precisar rolar. */
.lojas-grid--categorias {
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: .7rem;
}
@media (max-width: 520px) {
  .lojas-grid--categorias { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
}

/* ============ índice de lojas (/lojas/) ============ */

/* Aqui a LOGO é o conteúdo, não um crachá ao lado do conteúdo.
 *
 * Nas outras telas a marca identifica outra coisa (um cupom, uma linha de
 * menu) e cabe num chip de 20-38px. Nesta a loja é o assunto, então ela ganha
 * uma PLACA branca própria — larga o suficiente pra um wordmark deitar na
 * proporção real — e a cor da marca pinta o card inteiro em vez de se
 * esconder numa faixa de 7px. A grade uniforme antiga fazia o contrário:
 * marca de 38px num card de 180px, que é de onde vinham as duas queixas
 * (logo pequena e espaço vazio).
 *
 * A placa é BRANCA em todos os níveis pelo mesmo motivo de .marca-loja: logo
 * de loja é desenhada pra fundo claro e muita delas tem tinta escura — sobre
 * a própria cor da marca, metade sumiria.
 *
 * Três níveis, porque o catálogo tem três (ver App\StoreShowcase):
 *   .vitrine       — as poucas lojas que carregam quase todo o estoque
 *   .marcas-grid   — a cauda longa, de 1 a 5 cupons
 *   .marcas-fila   — as sem cupom vigente, que só precisam continuar linkadas
 */

/* ---- placa: a logo ocupa a caixa inteira ----
 * Diferente de --faixa (que fixa a ALTURA e solta a largura), aqui quem manda
 * é o container: a placa tem tamanho próprio e a logo se encaixa dentro dela
 * inteira, em qualquer proporção. É o que deixa a logo da Amazon (3,3:1) e a
 * do ML (quase quadrada) parecerem do mesmo tamanho na mesma linha.
 *
 * A imagem é limitada por max-width/max-height com width/height em AUTO, e a
 * placa é flex — nunca grid com place-items:center. Feito em grid, a linha é
 * dimensionada pelo conteúdo, então `height: 100%` no filho é circular e o
 * navegador resolve como `auto`: a logo volta à altura natural e vaza. Com
 * `overflow: hidden` na placa isso não aparece como estouro, aparece como
 * logo CORTADA — a do Kabum (4096x4096) renderizava 270x270 dentro de uma
 * placa de 86px de altura. Em flex, `align-items: stretch` dá ao filho a
 * altura definida da placa, e aí a porcentagem tem contra o que resolver. */
.marca-loja--placa {
  display: flex; align-items: center; justify-content: center;
  width: 100%; max-width: none; height: auto; min-width: 0; min-height: 0;
  background: none; border: 0; border-radius: 0;
  overflow: visible;
}
.marca-loja--placa .marca-loja__img {
  width: auto; height: auto;
  max-width: 100%; max-height: 100%;
  object-fit: contain; padding: 0;
}
/* Sem logo cadastrada a placa inverte: em vez de duas letrinhas perdidas num
   retângulo branco, o retângulo inteiro vira a cor da marca. */
.marca-loja--placa.marca-loja--mono {
  width: 100%; align-self: stretch;
  background: var(--loja-cor); color: var(--loja-chip-texto);
  border-radius: 0;
  font-size: clamp(1.3rem, 5vw, 2rem);
}

/* ---- nível 1: vitrine ---- */

.vitrine {
  display: grid; gap: 1rem; margin: .4rem 0 .5rem;
  grid-template-columns: repeat(auto-fit, minmax(288px, 1fr));
}
.vitrine-card {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: .8rem;
  padding: 1rem;
  text-decoration: none; color: var(--texto);
  border-radius: calc(var(--raio) + 4px);
  border: 1px solid color-mix(in srgb, var(--loja-cor) 30%, var(--borda));
  /* O card VESTE a loja: o pálido da marca como fundo e um brilho da cor
     cheia no canto superior — é o que faz a grade inteira ler como uma
     estante de marcas em vez de uma tabela de nomes. */
  background:
    radial-gradient(320px 200px at 100% 0%, color-mix(in srgb, var(--loja-cor) 22%, transparent), transparent 72%),
    var(--loja-suave);
  box-shadow: var(--sombra);
  /* opacity/transform pagam a entrada do .surge (ver a regra lá em cima);
     o lift de hover anda em translate, que é propriedade independente. */
  transition: opacity .5s ease, transform .5s cubic-bezier(.2, .7, .3, 1),
              translate .18s cubic-bezier(.2, .8, .3, 1.2),
              box-shadow .18s, border-color .18s;
}
.vitrine-card:hover {
  translate: 0 -5px;
  border-color: var(--loja-cor);
  box-shadow: var(--sombra-alta);
}

.vitrine-card__placa {
  display: flex; align-items: stretch; justify-content: center;
  height: 88px; padding: .85rem 1.15rem;
  background: #fff; border-radius: 14px; overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--loja-cor) 18%, var(--borda));
  box-shadow: 0 1px 2px rgba(12, 27, 23, .04);
}
/* A logo cresce um tico no hover, sem girar: no tamanho de placa, a rotação
   que funciona num chip de 38px vira um solavanco. */
.vitrine-card__placa .marca-loja { transition: transform .2s cubic-bezier(.2, .8, .3, 1.3); }
.vitrine-card:hover .vitrine-card__placa .marca-loja { transform: scale(1.05); }

.vitrine-card__corpo { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
/* Nome e selo dividem a linha, o selo ancorado à direita.
 * `baseline` e não `center`: o selo é texto ao lado de texto, e alinhar as
 * duas linhas de base é o que faz a pastilha parecer parte da linha do
 * título em vez de um adesivo flutuando ao lado dela. Com nome comprido, a
 * base usada é a da PRIMEIRA linha — o selo fica no alto, junto do começo do
 * nome, que é onde o olho já está. */
.vitrine-card__titulo {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: .6rem; min-width: 0;
}
.vitrine-card__nome {
  font-family: var(--fonte-display); font-weight: 800;
  font-size: 1.25rem; letter-spacing: -.028em; line-height: 1.15;
  overflow-wrap: anywhere; min-width: 0;
}
.vitrine-card__numeros { font-size: .85rem; color: var(--texto-fraco); }
.vitrine-card__numeros strong {
  color: var(--loja-tinta); font-weight: 800; font-size: 1.02rem;
  font-variant-numeric: tabular-nums;
}
.vitrine-card__quebra { display: block; font-size: .77rem; }

/* Prateleira: a mercadoria da própria loja. Só marketplace tem foto de
   produto, então só marketplace ganha esta faixa — as lojas de código caem no
   bloco de desconto logo abaixo, que é a única promessa que elas podem fazer. */
/* `margin-top: auto` nos TRÊS blocos de manchete (aqui e no __desconto
 * abaixo): a grade estica todos os cards de uma linha até a mesma altura, e
 * sem isso a sobra cai no fim do card — o buraco do layout antigo de volta.
 * Empurrada pra cima, a sobra fica entre o nome e a manchete, e as manchetes
 * de uma linha se alinham por baixo mesmo quando são coisas diferentes
 * (prateleira num card, número em outro). */
.vitrine-card__prateleira {
  margin-top: auto;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: .4rem;
}
.vitrine-card__foto {
  aspect-ratio: 1; border-radius: 10px; overflow: hidden;
  background: #fff;
  border: 1px solid color-mix(in srgb, var(--loja-cor) 15%, var(--borda));
}
/* `contain`, não `cover`: as fotos vêm do anúncio da loja e chegam em
   proporções que não controlamos. `cover` preenche o quadrado mais bonito,
   mas corta as bordas — num anúncio de produto isso é cortar o produto, e
   uma foto cortada lê como bug. Sobre o fundo branco da moldura, o
   letterbox do `contain` é invisível quando a foto já é quadrada, que é o
   caso da maioria vinda de marketplace. */
.vitrine-card__foto img {
  width: 100%; height: 100%; display: block;
  object-fit: contain; padding: 3px;
}

.vitrine-card__desconto {
  margin-top: auto;
  display: flex; align-items: baseline; gap: .4rem;
  padding: .55rem .9rem; border-radius: 12px;
  background: #fff;
  border: 1px dashed color-mix(in srgb, var(--loja-cor) 45%, transparent);
}
.vitrine-card__desconto strong {
  font-family: var(--fonte-display); font-weight: 800;
  font-size: 2.1rem; letter-spacing: -.05em; line-height: 1;
  color: var(--loja-tinta); font-variant-numeric: tabular-nums;
}
.vitrine-card__desconto span {
  font-size: .78rem; font-weight: 800; letter-spacing: .09em;
  color: var(--loja-tinta);
}
/* Variante 3 do bloco de manchete (ver a view): a contagem no lugar do
   desconto, pra loja cujos cupons não registram valor nenhum. Sólida em vez
   de tracejada — o tracejado é a linguagem de "cupom", e aqui não há cupom
   específico sendo prometido, só quantidade. */
.vitrine-card__desconto--total { border-style: solid; border-color: color-mix(in srgb, var(--loja-cor) 26%, var(--borda)); }
.vitrine-card__desconto--total span { letter-spacing: 0; text-transform: none; font-weight: 750; }

/* `flex: none` porque a pastilha é a metade que NÃO pode encolher: entre
   "Mercado Livre" e "até 67% OFF", quem quebra linha é o nome. */
.vitrine-card__selo {
  flex: none;
  background: var(--loja-cor); color: var(--loja-chip-texto);
  font-size: .75rem; font-weight: 800; padding: .2rem .55rem; border-radius: 999px;
}

/* ---- nível 2: cauda longa ----
   Mesma ideia da vitrine em escala menor: placa branca sobre o pálido da
   marca. O fundo pálido é o que faz a placa existir — placa branca sobre
   card branco não é placa nenhuma. */

.marcas-grid {
  display: grid; gap: .75rem; margin: 0 0 .5rem;
  grid-template-columns: repeat(auto-fill, minmax(172px, 1fr));
}
.marca-card {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: .55rem;
  padding: .75rem;
  text-decoration: none; color: var(--texto);
  background: var(--loja-suave);
  border: 1px solid color-mix(in srgb, var(--loja-cor) 24%, var(--borda));
  border-radius: var(--raio);
  transition: translate .18s cubic-bezier(.2, .8, .3, 1.2),
              box-shadow .18s, border-color .18s;
}
.marca-card:hover {
  translate: 0 -3px;
  border-color: var(--loja-cor);
  box-shadow: var(--sombra-alta);
}
.marca-card__placa {
  display: flex; align-items: stretch; justify-content: center;
  height: 64px; padding: .5rem .7rem;
  background: #fff; border-radius: 10px; overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--loja-cor) 16%, var(--borda));
}
.marca-card__nome {
  font-family: var(--fonte-display); font-weight: 800;
  font-size: .95rem; line-height: 1.2; letter-spacing: -.02em;
  overflow-wrap: anywhere;
}
.marca-card__total { margin-top: auto; font-size: .78rem; color: var(--texto-fraco); }
.marca-card__total strong {
  color: var(--loja-tinta); font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.marca-card__ate { display: block; font-weight: 750; color: var(--loja-tinta); }

/* ---- nível 3: sem cupom vigente ----
   Continuam linkadas (a página da loja guarda o texto de SEO, e link antigo
   ainda aponta pra lá), mas como pastilha e não como card: em tamanho de
   card, nove "sem cupom no momento" eram o maior bloco de vazio da página. */

.secao-titulo--quieto {
  font-size: 1.05rem; color: var(--texto-fraco);
  margin-top: 2.4rem; margin-bottom: .8rem;
}
.marcas-fila { display: flex; flex-wrap: wrap; gap: .45rem; margin-bottom: 1rem; }
.marca-pastilha {
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .35rem .8rem .35rem .45rem;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: 999px; text-decoration: none;
  color: var(--texto-fraco); font-size: .84rem; font-weight: 650;
  transition: border-color .18s, color .18s;
}
.marca-pastilha:hover { border-color: var(--loja-cor); color: var(--texto); }
.marca-pastilha .marca-loja--faixa { --larg: 74px; }

@media (max-width: 620px) {
  .vitrine { gap: .8rem; }
  .vitrine-card__placa { height: 74px; }
  .marcas-grid { grid-template-columns: repeat(auto-fill, minmax(146px, 1fr)); gap: .6rem; }
  .marca-card__placa { height: 52px; }
}

/* ============ LISTA de cupons ============ */

.cupons-lista { display: flex; flex-direction: column; gap: .85rem; }

.cupom {
  position: relative;
  z-index: 0;              /* segura o ::before (z-index -1) dentro do card */
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr);
  gap: .35rem 1.1rem;
  align-items: center;

  /* O 6px extra à esquerda paga a faixa da loja, que mora no ::before. */
  padding: 1.05rem 1.15rem 1.05rem calc(1.15rem + 6px);
  border-radius: var(--raio);
  /* O deep link #c-slug é COMO o tráfego do Telegram chega. O valor fixo de
   * 96px era menor que o header sticky real (198px no celular) e o cupom
   * apontado nascia escondido atrás dele. --topo-h é medida e publicada pelo
   * app.js; o 96px vira só o fallback de antes do JS rodar. */
  scroll-margin-top: calc(var(--topo-h, 96px) + .75rem);
  /* Só a entrada do .surge (ver lá o porquê). `translate` e `box-shadow`
   * estavam nesta lista pelo lift de hover, que não existe mais — animar
   * propriedade que nada muda é só custo. */
  transition: opacity .5s ease, transform .5s cubic-bezier(.2, .7, .3, 1);

  /* Borda e sombra REAIS, no próprio card. A versão anterior desenhava o
   * contorno com drop-shadows de 1px pra acompanhar furos recortados por
   * máscara — frágil e quase invisível. Os furos foram embora; o picote
   * tracejado (que é o que lê como ticket) ficou. */
  --cupom-linha: var(--borda-forte);
  background: var(--superficie);
  border: 1px solid var(--cupom-linha);
  box-shadow: var(--cupom-sombra);
}

/* A faixa da loja: pseudo colado na borda esquerda, por baixo do conteúdo.
 * border-left num pseudo de altura cheia (e não no .cupom) pros modificadores
 * de borda (--top dourado, :target verde) não engolirem a cor da loja. */
.cupom::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  border-left: 6px solid var(--loja-cor);
  border-radius: inherit;
}
/* O card NÃO reage ao mouse — de propósito, e isto já foi o contrário.
 *
 * A linha inteira levantava 3px no hover, com sombra e contorno mudando
 * junto. Numa lista que existe pra ser varrida, isso vira a página se
 * mexendo debaixo do cursor: o card não é clicável (o alvo é o CTA), então
 * a elevação prometia um clique que não existe naquela área e ainda
 * empurrava o olho pra fora do lugar onde ele estava lendo.
 *
 * Quem responde ao mouse é o botão, que é o que de fato se clica — ver
 * `.cupom__cta:hover`. */

/* Cupom apontado por um link específico (Telegram/WhatsApp/"copiar link") —
 * TRÊS canais ligados ao mesmo tempo, porque nenhum um deles isolado se lê
 * contra dez cards igualmente sombreados na mesma lista: anel OPACO (não o
 * `--verde-luz` pastel de antes, que sobre `--superficie` branca é quase
 * invisível), fundo tingido, e uma sombra que só este card tem. Isto já
 * existia como só a sombra + um anel pastel de 3px — pouco demais pra
 * chamar atenção de verdade.
 *
 * `.cupom--destaque` é a classe que o SERVIDOR decide
 * (Controller\Site::highlightedCoupon, a partir de `?c=`) — ele sabe quando
 * o cupom expirou ou nunca pertenceu a esta página, o que `:target` sozinho
 * não sabe, e não se perde se a pessoa clicar em outra âncora da página.
 * `:target` continua aqui como rede de segurança pra um link antigo com só
 * `#c-slug`, sem `?c=`. */
.cupom:target,
.cupom--destaque {
  --cupom-linha: var(--verde);
  background: var(--verde-luz);
  box-shadow: inset 0 0 0 3px var(--verde), var(--cupom-sombra-alta);
  /* Só na CHEGADA: um pulso curto que puxa o olho pro card certo assim que a
   * página carrega. O estado acima fica pra sempre — isto toca uma vez e
   * assenta de volta nele (a animação não tem `forwards` porque o valor de
   * repouso já é exatamente o `box-shadow` estático desta regra). */
  animation: cupom-destaque-chegada 1.4s ease-out 1;
}

@keyframes cupom-destaque-chegada {
  0%, 100% { box-shadow: inset 0 0 0 3px var(--verde), var(--cupom-sombra-alta); }
  35% { box-shadow: inset 0 0 0 6px var(--verde), 0 0 0 10px var(--verde-luz), var(--cupom-sombra-alta); }
}
@media (prefers-reduced-motion: reduce) {
  .cupom:target,
  .cupom--destaque {
    animation: none;
  }
}

.cupom--top { --cupom-linha: #ecc94b; }
.cupom__faixa {
  /* A faixa é larga o bastante pra alcançar a costura do picote. Sem o
   * z-index ela perde pro .cupom__picote (que vem depois no HTML) e o
   * tracejado atravessa o selo. */
  position: absolute; z-index: 1; top: -.65rem; left: calc(1.1rem + 6px);
  background: linear-gradient(100deg, #ffe9a8, var(--ouro-luz));
  color: var(--ouro);
  font-size: .68rem; font-weight: 800; letter-spacing: .05em;
  padding: .16rem .6rem; border-radius: 999px;
  border: 1px solid #ecc94b;
  box-shadow: 0 3px 8px -3px rgba(138, 90, 0, .4);
}

/* O picote do ticket: linha tracejada vertical entre o canhoto e o corpo.
 * Só no desktop — no celular a linha cruzaria o CTA, que ocupa a base. */
.cupom__picote { display: none; }
@media (min-width: 720px) {
  .cupom {
    /* Costura, medida do miolo do card (dentro da borda): faixa da loja
     * (6px) + padding (1.15rem) + canhoto (96px) + meia-calha (.6rem). */
    --picote-x: calc(6px + 1.15rem + 96px + .6rem);
  }
  /* Os furos do picote: dois meio-círculos DESENHADOS (não recortados) nas
   * bordas de cima e de baixo, na cor do fundo da página com um aro na cor
   * da borda do card. O pseudo cobre o card inteiro e o gradiente pinta só
   * o que cai dentro dele — vira meia-lua sozinho, sem máscara. O aro usa
   * --cupom-linha, então acompanha o dourado do --top, o verde do :target e
   * o escurecer do hover de graça. Pintar (em vez de recortar por máscara)
   * é o que permite borda e box-shadow reais no card. */
  /* inset -1px: o pseudo cresce por cima da borda de 1px do card, senão ela
   * atravessa a boca do furo como um fio. O +1px no X compensa a origem
   * deslocada e mantém o furo centrado no tracejado. */
  .cupom::after {
    content: ""; position: absolute; inset: -1px; z-index: -1;
    border-radius: inherit;
    background:
      radial-gradient(circle 12px at calc(var(--picote-x) + 1px) 0,
        var(--bg) 9px, var(--cupom-linha) 10px 11px, transparent 12px),
      radial-gradient(circle 12px at calc(var(--picote-x) + 1px) 100%,
        var(--bg) 9px, var(--cupom-linha) 10px 11px, transparent 12px);
    pointer-events: none;
  }
  /* Tracejado por gradiente, não `border dashed`: o dashed nativo estica os
   * traços pra fechar a caixa e o ritmo muda de card pra card conforme a
   * altura. Aqui o passo é fixo (5px traço / 6px vão) e sempre igual. */
  .cupom__picote {
    display: block; position: absolute;
    left: calc(var(--picote-x) - 1px);   /* -1px = metade do tracejado, pra centrar */
    /* Começa depois do furo (12px) com um respiro, senão a linha invade. */
    top: 17px; bottom: 17px;
    width: 2px; border-radius: 1px;
    /* Um degrau mais escuro que a --borda-forte: com o cinza-claro puro a
     * linha sumia no fundo branco e o picote deixava de existir na prática. */
    background: repeating-linear-gradient(
      to bottom,
      color-mix(in srgb, var(--borda-forte) 55%, var(--texto-fraco)) 0 5px,
      transparent 5px 11px
    );
    pointer-events: none;
  }
}

/* --- coluna 1: o número. Sempre no mesmo lugar em toda a lista. --- */
.cupom__selo {
  /* Encosta no topo da linha em vez de boiar no meio dela: o `align-items:
   * center` do grid centrava o selo (72px) contra o corpo (~190px no celular)
   * e abria ~59px de vão morto acima do número. Alinhado no topo, o desconto
   * fica na altura do chip da loja e do título — que é o par que o olho lê. */
  align-self: start;
  background: var(--loja-suave);
  border: 1px solid color-mix(in srgb, var(--loja-cor) 35%, transparent);
  border-radius: 12px;
  min-height: 72px; padding: .5rem .3rem;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: .1rem;
}
.cupom__selo-valor {
  font-family: var(--fonte-display);
  font-size: 1.55rem; font-weight: 800; line-height: 1;
  letter-spacing: -.045em; color: var(--loja-tinta);
  overflow-wrap: anywhere;
}
.cupom__selo-rotulo {
  font-size: .64rem; font-weight: 800; letter-spacing: .1em;
  color: var(--loja-tinta); opacity: .75;
}

/* --- coluna 1, versão PRODUTO: a foto no lugar do canhoto ---
   Promoção sem código não é um ticket pra copiar, é um PRODUTO com preço. Onde
   dá pra mostrar a foto que o coletor leu do anúncio, ela ocupa a coluna do
   selo e o desconto vem numa tarja por cima — o olho lê mercadoria, não um
   cupom que esqueceu o código.

   A largura é a MESMA do selo (92px no celular, 96px no desktop) de propósito:
   é o que mantém título, preço e CTA alinhados entre um card e outro numa
   lista que mistura os dois tipos. */
.cupom__foto {
  align-self: start;
  position: relative;
  aspect-ratio: 1;
  border-radius: 12px;
  overflow: hidden;
  /* Branco fixo, não var(--superficie): foto de e-commerce já vem recortada
     sobre branco. Amarrar a moldura à variável faria o dia em que ela mudar
     abrir um halo branco em volta de cada produto da lista. */
  background: #fff;
  border: 1px solid var(--borda);
}
.cupom__foto-img {
  width: 100%; height: 100%;
  /* `contain`, não `cover`: recortar corta justamente a peça que a pessoa quer
     reconhecer. Sobra do lado é o branco do anúncio, que ninguém percebe. */
  object-fit: contain;
  /* O respiro embaixo é a altura da tarja — sem ele o desconto tapa o produto. */
  padding: .3rem .3rem 1.15rem;
}
/* A tarja do desconto: atravessa a base da foto, na cor da loja. É o
   equivalente do .cupom__selo aqui — o desconto continua sendo a primeira
   coisa que o olho pega na linha. */
.cupom__foto-selo {
  position: absolute; inset: auto 0 0 0;
  background: var(--loja-cor); color: var(--loja-chip-texto);
  font-size: .68rem; font-weight: 800; letter-spacing: .03em;
  text-align: center; padding: .2rem .15rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* O picote e os furos somem no card de produto: o recorte de ticket é o que
   diz "cupom", e aqui a promessa é outra. */
.cupom--produto .cupom__picote { display: none; }
.cupom--produto::after { display: none; }

/* --- coluna 2: conteúdo --- */
.cupom__corpo { min-width: 0; }

.cupom__linha-topo { display: flex; align-items: center; gap: .45rem; margin-bottom: .3rem; }
.cupom__loja {
  font-size: .68rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .07em; text-decoration: none;
  background: var(--loja-cor); color: var(--loja-chip-texto);
  padding: .17rem .55rem; border-radius: 6px;
}
.cupom__tipo {
  font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--texto-fraco);
}


/* Título e regras com clamp: é o que mantém TODAS as linhas na mesma altura.
 * O `min-height` de 2 linhas (2 × line-height 1.3) fecha o outro lado: sem ele
 * um título curto encolhe a linha e a lista fica serrilhada. */
.cupom__titulo {
  margin: 0 0 .2rem;
  font-size: 1.04rem; line-height: 1.3; font-weight: 700; letter-spacing: -.015em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.6em;
}
.cupom__regras {
  margin: 0 0 .4rem; font-size: .83rem; color: var(--texto-fraco); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Nota do produto — só aparece quando a origem trouxe uma (não é obrigatória,
   mesma regra do preço logo abaixo). Sem altura reservada: é a mesma escolha
   que o preço já faz quando falta, não uma nova. */
.cupom__nota {
  margin: 0 0 .3rem;
  display: flex; align-items: center; gap: .3rem;
  font-size: .82rem; font-weight: 700; color: var(--ouro);
}
.cupom__nota-max {
  font-size: .74rem; font-weight: 600; color: var(--texto-fraco);
}

/* A linha de preço. Uma linha só, e quebra por item (não no meio do número):
   "R$ 1.234,90" partido ao meio é ilegível justo no dado que a pessoa veio
   conferir.

   `center`, não `baseline`: os três têm tamanhos e caixas diferentes (texto
   miúdo, número grande, pílula com borda), e alinhar pelo pé da letra jogava
   a etiqueta ~2px abaixo do meio do preço — pouco, e ainda assim visível
   porque a pílula tem contorno próprio. Centrados, os três sentam na mesma
   linha do olho. */
.cupom__preco {
  margin: 0 0 .35rem;
  display: flex; flex-wrap: wrap; align-items: center; gap: .1rem .5rem;
}
.cupom__preco-de {
  font-size: .78rem; color: var(--texto-fraco);
  white-space: nowrap;
}
.cupom__preco-por {
  font-family: var(--fonte-display);
  font-size: 1.3rem; font-weight: 800; line-height: 1.1;
  letter-spacing: -.03em; color: var(--texto);
  white-space: nowrap;
}
/* O quanto cai, em reais. Vende mais que a porcentagem — "economize R$ 149,90"
   é dinheiro, "50% OFF" é conta. Os dois convivem: a tarja da foto tem a
   porcentagem, esta etiqueta tem o valor. */
.cupom__preco-economia {
  font-size: .73rem; font-weight: 800; letter-spacing: .01em;
  color: var(--verde-forte); background: var(--verde-luz);
  border: 1px solid color-mix(in srgb, var(--verde) 25%, transparent);
  padding: .1rem .45rem; border-radius: 999px;
  white-space: nowrap;
}

/* No celular as 4 provas são um GRID 2×2 ocupando a LARGURA INTEIRA do card.
 * Dentro da coluna do corpo (só ~190px num iPhone) cada prova quebrava em duas
 * linhas e o bloco ia a 83px — o card a 314px, ou seja 2,3 cupons por tela.
 * Atravessando o card sobram ~146px por coluna e a prova mais longa ("Sem
 * prazo definido", 112px) cabe numa linha só. As colunas ainda alinham as
 * provas de um cupom com as do outro, que é o ponto da lista. */
.cupom__provas {
  grid-column: 1 / -1;
  list-style: none; margin: .5rem 0 0; padding: 0;
  display: grid; grid-template-columns: 1fr 1fr; gap: .15rem .75rem;
  font-size: .77rem; color: var(--texto-fraco);
}
@media (min-width: 720px) {
  /* No desktop sobra largura: as provas voltam pra baixo do corpo, em linha. */
  .cupom__provas { grid-column: 2; display: flex; flex-wrap: wrap; margin-top: .1rem; }
}
.prova strong { color: var(--texto); }
.prova--ok { color: var(--verde-forte); }
.prova--ok strong { color: var(--verde-forte); }
.prova--urgente { color: var(--vermelho); font-weight: 700; }

/* --- o CTA. No celular ocupa a linha inteira (alvo de toque máximo);
       no desktop vira a terceira coluna, sempre na mesma posição. --- */
.cupom__acao {
  grid-column: 1 / -1; display: flex; flex-direction: column;
  align-items: stretch; gap: .3rem; margin-top: .65rem;
}

@media (min-width: 720px) {
  .cupom {
    grid-template-columns: 96px minmax(0, 1fr) 240px;
    gap: 0 1.2rem;
  }
  /* No desktop a linha é baixa (o corpo cabe em ~118px) e selo e CTA voltam a
     ficar centrados nas DUAS linhas (corpo + provas) — o vão morto do celular
     não existe aqui, e é o que mantém as três colunas na mesma altura. */
  .cupom__selo { grid-row: 1 / span 2; align-self: center; }
  /* A foto ocupa as duas linhas e fica CENTRADA nelas, igualzinho ao selo: os
     dois tipos de card convivem na mesma lista, e a foto ancorada no topo
     deixava o produto num degrau acima do desconto do card vizinho. O
     `center` não estica nada — o `aspect-ratio: 1` já fixou o tamanho, isto
     só decide onde ele senta na linha. */
  .cupom__foto { grid-row: 1 / span 2; align-self: center; }
  .cupom__acao { grid-column: 3; grid-row: 1 / span 2; margin-top: 0; }
}

/* --- o botão: um alvo só, o elemento mais pesado da linha --- */
.cupom__cta {
  position: relative;
  display: flex; align-items: stretch; width: 100%;
  font: inherit; cursor: pointer; text-align: left; text-decoration: none;
  border: 0; border-radius: 12px; overflow: hidden;
  background: var(--verde);
  box-shadow: 0 3px 0 var(--verde-escuro);
  transition: background .15s, transform .15s cubic-bezier(.2, .8, .3, 1.3), box-shadow .15s;
}
/* O botão levanta e ganha sombra própria. Com o card parado, esta é a ÚNICA
 * coisa que se move na linha — que é exatamente o recado: o alvo do clique
 * é aqui. */
.cupom__cta:hover {
  background: var(--verde-forte);
  transform: translateY(-1px);
  box-shadow: 0 4px 0 var(--verde-escuro), 0 12px 20px -10px rgba(0, 122, 63, .6);
}
.cupom__cta:active { transform: translateY(3px); box-shadow: none; }

/* Brilho que varre o botão. Disparava no hover do CARD inteiro, pra quem
 * passasse pela linha ver o CTA acenar de longe — e era metade do problema:
 * o brilho acendia sozinho quando o cursor só atravessava a lista. Agora sai
 * do hover do próprio botão, junto com o resto da resposta dele. */
.cupom__cta::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(115deg, transparent 30%, rgba(255, 255, 255, .35) 50%, transparent 70%);
  transform: translateX(-110%);
  pointer-events: none;
}
.cupom__cta:hover::after { transition: transform .55s ease; transform: translateX(110%); }
@media (prefers-reduced-motion: reduce) { .cupom__cta::after { display: none; } }

.cupom__cta-texto {
  flex: 1; padding: .8rem .95rem;
  color: #fff; font-weight: 800; font-size: .97rem; letter-spacing: -.01em;
  display: flex; align-items: center; white-space: nowrap;
}

/* O "espia": 2 primeiras letras e pontos. Prova que existe código de verdade
 * — que é o que faz clicar — sem entregar o código. */
.cupom__cta-codigo {
  display: flex; align-items: center; justify-content: center;
  min-width: 88px; padding: .8rem .6rem;
  background: rgba(255, 255, 255, .2);
  border-left: 2px dashed rgba(255, 255, 255, .6);
  color: #fff; font-weight: 800; font-size: .92rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: .05em; white-space: nowrap;
  transition: background .2s, letter-spacing .2s;
}
/* O espia clareia e abre as letras junto com o hover do botão: o código
 * "se mostra" um pouco mais — reforço do que o clique vai entregar. */
.cupom__cta:hover .cupom__cta-codigo {
  background: rgba(255, 255, 255, .32);
  letter-spacing: .09em;
}

/* Ticket revelado dentro do modal de cupons aplicáveis (ver app.js
 * `revelarNoTicket`): o botão vira um alvo só de copiar — ícone de
 * clipboard fixo à esquerda, código por inteiro ocupando o resto — em vez
 * do "Ver cupom" + espia tracejado, que é o que fazia o texto colidir com o
 * código quando os dois cabiam na mesma largura de sempre. */
.cupom__cta--revelado .cupom__cta-texto {
  flex: 0 0 auto;
  padding: .8rem 0 .8rem .95rem;
  font-size: 1.05rem;
}
.cupom__cta--revelado .cupom__cta-codigo {
  flex: 1;
  justify-content: flex-start;
  min-width: 0;
  padding: .8rem .95rem .8rem .5rem;
  background: transparent;
  border-left: 0;
  font-size: .92rem;
  letter-spacing: .04em;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cupom__cta--revelado:hover .cupom__cta-codigo {
  background: transparent;
  letter-spacing: .04em;
}

/* Confirmação rápida de "copiado" — mesmo verde do hover, sem esperar o
 * ícone voltar a virar clipboard (ver o setTimeout em app.js). */
.cupom__cta--copiado { background: var(--verde-forte); }

/* O padding é o alvo de toque: sem ele o link tinha ~14px de altura, longe do
   mínimo confortável no dedo. O texto continua discreto. */
.cupom__compartilhar {
  align-self: center; font-size: .74rem; color: var(--texto-fraco);
  text-decoration: none; padding: .45rem .8rem; margin: -.15rem 0;
}
.cupom__compartilhar:hover { color: var(--texto); text-decoration: underline; }

/* ============ Abas Cupons / Ofertas (loja + categoria) ============
 *
 * Controle segmentado grande: duas "gavetas" com badge de contagem. Ativo
 * ganha superfície branca + sombra — o mesmo idioma visual do admin
 * (`.abas`), mas com escala de página pública. */

.cupom-abas { margin: 1.6rem 0 0; }

.cupom-abas__lista {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  margin: 0 0 1.25rem;
  padding: 4px;
  background:
    linear-gradient(180deg, var(--superficie-2), color-mix(in srgb, var(--superficie-2) 70%, var(--borda)));
  border: 1px solid var(--borda);
  border-radius: calc(var(--raio) + 2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .7);
}

.cupom-abas__aba {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  min-height: 2.85rem;
  padding: .6rem .85rem;
  border: 0;
  border-radius: calc(var(--raio) - 2px);
  background: transparent;
  color: var(--texto-fraco);
  font: inherit;
  font-family: var(--fonte-display);
  font-size: clamp(.92rem, 2.4vw, 1.05rem);
  font-weight: 750;
  letter-spacing: -.015em;
  cursor: pointer;
  transition: background .15s, color .15s, box-shadow .15s;
  -webkit-tap-highlight-color: transparent;
}

.cupom-abas__aba:hover {
  color: var(--texto);
  background: rgba(255, 255, 255, .55);
}

.cupom-abas__aba--atual {
  background: var(--superficie);
  color: var(--texto);
  box-shadow:
    0 1px 2px rgba(12, 27, 23, .06),
    0 8px 18px -10px rgba(12, 27, 23, .22);
  font-weight: 800;
}

.cupom-abas__aba--atual:hover {
  background: var(--superficie);
  color: var(--texto);
}

.cupom-abas__icone {
  display: inline-flex;
  flex: none;
  color: currentColor;
  opacity: .7;
}
.cupom-abas__aba--atual .cupom-abas__icone {
  opacity: 1;
  color: var(--verde-forte);
}

.cupom-abas__rotulo {
  min-width: 0;
  line-height: 1.15;
  text-align: left;
}

.cupom-abas__badge {
  flex: none;
  min-width: 1.55rem;
  height: 1.4rem;
  padding: 0 .42rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  font-family: var(--fonte-corpo);
  font-size: .72rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  background: color-mix(in srgb, var(--borda) 80%, var(--superficie));
  color: var(--texto-fraco);
  border: 1px solid var(--borda);
}

.cupom-abas__aba--atual .cupom-abas__badge {
  background: var(--verde-luz);
  color: var(--verde-escuro);
  border-color: color-mix(in srgb, var(--verde) 35%, transparent);
}

/* Com JS: painel inativo some. Sem JS (sem html.js): os dois painéis ficam
 * empilhados — o `hidden` do servidor é ignorado pra ninguém perder ofertas. */
html.js .cupom-abas__painel[hidden] { display: none !important; }
html:not(.js) .cupom-abas__painel[hidden] {
  display: block !important;
  margin-top: 2rem;
}
html:not(.js) .cupom-abas__lista { pointer-events: none; }

/* No celular o rótulo "Ofertas imperdíveis" aperta: quebra em duas linhas. */
@media (max-width: 420px) {
  .cupom-abas__aba {
    flex-wrap: wrap;
    gap: .3rem .4rem;
    padding: .55rem .5rem;
    min-height: 3.1rem;
  }
  .cupom-abas__rotulo {
    flex: 1 1 100%;
    order: 3;
    font-size: .88rem;
    text-align: center;
  }
  .cupom-abas__icone { order: 1; }
  .cupom-abas__badge { order: 2; margin-left: auto; }
}

/* ============ cupons aplicáveis (produto sem código → cupons da mesma loja) ============
 *
 * Uma promoção sem código pode ter cupons PUROS (sem foto/preço próprios) da
 * MESMA loja que se aplicam em cima dela
 * (Repo\Coupon::eligibleByStores/applicableToPrice) — este é o "X cupons
 * disponíveis". O botão em si é compartilhado pelo ticket (.cupom) e pelo
 * tile de grade (.cupom-grid); a LISTA mora num <template> (nunca visível,
 * nunca no fluxo do teclado) e o clique clona esse conteúdo pro modal
 * compartilhado #modal-cupons (ver src/View/layout.php e app.js) — um modal
 * em vez de abrir inline porque o card já compete por espaço com o resto da
 * listagem.
 *
 * Cada item dentro do modal é o MESMO ticket (.cupom / coupon-card.php) do
 * resto do site — pedido do usuário — então não há CSS de item aqui: o
 * modal só precisa de espaço pra esse ticket respirar (.modal__caixa--cupons
 * mais largo que o modal de código) e rolagem quando a lista passa da tela.
 *
 * No tile de grade o botão fica FORA do <a> que embrulha o card inteiro —
 * um <button> dentro de <a> é HTML inválido e roubaria o clique do link —
 * então esta é uma peça irmã, não uma filha, do link.
 */
.cupons-aplicaveis { grid-column: 1 / -1; }

/* ---- a forma CHIP (tile de grade) ----
 * No tile de grade a barra de largura inteira caía no fim do card, embaixo do
 * "copiar link": lia como rodapé e custava uma faixa inteira de altura numa
 * coluna que já é estreita. Como chip ela sobe pra foto e vira o terceiro
 * selo, junto do desconto (canto superior esquerdo) e da urgência (superior
 * direito) — canto INFERIOR esquerdo, alinhado com o desconto na mesma
 * coluna, sem custar altura nenhuma.
 *
 * A moldura absoluta espelha o quadrado da foto sem medir nada: mesma largura
 * do card (left/right: 0) e `aspect-ratio: 1`, exatamente o que .cupom-grid__foto
 * usa. Ela cobre a foto inteira, que é área clicável do <a> do card, então
 * `pointer-events: none` devolve o clique pro link e só o chip volta a
 * recebê-lo. */
.cupons-aplicaveis--chip {
  position: absolute; top: 0; left: 0; right: 0;
  aspect-ratio: 1;
  display: flex; align-items: flex-end;
  padding: .5rem .5rem 0;
  pointer-events: none;
}
/* Verde ESCURO, não o --verde do "Ver oferta": sobre foto branca de
 * e-commerce o chip precisa de contraste de texto que o --verde não dá em
 * 11px (3,7:1), e ficar diferente do CTA deixa claro que são duas ações
 * distintas — uma abre a loja, a outra abre a lista de cupons. */
/* O chip ATRAVESSA a linha que fecha a foto (pedido do usuário: "mais pra
 * baixo") — a margem negativa o desce pra fora do quadrado da foto, então ele
 * fica pendurado na borda em vez de flutuar na folga de cima dela. O corpo do
 * card tem .75rem de respiro no topo, que é o teto desse avanço: mais que
 * isso e o chip encosta no nome da loja. */
.cupons-aplicaveis--chip .cupons-aplicaveis__btn {
  margin-bottom: -.55rem;
  pointer-events: auto;
  width: auto; gap: .25rem;
  border: 0; border-radius: 999px;
  padding: .32rem .6rem;
  background: var(--verde-escuro); color: #fff;
  font-size: .68rem; font-weight: 800; letter-spacing: .01em;
  white-space: nowrap;
  box-shadow: 0 2px 6px -2px rgba(0, 0, 0, .35);
}
.cupons-aplicaveis--chip .cupons-aplicaveis__btn:hover {
  background: var(--verde-forte); border-color: transparent;
}

.cupons-aplicaveis__btn {
  display: flex; align-items: center; justify-content: center; gap: .4rem;
  width: 100%; font: inherit; cursor: pointer;
  border: 1px dashed var(--verde);
  border-radius: 10px;
  padding: .55rem .7rem;
  background: var(--verde-luz);
  color: var(--verde-escuro);
  font-weight: 700; font-size: .82rem;
  transition: background .15s, border-color .15s;
}
.cupons-aplicaveis__btn:hover {
  background: color-mix(in srgb, var(--verde-luz) 60%, var(--verde));
  border-color: var(--verde-forte);
}

/* A lista real (.cupons-lista com tickets .cupom dentro) vive em
 * #modal-cupons-corpo depois de clonada do <template> do card — ver
 * app.js:abrirModalCupons(). Mais largo que o modal de código (430px): o
 * ticket no layout desktop usa 3 colunas e precisa de espaço pra não
 * espremer título/regras. */
/* Especificidade composta (não só .modal__caixa--cupons) de propósito: a
 * regra base .modal__caixa (mais abaixo no arquivo) tem a MESMA
 * especificidade de uma classe só, e por vir depois na cascata venceria o
 * width daqui — foi o que deixava este modal preso nos 430px do outro. */
.modal__caixa.modal__caixa--cupons { text-align: left; width: min(800px, calc(100% - 2rem)); }
.modal__cupons-corpo { max-height: 65vh; overflow-y: auto; margin: 0 -1.6rem; padding: 0 1.6rem; }

/* ============ GRID de ofertas sem código ============ */

/* Estante de produto, não fileira de linhas — ver o comentário no topo do
 * arquivo. 2 colunas no celular (padrão dos apps de marketplace), 3 quando
 * sobra largura de tablet, 4 no desktop — o "4 por linha" pedido só cabe
 * confortável a partir de --wrap ampla o bastante (ver .wrap, min(1060px,
 * 100% - 2rem)); forçar 4 antes disso espremia foto+título+preço demais. */
.cupons-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .9rem;
}
@media (min-width: 600px) {
  .cupons-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 1100px) {
  .cupons-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1.1rem; }
}

/* O card inteiro é UM alvo pro "Ver oferta" (diferente do ticket, onde só o
 * CTA reage ao mouse — ver o comentário lá): a ação principal é sempre a
 * mesma, então o hover do card inteiro não atrapalha nenhum sub-alvo dela.
 * O "copiar link" é a exceção — mora FORA do <a>, como peça irmã (mesmo
 * motivo do .cupons-aplicaveis logo abaixo), então não compete com esse hover. */
.cupom-grid {
  position: relative;
  display: flex; flex-direction: column;
  border-radius: var(--raio);
  background: var(--superficie);
  border: 1px solid var(--borda-forte);
  box-shadow: var(--cupom-sombra);
  /* Mesmo motivo do .cupom: sem isso o deep link #c-slug encosta o card no
   * topo da viewport e o header sticky (--topo-h, medido pelo app.js) cobre
   * a parte de cima — inclusive o selo de desconto. */
  scroll-margin-top: calc(var(--topo-h, 96px) + .75rem);
  overflow: hidden;
  transition: transform .15s cubic-bezier(.2, .8, .3, 1.3), box-shadow .15s;
}
.cupom-grid:hover {
  transform: translateY(-2px);
  box-shadow: var(--cupom-sombra-alta);
}
@media (prefers-reduced-motion: reduce) {
  .cupom-grid { transition: none; }
  .cupom-grid:hover { transform: none; }
}

/* Mesmo destaque de deep link do ticket (ver .cupom:target/.cupom--destaque)
 * — reaproveita as mesmas variáveis e a mesma animação de chegada, só que
 * aplicadas na moldura do card em vez do fundo de uma linha. */
.cupom-grid:target,
.cupom-grid--destaque {
  box-shadow: inset 0 0 0 3px var(--verde), var(--cupom-sombra-alta);
  animation: cupom-destaque-chegada 1.4s ease-out 1;
}
@media (prefers-reduced-motion: reduce) {
  .cupom-grid:target,
  .cupom-grid--destaque { animation: none; }
}

/* Cartão "Ofertas da Shopee agora" (Controller\Site::shopeeLive()):
 * mesmo tile de estante que qualquer outra oferta sem código no site — só a
 * borda tracejada marca que este nunca passou pela curadoria normal (sem
 * `coupons` row por trás dele). O rótulo de "ao vivo" fica na seção (título
 * + parágrafo em search.php), não repetido card a card. */
.cupom-grid--vivo { border-style: dashed; }

.cupom-grid__link {
  display: flex; flex-direction: column; flex: 1;
  color: inherit; text-decoration: none;
}
.cupom-grid__link:focus-visible {
  outline: 3px solid var(--verde); outline-offset: -3px;
}

.cupom-grid__foto {
  position: relative;
  aspect-ratio: 1;
  /* Sem isso, o item de flex (a coluna inteira dentro de .cupom-grid__link)
   * calcula um tamanho mínimo automático a partir do CONTEÚDO — e uma foto
   * retrato alta (ex.: fone de ouvido vertical) vence o aspect-ratio: 1 e
   * estica o quadrado num retângulo. `overflow: hidden` zera esse mínimo
   * automático (é a regra do spec: min-size automático é 0 quando overflow
   * não é visible), então o aspect-ratio passa a mandar de verdade. */
  overflow: hidden;
  background: #fff; /* foto de e-commerce já vem recortada sobre branco */
  border-bottom: 1px solid var(--borda);
}
.cupom-grid__foto-img {
  width: 100%; height: 100%;
  object-fit: contain; /* `cover` cortaria a peça que a pessoa quer reconhecer */
  padding: .5rem;
}
/* Sem foto (linha coletada antes da coluna existir): tarja com a cor da
 * loja no lugar do produto, em vez de deixar o slot vazio — mantém a altura
 * do card igual à dos vizinhos que têm foto. */
.cupom-grid__foto--vazio {
  display: flex; align-items: center; justify-content: center;
  background: var(--loja-suave);
}
.cupom-grid__foto-rotulo {
  font-size: .78rem; font-weight: 800; letter-spacing: .08em;
  color: var(--loja-tinta); opacity: .6;
}
.cupom-grid__selo {
  position: absolute; top: .5rem; left: .5rem;
  background: var(--loja-cor); color: var(--loja-chip-texto);
  font-size: .7rem; font-weight: 800; letter-spacing: .02em;
  padding: .2rem .5rem; border-radius: 999px;
  box-shadow: 0 2px 6px -2px rgba(0, 0, 0, .35);
}
/* Canto oposto ao desconto — de propósito, ver o comentário no partial. */
.cupom-grid__urgencia {
  position: absolute; top: .5rem; right: .5rem;
  background: var(--vermelho); color: #fff;
  font-size: .66rem; font-weight: 800; letter-spacing: .02em;
  padding: .2rem .5rem; border-radius: 999px;
  box-shadow: 0 2px 6px -2px rgba(0, 0, 0, .35);
}

.cupom-grid__corpo {
  display: flex; flex-direction: column; gap: .35rem;
  flex: 1; /* empurra o CTA pro rodapé mesmo quando o corpo é curto */
  padding: .75rem .85rem .3rem;
}
.cupom-grid__loja {
  align-self: flex-start; max-width: 100%;
  display: inline-flex; align-items: center; gap: .3rem;
  /* Padding IGUAL dos dois lados. A versão anterior encolhia a esquerda
     (.16rem) pra "compensar" o peso da logo, e o resultado era um chip
     visivelmente torto: 3px de folga na esquerda contra 8px na direita. */
  padding: .16rem .5rem; border-radius: 999px;
  background: var(--loja-suave);
  border: 1px solid color-mix(in srgb, var(--loja-cor) 22%, transparent);
  font-size: .7rem; font-weight: 800; letter-spacing: -.01em;
  color: var(--loja-tinta);
}
.cupom-grid__loja .marca-loja { --h: 17px; border-radius: 5px; }
.cupom-grid__loja .marca-loja--mono { font-size: .5rem; }
.cupom-grid__loja-nome { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cupom-grid__titulo {
  margin: 0;
  font-size: .88rem; font-weight: 700; line-height: 1.3;
  color: var(--texto);
  /* Clamp de 2 linhas — sem isso um título longo empurra o preço/CTA pra
   * fora da altura comum da linha do grid. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Nota e "verificado" pareadas numa linha só — cada uma é uma prova curta,
 * juntas custam menos altura que empilhadas. `space-between` com um dos dois
 * ausente ainda funciona (o que sobra fica à esquerda, sem vão estranho). */
.cupom-grid__linha-secundaria {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
}
.cupom-grid__nota {
  margin: 0; display: flex; align-items: center; gap: .2rem;
  font-size: .78rem; font-weight: 700; color: var(--ouro);
  white-space: nowrap;
}
.cupom-grid__estrela { color: var(--ouro); }
.cupom-grid__preco {
  margin: 0; display: flex; flex-direction: column; gap: .05rem;
}
.cupom-grid__preco-de {
  font-size: .72rem; color: var(--texto-fraco);
}
.cupom-grid__preco-por {
  font-family: var(--fonte-display);
  font-size: 1.15rem; font-weight: 800; letter-spacing: -.02em;
  color: var(--texto);
}
.cupom-grid__prova {
  margin: 0; font-size: .72rem; font-weight: 600;
  color: var(--verde-forte);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.cupom-grid__cta {
  margin: .6rem .85rem .85rem;
  display: flex; align-items: center; justify-content: center; gap: .3rem;
  padding: .6rem; border-radius: 10px;
  background: var(--verde); color: #fff;
  font-weight: 800; font-size: .85rem;
  transition: background .15s;
}
.cupom-grid__link:hover .cupom-grid__cta { background: var(--verde-forte); }

/* Mesmo idioma visual do .cupom__compartilhar do ticket: texto discreto,
 * padding pensado pro alvo de toque (sem ele fica bem abaixo do mínimo
 * confortável no dedo), sem sublinhado até o hover. */
.cupom-grid__compartilhar {
  display: block; text-align: center;
  margin: -.15rem .85rem .7rem;
  padding: .45rem .8rem;
  font-size: .74rem; color: var(--texto-fraco);
  text-decoration: none;
}
.cupom-grid__compartilhar:hover { color: var(--texto); text-decoration: underline; }

/* ============ botões genéricos ============ */

/* `display: inline-flex` + `text-decoration: none` porque .btn é usado tanto em
 * <button> quanto em <a> (admin: "+ Novo cupom", "Voltar", "Editar antes"). No
 * <a> o sublinhado do link vazava e o padding vertical não valia. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  font: inherit; cursor: pointer; text-decoration: none;
  border-radius: 10px; border: 1px solid transparent;
  padding: .6rem 1rem; font-weight: 600;
  transition: background .15s, border-color .15s;
}
.btn--principal { background: var(--verde); color: #fff; font-weight: 700; }
.btn--principal:hover { background: var(--verde-forte); }
.btn--copiar { background: var(--verde); color: #fff; font-weight: 800; padding-inline: 1.2rem; }
.btn--copiar:hover { background: var(--verde-forte); }
.btn--mini {
  padding: .35rem .7rem; font-size: .82rem;
  background: var(--superficie-2); border-color: var(--borda); color: var(--texto);
}
.btn--mini[aria-pressed="true"] { background: var(--verde); color: #fff; border-color: var(--verde); }
.btn--sec { background: var(--superficie); border-color: var(--borda-forte); color: var(--texto); }
.btn--sec:hover { border-color: var(--texto-fraco); }
.btn--perigo { background: var(--vermelho); color: #fff; }

/* ============ modal ============ */

.modal { position: fixed; inset: 0; z-index: 50; display: grid; place-items: center; }
.modal[hidden] { display: none; }
.modal__fundo {
  position: absolute; inset: 0; background: rgba(8, 20, 16, .62);
  -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
}
.modal__caixa {
  position: relative; overflow: hidden;
  width: min(430px, calc(100% - 2rem));
  background: var(--superficie); border-radius: 22px;
  padding: 1.9rem 1.6rem 1.2rem;
  box-shadow: 0 30px 70px rgba(8, 20, 16, .35);
  text-align: center;
  animation: sobe .2s cubic-bezier(.2, 1.2, .4, 1);
}
@keyframes sobe { from { opacity: 0; transform: translateY(14px) scale(.96); } }
@media (prefers-reduced-motion: reduce) { .modal__caixa { animation: none; } }

.modal__x {
  position: absolute; top: .5rem; right: .75rem;
  background: none; border: 0; font-size: 1.7rem; line-height: 1;
  cursor: pointer; color: var(--texto-fraco);
}
.modal__olho {
  margin: 0; font-size: .7rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--verde-forte); font-weight: 800;
}
.modal__titulo {
  margin: .35rem 0 1.1rem;
  font-family: var(--fonte-display);
  font-size: 1.08rem; line-height: 1.3; font-weight: 750;
}

.modal__codigo-area { display: flex; gap: .5rem; align-items: stretch; margin-bottom: .8rem; }
.modal__codigo {
  flex: 1; display: grid; place-items: center;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1.32rem; font-weight: 800; letter-spacing: .1em;
  padding: .75rem .8rem; border-radius: 12px;
  background: var(--verde-luz); border: 2px dashed var(--verde);
  color: var(--verde-escuro); word-break: break-all;
}
.modal__dica { margin: 0 0 1rem; font-size: .84rem; color: var(--texto-fraco); line-height: 1.45; }
.modal__feedback {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  font-size: .84rem; color: var(--texto-fraco);
  border-top: 1px solid var(--borda); padding-top: .9rem; flex-wrap: wrap;
}

/* Confete quando o código chega — 1s de festa, some sozinho. */
.confete {
  position: absolute; top: 42%; left: 50%;
  width: 9px; height: 13px; border-radius: 2px;
  pointer-events: none; opacity: 0;
  animation: estoura .95s ease-out forwards;
}
@keyframes estoura {
  0%   { opacity: 1; transform: translate(0, 0) rotate(0); }
  100% { opacity: 0; transform: translate(var(--cx), var(--cy)) rotate(var(--cr)); }
}

/* ============ conteúdo e rodapé ============ */

.conteudo-loja { margin-top: 2.5rem; max-width: 700px; }
.conteudo-loja h2 { font-family: var(--fonte-display); font-size: 1.15rem; }

/* ---- "isso é só a vitrine": as duas portas pro índice completo ----
 * Fecha as duas prateleiras da home (cupons + ofertas), que mostram só um
 * punhado de cada. Painel claro de propósito: o rodapé é o único bloco escuro
 * do site, e um segundo logo acima dele mataria esse efeito. O peso vem do
 * gradiente verde e do brilho lima, não de inverter a página. */

.explorar {
  position: relative; overflow: hidden;
  margin: 3.2rem 0 0; padding: 2.1rem 1.5rem 1.9rem;
  border: 1px solid color-mix(in srgb, var(--verde) 28%, transparent);
  border-radius: calc(var(--raio) + 6px);
  background:
    radial-gradient(520px 260px at 12% -40%, color-mix(in srgb, var(--lima) 34%, transparent), transparent 68%),
    linear-gradient(160deg, var(--verde-luz), var(--superficie) 62%);
  text-align: center;
}
/* Bolha lima atrás do canto direito — a mesma família de arte do hero, só
   que aqui ela existe pra dar profundidade num bloco que é quase só texto. */
.explorar__brilho {
  position: absolute; right: -90px; top: -110px;
  width: 300px; height: 300px; border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--verde) 20%, transparent), transparent 62%);
  pointer-events: none;
}
.explorar__titulo {
  position: relative;
  font-family: var(--fonte-display);
  font-size: clamp(1.4rem, 3.4vw, 1.85rem); font-weight: 800; letter-spacing: -.028em;
  margin: 0 0 .45rem;
}
.explorar__texto {
  position: relative;
  margin: 0 auto 1.5rem; max-width: 46ch;
  color: var(--texto-fraco); font-size: .95rem;
}
.explorar__portas {
  position: relative;
  display: grid; gap: .8rem;
  grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
  max-width: 720px; margin: 0 auto;
}

.porta {
  display: flex; align-items: center; gap: .85rem;
  padding: 1rem 1.1rem;
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  box-shadow: var(--sombra);
  color: inherit; text-decoration: none; text-align: left;
  transition: translate .18s, box-shadow .18s, border-color .18s;
}
.porta:hover, .porta:focus-visible {
  translate: 0 -3px;
  border-color: color-mix(in srgb, var(--verde) 45%, transparent);
  box-shadow: var(--sombra-alta);
}
.porta__icone {
  display: grid; place-items: center; flex: none;
  width: 44px; height: 44px; border-radius: 12px;
  background: var(--verde-luz);
  border: 1px solid color-mix(in srgb, var(--verde) 22%, transparent);
  font-size: 1.35rem; line-height: 1;
}
.porta--categorias .porta__icone { background: var(--ouro-luz); border-color: color-mix(in srgb, var(--ouro) 22%, transparent); }
.porta__corpo { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.porta__titulo {
  font-family: var(--fonte-display);
  font-size: 1.02rem; font-weight: 800; letter-spacing: -.02em;
}
.porta__linha { font-size: .83rem; color: var(--texto-fraco); font-variant-numeric: tabular-nums; }
.porta__linha strong { color: var(--verde-escuro); font-weight: 800; }
/* A seta anda um pouco no hover — o único movimento dentro do card, então
   lê como "isto leva a algum lugar" sem precisar de mais nada. */
.porta__seta {
  margin-left: auto; flex: none;
  color: var(--verde-forte); font-weight: 800; font-size: 1.05rem;
  transition: translate .18s;
}
.porta:hover .porta__seta, .porta:focus-visible .porta__seta { translate: 3px 0; }

@media (prefers-reduced-motion: reduce) {
  .porta, .porta__seta { transition: none; }
  .porta:hover, .porta:focus-visible { translate: none; }
  .porta:hover .porta__seta, .porta:focus-visible .porta__seta { translate: none; }
}

/* ---- "como funciona": 4 passos com trilha tracejada ---- */

.como { margin: 3rem 0 3.5rem; }
.passos-grade {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: .9rem;
  grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  counter-reset: passo;
}
.passo {
  position: relative;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 1.2rem 1.2rem 1.15rem;
  box-shadow: var(--sombra);
  /* opacity/transform = entrada do .surge (mesmo esquema dos cards). */
  transition: opacity .5s ease, transform .5s cubic-bezier(.2, .7, .3, 1),
              translate .18s, box-shadow .18s;
}
.passo:hover { translate: 0 -3px; box-shadow: var(--sombra-alta); }
.passo__n {
  display: grid; place-items: center;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--tinta); color: var(--lima);
  font-family: var(--fonte-display);
  font-size: .95rem; font-weight: 800;
  margin-bottom: .65rem;
}
/* Traço ligando um passo ao próximo (some no último e no empilhado). */
@media (min-width: 920px) {
  .passo:not(:last-child)::after {
    content: "";
    position: absolute; top: 2.25rem; left: calc(100% + 1px);
    width: .9rem; border-top: 2px dashed var(--borda-forte);
  }
}
.passo h3 { margin: 0 0 .25rem; font-size: .99rem; font-weight: 750; letter-spacing: -.015em; }
.passo p  { margin: 0; font-size: .86rem; color: var(--texto-fraco); line-height: 1.5; }

/* ---- rodapé: o único bloco escuro do site — fecho premium, não tema ---- */

.rodape {
  margin-top: 4rem; padding: 2.75rem 0 1.1rem;
  background: var(--tinta); color: #a7b6ae;
  font-size: .87rem;
}
.rodape a { color: #cfe0d6; }
.rodape__grade {
  display: grid; gap: 1.9rem;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  padding-bottom: 1.9rem;
}
.rodape__bloco p { margin: 0 0 .6rem; line-height: 1.65; }
.rodape__marca {
  display: block; margin-bottom: .6rem;
  font-family: var(--fonte-display);
  font-size: 1.25rem; font-weight: 700; letter-spacing: -.03em; color: #fff;
}
.rodape__marca strong { color: var(--lima); font-weight: 800; }
.rodape__titulo {
  margin: 0 0 .65rem; font-size: .72rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .12em; color: #fff;
}
.rodape__lista { list-style: none; margin: 0; padding: 0; }
.rodape__lista li { margin-bottom: .4rem; }
.rodape__lista a { color: #a7b6ae; text-decoration: none; }
.rodape__lista a:hover { color: var(--lima); text-decoration: underline; }
.rodape__mini { font-size: .8rem; }
.rodape__mini strong { color: #e6efe9; }

/* Sinalização de publicidade — exigência legal (CDC/CONAR). Em linha própria
 * logo acima do copyright: dentro do bloco escuro não precisa de fundo
 * próprio, só de espaço e do grifo em lima pra não virar letra miúda. */
.aviso-afiliado {
  margin: 0; padding-inline: 1rem;
  font-size: .82rem; line-height: 1.55; letter-spacing: .01em;
  text-align: center;
  color: #a7b6ae;
}
.aviso-afiliado strong { color: var(--lima); font-weight: 750; }
.rodape__base .aviso-afiliado { flex-basis: 100%; padding-inline: 0; }

.rodape__base {
  display: flex; flex-wrap: wrap; justify-content: center; gap: .4rem 1.25rem;
  padding: 1.1rem 1rem 1.25rem; border-top: 1px solid rgba(255, 255, 255, .12);
  font-size: .78rem; text-align: center;
}

/* Wordmark gigante fantasma no pé — assinatura da marca. */
.rodape__eco {
  margin: 0; padding-top: 1.5rem;
  font-family: var(--fonte-display);
  /* O piso era 3rem: em tela de 320px o clamp travava aí e a palavra media
     350px — 30px de estouro, a maior fonte de deslize lateral do celular.
     Com 2rem o 12vw manda em qualquer telefone e a palavra sempre cabe. */
  font-size: clamp(2rem, 12vw, 8.5rem); font-weight: 800; letter-spacing: -.05em;
  line-height: .8; text-align: center; user-select: none;
  color: transparent;
  -webkit-text-stroke: 1px rgba(255, 255, 255, .14);
}

/* ============ busca ============ */

.busca-form { position: relative; }
.busca-form__rotulo {
  /* Visually hidden, not display:none — a screen reader still needs the
     label; the placeholder already carries the visible hint. */
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
.busca-form__caixa {
  display: flex; align-items: center; gap: .5rem;
  background: var(--superficie); border: 1px solid var(--borda-forte);
  border-radius: 999px; padding: .3rem .3rem .3rem 1.1rem;
  transition: border-color .15s, box-shadow .15s;
}
.busca-form__caixa:focus-within {
  border-color: var(--verde); box-shadow: 0 0 0 3px var(--verde-luz);
}
.busca-form__icone { width: 20px; height: 20px; flex: none; color: var(--texto-fraco); }
.busca-form__campo {
  flex: 1; min-width: 0; border: 0; background: transparent; font: inherit;
  color: var(--texto); padding: .5rem 0;
}
.busca-form__campo:focus { outline: none; }
.busca-form__campo::placeholder { color: var(--texto-fraco); }
/* Kills the native ✕/spyglass Safari and Chrome add on type="search" — the
   custom icon and the dropdown already give plenty of affordance. */
.busca-form__campo::-webkit-search-cancel-button,
.busca-form__campo::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
.busca-form__botao {
  flex: none; border: 0; cursor: pointer;
  background: var(--verde); color: #fff; font-weight: 750; font-size: .9rem;
  padding: .62rem 1.3rem; border-radius: 999px;
  transition: background .15s, transform .15s;
}
.busca-form__botao:hover { background: var(--verde-forte); }
.busca-form__botao:active { transform: scale(.97); }

/* ---- variante hero: o campo é o objeto principal da home ----
 *
 * A presença vem de TRÊS camadas que acendem juntas no foco, não de uma borda
 * mais grossa: a aura desfocada atrás da pílula, o anel em gradiente lima→verde
 * na borda, e a sombra de elevação. Sozinha nenhuma sustenta um campo desse
 * tamanho — junto, o input deixa de ler como controle de formulário. */

.busca-form--hero {
  max-width: none; margin: 0;
  /* `isolate` cria contexto de empilhamento: sem ele o z-index:-1 da aura cai
     atrás do fundo da faixa do hero e some. */
  isolation: isolate;
}

.busca-form--hero::before {
  content: "";
  position: absolute; inset: -12px -5px -18px; z-index: -1;
  border-radius: 999px;
  background: linear-gradient(100deg, var(--lima), var(--verde) 55%, var(--lima));
  filter: blur(24px); opacity: .32;
  transition: opacity .28s ease, filter .28s ease;
}
.busca-form--hero:hover::before { opacity: .48; }
.busca-form--hero:focus-within::before { opacity: .72; filter: blur(30px); }

.busca-form--hero .busca-form__caixa {
  position: relative; z-index: 1;
  gap: .9rem;
  padding: .55rem .55rem .55rem 1.75rem;
  /* Anel em gradiente com canto arredondado sem SVG: o branco pinta o
     padding-box e o gradiente pinta o border-box, com a borda transparente
     deixando o segundo aparecer. Por isso `border-color` fica transparent em
     TODOS os estados daqui pra baixo — pintar a borda apaga o anel. */
  border: 2px solid transparent;
  background:
    linear-gradient(var(--superficie), var(--superficie)) padding-box,
    linear-gradient(100deg,
      color-mix(in srgb, var(--lima) 70%, white),
      color-mix(in srgb, var(--verde) 45%, white) 50%,
      color-mix(in srgb, var(--lima) 60%, white)) border-box;
  box-shadow: 0 4px 12px rgba(12, 27, 23, .07), 0 26px 50px -22px rgba(12, 27, 23, .38);
  transition: box-shadow .22s ease, background .22s ease;
}
.busca-form--hero .busca-form__caixa:focus-within {
  border-color: transparent;
  background:
    linear-gradient(var(--superficie), var(--superficie)) padding-box,
    linear-gradient(100deg, var(--verde), var(--lima) 50%, var(--verde)) border-box;
  box-shadow: 0 4px 14px rgba(12, 27, 23, .08), 0 34px 60px -22px rgba(12, 27, 23, .42);
}

/* A lupa acompanha o foco: cinza em repouso, verde quando o campo está ativo. */
.busca-form--hero .busca-form__icone {
  width: 26px; height: 26px;
  transition: color .22s ease;
}
.busca-form--hero .busca-form__caixa:focus-within .busca-form__icone { color: var(--verde); }

.busca-form--hero .busca-form__campo {
  font-family: var(--fonte-display);
  font-size: 1.3rem; font-weight: 500; letter-spacing: -.015em;
  padding: 1.05rem 0;
}

.busca-form--hero .busca-form__botao {
  font-family: var(--fonte-display);
  font-size: 1.05rem; letter-spacing: -.01em;
  padding: .95rem 2.2rem;
  /* Mesma linguagem de "botão físico" do .btn-hero logo abaixo: aresta sólida
     embaixo + halo verde difuso. Dois botões primários lado a lado com
     sombras diferentes brigam. */
  box-shadow: 0 3px 0 var(--verde-escuro), 0 14px 26px -12px rgba(0, 153, 79, .55);
  transition: background .15s, transform .15s, box-shadow .15s;
}
.busca-form--hero .busca-form__botao:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 0 var(--verde-escuro), 0 18px 32px -12px rgba(0, 153, 79, .6);
}
.busca-form--hero .busca-form__botao:active {
  transform: translateY(2px); box-shadow: 0 0 0 var(--verde-escuro);
}

/* Sugestões acompanham a largura nova, então ganham respiro e fonte de leitura
   à altura do campo. */
.busca-form--hero .busca-sugestoes { padding: .5rem; top: calc(100% + .7rem); }
.busca-form--hero .busca-sugestoes__link { padding: .7rem .85rem; font-size: 1rem; }

/* No celular o botão come a largura que o texto digitado precisa: encolhe os
   dois lados em vez de deixar o campo virar uma fresta. */
@media (max-width: 619px) {
  .busca-form--hero::before { inset: -7px -3px -11px; filter: blur(16px); }
  .busca-form--hero .busca-form__caixa { gap: .55rem; padding: .4rem .4rem .4rem 1.1rem; }
  .busca-form--hero .busca-form__icone { width: 21px; height: 21px; }
  .busca-form--hero .busca-form__campo { font-size: 1.08rem; padding: .78rem 0; }
  .busca-form--hero .busca-form__botao { padding: .72rem 1.25rem; font-size: .95rem; }
}

.busca-form--compacto { max-width: 480px; }
.busca-form--compacto .busca-form__caixa { padding: .18rem .18rem .18rem 1rem; }
.busca-form--compacto .busca-form__botao { padding: .5rem 1.1rem; font-size: .86rem; }

.busca-form--topo { width: 100%; }
.busca-form--topo .busca-form__caixa {
  min-height: 46px;
  padding: .18rem .22rem .18rem .95rem;
  border-color: color-mix(in srgb, var(--verde) 18%, var(--borda-forte));
  background: color-mix(in srgb, var(--superficie) 92%, var(--verde-luz));
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .72);
}
.busca-form--topo .busca-form__caixa:focus-within {
  border-color: var(--verde);
  box-shadow: 0 0 0 3px var(--verde-luz), var(--sombra);
}
.busca-form--topo .busca-form__icone { width: 19px; height: 19px; }
.busca-form--topo .busca-form__campo {
  font-size: .95rem;
  padding: .48rem 0;
}
.busca-form--topo .busca-form__botao {
  padding: .56rem 1.05rem;
  font-size: .86rem;
  box-shadow: 0 2px 0 var(--verde-escuro);
}
.busca-form--topo .busca-form__botao:hover { transform: translateY(-1px); }
.busca-form--topo .busca-form__botao:active {
  transform: translateY(1px);
  box-shadow: 0 0 0 var(--verde-escuro);
}

@media (max-width: 520px) {
  .busca-form--topo .busca-form__caixa { gap: .4rem; padding-left: .8rem; }
  .busca-form--topo .busca-form__campo { font-size: .9rem; }
  .busca-form--topo .busca-form__botao { padding-inline: .85rem; }
}

/* ---- autocomplete dropdown ---- */

.busca-sugestoes {
  position: absolute; left: 0; right: 0; top: calc(100% + .5rem);
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); box-shadow: var(--sombra-alta);
  list-style: none; margin: 0; padding: .4rem; z-index: 30;
  max-height: 60vh; overflow-y: auto;
}
.busca-sugestoes[hidden] { display: none; }
.busca-sugestoes__item { margin: 0; }
.busca-sugestoes__link {
  display: flex; align-items: center; gap: .6rem;
  padding: .55rem .7rem; border-radius: 10px;
  text-decoration: none; color: var(--texto); font-size: .92rem;
}
.busca-sugestoes__link:hover,
.busca-sugestoes__link[aria-selected="true"] { background: var(--superficie-2); }
.busca-sugestoes__loja {
  font-weight: 750; color: var(--verde-escuro);
  background: var(--verde-luz); padding: .15rem .55rem; border-radius: 999px;
  font-size: .78rem; flex: none;
}
.busca-sugestoes__titulo { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.busca-sugestoes__loja-nome { color: var(--texto-fraco); font-size: .82rem; flex: none; }

/* Group headings (Categoria / Loja / Cupons). The dropdown reaches all three
   kinds of destination now — that's what let the header stop listing stores.
   Not focusable and not role="option", so arrow-key navigation skips it. */
.busca-sugestoes__grupo {
  margin: .5rem 0 .15rem; padding: 0 .7rem;
  font-size: .72rem; font-weight: 750; letter-spacing: .08em;
  text-transform: uppercase; color: var(--texto-fraco);
}
.busca-sugestoes__grupo:first-child { margin-top: .15rem; }

/* ---- results page ---- */

.busca-topo { padding: .2rem 0 1.6rem; }
.busca-topo h1 {
  font-family: var(--fonte-display); font-size: clamp(1.5rem, 4vw, 2.1rem);
  font-weight: 800; letter-spacing: -.03em; margin: 0 0 1rem;
}

/* Matched-store card: a shortcut to the canonical store page, sitting above
   the token-filtered results — see Search\StoreMatcher / Controller\Site::search(). */
.busca-loja {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 1rem;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 1rem 1.3rem;
  text-decoration: none; color: var(--texto);
  box-shadow: var(--sombra); margin-bottom: 1.8rem;
}
.busca-loja::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 6px; background: var(--loja-cor); }
.busca-loja:hover { border-color: color-mix(in srgb, var(--loja-cor) 55%, var(--borda)); box-shadow: var(--sombra-alta); }
.busca-loja__texto { display: flex; flex-direction: column; gap: .1rem; }
.busca-loja__texto strong { font-family: var(--fonte-display); font-size: 1.1rem; }
.busca-loja__texto span { font-size: .85rem; color: var(--texto-fraco); }
.busca-loja__seta { margin-left: auto; font-weight: 650; font-size: .88rem; color: var(--loja-tinta); flex: none; }

/* ============ toast ============ */

.toast {
  position: fixed; left: 50%; bottom: 1.25rem; transform: translateX(-50%);
  background: var(--tinta); color: #fff;
  padding: .6rem 1.1rem; border-radius: 999px; font-size: .86rem; font-weight: 600;
  z-index: 80; box-shadow: var(--sombra-alta);
}

/* ============ admin ============ */

.admin-topo { background: #101c2e; border-bottom-color: #101c2e; }
.admin-topo a { color: #b6d8c6; }
.admin-topo .topo__linha { padding: .6rem 0; }
.admin-topo .marca { color: #fff; }
.admin-topo .menu a:hover { background: rgba(255,255,255,.12); color: #fff; border-color: transparent; }

.painel {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 1.1rem; margin-bottom: 1rem;
}
.numeros { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.numero { background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--raio); padding: .95rem; }
.numero__valor { font-size: 1.8rem; font-weight: 800; line-height: 1.05; letter-spacing: -.035em; }
.numero__rotulo { font-size: .8rem; color: var(--texto-fraco); }
.numero--alerta { border-color: var(--vermelho); }

.tabela { width: 100%; border-collapse: collapse; font-size: .9rem; }
.tabela th, .tabela td { text-align: left; padding: .6rem .5rem; border-bottom: 1px solid var(--borda); vertical-align: top; }
.tabela th { font-size: .76rem; text-transform: uppercase; letter-spacing: .05em; color: var(--texto-fraco); }
.tabela-scroll { overflow-x: auto; }

.form-linha { display: grid; gap: .35rem; margin-bottom: .9rem; }
.form-linha label { font-size: .85rem; font-weight: 600; }
.form-linha input, .form-linha select, .form-linha textarea {
  font: inherit; padding: .6rem .75rem; border-radius: 10px;
  border: 1px solid var(--borda-forte); background: var(--superficie); color: var(--texto);
  width: 100%;
  min-height: 2.65rem;
  line-height: 1.35;
  box-sizing: border-box;
}
.form-linha textarea { min-height: 5.5rem; }
.form-linha select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.35rem;
  background-color: var(--superficie);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%2356675f' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .75rem center;
  background-size: 14px;
  cursor: pointer;
}
.form-linha small { font-size: .78rem; color: var(--texto-fraco); }
.form-grade { display: grid; gap: 0 1rem; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.form-acoes { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: .5rem; align-items: center; }

.pill { font-size: .72rem; padding: .18rem .55rem; border-radius: 999px; background: var(--superficie-2); border: 1px solid var(--borda); }
.pill--pendente { border-color: var(--vermelho); color: var(--vermelho); }
.pill--ativo    { border-color: var(--verde); color: var(--verde-forte); }

.flash { padding: .75rem 1rem; border-radius: 10px; margin-bottom: 1rem; font-size: .92rem; }
.flash--ok   { background: var(--verde-luz); border: 1px solid var(--verde); }
.flash--error { background: #fdecea; border: 1px solid var(--vermelho); }

.login-caixa { max-width: 370px; margin: 4rem auto; }

/* ============================================================
   Categorias — o eixo de navegação que substituiu "por loja" no topo.
   Reaproveita .lojas-grid / .loja-tile / .loja-topo de propósito: são a
   mesma ideia de navegação, e duplicar o visual só criaria duas coisas
   pra manter em sincronia.
   ============================================================ */

/* ---- painel de filtro ----
   Na categoria, Tipo / Loja / Ordenar moram no MESMO cartão. Ordenação
   reutiliza o mesmo trilho + chip (`.filtro-chip`). Visual leve: pílulas
   bem arredondadas, fundo suave, borda quase invisível.

   Classe .filtros é SÓ do site público. O admin usa .lista-filtros. */

.filtros,
.ordenacao {
  margin: .75rem 0 1.15rem;
  padding: .55rem .75rem .6rem;
  background: var(--superficie);
  border: 1px solid color-mix(in srgb, var(--borda) 70%, transparent);
  border-radius: 18px;
}
.ordenacao {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: .55rem;
  padding: .55rem .75rem;
}

.filtros__topo {
  display: flex;
  align-items: center;
  gap: .4rem;
  margin: 0 0 .35rem;
  padding: 0 .15rem .4rem;
  border-bottom: 1px solid color-mix(in srgb, var(--borda) 65%, transparent);
}
.filtros__titulo,
.ordenacao__rotulo,
.filtros__rotulo {
  font-size: .68rem;
  font-weight: 750;
  letter-spacing: .05em;
  text-transform: uppercase;
  margin: 0;
  color: var(--texto-fraco);
  line-height: 1;
}
.filtros__contagem {
  font-size: .66rem;
  font-weight: 750;
  color: var(--verde-escuro);
  background: color-mix(in srgb, var(--verde-luz) 80%, #fff);
  padding: .12rem .48rem;
  border-radius: 999px;
  font-variant-numeric: tabular-nums;
}
/* Sem ele, voltar ao estado neutro é clicar chip por chip. */
.filtros__limpar {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: center;
  font-size: .76rem;
  font-weight: 650;
  color: var(--texto-fraco);
  text-decoration: none;
  padding: .22rem .6rem;
  border-radius: 999px;
  transition: background-color .12s, color .12s;
}
.filtros__limpar:hover {
  background: var(--superficie-2);
  color: var(--texto);
}

.filtros__linha {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: .55rem;
  padding: .32rem 0;
  margin: 0;
  border: 0;
  min-width: 0;
}
.filtros__linha + .filtros__linha {
  border-top: 1px solid color-mix(in srgb, var(--borda) 55%, transparent);
}

.filtros__rotulo {
  display: inline-flex;
  align-items: center;
  min-width: 3.5rem;
}
.ordenacao__rotulo { flex: none; }

/* Trilho: cápsula leve onde moram os chips (tipo, loja e ordenar).
   Raio alto, mas não 999px — com wrap em 2 linhas o “stadium” fica estranho. */
.filtros__trilho {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  min-width: 0;
  padding: 4px;
  background: color-mix(in srgb, var(--superficie-2) 88%, #fff);
  border: 1px solid color-mix(in srgb, var(--borda) 55%, transparent);
  border-radius: 16px;
}

/*
  Chip único — filtro e ordenação. Querystring + noindex na categoria
  (Site::category). Ativo em verde suave (não bloco sólido pesado),
  exceto loja (cor da marca, ainda em pílula).
*/
.filtro-chip,
.filtro-lojas__item,
.filtro-tags__item {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .38rem .78rem;
  border-radius: 999px;
  border: 0;
  background: transparent;
  color: var(--texto-fraco);
  text-decoration: none;
  font-size: .8rem;
  font-weight: 650;
  line-height: 1.25;
  white-space: nowrap;
  transition: background-color .12s, color .12s;
}
.filtro-chip:hover,
.filtro-lojas__item:hover,
.filtro-tags__item:hover {
  color: var(--texto);
  background: rgba(255, 255, 255, .55);
}

/*
  Ativo genérico (ordenar, tipo, "Todas"): pílula branca que sobe no
  trilho — o mesmo "thumb" de um segmented control. Loja escolhida usa a
  cor da marca em vez do branco (logo abaixo).
*/
.filtro-chip--atual,
.filtro-tags__item--atual,
.filtro-lojas__item--todas.filtro-lojas__item--atual {
  background: #fff;
  color: var(--texto);
  font-weight: 750;
  box-shadow:
    0 1px 2px rgba(12, 27, 23, .06),
    0 0 0 1px color-mix(in srgb, var(--borda) 55%, transparent);
}
.filtro-chip--atual:hover,
.filtro-tags__item--atual:hover,
.filtro-lojas__item--todas.filtro-lojas__item--atual:hover {
  background: #fff;
  color: var(--texto);
  filter: none;
}

/* Loja selecionada: cor da marca, pílula com o mesmo “thumb” elevado. */
.filtro-lojas__item--atual {
  background: var(--loja-cor, var(--verde));
  color: var(--loja-chip-texto, #fff);
  font-weight: 750;
  box-shadow:
    0 1px 2px color-mix(in srgb, var(--loja-cor, var(--verde)) 28%, transparent),
    0 0 0 1px color-mix(in srgb, var(--loja-cor, var(--verde)) 35%, transparent);
}
.filtro-lojas__item--atual:hover {
  background: var(--loja-cor, var(--verde));
  color: var(--loja-chip-texto, #fff);
  filter: brightness(1.04);
}

/* Monograma da loja no chip: sempre legível, mesmo inativo. */
.filtro-lojas__item .marca-loja {
  flex: none;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--loja-cor, var(--borda)) 18%, transparent);
}
.filtro-lojas__item--atual .marca-loja {
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .45);
}
.filtro-lojas__nome { min-width: 0; }

/* Contador da tag: pílula discreta. */
.filtro-tags__n {
  font-size: .66rem;
  font-weight: 750;
  font-variant-numeric: tabular-nums;
  min-width: 1.1rem;
  padding: .06rem .34rem;
  border-radius: 999px;
  text-align: center;
  background: rgba(12, 27, 23, .06);
  color: var(--texto-fraco);
}
.filtro-tags__item--atual .filtro-tags__n {
  background: var(--superficie-2);
  color: var(--texto-fraco);
}

@media (max-width: 560px) {
  .filtros,
  .ordenacao {
    padding: .45rem .55rem .5rem;
    border-radius: 16px;
  }
  .ordenacao,
  .filtros__linha {
    grid-template-columns: 1fr;
    gap: .3rem;
  }
  .filtros__rotulo,
  .ordenacao__rotulo {
    min-width: 0;
    font-size: .64rem;
  }
  .filtro-chip,
  .filtro-lojas__item,
  .filtro-tags__item {
    padding: .34rem .65rem;
    font-size: .78rem;
  }
}

/* "Veja também": as ligações laterais que substituem a hierarquia. Um produto
   de lavação de carro pertence a elétrico E a combustão — numa árvore teria
   que escolher um pai. */
.categorias-vizinhas { margin-top: 2.4rem; }
.categorias-chips { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .8rem; }
.categoria-chip {
  display: inline-block; padding: .45rem .9rem; border-radius: 999px;
  background: var(--loja-suave, var(--superficie-2));
  color: var(--loja-tinta, var(--texto));
  border: 1px solid var(--borda); text-decoration: none;
  font-size: .88rem; font-weight: 650;
}
.categoria-chip:hover { border-color: var(--borda-forte); }

/* ---- busca: seção dos "parecidos" ----
   Eles continuam visíveis, mas nunca mais se passam por resposta: era esse o
   defeito de origem, "tapete carro elétrico" devolvendo um tapete de sala
   como se fosse o cupom certo. */
.secao-titulo--fraco { color: var(--texto-fraco); font-size: 1.05rem; }

.busca-parecidos {
  margin-top: 2.6rem; padding-top: 1.6rem;
  border-top: 1px dashed var(--borda-forte);
}
.busca-parecidos__aviso {
  margin: -.4rem 0 1.2rem; font-size: .86rem; color: var(--texto-fraco);
}
/* Meio-tom deliberado: o olho tem que bater primeiro nos exatos. */
.busca-parecidos .cupons-lista { opacity: .88; }
.busca-parecidos .cupons-lista:hover { opacity: 1; }

/* "Ofertas da Shopee agora" (Controller\Site::shopeeLive()): mesma separação
   dos parecidos, porque cumpre o mesmo papel de fronteira — dali pra baixo
   não é mais resposta do nosso catálogo. Sem o meio-tom, porém: um parecido é
   um quase-acerto e merece pesar menos, uma oferta da Shopee é o produto
   buscado e só não é nossa.

   O `hidden` vem do servidor e sai no JS quando a Shopee responde. A regra
   `[hidden]` abaixo é só um seguro: hoje nada aqui declara `display`, mas no
   dia em que alguém der um `display: grid` a esta seção, o atributo pararia
   de esconder nada e ela piscaria vazia até o pedido voltar. */
.busca-shopee[hidden] { display: none; }
/* A fronteira só existe quando há o que separar: sem nenhum resultado nosso
   acima, a seção É a página, e uma linha tracejada no topo do vazio parece
   defeito. Por isso a classe vem do servidor (search.php), que é quem sabe se
   a lista de cima ficou preenchida. */
.busca-shopee--separada {
  margin-top: 2.6rem; padding-top: 1.6rem;
  border-top: 1px dashed var(--borda-forte);
}

/* ============ /grupos-de-promocoes/ — a página de convite ============
   Ver src/View/groups.php, App\GroupShowcase e
   Repo\DeliveryChannel::publicChannels().

   Desenhada pro celular primeiro e literalmente: o tráfego dessa página vem
   de link na bio do Instagram, ou seja quase 100% telefone, uma mão só. Daí
   as três decisões que mandam no bloco inteiro —

     1. UMA coluna até 760px. Dois cards lado a lado num telefone deixariam a
        foto do produto pequena demais pra reconhecer o que é, e a foto é o
        argumento do card.
     2. Botão de entrar em bloco, largura cheia, altura >= 48px (alvo de
        polegar). Eles ficam no PÉ do card, que é onde o polegar já está.
     3. Nada acima do primeiro card além de prova: número real de 24 h,
        título e três selos de objeção. Nenhum banner decorativo empurrando
        o primeiro grupo pra fora da dobra. */

.grupos-selos {
  list-style: none; margin: .85rem 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: .35rem .4rem;
}
.grupos-selos li {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .3rem .6rem; border-radius: 999px;
  background: var(--superficie); border: 1px solid var(--borda);
  font-size: .78rem; font-weight: 600; color: var(--texto-fraco);
  box-shadow: var(--sombra); white-space: nowrap;
}
@media (min-width: 560px) { .grupos-selos li { font-size: .84rem; padding: .34rem .7rem; } }

/* O hero desta página é mais curto que o das outras DE PROPÓSITO: quem chega
   aqui veio de um link na bio pra escolher um grupo, e cada 100px gastos em
   discurso é o primeiro card saindo da dobra do telefone. Só na página de
   convite — o hero da home continua com o tamanho dele. */
.grupos-hero.hero--compacto { padding: 1.5rem 0 1.2rem; gap: .9rem; }
.grupos-hero .hero__olho { font-size: .74rem; }
.hero.grupos-hero h1 { font-size: clamp(1.55rem, 6.6vw, 2.6rem); margin-bottom: .45rem; }
.grupos-hero .hero__texto { font-size: .95rem; }
@media (min-width: 560px) {
  .grupos-hero.hero--compacto { padding: 2.4rem 0 1.9rem; }
  .grupos-hero .hero__texto { font-size: 1rem; }
}

.grupos-grade {
  display: grid; gap: 1rem; margin: 1.6rem 0 .5rem;
  grid-template-columns: 1fr;
}
/* 760 e não 560: o card cresceu (prateleira + dois botões em bloco), e a
   partir de duas colunas antes disso a foto do produto some. */
@media (min-width: 760px) {
  .grupos-grade { grid-template-columns: repeat(2, 1fr); gap: 1.2rem; }
}

/* Cor de cada card = a da PRIMEIRA categoria vinculada ao canal (ver
   Repo\DeliveryChannel::publicChannels()) — mesmas 4 variáveis --loja-* que
   Html::storeStyle() já usa nos tiles de loja/categoria, então "Eletrônicos"
   aparece aqui na mesma cor da própria página /cupom-eletronicos/. O canal
   "geral" (sem categoria) usa o verde da marca — ver GENERAL_ACCENT_COLOR. */
.grupo-card {
  position: relative; overflow: hidden;
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); box-shadow: var(--sombra);
  padding: 1.15rem 1.1rem 1.1rem 1.35rem;
  display: flex; flex-direction: column; gap: .75rem;
  transition: box-shadow .18s cubic-bezier(.2, .8, .3, 1.1), border-color .18s,
              translate .18s cubic-bezier(.2, .8, .3, 1.2);
}
.grupo-card__faixa { position: absolute; inset: 0 auto 0 0; width: 6px; background: var(--loja-cor); }
/* Brilho de canto na cor do card — mesma ideia do .loja-tile::after, só que
   mais discreto (o card já carrega bastante informação). */
.grupo-card::after {
  content: ""; position: absolute; right: -36px; top: -36px;
  width: 140px; height: 140px; border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--loja-cor) 16%, transparent), transparent);
}
.grupo-card:hover {
  translate: 0 -3px;
  box-shadow: var(--sombra-alta);
  border-color: color-mix(in srgb, var(--loja-cor) 45%, var(--borda));
}
/* O card com mais envios nas últimas 24 h (App\GroupShowcase::decorate) —
   um anel na própria cor, não uma cor nova: o destaque tem que dizer "este
   aqui", sem inventar uma segunda identidade visual pro mesmo tema. */
.grupo-card--quente {
  border-color: color-mix(in srgb, var(--loja-cor) 55%, var(--borda));
  box-shadow: var(--sombra), 0 0 0 3px color-mix(in srgb, var(--loja-cor) 16%, transparent);
}

.grupo-card__cabeca {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: .65rem;
}
.grupo-card__aro {
  flex-shrink: 0; width: 2.6rem; height: 2.6rem; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--loja-suave); transition: transform .18s cubic-bezier(.2, .8, .3, 1.4);
}
.grupo-card:hover .grupo-card__aro { transform: rotate(-8deg) scale(1.08); }
.grupo-card__emoji { font-size: 1.4rem; line-height: 1; }
.grupo-card__identidade { min-width: 0; flex: 1 1 auto; }
.grupo-card__nome {
  margin: 0; font-family: var(--fonte-display);
  font-size: 1.18rem; font-weight: 800; letter-spacing: -.025em;
  line-height: 1.15; text-wrap: balance;
}
/* A linha viva. Cor de texto normal no número (é a prova) e fraca no resto,
   pra não virar um parágrafo cinza que o olho pula. */
.grupo-card__pulso {
  margin: .2rem 0 0; display: flex; align-items: center; flex-wrap: wrap; gap: .25rem .4rem;
  font-size: .82rem; color: var(--texto-fraco); line-height: 1.3;
}
.grupo-card__pulso strong { color: var(--texto); font-weight: 800; }
.grupo-card__ultima { white-space: nowrap; }
/* Mora dentro da linha do pulso (ver groups.php) — no lugar da bolinha
   verde, não ao lado dela: os dois dizem "este grupo está se mexendo", e
   lado a lado viram dois enfeites disputando a mesma frase. */
.grupo-card__quente {
  flex-shrink: 0;
  padding: .16rem .45rem; border-radius: 999px;
  background: color-mix(in srgb, var(--loja-cor) 14%, var(--superficie));
  color: var(--loja-tinta); border: 1px solid color-mix(in srgb, var(--loja-cor) 32%, transparent);
  font-size: .7rem; font-weight: 800; white-space: nowrap; letter-spacing: -.01em;
}
.grupo-card__desc {
  position: relative; z-index: 1; margin: 0; color: var(--texto-fraco);
  font-size: .92rem; line-height: 1.45;
}

/* ---- prateleira: o que o grupo mandou, com foto e corte de preço ---- */
.grupo-vitrine { position: relative; z-index: 1; }
.grupo-vitrine__rotulo {
  margin: 0 0 .4rem; font-size: .74rem; font-weight: 800;
  letter-spacing: .04em; text-transform: uppercase; color: var(--texto-fraco);
}
/* Três colunas fixas, não auto-fit: com um ou dois achados, auto-fit
   esticaria a foto até virar um banner — e um produto esticado deixa de ser
   reconhecível, que é a única coisa que a prateleira precisa fazer. */
.grupo-vitrine__lista {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: .5rem;
}
.grupo-vitrine__lista--dupla { grid-template-columns: repeat(2, 1fr); }
.grupo-vitrine__item { min-width: 0; display: flex; flex-direction: column; gap: .3rem; }
.grupo-vitrine__foto {
  position: relative; display: block; aspect-ratio: 1 / 1;
  border-radius: 12px; overflow: hidden;
  background: var(--superficie-2); border: 1px solid var(--borda);
}
.grupo-vitrine__foto img { width: 100%; height: 100%; object-fit: contain; display: block; padding: .25rem; }
/* O selo de desconto é o único elemento da página em vermelho pleno: é o
   número que faz alguém parar de rolar, e ele só aparece onde há um preço
   antigo e um novo logo abaixo, checáveis. */
.grupo-vitrine__off {
  position: absolute; left: .3rem; top: .3rem;
  padding: .16rem .38rem; border-radius: 8px;
  background: var(--vermelho); color: #fff;
  font-size: .72rem; font-weight: 800; letter-spacing: -.02em;
  box-shadow: 0 2px 6px -2px rgba(12, 27, 23, .5);
}
.grupo-vitrine__preco {
  display: flex; flex-direction: column; line-height: 1.15;
  font-size: .78rem;
}
.grupo-vitrine__de { color: var(--texto-fraco); text-decoration: line-through; font-size: .7rem; }
/* Marca da loja no ladrilho. Herda --loja-* da PRÓPRIA loja da oferta (o
   style inline no elemento), não a cor do canal que pinta o card em volta —
   é a Shopee ou o Mercado Livre que precisa ficar reconhecível aqui. */
.grupo-vitrine__loja {
  display: inline-flex; align-items: center; gap: .22rem; max-width: 100%;
  margin-top: .1rem;
  font-size: .66rem; font-weight: 700; color: var(--texto-fraco);
}
.grupo-vitrine__loja .marca-loja { --h: 14px; border-radius: 4px; }
.grupo-vitrine__loja .marca-loja--mono { font-size: .42rem; }
.grupo-vitrine__loja-nome { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grupo-vitrine__preco strong { font-size: .88rem; font-weight: 800; letter-spacing: -.02em; }

/* ---- os dois botões: o motivo da página existir ---- */
.grupo-card__acoes {
  position: relative; z-index: 1;
  display: grid; gap: .5rem; margin-top: auto; padding-top: .15rem;
}

/* Botão por destino (Telegram/WhatsApp) — cor da marca do app, não da loja:
   é o convite pra SAIR do site que precisa ficar reconhecível de relance,
   reaproveitado no cabeçalho da categoria e nos popups abaixo. */
.btn-grupo {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .6rem 1rem; border-radius: 10px;
  font-weight: 700; font-size: .92rem; text-decoration: none;
  transition: background .15s, transform .15s;
}
.btn-grupo--telegram { background: #29a9eb; color: #fff; }
.btn-grupo--telegram:hover { background: #1c8fcc; }
.btn-grupo--whatsapp { background: #25d366; color: #ffffff; }
.btn-grupo--whatsapp:hover { background: #1eb958; }
.btn-grupo:active { transform: translateY(1px); }
.btn-grupo--sm { padding: .42rem .8rem; font-size: .82rem; border-radius: 8px; }
.btn-grupo__icone { width: 1.1em; height: 1.1em; flex-shrink: 0; }
/* Variante da página de convite: largura cheia e 50px de altura — alvo de
   polegar de verdade (a recomendação de 48px pra toque), não um link que
   por acaso tem fundo colorido. */
.btn-grupo--bloco {
  justify-content: center; width: 100%;
  min-height: 50px; padding: .8rem 1rem; border-radius: 12px;
  font-size: 1rem; letter-spacing: -.01em;
  box-shadow: 0 8px 16px -12px rgba(12, 27, 23, .6);
}
.btn-grupo--bloco .btn-grupo__icone { width: 1.2em; height: 1.2em; }

.grupo-card__rodape {
  position: relative; z-index: 1; margin: 0;
  display: flex; align-items: baseline; justify-content: space-between; gap: .5rem;
  font-size: .78rem; color: var(--texto-fraco);
}
.grupo-card__rodape-forte { font-weight: 700; color: var(--texto); }
.grupo-card__ver { color: var(--loja-tinta); font-weight: 700; text-decoration: none; white-space: nowrap; }
.grupo-card__ver:hover { text-decoration: underline; }

/* ---- fecho: mecanismo + dúvidas ---- */
.grupos-final { margin-top: 2.2rem; }
.grupos-passos {
  list-style: none; margin: 0 0 .5rem; padding: 0;
  display: grid; gap: .7rem;
}
@media (min-width: 760px) {
  .grupos-passos { grid-template-columns: repeat(3, 1fr); gap: .9rem; }
}
.grupos-passos li {
  position: relative; margin: 0;
  background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--raio);
  padding: .95rem 1rem .95rem 3rem;
  font-size: .9rem; color: var(--texto-fraco); line-height: 1.45;
  box-shadow: var(--sombra);
}
.grupos-passos li strong { display: block; color: var(--texto); font-size: .95rem; margin-bottom: .15rem; }
.grupos-passos__num {
  position: absolute; left: .95rem; top: .95rem;
  width: 1.6rem; height: 1.6rem; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--verde-luz); color: var(--verde-escuro);
  font-family: var(--fonte-display); font-weight: 800; font-size: .9rem;
}

.grupos-duvidas { margin: 0; display: grid; gap: .55rem; }
@media (min-width: 760px) { .grupos-duvidas { grid-template-columns: repeat(2, 1fr); gap: .7rem; } }
.grupos-duvidas > div {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: .85rem 1rem; box-shadow: var(--sombra);
}
.grupos-duvidas dt { font-weight: 800; font-size: .93rem; margin-bottom: .2rem; }
.grupos-duvidas dd { margin: 0; font-size: .87rem; color: var(--texto-fraco); line-height: 1.45; }

/* Convite repetido no pé. Cartão pintado (não mais um card branco): depois
   de quatro caixas brancas de dúvida, outra caixa branca não seria lida como
   "aqui tem uma escolha pra fazer". */
.grupos-fecho {
  margin-top: 1.6rem; padding: 1.2rem 1.1rem;
  border-radius: var(--raio);
  background: linear-gradient(120deg, var(--loja-tinta), var(--loja-cor) 70%);
  box-shadow: 0 16px 32px -20px color-mix(in srgb, var(--loja-tinta) 70%, transparent);
  text-align: center;
}
.grupos-fecho__titulo {
  margin: 0; color: #fff; font-family: var(--fonte-display);
  font-size: 1.15rem; font-weight: 800; letter-spacing: -.02em; text-wrap: balance;
}
.grupos-fecho__texto { margin: .3rem 0 .9rem; color: rgba(255, 255, 255, .88); font-size: .88rem; }
.grupos-fecho__acoes { display: grid; gap: .5rem; }
/* Mesma troca do .convite-canal, pelo mesmo motivo: o cartão do fecho é
   pintado na cor do canal, e verde-sobre-verde não tem contraste nenhum.
   A marca continua reconhecível pelo ícone e pela cor do texto. */
.grupos-fecho .btn-grupo { background: #fff; box-shadow: 0 2px 0 rgba(8, 20, 16, .12); }
.grupos-fecho .btn-grupo--whatsapp { color: #0f8a45; }
.grupos-fecho .btn-grupo--telegram { color: #1c8fcc; }
.grupos-fecho .btn-grupo:hover { transform: translateY(-2px); box-shadow: 0 6px 12px -4px rgba(8, 20, 16, .35); }
.grupos-fecho .btn-grupo:active { transform: translateY(0); }
@media (min-width: 560px) {
  .grupos-fecho { padding: 1.5rem; }
  .grupos-fecho__acoes { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); justify-content: center; max-width: 520px; margin: 0 auto; }
}

/* ============ cabeçalho da categoria — canal vinculado (Q13) ============
   Só existe quando Repo\DeliveryChannel::channelForCategory() acha algo.
   `.loja-topo` já é flex-wrap, então flex-basis:100% empurra isto pra uma
   faixa própria abaixo dos números.

   Um cartão de verdade, não uma linha de texto: gradiente na PRÓPRIA cor da
   categoria (--loja-cor/--loja-tinta, já setadas pelo <header> via
   Html::storeStyle — nasce combinando com qualquer categoria, sem cor fixa
   pra brigar com a caixa pastel ao redor), selo do emoji com anel pulsando,
   e um brilho diagonal que varre devagar — o mesmo tipo de detalhe que faz
   um botão de CTA parecer vivo em vez de só mais um bloco de texto. */
.convite-canal {
  flex-basis: 100%; position: relative; overflow: hidden; isolation: isolate;
  display: flex; align-items: center; flex-wrap: wrap; gap: .9rem;
  margin-top: .9rem; padding: 1.1rem 1.3rem;
  border-radius: 16px;
  background: linear-gradient(120deg, var(--loja-tinta), var(--loja-cor) 65%);
  box-shadow: 0 14px 28px -16px color-mix(in srgb, var(--loja-tinta) 70%, transparent);
}
.convite-canal__brilho {
  position: absolute; inset: 0; pointer-events: none; z-index: 0;
  background: linear-gradient(115deg, transparent 35%, rgba(255,255,255,.32) 48%, transparent 60%);
  background-size: 220% 100%; background-position: 140% 0;
  animation: convite-brilho-varre 5s ease-in-out infinite;
}
@keyframes convite-brilho-varre {
  0%, 45%  { background-position: 140% 0; }
  100%     { background-position: -40% 0; }
}
@media (prefers-reduced-motion: reduce) { .convite-canal__brilho { animation: none; } }

.convite-canal__aro {
  position: relative; z-index: 1; flex-shrink: 0;
  width: 2.7rem; height: 2.7rem; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, .16);
  box-shadow: 0 0 0 0 rgba(255, 255, 255, .45);
  animation: convite-aro-pulsa 2.6s ease-out infinite;
}
@keyframes convite-aro-pulsa {
  70%  { box-shadow: 0 0 0 9px rgba(255, 255, 255, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
}
@media (prefers-reduced-motion: reduce) { .convite-canal__aro { animation: none; } }
.convite-canal__emoji { font-size: 1.4rem; line-height: 1; }

.convite-canal__titulo {
  position: relative; z-index: 1; flex: 1 1 200px; min-width: 0; margin: 0;
  color: #fff; font-family: var(--fonte-display); font-weight: 800;
  font-size: 1.02rem; letter-spacing: -.01em; line-height: 1.3;
  text-wrap: balance;
}

.convite-canal__botoes { position: relative; z-index: 1; display: flex; flex-wrap: wrap; gap: .6rem; }
/* Dentro do cartão colorido, o botão vira pílula clara — verde-sobre-verde
   ou azul-sobre-cor-da-categoria não dá contraste nenhum. A marca continua
   reconhecível pelo ícone + pela cor do texto, só que legível agora. */
.convite-canal .btn-grupo {
  background: #fff; box-shadow: 0 2px 0 rgba(8, 20, 16, .1);
  transition: background .15s, transform .15s, box-shadow .15s;
}
.convite-canal .btn-grupo--whatsapp { color: #0f8a45; }
.convite-canal .btn-grupo--telegram { color: #1c8fcc; }
.convite-canal .btn-grupo:hover { transform: translateY(-2px); box-shadow: 0 5px 10px -3px rgba(8, 20, 16, .28); }
.convite-canal .btn-grupo:active { transform: translateY(0); }

@media (max-width: 480px) {
  .convite-canal { padding: 1rem; }
  .convite-canal__titulo { flex-basis: 100%; }
  .convite-canal__botoes { flex-basis: 100%; }
}

/* ============ convite de grupo (popup) ============
   Dois formatos pela origem da sessão (ver public/assets/app.js): banner de
   rodapé sem overlay na primeira página (o que o Google aceita — só "small
   fraction of the screen", nunca cobre o conteúdo) e modal na navegação
   interna, onde a pessoa não acabou de chegar da busca.

   Os dois usam --loja-cor/--loja-tinta/--loja-chip-texto/--loja-suave —
   aplicadas em JS (aplicarAcento()) a partir de Repo\DeliveryChannel::
   publicChannels()['accent_color'], a MESMA cor do card em /grupos-de-
   -promocoes/ e do cabeçalho da categoria. Um convite sobre "Eletrônicos"
   chega roxo em qualquer um dos três lugares — nunca cor aleatória. */

.convite-banner {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  padding: .8rem 1.1rem; padding-bottom: calc(.8rem + env(safe-area-inset-bottom, 0px));
  background: var(--superficie);
  border-top: 3px solid var(--loja-cor);
  box-shadow: 0 -10px 28px rgba(12, 27, 23, .14);
  transform: translateY(100%); transition: transform .28s cubic-bezier(.2, .8, .3, 1);
}
.convite-banner[hidden] { display: none; }
.convite-banner--aberto { transform: translateY(0); }
/* A barra (.convite-banner) fica full-bleed de propósito — a faixa colorida
   do topo precisa ir de ponta a ponta. O CONTEÚDO não: sem isto, numa tela
   larga o emoji cola na esquerda e os botões na direita com um vão vazio
   enorme no meio. Mesma largura máxima do resto do site (ver .wrap). */
.convite-banner__miolo {
  width: min(1060px, 100%); margin-inline: auto;
  display: flex; align-items: center; gap: .9rem;
}
.convite-banner__aro {
  flex-shrink: 0; width: 2.6rem; height: 2.6rem; border-radius: 50%;
  display: grid; place-items: center; background: var(--loja-suave);
}
.convite-banner__emoji { font-size: 1.35rem; line-height: 1; }
.convite-banner__corpo { flex: 1; min-width: 0; }
.convite-banner__titulo { margin: 0; font-family: var(--fonte-display); font-weight: 800; font-size: 1rem; }
/* Some no celular de propósito — card compacto (emoji + título + botão) fica
   fora de qualquer leitura de "cobre o conteúdo", sem precisar de um número
   de altura em px que ninguém publicou. */
.convite-banner__desc { margin: .1rem 0 0; font-size: .82rem; color: var(--texto-fraco); display: none; }
.convite-banner__acoes { display: flex; align-items: center; gap: .5rem; flex-shrink: 0; }
.convite-banner__fechar {
  background: none; border: 0; color: var(--texto-fraco); cursor: pointer;
  font-size: 1.3rem; line-height: 1; padding: .2rem .4rem;
}
@media (min-width: 640px) {
  .convite-banner__desc { display: block; }
}

.convite-modal { position: fixed; inset: 0; z-index: 50; display: grid; place-items: center; padding: 1rem; }
.convite-modal[hidden] { display: none; }
.convite-modal__fundo {
  position: absolute; inset: 0; background: rgba(8, 20, 16, .6);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.convite-modal__caixa {
  position: relative;
  width: min(400px, 100%);
  background: var(--superficie); border-radius: 24px;
  padding: 2.1rem 1.7rem 1.6rem; text-align: center;
  box-shadow: 0 30px 70px rgba(8, 20, 16, .4);
  animation: sobe .25s cubic-bezier(.2, 1.2, .4, 1);
}
@media (prefers-reduced-motion: reduce) { .convite-modal__caixa { animation: none; } }

/* Halo: um borrão colorido vazando por cima do card, atrás do selo do
   emoji — a mesma ideia de "personalidade" que o brilho-varre do cabeçalho
   da categoria, só que parado (um modal não precisa de movimento contínuo
   pra sentir vivo, ele já é o centro da atenção sozinho). */
.convite-modal__halo {
  position: absolute; top: -90px; left: 50%; translate: -50% 0;
  width: 260px; height: 260px; border-radius: 50%; pointer-events: none;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--loja-cor) 30%, transparent), transparent);
  filter: blur(14px);
}
.convite-modal__x {
  position: absolute; top: .6rem; right: .75rem; z-index: 1;
  background: var(--superficie); border: 1px solid var(--borda); border-radius: 50%;
  width: 2rem; height: 2rem; display: grid; place-items: center;
  font-size: 1.3rem; line-height: 1; cursor: pointer; color: var(--texto-fraco);
}
.convite-modal__aro {
  position: relative; z-index: 1; margin: 0 auto .9rem;
  width: 4.4rem; height: 4.4rem; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--loja-suave);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--loja-cor) 45%, transparent);
  animation: convite-aro-pulsa 2.4s ease-out infinite;
}
@keyframes convite-aro-pulsa {
  70%  { box-shadow: 0 0 0 12px color-mix(in srgb, var(--loja-cor) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--loja-cor) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .convite-modal__aro { animation: none; } }
.convite-modal__emoji { font-size: 2.1rem; line-height: 1; }
.convite-modal__titulo {
  position: relative; z-index: 1; margin: 0 0 .4rem; color: var(--texto);
  font-family: var(--fonte-display); font-weight: 800;
  font-size: 1.3rem; letter-spacing: -.01em; line-height: 1.25;
}
.convite-modal__desc {
  position: relative; z-index: 1; margin: 0 0 1rem;
  color: var(--texto-fraco); font-size: .92rem; line-height: 1.4;
}
.convite-modal__selos {
  position: relative; z-index: 1; display: flex; flex-direction: column; gap: .4rem;
  margin: 0 0 1.3rem;
}
.convite-modal__selo {
  font-size: .78rem; font-weight: 650; color: var(--loja-tinta);
  background: var(--loja-suave); border-radius: 999px; padding: .4rem .8rem;
}
.convite-modal__acoes { position: relative; z-index: 1; display: flex; flex-direction: column; gap: .6rem; }

/* --lg: o mesmo botão, só que o CTA principal do modal — tamanho de botão
   de hero, largura cheia, texto maior. O banner continua com o --sm/normal,
   ele tem menos espaço e é o formato menos assertivo dos dois de propósito. */
.btn-grupo--lg, .btn--lg {
  width: 100%; justify-content: center; padding: .85rem 1.2rem; font-size: 1rem; border-radius: 12px;
  box-shadow: 0 3px 0 rgba(0, 0, 0, .15);
}
.btn-grupo--lg:active, .btn--lg:active { transform: translateY(2px); box-shadow: 0 0 0 rgba(0,0,0,.15); }
.btn-grupo--lg .btn-grupo__icone { width: 1.25em; height: 1.25em; }
