/* ==============================================================================
   ARQUIVO: COMPONENTES_COMPARTILHADOS.CSS
   OBJETIVO: OS COMPONENTES QUE MAIS DE UMA TELA USA

   Este arquivo nasceu de dentro do antigo base.css, que tinha 856 linhas e o nome
   errado: das suas regras, só o corpo da página era realmente base — todo o resto
   eram cinco componentes do fluxo de venda. Enquanto os dois viviam juntos, levar
   a fundação para uma tela nova significava levar a gaveta de login junto, mesmo
   para o PDV de feira, que não tem login nenhum.

   O QUE MORA AQUI: a torrada de avisos, a janela flutuante, a gaveta de acesso, a
   cortina de recarregamento e o carrossel de itens salvos.

   QUEM CARREGA: apenas /loja e /loja/pagamento — as duas telas que carregam o
   motor_base.js e o motor_de_pagamento.js, que são quem injeta e comanda estes
   componentes. Se um dia outra tela precisar de um deles, é este arquivo que ela
   passa a incluir, sempre DEPOIS da fundacao.css e ANTES do CSS da própria tela.
============================================================================== */

/* ========================================================== */
/* COMPONENTES GLOBAIS: JANELAS FLUTUANTES					*/
/* ========================================================== */
.fundo_de_janela_flutuante {
	/* O display de quando a janela ESTÁ ABERTA. Fechá-la é trabalho da classe
	   .estado_oculto, posta no HTML e retirada pelo JavaScript — antes era este
	   `display: none` que a mantinha fechada, e o JavaScript a abria escrevendo
	   `flex` no atributo de estilo do elemento. Com a abertura vindo do estilo
	   inline e o fechamento vindo daqui, o mesmo elemento tinha duas fontes de
	   verdade para a mesma propriedade. */
	display: flex;
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background-color: rgba(0, 0, 0, 0.7);
	z-index: 10020; /* Fica acima do menu lateral e do cabeçalho */
	justify-content: center;
	align-items: center;
	backdrop-filter: blur(5px);
}

.conteudo_de_janela_flutuante {
	background-color: var(--cor_de_superficie);
	width: 90%;
	max-width: 600px;
	max-height: 85vh;
	border-radius: var(--raio_de_canto_de_cartao);
	padding: 30px;
	position: relative;
	overflow-y: auto;
	box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}

.botao_de_fechar_janela_flutuante {
	position: absolute;
	top: 15px;
	right: 20px;
	font-size: 28px;
	color: var(--cor_de_texto_suave);
	cursor: pointer;
	border: none;
	background: none;
	font-weight: bold;
	transition: 0.2s;
}

.botao_de_fechar_janela_flutuante:hover {
	color: var(--cor_de_alerta);
	transform: scale(1.1);
}

/* ==========================================================================
   A FOTO DENTRO DA JANELA DE DETALHES (item 1.10, 2026-08-10)

   A ALTURA É FIXA, e não `auto`. Uma janela que cresce conforme a proporção da
   foto muda de tamanho a cada produto aberto — e como a janela é centrada na
   tela, ela também muda de POSIÇÃO: o botão de fechar sai do lugar entre uma
   abertura e a seguinte, no canto onde o polegar já estava indo.

   `object-fit: cover` é o que permite a altura fixa sem deformar nada: a foto
   preenche a moldura e o excedente é aparado pelas bordas. Um `contain` deixaria
   tarja nas laterais das fotos verticais, dentro de uma janela branca — e o
   resultado seria a foto parecendo pequena justamente onde ela deveria ser
   grande.

   O `overflow: hidden` da moldura é obrigatório junto com o raio de canto: sem
   ele, a imagem retangular vaza pelos quatro cantos arredondados, e o efeito é o
   de uma foto colada torta por cima da janela.
   ========================================================================== */
.moldura_de_imagem_de_janela_de_detalhes {
	/* ⚠️ O `position: relative` ENTROU NA ETAPA 3 DO CARROSSEL (2026-08-14), e ele é
	   a âncora do carrossel de fotos que a janela passou a desenhar por dentro: as
	   setas e o contador são `position: absolute`, e sem esta linha eles se
	   pendurariam no primeiro ancestral posicionado — que é a janela inteira, com as
	   setas indo parar em cima do texto de ingredientes.

	   As regras do carrossel moram em `vitrine_de_loja.css`, junto com as do cartão,
	   porque a janela de detalhes só existe na vitrine e as duas telas do carrossel
	   precisam concordar. Esta linha fica aqui porque ela é da MOLDURA, que é deste
	   arquivo. */
	position: relative;

	width: 100%;
	height: 220px;
	margin-bottom: 20px;
	border-radius: var(--raio_de_canto_de_cartao);
	overflow: hidden;
	background-color: var(--cor_de_superficie_suave);
}

.imagem_de_janela_de_detalhes {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* ==========================================================================
   A ETIQUETA "EM BREVE"

   VEIO DE `pagina_de_pagamento.css` EM 2026-08-10, e quem a usa hoje é só a opção
   de retirada na loja, lá. O cartão da vitrine chegou a usá-la e não usa mais: ele
   ficou com um bloco de duas linhas próprio, que ocupa o lugar dos pesos e do
   preço em vez de uma pílula ao lado do nome.

   ELA FICA AQUI MESMO ASSIM, e a razão é a vizinha logo abaixo: a faixa da janela
   de detalhes é o mesmo azul, e as duas precisam concordar. Separá-las em arquivos
   diferentes é como se acaba com dois tons de "em breve" no mesmo site.

   O AZUL É DE PROPÓSITO, e não o cinza de "indisponível": a etiqueta anuncia,
   não recusa. Quem lê "EM BREVE" precisa entender que vem coisa nova, e é essa
   antecipação que queremos — daí o contraste ficar acima do mínimo de leitura em
   vez de desbotar como rótulo desativado.
   ========================================================================== */
.etiqueta_de_em_breve {
	display: inline-block;
	margin-left: 6px;
	padding: 2px 7px;
	border-radius: 10px;
	background-color: #eaf4fb;
	color: #2980b9;
	font-size: 11px;
	font-weight: bold;
	letter-spacing: 0.3px;
	vertical-align: middle;
}

/* ==========================================================================
   A FAIXA DE "EM BREVE" DENTRO DA JANELA DE DETALHES

   É a mesma informação da etiqueta do cartão, e mesmo assim NÃO é a mesma
   classe. No cartão ela é uma pílula pequena ao lado do nome, disputando espaço
   com a pista de pesos; aqui ela é a primeira coisa da janela, e tem a largura
   toda para explicar por que aquele cartão estava cinza.

   A barra lateral repete o desenho da caixa de alerta de alergia logo abaixo —
   mesmo vocabulário visual para "leia isto antes do resto".
   ========================================================================== */
.faixa_de_em_breve_de_janela {
	background-color: #eaf4fb;
	color: #2980b9;
	border-left: 4px solid #2980b9;
	padding: 12px 15px;
	border-radius: 8px;
	margin-bottom: 15px;
	font-size: 14px;
	font-weight: bold;
}

/* ========================================================================== */
/* JANELA FLUTUANTE GLOBAL DE ACESSO TITANIUM */
/* ========================================================================== */
/* ========================================================================== */
/* FUNDO DO MODAL DE ACESSO (Com Fade-In Premium) */
/* ========================================================================== */
.fundo_escurecido_de_janela {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100dvh; /* Altura blindada contra o teclado e barra do navegador */
	
	background-color: rgba(0, 0, 0, 0.6); /* Mantido escuro pelo Efeito Teatro */
	backdrop-filter: blur(3px);
	-webkit-backdrop-filter: blur(3px);
	
	display: flex; /* Sempre flex, nunca none! */
	justify-content: center;
	align-items: center;
	z-index: 10020; /* Fica na mesma camada segura do carrinho */
	
	/* FÍSICA DE INVISIBILIDADE */
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	
	/* TRANSIÇÃO MACIA DE 0.3s */
	transition: opacity 0.3s ease-out, visibility 0.3s;
}

/* O gatilho que revela o modal suavemente */
.fundo_escurecido_de_janela.janela_visivel {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
}

/*
	A SAÍDA, ENQUANTO A JANELA AINDA ESTÁ NA TELA.

	`.estado_saindo` é o intervalo entre "o cliente pediu para fechar" e "a
	janela deixou de existir": ela continua ocupando a tela, esmaecendo e — no
	celular — deslizando de volta para baixo, e só quando o movimento termina é
	que o JavaScript põe `.estado_oculto` e a retira do fluxo. Esconder antes de
	animar não animaria nada.

	Os cliques morrem aqui: um toque no meio da animação encontraria um
	formulário que já está de partida.
*/
.fundo_escurecido_de_janela.estado_saindo {
	pointer-events: none;
}

.caixa_de_janela_de_acesso {
	background-color: var(--cor_de_superficie);
	width: 90%;
	max-width: 400px;
	border-radius: var(--raio_de_canto_de_cartao);
	padding: 30px;
	box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
	position: relative;
	transform: translateY(-20px);
	transition: transform 0.2s ease-in-out;

	/*
		O TETO TAMBÉM VALE NO COMPUTADOR.

		No celular ele sempre existiu, por causa do teclado. Aqui ele passou a
		fazer falta com o passo de cadastro, que é o mais alto dos três: num
		notebook de tela baixa, ou com a janela do navegador reduzida, o
		formulário passava do rodapé e o botão de criar conta ficava fora do
		alcance, sem rolagem nenhuma para alcançá-lo — a caixa não rolava, e a
		página atrás não rola enquanto a janela está aberta.

		`dvh` e não `vh`: no celular, `vh` conta a barra de endereço como se ela
		nunca fosse recolher, e a conta fica errada justamente no aparelho onde
		sobra menos tela.
	*/
	max-height: 92dvh;
	overflow-y: auto;
	overscroll-behavior: contain;

	/* INJEÇÃO TITANIUM: O Respiro da Janela no celular */
	box-sizing: border-box;
}

.fundo_escurecido_de_janela.janela_visivel .caixa_de_janela_de_acesso {
	transform: translateY(0);
}

.botao_de_fechar_janela {
	position: absolute;
	top: 15px;
	right: 15px;
	background: transparent;
	border: none;
	font-size: 28px;
	color: var(--cor_de_texto_suave);
	cursor: pointer;
	transition: color 0.2s;
	line-height: 1;
}

.botao_de_fechar_janela:hover {
	color: var(--cor_de_alerta);
}

/* ==========================================================================
   A GAVETA DE ACESSO

   No computador ela é o modal centrado de sempre. No celular vira uma gaveta
   grudada no rodapé: é o único lugar onde o teclado virtual não briga com o
   formulário, porque o teclado sobe do mesmo lado e apenas empurra a gaveta.
   ========================================================================== */

@media (max-width: 768px) {
	.fundo_escurecido_de_janela {
		align-items: flex-end; /* Cola a caixa no rodapé em vez de centrá-la */
	}

	.caixa_de_janela_de_acesso {
		width: 100%;
		max-width: none;
		padding: 8px 22px 28px 22px;

		/* ==================================================================
		   ⚠️⚠️ OS CANTOS DE BAIXO ARREDONDAM QUANDO A GAVETA SAI DO CHÃO  (item 1.17)

		   Ele notou cantos inferiores quadrados num modal da página de pagamento em
		   2026-08-17, e a varredura do mesmo dia não achou nada: no computador os três
		   modais daquela tela têm raio uniforme, e esta regra — que era
		   `border-radius: 22px 22px 0 0` — parecia intencional e correta, porque uma
		   gaveta colada no rodapé com cantos de baixo arredondados fica errada.

		   ELA ESTAVA CERTA ATÉ O `bottom` LOGO ABAIXO ENTRAR EM CENA. O elevador do
		   teclado escreve `--altura-de-teclado` e levanta a gaveta essa distância: com
		   o teclado do iOS aberto, ela DEIXA de estar colada no rodapé e passa a
		   flutuar acima dele — com dois cantos retos aparecendo por cima do fundo
		   escurecido. É a mesma caixa em dois estados, e o raio só servia a um deles.

		   📌 E É POR ISSO QUE ISTO NÃO SE REPRODUZ NO COMPUTADOR NEM NA AUTOMAÇÃO: só
		   aparece com teclado virtual aberto, que é o único momento em que a variável
		   deixa de ser zero. Foi achado lendo, depois de ele dizer quais são as duas
		   apresentações — e não medindo, porque a medição no desktop respondia "está
		   tudo redondo" com toda a razão.

		   O `min()` FAZ O RAIO ACOMPANHAR O ELEVADOR, sem uma linha de JavaScript: em
		   zero ele é zero e a gaveta continua grudada como sempre; com o teclado aberto
		   ele chega aos mesmos 22px de cima e a caixa fecha como um cartão. Uma classe
		   escrita pelo JavaScript daria o mesmo desenho e uma segunda fonte de verdade
		   sobre "o teclado está aberto?", que é justamente o tipo de coisa que passa a
		   divergir no primeiro conserto.
		   ================================================================== */
		border-radius:
			22px 22px
			min(var(--altura-de-teclado, 0px), 22px)
			min(var(--altura-de-teclado, 0px), 22px);

		/*
			O ELEVADOR.

			O teclado do iOS flutua por cima da página em vez de encolhê-la, e a
			gaveta ficava ancorada atrás dele. O JavaScript mede a altura do
			teclado e escreve aqui; o `bottom` levanta a gaveta exatamente essa
			distância, deixando-a pousada na borda de cima do teclado.

			O mesmo número é descontado da altura máxima. Sem esse desconto a
			gaveta subiria inteira e vazaria pelo alto da tela; com ele, ela
			encolhe, o `overflow-y` acorda e o formulário rola por dentro.

			O valor de reserva é zero: no computador, no Android e sempre que não
			há teclado, estas duas linhas não fazem nada.
		*/
		bottom: var(--altura-de-teclado, 0px);
		max-height: calc(92dvh - var(--altura-de-teclado, 0px));
		overflow-y: auto;

		/* A rolagem morre aqui dentro em vez de contagiar a página atrás */
		overscroll-behavior: contain;

		/* Entra deslizando de baixo, e não descendo do alto como o modal */
		transform: translateY(100%);
		transition: transform 0.35s cubic-bezier(0.25, 1, 0.5, 1);
	}

	/*
		A FAIXA DE ARRASTE.

		O puxador desenhado tem 5px de altura — alvo impossível para o polegar.
		Esta faixa é a área de toque de verdade em volta dele, e é nela que moram
		os tratadores do deslizar para baixo. O `touch-action: none` avisa o
		navegador para não tentar rolar nada enquanto o dedo conduz a gaveta.
	*/
	.area_de_arraste_de_gaveta {
		display: block;
		padding: 6px 0 2px 0;
		margin: 0 -22px; /* Atravessa o respiro lateral: pega a largura toda */
		touch-action: none;
		cursor: grab;
	}

	/* O tracinho que anuncia "isto desliza" */
	.puxador_de_gaveta {
		display: block;
		width: 42px;
		height: 5px;
		margin: 10px auto 18px auto;
		border-radius: 3px;
		background-color: #dfe4ea;
	}

	/* No celular o X sai de cena: o puxador e o toque no fundo já dão conta,
	   e um X pequeno tão perto da borda superior é alvo difícil para o polegar. */
	.caixa_de_janela_de_acesso .botao_de_fechar_janela {
		display: none;
	}
}

/*
	No computador não existe puxador nem arraste: lá é um modal, não uma gaveta.

	ESTA REGRA PRECISA DA CONSULTA DE MÍDIA. Antes ela era solta, valendo para
	qualquer largura, e como mora DEPOIS do bloco de celular — mesma
	especificidade, arquivo abaixo — era ela que vencia. O puxador que o bloco de
	celular acendia lá em cima nunca chegou a aparecer: o tracinho que
	anunciava "isto desliza" estava, ele próprio, invisível. Trocar por
	`min-width` faz as duas regras pararem de disputar, cada uma no seu tamanho
	de tela.
*/
@media (min-width: 769px) {
	.puxador_de_gaveta,
	.area_de_arraste_de_gaveta {
		display: none;
	}
}

/* --- O CAMPO UNIVERSAL E OS DEMAIS --- */
.titulo_de_gaveta_de_acesso {
	margin: 0 0 6px 0;
	font-size: 20px;
	color: var(--cor_de_texto_principal);
}

.texto_de_apoio_de_gaveta {
	margin: 0 0 20px 0;
	font-size: 14px;
	color: var(--cor_de_texto_suave);
}

.campo_de_gaveta_de_acesso {
	width: 100%;
	padding: 14px 16px;
	font-size: 16px; /* Abaixo de 16px o iOS dá zoom sozinho ao focar */
	border: 1px solid var(--cor_de_borda_suave);
	border-radius: 10px;
	outline: none;
	background-color: var(--cor_de_superficie);
	color: var(--cor_de_texto_principal);
	box-sizing: border-box;
	transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.campo_de_gaveta_de_acesso:focus {
	border-color: var(--cor_de_conversao);
	box-shadow: 0 0 0 3px rgba(39, 174, 96, 0.15);
}

/* O RESPIRO ENTRE UM CAMPO E O SEGUINTE.

   É O MESMO 14px QUE SEPARA O ÚLTIMO CAMPO DA MENSAGEM DE ERRO. Um formulário
   com dois espaçamentos parecidos mas diferentes — 12 aqui, 14 ali — não parece
   organizado por uma régua; parece que cada peça foi ajustada num dia diferente.

   OS SELETORES SÃO QUATRO PORQUE O CAMPO DE SENHA MUDA DE FORMA. No instante em
   que o motor_de_formularios.js o envolve para pendurar o olhinho, ele deixa de
   ser irmão do campo acima: o que vem depois passa a ser a
   `div.envoltoria_de_campo_de_senha`.

   E O ÚLTIMO É O QUE ESTAVA FALTANDO. Entre o campo de identificação e o de
   senha existe a linha de aviso, que fica VAZIA quase o tempo todo — e, vazia,
   não ocupa altura nenhuma desde que ela deixou de anunciar "✓ E-mail". Com uma
   div no meio, a regra de irmãos adjacentes não alcançava o campo de baixo, e os
   dois ficavam encostados um no outro. */
.campo_de_gaveta_de_acesso + .campo_de_gaveta_de_acesso,
.campo_de_gaveta_de_acesso + .envoltoria_de_campo_de_senha,
.envoltoria_de_campo_de_senha + .campo_de_gaveta_de_acesso,
.pista_de_formato_de_acesso + .envoltoria_de_campo_de_senha,
.pista_de_formato_de_acesso + .campo_de_gaveta_de_acesso {
	margin-top: 14px;
}

/* O PRIMEIRO CAMPO DE UM PASSO não entra na regra acima — ele não tem irmão
   antes dele, e sim o texto de apoio, do outro lado da fronteira do <form>. O
   respiro dali vem da margem do próprio texto, e é por isso que a tela de senha
   nova já nascia com folga: ali só existe um campo. */

/* O CAMPO RECONHECIDO SE ANUNCIA PELA BORDA, E NÃO POR UMA FRASE.

   Havia um "✓ E-mail" embaixo do campo assim que o endereço ficava completo:
   dizia em palavras o que a pessoa acabou de escrever e ocupava, o tempo todo, a
   mesma linha reservada aos avisos de erro. Um aviso que fala quando está tudo
   certo perde a força de falar quando não está. */
.campo_de_gaveta_de_acesso.estado_de_campo_reconhecido {
	border-color: var(--cor_de_conversao);
}

/* A linha de aviso só existe quando tem o que dizer: vazia, ela não reserva
   altura nenhuma, e por isso o formulário não fica com um buraco à espera de um
   erro que talvez nunca venha. */
.pista_de_formato_de_acesso {
	margin: 0 2px;
	font-size: 12px;
	font-weight: 600;
	color: var(--cor_de_alerta, #c0392b);
}

.pista_de_formato_de_acesso:not(:empty) {
	margin-top: 6px;
}

/* ==========================================================================
   AS DUAS SAÍDAS DE QUEM NÃO CONSEGUE ENTRAR

   Ficam abaixo do formulário, à direita e em corpo pequeno: são a alternativa,
   não o caminho. Caixa de contorno fino com fundo branco — o mesmo verde do
   botão principal, sem o peso dele, porque um segundo botão cheio ao lado do
   ENTRAR faria a pessoa parar para escolher entre dois iguais.
   ========================================================================== */
.trilha_de_saidas_de_recuperacao {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	gap: 8px;
	margin-top: 14px;
}

.botao_de_saida_de_recuperacao {
	padding: 7px 12px;
	border: 1px solid var(--cor_de_conversao);
	border-radius: 6px;
	background-color: var(--cor_de_superficie);

	font-size: 12px;
	font-weight: 600;
	color: var(--cor_de_conversao);
	line-height: 1.2;
	cursor: pointer;

	transition: background-color 0.2s ease;
}

.botao_de_saida_de_recuperacao:hover {
	background-color: var(--cor_de_conversao_clara);
}

.botao_de_saida_de_recuperacao:disabled {
	opacity: 0.55;
	cursor: not-allowed;
}

/* ==========================================================================
   OS PASSOS DA RECUPERAÇÃO
   ========================================================================== */
.passo_de_recuperacao_de_acesso {
	display: none;
}

.passo_de_recuperacao_de_acesso.passo_visivel {
	display: block;
}

/* --- OS BLOQUINHOS DO CÓDIGO SAÍRAM DAQUI EM 2026-08-17 ---

   As cento e treze linhas que desenhavam `.bloco_de_codigo_com_prefixo`, o selo
   do prefixo, a trilha, o separador e os seis quadradinhos foram para a
   `fundacao.css`, na seção "A TRILHA DE BLOQUINHOS DE CÓDIGO".

   O MOTIVO É QUE A GAVETA DEIXOU DE SER A ÚNICA A PEDIR UM CÓDIGO. As telas de
   `/acesso/codigo` e `/acesso/trocar-senha` mostram a mesma trilha, e nenhuma
   delas carrega este arquivo — ele traz junto a janela flutuante, o carrossel de
   itens salvos e a cortina de recarregamento, que aquelas páginas não usam.

   A FUNDAÇÃO É O ARQUIVO QUE AS DUAS JÁ CARREGAM, e a regra da casa manda
   unificar lá dentro em vez de criar um terceiro arquivo. É a mesma decisão que
   pôs ali o campo de senha com olhinho e a torrada: componente pequeno, pedido
   por telas que não compartilham mais nada entre si.

   ⚠️ E AS CLASSES MUDARAM DE NOME NA MUDANÇA, porque o nome passou a mentir:
   `.digito_de_codigo_de_recuperacao` virou `.bloquinho_de_codigo`,
   `.trilha_de_digitos_de_codigo_de_recuperacao` virou
   `.trilha_de_bloquinhos_de_codigo`, `.separador_de_digitos_de_codigo` virou
   `.separador_de_bloquinhos_de_codigo` e `.estado_de_digito_preenchido` virou
   `.estado_de_bloquinho_preenchido`. Quem procurar os nomes antigos não vai
   achá-los em lugar nenhum — eles não existem mais. */

/* O rodapé do passo: reenviar de um lado, voltar do outro. */
.rodape_de_passo_de_recuperacao {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	margin-top: 16px;
}

/* --- BOTÕES --- */
.botao_principal_de_gaveta {
	width: 100%;
	margin-top: 18px;
	padding: 15px;
	background-color: var(--cor_de_conversao);
	color: var(--cor_de_texto_sobre_cor);
	border: none;
	border-radius: 10px;
	font-size: 16px;
	font-weight: 700;
	cursor: pointer;
	transition: all 0.2s ease;
}

.botao_principal_de_gaveta:hover {
	background-color: var(--cor_de_conversao_escura);
}

.botao_principal_de_gaveta:disabled {
	background-color: #a9dfbf;
	cursor: default;
}

.botao_secundario_de_gaveta {
	width: 100%;
	margin-top: 10px;
	padding: 14px;
	background-color: transparent;
	color: var(--cor_de_conversao);
	border: 1.5px solid var(--cor_de_conversao);
	border-radius: 10px;
	font-size: 15px;
	font-weight: 600;
	cursor: pointer;
	transition: all 0.2s ease;
}

.botao_secundario_de_gaveta:hover {
	background-color: var(--cor_de_conversao_clara);
}

.botao_secundario_de_gaveta:disabled {
	border-color: #a9dfbf;
	color: #a9dfbf;
	cursor: default;
}

/* --- O DIVISOR COM "ou" NO MEIO --- */
.divisor_de_gaveta_de_acesso {
	display: flex;
	align-items: center;
	gap: 12px;
	margin: 22px 0;
	color: #b2bec3;
	font-size: 13px;
}

.divisor_de_gaveta_de_acesso::before,
.divisor_de_gaveta_de_acesso::after {
	content: "";
	flex: 1;
	height: 1px;
	background-color: #edf0f2;
}

/* --- LOGIN SOCIAL (o HTML está comentado até o OAuth existir) --- */
.botao_social_de_gaveta {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	width: 100%;
	margin-top: 10px;
	padding: 13px;
	background-color: var(--cor_de_superficie);
	color: var(--cor_de_texto_principal);
	border: 1px solid var(--cor_de_borda_suave);
	border-radius: 10px;
	font-size: 15px;
	font-weight: 600;
	cursor: pointer;
	transition: all 0.2s ease;
}

.botao_social_de_gaveta:hover {
	background-color: var(--cor_de_superficie_suave);
	border-color: #cbd3da;
}

/* --- O RECADO DE ERRO --- */
.aviso_de_erro_de_gaveta {
	display: none;
	margin-top: 14px;
	padding: 12px 14px;
	background-color: #fdecea;
	border-radius: 8px;
	color: #c0392b;
	font-size: 14px;
	font-weight: 600;
}

.aviso_de_erro_de_gaveta.aviso_visivel {
	display: block;
}

/* --- O PASSO DO CÓDIGO POR MENSAGEM (OTP) --- */
.passo_de_codigo_de_acesso {
	display: none;
}

.passo_de_codigo_de_acesso.passo_visivel {
	display: block;
}

/* --- A ALTURA FLUIDA, USADA PELA GAVETA E PELA LISTA DO CARRINHO ---

   Veio do vitrine_de_loja.css, onde nasceu para a lista do carrinho. Está aqui
   porque a gaveta de acesso passou a usá-la ao trocar de passo — e a gaveta
   existe também no checkout, que não carrega o CSS da vitrine.

   0,42s com uma curva que desacelera longamente no fim. A primeira versão usava
   0,3s e chegava ao tamanho final ainda com velocidade — o olho lia como uma
   parada brusca, mesmo sendo uma transição.

   O `overflow: hidden` é o que impede o conteúdo novo de vazar por baixo
   enquanto a altura ainda não o alcançou; na gaveta ele também suspende a
   rolagem interna pelo tempo da transição, o que é justamente o que se quer:
   uma barra de rolagem aparecendo e sumindo no meio do movimento seria um
   segundo movimento por cima do primeiro. */
/* --- A TRANSIÇÃO DE ALTURA SAIU DAQUI EM 2026-08-17 ---

   `.recipiente_de_lista_em_transicao_de_altura` foi para a `fundacao.css`, junto
   com a função que a aplica, que virou o `altura_fluida.js`.

   O MOTIVO É A PÁGINA `/acesso`, que passou a trocar de passo dentro da própria
   caixa em vez de navegar — o mesmo gesto da gaveta, e por isso a mesma curva e o
   mesmo tempo. Ela não carrega este arquivo, que traz junto a janela flutuante, o
   carrossel de itens salvos e a cortina de recarregamento pós-login.

   ⚠️ ESCREVER UMA SEGUNDA TRANSIÇÃO LÁ SERIA O ERRO: a mesma loja se moveria de
   dois jeitos. É o que o princípio da harmonia proíbe, e está no CLAUDE.md. */

/* --- O PASSO DE CRIAR CONTA ---

   Mesma mecânica dos outros dois, e de propósito: os três passos são telas da
   mesma gaveta, e quem chega ao cadastro pela porta do login não deve sentir que
   trocou de lugar. Herda da caixa a rolagem interna e o elevador de teclado —
   este é o passo mais alto dos três, e o único em que o formulário pode não
   caber inteiro com o teclado de pé. */
.passo_de_cadastro_de_acesso {
	display: none;
}

.passo_de_cadastro_de_acesso.passo_visivel {
	display: block;
}

.trilha_de_digitos_de_codigo {
	display: flex;
	justify-content: center;
	gap: 10px;
	margin: 18px 0 4px 0;
}

.digito_de_codigo_de_acesso {
	width: 56px;
	height: 64px;
	padding: 0;
	text-align: center;
	font-size: 26px;
	font-weight: 700;
	color: var(--cor_de_texto_principal);
	border: 1px solid var(--cor_de_borda_suave);
	border-radius: var(--raio_de_canto_de_cartao);
	outline: none;
	background-color: var(--cor_de_superficie);
	transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.digito_de_codigo_de_acesso:focus {
	border-color: var(--cor_de_conversao);
	box-shadow: 0 0 0 3px rgba(39, 174, 96, 0.15);
}

.botao_de_voltar_de_gaveta {
	width: 100%;
	margin-top: 14px;
	padding: 10px;
	background: none;
	border: none;
	color: var(--cor_de_texto_suave);
	font-size: 14px;
	cursor: pointer;
}

.botao_de_voltar_de_gaveta:hover {
	color: var(--cor_de_texto_principal);
}

/* ========================================================================== */
/* CORTINA GLOBAL DE CARREGAMENTO (Design Original + Transição Suave) */
/* ========================================================================== */
.cortina_de_carregamento_global {
	position: fixed;

	/*
		ESTABILIZAÇÃO DE CELULAR (ANTI-SOLAVANCO)

		Era top/left/width/height com 100dvh. O dvh acompanha a barra de endereço
		do navegador, que aparece e some conforme o cliente rola — e a cada troca
		dessas a cortina mudava de altura, jogando o círculo giratório para cima e
		para baixo no meio da coreografia.

		Com inset, a cortina não tem altura própria: ela se prende às quatro bordas
		da janela, seja qual for o tamanho dela naquele instante. A barra do
		navegador pode ir e vir à vontade; o centro continua no centro.
	*/
	inset: 0;

	background-color: rgba(255, 255, 255, 0.7);
	backdrop-filter: blur(4px);
	-webkit-backdrop-filter: blur(4px);
	
	display: flex; /* Sempre flex para a transição funcionar */
	justify-content: center;
	align-items: center;
	flex-direction: column;
	z-index: 99999; /* Fica por cima de absolutamente tudo */
	
	/* ESTADO INICIAL: Invisível, mas pronto para animar */
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	
	/* A Transição Premium que testamos */
	transition: opacity 0.4s ease-in-out, background-color 0.8s ease-in-out, visibility 0.4s;
}

/* Nova classe que o JS vai injetar para fechar o clarão branco */
.cortina_branca_solida {
	background-color: rgba(255, 255, 255, 1) !important;
}

/* O gatilho que revela a cortina suavemente */
.cortina_de_carregamento_global.estado_visivel_de_cortina {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
}

/* --- OS SEUS ESTILOS ORIGINAIS DEVOLVIDOS --- */
.icone_giratorio_de_carregamento {
	width: 50px;
	height: 50px;
	border: 5px solid transparent; /* */
	border-top: 5px solid var(--cor_de_conversao);
	border-radius: 50%;
	animation: animacao_de_giro_de_icone 1s linear infinite;
}

.texto_de_mensagem_de_cortina {
	margin-top: 20px;
	color: var(--cor_de_texto_principal);
	font-size: 18px;
	font-weight: bold;
	text-align: center;
}

@keyframes animacao_de_giro_de_icone {
	0% { transform: rotate(0deg); }
	100% { transform: rotate(360deg); }
}

/* ========================================================================== */
/* COREOGRAFIA DE ENTRADA E SAÍDA (Alta Precisão com Keyframes) */
/* ========================================================================== */
/* 1. Base limpa (removemos as transitions que davam conflito) */
.icone_giratorio_de_carregamento,
.texto_de_mensagem_de_cortina {
	opacity: 0;
}

/* 2. A ENTRADA: Ícone entra a 0s, Texto entra exatamente 0.3s depois */
.cortina_de_carregamento_global.estado_visivel_de_cortina .icone_giratorio_de_carregamento {
	animation: animacao_de_surgimento_suave 0.4s ease-out both, animacao_de_giro_de_icone 1s linear infinite;
	animation-delay: 0s, 0s; 
}
.cortina_de_carregamento_global.estado_visivel_de_cortina .texto_de_mensagem_de_cortina {
	animation: animacao_de_surgimento_suave 0.4s ease-out both;
	animation-delay: 0.3s; /* O texto espera 0.3s no escuro para surgir */
}

/* Os Motores de Opacidade Semânticos */
@keyframes animacao_de_surgimento_suave {
	0% { opacity: 0; }
	100% { opacity: 1; }
}

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

/* ==========================================================================
   COREOGRAFIA DA CORTINA DE SUAVIDADE

   O recarregamento pós-acesso é dividido em dois atos, e o cliente não pode
   perceber a emenda entre eles. O primeiro acontece na página que está sendo
   deixada; o segundo, na que chega. O truque inteiro está em a cortina do
   segundo ato já nascer no lugar exato onde a do primeiro parou.
   ========================================================================== */

/* --- ATO I, na página que sai: o texto se despede antes do recarregamento --- */
.cortina_de_carregamento_global.retirar_texto_de_cortina .texto_de_mensagem_de_cortina {
	opacity: 1;
	animation: animacao_de_desaparecimento_suave 0.3s ease-in forwards !important;
	animation-delay: 0s !important;
}

/* --- ATO II, na página que chega: a cortina não NASCE, ela CONTINUA ---

   A classe abaixo é posta na raiz do documento por um script que roda antes de
   qualquer desenho na tela. Sem isso, a cortina da página nova começaria
   invisível e faria a sua animação de entrada — e o cliente veria, por uma
   fração de segundo, a página crua por baixo antes de o branco cobrir tudo.
   Justamente o piscar que a cortina existe para esconder.

   Aqui não há transição nem animação de entrada: a cortina e o círculo já
   aparecem sólidos no primeiro quadro. */
:root.modo_de_recarregamento_pos_login .cortina_de_carregamento_global {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	background-color: rgba(255, 255, 255, 1);
	transition: none;
}

:root.modo_de_recarregamento_pos_login .icone_giratorio_de_carregamento {
	opacity: 1;
	animation: animacao_de_giro_de_icone 1s linear infinite;
}

/* O texto pulsa enquanto a página se monta por baixo. É o sinal de que existe
   trabalho acontecendo — um círculo girando sozinho, parado no branco, dá a
   impressão de tela travada. */
:root.modo_de_recarregamento_pos_login .texto_de_mensagem_de_cortina {
	opacity: 1;
	animation: animacao_de_pulso_de_texto 1.6s ease-in-out infinite;
}

@keyframes animacao_de_pulso_de_texto {
	0%, 100% { opacity: 0.3; }
	50% { opacity: 1; }
}

/* --- ATO II, o desfecho: primeiro o palco esvazia, depois o pano sobe --- */

/* O pulso é interrompido no ponto em que estiver e o texto sai por cima disso.
   O !important existe porque a regra de pulso acima também é forte. */
:root.modo_de_recarregamento_pos_login .cortina_de_carregamento_global.retirar_elenco_de_cortina .texto_de_mensagem_de_cortina,
.cortina_de_carregamento_global.retirar_elenco_de_cortina .texto_de_mensagem_de_cortina {
	animation: animacao_de_desaparecimento_suave 0.35s ease-in forwards !important;
}

:root.modo_de_recarregamento_pos_login .cortina_de_carregamento_global.retirar_elenco_de_cortina .icone_giratorio_de_carregamento,
.cortina_de_carregamento_global.retirar_elenco_de_cortina .icone_giratorio_de_carregamento {
	animation: animacao_de_desaparecimento_suave 0.4s ease-in forwards,
			   animacao_de_giro_de_icone 1s linear infinite !important;
	animation-delay: 0.1s, 0s !important;
}

/* Só depois de o elenco sair é que o pano sobe. A transição precisa ser
   devolvida à cortina, porque o modo de recarregamento a havia desligado para
   garantir o primeiro quadro sólido. */
:root.modo_de_recarregamento_pos_login .cortina_de_carregamento_global.retirar_cortina {
	transition: opacity 0.45s ease-in-out, visibility 0.45s;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

/* ==========================================================================
   CARROSSEL DE ITENS SALVOS (ESTILO NETFLIX COM ANCORAGEM MAGNÉTICA)
   ========================================================================== */

.recipiente_de_carrossel_de_itens_salvos {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    gap: 12px;
    padding-bottom: 10px;
    
    /* Esconde a barra de rolagem em todos os navegadores para visual de aplicativo */
    -ms-overflow-style: none;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}

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

/* ==========================================================================
   O CARTÃO DE ITEM GUARDADO

   De cima para baixo: etiqueta de origem, foto de fora a fora, nome, a linha de
   variação e preço, e o botão largo no rodapé. É a mesma leitura do cartão da
   vitrine, em miniatura — quem já entendeu a grade não precisa aprender outro
   cartão para entender o carrossel.

   O PADDING SAIU DO CARTÃO E FOI PARA DENTRO. Ele existia para afastar o texto
   das bordas, e fazia isso bem; só que a foto precisa encostar nas laterais, e
   um padding no pai impede qualquer filho de alcançar a borda. Agora quem recua
   o texto é o corpo do cartão, e a foto fica livre para ir de ponta a ponta.

   O CARTÃO INTEIRO É CLICÁVEL, e o `cursor` é o que anuncia isso antes do toque.
   ========================================================================== */
.cartao_de_item_salvo {
    /* INJEÇÃO TITANIUM: Largura cravada e perfeita para celular e computador */
    flex: 0 0 180px;
    width: 180px;
    scroll-snap-align: start;

    /* A âncora da etiqueta flutuante, que se posiciona sobre a foto. */
    position: relative;

    background-color: var(--cor_de_superficie);
    border: 1px solid var(--cor_de_divisor);
    border-radius: var(--raio_de_canto_de_cartao);
    display: flex;
    flex-direction: column;
    align-items: stretch;
    text-align: center;
    box-sizing: border-box;
    cursor: pointer;

    /* INJEÇÃO TITANIUM: O motor do deslizamento suave (Layout Reflow) */
    transition: all 0.4s ease-in-out;
    transform-origin: center;
    overflow: hidden;
}

.cartao_de_item_salvo:hover {
    border-color: var(--cor_de_conversao);
    box-shadow: var(--sombra_de_cartao);
}

/* A ETIQUETA DE ORIGEM FLUTUA SOBRE A FOTO, no canto superior esquerdo.

   Ela ocupava uma faixa própria acima da imagem, e essa faixa custava duas
   coisas: o espaço dela, e o topo da foto — que passava a começar no meio do
   cartão em vez de na borda. Tirada do fluxo, a imagem sobe até encostar no topo
   e o cartão ganha a mesma silhueta do da vitrine.

   O FUNDO CLARO DA PÍLULA É O QUE A TORNA POSSÍVEL. Solta sobre a foto, ela
   dependeria de a imagem ser escura o bastante para o texto colorido aparecer —
   e as fotos do catálogo são claras. Com o fundo próprio, a legibilidade não
   depende mais da foto que alguém cadastrar amanhã. O leve desfoque atrás resolve
   o caso da foto clara demais, onde branco sobre branco sumiria.

   O CANTO ESQUERDO, e não centralizada: é onde a leitura começa, e deixa o canto
   direito livre para o que vier a morar ali. */
.cartao_de_item_salvo .etiqueta_de_origem_de_prateleira {
    position: absolute;
    top: 8px;
    left: 8px;
    z-index: 2;

    margin-bottom: 0;
    padding: 4px 8px;
    max-width: calc(100% - 16px);
    box-sizing: border-box;

    background-color: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    border-radius: 6px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);

    font-size: 10px;
    line-height: 1.3;
    letter-spacing: 0.3px;
    text-align: left;

    /* Nome longo de origem não pode empurrar a pílula por cima da foto inteira. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A MOLDURA DA FOTO TEM ALTURA FIXA, e a imagem preenche por corte.
   Sem altura fixa, cada cartão do carrossel teria um tamanho conforme a foto que
   o catálogo cadastrou, e a fila inteira ficaria irregular. O `object-fit`
   garante que o corte aconteça na imagem, e não na proporção dela. */
.moldura_de_foto_de_item_salvo {
    width: 100%;
    height: 110px;
    background-color: var(--cor_de_superficie_suave);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    flex-shrink: 0;
}

.imagem_de_item_salvo {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* O corpo recebe o padding que saiu do cartão, e o `margin-top: auto` do botão
   empurra-o para o rodapé — assim cartões com nomes de uma ou de três linhas
   terminam com o botão na mesma altura. */
.corpo_de_cartao_de_item_salvo {
    display: flex;
    flex-direction: column;
    flex-grow: 1;
    padding: 12px;
    gap: 6px;
}

/* A VARIAÇÃO E O PREÇO ANDAM JUNTOS, ENCOSTADOS À DIREITA.

   Eles ficavam nas duas pontas da linha, e a distância entre os dois obrigava o
   olho a atravessar o cartão para juntar duas informações que só fazem sentido
   uma ao lado da outra: "300g" e "R$ 29,40" são a mesma frase — este peso custa
   isto. Separados, pareciam dois dados independentes.

   SEM `margin-top: auto`. Ele empurrava esta linha para o rodapé, e o vão que
   sobrava entre o nome e o preço fazia o cartão parecer um formulário pela
   metade. */
.linha_de_variacao_e_preco_de_item_salvo {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}

/* O BLOQUINHO DE PESO É CINZA, e não verde.

   O verde é a cor de conversão desta loja: ele está no preço da vitrine, na
   pílula escolhida, no botão de comprar. Usá-lo aqui, num rótulo que só informa
   qual peso é este, gastava a cor mais forte da marca com o dado menos decisivo
   do cartão — e disputava atenção com o próprio preço ao lado.

   Em cinza, ele faz o que um rótulo deve fazer: diz o que precisa dizer e sai da
   frente. A hierarquia do cartão passa a ser a foto, o nome e o botão.

   O CINZA VAI ATÉ ONDE A LEITURA PERMITE. O texto usa o cinza médio da paleta, e
   não o mais claro: cinza clarinho sobre fundo claro é legível para quem desenha
   a tela olhando de perto, e deixa de ser para quem lê no sol com o celular na
   mão.

   O `position: relative` é a âncora da moedinha de quantidade. */
.selo_de_variacao_de_item_salvo {
    position: relative;
    display: inline-flex;
    align-items: center;
    padding: 3px 6px;
    background-color: var(--cor_de_superficie_suave);
    border: 1px solid var(--cor_de_borda_suave);
    border-radius: 4px;
    color: var(--cor_de_texto_suave);
    font-size: 9px;
    font-weight: bold;
    white-space: nowrap;
}

/* A moedinha de quantidade, no mesmo canto e com o mesmo desenho da que vive nos
   bloquinhos da vitrine, encolhida na mesma proporção do selo que a carrega. Ela
   só é impressa quando há número — o cartão de favorito simplesmente não a
   recebe, porque um coração não tem unidades. */
.selo_de_quantidade_de_item_salvo {
    position: absolute;
    top: -7px;
    right: -7px;
    min-width: 15px;
    height: 15px;
    padding: 0 3px;
    box-sizing: border-box;
    background-color: var(--cor_de_conversao);
    color: var(--cor_de_texto_sobre_cor);
    border: 2px solid var(--cor_de_superficie);
    border-radius: 8px;
    font-size: 9px;
    font-weight: 700;
    line-height: 11px;
    text-align: center;
}

/* O PREÇO ACOMPANHA O PESO NO CINZA.

   Ele era verde, e o verde aqui não estava pedindo nada: neste cartão quem chama
   para a ação é o botão, e o preço é referência — o cliente já escolheu este item
   antes, e está reencontrando o que guardou. Deixá-lo em cinza junto do peso faz
   os dois lerem como uma informação só, e devolve ao botão o único ponto de cor
   forte do rodapé.

   O CORPO CONTINUA MAIOR QUE O DO PESO. Perder a cor não é perder a hierarquia:
   entre os dois, o preço ainda é o que decide, e o tamanho é o que diz isso. */
.texto_de_preco_de_item_salvo {
    color: var(--cor_de_texto_suave);
    font-size: 14px;
    font-weight: bold;
    white-space: nowrap;
}

/* ==========================================================================
   O ESTADO ENCOLHIDO, USADO NOS DOIS SENTIDOS

   Ele nasceu para a saída: o cartão fecha sobre si mesmo e os vizinhos deslizam
   para ocupar o buraco, em vez de a pista dar um salto quando o elemento é
   retirado do documento. A entrada de um cartão novo é exatamente o mesmo estado
   lido ao contrário — ele nasce fechado e cresce até a largura natural,
   empurrando os vizinhos para abrir o próprio espaço. Por isso as duas classes
   dividem a mesma regra: são o mesmo lugar, percorrido em direções opostas.

   Quem anima é a `transition: all 0.4s` que o cartão já declara.
   ========================================================================== */
.cartao_de_item_salvo.estado_de_remocao_suave,
.cartao_de_item_salvo.estado_de_entrada_de_cartao_novo {
    flex: 0 0 0px;
    width: 0px;

    /* INJEÇÃO TITANIUM: Novas travas verticais para anular o "pulo" do texto */
    height: 0px;
    padding: 0px;

    margin-right: -12px; /* Compensa exatamente o 'gap' do carrossel para fechar o buraco */
    opacity: 0;
    transform: scale(0);
    border-width: 0;
}

/* ==========================================================================
   A ENTRADA EM CASCATA DA PRATELEIRA INTEIRA

   Mesma coreografia da lista do carrinho: cada cartão espera a sua vez, o atraso
   sai de `--indice` multiplicado aqui — assim a prateleira pode ter três ou
   trinta itens sem que o JavaScript precise saber de tempos — e o teto de oito
   posições existe porque cascata é tempero, não espera.

   A ANIMAÇÃO NASCE PAUSADA, e é isso que espera o cliente chegar. Com `both`, o
   primeiro quadro já vale desde o começo: o cartão fica invisível e encolhido
   sem nunca ter piscado, mesmo que a prateleira tenha sido montada com a página
   rolada três telas abaixo. Quando ela entra no campo de visão, o JavaScript
   marca o bloco e as animações destravam todas de uma vez, cada uma no seu
   degrau.
   ========================================================================== */
@keyframes animacao_de_entrada_de_cartao_de_prateleira {
    from {
        opacity: 0;
        transform: scale(0.92) translateY(10px);
    }
    to {
        opacity: 1;
        transform: scale(1) translateY(0);
    }
}

.cartao_de_item_salvo.estado_de_entrada_em_cascata_de_prateleira {
    animation: animacao_de_entrada_de_cartao_de_prateleira 0.38s
        cubic-bezier(0.25, 1, 0.5, 1) both;
    animation-delay: calc(min(var(--indice, 0), 8) * 55ms);
    animation-play-state: paused;
}

.bloco_de_prateleira_com_coreografia_liberada
    .cartao_de_item_salvo.estado_de_entrada_em_cascata_de_prateleira {
    animation-play-state: running;
}

/* O miolo fechado enquanto a coreografia espera a sua vez. O bloco em volta
   continua no layout — é ele que o observador precisa enxergar para saber que
   chegou a hora —, mas nada dentro dele ocupa altura até lá, e por isso a página
   de quem está lendo outra seção não salta. */
.recipiente_de_prateleira_aguardando_entrada {
    height: 0;
    overflow: hidden;
}

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

.miniatura_de_item_salvo {
    font-size: 32px;
    margin-bottom: 10px;
}

/* O NOME DO PRODUTO

   A ALTURA FIXA SAIU. Ela reservava duas linhas em todo cartão, e o produto de
   nome curto — a maioria — pagava por uma linha vazia que nunca usaria. Agora o
   nome ocupa o que precisa, e quem iguala a altura entre os cartões vizinhos é
   `igualar_alturas_de_titulos_de_cartoes_salvos`, no JavaScript.

   POR QUE ISSO NÃO É CSS. Num carrossel flex, a altura de um elemento interno não
   enxerga a dos irmãos: cada cartão resolve o próprio layout sozinho. Só um
   contêiner de grade compartilhada — `subgrid` — faria isso em CSS puro, e ele
   não convive bem com o scroll-snap horizontal que o carrossel usa. Medir o maior
   e aplicar aos demais é determinístico e funciona em qualquer navegador.

   O corte em duas linhas continua: é o teto do que o cartão comporta antes de o
   nome empurrar o preço e o botão para fora do campo de visão. */
.texto_de_nome_de_item_salvo {
    font-size: 13px;
    font-weight: bold;
    color: var(--cor_de_texto_principal);
    line-height: 1.4;

    /* Limita o texto a 2 linhas e adiciona reticências se for maior */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2; /* INJEÇÃO TITANIUM: O Padrão Oficial do Futuro! */
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;

	padding-bottom: 7px; /* Dá um respiro entre o nome e a linha de variação/preço */

    /* A RÉGUA DOS TÍTULOS MUDA DE ALTURA SEM TRANCO.
       Quando um produto de nome longo entra ou sai do carrossel, a altura de
       TODOS os títulos muda junto — e, sem esta transição, o preço e o botão de
       cada cartão davam um salto de vinte pixels no meio da tela. Quem escreve a
       altura é `igualar_alturas_de_titulos_de_cartoes_salvos`, e ela devolve o
       valor anterior em pixels antes de aplicar o novo justamente para que haja
       dois números para percorrer aqui. */
    transition: height 0.3s ease;
}

/* Quem pediu para o sistema não animar recebe a mudança de altura pronta. */
@media (prefers-reduced-motion: reduce) {
    .texto_de_nome_de_item_salvo {
        transition: none;
    }
}

/* O rótulo diz para onde o item vai, em maiúsculas e sem o "+".

   O SINAL DE MAIS ERA REDUNDANTE: o texto já diz o que o toque faz, e o "+"
   herdava a leitura dos botões de quantidade da vitrine, onde ele significa
   "mais um" — aqui não é isso, é "leve para o carrinho".

   AS MAIÚSCULAS SÃO O QUE DÁ PESO SEM PEDIR TAMANHO. Num cartão de 180px o texto
   não pode crescer, e a caixa alta com um respiro entre as letras rende a
   presença que o corpo maior daria, sem quebrar em duas linhas. O corpo continua
   confortável de ler porque a caixa alta não tem descidas nem subidas — ela ocupa
   uma faixa uniforme, e por isso se lê bem menor do que a caixa baixa. */
.botao_de_restauracao_de_carrossel {
    width: 100%;
    background-color: transparent;
    border: 1px solid var(--cor_de_informacao);
    color: var(--cor_de_informacao);
    border-radius: 6px;

    /* O corpo e o espaçamento foram medidos contra o pior caso: "ADICIONAR AO
       CARRINHO" em caixa alta dentro dos 180px do cartão da vitrine, que deixam
       154px livres para o texto. Em 10px com 0,3px entre letras ele ocupa 147px e
       cabe numa linha; em 11px passaria de 168px e quebraria em duas, deixando o
       botão com o dobro da altura. No checkout, onde o cartão único é o dobro de
       largo, sobra folga de qualquer maneira.

       A ALTURA DO ALVO DE TOQUE NÃO ENCOLHEU: o corpo menor foi compensado no
       `padding` vertical, e o botão continua com a largura inteira do cartão. */
    padding: 13px 4px;
    font-size: 10px;
    font-weight: bold;
    letter-spacing: 0.3px;
    text-transform: uppercase;
    line-height: 1.2;
    cursor: pointer;
    transition: all 0.2s ease;
}

.botao_de_restauracao_de_carrossel:hover {
    background-color: var(--cor_de_informacao);
    color: white;
}

/* ==========================================================================
   BOTOES DE NAVEGACAO DE CARROSSEL (EXCLUSIVO PARA COMPUTADOR)
   ========================================================================== */

/* Essa envoltória garante que as setas flutuem perfeitamente alinhadas ao carrossel */
.envoltoria_de_carrossel {
    position: relative;
    width: 100%;
}

.botao_de_navegacao_de_carrossel {
    display: none; /* Escondido por padrão (será ativado pelo media query abaixo) */
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 40px;
    height: 40px;
    background-color: var(--cor_de_superficie);
    border: 1px solid var(--cor_de_divisor);
    border-radius: 50%;
    box-shadow: 0 4px 10px rgba(0,0,0,0.1);
    font-size: 18px;
    color: var(--cor_de_texto_principal);
    cursor: pointer;
    z-index: 10;
    align-items: center;
    justify-content: center;
    transition: opacity 0.3s ease, visibility 0.3s ease; /* Transição suave de esmaecimento */
}

.botao_de_navegacao_de_carrossel:hover {
    background-color: var(--cor_de_superficie_suave);
    box-shadow: 0 6px 14px rgba(0,0,0,0.15);
}

/* Posições extremas das setas (ficam um pouquinho para fora do carrossel) */
.botao_de_navegacao_de_carrossel_esquerda {
    left: -15px;
}

.botao_de_navegacao_de_carrossel_direita {
    right: -15px;
}

/* A Classe Mágica que o JavaScript vai injetar e remover */
.estado_oculto_de_botao {
    opacity: 0;
    visibility: hidden;
    pointer-events: none; /* Evita que o cliente clique em uma seta invisível */
}

/* Regra de Ouro: Só mostra as setas se a tela for maior que um celular (769px+) */
@media (min-width: 769px) {
    .botao_de_navegacao_de_carrossel {
        display: flex;
    }
}
/* ==============================================================================
   A ENTRADA DAS JANELAS FLUTUANTES

   A janela aparecia de uma vez, no quadro em que a classe de ocultação saía. Não
   havia nada de errado tecnicamente, mas o olho perde a referência: um bloco
   grande que surge pronto no meio da tela não conta de onde veio, e o cliente
   precisa reencontrar o que estava fazendo.

   O zoom curto resolve isso dizendo "isto cresceu daqui". São 0,26s — tempo de
   perceber o movimento sem esperar por ele.

   POR QUE `:not(.estado_oculto)` E NÃO UMA CLASSE DE ABERTURA: a janela é aberta
   retirando .estado_oculto, e uma animação de CSS recomeça sozinha quando o
   elemento volta a ser desenhado. Amarrar a animação à ausência da classe
   dispensa o JavaScript de acender e apagar um segundo estado só para animar —
   ele continua fazendo uma coisa só, que é abrir e fechar.
============================================================================== */

@keyframes animacao_de_surgimento_em_zoom {
	from {
		opacity: 0;
		transform: scale(0.92);
	}
	to {
		opacity: 1;
		transform: scale(1);
	}
}

@keyframes animacao_de_escurecimento_de_fundo {
	from { opacity: 0; }
	to   { opacity: 1; }
}

/* O `:not(.estado_saindo)` NÃO É REDUNDANTE. Durante o fechamento a janela ainda
   não recebeu .estado_oculto — é justamente por isso que ela continua na tela
   para poder animar —, então sem esta exclusão a regra de ENTRADA continuaria
   valendo ao mesmo tempo que a de saída. Funcionaria por acidente, porque a de
   saída está declarada depois e venceria o empate de especificidade; bastaria
   alguém reordenar o arquivo para a janela voltar a piscar ao fechar. */
.fundo_de_janela_flutuante:not(.estado_oculto):not(.estado_saindo) {
	animation: animacao_de_escurecimento_de_fundo 0.22s ease-out;
}

.fundo_de_janela_flutuante:not(.estado_oculto):not(.estado_saindo)
	.conteudo_de_janela_flutuante {
	animation: animacao_de_surgimento_em_zoom 0.26s cubic-bezier(0.25, 1, 0.5, 1);
}

/* Quem pediu menos movimento ao sistema operacional continua vendo a janela
   abrir — o que some é a escala. Mesmo tratamento que a torrada já recebe. */
@media (prefers-reduced-motion: reduce) {
	.fundo_de_janela_flutuante:not(.estado_oculto):not(.estado_saindo),
	.fundo_de_janela_flutuante:not(.estado_oculto):not(.estado_saindo)
		.conteudo_de_janela_flutuante {
		animation: none;
	}
}

/* ==============================================================================
   O RESPIRO DAS JANELAS NO CELULAR

   A janela de detalhes de produto encostava nas bordas da tela: o conteúdo dela
   cresce com a descrição, e ao passar da altura disponível ela ficava colada em
   cima e embaixo, sem margem nenhuma. A de carrinho não sofria disso porque tem
   um teto de altura próprio, declarado no HTML.

   O respiro passa a ser do FUNDO, e não de cada janela: assim as duas ficam
   igualmente afastadas das quatro bordas, e qualquer janela nova nasce com o
   mesmo enquadramento sem precisar declarar nada.
============================================================================== */

@media (max-width: 768px) {
	.fundo_de_janela_flutuante {
		padding: 18px;
		box-sizing: border-box;
	}

	.fundo_de_janela_flutuante .conteudo_de_janela_flutuante {
		/* Os 90% da regra geral eram medidos contra a tela inteira; agora a
		   largura é medida dentro do respiro, então 100% já vem afastado. */
		width: 100%;

		/* dvh acompanha a barra de endereço do navegador, que aparece e some
		   conforme o cliente rola. Os 36px descontam o respiro de cima e de baixo. */
		max-height: calc(100dvh - 36px);
	}

	/* Os 30px de recheio da regra geral apertam o texto numa tela estreita: sobra
	   pouca largura útil e a leitura vira uma coluna fina. */
	#fundo_de_janela_flutuante_de_detalhes .conteudo_de_janela_flutuante {
		padding: 24px 20px;
	}
}

/* ==============================================================================
   A SAÍDA DAS JANELAS FLUTUANTES

   Abrir já tinha coreografia; fechar não tinha nenhuma — a janela simplesmente
   deixava de existir no quadro seguinte. O desequilíbrio se nota: a mesma janela
   que cresceu suavemente desaparecia com um corte seco.

   COMO FUNCIONA A CONVERSA COM O JAVASCRIPT: ele põe .estado_saindo, espera o
   tempo da animação e só então põe .estado_oculto. Enquanto .estado_saindo está
   presente a janela ainda ocupa a tela, então a animação tem o que animar.

   O `forwards` no final é o que impede o piscar: sem ele, o último quadro da
   animação seria descartado e a janela reapareceria inteira por um instante,
   antes de o JavaScript conseguir escondê-la.
============================================================================== */

@keyframes animacao_de_saida_em_zoom {
	from {
		opacity: 1;
		transform: scale(1);
	}
	to {
		opacity: 0;
		transform: scale(0.94);
	}
}

@keyframes animacao_de_clareamento_de_fundo {
	from { opacity: 1; }
	to   { opacity: 0; }
}

.fundo_de_janela_flutuante.estado_saindo {
	animation: animacao_de_clareamento_de_fundo 0.2s ease-in forwards;

	/* Durante a saída a janela não aceita mais cliques: sem isto, um toque no
	   intervalo entre o começo da animação e o fim dela reabriria o que está
	   fechando. */
	pointer-events: none;
}

.fundo_de_janela_flutuante.estado_saindo .conteudo_de_janela_flutuante {
	animation: animacao_de_saida_em_zoom 0.2s ease-in forwards;
}

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


/* ==============================================================================
   ==============================================================================
   AS PÍLULAS DE ORDENAÇÃO

   VIERAM DE `vitrine_de_loja.css` EM 2026-08-03, e o motivo da mudança é o motivo
   desta camada existir: elas deixaram de ser só da trilha de categorias da
   vitrine. A janela do carrinho e a lista de itens da página de pagamento
   passaram a ter as mesmas duas no canto do título, para ordenar os itens do
   pedido — e esta folha é a única carregada pelas duas telas.

   Cor própria, verde, para se distinguirem das categorias em laranja: elas não
   competem com o filtro de categoria, se somam a ele. Uma ordenação e categorias
   podem estar acesas ao mesmo tempo.

   Cada pílula é um interruptor de três tempos: apagada → crescente → decrescente →
   apagada. Um clique só, no mesmo lugar, em vez de duas pílulas irmãs.
============================================================================== */
.pilula_de_ordenacao {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	background-color: var(--cor_de_conversao_clara);
	border: 0px solid #2ecc71;
	color: var(--cor_de_conversao);
	padding: 8px 16px;
	border-radius: 7px;
	font-size: 14px;
	font-weight: 500;
	cursor: pointer;
	transition: all 0.2s ease;
	flex-shrink: 0;
	outline: none;
	white-space: nowrap;
}

.pilula_de_ordenacao:hover {
	background-color: #d5f5e3;
}

.pilula_de_ordenacao.pilula_de_ordenacao_ativa {
	background-color: var(--cor_de_conversao);
	color: var(--cor_de_texto_sobre_cor);
	font-weight: 600;
}

/* AS SETAS DO PREÇO: as duas estão sempre lá, e o destaque é que diz o sentido.
   Apagadas elas ficam discretas; a do sentido em uso cresce e ganha opacidade. */
/* ==============================================================================
   AS DUAS SETAS DA ORDENAÇÃO, EMPILHADAS

   Eram dois emojis lado a lado, e emoji traz consigo a cor e o desenho do sistema
   operacional: a mesma pílula ficava diferente no iPhone, no Android e no
   Windows, e a cor deles não obedecia à da pílula. Os triângulos geométricos são
   TEXTO — herdam a cor de quem os contém e mudam de estado sem trocar de fonte.

   O PAR DIZ O ESTADO SOZINHO, sem depender de opacidade: as duas vazadas
   significam "não estou ordenando por isto"; a de cima cheia, crescente; a de
   baixo cheia, decrescente. O contorno permanece visível nos dois casos, então o
   cliente vê que existe o outro sentido para onde ir.

   QUEM ESCREVE O CARACTERE É O CSS, pelo `content`. Assim o JavaScript continua
   apenas trocando a classe de sentido na pílula, como sempre fez, sem precisar
   saber que triângulos existem.
============================================================================== */
.pilha_de_setas_de_ordenacao {
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;

	/* Alinha o par com a linha do texto ao lado, em vez de com a base dele. */
	vertical-align: middle;
	margin-left: 5px;

	/* A entrelinha aperta o par para ele caber na altura da pílula sem esticá-la.
	   Foi a 0,72 primeiro, e nesse valor os dois triângulos se encostavam pelas
	   pontas e liam como um losango — uma forma só, em vez de duas setas opostas.
	   0,95 devolve a folga que separa os dois desenhos e ainda cabe na pílula. */
	line-height: 0.95;

	/* A ALTURA DA PILHA É FIXA, e é isto que impede a pílula de crescer ao ser
	   escolhida. A seta ativa passa de 9px para 12px, e sem uma caixa de altura
	   travada esse aumento subia para o botão: a pílula ia de 33px para 36px a
	   cada clique, empurrando a linha inteira e desalinhando-a das categorias, que
	   têm 35px. Com a altura presa, o triângulo cresce por dentro e nada se move
	   em volta.

	   O valor é o que faz esta pílula terminar com a mesma altura das categorias:
	   com 22px ela ficava 3px mais alta que as vizinhas, e a fila perdia a linha
	   de base comum. */
	height: 19px;
	overflow: hidden;
}

/* A SETA ESCOLHIDA É MAIOR QUE A OUTRA — E ISSO CORRIGE UMA ILUSÃO, NÃO UM
   CAPRICHO.

   No mesmo corpo, o triângulo cheio parece MENOR que o vazado. O vazado tem o
   traço do contorno somado à silhueta, e é essa borda que engorda o desenho aos
   olhos; o cheio termina exatamente onde a forma termina. Deixar os dois em 10px
   fazia o escolhido — que é o que precisa se impor — parecer o miúdo dos dois.

   Os dois números se afastam pelos dois lados: o inativo desce para 9px e o ativo
   sobe para 12px. Só aumentar o ativo empurraria a pílula para cima, porque a
   pilha das duas setas é o que dita a altura dela. */
.seta_de_ordenacao {
	font-size: 9px;
	opacity: 0.45;
	transition: opacity 0.2s ease, font-size 0.2s ease;
}

.seta_de_ordenacao_crescente::before {
	content: "△";
}

.seta_de_ordenacao_decrescente::before {
	content: "▽";
}

.pilula_de_ordenacao.sentido_crescente .seta_de_ordenacao_crescente::before {
	content: "▲";
}

.pilula_de_ordenacao.sentido_decrescente .seta_de_ordenacao_decrescente::before {
	content: "▼";
}

.pilula_de_ordenacao.sentido_crescente .seta_de_ordenacao_crescente,
.pilula_de_ordenacao.sentido_decrescente .seta_de_ordenacao_decrescente {
	opacity: 1;
	font-size: 12px;
}


/* ==============================================================================
   O CABEÇALHO QUE DIVIDE A LINHA COM AS PÍLULAS

   Serve aos dois títulos: "Meu Carrinho", na janela flutuante da vitrine, e
   "Itens do Pedido", na coluna lateral do checkout. O `gap` com quebra permite
   que as pílulas desçam para uma segunda linha quando o título for longo ou a
   fonte do sistema estiver ampliada, em vez de espremerem o título.
============================================================================== */
.cabecalho_de_secao_com_ordenacao {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 8px 12px;
}

/* O `margin-left: auto` mantém o grupo colado à direita mesmo quando a linha
   quebra e ele passa a ser o único elemento da segunda linha. */
.grupo_de_pilulas_de_ordenacao_de_carrinho {
	display: flex;
	align-items: center;
	gap: 6px;
	margin-left: auto;
	flex-shrink: 0;
}

/* ==============================================================================
   AS PÍLULAS, NA VERSÃO DE CARRINHO

   Menores que as da trilha da vitrine, e por uma razão de espaço: lá elas são o
   comando principal de uma faixa larga; aqui dividem a linha com um título, na
   coluna estreita do checkout. O desenho, as cores e os três estados são os
   mesmos — só as medidas encolhem.
============================================================================== */
.pilula_de_ordenacao_de_carrinho {
	padding: 5px 10px;
	font-size: 12px;
	gap: 4px;
}

/* O CIFRÃO NÃO PODE SUMIR AQUI.

   `vitrine_de_loja.css` esconde `.rotulo_curto_de_ordenacao_de_preco` acima de
   768px, porque na trilha larga da vitrine a palavra "Preço" toma o lugar dele.
   A pílula do carrinho nunca teve a palavra — só o cifrão —, então aquela regra
   a deixaria com um botão de setas e nenhum rótulo em tela de computador. Esta
   linha a devolve, e precisa do seletor mais específico para vencer a media
   query que vem depois na cascata. */
.pilula_de_ordenacao_de_carrinho .rotulo_curto_de_ordenacao_de_preco {
	display: inline !important;
}

/* A pilha de setas do carrinho acompanha o corpo menor da pílula */
.pilula_de_ordenacao_de_carrinho .pilha_de_setas_de_ordenacao {
	margin-left: 3px;
	height: 17px;
}

/* O BOTÃO DE FECHAR JÁ OCUPAVA ESSE CANTO.

   Na janela flutuante do carrinho, o "×" é `position: absolute` a 20px da borda
   direita e mede 28px — ou seja, ele flutua POR CIMA do cabeçalho, e a linha do
   título não sabe que ele existe. As pílulas de ordenação chegaram nesse mesmo
   canto e passaram por baixo dele: o A-Z ficava com o × atravessado na letra.

   A margem reserva a faixa dele (28px do botão + 20px da borda, arredondado para
   54px de folga). Vale só dentro desta janela — na página de pagamento não há
   botão de fechar nenhum, e lá a margem só afastaria as pílulas da borda sem
   motivo. */
#fundo_de_janela_flutuante_de_carrinho .grupo_de_pilulas_de_ordenacao_de_carrinho {
	margin-right: 54px;
}

/* ==============================================================================
   O TRAÇO ABAIXO DO TÍTULO MUDA DE DONO

   `.titulo_de_secao` carrega o próprio `border-bottom`, e isso funcionava
   enquanto o `<h2>` era um bloco ocupando a linha inteira. Ao virar item de um
   flex, ele passou a medir só o texto — e o traço encolheu junto, parando no fim
   de "Itens do Pedido" em vez de atravessar a coluna.

   A borda passa para o cabeçalho, que é quem tem a largura toda. `com_traco_de_secao`
   é classe à parte, e não comportamento automático deste cabeçalho, porque a
   janela do carrinho da vitrine já tem o traço dela na div de cima: lá, uma borda
   aqui desenharia duas linhas paralelas.
============================================================================== */
.cabecalho_de_secao_com_ordenacao.com_traco_de_secao {
	border-bottom: 2px solid var(--cor_de_divisor);
	padding-bottom: 15px;
	margin-bottom: 20px;
}

.cabecalho_de_secao_com_ordenacao.com_traco_de_secao .titulo_de_secao {
	border-bottom: none;
	padding-bottom: 0;
	margin-bottom: 0;
}
