/* ==============================================================================
   ARQUIVO: VITRINE_DE_LOJA.CSS
   OBJETIVO: ESTILOS EXCLUSIVOS DA TELA PRINCIPAL (PRODUTOS E CABEÇALHO)
============================================================================== */

/* A trava de vazamento horizontal vinha do antigo base.css, que era carregado
   aqui. Ela desceu para o CSS da própria vitrine em vez de subir para a fundação
   porque `overflow` num ancestral quebra o `position: sticky` dos descendentes —
   e a área de membros, que passou a carregar a fundação, depende de sticky.
   Aqui a vitrine já convive com as duas coisas desde sempre. */
body {
	overflow-x: hidden;
}

/* ==============================================================================
   CABEÇALHO FIXO (PREPARADO PARA ANIMAÇÃO DE ROLAGEM)
============================================================================== */
.bloco_de_cabecalho_fixo {
	position: sticky; /* Mantém a sua pílula flutuante original */
	top: 0;
	z-index: 100;

	/* Prepara a descida e subida */
	transition: transform 0.4s cubic-bezier(0.25, 1, 0.5, 1);
}

/* Nova classe com semântica limpa para o gatilho de esconder o topo

   O DESLOCAMENTO PRECISA CONTAR O TRANSBORDO DO LOGOTIPO. Os -120% valiam quando
   tudo cabia dentro da barra: um pouco mais que a altura dela bastava para tirar
   o cabeçalho de cena. Com o logo descendo metade da própria altura para fora,
   a porcentagem sozinha deixava justamente esse pedaço à mostra — o cabeçalho
   sumia e o logotipo ficava pendurado no alto da tela, sem barra nenhuma.

   O `calc` resolve somando um valor fixo à altura: cem por cento tira a barra, e
   os 70px levam o transbordo junto, com folga para a sombra. */
.cabecalho_escondido_por_rolagem {
	transform: translateY(calc(-100% - 70px));
}

/* ==============================================================================
   CABEÇALHO DE LOJA (AS 3 RAIAS INDEPENDENTES)
============================================================================== */
.cabecalho_de_loja {
	min-height: 25px;
	background-color: var(--cor_de_superficie);
	color: var(--cor_de_texto_principal);
	padding: 15px 20px;

	/* A MÁGICA DA BALANÇA: 3 colunas (Esquerda, Centro exato, Direita) */
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;

	position: relative;
	z-index: 10;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);

	backdrop-filter: blur(70px);
	-webkit-backdrop-filter: blur(5px);
}

/* Nome da loja cravado no centro absoluto da grade */
.titulo_de_cabecalho {
	margin: 0;
	font-size: 22px;
	color: var(--cor_de_texto_principal);
	text-align: center;
	white-space: nowrap;
	justify-self: center; /* Garante que fique no meio da coluna central */
}

/* ==============================================================================
   O LOGOTIPO TRANSBORDA A BARRA DO CABEÇALHO

   O logotipo desta marca é EMPILHADO — "NUTS" em cima, "DA ILHA" embaixo, quase
   um quadrado. Um cabeçalho é o oposto disso: uma faixa baixa e larga. Coubesse
   dentro dela, o logo teria uns 70px de largura e a segunda linha ficaria com
   letras de poucos pixels; para ter a presença que o texto tinha, precisaria de
   mais altura do que a barra inteira.

   ENTÃO ELE NÃO CABE — ELE ATRAVESSA. Metade fica na barra, metade desce sobre a
   capa, como um selo aplicado por cima. O logo ganha o tamanho de que precisa
   sem que o cabeçalho engorde, e o transbordo vira assinatura visual em vez de
   acidente.

   COMO A BARRA NÃO ENGORDA: a margem inferior negativa vale exatamente metade da
   altura da imagem. Para o cálculo do layout, a caixa do logo mede só a metade
   de cima — é essa metade que ocupa lugar na linha do cabeçalho; a de baixo
   existe apenas para os olhos. Nada aqui usa posicionamento absoluto, então o
   logo continua centralizado pela mesma coluna do meio da grade que centralizava
   o texto.

   A SOMBRA NÃO É ENFEITE. O cabeçalho da vitrine é transparente e a capa é um
   pôr do sol dourado; o logotipo também é dourado. Sem a sombra escura por trás,
   ele desaparece justamente na tela em que mais aparece. É o mesmo motivo pelo
   qual o título de antes era azul-escuro, e não da cor da marca.
============================================================================== */
.logotipo_de_cabecalho_de_loja {
	height: 104px;
	margin-bottom: -52px;

	/* Levanta o logo dos 15px de recheio do cabeçalho, para o transbordo começar
	   rente à borda de baixo da barra em vez de nascer no meio dela. */
	margin-top: -8px;

	/* DUAS SOMBRAS, COM PAPÉIS DIFERENTES. A primeira é curta e quase opaca, e
	   funciona como contorno: ela desenha a borda do logo contra o que estiver
	   atrás, e é o que salva o dourado sobre o céu dourado. A segunda é larga e
	   difusa, e afasta o logo do fundo dando a ele a aparência de selo aplicado
	   por cima. Uma sombra só teria de escolher entre os dois papéis, e faria
	   qualquer um dos dois pela metade. */
	filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.75))
		drop-shadow(0 4px 12px rgba(0, 0, 0, 0.45));

	/* Ele desce por cima da capa, e a capa não pode passar por cima dele. */
	position: relative;
	z-index: 2;
}

/* Em tela estreita a barra é mais curta e a capa começa mais cedo: o logo
   encolhe junto, mantendo a mesma proporção de metade dentro, metade fora. */
@media (max-width: 767px) {
	.logotipo_de_cabecalho_de_loja {
		height: 84px;
		margin-bottom: -42px;
	}
}

/* Botao de menu hamburguer na extrema esquerda (AGORA LIVRE DO CABEÇALHO) */
.bloquinho_de_menu_cabecalho {
	position: fixed;
	top: 15px;
	left: 20px;
	z-index: 10006; /* Flutua acima do cabeçalho */
	background: transparent;
	border: none;
	cursor: pointer;
	padding: 8px;
	display: flex;
	align-items: center;
	justify-content: center;

	/* 🚨 MÁGICA 1: Mantém a memória da borda para não ficar quadrado no caminho de volta */
	border-radius: 14px;

	/* PREPARAÇÃO PARA A FASE 1 (A Mola do Zoom Out) */
	opacity: 1;
	transform: scale(1);
	transform-origin: center;

	/* 🚨 MÁGICA 2: Trocamos para "all" para ele suavizar o fundo branco e a sombra sumindo! */
	transition: all 0.4s cubic-bezier(0.25, 1, 0.5, 1);
}

/* --- COMPORTAMENTO DA BARRA DO TOPO (EXTREMA DIREITA) --- */
.menu_de_navegacao {
	display: flex;
	align-items: center;
	gap: 20px;
	justify-self: end; /* Joga todo o bloco para o final da 3ª coluna */
}

/* Links do menu em cor escura */
.menu_de_navegacao a {
	color: var(--cor_de_texto_sobre_cor);
	text-decoration: none;
	font-weight: bold;
	cursor: pointer;
}

.menu_de_navegacao a:hover {
	color: var(--cor_de_atencao);
}

/* --- COMPORTAMENTO DA BARRA DO TOPO (DESKTOP) --- */
/* A redeclaração de `.menu_de_navegacao` que abria esta seção pedia `display:
   flex` e `align-items: center` — as duas já declaradas vinte linhas acima, com
   os mesmos valores. Removida em 2026-08-07; o título da seção fica, porque o que
   vem abaixo dele é de fato o comportamento da barra em tela larga. */

/* Prepara CADA ITEM para animar do seu próprio centro geométrico */
.menu_de_navegacao > a,
.menu_de_navegacao > .bloco_de_carrinho_em_cabecalho {
	opacity: 1;
	transform: scale(1);
	transform-origin: center; /* Mágica: O zoom out acontece no próprio eixo do item! */
	transition:
		transform 0.4s cubic-bezier(0.25, 1, 0.5, 1),
		opacity 0.3s ease;
}

.bloco_de_carrinho_em_cabecalho {
	display: flex;
	align-items: center;
	background-color: #1a252f;
	padding: 8px 15px;
	border-radius: 8px;
	cursor: pointer;
	transition: background 0.3s;
}

.bloco_de_carrinho_em_cabecalho:hover {
	background-color: #0f161c;
}

.informacao_de_carrinho {
	display: flex;
	flex-direction: column;
	font-size: 14px;
	font-weight: bold;
}

/* ==========================================================================
   O CONTADOR DE ITENS, NAS DUAS TELAS

   O bloco tem fundo quase preto (#1a252f) dentro de um cabeçalho branco, e o
   "0 itens" não pedia cor nenhuma — herdava a do cabeçalho, que é o azul-escuro
   de texto principal. Azul-escuro sobre quase-preto: a linha existia e quase não
   se lia, justamente a que diz quantas coisas o cliente já escolheu.

   O cinza claro é o mesmo que a pílula de tela estreita já usava — de onde ele
   veio, aliás: estava escrito à mão num `style` inline lá no HTML, e agora as
   duas telas leem a mesma regra. A hierarquia fica igual nos dois tamanhos:
   cinza discreto para a contagem, laranja para o valor.
   ========================================================================== */
.contador_de_itens_global {
	color: var(--cor_de_borda_de_campo);
}

.informacao_de_carrinho span:nth-child(2) {
	color: var(--cor_de_atencao);
	margin-top: 2px;
	transition: color 0.3s ease;
}

.informacao_de_carrinho span.celebracao_de_adicao {
	color: #2ecc71 !important;
}

/* --- 2. BARRA DE PESQUISA (PÍLULA FLUTUANTE) --- */
.bloco_de_pesquisa {
	width: 100%;
	padding: 40px 20px 5px 20px; /* Respiro elegante entre o cartaz e a barra */
	background-color: transparent;
	box-sizing: border-box;
	pointer-events: auto; /* MÁGICA: Devolve o poder de clique para o contêiner! */
	position: relative;
	z-index: 50; /* Fica num nível seguro, abaixo dos menus flutuantes */
}

.recipiente_do_campo_de_pesquisa {
	position: relative;
	width: 100%;
	max-width: 600px;
	margin: 0 auto;
	pointer-events: auto;

	/* MÁGICA: Coloca o campo e o botão perfeitamente lado a lado */
	display: flex;
	align-items: center;
	gap: 12px; /* O respiro perfeito entre a barra e o bloquinho */
}

/* O Campo de Busca cede espaço para o botão */
#campo_de_busca_de_vitrine {
	flex: 1; /* Pega todo o espaço que sobrar */
	width: 100%;
	padding: 12px 20px 12px 45px;
	font-size: 16px;
	border: 1px solid var(--cor_de_borda_suave);
	border-radius: 25px;
	outline: none;
	background-color: var(--cor_de_superficie);
	color: var(--cor_de_texto_principal);
	box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08); /* Sombra elegante que destaca a pílula */
	transition: all 0.3s ease;
	box-sizing: border-box;
}

#campo_de_busca_de_vitrine:focus {
	border-color: var(--cor_de_conversao);
	box-shadow: 0 6px 20px rgba(39, 174, 96, 0.25); /* Brilho forte ao focar */
}

/* O NOVO BLOQUINHO DE FILTROS COM CANTOS ARREDONDADOS */
#botao_de_filtros_de_pesquisa {
	flex-shrink: 0; /* Impede que o navegador esmague o botão */
	width: 48px;
	height: 48px;
	background-color: var(--cor_de_superficie);
	border: 1px solid var(--cor_de_borda_suave);
	border-radius: 14px; /* O cantinho arredondado perfeito! */
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
	transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
	color: var(--cor_de_texto_principal);
}

#botao_de_filtros_de_pesquisa:active {
	transform: scale(0.92); /* Efeito de clique físico Apple */
}

/* Com o painel aberto, o fogãozinho vira X — o botão passa a anunciar o fechamento.
   A troca depende da classe no GRUPO, não na seção de pílulas: a classe de aberto
   mora na seção, que é irmã posterior da barra de pesquisa, e o CSS não seleciona
   para trás. O JavaScript marca o grupo, que é o ancestral comum dos dois. */
.icone_de_filtros_de_pesquisa,
.icone_de_fechar_filtros {
	font-size: 16px;
	line-height: 1;
}

.icone_de_fechar_filtros {
	display: none;
}

.grupo_com_painel_de_categorias_aberto .icone_de_filtros_de_pesquisa {
	display: none;
}

.grupo_com_painel_de_categorias_aberto .icone_de_fechar_filtros {
	display: inline;
}

/* Oculta o botão de filtros no computador (A mágica vai acontecer na trilha de categorias) */
@media (min-width: 769px) {
	#botao_de_filtros_de_pesquisa {
		display: none !important;
	}
}

/* No celular ele também não nasce à mostra: na posição padrão, encaixada abaixo do
   cartaz, a trilha de categorias já está logo ali embaixo, e o bloquinho seria um
   segundo caminho para a mesma coisa. Ele só entra quando a lupa convoca a barra,
   que é quando o acesso rápido aos filtros ao lado do campo passa a valer. */
@media (max-width: 768px) {
	#botao_de_filtros_de_pesquisa {
		display: none;
	}

	/* Continua à mostra durante o recolhimento para não sumir antes da barra,
	   o que daria um salto no meio da animação de saída. */
	.grupo_de_busca_convocado #botao_de_filtros_de_pesquisa,
	.grupo_de_busca_recolhendo #botao_de_filtros_de_pesquisa {
		display: flex;
	}

	/* E o contrário para a trilha: com a barra convocada, quem dá acesso às
	   categorias é o bloquinho ao lado do campo, então a trilha não desce junto.
	   Assim a barra convocada ocupa pouco da tela e não existem dois caminhos
	   para o mesmo filtro ao mesmo tempo. Segue escondida durante o recolhimento
	   para não reaparecer no meio da subida. */
	.grupo_de_busca_convocado .secao_de_pilulas_de_categorias,
	.grupo_de_busca_recolhendo .secao_de_pilulas_de_categorias {
		display: none;
	}
}

.icone_de_lupa {
	position: absolute;
	left: 18px;
	top: 50%;
	transform: translateY(-50%);
	font-size: 16px;
	color: var(--cor_de_texto_suave);
	pointer-events: none; /* A lupa não bloqueia o cursor de digitação */
}

/* O campo de busca e o `:focus` dele eram declarados AQUI e cem linhas acima, com
   os mesmos valores — esta cópia não acrescentava nada, e a de cima ainda trazia
   o `flex: 1` que faz o campo ceder espaço ao botão de filtros. Removida em
   2026-08-07; os comentários que viviam nela foram junto para a que ficou. */

/* ==========================================================================
   2. O EFEITO PINTEREST (Alvenaria / Masonry)

   ATÉ 2026-08-10 ISTO ERA `column-count`, E O DEFEITO ERA A ORDEM DE LEITURA
   (item 1.11). Multi-coluna preenche COLUNA POR COLUNA, por definição: em tela
   larga o cliente descia a primeira coluna inteira antes de chegar ao segundo
   produto da lista. Ou seja, a ordenação inteligente de dezoito níveis decidia
   uma ordem que a tela não mostrava — o produto que o motor pôs em segundo
   lugar aparecia no meio da coluna da esquerda, quinze cartões abaixo.
   Não era defeito de cálculo nosso; é o que a propriedade faz.

   AGORA É GRID COM LINHAS DE 1 PIXEL, e cada tijolo declara quantas linhas
   ocupa (`grid-row-end: span N`, escrito pelo JavaScript em
   `vitrine-alvenaria.js`). O grid preenche LINHA POR LINHA, então a ordem de
   leitura passa a ser a ordem do DOM; e como cada tijolo reserva exatamente a
   altura que tem, o empacotamento da alvenaria fica de pé. É a saída (b) do
   item 1.11, feita com grid em vez de posicionamento absoluto — sem biblioteca
   de masonry, sem tirar os cartões do fluxo.

   POR QUE `row-gap: 0`. O respiro vertical entre tijolos continua sendo o
   `margin-bottom: 15px` de cada um, que já existia. Somar um `row-gap` aqui
   daria trinta pixels entre as linhas e quinze na horizontal, e o ritmo da
   grade deixaria de ser um só. A margem entra na conta do span, então o
   JavaScript reserva altura + margem.

   O SPAN DE PARTIDA (420) É UM CHUTE PROPOSITAL. Entre a página desenhar e o
   JavaScript medir há um quadro em que todo tijolo valeria uma linha de 1px, e
   os cinquenta cartões se empilhariam num monte de um pixel no topo. Quatrocentos
   e vinte é a altura aproximada de um cartão de produto: a primeira pintura já
   sai parecida com o resultado, e a medição corrige em seguida.
   ========================================================================== */
.recipiente_de_vitrine {
	max-width: 1200px;
	margin: 30px auto;
	padding: 0 15px;

	/* ------------------------------------------------------------------
	   A QUANTIDADE DE COLUNAS É UMA VARIÁVEL, E ESSE É O ÚNICO LUGAR ONDE
	   ELA É ESCRITA.

	   Ela serve a dois leitores: o `repeat()` logo abaixo, e o JavaScript da
	   alvenaria, que precisa saber quantas colunas existem para não deixar um
	   bloco de `quantidade_de_espaco_ocupado = 3` pedir três colunas numa grade
	   de duas.

	   POR QUE NÃO PERGUNTAR AO GRID. A primeira versão lia
	   `getComputedStyle(grade).gridTemplateColumns` e contava os pedaços, para
	   não repetir os pontos de quebra no JavaScript. Parecia a escolha certa e
	   era medida errada: O CHROME INCLUI AS COLUNAS IMPLÍCITAS NAQUELE VALOR.
	   Com duas colunas declaradas e um bloco pedindo `span 3`, ele responde três
	   — ou seja, o próprio item que se queria cortar inflava a régua usada para
	   cortá-lo, e o corte nunca acontecia. No celular a vitrine ganharia uma
	   terceira coluna espremida, e o defeito não apareceria em tela larga
	   nenhuma.

	   Com a variável, o número continua morando só no CSS (que é onde os pontos
	   de quebra vivem) e o JavaScript lê o que foi DECLARADO, e não o que o
	   layout acabou fazendo.
	   ------------------------------------------------------------------ */
	--quantidade_de_colunas_de_vitrine: 2;

	display: grid;
	/* A Mágica do Pinterest começa aqui: 2 colunas no celular! */
	grid-template-columns: repeat(var(--quantidade_de_colunas_de_vitrine), 1fr);
	column-gap: 15px;
	row-gap: 0;

	grid-auto-rows: 1px;
	align-items: start;
}

.recipiente_de_vitrine > * {
	grid-row-end: span 420;
}

/* Se for tablet ou computador, aumentamos as colunas suavemente */
@media (min-width: 768px) {
	.recipiente_de_vitrine {
		--quantidade_de_colunas_de_vitrine: 3;
	}
}
@media (min-width: 1024px) {
	.recipiente_de_vitrine {
		--quantidade_de_colunas_de_vitrine: 4;
	}
}

.cartao_de_produto {
	background-color: var(--cor_de_superficie);
	border-radius: var(--raio_de_canto_de_cartao);
	overflow: hidden;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
	display: flex;
	flex-direction: column;
	position: relative;

	/* AS TRÊS LINHAS DE `break-inside: avoid` SAÍRAM DAQUI EM 2026-08-10, com a
	   troca de `column-count` por grid (item 1.11). Elas impediam o cartão de ser
	   FATIADO entre o fim de uma coluna e o começo da seguinte — um risco que só
	   existe em layout multi-coluna, onde o conteúdo escorre. No grid cada tijolo
	   é uma célula, e não há corte a evitar: as três não faziam mais nada.
	   A nota fica para ninguém as devolver achando que estavam segurando algo. */

	margin-bottom: 15px;
	/* Espaço embaixo de cada tijolo — e, desde a troca para grid, o respiro
	   vertical da alvenaria inteira: o recipiente tem `row-gap: 0` e este número
	   entra na conta do span. Mudar aqui muda o ritmo da grade toda. */
}

/* ==========================================================================
   O CARTÃO "EM BREVE" (item 1.13, 2026-08-10)

   Duas portas levam a este estado, e o CSS não sabe qual foi — nem precisa: o
   produto marcado à mão no painel e o produto com estoque zerado em todas as
   variações visíveis pedem a mesma coisa ao cliente, que é olhar em vez de
   comprar. Quem separa as duas é a frase da etiqueta, escrita pelo PHP.

   O CINZA É NA FOTO, E NÃO NO CARTÃO INTEIRO. Um `filter: grayscale` no cartão
   apagaria junto o coração vermelho do favorito e a etiqueta azul de "em breve"
   — os dois elementos que precisam continuar sendo lidos ali. Aplicado só na
   imagem, o efeito é o de uma foto em preto e branco com uma legenda colorida em
   cima, que é exatamente a leitura desejada.

   A OPACIDADE É PARCIAL (0.55, e não 0.2). A intenção é anunciar, não esconder:
   uma foto que mal se vê não faz ninguém querer o produto quando ele voltar — e
   é justamente esse desejo que o cartão em breve existe para plantar.

   `cursor: pointer` NO CARTÃO INTEIRO. Ele deixou de ter botões e passou a ser
   um só: qualquer toque abre a janela de detalhes. Sem o cursor, a área parece
   morta em tela larga e ninguém descobre que ela responde.
   ========================================================================== */
.cartao_de_produto_em_breve {
	cursor: pointer;
}

.cartao_de_produto_em_breve .imagem_de_produto {
	filter: grayscale(1);
	opacity: 0.55;
}

/* ==========================================================================
   O BLOCO DE "EM BREVE" — O QUE OCUPA O LUGAR DOS PESOS E DO PREÇO

   A PRIMEIRA VERSÃO MANTINHA AS PÍLULAS NA TELA, inertes por `pointer-events`,
   com uma etiqueta pequena ao lado do nome e um "Toque para ver os detalhes" no
   rodapé. Três declarações foram apagadas daqui em 2026-08-10 junto com essa
   ideia — `.cartao_de_produto_em_breve .botao_de_selecao_de_peso`,
   `.etiqueta_de_em_breve_de_cartao` e `.aviso_de_cartao_em_breve` —, e a nota
   fica para a próxima pessoa não reintroduzi-las achando que faltavam.

   O QUE ESTAVA ERRADO ALI: as pílulas são o SELETOR de quanto se vai levar, e
   um seletor inerte é um convite ao toque que não responde. O preço é uma
   promessa de compra que aquele cartão não pode cumprir. E a instrução do rodapé
   ensinava um gesto que é o mesmo em todo cartão da vitrine.

   UMA LINHA OU DUAS, CONFORME O MOTIVO. O título em caixa alta, com espaçamento
   entre letras, é o que se lê de relance numa grade de cinquenta cartões. A
   segunda linha é CONDICIONAL e vem do PHP: "EM BREVE" não a tem, porque já é a
   promessa inteira; "ESGOTADO" tem, porque sozinho conta o fato e cala a
   promessa. O CSS não sabe qual das duas portas foi — ele só centraliza o que
   chegar, e por isso funciona igual com um filho ou com dois.

   `margin: auto 0` CONTINUA INERTE, E AGORA SABEMOS QUE VAI CONTINUAR.

   Esta linha foi escrita apostando que a troca da máquina de posicionar (item
   1.11) traria linhas de altura igual, e que aí a margem automática centralizaria
   o bloco no espaço que sobrasse. Em 2026-08-10 a troca aconteceu — e a aposta
   não se pagou, porque a saída escolhida foi a ALVENARIA por span de linha, e não
   o grid de linhas alinhadas. No span, o cartão continua tendo a altura do
   próprio conteúdo, exatamente como tinha no `column-count`.

   MEDIDO, e não suposto: nos três cartões em breve da vitrine local o
   `margin-top` resolvido é `0px`. Um `auto` só vira espaço quando há espaço
   sobrando, e num contêiner do tamanho do conteúdo nunca há.

   A LINHA FICA, e a razão não é inércia: ela é a expressão correta da intenção
   — "centralize no que sobrar" —, custa zero byte de processamento e passa a
   valer sozinha se um dia este cartão ganhar altura mínima. O que não podia ficar
   era o comentário antigo, que prometia um dia que já chegou e passou.

   SE O DESEJO FOR CENTRALIZAR DE VERDADE, o caminho não é este: é dar altura
   mínima ao `.cartao_de_produto_em_breve`, para o cartão ter espaço a distribuir.
   Isso é decisão de desenho, e não estava no item 1.11.

   O AZUL É O MESMO DA ETIQUETA E DA FAIXA DA JANELA, e vem escrito por extenso
   como eles: são os três pedaços do vocabulário de "em breve", e a cor mora nos
   três lugares até virar token — anunciar não é a mesma coisa que alertar, e
   nenhum token existente diz isso.
   ========================================================================== */
.bloco_de_em_breve_de_cartao {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 3px;

	margin: auto 0 25px 0;
	padding: 20px 12px;

	background-color: #eaf4fb;
	border-radius: var(--raio_de_canto_de_cartao);
	color: #2980b9;
}

.titulo_de_em_breve_de_cartao {
	font-size: 17px;
	font-weight: 700;
	letter-spacing: 0.08em;
	line-height: 1.1;
}

/* O corpo menor não é enfeite: é o que impede as duas linhas de disputarem a
   mesma atenção. Sem a diferença de tamanho, "EM BREVE por aqui" vira uma frase
   só quebrada no meio, e a leitura de relance se perde. */
.complemento_de_em_breve_de_cartao {
	font-size: 12px;
	line-height: 1.2;
	opacity: 0.85;
}

.imagem_de_produto {
	width: 100%;
	height: 160px;
	background-color: var(--cor_de_divisor);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 40px;
	cursor: pointer;
	position: relative;
}
/* ------------------------------------------------------------------------------
   AS RESTRIÇÕES DO PRODUTO (texto desde 2026-08-13)

   ⚠️ ISTO ERA UMA PÍLULA BRANCA COM EMOJI DENTRO, e a troca não foi estética: o
   ícone de "Sem Glúten" é 🌾, uma espiga de trigo, e uma espiga sobre um produto
   sem trigo lê ao contrário do que ela quer dizer.

   ⚠️ O ELEMENTO DEIXOU DE SER A PÍLULA E VIROU A PILHA. O fundo branco, o recheio
   e o canto arredondado desceram para `.etiqueta_de_restricao_de_cartao`, que é
   cada bloquinho — com texto, uma pílula só não teria onde ser cortada, e quem
   lesse não saberia se são duas restrições ou uma de nome comprido.

   ⚠️ E ELA CONTINUA SENDO A PRIMEIRA DO CANTO. A faixa de selos desce 48px quando
   este bloco existe (a regra de irmão, mais abaixo) — com a pilha, aquele valor
   passou a depender de QUANTAS restrições há, e por isso o desconto virou uma
   variável que este bloco declara para o irmão ler.
------------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------------
   A CAIXA QUE EMPILHA AS DUAS FAIXAS (2026-08-13)

   ⚠️ ELA NASCEU PARA MATAR UM NÚMERO MÁGICO. Enquanto as restrições eram um emoji,
   as duas faixas eram `position: absolute` no mesmo canto, e uma regra de irmão
   descia os selos 48px — a altura de uma pílula. Com texto empilhado, aquela
   altura passou a depender de QUANTAS restrições o produto tem, e 48px vira o
   valor certo só para o caso de uma.

   Aqui quem empilha é o `flex`: restrições primeiro, selos depois, e o vão entre
   os dois grupos é o `gap`. Acrescentar uma sexta restrição não pede uma linha de
   CSS.

   ⚠️ O `pointer-events: none` MORA AQUI, e não nas filhas. A foto inteira abre a
   janela de detalhes, e um bloquinho decorativo no caminho engoliria o gesto.
------------------------------------------------------------------------------ */
.canto_de_etiquetas_de_cartao {
	position: absolute;
	top: 10px;
	left: 10px;
	z-index: 5;

	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 8px;

	pointer-events: none;

	/* ⚠️ TETO DE LARGURA. "Rico em Proteínas" é o nome mais longo das cinco, e sem
	   o teto ele encostaria no coração, que fica no canto oposto. */
	max-width: 60%;
}

.etiquetas_visuais {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 4px;
}

/* Cada restrição é um bloquinho branco, com a mesma geometria dos selos logo
   abaixo — o cartão passa a ter um vocabulário só para "etiqueta sobre a foto".
   A sombra existe porque o bloquinho vive sobre uma FOTO, e não sobre um fundo
   conhecido: sem ela, um bloco branco sobre uma castanha clara some. */
.etiqueta_de_restricao_de_cartao {
	padding: 3px 8px;

	font-size: 11px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: 0.2px;

	background-color: var(--cor_de_superficie);
	color: var(--cor_de_texto_principal);
	border-radius: 999px;
	box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
}
.bloco_de_botao_flutuante {
	text-align: center;
	margin-top: -14px;
	position: relative;
	z-index: 10;
	height: 14px;
	margin-bottom: 15px;
}

.botao_de_detalhes {
	font-size: 10px;
	color: #34495e;
	background-color: #f1f2f6;
	border: 1px solid #dfe4ea;
	padding: 5px 12px;
	border-radius: 7px;
	cursor: pointer;
	font-weight: bold;
	text-transform: uppercase;
	box-shadow: var(--sombra_de_barra);
	transition: all 0.3s;
}

.detalhes_de_produto {
	padding: 0 12px 15px 12px;
	display: flex;
	flex-direction: column;
	text-align: center;
	flex-grow: 1;
}
.nome_de_produto {
	margin: 15px 0 20px 0;
	font-size: 15px;
	color: var(--cor_de_texto_principal);
	line-height: 1.2;
}

/* --- 3. BLOCO DE PESOS (Quebra de Linha e Centralizado) --- */
.recipiente_de_pista_de_pesos {
	display: flex;
	flex-wrap: wrap; /* A MÁGICA: Se não couber, joga para a linha de baixo */
	justify-content: center; /* Centraliza todos os botões perfeitamente */
	gap: 7px;
	margin-bottom: 25px; /* Um respiro um pouco maior embaixo */
}

/* OS TRÊS ESTADOS DA PÍLULA DE PESO, EM ESCALA DE INTENSIDADE
   1. Padrão: fundo branco com borda e texto verdes. Disponível, à espera.
   2. Com itens na sacola, mas não selecionada agora: verde suave preenchendo o
      fundo — ela lembra que há unidades ali sem competir com a seleção.
   3. Selecionada: verde cheio. É o estado mais forte porque responde ao dedo.
   A ordem das regras importa: a selecionada vem por último para vencer a de itens
   quando as duas valem ao mesmo tempo.

   O PADRÃO ERA CINZA, E CINZA MENTIA. Num cartão com cinco pesos, um verde e
   quatro cinzas, a leitura que sobrava era "um disponível e quatro esgotados" —
   e não "um escolhido e quatro que você também pode escolher". A escala acima
   diz a mesma coisa que o cinza dizia (não é este que está valendo) sem dizer a
   que não estava. É a mesma gramática do seletor de peso dentro do carrinho: o
   mesmo gesto, nas duas telas, com as mesmas cores. */
.botao_de_selecao_de_peso {
	position: relative; /* A âncora da bolinha de contagem */
	background-color: var(--cor_de_superficie);
	color: var(--cor_de_conversao);
	border: 1px solid var(--cor_de_conversao);
	border-radius: 5px;
	padding: 6px 10px;
	font-size: 12px;
	font-weight: bold;
	cursor: pointer;
	transition: all 0.3s ease;
}

.botao_de_selecao_de_peso.botao_de_peso_com_itens {
	background-color: var(--cor_de_conversao_clara);
	color: var(--cor_de_conversao);
	border-color: var(--cor_de_conversao);
}

.botao_de_selecao_de_peso.botao_de_peso_ativo {
	background-color: var(--cor_de_conversao);
	color: var(--cor_de_texto_sobre_cor);
	border-color: var(--cor_de_conversao);
}

/* A BOLINHA DE CONTAGEM
   Vazia ela não existe: o :empty evita precisar de uma classe só para escondê-la,
   e o PHP e o JavaScript se limitam a escrever ou apagar o número. */
.selo_de_quantidade_de_peso {
	position: absolute;
	top: -7px;
	right: -7px;
	min-width: 18px;
	height: 18px;
	padding: 0 4px;
	box-sizing: border-box;
	background-color: var(--cor_de_conversao);
	color: var(--cor_de_texto_sobre_cor);
	border: 2px solid var(--cor_de_superficie); /* Descola a bolinha da pílula vizinha */
	border-radius: 10px;
	font-size: 10px;
	font-weight: 700;
	line-height: 14px;
	text-align: center;
	pointer-events: none;

	/* A entrada e a saída das duas moedas. Ver o bloco de aparecimento adiante. */
	opacity: 1;
	transform: scale(1);
	transition:
		opacity 0.22s ease,
		transform 0.22s ease;
}

/* VAZIA ELA SOME SEM `display: none`, e isso é o que torna a saída animável:
   `display` não tem valores intermediários, então o navegador não tem como
   percorrer o caminho entre um estado e outro — a bolinha simplesmente piscava
   para fora. Como ela é posicionada em absoluto, apagá-la com opacidade não
   deixa buraco nenhum no lugar onde estava, que era a única razão de existir do
   `display: none` aqui. O `:empty` continua sendo o seletor: o PHP e o
   JavaScript seguem só escrevendo ou apagando o número. */
.selo_de_quantidade_de_peso:empty {
	opacity: 0;
	transform: scale(0.4);
}

/* A MOEDINHA DE FAVORITO (v9_18)

   SOZINHA, ELA MORA NO MESMO CANTINHO DA CONTAGEM. Não há motivo para ficar num
   canto secundário quando o principal está livre — e assim o cliente aprende um
   lugar só para "o canto que fala sobre este peso", seja o número, seja o
   coração.

   COM A CONTAGEM À MOSTRA, ELA DESLIZA PARA A ESQUERDA e passa a correr por
   baixo: as duas se sobrepõem lateralmente, e sobra do coração a metade que não
   está coberta. A contagem fica por cima porque é número e precisa ser lida
   inteira; o coração é só um sinal de "este aqui você marcou" e se dá por
   satisfeito com a metade.

   POR QUE SOBREPOSTAS, E NÃO LADO A LADO DE VERDADE. A pista de pesos é uma
   linha de pílulas apertadas — duas moedas separadas alargariam cada pílula em
   uns 20px e a pista quebraria numa segunda linha, mudando a altura de todos os
   cartões da grade por causa de um detalhe de canto.

   O `top` das duas é diferente de propósito: a contagem tem 18px de altura e o
   coração 16px, e é essa diferença de 1px em cada ponta que alinha os CENTROS
   quando ficam lado a lado. Alinhar pelo topo deixaria o coração visivelmente
   caído.

   O `z-index` explícito não é decorativo: sem ele valeria a ordem do HTML, e um
   dia alguém trocaria as duas linhas de lugar sem imaginar que estava escondendo
   o número do carrinho atrás de um coração. */
.selo_de_favorito_de_peso {
	position: absolute;
	top: -6px;
	right: -7px;
	z-index: 1;
	width: 16px;
	height: 16px;
	box-sizing: border-box;
	background-color: var(--cor_de_alerta, #e74c3c);
	color: var(--cor_de_superficie);
	border: 2px solid var(--cor_de_superficie);
	border-radius: 50%;
	font-size: 9px;
	line-height: 12px;
	text-align: center;
	pointer-events: none;

	/* Apagada por padrão: quem a acende é a classe posta pelo JavaScript. Não dá
	   para usar a `.estado_oculto` do sistema aqui — ela é `display: none`, e
	   `display` não anima. */
	opacity: 0;
	transform: scale(0.4);
	transition:
		opacity 0.22s ease,
		transform 0.22s ease,
		right 0.22s ease;
}

.selo_de_favorito_de_peso.estado_de_selo_aceso {
	opacity: 1;
	transform: scale(1);
}

/* O EMPURRÃO. O seletor de irmão adjacente só enxerga para a frente, e é por isso
   que a contagem vem antes do coração no HTML da pílula: é ela quem manda no
   deslocamento, e não o contrário. Trocar a ordem dos dois `<span>` no PHP
   desliga esta regra em silêncio — o coração voltaria a ficar sob a contagem,
   escondido, sem que nada acusasse o erro. */
.selo_de_quantidade_de_peso:not(:empty) + .selo_de_favorito_de_peso {
	right: 5px;
}

.selo_de_quantidade_de_peso {
	z-index: 2;
}

/* A PULSAÇÃO DE QUANDO A MOEDA ACENDE

   O fade sozinho é discreto demais para o momento em que ele acontece: o cliente
   acabou de tocar num botão e precisa ver que o toque foi entendido. A moeda
   entra passando um pouco do tamanho final e volta — o mesmo exagero curto que o
   coração grande do cartão já faz ao ser clicado.

   É ANIMAÇÃO, E NÃO TRANSIÇÃO, porque a transição descreve um caminho entre dois
   estados e aqui o caminho tem três pontos: pequena, grande demais, certa. E é
   posta pelo JavaScript, e não pelo próprio seletor de aceso, para que ela
   aconteça só quando a moeda ACENDE — se morasse na classe de aceso, cada
   recarregamento faria pipocar toda moeda já acesa na tela, e uma vitrine
   inteira pulsando sem que ninguém tenha tocado em nada parece defeito. */
@keyframes animacao_de_surgimento_de_selo_de_bloquinho {
	0% {
		transform: scale(0.4);
	}
	55% {
		transform: scale(1.3);
	}
	100% {
		transform: scale(1);
	}
}

.selo_de_bloquinho_em_pulsacao {
	animation: animacao_de_surgimento_de_selo_de_bloquinho 0.42s ease-out;
}

/* Quem pediu para o sistema não animar não quer ser surpreendido por um salto.
   O fade continua, porque ele é leve; o que sai é o exagero de escala. */
@media (prefers-reduced-motion: reduce) {
	.selo_de_bloquinho_em_pulsacao {
		animation: none;
	}
}

/* --- 4. PREÇO, QUANTIDADE E BOTÕES ADAPTADOS --- */
.bloco_de_preco_e_peso {
	display: flex;
	flex-direction: column;
	align-items: center;
	margin-bottom: 10px;
	margin-top: auto;
}
.preco_de_produto {
	font-size: 20px;
	font-weight: bold;
	color: var(--cor_de_conversao);
	margin: 0;
}

/* ------------------------------------------------------------------------------
   O PREÇO CHEIO RISCADO (2026-08-13)

   Ele só existe quando há promoção vigente, e é ele que dá sentido ao número em
   destaque: "R$ 6,90" sozinho não conta que houve desconto, e é o desconto que faz
   o cliente decidir agora em vez de depois.

   ⚠️ ELE É MENOR E CINZA DE PROPÓSITO. Dois preços do mesmo tamanho na mesma linha
   fazem o olho parar para descobrir qual é o que vale — que é exatamente o
   contrário do que um preço promocional deve provocar. O risco (`line-through`) diz
   "este não vale mais"; o tamanho e a cor dizem "e não é nele que você deve olhar".

   ⚠️ E ELE VIVE DENTRO DO `.preco_de_produto`, e não ao lado. Aquele elemento é
   reescrito inteiro por `selecionar_peso_na_vitrine()` a cada troca de pílula —
   estando dentro, o riscado SOME junto quando o peso muda, em vez de ficar parado
   descrevendo o peso anterior.
------------------------------------------------------------------------------ */
/* ⚠️ A MARGEM É À DIREITA DESDE 2026-08-13, e antes era à esquerda. O riscado passou
   a vir ANTES do preço — a pedido do Felipe —, e a leitura virou a de um desconto:
   "era 8,50, é 6,90". A margem acompanha o lado; deixá-la à esquerda colaria o
   riscado no preço e o afastaria da borda do cartão. */
.preco_cheio_riscado_de_produto {
	margin-right: 8px;

	font-size: 14px;
	font-weight: 500;
	color: var(--cor_de_texto_suave);
	text-decoration: line-through;
}
.controles_de_quantidade {
	display: flex;
	align-items: center;
	justify-content: space-between;
	background-color: var(--cor_de_superficie);
	border-radius: 7px;
	padding: 2px;
	height: 36px;
	width: 120px;
	margin: 0 auto 12px auto;
	box-sizing: border-box;
}
.botao_de_alteracao {
	background-color: var(--cor_de_divisor);
	border: none;
	border-radius: 6px;
	width: 32px;
	height: 32px;
	flex: 0 0 32px;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 18px;
	color: var(--cor_de_informacao);
	cursor: pointer;
	padding: 0;
}
/* ⚠️⚠️ OS 16px NÃO SÃO PREFERÊNCIA DE TAMANHO — SÃO O QUE IMPEDE O iOS DE AMPLIAR A PÁGINA
   (item D25, 2026-08-17)

   O Safari do iPhone dá zoom na página inteira ao focar um campo com fonte MENOR que
   16px, e não desfaz o zoom ao sair dele. O cliente toca no campo de quantidade para
   digitar "2", a vitrine fica ampliada, e ele passa o resto da visita arrastando a tela
   para os lados — sem ter pedido nada disso e sem ter como desfazer, porque o
   `touch-action: manipulation` da fundação tira o zoom por toque duplo.

   ⚠️ E NÃO ADIANTA CONSERTAR COM `maximum-scale=1` NA META VIEWPORT, que é o atalho que
   se encontra por aí: aquilo desliga o zoom manual da página inteira, inclusive o de
   quem precisa dele para enxergar. Trocar acessibilidade por um pixel de fonte é o
   negócio errado — 16px resolve o mesmo problema sem tirar nada de ninguém.

   📌 SÃO TRÊS CAMPOS NA VITRINE, e não um. Este, o da janela de carrinho e o da resposta
   do enigma dos blocos — os três eram menores que 16px e os três produziam o mesmo zoom.
   O de busca do topo já estava em 16px desde sempre, e é por isso que o defeito nunca
   apareceu ali. Consertar só o que foi relatado deixaria dois de três de pé, com o
   sintoma idêntico e a causa já conhecida. */
.campo_de_quantidade {
	flex: 1 1 0px;
	min-width: 0;
	width: 100%;
	border: none;
	text-align: center;
	font-size: 16px;
	font-weight: bold;
	color: var(--cor_de_texto_principal);
	background: transparent;
	appearance: textfield;
	-moz-appearance: textfield;
}
.campo_de_quantidade::-webkit-outer-spin-button,
.campo_de_quantidade::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

.bloco_de_botoes_de_compra {
	display: flex;
	gap: 6px;
	width: 100%;
}
.botao_de_adicao_ao_carrinho {
	border: none;
	padding: 10px;
	border-radius: 8px;
	font-weight: bold;
	cursor: pointer;
	transition: 0.3s;
	height: 44px;
	display: flex;
	align-items: center;
	justify-content: center;
}

/* Botão de Adicionar (apenas o ícone para economizar espaço) */
.estilo_de_botao_secundario {
	background-color: var(--cor_de_divisor);
	color: var(--cor_de_texto_principal);
	flex: 0 0 45px;
	font-size: 16px;
}
/* Botão Comprar (Laranja em destaque) */
.estilo_de_botao_primario {
	background-color: var(--cor_de_atencao);
	color: var(--cor_de_texto_sobre_cor);
	flex: 1;
	font-size: 12px;
}

.botao_de_compartilhamento {
	background-color: var(--cor_de_superficie_suave);
	color: var(--cor_de_texto_suave);
	border: 1px solid #dfe4ea;
	margin-top: 8px;
	width: 100%;
	height: 36px;
	font-size: 11px;
}

/* ==============================================================================
   ANIMAÇÃO DE CARREGAMENTO
============================================================================== */
@keyframes animacao_de_giro_de_carregamento {
	0% {
		transform: rotate(0deg);
	}
	100% {
		transform: rotate(360deg);
	}
}
.circulo_de_carregamento {
	width: 40px;
	height: 40px;

	/* SÓ O ARCO ATIVO GIRA.

	   Havia um anel cinza completo por baixo, e o arco colorido corria por cima
	   dele. Com o trilho visível, o que se vê é um círculo parado com um pedaço
	   mais escuro passando; sem ele, o que se vê é o próprio movimento. */
	border: 4px solid transparent;
	border-top: 4px solid var(--cor_de_atencao);

	border-radius: 50%;

	animation: animacao_de_giro_de_carregamento 0.8s linear infinite;

	margin: 0 auto 15px auto;
}

/* ==============================================================================
   BOTÃO DE FINALIZAR COMPRA (GAVETA DO CARRINHO)
============================================================================== */
.botao_de_finalizar_compra {
	background-color: #28a745; /* Verde universal de conversão e aprovação */
	color: var(--cor_de_texto_sobre_cor);
	text-decoration: none; /* Remove o sublinhado azul nativo do link */
	padding: 15px;
	border-radius: 8px;
	font-weight: bold;
	font-size: 18px;
	display: block;
	text-align: center;
	width: 100%;
	box-sizing: border-box;
	transition: background-color 0.3s;
}

.botao_de_finalizar_compra:hover {
	background-color: #218838;
}

/* ==============================================================================
   BOTÃO PROMOCIONAL (OFERTA IRRESISTÍVEL / GATILHO VISUAL)
============================================================================== */
.botao_de_selecao_de_peso.botao_de_peso_promocional {
	border: 2px dashed #9b59b6; /* Violeta elegante tracejado */

	/* ⚠️ O `#8e44ad` VIROU `--cor_de_oferta` NA FUNDAÇÃO EM 2026-08-13, quando os
	   selos do cartão passaram a precisar do mesmo violeta. O valor não mudou um
	   dígito; o que mudou é que agora ele tem um lugar só.
	   A borda continua com `#9b59b6` literal, e é outro tom de propósito — ela é o
	   tracejado, e não o texto. */
	color: var(--cor_de_oferta);
	background-color: var(--cor_de_superficie);
	animation: animacao_de_pulsacao_promocional 2s infinite; /* Chama a atenção */
}

/* Na promoção a bolinha veste violeta: o bloquinho mantém a identidade dele, e não
   ficam dois sistemas de cor brigando dentro da mesma pílula. */
.botao_de_peso_promocional .selo_de_quantidade_de_peso {
	background-color: #8e44ad;
}

/* Escolhida, a promoção enche de cor e para de pulsar.
   O violeta cheio é o que o verde cheio é para os pesos comuns: o estado mais
   forte da escala, reservado para o que está valendo. Antes ela ficava em
   violeta claro, um degrau abaixo do verde das vizinhas — e a oferta escolhida
   parecia menos escolhida que um peso comum escolhido. A pulsação para porque
   ela já foi atendida: continuar chamando depois do clique é não ter percebido
   o clique. */
.botao_de_selecao_de_peso.botao_de_peso_promocional.botao_de_peso_ativo {
	background-color: #8e44ad;
	border-style: solid; /* Fica sólido, confirmando a ação */
	border-color: #8e44ad;
	color: var(--cor_de_texto_sobre_cor);
	animation: none;
}

/* A BOLINHA DA OFERTA NÃO INVERTE MAIS QUANDO A PÍLULA É ESCOLHIDA.

   Ela invertia — fundo branco, número violeta — pelo receio de que violeta sobre
   violeta virasse um vulto ilegível. Só que quem separa os dois violetas é o anel
   branco de 2px que a bolinha já tem por baixo, o mesmo que separa a bolinha
   verde da pílula verde cheia do lado. Lá nunca houve inversão, e ninguém
   estranhou.

   O QUE A INVERSÃO CUSTAVA era a bolinha mudar de aparência conforme a pílula
   estivesse escolhida ou não: a mesma informação — quantas unidades — trocava de
   cor por um motivo que não tem nada a ver com ela. Agora a regra é uma só, e
   igual à das verdes: fundo da cor do bloquinho, número branco, anel branco. */
.botao_de_peso_promocional.botao_de_peso_ativo .selo_de_quantidade_de_peso {
	background-color: #8e44ad;
	color: var(--cor_de_texto_sobre_cor);
	border-color: var(--cor_de_superficie);
}

/* ==============================================================================
   A PÍLULA DE OFERTA DE LOTE — O ANZOL DE CONVERSÃO (v9_22)

   Ela veste o MESMO roxo da promoção de catálogo, e isso é decisão, não preguiça:
   o cliente já aprendeu nesta vitrine que roxo tracejado quer dizer "preço melhor
   aqui", e inventar uma quarta cor para um segundo tipo de preço melhor gastaria
   esse aprendizado para comunicar uma distinção que só interessa à loja. Para quem
   compra, as duas são a mesma coisa: está mais barato neste peso.

   O QUE MUDA É O RITMO. A pulsação anda mais rápido porque esta oferta tem prazo —
   ela existe enquanto um lote específico não vence, e some com ele. É a diferença
   que se sente sem precisar ler.

   A CLASSE VEM SEMPRE ACOMPANHADA de `botao_de_peso_promocional`, nunca sozinha:
   toda a borda, a cor e o estado escolhido saem de lá, e aqui fica só o que
   diverge. Sozinha, ela não desenha pílula nenhuma.

   Ela é também o gancho para quando o preço da oferta passar a ser COBRADO de
   verdade — hoje a pílula muda a ordem e a seleção do cartão, mas o valor exibido
   ainda é o preço da variação, porque o carrinho e o checkout não sabem o que é um
   lote. Veja `comando-v9_22.txt`.
============================================================================== */
.botao_de_selecao_de_peso.botao_de_peso_de_oferta_de_lote {
	animation-duration: 1.2s;
}

/* Escolhida, ela para de pulsar como a irmã — pelo mesmo motivo: continuar
   chamando depois do clique é não ter percebido o clique. */
.botao_de_selecao_de_peso.botao_de_peso_de_oferta_de_lote.botao_de_peso_ativo {
	animation: none;
}

/* O Motor de Pulsação Suave (Efeito Radar) */
@keyframes animacao_de_pulsacao_promocional {
	0% {
		box-shadow: 0 0 0 0 rgba(155, 89, 182, 0.4);
	}
	70% {
		box-shadow: 0 0 0 6px rgba(155, 89, 182, 0);
	}
	100% {
		box-shadow: 0 0 0 0 rgba(155, 89, 182, 0);
	}
}

/* ==============================================================================
   ESTRUTURA DE TELA ESTREITA (BLOQUINHOS FLUTUANTES)
============================================================================== */
.elemento_de_tela_estreita {
	/* Ao invés de sumir com display: none, nós afundamos eles no chão */
	opacity: 0;
	transform: translateY(120px) scale(0.8);
	pointer-events: none; /* Garante que ninguém clique em fantasmas na tela larga */

	/* O Motor que faz o movimento reverso suave quando a tela estica */
	transition:
		opacity 0.4s ease,
		transform 0.5s cubic-bezier(0.25, 1, 0.5, 1);
}

/* ==============================================================================
   MENU LATERAL E ÍCONE DE HAMBÚRGUER (Global - Todas as telas)
============================================================================== */

/* --- ÍCONE DE HAMBÚRGUER (2 Linhas virando X) --- */
.icone_de_hamburguer_duplo {
	width: 20px;
	height: 14px;
	position: relative;
}
.icone_de_hamburguer_duplo span {
	display: block;
	position: absolute;
	height: 3px;
	width: 100%;
	background: var(--cor_de_texto_principal);
	border-radius: 3px;
	transition: all 0.3s ease;
	left: 0;
}
.icone_de_hamburguer_duplo span:nth-child(1) {
	top: 2px;
}
.icone_de_hamburguer_duplo span:nth-child(2) {
	top: 10px;
}

.botao_de_menu_ativo .icone_de_hamburguer_duplo span:nth-child(1) {
	top: 6px;
	transform: rotate(45deg);
	background: var(--cor_de_alerta);
}
.botao_de_menu_ativo .icone_de_hamburguer_duplo span:nth-child(2) {
	top: 6px;
	transform: rotate(-45deg);
	background: var(--cor_de_alerta);
}

/* ==============================================================================
	MÁGICA 2: O GATILHO DO EMPURRÃO FÍSICO (Agora é Global para PC e Celular!)
============================================================================== */
.botao_de_menu_ativo {
	z-index: 10006 !important;

	/* A variável que o JavaScript vai injetar (Positiva pro PC, Negativa pro Celular) */
	transform: translateX(var(--distancia-de-fuga, 0px)) !important;

	/* Forçamos o fundo branco e a sombra para ele parecer um botão flutuante sobre o menu */
	background-color: var(--cor_de_superficie) !important;
	box-shadow: 0 4px 15px rgba(0, 0, 0, 0.25) !important;
	border-radius: 14px !important;

	/* 🚨 Apagamos o animation: none daqui para o navegador não reiniciar a entrada na volta! */

	/* Proteção e sincronia com a janela de 0.4s */
	transition:
		transform 0.25s cubic-bezier(0.25, 1, 0.5, 1) 0.15s,
		background-color 0.3s !important;
}

/* ==============================================================================
   ESTILO BASE DO MENU FLUTUANTE (Comum para todas as telas)
============================================================================== */
.menu_lateral_escondido {
	position: fixed;
	top: 15px;
	bottom: 15px;
	width: calc(100vw - 80px);
	max-width: 320px;
	background-color: var(--cor_de_superficie);
	border-radius: 20px;
	z-index: 10005;
	display: flex;
	flex-direction: column;
	overflow: hidden;

	/* A MÁGICA: Devolve a massa física para o menu, impedindo que o dedo atravesse! */
	pointer-events: auto;
}

/* ==============================================================================
   COMPORTAMENTO NO CELULAR (Nasce e abre pela DIREITA)
============================================================================== */
@media (max-width: 768px) {
	.menu_lateral_escondido {
		right: -100%;
		left: auto;
		box-shadow: -5px 0 30px rgba(0, 0, 0, 0.2);
		transition: right 0.4s cubic-bezier(0.25, 1, 0.5, 1);
	}
	.menu_lateral_em_aberto {
		right: 15px;
	}
}

/* ==============================================================================
   COMPORTAMENTO NO COMPUTADOR (Nasce e abre pela ESQUERDA)
============================================================================== */
@media (min-width: 769px) {
	.menu_lateral_escondido {
		left: -100%;
		right: auto;
		box-shadow: 5px 0 30px rgba(0, 0, 0, 0.2);
		transition: left 0.4s cubic-bezier(0.25, 1, 0.5, 1);
	}
	.menu_lateral_em_aberto {
		left: 15px;
	}
}

.cabecalho_de_menu_lateral {
	background-color: var(--cor_de_texto_principal);
	color: var(--cor_de_texto_sobre_cor);
	padding: 30px 20px 20px 20px;
}
.cabecalho_de_menu_lateral h2 {
	margin: 0;
	font-size: 20px;
}

.links_de_menu_lateral {
	display: flex;
	flex-direction: column;
	padding: 10px 0;
	overflow-y: auto;
}
.links_de_menu_lateral a {
	padding: 18px 25px;
	color: var(--cor_de_texto_principal);
	text-decoration: none;
	font-size: 16px;
	border-bottom: 1px solid #f1f2f6;
	font-weight: bold;
}
.links_de_menu_lateral a:hover,
.links_de_menu_lateral a:active {
	background-color: var(--cor_de_superficie_suave);
}

/* --- FUNDO ESCURO DE MENU --- */
.fundo_escuro_escondido {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: rgba(0, 0, 0, 0.5);
	z-index: 10004;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.4s ease;
	display: block !important;
}
.fundo_escuro_em_aberto {
	opacity: 1;
	pointer-events: auto;
}

/* ==============================================================================
   ESTRUTURA GLOBAL DO RODAPÉ (Libertados da jaula do Celular)
============================================================================== */
/* --- O RECIPIENTE FANTASMA --- */
.base_flutuante_de_tela_estreita {
	position: fixed;
	bottom: 25px;
	left: 0;
	width: 100%;
	padding: 0 15px;
	box-sizing: border-box;
	z-index: 9900;
	display: flex;
	justify-content: flex-end;
	align-items: center;
	gap: 12px;
	background: transparent;
	pointer-events: none;
}

/* --- OS BLOQUINHOS (Menu e Conta) --- */
.bloquinho_flutuante {
	pointer-events: auto;
	width: 48px;
	height: 48px;
	background-color: var(--cor_de_superficie);
	border-radius: 14px;
	box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
	display: flex;
	align-items: center;
	justify-content: center;
	border: none;
	color: var(--cor_de_texto_principal);
	text-decoration: none;
	cursor: pointer;
	transition:
		transform 0.4s cubic-bezier(0.25, 1, 0.5, 1),
		background-color 0.3s,
		opacity 0.4s ease;
	flex-shrink: 0;
	z-index: 996;
}
.bloquinho_flutuante:active {
	transform: scale(0.92);
}

/* --- PÍLULA DE CARRINHO --- */
.pilula_de_carrinho_flutuante {
	pointer-events: auto;
	background-color: #1a252f;
	border: 1px solid var(--cor_de_atencao);
	border-radius: 14px;
	height: 48px;
	padding: 0 20px;
	display: flex;
	align-items: center;
	gap: 12px;
	box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
	cursor: pointer;
	transition:
		transform 0.4s cubic-bezier(0.25, 1, 0.5, 1),
		opacity 0.4s ease;
	z-index: 996;
}
.pilula_de_carrinho_flutuante:active {
	transform: scale(0.96);
}

.icone_de_carrinho_de_rodape {
	font-size: 20px;
}

.linhas_de_resumo_de_tela_estreita {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	font-size: 11px;
	line-height: 1.2;
}
.linhas_de_resumo_de_tela_estreita .destaque_de_valor {
	color: var(--cor_de_atencao);
	font-size: 14px;
	font-weight: bold;
}

/* A ANIMAÇÃO DE LUPA DE RODAPÉ */
#botao_de_pesquisa_de_rodape {
	background-color: var(--cor_de_superficie);
	border-radius: 14px;
	box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
	color: var(--cor_de_texto_principal);
	border: none;
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	width: 0;
	margin: 0;
	padding: 0;
	opacity: 0;
	transform: scale(0);
	pointer-events: none;
	transition:
		width 0.3s ease,
		margin 0.3s ease,
		opacity 0.3s ease,
		transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
#botao_de_pesquisa_de_rodape.botao_pesquisa_visivel {
	width: 48px;
	opacity: 1;
	transform: scale(1);
	pointer-events: auto;
}

/* Ao esticar a janela, a lupa mergulha junto com o hambúrguer, o acesso e o carrinho.
   Ela já carrega a classe .elemento_de_tela_estreita no HTML, mas as regras acima usam
   seletor de ID e venciam o mergulho compartilhado por especificidade — por isso esta
   repete o mesmo movimento com a força necessária para valer na tela larga.
   A largura de 48px é mantida de propósito: com width: 0 não haveria corpo para
   afundar, e a saída dela destoaria da dos irmãos. */
@media (min-width: 769px) {
	#botao_de_pesquisa_de_rodape,
	#botao_de_pesquisa_de_rodape.botao_pesquisa_visivel {
		width: 48px;
		opacity: 0;
		transform: translateY(120px) scale(0.8);
		pointer-events: none;
		transition:
			opacity 0.4s ease,
			transform 0.5s cubic-bezier(0.25, 1, 0.5, 1);
	}
}

/* ==============================================================================
   REGRAS EXCLUSIVAS DE CELULAR (Apenas Efeitos e Ocultação do Topo)
============================================================================== */
@media (max-width: 768px) {
	.elemento_de_tela_estreita {
		/* Restaura o estado natural para que a nossa animação de cascata atue perfeitamente */
		opacity: 1;
		transform: translateY(0) scale(1);
		pointer-events: auto;
	}

	/* --- MÁGICA 4: ZOOM OUT INDIVIDUAL DOS ITENS DO TOPO --- */
	.bloquinho_de_menu_cabecalho {
		opacity: 0 !important;
		transform: scale(0.3) !important;
		pointer-events: none !important;
		position: absolute !important;
		left: 20px;
	}

	.menu_de_navegacao {
		position: absolute !important;
		right: 20px;
		pointer-events: none !important;
	}

	.menu_de_navegacao > a {
		opacity: 0 !important;
		transform: scale(0.3) !important;
	}

	.menu_de_navegacao > .bloco_de_carrinho_em_cabecalho {
		opacity: 0 !important;
		transform: scale(0.3) !important;
		transition-delay: 0.1s;
	}

	body {
		padding-bottom: 90px;
	}

	/* --- ANIMAÇÃO DE ENTRADA (EFEITO CASCATA ASCENDENTE CORRIGIDO) --- */
	@keyframes entrada_suave_de_base {
		0% {
			opacity: 0;
			transform: translateY(30px) scale(0.9);
		}
		100% {
			opacity: 1;
			transform: translateY(0) scale(1);
		}
	}

	#botao_de_menu_hamburguer,
	.base_flutuante_de_tela_estreita > a.bloquinho_flutuante,
	.pilula_de_carrinho_flutuante {
		opacity: 1;
		transform: translateY(0) scale(1);
	}

	#botao_de_menu_hamburguer {
		animation: entrada_suave_de_base 0.5s cubic-bezier(0.25, 1, 0.5, 1)
			backwards;
		animation-delay: 0.3s;
	}

	.base_flutuante_de_tela_estreita > a.bloquinho_flutuante {
		animation: entrada_suave_de_base 0.5s cubic-bezier(0.25, 1, 0.5, 1)
			backwards;
		animation-delay: 0.2s;
	}

	.pilula_de_carrinho_flutuante {
		animation: entrada_suave_de_base 0.5s cubic-bezier(0.25, 1, 0.5, 1)
			backwards;
		animation-delay: 0.1s;
	}
}

/* ==============================================================================
   ANIMAÇÃO DE ENTRADA EM CASCATA (TELA LARGA - DIREÇÃO DE ATENÇÃO)
============================================================================== */
@media (min-width: 769px) {
	/* 1. O Motor de Animação (Escala de 85% para 100% com ganho de opacidade) */
	@keyframes animacao_de_entrada_em_zoom {
		0% {
			opacity: 0;
			transform: scale(0.85);
		}
		100% {
			opacity: 1;
			transform: scale(1);
		}
	}

	/* 2. Definimos o estado final como sólido para não precisarem do cadeado da animação */
	.titulo_de_cabecalho,
	.bloquinho_de_menu_cabecalho,
	.menu_de_navegacao > a,
	.bloco_de_carrinho_em_cabecalho {
		opacity: 1;
		transform: scale(1);
	}

	/* 3. A Coreografia (O parâmetro 'backwards' garante que fiquem invisíveis antes de começar) */

	/* Primeiro a entrar: O Logotipo (Gatilho de Autoridade e Confiança) */
	.titulo_de_cabecalho {
		animation: animacao_de_entrada_em_zoom 0.6s
			cubic-bezier(0.25, 1, 0.5, 1) backwards;
		animation-delay: 0.1s;
	}

	/* Segundo a entrar: O Hambúrguer na extrema esquerda (Opções de Navegação) */
	.bloquinho_de_menu_cabecalho {
		animation: animacao_de_entrada_em_zoom 0.6s
			cubic-bezier(0.25, 1, 0.5, 1) backwards;
		animation-delay: 0.25s;
	}

	/* Terceiro a entrar: O Acesso de Conta na direita (Relacionamento) */
	.menu_de_navegacao > a {
		animation: animacao_de_entrada_em_zoom 0.6s
			cubic-bezier(0.25, 1, 0.5, 1) backwards;
		animation-delay: 0.4s;
	}

	/* Quarto a entrar: O Carrinho (Foco na Conversão - onde o olho deve parar) */
	.bloco_de_carrinho_em_cabecalho {
		animation: animacao_de_entrada_em_zoom 0.6s
			cubic-bezier(0.25, 1, 0.5, 1) backwards;
		animation-delay: 0.55s;
	}
}

/* ==============================================================================
   CARTAZ IMERSIVO E TOPO TRANSPARENTE (EFEITO KORO / THRIVE)
============================================================================== */

/* O grande container do topo (Garante que nunca quebre, mesmo se não houver imagem) */
.secao_de_cartaz_de_topo_imersivo {
	position: relative;
	width: 100%;
	background-color: #fdf5e6; /* Tom pastel de segurança de marca */
	min-height: 180px;
}

/* ==============================================================================
   O CARTAZ NASCE FECHADO E SE ABRE QUANDO A FOTO CHEGA

   A capa é a maior imagem da loja, e é a primeira coisa que o navegador precisa
   baixar. Enquanto ela não chega, o espaço dela já existia no layout — uma
   moldura vazia ocupando meia tela, que depois piscava para a foto de uma vez.
   Pior: se a imagem demorasse mais do que o resto da página, tudo abaixo dela
   saltava de lugar no instante em que ela aparecia.

   Agora o bloco começa com altura zero e invisível. Quando a foto termina de
   baixar, o JavaScript mede a altura que ela vai ocupar e anima daí até lá,
   empurrando a página para baixo com calma, enquanto a imagem aparece por
   desvanecimento. Quem chega vê a loja pronta e a capa se abrindo — e não um
   buraco que se preenche.

   A ALTURA É ANIMADA PELO JAVASCRIPT, e não daqui, porque ela depende da largura
   da tela: com `aspect-ratio`, a altura da capa muda a cada tamanho de janela, e
   nenhum valor escrito no CSS serviria para todas. Aqui fica só o estado
   fechado e a transição do desvanecimento.
============================================================================== */
.link_de_fundo_de_cartaz {
	display: block;
	width: 100%;

	/* O estado de partida: fechado e invisível. */
	height: 0;
	overflow: hidden;
	opacity: 0;
	transition: opacity 0.55s ease;
}

.link_de_fundo_de_cartaz.estado_de_cartaz_revelado {
	height: auto;
	overflow: visible;
	opacity: 1;
}

/* Quem pediu para o sistema não animar recebe a capa aberta, sem abertura nem
   desvanecimento. O JavaScript também respeita esta preferência e pula direto
   para o estado final. */
@media (prefers-reduced-motion: reduce) {
	.link_de_fundo_de_cartaz {
		transition: none;
	}
}

/* ==============================================================================
   A CAPA TEM PROPORÇÃO, E NÃO ALTURA FIXA

   A altura era travada — 380px no computador, 50vh no celular — e a largura ia
   até a borda. O resultado é que a MOLDURA mudava de formato conforme a janela,
   e com ela o quanto da imagem sobrevivia ao corte do `object-fit: cover`:

     notebook de 1400px  →  48% da altura da imagem
     monitor de 1920px   →  35%
     ultrawide de 2560px →  26%

   Ou seja: não existia enquadramento possível. Uma capa desenhada para ficar boa
   no notebook perdia a cabeça do personagem no monitor grande, e quem produz a
   imagem não tinha alvo nenhum a mirar — o alvo mudava com o tamanho da tela de
   quem olhasse.

   COM `aspect-ratio`, A MOLDURA TEM SEMPRE O MESMO FORMATO. A capa cresce e
   encolhe junto com a janela, mantendo a proporção, e o pedaço da imagem que
   aparece passa a ser o mesmo em qualquer largura. O que foi enquadrado na hora
   de gerar a imagem é o que todo mundo vê.

   SÃO DUAS PROPORÇÕES, E NÃO UMA. A mesma proporção nas duas telas é impossível
   de conciliar: 3:1 num celular de 390px daria uma faixa de 130px de altura, e
   1:1 num monitor de 1920px daria uma capa de 1920px que engoliria a loja
   inteira. Duas proporções fixas mantêm a promessa que importa — dentro de cada
   faixa, o corte não muda.

   A ZONA SEGURA QUE ISTO CRIA, para uma imagem 16:9 (a proporção usual do que
   sai dos geradores): sobrevive 56% da largura no celular e 59% da altura no
   computador. Então o que for essencial — rosto, produto, texto — precisa caber
   no retângulo central de aproximadamente 56% × 59%. Antes eram 55% × 35%, e o
   35% era o que decapitava o personagem.
============================================================================== */
.imagem_de_fundo_de_cartaz {
	width: 100%;

	/* Celular: quase quadrado, que é o formato de uma tela em pé. */
	aspect-ratio: 1 / 1;

	/* O mínimo é a única rede que sobra, e existe para telas absurdamente
	   estreitas, onde a proporção sozinha daria uma faixa fina demais para
	   qualquer imagem dizer alguma coisa.

	   O TETO DE ALTURA SAIU, E ISSO É O PONTO DA MUDANÇA. Um `max-height` parece
	   inofensivo, mas ele é exatamente o que reintroduz o problema: no instante em
	   que entra em ação, a moldura deixa de seguir a proporção e volta a mudar de
	   formato conforme a janela. E ele entrava nas telas MAIS COMUNS — a 60vh, um
	   notebook de 1400x900 já batia no teto. O corte voltaria a variar justamente
	   onde está a maior parte das visitas, que é o pior lugar para ser
	   imprevisível. */
	min-height: 250px;

	object-fit: cover;
	object-position: center;
	display: block;
}

@media (min-width: 768px) {
	.imagem_de_fundo_de_cartaz {
		/* Computador: três por um. Numa janela de 1400px dá 467px de altura —
		   perto dos 380px de antes, e generosa o bastante para a cena respirar sem
		   esconder a vitrine que vem logo abaixo.

		   O preço de não ter teto: num monitor de 2560px a capa fica com 853px de
		   altura. É alta, e é o que uma capa de borda a borda com proporção fixa
		   custa nessa largura — em troca, o enquadramento vale para todo mundo. */
		aspect-ratio: 3 / 1;
	}
}

/* ==============================================================================
   SOBRESCREVENDO O CABEÇALHO PARA FLUTUAR SOBRE O CARTAZ
============================================================================== */
.secao_de_cartaz_de_topo_imersivo .bloco_de_cabecalho_fixo {
	position: fixed; /* MUDANÇA CIRÚRGICA: Devolvemos o poder de acompanhar a tela! */
	top: 0;
	left: 0;
	width: 100%;
	z-index: 9999; /* Elevamos para garantir que a lupa puxe ele por cima de tudo */

	/* Fundo todo transparente exatamente como você pediu: */
	background: transparent;

	/* DICA DE ARQUITETO DE CONVERSÃO (Regra 10 - Efeito Apple):
	   Como o fundo é transparente, ao rolar a tela, as castanhas podem se misturar com o texto. 
	   Se quiser um efeito luxuoso de "Vidro Fosco" (Blur), basta remover as barras das linhas abaixo: */
	/* backdrop-filter: blur(8px); */
	/* -webkit-backdrop-filter: blur(8px); */
}

/* Removemos o fundo branco e a sombra do cabeçalho original */
.secao_de_cartaz_de_topo_imersivo .cabecalho_de_loja {
	background-color: rgb(91 37 0 / 80%) !important;
	box-shadow: none !important;
}

/* ==============================================================================
   GRUPO FIXO DE BUSCA E FILTROS (A BARRA DE PESQUISA + A TRILHA VIAJAM JUNTAS)

   ATENÇÃO: este grupo é IRMÃO do .bloco_de_cabecalho_fixo, nunca filho dele.
   O cabeçalho se esconde com transform: translateY(-120%), e um transform faz
   todo descendente position: fixed passar a se posicionar em relação a ele em
   vez da janela — foi por isso que o menu lateral ficou solto no body. Manter
   este grupo de fora preserva a animação do menu intacta.
============================================================================== */

.grupo_fixo_de_busca_e_filtros {
	/* Sem fundo próprio de propósito: quem tem cor é a pílula do campo de busca.
	   Assim o grupo não desenha uma faixa branca em volta dela, seguindo o mesmo
	   partido do cabeçalho, que também flutua transparente sobre o cartaz. */
	background-color: transparent;
	z-index: 9990; /* Abaixo do cabeçalho (9999) e bem abaixo do menu (10005) */
}

/* --- TELA LARGA: encosta no cabeçalho e fica --- */
@media (min-width: 769px) {
	.grupo_fixo_de_busca_e_filtros {
		position: sticky;
		top: var(
			--altura_de_cabecalho_de_loja,
			64px
		); /* Sobe até encostar no cabeçalho */

		backdrop-filter: blur(70px);
	}
}

/* --- TELA ESTREITA: no lugar dela, é conteúdo comum ---
   Nenhum position especial e nenhum transform aqui de propósito: encaixada abaixo
   do cartaz, a barra some rolando junto com o resto da página, sem animação. */

@media (max-width: 768px) {
	/* O ÚNICO momento com animação: quando o 🔍 do rodapé convoca a barra de volta.
	   Aí sim ela desce sobre o conteúdo, porque o lugar natural dela ficou lá em cima. */
	.grupo_fixo_de_busca_e_filtros.grupo_de_busca_convocado {
		position: fixed;
		top: var(--altura_de_cabecalho_de_loja, 64px);
		left: 0;
		width: 100%;
		/* Nenhuma sombra aqui: o grupo é transparente, então a sombra apareceria
		   como um retângulo fantasma em volta do nada. Quem já tem sombra própria
		   é a pílula do campo de busca. */
		animation: animacao_de_descida_de_busca 0.35s
			cubic-bezier(0.25, 1, 0.5, 1) forwards;
	}

	@keyframes animacao_de_descida_de_busca {
		0% {
			opacity: 0;
			transform: translateY(-100%);
		}
		100% {
			opacity: 1;
			transform: translateY(0);
		}
	}

	/* A despedida: estado passageiro que segura a barra fixa só o tempo de ela subir.
	   Sem ele a barra sumiria de uma vez, porque perder a classe de convocada devolve
	   o grupo ao fluxo normal no mesmo quadro. O JavaScript retira esta classe quando
	   a animação termina — se mudar a duração aqui, mude lá também. */
	.grupo_fixo_de_busca_e_filtros.grupo_de_busca_recolhendo {
		position: fixed;
		top: var(--altura_de_cabecalho_de_loja, 64px);
		left: 0;
		width: 100%;
		pointer-events: none; /* Enquanto sai, não rouba o toque de quem está navegando */
		animation: animacao_de_subida_de_busca 0.3s
			cubic-bezier(0.25, 1, 0.5, 1) forwards;
	}

	@keyframes animacao_de_subida_de_busca {
		0% {
			opacity: 1;
			transform: translateY(0);
		}
		100% {
			opacity: 0;
			transform: translateY(-100%);
		}
	}
}

/* ==============================================================================
   TRILHA DE PÍLULAS DE CATEGORIA (NAVEGAÇÃO IFOOD / SHOPEE)
============================================================================== */

.secao_de_pilulas_de_categorias {
	width: 100%;
	max-width: 1200px;
	margin: 5px auto 5px auto;
	padding: 0 20px;
	box-sizing: border-box;
}

/* O contêiner rolável (Atrito Zero) */
/* ==============================================================================
   A TRILHA QUEBRA EM LINHAS EM VEZ DE CORTAR

   Ela era uma fila de uma linha só, e quem não coubesse saía de cena. Isso
   funcionava enquanto as categorias escolhidas eram estreitas — mas uma sozinha,
   de nome longo, já ocupava a largura inteira de um celular. A pílula seguinte
   ficava cortada pela metade, e com ela o botão "+N": o cliente perdia o acesso
   às demais categorias justamente depois de escolher uma.

   Com `flex-wrap`, o que não cabe desce para a linha de baixo em vez de sumir na
   borda. A trilha cresce em altura conforme precisa, e a altura é animada — a
   barra se ajusta em vez de saltar de tamanho.

   A ROLAGEM HORIZONTAL SAIU JUNTO. Ela nunca chegou a ser usada — o JavaScript
   escondia o excedente antes que houvesse o que rolar —, e com a quebra de linha
   ela passaria a competir com o gesto de rolar a página no celular.
============================================================================== */
.trilha_rolavel_de_pilulas {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	row-gap: 10px;
	white-space: normal;
	padding-bottom: 5px; /* Respiro para não cortar a sombra */
	overflow: hidden;
	scrollbar-width: none; /* Esconde a barra no Firefox */

	/* AS PÍLULAS NÃO ESTICAM COM A TRILHA.
	   O padrão de um contêiner flex é `align-items: stretch`: os filhos crescem
	   até a altura da caixa. Isso passava despercebido enquanto a altura era
	   automática — ela valia exatamente o conteúdo. No momento em que o JavaScript
	   prende a altura em pixels para animar, os 82px de duas fileiras viravam a
	   altura de CADA pílula, que engordava e ia afinando conforme a animação
	   corria. O tranco não era da transição: eram as pílulas mudando de forma
	   durante ela.

	   Com `center`, cada pílula mantém a própria altura e apenas se acomoda na
	   fileira. E `align-content: flex-start` impede que as FILEIRAS se espalhem
	   pela altura sobrando enquanto a animação acontece — sem ele, as linhas se
	   afastariam e voltariam a se juntar no fim. */
	align-items: center;
	align-content: flex-start;

	/* A âncora das pílulas que saem de cena: elas são tiradas do fluxo para não
	   segurar o lugar enquanto encolhem, e se posicionam em relação a esta caixa. */
	position: relative;

	/* A transição de altura NÃO é declarada aqui: existe outra regra
	   `.trilha_rolavel_de_pilulas` mais adiante neste arquivo, e ela venceria esta
	   por vir depois com a mesma especificidade. As duas animações de tamanho da
	   trilha estão declaradas juntas lá, com o porquê. */
}

@media (prefers-reduced-motion: reduce) {
	.trilha_rolavel_de_pilulas {
		transition: none;
	}
}

/* Esconde a barra de rolagem no Chrome, Safari e Edge */
.trilha_rolavel_de_pilulas::-webkit-scrollbar {
	display: none;
}

/* ==============================================================================
   A PÍLULA-BOTÃO "VER MAIS" E O DESAPARECIMENTO DAS CATEGORIAS QUE NÃO CABEM

   A trilha não rola mais, nem com o dedo nem com o mouse. Quem não couber sai de
   cena (.pilula_encolhida, aplicada pelo JavaScript) e volta quando a caixa abre.
   Por isso a pílula-botão pode ser o último item da própria fila: como a fila nunca
   transborda, ela nunca é empurrada para fora nem precisa de posição absoluta — e
   assim alinha certinho com as outras, na mesma linha de base.
============================================================================== */

/* ==============================================================================
   AS PÍLULAS DE ORDENAÇÃO MUDARAM DE ARQUIVO EM 2026-08-03.

   Elas foram para `componentes_compartilhados.css` — a camada 2, carregada por
   /loja e por /loja/pagamento —, porque a lista de itens da página de pagamento
   e a janela do carrinho daqui passaram a ter as mesmas duas pílulas no canto do
   título, para ordenar os itens do carrinho.

   Ficaram lá inteiras, com as setas e a mecânica dos três estados. Duplicá-las
   aqui era o caminho curto, e é exatamente o que criou os três cinzas quase
   iguais que os tokens da fundação vieram desfazer.

   As duas regras de largura de tela (`.rotulo_longo_de_ordenacao_de_preco` e
   `.rotulo_curto_de_ordenacao_de_preco`) continuam aqui embaixo, porque a troca
   de "Preço" por "$" é da trilha da vitrine: no carrinho só existe o cifrão.
============================================================================== */

/* --- A CHEGADA DAS PÍLULAS: ZOOM IN EM CASCATA AO ABRIR A PÁGINA ---
   O "backwards" é o que segura cada pílula no estado inicial durante a espera dela;
   sem ele, todas apareceriam inteiras e só depois encolheriam para animar. */
@keyframes entrada_de_pilula_em_zoom {
	0% {
		opacity: 0;
		transform: scale(0.6);
	}
	100% {
		opacity: 1;
		transform: scale(1);
	}
}

/* O `:not()` EXCLUI AS PÍLULAS DO CARRINHO desta cascata. Elas usam a mesma
   classe, mas vivem dentro da janela flutuante do carrinho, que está oculta
   quando a página carrega — e uma animação de entrada gasta em elemento invisível
   é, na melhor das hipóteses, invisível. Na pior, ela roda de novo quando a
   janela é aberta, e as duas pílulas dão um salto na cara do cliente que só
   queria conferir o carrinho. */
.pilula_de_categoria,
.pilula_de_ordenacao:not(.pilula_de_ordenacao_de_carrinho),
.pilula_de_contagem_de_categorias {
	animation: entrada_de_pilula_em_zoom 0.45s cubic-bezier(0.34, 1.56, 0.64, 1)
		backwards;
}

/* A cascata: cada uma entra um pouquinho depois da anterior. Da nona em diante
   todas dividem o mesmo atraso, para a fila não demorar a se formar. */
.trilha_rolavel_de_pilulas > * {
	animation-delay: 0.36s;
}
.trilha_rolavel_de_pilulas > *:nth-child(1) {
	animation-delay: 0.04s;
}
.trilha_rolavel_de_pilulas > *:nth-child(2) {
	animation-delay: 0.08s;
}
.trilha_rolavel_de_pilulas > *:nth-child(3) {
	animation-delay: 0.12s;
}
.trilha_rolavel_de_pilulas > *:nth-child(4) {
	animation-delay: 0.16s;
}
.trilha_rolavel_de_pilulas > *:nth-child(5) {
	animation-delay: 0.2s;
}
.trilha_rolavel_de_pilulas > *:nth-child(6) {
	animation-delay: 0.24s;
}
.trilha_rolavel_de_pilulas > *:nth-child(7) {
	animation-delay: 0.28s;
}
.trilha_rolavel_de_pilulas > *:nth-child(8) {
	animation-delay: 0.32s;
}
/* A PÍLULA [ +3 ]: O ÚNICO GATILHO DA CAIXA DE CATEGORIAS

   Ela aparece só quando há categorias guardadas, e é ela mesma que vira X para
   fechar. Isso não é enfeite: com a caixa aberta ninguém está escondido, então uma
   pílula que sumisse nessa hora deixaria a caixa sem nenhuma forma de fechar na
   tela larga, onde não existe o fogãozinho ao lado do campo de busca. */
.pilula_de_contagem_de_categorias {
	display: none; /* Nasce fora da fila; o JavaScript a chama quando há o que contar */
	align-items: center;
	background-color: var(--cor_de_atencao);
	color: var(--cor_de_texto_sobre_cor);
	border: none;
	font-size: 14px;
	font-weight: 700;
	padding: 8px 14px;
	border-radius: 7px; /* O mesmo raio das pílulas de categoria */
	cursor: pointer;
	flex-shrink: 0;
	white-space: nowrap;
	transition: all 0.2s ease;
}

.pilula_de_contagem_de_categorias.tem_categorias_guardadas,
.painel_de_categorias_aberto .pilula_de_contagem_de_categorias {
	display: inline-flex;
}

.pilula_de_contagem_de_categorias:hover {
	background-color: #e08e0b;
}

.pilula_de_contagem_de_categorias:active {
	transform: scale(0.96);
}

/* Aberta a caixa, o número dá lugar ao X */
.icone_de_fechar_contagem {
	display: none;
}

.painel_de_categorias_aberto .texto_de_contagem_de_categorias {
	display: none;
}

.painel_de_categorias_aberto .icone_de_fechar_contagem {
	display: inline;
	line-height: 1;
}

/* As categorias que deixaram de caber simplesmente saem de cena, sem animação: a
   fila se reorganiza na hora. Com display: none elas também não deixam para trás o
   espaço do gap, que sobraria se apenas encolhessem a largura. */
/* A pílula que não coube sai do fluxo por inteiro. Não basta zerar a largura:
   com `flex-wrap`, o `gap` continua contando entre elementos de largura zero, e
   uma fila de dez escondidas somaria mais de cem pixels de espaço fantasma — a
   conta de quem cabe daria errado por causa de quem não está lá. */
.pilula_de_categoria.pilula_encolhida {
	display: none;
}

/* A ENTRADA DE QUEM VOLTA À FILA, e a saída de quem deixa de caber.

   As duas classes são postas e retiradas pelo JavaScript no mesmo gesto que
   recalcula a trilha.

   A SAÍDA PRECISA SAIR DO FLUXO PARA ACONTECER. Uma pílula que encolhe ocupando
   o próprio lugar seguraria a fila parada até terminar, e as vizinhas só se
   reorganizariam depois — dois movimentos em sequência onde deveria haver um. Em
   `position: absolute` ela é retirada da conta no primeiro quadro: as outras
   deslizam para o lugar dela enquanto ela encolhe por cima, e os dois movimentos
   acontecem juntos.

   As coordenadas são escritas pelo JavaScript, que mede onde a pílula estava
   antes de tirá-la do fluxo — sem isso ela saltaria para o canto da caixa antes
   de começar a encolher. */
.pilula_de_categoria.pilula_reaparecendo {
	animation: entrada_de_pilula_em_zoom 0.35s ease backwards;
}

.pilula_de_categoria.pilula_saindo {
	position: absolute;
	z-index: 1;
	pointer-events: none;
	animation: saida_de_pilula_em_zoom 0.24s ease forwards;
}

@keyframes saida_de_pilula_em_zoom {
	0% {
		opacity: 1;
		transform: scale(1);
	}
	100% {
		opacity: 0;
		transform: scale(0.55);
	}
}

@media (prefers-reduced-motion: reduce) {
	.pilula_de_categoria.pilula_reaparecendo,
	.pilula_de_categoria.pilula_saindo {
		animation: none;
	}
}

/* A trilha não rola em largura nenhuma: quem não cabe sai, não se esconde atrás de
   um arrasto. E o conjunto todo — categorias mais a pílula "Ver mais" — procura o
   centro, tanto na fila quanto dentro da caixa aberta.

   O overflow escondido e a transição de altura são o que fazem a caixa crescer
   empurrando os cartões com gentileza, em vez de saltar de uma vez. Quem escreve o
   max-height em pixels é o JavaScript: uma altura "auto" não tem como ser
   interpolada, então ele mede o antes e o depois e deixa o navegador percorrer o
   caminho. A sombra da caixa não é cortada por isso — overflow recorta o conteúdo
   de dentro, nunca a sombra do próprio elemento. */
.trilha_rolavel_de_pilulas {
	overflow: hidden;
	justify-content: center;

	/* SÃO DUAS ANIMAÇÕES DE TAMANHO, E ELAS NÃO SE CONFUNDEM.
	   `max-height` é a da CAIXA que se abre pelo botão de filtros, escrita pelo
	   JavaScript quando o painel expande. `height` é a da FILA quando ela ganha ou
	   perde uma fileira, ao escolher uma categoria de nome longo no celular.
	   Precisam conviver na mesma declaração: esta regra vem depois da que define a
	   trilha lá em cima e venceria sozinha, apagando a segunda transição. */
	transition:
		max-height 0.4s cubic-bezier(0.25, 1, 0.5, 1),
		padding 0.4s cubic-bezier(0.25, 1, 0.5, 1),
		height 0.35s ease;
}

/* ABERTO: a caixa envolve as pílulas que já estavam à mostra e as demais quebram
   em linhas abaixo. O alinhamento não se repete aqui porque o centro já vem da
   regra geral da trilha — fila e caixa usam o mesmo, então nada salta de lugar
   na hora de abrir. */
.secao_de_pilulas_de_categorias.painel_de_categorias_aberto
	.trilha_rolavel_de_pilulas {
	flex-wrap: wrap;
	white-space: normal;
	/* Segue recortando de propósito: é o recorte que revela as fileiras aos poucos,
	   conforme a altura cresce. Com overflow visível, todas apareceriam de imediato
	   e a animação de crescimento perderia a graça. */
	overflow: hidden;
	background-color: var(--cor_de_superficie);
	border-radius: 16px;
	border: 1px solid #f1f2f6;
	box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12);
	padding: 16px;
	row-gap: 10px;
}

/* O formato visual da Pílula */
.pilula_de_categoria {
	/* O creme virou token em 2026-08-12 (D5): a marcação de categorias do painel
	   usa o mesmo par claro/forte desta pílula, e um segundo `#ffe7be` escrito à
	   mão seria a cópia que envelhece sozinha. */
	background-color: var(--cor_de_atencao_clara);
	border: 0px solid #e0e0e0;
	color: var(--cor_de_atencao); /* 8d8a7f */
	padding: 8px 20px;
	border-radius: 7px; /* Arredondamento perfeito estilo pílula */
	font-size: 14px;
	font-weight: 500;
	cursor: pointer;
	transition: all 0.2s ease;
	flex-shrink: 0; /* Impede que o navegador esmague as pílulas */
	outline: none;
}

/* O hover aprofunda o próprio laranja da pílula, em vez de puxá-la para um cinza
   que sumia contra o fundo claro. O texto escurece junto para o contraste subir. */
.pilula_de_categoria:hover {
	background-color: #ffd79a;
	color: #d9820a;
}

/* ==============================================================================
   A PÍLULA DE FAVORITOS

   Ela faz o mesmo que as categorias — recorta a vitrine —, mas por um critério
   que é da pessoa e não do catálogo: o que ela marcou no coração. Por isso veste
   o VERMELHO do coração em vez do laranja das outras. Numa fila de pílulas
   iguais, a cor é o que diz, antes de qualquer leitura, que aquela ali responde a
   outra pergunta.

   Apagada, ela é vazada: fundo vermelho bem claro, traço e texto no vermelho
   cheio. Acesa, inverte para vermelho sólido com texto branco — a mesma gramática
   das categorias, que também invertem ao acender.

   ELA ENTRA E SAI POR DESVANECIMENTO, e é por isso que o estado recolhido não
   usa `display: none`: `display` não tem valores intermediários, e a pílula
   piscaria para dentro e para fora da fila. Recolhida, ela fica sem largura, sem
   recheio e transparente — as vizinhas se fecham sobre o lugar dela com o mesmo
   movimento com que se abriram depois.
============================================================================== */
.pilula_de_favoritos {
	background-color: var(--cor_de_alerta_clara);
	border: 1px solid var(--cor_de_alerta);
	color: var(--cor_de_alerta);

	/* O traço acrescenta 2px à altura; o recheio encolhe para compensar e a
	   pílula continuar na mesma linha das vizinhas, que não têm borda. */
	padding: 7px 19px;

	overflow: hidden;
	white-space: nowrap;
	max-width: 220px;

	/* A entrada e a saída não são a cascata das outras: quando a página carrega
	   com favoritos, esta espera a fila inteira se formar; quando o cliente
	   favorita o primeiro item, ela surge sozinha numa trilha já parada. Quem
	   comanda os dois momentos é o JavaScript, tirando a classe de recolhida. */
	animation: none;
	transition:
		opacity 0.35s ease,
		max-width 0.35s ease,
		padding 0.35s ease,
		margin 0.35s ease,
		transform 0.35s ease,
		background-color 0.2s ease,
		color 0.2s ease;
}

.pilula_de_favoritos:hover {
	background-color: #fbd5d1;
	color: var(--cor_de_alerta);
}

.pilula_de_favoritos.pilula_ativa,
.pilula_de_favoritos.pilula_ativa:hover {
	background-color: var(--cor_de_alerta);
	border-color: var(--cor_de_alerta);
	color: var(--cor_de_texto_sobre_cor);
	font-weight: 600;
}

.pilula_de_favoritos.estado_de_pilula_de_favoritos_recolhida {
	max-width: 0;
	padding-left: 0;
	padding-right: 0;
	margin-left: 0;
	margin-right: 0;
	border-width: 0;
	opacity: 0;
	transform: scale(0.7);
	pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
	.pilula_de_favoritos {
		transition:
			background-color 0.2s ease,
			color 0.2s ease;
	}
}

/* O espaço entre o coração e a palavra. Fica na margem do rótulo, e não num
   caractere de espaço no HTML, porque em tela estreita a palavra some — e um
   espaço escrito à mão sobraria ali, desalinhando o coração dentro da pílula. */
.rotulo_de_pilula_de_favoritos {
	margin-left: 6px;
}

/* ==============================================================================
   EM TELA ESTREITA, OS RÓTULOS ENCOLHEM ATÉ O SÍMBOLO

   A trilha é uma fila horizontal com rolagem, e no celular ela é o gargalo da
   tela: cada palavra a mais empurra uma categoria para dentro da caixa do "+N".

   O CORAÇÃO E O CIFRÃO SE EXPLICAM SOZINHOS onde a palavra não cabe — são os dois
   símbolos que ninguém precisa aprender. As demais pílulas mantêm o texto porque
   nome de categoria não tem símbolo equivalente: "Castanhas" só se diz escrevendo.

   O `aria-label` do botão de favoritos carrega a frase inteira, então quem usa
   leitor de tela continua ouvindo "ver só os seus favoritos" — o encolhimento é
   visual, e não some com a informação.
============================================================================== */
@media (max-width: 767px) {
	.rotulo_de_pilula_de_favoritos {
		display: none;
	}

	/* Sem a palavra, o recheio lateral encolhe junto: um coração sozinho dentro do
	   espaçamento de uma palavra pareceria perdido no meio da pílula. */
	.pilula_de_favoritos {
		padding-left: 12px;
		padding-right: 12px;
	}

	.rotulo_longo_de_ordenacao_de_preco {
		display: none;
	}
}

/* Na tela larga sobra espaço, e a palavra diz melhor que o símbolo: "Preço" não
   deixa dúvida sobre o que está sendo ordenado, enquanto o cifrão sozinho pede
   um instante de interpretação. */
@media (min-width: 768px) {
	.rotulo_curto_de_ordenacao_de_preco {
		display: none;
	}
}

/* A pílula acesa já é laranja cheia, então o hover dela escurece um tom */
.pilula_de_categoria.pilula_ativa:hover {
	background-color: #e08e0b;
	color: var(--cor_de_texto_sobre_cor);
}

/* A pílula que está ativa (A categoria que o cliente está vendo) */
.pilula_ativa {
	background-color: var(--cor_de_atencao); /* Verde de Conversão: 27ae60 */
	color: var(--cor_de_texto_sobre_cor);
	border-color: var(--cor_de_conversao);
	/*	box-shadow: 0 3px 8px rgba(39, 174, 96, 0.3); /* Brilho sutil */
	font-weight: 600;
}

/* ==============================================================================
   BLOCOS DE ENGAJAMENTO (A QUEBRA DE PADRÃO VISUAL)
============================================================================== */

.cartao_de_engajamento {
	border-radius: var(--raio_de_canto_de_cartao);
	padding: 30px 20px;
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	text-align: center;
	box-shadow: var(--sombra_de_cartao);
	transition:
		transform 0.3s ease,
		box-shadow 0.3s ease;
	position: relative;
	overflow: hidden;
	cursor: pointer;
	min-height: 280px; /* Garante que fiquem imponentes no meio da alvenaria */
	/* A cor de fundo e a cor de texto já vêm dinamicamente do PHP */

	/* O RESPIRO QUE FALTAVA.

	   O bloco dinâmico é um tijolo da mesma alvenaria que os produtos, mas era o
	   único sem margem embaixo: o rodapé dele encostava no topo do cartão de
	   produto seguinte, e os dois liam como um bloco só. Os 15px são exatamente
	   os mesmos do .cartao_de_produto — é o que faz a coluna ter um ritmo, e não
	   dois espaçamentos diferentes conforme o tijolo. */
	margin-bottom: 15px;

	/* As três linhas de `break-inside: avoid` saíram daqui junto com as do
	   .cartao_de_produto, em 2026-08-10: elas evitavam o fatiamento entre colunas
	   do `column-count`, e no grid não há fatiamento nenhum a evitar. */
}

/* O Efeito de Levitação Magnética (Microinteração) */
.cartao_de_engajamento:hover {
	transform: translateY(-6px);
	box-shadow: var(--sombra_de_cartao_elevado);
}

/* ==============================================================================
   O TIJOLO COM IMAGEM DE FUNDO (2026-08-10)

   A imagem em si vem do PHP, no atributo `style`, porque o caminho é dado do
   banco. O que fica aqui é só o que NÃO varia de bloco para bloco — e é por isso
   que existe uma classe em vez de mais três propriedades repetidas dentro de cada
   `style` inline.

   A MESMA CLASSE SERVE À FRENTE E AO VERSO. São dois elementos diferentes
   (`.cartao_de_engajamento` e `.conteudo_de_verso_de_bloco`), e as três regras
   valem igual nos dois: cobrir, centralizar e não repetir.

   `cover` E NÃO `contain`: o tijolo é alto e estreito, e `contain` deixaria duas
   faixas da cor de fundo em cima e embaixo de toda foto horizontal — que é o
   formato de quase toda foto. Cortar a imagem é o preço de ela preencher o
   tijolo, e o véu que o PHP aplica por cima já assume que o miolo é o que
   interessa.

   O VÉU NÃO ESTÁ AQUI, e é de propósito: ele é uma camada de `linear-gradient`
   dentro do mesmo `background-image`, montada no PHP porque a cor dele sai da cor
   declarada para aquele bloco. Escrevê-lo aqui exigiria uma cor fixa, e uma cor
   fixa apaga o texto de metade dos blocos.
============================================================================== */

.bloco_com_imagem_de_fundo {
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
}

.conteudo_frontal_de_bloco {
	z-index: 2;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	height: 100%;
	width: 100%;
}

.titulo_de_bloco_dinamico {
	font-size: 22px;
	font-weight: 800;
	margin-top: 0;
	margin-bottom: 12px;
	line-height: 1.2;
}

.texto_de_bloco_dinamico {
	font-size: 15px;
	line-height: 1.5;
	margin-bottom: 20px;
	opacity: 0.9;
}

/* ==========================================================================
   O CRÉDITO DA VERSÃO DA BÍBLIA (v9_34, 2026-08-10)

   Só aparece no bloco cujo versículo veio DO BANCO — o texto copiado à mão não
   tem procedência conhecida, e o PHP nem desenha o elemento nesse caso.

   ELE É OBRIGATÓRIO, E É POR ISSO QUE ELE É PEQUENO. A Bíblia Livre é publicada
   sob CC BY 3.0 BR, e a atribuição é a condição de uso — não dá para escondê-la
   com `display: none` num dia de faxina de CSS sem descumprir a licença. O que
   se pode fazer é o que está aqui: tamanho de letra de rodapé e opacidade baixa,
   para ela caber sem competir com o versículo, que é o que a pessoa parou para
   ler.

   `margin-top: auto` EMPURRA O CRÉDITO PARA O PÉ DO TIJOLO, e não é enfeite: o
   cartão é um flex de coluna centralizado, e sem isso a licença ficaria colada na
   referência, lida como parte dela. O `auto` só age quando sobra altura — num
   tijolo apertado o crédito simplesmente segue o texto, que é o comportamento
   certo.

   ⚠️ O CONVITE "✨ Interaja comigo" TAMBÉM USA `margin-top: auto`. Quando os dois
   existem no mesmo tijolo (um versículo que gira, por exemplo), o primeiro come a
   folga e o segundo fica logo abaixo dele — que é a ordem certa, porque o convite
   é o último elemento do HTML.
   ========================================================================== */
.credito_de_versao_de_biblia {
	margin-top: auto;
	margin-bottom: 0;
	padding-top: 10px;

	font-size: 11px;
	line-height: 1.35;
	font-weight: 500;
	opacity: 0.65;
}

/* ==========================================================================
   A VIRADA DO BLOCO (item 1.14, 2026-08-10)

   A ação "Girar para o Verso" existe na tabela de domínio desde a v9_00 e nunca
   teve uma linha de código atrás dela: o bloco desenhava "✨ Interaja comigo" e
   não respondia a clique nenhum.

   NÃO É UMA VIRADA 3D DE VERDADE, e a escolha é deliberada. O jeito canônico
   (`transform-style: preserve-3d` com duas faces em `backface-visibility:
   hidden`) exige três níveis de elemento — cena, carta e faces — e o bloco só
   tem dois. Pior: `preserve-3d` e `overflow: hidden` se anulam, e o
   `overflow: hidden` daqui é o que segura a imagem de fundo dentro do canto
   arredondado.

   O QUE FAZEMOS: o tijolo inteiro gira meia volta, e o conteúdo troca no meio do
   caminho. O verso vem contra-rotacionado em 180 graus para o texto dele não
   sair espelhado; a frente fica espelhada no fim do giro, e não se vê, porque a
   essa altura ela já é invisível. O olho lê exatamente a mesma coisa que leria
   numa carta de verdade, com um terço do código.

   O VERSO É ABSOLUTO, e é isso que impede o salto de layout. Se ele entrasse no
   fluxo, um verso mais alto do que a frente esticaria o tijolo no meio da
   animação, e a alvenaria inteira daquela coluna se reorganizaria embaixo dele.
   Assim o tijolo mantém a altura da frente do começo ao fim.

   O ESCALONAMENTO DAS TRANSIÇÕES É O TRUQUE INTEIRO: a rotação leva 0,6s e a
   troca de opacidade leva 0,15s começando aos 0,3s — ou seja, exatamente quando
   o tijolo está de perfil e nada se lê. Trocar antes mostraria as duas faces
   sobrepostas; trocar depois mostraria a frente espelhada.
   ========================================================================== */
.cartao_de_engajamento.acao_de_bloco_2,
.cartao_de_engajamento.acao_de_bloco_6 {
	transition:
		transform 0.6s ease,
		box-shadow 0.3s ease;
}

.cartao_de_engajamento.bloco_de_engajamento_virado {
	transform: rotateY(180deg);
}

/* A levitação do `:hover` some enquanto o bloco está virado: as duas escrevem no
   mesmo `transform`, e a última a ganhar apagaria a outra. Virado, o gesto que
   importa é o giro. */
.cartao_de_engajamento.bloco_de_engajamento_virado:hover {
	transform: rotateY(180deg);
}

.conteudo_de_verso_de_bloco {
	position: absolute;
	inset: 0;
	z-index: 3;

	display: flex;
	align-items: center;
	justify-content: center;
	padding: 30px 20px;

	border-radius: var(--raio_de_canto_de_cartao);
	transform: rotateY(180deg);

	opacity: 0;
	pointer-events: none;
	transition: opacity 0.15s ease 0s;

	/* Verso mais comprido do que a frente rola dentro do próprio tijolo, em vez
	   de vazar por baixo do canto arredondado. */
	overflow-y: auto;
}

.bloco_de_engajamento_virado .conteudo_de_verso_de_bloco {
	opacity: 1;
	pointer-events: auto;
	transition: opacity 0.15s ease 0.3s;
}

.bloco_de_engajamento_virado .conteudo_frontal_de_bloco {
	opacity: 0;
	transition: opacity 0.15s ease 0.3s;
}

.conteudo_frontal_de_bloco {
	transition: opacity 0.15s ease 0s;
}

.texto_de_verso_de_bloco {
	margin: 0;
	font-size: 16px;
	line-height: 1.5;
	font-weight: 600;
}

/* ==========================================================================
   O ENIGMA (item 1.14b)

   O CAMPO É O CONVITE. Nos outros blocos interativos a pílula "✨ Interaja
   comigo" avisa que ali se toca; aqui ela não aparece, porque um campo de
   digitação com um botão ao lado já diz o que fazer — e diria duas vezes num
   tijolo que não tem altura sobrando.

   AS CORES SÃO TRANSLÚCIDAS, e não tokens da paleta. A cor de fundo de cada
   bloco vem do banco e muda de linha para linha: um campo branco fixo ficaria
   ótimo no versículo amarelo e sujo no alerta verde. Com branco a 55% sobre o
   fundo do próprio bloco, o campo é sempre um pouco mais claro do que o tijolo
   em que está — qualquer que seja o tijolo. É o mesmo raciocínio do vidro fosco
   da pílula de interação, logo acima.
   ========================================================================== */
.area_de_enigma_de_bloco {
	display: flex;
	gap: 6px;
	width: 100%;
	max-width: 260px;
	margin-top: auto;
}

.campo_de_resposta_de_enigma {
	flex: 1;
	min-width: 0;

	padding: 9px 12px;
	border: 1px solid rgba(255, 255, 255, 0.6);
	border-radius: 20px;
	background-color: rgba(255, 255, 255, 0.55);

	font-family: inherit;
	/* ⚠️ 16px PELA MESMA RAZÃO DO `.campo_de_quantidade` — o zoom automático do iOS, e o
	   porquê inteiro está escrito lá. Este é o campo mais fácil de esquecer dos três: ele
	   só existe nos blocos de engajamento do tipo enigma, e só quando há um cadastrado. */
	font-size: 16px;
	/* `color: inherit` faz o texto digitado herdar a cor de texto do bloco, que
	   veio do banco junto com a de fundo. Uma cor fixa aqui seria ilegível na
	   metade dos tijolos. */
	color: inherit;
}

.campo_de_resposta_de_enigma::placeholder {
	color: inherit;
	opacity: 0.6;
}

.campo_de_resposta_de_enigma:focus {
	outline: none;
	background-color: rgba(255, 255, 255, 0.85);
	border-color: rgba(255, 255, 255, 0.95);
}

.botao_de_resposta_de_enigma {
	padding: 9px 14px;
	border: 1px solid rgba(255, 255, 255, 0.5);
	border-radius: 20px;
	background-color: rgba(255, 255, 255, 0.4);

	font-family: inherit;
	font-size: 13px;
	font-weight: 700;
	color: inherit;
	cursor: pointer;

	backdrop-filter: blur(5px);
	-webkit-backdrop-filter: blur(5px);
	transition: background-color 0.2s ease;
}

.botao_de_resposta_de_enigma:hover {
	background-color: rgba(255, 255, 255, 0.7);
}

/* O CHACOALHÃO DA RESPOSTA ERRADA (decisão P18, 2026-08-10).

   Errar não custa nada: sem limite de tentativas, sem contador na tela, sem
   mensagem de derrota. O tijolo treme, o campo esvazia e continua ali. A vitrine
   é uma loja, não uma prova — quem errou está engajado, e punir é o oposto do que
   o bloco veio fazer.

   USA `translate` E NÃO `transform`, e por isso convive com o giro e com a
   levitação do `:hover` em vez de apagá-los — é a mesma razão registrada nos
   gestos da torrada, em `fundacao.css`. E é o MESMO `@keyframes` de lá: o gesto
   é da recusa, e não do componente que recusa. */
.cartao_de_engajamento.bloco_de_engajamento_com_erro {
	animation: chacoalhao_de_recusa 0.45s ease-in-out;
}

/* ==========================================================================
   A FAIXA RASPÁVEL (ação 5, item 1.14a — 2026-08-10)

   ⚠️ O GESTO NÃO MORA MAIS NO ARQUIVO DE BLOCOS — ele saiu para
   `_drive/javascript/motor_de_raspadinha.js` em 2026-09-03, porque a página
   `/modeladas/tesouro` precisa dele e não pode carregar esta folha de 151 KB.

   ESTAS SETE REGRAS FICARAM AQUI, e a segunda cópia delas está em
   `_drive/css/modeladas.css`. É duplicação consciente, e a régua do CLAUDE.md
   ("Unificar às vezes é o caminho errado") explica: as duas telas querem
   dimensões diferentes — aqui é uma tirinha de 280 por 96 dentro de um tijolo de
   vitrine, lá é uma foto inteira —, e um arquivo compartilhado custaria um
   `<link>` a mais em TODA visita à loja para economizar 108 linhas.

   ⚠️⚠️ O QUE AS DUAS CÓPIAS PRECISAM TER IGUAL SÃO TRÊS PROPRIEDADES, e nenhuma
   delas é de aparência: `position: relative` no envoltório,
   `position: absolute; inset: 0` no canvas, e o `touch-action: none`. Mexer numa
   dessas três aqui sem mexer lá quebra o gesto de um lado só.

   O prêmio é texto de verdade no HTML, e o canvas é uma cobertura POR CIMA dele.
   O contrário — desenhar o prêmio dentro do canvas — pareceria igual na tela e
   custaria o leitor de tela, a seleção do texto e a quebra de linha automática,
   tudo para economizar um `position: absolute`.

   ⚠️ `touch-action: none` NO CANVAS É O QUE FAZ A RASPADINHA EXISTIR NO CELULAR.
   Raspar é arrastar o dedo, e arrastar o dedo é rolar a página: sem esta linha o
   navegador leva o gesto para a rolagem, o `pointermove` para de chegar no
   primeiro milímetro, e a faixa fica intacta com o cliente achando que travou.
   Ela é a razão de a faixa ser um pedaço do tijolo e não o tijolo inteiro — um
   cartão inteiro que recusa rolagem, no meio de uma lista de produtos, é uma
   armadilha.

   O BOTÃO SOBE PARA CIMA DO CANVAS com `z-index`, e é de propósito: ele fica
   visível e clicável sobre a faixa ainda coberta, porque é a porta de quem navega
   por teclado, de quem usa leitor de tela e de quem raspou 40% e cansou. Um botão
   que só aparecesse depois de revelar não serviria a nenhum dos três.
   ========================================================================== */
.area_de_raspadinha_de_bloco {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 8px;

	width: 100%;
	max-width: 280px;
	min-height: 96px;
	margin-top: auto;
	padding: 14px 12px 10px;

	border-radius: 14px;
	/* O `overflow: hidden` recorta o canvas no canto arredondado. Sem ele a faixa
	   cinza vaza quatro quinas quadradas para fora do desenho do tijolo. */
	overflow: hidden;
}

/* ==============================================================================
   A FOTO ATRÁS DA FAIXA (2026-09-04)

   Camada de fundo abaixo do canvas e do botão, e não o fundo da área: a área é o
   pai posicionado dos dois, e um fundo nela ficaria por cima de ninguém mas
   embaixo de tudo — inclusive do véu de cor, que apagaria o texto do prêmio.

   `z-index: 0` com o canvas em 1 e o botão em 2 é o que mantém a ordem das três
   camadas explícita, em vez de depender da ordem do HTML.
   ============================================================================== */
/* ⚠️ O DIMENSIONAMENTO NÃO VEM DE GRAÇA COM A IMAGEM. `montar_estilo_de_imagem_de_fundo()`
   escreve só o `background-image` — quem enquadra é `.bloco_com_imagem_de_fundo`, e a
   primeira versão desta camada não a vestia. O resultado não é erro nenhum: a foto entra
   em tamanho natural, e uma imagem de 1254px numa faixa de 273 mostra um canto ampliado
   que parece uma textura escolhida de propósito. */
.foto_de_verso_de_raspadinha {
	position: absolute;
	inset: 0;
	z-index: 0;
	border-radius: inherit;

	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
}

/* Com foto atrás, o prêmio precisa de contraste próprio: a cor de texto do bloco
   foi escolhida contra a cor de FUNDO dele, e não contra uma fotografia. */
.area_de_raspadinha_com_foto .texto_de_premio_de_raspadinha {
	position: relative;
	z-index: 1;
	color: #ffffff;
	text-shadow: 0 1px 4px rgba(0, 0, 0, 0.75);
}

.texto_de_premio_de_raspadinha {
	margin: 0;
	font-size: 17px;
	line-height: 1.35;
	font-weight: 800;
	text-align: center;
	/* `color: inherit` pela mesma razão do campo do enigma: a cor de texto do
	   bloco vem do banco e muda de linha para linha. */
	color: inherit;
}

/* ==============================================================================
   O PRÊMIO NÃO APARECE ANTES DA FAIXA — A MESMA JANELA DA PÁGINA DE CAMPANHA

   O canvas nasce transparente e os blocos são posicionados por JavaScript depois
   da grade montar. Entre o primeiro quadro e a pintura da cobertura, o texto do
   prêmio fica legível — e numa vitrine com vários blocos isso vale para todos de
   uma vez.

   O mecanismo é o mesmo do `/modeladas/tesouro`, e vive num lugar só: o motor
   escreve `cobertura_pronta` no pai quando a faixa de fato existe. Aqui o que
   muda é O QUE se esconde — lá uma foto, aqui o texto e a foto de fundo.

   ⚠️ `visibility` E NÃO `opacity`, ao contrário da página de campanha, e a
   diferença é deliberada: lá o `alt` da foto É o prêmio para quem usa leitor de
   tela, e `opacity` o preserva na árvore. Aqui o prêmio é texto que continua no
   HTML — e o leitor de tela o lê ANTES de qualquer JavaScript rodar, então a
   brincadeira nunca foi para ele. Esconder de quem enxerga não tira nada de quem
   não enxerga.

   O guarda `pagina_com_javascript` é escrito pelo `<head>` da vitrine: sem
   JavaScript nenhuma faixa é pintada, e aí o prêmio TEM de aparecer — a
   alternativa é um bloco permanentemente vazio.
   ============================================================================== */
.pagina_com_javascript .area_de_raspadinha_de_bloco .texto_de_premio_de_raspadinha,
.pagina_com_javascript .area_de_raspadinha_de_bloco .foto_de_verso_de_raspadinha {
	visibility: hidden;
}

.pagina_com_javascript
	.area_de_raspadinha_de_bloco.cobertura_pronta
	.texto_de_premio_de_raspadinha,
.pagina_com_javascript
	.area_de_raspadinha_de_bloco.cobertura_pronta
	.foto_de_verso_de_raspadinha {
	visibility: visible;
}

.camada_de_raspadinha {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	z-index: 1;

	touch-action: none;
	cursor: crosshair;
	/* A saída da cobertura é uma dissolução curta, e não um corte seco: o corte
	   faz o prêmio "piscar" na tela, e a dissolução deixa claro que foi o gesto do
	   cliente que tirou a faixa dali. */
	transition: opacity 0.35s ease;
}

/* O canvas some do caminho DEPOIS de revelado — `pointer-events: none` é o que
   devolve ao cartão o clique na área da faixa, e `opacity` é o que faz a faixa
   sair sem levar junto o bitmap (apagar o canvas no JS obrigaria a repintá-lo do
   zero se a revelação fosse desfeita algum dia). */
.area_de_raspadinha_de_bloco.raspadinha_revelada .camada_de_raspadinha {
	opacity: 0;
	pointer-events: none;
}

.botao_de_revelar_raspadinha {
	position: relative;
	z-index: 2;

	padding: 5px 12px;
	border: 1px solid rgba(255, 255, 255, 0.5);
	border-radius: 20px;
	background-color: rgba(255, 255, 255, 0.4);

	font-family: inherit;
	font-size: 11px;
	font-weight: 700;
	color: inherit;
	cursor: pointer;

	backdrop-filter: blur(5px);
	-webkit-backdrop-filter: blur(5px);
	transition:
		background-color 0.2s ease,
		opacity 0.3s ease;
}

.botao_de_revelar_raspadinha:hover {
	background-color: rgba(255, 255, 255, 0.7);
}

/* Revelado, o botão não tem mais o que fazer. Ele sai por `display: none` e não
   por `visibility`, para o prêmio recuperar a altura que ele ocupava — num tijolo
   de 220px, doze pixels de botão morto são uma linha de texto a menos. */
.area_de_raspadinha_de_bloco.raspadinha_revelada .botao_de_revelar_raspadinha {
	display: none;
}

/* ==========================================================================
   A FRASE SOLTA (item 1.6)

   "O mesmo mecanismo dos blocos dinâmicos, com conteúdo diferente" — e é
   literalmente isso: mesmo tijolo, mesma âncora, mesmo posicionador. O que muda
   é o desenho, e a mudança inteira cabe em não desenhar coisas.

   SEM ALTURA MÍNIMA, e essa é a diferença que importa. Os quatro tipos antigos
   têm altura cadastrada no banco (220 a 380) porque o desalinhamento entre eles
   é o que quebra a cegueira visual da grade. A frase solta quer o oposto: ser o
   tijolo baixo, de uma ou duas linhas, que passa quase despercebido entre dois
   produtos. Um `min-height: 280px` herdado a transformaria num bloco comum com
   pouco texto dentro e muito ar em volta.

   SEM TÍTULO E SEM CONVITE A INTERAGIR — os dois são omitidos já no PHP. E a
   sombra sai junto: o que faz a frase parecer solta é ela não parecer um cartão.
   ========================================================================== */
.cartao_de_engajamento.tipo_de_bloco_5 {
	min-height: 0;
	padding: 16px 18px;
	box-shadow: none;
}

/* Sem sombra, a levitação do `:hover` fica sem sentido: o tijolo subiria seis
   pixels sem nada embaixo que explicasse a subida. */
.cartao_de_engajamento.tipo_de_bloco_5:hover {
	transform: none;
	box-shadow: none;
}

.texto_de_frase_solta {
	margin: 0;
	font-size: 15px;
	line-height: 1.45;
	font-style: italic;
	font-weight: 600;
	opacity: 0.9;
}

/* Quem pediu menos movimento ao sistema operacional continua vendo o verso e
   continua sabendo que errou — o que some é a dança. Mesma regra dos gestos da
   torrada. */
@media (prefers-reduced-motion: reduce) {
	.cartao_de_engajamento.acao_de_bloco_2,
	.cartao_de_engajamento.acao_de_bloco_6,
	.conteudo_de_verso_de_bloco,
	.conteudo_frontal_de_bloco {
		transition: none;
	}

	.cartao_de_engajamento.bloco_de_engajamento_virado,
	.cartao_de_engajamento.bloco_de_engajamento_virado:hover {
		transform: none;
	}

	/* Sem o giro, o verso não pode continuar contra-rotacionado: ele apareceria
	   espelhado, que é o único desfecho pior do que não animar. */
	.conteudo_de_verso_de_bloco {
		transform: none;
	}

	.cartao_de_engajamento.bloco_de_engajamento_com_erro {
		animation: none;
	}
}

/* A pílula translúcida que convida ao clique */
.indicador_de_interacao_de_bloco {
	margin-top: auto;
	background-color: rgba(255, 255, 255, 0.4);
	padding: 8px 18px;
	border-radius: 20px;
	font-size: 13px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 1px;
	border: 1px solid rgba(255, 255, 255, 0.5);
	/* O famoso Efeito Vidro Fosco (Glassmorphism) */
	backdrop-filter: blur(5px);
	-webkit-backdrop-filter: blur(5px);
}

/* ==============================================================================
   EFEITO ALVENARIA (MASONRY): DESALINHAMENTO
==============================================================================
   AQUI HAVIA `#grade_de_produtos { align-items: start; }`, com o comentário
   "corta a mola da grade para que os itens não estiquem". Ele estava certo na
   intenção e inerte na prática: enquanto a vitrine foi `column-count`, o
   `align-items` não fazia nada — é propriedade de flex e de grid, e multi-coluna
   não é nenhum dos dois. Era código do futuro, escrito antes do futuro chegar.

   Em 2026-08-10 o futuro chegou, e a linha passou a viver onde manda:
   `.recipiente_de_vitrine`, junto do resto da declaração do grid. Deixá-la aqui
   também seria a mesma propriedade com o mesmo valor declarada duas vezes, com
   um seletor de id vencendo por especificidade — a primeira viraria código
   morto que continua parecendo vivo.

   O QUE ELA FAZ, e por que não é opcional: sem `start`, o tijolo estica até
   preencher as N linhas que o span reservou, e essas N linhas já incluem os
   15px de margem inferior. O cartão engordaria exatamente a margem, e ganharia
   outra margem embaixo — o ritmo da grade sairia dobrado.
============================================================================== */

/* ==============================================================================
   MÁGICA TITANIUM: EMPILHAMENTO MAGNÉTICO (COMPUTADOR)
============================================================================== */
@media (min-width: 769px) {
	/* QUEM FIXA É O GRUPO, NÃO CADA PEÇA.
	   Aqui a barra e a trilha eram sticky por conta própria, com top: 70px e
	   top: 140px escritos à mão. Como as duas agora moram dentro do
	   .grupo_fixo_de_busca_e_filtros, que já é sticky na altura medida do cabeçalho,
	   sobravam dois sistemas de fixação disputando a mesma rolagem — e os números
	   fixos quebravam assim que o cabeçalho mudava de altura. Ficou só o efeito
	   visual; o encaixe é responsabilidade do grupo. */

	/* 1. A Barra de Pesquisa */
	.bloco_de_pesquisa {
		/* O EFEITO VIDRO FOSCO: Mantém a leveza, mas blinda a leitura! */
		background-color: rgba(
			244,
			247,
			246,
			0.1
		); /* Transparente, mas puxando pra cor do fundo */
		/*		backdrop-filter: blur(70px);
		-webkit-backdrop-filter: blur(70px); /* */

		border-bottom: 0px solid rgba(0, 0, 0, 0.05); /* Uma linha sutil para separar */
	}

	/* 2. As Pílulas de Categoria */
	.secao_de_pilulas_de_categorias {
		/* O mesmo Efeito Vidro para as pílulas */
		background-color: rgba(244, 247, 246, 0.1);
		/*		backdrop-filter: blur(70px);
		-webkit-backdrop-filter: blur(70px); /* */

		padding-top: 10px;
		padding-bottom: 10px;
		border-bottom: 0px solid rgba(0, 0, 0, 0.05);
	}
}

/* ==============================================================================
   MÁGICA TITANIUM: ANIMAÇÃO INVERSA DO RODAPÉ (FOCO NO MENU)
============================================================================== */

/* 1. Quando o menu abre, elevamos a base toda para o Hambúrguer reinar */
.base_flutuante_de_tela_estreita.estado_de_menu_aberto {
	z-index: 10006;
}

/* 2. Ocultamos os outros botões com um zoom-out (efeito Apple) */
.base_flutuante_de_tela_estreita.estado_de_menu_aberto
	#botao_de_pesquisa_de_rodape,
.base_flutuante_de_tela_estreita.estado_de_menu_aberto a.bloquinho_flutuante,
.base_flutuante_de_tela_estreita.estado_de_menu_aberto
	.pilula_de_carrinho_flutuante {
	opacity: 0;
	transform: scale(0); /* Encolhe até sumir */
	pointer-events: none; /* Desativa o clique de fantasmas */
}

/* ==============================================================================
   MÁGICA TITANIUM: O PAINEL EXPANDIDO DE CATEGORIAS E FILTROS (CELULAR)
============================================================================== */

@media (max-width: 768px) {
	/* 1. A trilha fica SEMPRE à mostra, igual à tela larga, rolando na horizontal.
	   Antes ela nascia com display: none e só existia dentro do botão 🎛️. */
	.secao_de_pilulas_de_categorias {
		position: relative; /* Mantém no fluxo para empurrar os produtos gentilmente para baixo */
		z-index: 50; /* Acima dos cartões, bem abaixo do menu e do rodapé flutuante */
		padding: 0 20px;
		margin-top: 10px; /* Cola a trilha bem perto da barra de pesquisa */
	}

	/* AS DUAS REGRAS ABAIXO VALEM SÓ COM A BARRA CONVOCADA PELA LUPA.
	   No topo, na posição padrão, o celular se comporta igual ao computador: a
	   trilha com a pílula "Ver mais" na ponta, tratada pelas regras gerais lá em
	   cima. Este é o outro caso — o cliente rolou para baixo, chamou a barra pela
	   lupa e abriu os filtros pelo 🎛️. Aqui a trilha nasce escondida, então o
	   painel precisa devolvê-la à tela, e as pílulas aparecem centradas como os
	   seletores de gramatura, porque não há fila anterior a preservar. */

	/* 2. O Gatilho de Abertura (Será acionado pelo JavaScript) */
	.grupo_de_busca_convocado
		.secao_de_pilulas_de_categorias.painel_de_categorias_aberto {
		display: block;
		animation: animacao_de_surgimento_de_painel 0.3s
			cubic-bezier(0.25, 1, 0.5, 1) forwards;
	}

	/* 3. A Morfose: Transforma a trilha rolável em uma caixa de cantos arredondados */
	.grupo_de_busca_convocado
		.secao_de_pilulas_de_categorias.painel_de_categorias_aberto
		#painel_de_categorias_flutuante {
		display: flex;
		flex-wrap: wrap; /* A MÁGICA: Quebra a linha automaticamente respeitando a tela! */
		justify-content: center; /* Pílulas centradas, como os seletores de gramatura */
		white-space: normal;
		background-color: var(--cor_de_superficie);
		border-radius: 16px;
		padding: 20px;
		box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12); /* Sombra elegante de flutuação */
		gap: 10px;
		border: 1px solid #f1f2f6;

		/* Mata a barra de rolagem horizontal. A altura ninguém dita: a caixa cresce
		   sozinha conforme a quantidade de categorias quebra em novas linhas. */
		overflow-x: visible;
	}

	/* Com a barra convocada quem fecha é o 🎛️ ao lado do campo, então a pílula de
	   contagem não se repete dentro do painel. */
	.grupo_de_busca_convocado .pilula_de_contagem_de_categorias {
		display: none;
	}

	/* A animação Apple para o painel surgindo de baixo da pesquisa */
	@keyframes animacao_de_surgimento_de_painel {
		0% {
			opacity: 0;
			transform: translateY(-15px);
		}
		100% {
			opacity: 1;
			transform: translateY(0);
		}
	}

	/* A DESPEDIDA DA CAIXA (SÓ NA TELA ESTREITA)
	   Ela esmaece e encolhe um pouco antes de voltar a ser fila. Sem isto a caixa
	   trocava de forma no mesmo quadro, e o que era uma janela virava uma linha
	   sem transição nenhuma. O JavaScript retira a classe quando a animação
	   termina — se mudar a duração aqui, mude lá também. */
	.secao_de_pilulas_de_categorias.painel_de_categorias_saindo
		.trilha_rolavel_de_pilulas {
		animation: animacao_de_saida_de_painel 0.2s ease forwards;
	}

	@keyframes animacao_de_saida_de_painel {
		0% {
			opacity: 1;
			transform: scale(1);
		}
		100% {
			opacity: 0;
			transform: scale(0.94);
		}
	}

	/* De volta à fila, as pílulas reaparecem suavemente em vez de estalarem na tela */
	.secao_de_pilulas_de_categorias:not(.painel_de_categorias_aberto):not(
			.painel_de_categorias_saindo
		)
		.trilha_rolavel_de_pilulas {
		animation: animacao_de_retorno_de_fila 0.25s ease backwards;
	}

	@keyframes animacao_de_retorno_de_fila {
		0% {
			opacity: 0;
		}
		100% {
			opacity: 1;
		}
	}
}

/* ==============================================================================
   A JANELA FLUTUANTE DE CARRINHO — MONTADA PELO MOTOR_DE_VITRINE.JS

   Estas regras estavam escritas como `style="..."` dentro dos moldes de HTML do
   motor_de_vitrine.js. Saíram de lá em 2026-07-30 por quatro motivos concretos:

   1. Estilo inline não responde a consulta de mídia — `padding: 60px 20px` era
      60px em qualquer tela, do celular ao monitor.
   2. Estilo inline vence quase toda regra de arquivo, então ajustar qualquer
      um deles daqui exigia `!important`.
   3. As cores ali escritas escaparam da migração para os tokens da marca: havia
      #2c3e50 e #27ae60 escritos à mão, fora do alcance do :root.
   4. Viajavam de novo a cada montagem da lista, sem passar por cache nenhum.

   As classes-âncora que o JavaScript já usava para ACHAR os elementos
   (.linha_de_item_de_carrinho, .valor_de_subtotal_de_carrinho) agora também os
   DESENHAM — antes elas existiam sem uma única regra de estilo.
============================================================================== */

/* --- Os dois estados vazios da janela --- */
.aviso_de_carregamento_de_carrinho {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 60px 20px;
	color: #95a5a6;
	text-align: center;
}

.texto_de_carregamento_de_carrinho {
	font-size: 15px;
	font-weight: bold;
	color: var(--cor_de_texto_suave);
}

.aviso_de_carrinho_vazio {
	text-align: center;
	color: var(--cor_de_texto_suave);
	margin-top: 30px;
}

/* --- A linha de um item --- */
.linha_de_item_de_carrinho {
	display: flex;
	flex-direction: column;
	border-bottom: 1px solid #eee;
	padding: 15px 0;
	width: 100%;
	box-sizing: border-box;
	transition: all 0.3s ease;
}

.bloco_de_nome_de_item_de_carrinho {
	width: 100%;
	margin-bottom: 12px;
}

.texto_de_nome_de_item_de_carrinho {
	font-weight: bold;
	color: var(--cor_de_texto_principal);
	line-height: 1.3;
	font-size: 15px;
}

.etiquetas_de_restricao_de_item_de_carrinho {
	font-size: 11px;
	color: var(--cor_de_conversao);
	font-weight: bold;
	margin-top: 4px;
	letter-spacing: 0.5px;
}

/* --- Os dois selos que podem aparecer no item --- */
.selo_de_brinde_de_carrinho {
	background-color: #f5eef8;
	color: #8e44ad;
	border: 2px dashed #9b59b6;
	border-radius: 5px;
	padding: 2px 6px;
	font-size: 11px;
	font-weight: bold;
	white-space: nowrap;
	flex-shrink: 0;
}

.selo_de_promocao_de_carrinho {
	background-color: var(--cor_de_conversao_clara);
	color: var(--cor_de_conversao);
	border: 1px solid #2ecc71;
	border-radius: 5px;
	padding: 3px 6px;
	font-size: 11px;
	font-weight: bold;
	white-space: nowrap;
	flex-shrink: 0;
}

/* --- A faixa de controles, abaixo do nome --- */
.linha_de_controles_de_item_de_carrinho {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 10px;
	width: 100%;
}

.grupo_de_quantidade_de_carrinho {
	display: flex;
	align-items: center;
	gap: 8px;
}

/* A trilha de [-] [n] [+] aqui é mais compacta que a da vitrine: dentro da
   janela ela divide a linha com o subtotal e a lixeira. */
.controles_de_quantidade_em_janela_de_carrinho {
	margin: 0;
	width: 95px;
	height: 32px;
	padding: 2px;
	display: flex;
	justify-content: space-between;
	box-sizing: border-box;
	flex-shrink: 0;
}

.botao_de_alteracao_em_janela_de_carrinho {
	width: 28px;
	height: 28px;
	font-size: 16px;
	flex-shrink: 0;
}

/* ⚠️ 16px PELA MESMA RAZÃO DO `.campo_de_quantidade` — o zoom automático do iOS. O porquê
   inteiro está escrito lá, uma vez só.

   ⚠️⚠️ E O `min-width` É QUEM DE FATO SEGURA A LARGURA AQUI — o `width` sozinho NÃO segura,
   e isso foi medido na tela, não deduzido. O campo é filho de um contêiner `flex`, então o
   `width` vira apenas a base de cálculo e o navegador encolhe o que quiser em cima dela:
   com `width: 42px` declarado, o que renderizava eram 27px.

   E 27px é exatamente o tamanho de "100" nesta fonte — 26,70px medidos com `measureText`.
   Trezentos milésimos de pixel de folga não são folga: é um recorte esperando por um
   arredondamento, e ele só apareceria no dia em que alguém comprasse cem unidades de uma
   coisa. Os 34px dão a folga de verdade, e é o `min-width` que a torna inegociável.

   📌 A LARGURA ANTIGA ERA 35px, calculada para os 13px de fonte de antes. Trocar a fonte
   sem mexer nela teria consertado o zoom e criado o recorte no mesmo movimento — o tipo de
   troca que passa despercebida porque quase todo mundo leva uma ou duas unidades. */
.campo_de_quantidade_em_janela_de_carrinho {
	width: 42px;
	min-width: 34px;
	font-size: 16px;
	text-align: center;
	padding: 0;
	border: none;
	background: transparent;
	font-weight: bold;
	color: var(--cor_de_texto_principal);
}

/* --- O lado direito da linha: unidades, subtotal e lixeira --- */
.grupo_de_valores_de_item_de_carrinho {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 10px;
	margin-left: auto;
}

.resumo_de_unidades_de_carrinho {
	font-size: 11px;
	white-space: nowrap;
}

.texto_de_unidades_de_carrinho {
	color: var(--cor_de_borda_de_campo);
	font-weight: normal;
}

.valor_de_subtotal_de_carrinho {
	font-weight: bold;
	color: var(--cor_de_texto_principal);
	font-size: 15px;
	white-space: nowrap;
}

.bloco_de_remocao_de_item_de_carrinho {
	text-align: right;
	flex-shrink: 0;
}

.botao_de_remocao_de_item_de_carrinho {
	background: none;
	border: none;
	font-size: 18px;
	cursor: pointer;
	color: var(--cor_de_alerta);
	padding: 0;
}

/* ==============================================================================
   A PRATELEIRA INTELIGENTE — TAMBÉM MONTADA PELO JAVASCRIPT
============================================================================== */

/* A ÚNICA COR QUE NÃO PODE VIRAR REGRA FIXA: cada origem de recomendação tem a
   sua, decidida no banco e entregue pelo JavaScript. Em vez de manter o
   `style="color: ..."` inline, o valor entra por uma variável no elemento e a
   regra a consome. O `currentColor` de reserva vale para o caso de a origem
   chegar sem cor cadastrada. */
.etiqueta_de_origem_de_prateleira {
	font-size: 11px;
	font-weight: bold;
	color: var(--cor-de-etiqueta-de-origem, currentColor);
	margin-bottom: 8px;
	letter-spacing: 0.5px;
	text-transform: uppercase;
}

.texto_de_nome_de_prateleira {
	font-weight: bold;
	color: var(--cor_de_texto_principal);
	margin-bottom: 10px;
}

/* O PESO ESCRITO NO CARTÃO DO CARROSSEL (v9_18)

   Enquanto o favorito era do produto, um produto aparecia uma vez só aqui e o
   peso era dispensável. Agora o cliente pode guardar o pote de 100g e o de 500g:
   sem esta etiqueta, ele veria dois cartões com o mesmo nome e preços diferentes,
   sem nada que explicasse a diferença.

   Fica ao lado do preço, num cinza discreto — quem varre o carrossel procura o
   nome do produto, e o peso é o desempate de quem já achou o que queria. O
   `:empty` esconde a etiqueta sozinha se a resposta vier sem o campo, que é o que
   acontece por alguns minutos quando o servidor ainda está com o arquivo antigo. */
.selo_de_peso_de_item_salvo {
	margin-right: 6px;
	padding: 1px 6px;
	border-radius: 8px;
	background-color: var(--cor_de_superficie_suave);
	color: var(--cor_de_texto_suave);
	font-size: 11px;
	font-weight: 600;
}

.selo_de_peso_de_item_salvo:empty {
	display: none;
}

/* ==============================================================================
   O CORAÇÃO DE FAVORITAR, NA QUINA DO CARTÃO

   O estilo deste botão vivia escrito por extenso no atributo de estilo, dentro do
   PHP — foi o único que escapou da mudança dos estilos inline, porque aquela
   varredura olhou os moldes de HTML do JavaScript e este mora no molde do PHP.

   A CLASSE DE ESTADO existe porque o coração não é só um emoji trocado: ela
   permite que o CSS reaja ao "está favoritado" sem o JavaScript precisar
   escrever aparência. Hoje ela dá o realce; amanhã pode dar qualquer outra coisa
   sem que o JavaScript mude.
============================================================================== */

/* O CORAÇÃO PERDEU A MOEDA BRANCA ATRÁS DELE.
   O disco existia para o emoji ter contraste contra a foto do produto, e cobrava
   caro por isso: um botão de 36px com fundo e sombra, no canto de cada cartão,
   competindo pela atenção com o próprio produto numa grade de quatro colunas.
   Com o símbolo tipográfico no lugar do emoji, o contraste vem da cor e do
   contorno do próprio traço — e o que sobra na tela é o coração, não o botão.

   O ALVO DE TOQUE CONTINUA OS MESMOS 36px, porque quem clica é o dedo e o dedo
   não encolheu. O que sumiu foi só o desenho do fundo. */
.botao_de_favorito_de_cartao {
	position: absolute;
	top: 7px;
	right: 12px;
	z-index: 10;
	width: 36px;
	height: 36px;
	display: flex;
	align-items: center;
	justify-content: center;

	/* 30px porque o ♡ ocupa menos espaço visual que o emoji que ele substitui:
	   é um traço fino, sem preenchimento, e no mesmo corpo ficaria miúdo. */
	font-size: 24px;
	line-height: 1;
	cursor: pointer;

	color: var(--cor_de_superficie);

	/* O contorno é o que salva o coração vazio sobre uma foto clara — sem ele,
	   branco sobre castanha clara desaparece. */
	text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);

	/* A escala é escrita pelo JavaScript no momento do clique; a transição é que
	   transforma o salto em movimento. */
	transition:
		transform 0.2s ease,
		color 0.2s ease,
		text-shadow 0.2s ease;
}

.botao_de_favorito_de_cartao:hover {
	text-shadow: 0 1px 5px rgba(0, 0, 0, 0.6);
}

/* Favoritado: o traço vazio dá lugar ao coração cheio, em vermelho. A classe
   continua sendo a fonte da verdade do estado — o JavaScript troca o símbolo e a
   classe juntos, e é a classe que o resto do código consulta. */
.botao_de_favorito_de_cartao.estado_de_produto_favoritado {
	color: var(--cor_de_alerta, #e74c3c);
	text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

/* O ESTADO DO MEIO: FAVORITOU OUTRO PESO DESTE PRODUTO (v9_18).

   Com um favorito por peso, o coração precisa dizer três coisas, e não duas. Este
   é o degrau intermediário: existe favorito neste produto, mas não é o peso que
   está selecionado agora.

   O DESENHO CONTINUA SENDO O ♡ VAZIO, e só a cor muda. Um terceiro símbolo — meio
   coração, coração pontilhado — dependeria de uma fonte que desenhasse isso igual
   no iPhone, no Android e no Windows, e essa fonte não existe. Vazio-em-vermelho
   se lê sozinho: a cor diz "há favorito aqui", o vazio diz "não é este".

   O contorno escuro sai junto com o branco: ele existia para salvar o traço claro
   sobre foto clara, e o vermelho já se sustenta. Fica um brilho de mesma cor, que
   destaca o desenho da foto sem sujá-lo de preto. */
.botao_de_favorito_de_cartao.estado_de_favorito_em_outro_peso {
	color: var(--cor_de_alerta, #e74c3c);
	text-shadow: 0 1px 4px rgba(231, 76, 60, 0.55);
}

/* ==============================================================================
   A COREOGRAFIA DA LISTA DE ITENS DO CARRINHO

   Três movimentos, todos declarados aqui e apenas DISPARADOS pelo JavaScript —
   ele põe e tira classes e escreve um número; quem descreve o movimento é o CSS.

   1. A ENTRADA EM CASCATA. Os itens chegavam todos no mesmo quadro, e uma lista
      inteira que aparece de uma vez é lida como um borrão: o olho não sabe se
      são três itens ou oito. Entrando em sequência, cada linha ganha um instante
      próprio e a contagem acontece sozinha.

      O ATRASO VEM DE UMA VARIÁVEL, não de uma regra por posição. O JavaScript
      escreve `--indice` em cada linha e o cálculo mora aqui — assim a lista pode
      ter três ou trinta itens sem que o CSS precise saber quantos são.

      O TETO DE 8 POSIÇÕES existe porque a cascata é tempero, não espera: sem ele,
      o décimo item de um carrinho cheio começaria a aparecer meio segundo depois
      do primeiro, e o cliente ficaria olhando uma lista se montando.

   2. A SAÍDA DO ITEM REMOVIDO. Encolhe a própria altura até zero ao mesmo tempo
      em que some — é o que faz a lista se fechar sobre o buraco em vez de dar um
      salto quando a linha é retirada do documento.

   3. A ALTURA FLUIDA. A transição de altura fica no recipiente; quem calcula os
      dois valores é o JavaScript, porque `height: auto` não é animável e o
      navegador precisa de dois números concretos para interpolar.
============================================================================== */

@keyframes animacao_de_entrada_de_item_de_carrinho {
	from {
		opacity: 0;
		transform: scale(0.94) translateY(6px);
	}
	to {
		opacity: 1;
		transform: scale(1) translateY(0);
	}
}

.linha_de_item_de_carrinho.estado_de_entrada_em_cascata {
	/* O `both` segura o primeiro quadro: sem ele a linha apareceria inteira antes
	   de a sua vez chegar, e só então começaria a animar. */
	animation: animacao_de_entrada_de_item_de_carrinho 0.32s
		cubic-bezier(0.25, 1, 0.5, 1) both;

	animation-delay: calc(min(var(--indice, 0), 8) * 45ms);
}

/* --- A SAÍDA --- */
.linha_de_item_de_carrinho.estado_de_saida_de_item {
	/* A altura entra na transição junto com a opacidade: é o encolhimento que
	   fecha o espaço, e não a remoção da tag lá no fim. */
	overflow: hidden;
	opacity: 0;
	transform: scale(0.92);
	max-height: 0;
	padding-top: 0;
	padding-bottom: 0;
	margin-top: 0;
	margin-bottom: 0;
	border-bottom-width: 0;

	transition:
		opacity 0.18s ease-in,
		transform 0.22s ease-in,
		max-height 0.26s ease-in,
		padding 0.26s ease-in,
		border-bottom-width 0.26s ease-in;
}

/* O estado de repouso precisa declarar o teto de altura e a transição, senão a
   linha saltaria de "sem limite" para zero em vez de percorrer o caminho. O
   valor é generoso de propósito: é um teto, não uma altura. */
.linha_de_item_de_carrinho {
	max-height: 400px;
	transition:
		max-height 0.26s ease-out,
		opacity 0.2s ease-out;
}

/* --- A ALTURA FLUIDA DO RECIPIENTE ---
   A regra de `.recipiente_de_lista_em_transicao_de_altura` mudou para o
   componentes_compartilhados.css, junto com a função de JavaScript que a aplica:
   a gaveta de acesso passou a usar as duas para trocar de passo sem tranco, e a
   gaveta também existe no checkout, que não carrega este arquivo. */

@media (prefers-reduced-motion: reduce) {
	.linha_de_item_de_carrinho.estado_de_entrada_em_cascata {
		animation-duration: 0.01s;
		animation-delay: 0s;
	}
}

/* ==============================================================================
   O SELETOR DE PESO DENTRO DO CARRINHO

   O peso do item era um texto solto — informação, não escolha. Trocar de 100g
   para 500g exigia fechar o carrinho, achar o produto na grade, escolher o peso
   e adicionar de novo, com o item antigo ainda lá para remover à mão.

   Agora é um botão que abre um balão com as opções, no lugar onde a pergunta
   nasce.

   POR QUE UM BALÃO SOBREPOSTO, E NÃO UMA GAVETA QUE EMPURRA: a lista do carrinho
   já rola dentro de uma janela de altura limitada. Um seletor que empurrasse os
   itens moveria tudo que está abaixo no instante do clique — inclusive a linha
   que o cliente está olhando. Sobrepondo, o resto da lista fica exatamente onde
   estava, e fechar o balão devolve a tela ao estado anterior sem susto.
============================================================================== */

/* --- O GATILHO, EM DUAS METADES ---

   [ 200g ] [ ▾ ] em vez de [ 200g ▾ ]. A seta colada ao texto dentro do mesmo
   contorno lia-se como enfeite do rótulo; num bloquinho quadrado próprio ela
   passa a se anunciar como controle. As duas metades chamam a mesma função,
   porque quem quer trocar o peso clica no peso tanto quanto na seta.

   ELE VESTE A COR DA OPÇÃO QUE ESTÁ VALENDO, EM DOIS TONS. Em repouso é o verde
   claro com borda verde — o mesmo par do bloquinho "com itens" do cartão —, que
   diz "escolhido" sem gritar mais alto que o subtotal e a lixeira, que dividem a
   linha com ele. Ao abrir o seletor ele fecha em verde sólido, igual à pílula
   ativa lá dentro: o gatilho e a opção que ele representa ficam da mesma cor no
   instante em que aparecem lado a lado. A transição entre os dois tons já estava
   declarada e passou a ser usada.

   O cinza foi embora daqui e das opções do balão: num carrinho, cinza é a cor de
   "indisponível", e essas são justamente as escolhas que estão disponíveis. */
.grupo_de_gatilho_de_troca_de_peso {
	display: inline-flex;
	/* `stretch` é o que garante a mesma altura nas duas metades sem que nenhuma
	   das duas precise declarar altura fixa: quem manda é a maior. */
	align-items: stretch;
	gap: 3px;
	flex-shrink: 0;
}

.botao_de_troca_de_peso,
.botao_de_seta_de_troca_de_peso {
	display: inline-flex;
	align-items: center;
	justify-content: center;

	min-height: 24px;
	padding: 6px 10px;
	border: 1px solid var(--cor_de_conversao);
	border-radius: 5px;
	background-color: var(--cor_de_conversao_clara);

	font-size: 11px;
	font-weight: bold;
	color: var(--cor_de_conversao);
	white-space: nowrap;
	cursor: pointer;

	transition:
		border-color 0.2s ease,
		color 0.2s ease,
		background-color 0.2s ease,
		filter 0.2s ease;
}

/* Aberto, o gatilho fecha em sólido e passa a ser a mesma coisa que a pílula
   ativa do balão que ele acabou de abrir. */
.grupo_de_gatilho_de_troca_de_peso.estado_de_seletor_aberto
	.botao_de_troca_de_peso,
.grupo_de_gatilho_de_troca_de_peso.estado_de_seletor_aberto
	.botao_de_seta_de_troca_de_peso {
	background-color: var(--cor_de_conversao);
	color: var(--cor_de_texto_sobre_cor);
}

/* O bloquinho da seta é quadrado: a largura acompanha a altura mínima em vez de
   ser calculada pelo tamanho do caractere. */
.botao_de_seta_de_troca_de_peso {
	width: 24px;
	padding: 0;
}

/* O passar do mouse escurece as duas metades juntas — são um controle só. Um
   escurecimento, e não outra cor: o gatilho já está na cor do estado ativo, e
   trocá-la no hover diria que o estado mudou. */
.grupo_de_gatilho_de_troca_de_peso:hover .botao_de_troca_de_peso,
.grupo_de_gatilho_de_troca_de_peso:hover .botao_de_seta_de_troca_de_peso {
	filter: brightness(0.94);
}

/* A OFERTA VESTE VIOLETA, COMO NO CARTÃO.
   É exatamente o estado "promocional + selecionado" do bloquinho da vitrine
   (fundo violeta claro, borda sólida, texto violeta) — o mesmo item, a mesma
   roupa, esteja ele no cartão ou na linha do carrinho. Os tons são literais de
   propósito: são cores de exceção, fora da paleta do `:root`. */
.grupo_de_gatilho_de_troca_de_peso.estado_de_gatilho_promocional
	.botao_de_troca_de_peso,
.grupo_de_gatilho_de_troca_de_peso.estado_de_gatilho_promocional
	.botao_de_seta_de_troca_de_peso {
	background-color: #f5eef8;
	color: #8e44ad;
	border-color: #9b59b6;
}

/* E fecha em violeta sólido ao abrir, pelo mesmo motivo que o comum fecha em
   verde: enquanto o balão está aberto, o gatilho e a opção que ele representa
   precisam ser a mesma coisa. Vem depois do bloco verde para vencê-lo aqui. */
.grupo_de_gatilho_de_troca_de_peso.estado_de_gatilho_promocional.estado_de_seletor_aberto
	.botao_de_troca_de_peso,
.grupo_de_gatilho_de_troca_de_peso.estado_de_gatilho_promocional.estado_de_seletor_aberto
	.botao_de_seta_de_troca_de_peso {
	background-color: #8e44ad;
	color: var(--cor_de_texto_sobre_cor);
	border-color: #8e44ad;
}

/* A setinha gira para anunciar que aquilo abre — e que agora está aberto. Com o
   gatilho já sólido nas duas situações, é ela que carrega sozinha o sinal de
   aberto. */
.seta_de_troca_de_peso {
	display: inline-block;
	font-size: 9px;
	line-height: 1;
	transition: transform 0.2s ease;
}

.grupo_de_gatilho_de_troca_de_peso.estado_de_seletor_aberto
	.seta_de_troca_de_peso {
	transform: rotate(180deg);
}

/* --- O BALÃO ---

   `fixed`, e não `absolute`: a lista do carrinho rola dentro de um recipiente de
   altura limitada, e um filho desse recipiente não transborda dele. O balão do
   último item era cortado pela borda da rolagem e sumia atrás do rodapé de
   "FINALIZAR COMPRA" — logo o item que mais precisa dele, por ser o que fica
   colado no rodapé. Em coordenadas de tela ele não pertence a nenhuma área de
   rolagem, e por isso nenhuma pode cortá-lo. Quem calcula `top` e `left` é o
   JavaScript no momento do clique, porque só ali se sabe onde o gatilho está.

   O z-index precisa vencer a própria janela flutuante do carrinho, que vive em
   10020. */
.balao_de_variacoes_de_item {
	position: fixed;
	z-index: 10030;
	top: 0;
	left: 0;

	min-width: 190px;
	max-width: 260px;
	padding: 8px;

	background-color: var(--cor_de_superficie);
	border: 1px solid var(--cor_de_borda_suave);
	border-radius: 10px;
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);

	animation: animacao_de_surgimento_de_balao 0.16s ease-out both;
}

/* Aberto para cima, o movimento de entrada inverte junto: um balão que nasce
   acima do gatilho deslizando de cima para baixo parece vir do lugar errado. */
.balao_de_variacoes_de_item.estado_de_balao_acima_do_gatilho {
	animation-name: animacao_de_surgimento_de_balao_acima;
	transform-origin: bottom left;
}

@keyframes animacao_de_surgimento_de_balao {
	from {
		opacity: 0;
		transform: translateY(-4px) scale(0.97);
	}
	to {
		opacity: 1;
		transform: translateY(0) scale(1);
	}
}

@keyframes animacao_de_surgimento_de_balao_acima {
	from {
		opacity: 0;
		transform: translateY(4px) scale(0.97);
	}
	to {
		opacity: 1;
		transform: translateY(0) scale(1);
	}
}

.balao_de_variacoes_de_item.estado_saindo {
	animation: animacao_de_saida_de_balao 0.14s ease-in both;
	pointer-events: none;
}

@keyframes animacao_de_saida_de_balao {
	from {
		opacity: 1;
		transform: translateY(0) scale(1);
	}
	to {
		opacity: 0;
		transform: translateY(-4px) scale(0.97);
	}
}

/* --- AS PÍLULAS ---

   AS OPÇÕES SÃO OS MESMOS BLOQUINHOS DO CARTÃO DE PRODUTO, e literalmente: elas
   carregam as classes `.botao_de_selecao_de_peso`, `.botao_de_peso_ativo` e
   `.botao_de_peso_promocional` da vitrine, em vez de uma cópia parecida que
   sairia do lugar no primeiro ajuste que só uma das duas recebesse. Escolher o
   peso no cartão e trocá-lo no carrinho é o mesmo gesto, e duas gramáticas
   visuais para o mesmo gesto obrigam a reaprender no meio do caminho.

   Sobra para esta classe só o que é do balão: o espaçamento da trilha e o estado
   esgotado. Cor, borda e formato vêm de lá. */
.trilha_de_pilulas_de_variacao {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 6px;
}

/* O preço saiu de dentro das pílulas: ele já está na linha do carrinho, e
   repetido em cada opção transformava uma escolha de dois toques numa tabela
   para ler. Sem ele, a pílula volta a ser do tamanho da palavra que carrega. */
.pilula_de_variacao {
	line-height: 1.2;
}

/* AS OPÇÕES NÃO ESCOLHIDAS PERDEM O CINZA.
   No cartão da vitrine o cinza funciona: ali ele é o repouso de uma pista de
   pesos que ninguém tocou ainda. Dentro do carrinho a leitura vira outra — o
   cliente está diante de uma escolha já feita, e um bloquinho cinza ao lado da
   verde parece o peso que acabou, não o peso que ele pode pegar. Fundo branco
   com borda verde diz a mesma coisa que o cinza dizia (não é este que está
   valendo) sem dizer a que não estava (este aqui não dá).

   O `:not()` duplo é o que preserva os dois estados que têm cor própria: a
   escolhida continua verde sólida e a oferta continua violeta, ambas vindas das
   classes do cartão. */
.balao_de_variacoes_de_item
	.botao_de_selecao_de_peso:not(.botao_de_peso_ativo):not(
		.botao_de_peso_promocional
	) {
	background-color: var(--cor_de_superficie);
	border-color: var(--cor_de_conversao);
	color: var(--cor_de_conversao);
}

/* Sem o cinza, o realce de passagem passa a ser o preenchimento claro — o mesmo
   verde clarinho que o gatilho usa em repouso. */
.balao_de_variacoes_de_item
	.botao_de_selecao_de_peso:not(.botao_de_peso_ativo):not(
		.botao_de_peso_promocional
	):hover {
	background-color: var(--cor_de_conversao_clara);
}

/* A OFERTA SEGUE A MESMA GRAMÁTICA, EM VIOLETA.
   Clara com borda sólida quando é só mais uma opção, cheia quando é a escolhida
   — exatamente o que as verdes fazem, e exatamente o que o gatilho da linha faz
   ao abrir. No cartão da vitrine ela é tracejada e pulsa, porque lá a oferta
   ainda está sendo oferecida; aqui dentro ela já é uma das escolhas em cima da
   mesa, e uma opção que pisca num menu de cinco pede para ser clicada em vez de
   esperar a decisão. A borda também cai para 1px, que é a das vizinhas: 2px
   deixaria a pílula da oferta mais alta que as outras da mesma fileira. */
.balao_de_variacoes_de_item
	.botao_de_selecao_de_peso.botao_de_peso_promocional {
	background-color: #f5eef8;
	border: 1px solid #9b59b6;
	color: #8e44ad;
	animation: none;
}

.balao_de_variacoes_de_item
	.botao_de_selecao_de_peso.botao_de_peso_promocional.botao_de_peso_ativo {
	background-color: #8e44ad;
	border-color: #8e44ad;
	color: var(--cor_de_texto_sobre_cor);
}

/* Sem estoque: aparece, mas anuncia que não dá. Esconder a opção faria o cliente
   procurar na vitrine um peso que também não vai encontrar lá. */
.pilula_de_variacao.estado_de_variacao_esgotada {
	opacity: 0.45;
	cursor: not-allowed;
	text-decoration: line-through;
}

/* Nem o realce de passagem, nem a pulsação da oferta: uma opção esgotada que
   reage ao mouse promete um clique que não existe. */
.pilula_de_variacao.estado_de_variacao_esgotada,
.pilula_de_variacao.estado_de_variacao_esgotada:hover {
	animation: none;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.balao_de_variacoes_de_item,
	.balao_de_variacoes_de_item.estado_saindo {
		animation-duration: 0.01s;
	}
}


/* ==============================================================================
   OS SELOS DO CARTÃO (v9_37, 2026-08-13)

   Uma faixa de bloquinhos por cima da foto, no canto de cima à esquerda. É o único
   lugar do cartão que não disputa espaço com nada: o coração está à direita, os
   ícones de restrição embaixo dele, e o miolo é do nome e do preço.

   ⚠️ ELES SÃO DO PESO SELECIONADO, E NÃO DO PRODUTO. Quem manda é a variação que a
   cascata acendeu — a mesma que define o preço em destaque —, e por isso a faixa é
   redesenhada a cada troca de pílula. Mostrar os selos de todos os pesos juntos
   diria "Novidade" e "Edição limitada" ao mesmo tempo num produto em que cada
   coisa é de um peso diferente.

   ⚠️ E O DESENHO SEPARA AS DUAS NATUREZAS SEM CONHECER O NOME DE NENHUM SELO. O
   derivado fala de dinheiro e de prazo — "Em promoção", "Acaba com o lote" —, e é
   ele que precisa saltar; o declarado é informação, e é discreto. Se a cor fosse
   escolhida por nome, acrescentar um selo ao catálogo exigiria uma regra nova
   aqui, e o selo novo nasceria sem estilo nenhum.
============================================================================== */
/* ⚠️ ELA DEIXOU DE SE POSICIONAR SOZINHA EM 2026-08-13. O `position: absolute`, o
   `top`, o `left`, o `z-index`, o `pointer-events` e o teto de largura subiram
   para `.canto_de_etiquetas_de_cartao`, que é quem empilha as duas faixas.
   Devolver qualquer um deles aqui tira a faixa da pilha e a põe por cima das
   restrições — que é exatamente o defeito que a caixa comum veio resolver. */
.faixa_de_selos_de_cartao {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 4px;
}

/* Sem isto a faixa nasce visível e vazia em todo cartão sem selo, ocupando o canto
   com um bloco de altura zero que ainda assim empurra o `gap`. É a mesma armadilha
   do `display` vencendo o atributo `hidden` que a gaveta do painel documenta. */
.faixa_de_selos_de_cartao[hidden] {
	display: none;
}

/* ⚠️ A REGRA DE IRMÃO COM `top: 48px` SAIU DAQUI EM 2026-08-13, e a ausência não se
   explica sozinha. Ela descia a faixa de selos quando havia restrição no cartão,
   porque as duas eram `position: absolute` no mesmo canto — e 48px era a altura de
   UMA pílula de emoji. Com as restrições em texto empilhado, a altura passou a
   depender de quantas há, e nenhum número serviria.
   Quem empilha agora é `.canto_de_etiquetas_de_cartao`, e não há mais medida
   escrita à mão entre os dois grupos. */

.selo_de_cartao_de_vitrine {
	padding: 3px 8px;

	font-size: 11px;
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: 0.2px;

	border-radius: 999px;

	/* A sombra existe porque o selo vive por cima de uma FOTO, e não de um fundo
	   conhecido: sem ela, um selo claro sobre uma castanha clara some. */
	box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
}

/* O declarado é informação: branco sobre a foto, com o texto na cor do texto da
   casa. Ele não compete com o preço. */
.selo_de_cartao_de_vitrine[data-natureza="declarado"] {
	background-color: var(--cor_de_superficie);
	color: var(--cor_de_texto_principal);
}

/* O derivado fala de dinheiro e de prazo, e usa a mesma cor da pílula de promoção
   — é a cor que o cliente já aprendeu a ler como "aqui há oferta" na pista de
   pesos, dois centímetros abaixo. */
.selo_de_cartao_de_vitrine[data-natureza="derivado"] {
	background-color: var(--cor_de_oferta);
	color: var(--cor_de_texto_sobre_cor);
}


/* ==============================================================================
   AS RESTRIÇÕES NA JANELA DE DETALHES (2026-08-13)

   ⚠️ O ESTILO SAIU DO `style=` INLINE do HTML, e a mudança é consequência da
   troca de emoji por texto: `font-size: 24px` servia a dois caracteres e vira uma
   parede com "Sem Glúten" e "Vegano" escritos por extenso.

   Os bloquinhos são os mesmos do cartão, em fila horizontal — na janela há largura
   de sobra, e empilhar aqui gastaria altura de uma caixa que já rola.

   ⚠️ O `id` CONTINUA DIZENDO "ICONES", e o nome mente. Ele é lido por
   `vitrine-carrinho_e_janelas.js` e trocá-lo exigiria mexer nos dois lados no mesmo
   passo — fica anotado como dívida, e não como esquecimento.
============================================================================== */
.bloco_de_restricoes_de_janela_de_detalhes {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;

	margin-bottom: 15px;
}

/* O mesmo desenho do bloquinho do cartão, com uma diferença: aqui ele vive sobre o
   fundo branco da janela, e não sobre uma foto — então ganha borda em vez de
   sombra, que é o que separa o bloquinho do fundo quando os dois são claros. */
.etiqueta_de_restricao_de_janela {
	padding: 4px 10px;

	font-size: 12px;
	font-weight: 700;
	line-height: 1.3;

	color: var(--cor_de_texto_principal);
	background-color: var(--cor_de_fundo_de_pagina);
	border: 1px solid var(--cor_de_borda_suave);
	border-radius: 999px;
}


/* ==============================================================================
   O CARROSSEL DE FOTOS DO CARTÃO (etapa 3 do carrossel, 2026-08-14)

   ⚠️ ELE É CSS PURO, E O MOTIVO NÃO É ELEGÂNCIA — É A PRÉVIA DO PAINEL.

   `painel_de_previa_de_cartao.js` injeta o HTML deste cartão por `innerHTML`, NÃO
   carrega nenhum dos sete `vitrine-*.js` e tem `pointer-events: none` nos filhos.
   Um carrossel que precisasse de inicialização não rodaria ali — sem erro no
   console, e sem carrossel. Com `scroll-snap`, o mecanismo inteiro é do navegador,
   e a prévia mostra a capa parada, que é exatamente o que ela precisa mostrar.

   ⚠️ A ALTURA CONTINUA SENDO OS 160px DE `.imagem_de_produto`, E ISSO É TRAVA DA
   ALVENARIA. `vitrine-alvenaria.js` registra a premissa literal: as imagens dos
   cartões têm altura fixa em CSS, então elas não mexem na grade ao carregar. Um
   carrossel que mudasse de altura dispararia o `ResizeObserver` e faria os ~50
   tijolos serem remedidos a cada troca de slide, com os cartões de baixo pulando
   enquanto alguém desliza uma foto.
   ============================================================================== */

/* A pista e as setas ficam por cima da caixa inteira. `.imagem_de_produto` já é
   `position: relative` desde sempre — é ela que ancora a faixa de selos e o
   coração —, então o carrossel só se pendura no que já existia. */
.carrossel_de_fotos {
	position: absolute;
	inset: 0;

	border-radius: 8px;
	overflow: hidden;
}

/* ⚠️ NÃO ESCREVA `touch-action` AQUI. É o contrário do pegador do painel e da
   raspadinha do bloco de engajamento: lá o gesto PRECISA ser tirado do navegador,
   e aqui ele precisa ficar com ele. Uma pista com `overflow-x: auto` já negocia o
   eixo sozinha — deslizar de lado troca a foto, deslizar para baixo rola a
   vitrine —, e qualquer `touch-action` escrito aqui quebraria uma das duas. */
.pista_de_fotos_de_carrossel {
	display: flex;
	height: 100%;

	overflow-x: auto;
	overflow-y: hidden;

	scroll-snap-type: x mandatory;

	/* ⚠️ NÃO DEVOLVA `scroll-behavior: smooth` AQUI. Ele estava escrito nesta regra e
	   saiu em 2026-08-14, depois de a seta ser medida com clique de verdade: uma
	   rolagem suave programada é uma ANIMAÇÃO, e ela é cancelada por qualquer
	   mudança de layout — que nesta vitrine acontece o tempo todo, porque
	   `vitrine-alvenaria.js` mantém um `ResizeObserver` em cada cartão reescrevendo o
	   `grid-row-end`. O salto começava e não chegava a lugar nenhum, e a seta parecia
	   um botão morto.

	   O deslize do dedo e o giro da roda continuam suaves de qualquer forma: quem os
	   anima é o navegador, e não esta propriedade. */

	/* A BARRA DE ROLAGEM É ESCONDIDA, E A ROLAGEM CONTINUA. Uma barra cinza
	   atravessada sobre a foto, em cinquenta cartões, é ruído — e ela apareceria
	   permanentemente no Windows, onde a barra não some sozinha. */
	scrollbar-width: none;
}

.pista_de_fotos_de_carrossel::-webkit-scrollbar {
	display: none;
}

/* ⚠️ `flex: 0 0 100%` E NÃO `width: 100%`. Dentro de um flex, `width` é sugestão:
   o navegador encolhe os itens para caber, e as quatro fotos apareceriam lado a
   lado a 25% cada, com o `scroll-snap` sem ter para onde ajustar. O `0 0` é o que
   proíbe crescer e encolher. */
.foto_de_carrossel {
	flex: 0 0 100%;
	width: 100%;
	height: 100%;

	object-fit: cover;
	scroll-snap-align: start;
}

/* COM UMA FOTO SÓ NÃO HÁ PISTA NEM SETAS — o desenho é o mesmo `<img>` de sempre,
   e esta classe existe para substituir o `style=` em linha que ficava no PHP. */
.foto_unica_de_carrossel {
	width: 100%;
	height: 100%;

	object-fit: cover;
	border-radius: 8px;
}

/* ⚠️ AS SETAS SÓ APARECEM NO `:hover` DO CARTÃO, E NO TOQUE ELAS FICAM SEMPRE.
   Duas setas permanentes sobre cinquenta fotos é uma vitrine coberta de controles;
   mas num aparelho sem cursor o `:hover` nunca acontece, e escondê-las ali seria
   esconder o único gesto visível do carrossel de quem não sabe que pode deslizar. */
.seta_de_carrossel {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 2;

	width: 28px;
	height: 28px;

	border: none;
	border-radius: 50%;
	background-color: rgba(255, 255, 255, 0.85);
	color: var(--cor_de_texto_principal);

	font-size: 18px;
	line-height: 1;
	cursor: pointer;

	opacity: 0;
	transition: opacity 0.15s ease;
}

.cartao_de_produto:hover .seta_de_carrossel,
.seta_de_carrossel:focus-visible {
	opacity: 1;
}

@media (hover: none) {
	.seta_de_carrossel {
		opacity: 1;
	}
}

.seta_de_carrossel_anterior { left: 6px; }
.seta_de_carrossel_seguinte { right: 6px; }

/* O CONTADOR NASCE CERTO SEM JAVASCRIPT NENHUM — o PHP escreve "1/N", que é a
   verdade da primeira pintura. Quem o atualiza ao deslizar é uma escuta de rolagem
   em fase de captura, na vitrine; a prévia do painel não a tem, e ali ele continua
   dizendo a verdade daquele estado parado. */
.contador_de_fotos_de_carrossel {
	position: absolute;
	right: 6px;
	bottom: 6px;
	z-index: 2;

	padding: 1px 7px;

	border-radius: 10px;
	background-color: rgba(0, 0, 0, 0.55);
	color: #ffffff;

	font-size: 0.7rem;
	font-weight: 700;
}

/* ==============================================================================
   A FOTO DO PESO SOB O CURSOR

   ⚠️ ELA NÃO É UM SLIDE DO CARROSSEL, e confundir as duas coisas é o defeito que
   este bloco existe para impedir: a ligação foto↔peso ESCOLHE O DESTAQUE, e não
   filtra o carrossel. Fosse um slide, o carrossel mudaria de tamanho conforme o
   peso selecionado, e a pista pularia de posição a cada troca de pílula.

   ⚠️ `pointer-events: none` É OBRIGATÓRIO. Ela cobre a caixa inteira quando está
   acesa, e sem isto ela comeria o clique que abre a janela de detalhes e o das
   setas — a foto certa na tela, e o cartão inteiro parando de responder.

   ⚠️ E ELA NÃO TEM `src` NO HTML. `src=""` faz o navegador baixar a própria página
   no lugar da imagem; ela nasce sem o atributo, e o JavaScript o escreve na
   primeira vez que um peso com foto própria recebe o cursor.
   ============================================================================== */
.foto_de_destaque_de_peso {
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;

	width: 100%;
	height: 100%;

	object-fit: cover;
	border-radius: 8px;

	opacity: 0;
	transition: opacity 0.18s ease;
}

.foto_de_destaque_de_peso_acesa {
	opacity: 1;
}

/* ==============================================================================
   O MESMO CARROSSEL, DENTRO DA JANELA DE DETALHES

   ⚠️ AS REGRAS DE CIMA JÁ SERVEM À JANELA, e é isso que faz as duas telas
   concordarem por construção: a pista, os slides e o contador são as mesmas
   classes, montadas pelo navegador em vez de pelo PHP. O que muda aqui embaixo são
   três coisas que dependem de ONDE o carrossel está.

   ⚠️ E ELAS FICAM NESTE ARQUIVO, e não em `componentes_compartilhados.css`, apesar
   de a moldura ser de lá: a janela de detalhes só existe na vitrine, e separar as
   regras do carrossel em dois arquivos é como se acaba com duas setas de tamanhos
   diferentes para o mesmo gesto.
   ============================================================================== */

/* ⚠️ A IMAGEM ÚNICA PRECISA DESTA LINHA POR CAUSA DO `display: block` DELA. O
   atributo `hidden` vale `display: none` por folha de estilo do navegador, e
   QUALQUER declaração de `display` numa regra do site vence — é a mesma armadilha
   que a gaveta de variações do painel documenta ao contrário.
   Sem isto, esconder a `<img>` para desenhar a pista não esconderia nada: a capa
   ficaria por baixo do carrossel, com a altura da moldura repartida entre as duas. */
.imagem_de_janela_de_detalhes[hidden] {
	display: none;
}

/* AS SETAS FICAM SEMPRE VISÍVEIS NA JANELA, e no cartão só no `:hover`. A diferença
   é de contexto e não de gosto: no cartão elas são duas de cinquenta, sobre uma
   grade que já tem coração, selos e pílulas; aqui há uma janela só, aberta de
   propósito, e esconder o gesto até o cursor chegar seria esconder o carrossel de
   quem abriu a janela justamente para ver as fotos. */
.moldura_de_imagem_de_janela_de_detalhes .seta_de_carrossel {
	opacity: 1;

	width: 34px;
	height: 34px;

	font-size: 22px;
}
