/**
 * Animations — reveal on scroll, microinteracciones, hero.
 *
 * Contrato: el sitio es 100% usable sin JS y sin estas animaciones. El
 * estado oculto de .js-reveal solo se activa cuando <html> tiene la clase
 * "js" (agregada por main.js apenas carga) — si JS falla, nunca se llega a
 * aplicar `opacity: 0` y el contenido queda visible desde el primer render.
 */

.js-reveal {
	opacity: 1;
	transform: none;
}

html.js .js-reveal {
	opacity: 0;
	transform: translateY(28px);
	transition: opacity var(--duration-slow) var(--ease-out-expo),
		transform var(--duration-slow) var(--ease-out-expo);
	transition-delay: var(--reveal-delay, 0ms);
	will-change: opacity, transform;
}

html.js .js-reveal.is-visible {
	opacity: 1;
	transform: none;
}

/* Stagger manual vía data-reveal-index, aplicado por reveal.js */
html.js .js-reveal[data-reveal-index='1'] {
	--reveal-delay: 80ms;
}

html.js .js-reveal[data-reveal-index='2'] {
	--reveal-delay: 160ms;
}

html.js .js-reveal[data-reveal-index='3'] {
	--reveal-delay: 240ms;
}

html.js .js-reveal[data-reveal-index='4'] {
	--reveal-delay: 320ms;
}

/* -----------------------------------------------------------
 * View transitions — progressive enhancement, no-op donde no hay soporte
 * ----------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
	.product-card__media img {
		view-transition-name: none;
	}

	::view-transition-old(root),
	::view-transition-new(root) {
		animation-duration: var(--duration-base);
	}
}

/* -----------------------------------------------------------
 * Skeleton / loading sutil para imágenes de producto
 * ----------------------------------------------------------- */
.product-card__media.is-loading {
	background: linear-gradient(90deg, var(--color-surface-alt) 25%, var(--color-border) 50%, var(--color-surface-alt) 75%);
	background-size: 200% 100%;
	animation: shimmer 1.4s ease-in-out infinite;
}

@keyframes shimmer {
	from {
		background-position: 200% 0;
	}

	to {
		background-position: -200% 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	.product-card__media.is-loading {
		animation: none;
	}
}

/* -----------------------------------------------------------
 * Boot sequence (home, primera carga de la sesión) — ver assets/js/preload.js.
 *
 * Contrato: overlay puramente cosmético, nunca un gate de contenido. Por
 * default queda display:none — si JS no corre (deshabilitado, falla, tarda)
 * el overlay JAMÁS se muestra y la home es 100% usable de inmediato. Solo
 * JS lo activa (.is-active) y solo JS lo saca del DOM al terminar.
 * ----------------------------------------------------------- */
.boot-overlay {
	position: fixed;
	inset: 0;
	z-index: var(--z-overlay);
	display: none;
	align-items: center;
	justify-content: center;
	background: var(--vx-ink);
	opacity: 1;
	transform: translateY(0);
}

.boot-overlay.is-active {
	display: flex;
}

.boot-overlay__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-4);
	padding-inline: var(--space-5);
}

.boot-overlay__line {
	display: block;
	width: min(240px, 60vw);
	height: 2px;
	background: var(--vx-signal-blue);
	transform: scaleX(0);
	transform-origin: left;
}

.boot-overlay.is-animating .boot-overlay__line {
	transition: transform 500ms var(--ease-out-quart);
	transform: scaleX(1);
}

.boot-overlay__counter {
	font-family: var(--font-heading);
	font-size: var(--fs-300);
	font-weight: 600;
	letter-spacing: 0.1em;
	color: var(--vx-paper);
}

.boot-overlay__counter-value {
	font-variant-numeric: tabular-nums;
}

.boot-overlay.is-leaving {
	opacity: 0;
	transform: translateY(-12px);
	transition: opacity 400ms var(--ease-out-quart), transform 400ms var(--ease-out-quart);
	pointer-events: none;
}
