/**
 * Sections — estilos específicos de cada sección de home y de categoría.
 * Una sección por parcial, mismo nombre que en /template-parts/.
 */

/* Cabecera de sección reutilizada por varias secciones (título + intro). */
.lgzm-section__head {
	margin-bottom: 24px;
}
.lgzm-section__intro {
	color: var(--lgzm-ink-secondary);
	margin-top: 8px;
}

/* =========================================================================
   01 · Hero
   ========================================================================= */

/* align-items: stretch (valor por defecto de flex) en vez de flex-end: el
   contenido pasa a ocupar todo el alto del hero para poder repartir por
   dentro. El anclaje abajo lo sigue haciendo .lgzm-hero__content con
   justify-content: flex-end, así que visualmente los botones quedan
   exactamente donde estaban. */
.lgzm-hero {
	position: relative;
	min-height: 100svh;
	display: flex;
	overflow: hidden;
	color: var(--lgzm-on-ink);
}
@media (min-width: 1024px) {
	.lgzm-hero {
		min-height: 780px;
	}
}

.lgzm-hero__media {
	position: absolute;
	inset: 0;
	z-index: 0;
}
.lgzm-hero__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0;
	transition: opacity 900ms var(--lgzm-ease-out);
}
.lgzm-hero__img.is-active {
	opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
	.lgzm-hero__img {
		transition: none;
	}
}
.lgzm-hero__media--placeholder {
	width: 100%;
	height: 100%;
	background: #5c6175;
}

/* ---------- Masonry de fondo (template-parts/home/hero-masonry.php) ----------
   Cinco columnas (tres en móvil) que se desplazan en vertical en direcciones
   alternas. Cada columna lleva su lista de fotos DUPLICADA y se anima -50%:
   al terminar la primera copia, la segunda está exactamente donde empezó
   aquélla, así que el reinicio del bucle no se ve.

   Antes de duplicarla, cada columna repite su propia lista hasta un mínimo
   de 6 fotos (legazyum_hero_masonry_columnas() en helpers.php): así ninguna
   columna se queda con menos altura de contenido que el hero, sea cual sea
   el número de fotos del cliente — sin esto aparecía un hueco vacío debajo
   de las columnas con pocas fotos, bug real encontrado con fotos reales
   (2026-09-02). */
/* Sin position aquí a propósito: el elemento ya lleva también la clase
   .lgzm-hero__media (mismo <div>, ver hero-masonry.php), que le da
   position:absolute + inset:0 y por tanto su alto real (el del hero).
   Redeclarar position:relative aquí lo pisaría (misma especificidad, este
   archivo carga después) y lo dejaría en alto 0 — justo lo que pasó al
   escribir este arreglo la primera vez, encontrado antes de que llegara a
   producción gracias a probarlo con fotos reales del cliente (2026-09-02):
   position:absolute también sirve de contexto de posicionamiento para los
   .lgzm-masonry-set de abajo, así que no hace falta tocar nada aquí. */
.lgzm-hero__masonry {
	overflow: hidden;
}
/* Dos juegos completos de columnas (uno con reparto propio de round-robin
   para 3, otro para 5 — ver hero-masonry.php) en vez de "5 siempre, ocultar
   2 en móvil": ese primer enfoque desperdiciaba hasta el 40% de las fotos
   del cliente por debajo de 768px y repartía mal las 3 columnas visibles —
   bug real encontrado con fotos reales (2026-09-02). Solo uno de los dos
   juegos está en pantalla a la vez; el otro (incluidas sus fotos "lazy")
   nunca llega a descargarse mientras siga con display:none. */
.lgzm-masonry-set {
	position: absolute;
	inset: 0;
	display: none;
	grid-template-columns: repeat(3, 1fr);
	gap: 12px;
}
.lgzm-masonry-set--mobile {
	display: grid;
}
@media (min-width: 768px) {
	.lgzm-masonry-set--mobile {
		display: none;
	}
	.lgzm-masonry-set--desktop {
		display: grid;
		grid-template-columns: repeat(5, 1fr);
	}
}

.lgzm-masonry-col {
	position: relative;
	overflow: hidden;
}

.lgzm-masonry-col__track {
	display: flex;
	flex-direction: column;
	gap: 12px;
	will-change: transform;
	animation: lgzm-masonry-up 60s linear infinite;
}
/* Columnas pares al revés: mismo keyframe, dirección invertida. No hace
   falta un segundo @keyframes. */
.lgzm-masonry-col--2 .lgzm-masonry-col__track,
.lgzm-masonry-col--4 .lgzm-masonry-col__track {
	animation-direction: reverse;
}
/* Duraciones desiguales: si las cinco van al mismo ritmo se lee como un
   único bloque rígido moviéndose, no como cinco columnas. */
.lgzm-masonry-col--1 .lgzm-masonry-col__track { animation-duration: 58s; }
.lgzm-masonry-col--2 .lgzm-masonry-col__track { animation-duration: 72s; }
.lgzm-masonry-col--3 .lgzm-masonry-col__track { animation-duration: 64s; }
.lgzm-masonry-col--4 .lgzm-masonry-col__track { animation-duration: 78s; }
.lgzm-masonry-col--5 .lgzm-masonry-col__track { animation-duration: 66s; }

.lgzm-masonry-col__img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	border-radius: var(--lgzm-radius-16);
}

@keyframes lgzm-masonry-up {
	from { transform: translate3d(0, 0, 0); }
	to   { transform: translate3d(0, -50%, 0); }
}

/* Quieto, pero con las fotos igualmente visibles: es el fondo del hero, no
   un adorno prescindible. */
@media (prefers-reduced-motion: reduce) {
	.lgzm-masonry-col__track {
		animation: none;
		will-change: auto;
	}
}

/* Dos capas: el degradado exacto de Figma (§8, tres paradas) más una lámina
   plana. La lámina es nueva y solo se justifica desde que el fondo es un
   masonry de 20 fotos con colores arbitrarios: con una foto única bastaba el
   degradado, pero aquí la parte alta del hero puede tocarle una foto
   clarísima y el titular blanco se caía por debajo de AA. Es la excepción
   mínima que arregla el contraste sin repintar el degradado de marca. */
.lgzm-hero__scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	background:
		/* Capa negra uniforme añadida (2026-09-03, petición del cliente:
		   "que se lea mejor, un overlay negro con opacidad muy baja"). Va
		   ENCIMA de las otras dos capas (primer valor de la lista =
		   primer plano) y en negro puro, no en el azul de marca: sube el
		   contraste por igual en toda la foto sin teñirla más de azul,
		   que es lo que haría subir la opacidad de la lámina de abajo.
		   linear-gradient() con el mismo color en las dos paradas, no un
		   rgba() suelto: un color plano no es un valor válido de capa en
		   una lista de "background" con más de una capa (solo el ÚLTIMO
		   valor de la lista puede ser un color, y aquí el último ya es la
		   lámina azul) — con rgba() suelto aquí el navegador descarta la
		   declaración ENTERA como inválida y el scrim desaparece del todo
		   (bug real, encontrado con getComputedStyle: backgroundImage
		   volvía "none"). Un gradiente sin variación de color sí es una
		   "imagen" válida y consigue el mismo resultado visual. */
		linear-gradient(rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.15)),
		linear-gradient(
			to bottom,
			rgba(3, 6, 61, 0) 0%,
			rgba(3, 6, 61, 0.25) 50%,
			rgba(3, 6, 61, 0.85) 100%
		),
		rgba(3, 6, 61, 0.34);
}

/* No se apoya en el padding-inline de .lgzm-container (20px, igual en
   todo el rango): la cabecera flotante (.lgzm-header-bar) calcula su
   ancho como calc(100% - 40px) ANTES del max-width de 1200px, lo que le
   da un margen exterior propio de 20px que sí desaparece a partir de
   ~1240px de viewport (cuando el max-width de 1200 ya recorta esa misma
   cantidad igualmente) pero NO por debajo — .lgzm-container, sin ese
   calc(), no tiene ese margen exterior nunca. Replicar aquí la misma
   receta de caja que la cabecera (no solo igualar el padding a mano) es
   lo único que da el mismo resultado en cualquier ancho, no solo en el
   par de anchos donde por casualidad coincidiría un valor fijo. */
.lgzm-hero__content {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: flex-end;
	gap: 20px;
	width: calc(100% - 2 * var(--lgzm-margin-mobile));
	max-width: var(--lgzm-container);
	margin-inline: auto;
	padding-left: 20px;
	/* El padding de arriba deja sitio a la cabecera flotante (y al marquee,
	   si está): sin él, con el lead centrado, el titular podía quedar justo
	   debajo de la barra. */
	padding-block: 120px 64px;
}
@media (min-width: 1024px) {
	.lgzm-hero__content {
		gap: 28px;
		padding-left: 24px;
		padding-block: 140px 88px;
	}
}

/* margin-block: auto sobre el lead + justify-content: flex-end en el padre =
   los botones y la prueba social se quedan clavados abajo y el titular se
   centra en todo el hueco que queda por encima. Es exactamente lo que pidió
   el cliente: "el titular más arriba, los botones donde están". */
.lgzm-hero__lead {
	display: flex;
	flex-direction: column;
	gap: 20px;
	margin-block: auto;
	max-width: 100%;
}
@media (min-width: 1024px) {
	.lgzm-hero__lead {
		gap: 24px;
	}
}

/* font-size/line-height propios (2026-09-03, petición del cliente: "en
   móvil el titular un poco más grande"): sube el extremo móvil del
   clamp() de .t-display-h1 (34→40px) sin tocar la clase compartida, que
   también usan 404.php e index.php y ahí no se ha pedido nada. El
   extremo de escritorio (72px) se deja igual — el cliente solo mencionó
   móvil — así que la interpolación fluida se recalcula entera para
   estos dos puntos, mismo método que el resto de la escala
   (ver comentario largo al principio de base.css). */
.lgzm-hero__title {
	max-width: 620px;
	font-size: clamp(40px, 28.73px + 3.005vw, 72px);
	line-height: clamp(42px, 31.44px + 2.817vw, 72px);
}
@media (min-width: 1024px) {
	.lgzm-hero__title {
		/* 620px se quedaba corto para el tamaño fluido del título (hasta
		   72px): "Ropa personalizada" mide ~662px y "para universidades"
		   ~643px a ese tamaño, así que ninguna de las dos líneas cabía y
		   el titular se partía en 4 líneas en vez de 2. 700px cubre la
		   palabra más larga de la lista con margen. */
		max-width: 700px;
	}
}
.lgzm-hero__subtitle {
	max-width: 480px;
	color: rgba(255, 255, 255, 0.82);
}

.lgzm-hero__ctas {
	display: flex;
	flex-direction: column;
	align-self: stretch;
	gap: 12px;
}
.lgzm-hero__ctas .lgzm-btn {
	width: 100%;
}
@media (min-width: 640px) {
	.lgzm-hero__ctas {
		flex-direction: row;
		flex-wrap: wrap;
		align-self: auto;
	}
	.lgzm-hero__ctas .lgzm-btn {
		width: auto;
	}
}
@media (min-width: 1024px) {
	.lgzm-hero__ctas {
		gap: 14px;
	}
}

/* ---------- Titular con palabra rotatoria ("Ropa personalizada para
   {grupos}") — hero.php + word-rotate.js.
   Sin display:block en .lgzm-hero__title-line a propósito: el prefijo
   fluye como texto normal y la caja rotatoria (inline-block, abajo) se
   cuela justo detrás en la misma línea — "para" + la palabra van juntos,
   el salto de línea solo ocurre si de verdad no caben (igual que pasaría
   con texto normal), no siempre.
   Ancho/alto los fija word-rotate.js, midiendo la palabra ACTIVA en cada
   cambio (no la más larga de toda la lista): así con palabras cortas la
   caja es pequeña y se queda pegada a "para", y solo con una muy larga
   ("universidades") puede saltar de línea — igual que si ese texto
   estuviera escrito a mano. La transición de width/height de aquí abajo
   va a propósito MÁS RÁPIDA que el deslizamiento de la palabra (220ms
   contra 320ms): si van a la vez, la caja todavía es estrecha cuando la
   palabra entra y overflow: hidden la recorta por la izquierda. */
.lgzm-word-rotate {
	position: relative;
	display: inline-block;
	overflow: hidden;
	vertical-align: bottom;
	transition: width var(--lgzm-dur-ui) var(--lgzm-ease-out), height var(--lgzm-dur-ui) var(--lgzm-ease-out);
}
@media (prefers-reduced-motion: reduce) {
	.lgzm-word-rotate {
		transition: none;
	}
}
.lgzm-word-rotate__item {
	position: absolute;
	top: 0;
	left: 0;
	white-space: nowrap;
	opacity: 0;
	transform: translateY(100%);
	transition: transform 320ms var(--lgzm-ease-out), opacity 320ms var(--lgzm-ease-out);
	color: var(--lgzm-accent-on-ink);
}
.lgzm-word-rotate__item.is-active {
	opacity: 1;
	transform: translateY(0);
}
.lgzm-word-rotate__item.is-leaving {
	opacity: 0;
	transform: translateY(-100%);
}
@media (prefers-reduced-motion: reduce) {
	.lgzm-word-rotate__item {
		transition: none;
	}
}

.lgzm-hero__social-proof {
	display: inline-flex;
	align-items: center;
	padding: 10px 16px;
	border-radius: var(--lgzm-radius-16);
	background: rgba(255, 255, 255, 0.12);
	border: 1px solid rgba(255, 255, 255, 0.18);
}
.lgzm-hero__proof-text {
	font-family: 'Geist', sans-serif;
	font-weight: 400;
	font-size: 16px;
	line-height: 25px;
	color: rgba(255, 255, 255, 0.85);
}

/* =========================================================================
   02 · RTBs
   =========================================================================
   Rediseñado 2026-09-01: banda fina con icono + texto en fila, sin fondo de
   color y sin puntos de paginación. Antes eran tarjetas de 138px de alto
   mínimo sobre accent-wash; el cliente pidió expresamente recuperar ese
   espacio vertical. */

.lgzm-rtb-card {
	display: flex;
	align-items: center;
	gap: 12px;
	height: 100%;
	box-sizing: border-box;
	padding: 16px 8px;
}
.lgzm-rtb-card__icon {
	display: flex;
	flex-shrink: 0;
	width: 36px;
	height: 36px;
	align-items: center;
	justify-content: center;
	border-radius: var(--lgzm-radius-8);
	background: var(--lgzm-accent-wash);
	color: var(--lgzm-accent);
}
.lgzm-rtb-card__texto {
	margin: 0;
	font-weight: 500;
	color: var(--lgzm-ink);
}

/* La banda no lleva el padding vertical completo de sección: su trabajo es
   ser una franja de apoyo entre el hero y "Cómo trabajamos", no una sección
   con su propio aire. */
.lgzm-section--rtbs {
	padding-block: 20px;
	border-block: 1px solid var(--lgzm-ink-hairline);
}
@media (min-width: 1024px) {
	.lgzm-section--rtbs {
		padding-block: 24px;
	}
}

/* Separador vertical entre elementos, solo cuando son retícula (en móvil,
   con scroll horizontal, un borde a la izquierda del primer elemento visible
   quedaría cortado a mitad de gesto). */
@media (min-width: 900px) {
	.lgzm-carousel--rtbs .lgzm-carousel__item + .lgzm-carousel__item .lgzm-rtb-card {
		border-left: 1px solid var(--lgzm-ink-hairline);
		padding-left: 20px;
	}
}

/* =========================================================================
   03 · Cómo trabajamos — ficha del proceso
   ========================================================================= */

/* Container query y no media query: el componente responde al ancho que
   tiene, no al del navegador. Eso es lo que hace que el tramo intermedio
   (768-1023px) deje de ser un caso aparte — antes heredaba el layout de
   móvil y dejaba tarjetas de 260px perdidas en el centro. */
.lgzm-proceso {
	container-type: inline-size;
	container-name: proceso;
}

.lgzm-proceso__head {
	margin-bottom: 20px;
}
.lgzm-proceso__head p {
	margin-top: 8px;
	color: var(--lgzm-ink-secondary);
}

/* ---------- La ficha ---------- */

.lgzm-proceso__ficha {
	display: grid;
	grid-template-columns: 1fr;
	border-radius: var(--lgzm-radius-32);
	overflow: hidden;
	background: var(--lgzm-ink);
	/* Aísla el apilado de las fotos: sus z-index no pueden escaparse al
	   resto de la página. */
	isolation: isolate;
}
@container proceso (min-width: 680px) {
	.lgzm-proceso__ficha {
		grid-template-columns: 44fr 56fr;
		min-height: var(--lgzm-proceso-min);
	}
	.lgzm-proceso__ficha--sin-foto {
		grid-template-columns: 1fr;
	}
}

/* ---------- Media ---------- */

.lgzm-proceso__media {
	position: relative;
	aspect-ratio: 16 / 10;
	background: var(--lgzm-ink-wash);
	overflow: hidden;
}
@container proceso (min-width: 680px) {
	.lgzm-proceso__media {
		aspect-ratio: auto;
		height: 100%;
	}
}

/* Las fotos van apiladas y TODAS opacas. La que entra sube de z-index y
   se descubre con un barrido de clip-path por el lado hacia el que se
   avanza; la anterior se queda debajo, entera, derivando un poco en
   sentido contrario. Ese desfase entre las dos capas es lo que da la
   profundidad: no es un fundido, es una capa pasando por encima de otra.
   clip-path es la cuarta propiedad barata, junto a transform y opacity:
   no obliga a recalcular el layout.
   translate y scale van como propiedades independientes, no dentro de un
   transform compuesto, para que la deriva lateral y el zoom lento puedan
   animarse por separado sin pisarse. */
.lgzm-proceso__foto {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	z-index: 1;
	clip-path: inset(0 0 0 0);
	translate: 0;
	scale: 1;
	transition: clip-path var(--lgzm-dur-barrido) var(--lgzm-ease-in-out), translate var(--lgzm-dur-barrido) var(--lgzm-ease-in-out);
}
/* Un fotograma sin transición para colocar la foto entrante en su punto
   de partida — ver pintar() en assets/js/proceso.js. */
.lgzm-proceso__foto.is-instantaneo {
	transition: none;
}

/* Zoom lento mientras el paso está activo: 7s, un pelo más que los 6s de
   permanencia, para que nunca llegue al final y dé el tirón. Es una
   keyframe y no una transición a propósito — se reinicia entera en cada
   paso, corre fuera del hilo principal y no hay nada que interrumpir. */
.lgzm-proceso__foto.is-active {
	animation: lgzm-deriva var(--lgzm-dur-deriva) linear forwards;
}
@keyframes lgzm-deriva {
	from { scale: 1; }
	to   { scale: 1.07; }
}

/* ---------- Panel ---------- */

.lgzm-proceso__panel {
	display: flex;
	flex-direction: column;
	gap: 18px;
	padding: 24px;
	color: var(--lgzm-on-ink);
}
@container proceso (min-width: 680px) {
	.lgzm-proceso__panel {
		padding: 32px 36px;
		gap: 22px;
	}
}

/* ---------- Riel de progreso ---------- */

.lgzm-proceso__riel {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 1fr;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.lgzm-proceso__seg {
	position: relative;
	display: block;
	width: 100%;
	height: 4px;
	padding: 0;
	border: 0;
	border-radius: var(--lgzm-radius-pill);
	background: var(--lgzm-on-ink-hairline);
	cursor: pointer;
	overflow: hidden;
	transition: transform var(--lgzm-dur-fast) var(--lgzm-ease-out);
}
/* El segmento mide 4px porque así es el diseño, pero 4px es muy poco para
   un objetivo táctil (el mínimo de la WCAG 2.5.8 es 24). El ::after
   amplía solo el área sensible: visualmente no cambia nada. */
.lgzm-proceso__seg::after {
	content: '';
	position: absolute;
	inset: -12px 0;
}
.lgzm-proceso__seg:focus-visible {
	outline: 2px solid var(--lgzm-accent-on-ink);
	outline-offset: 4px;
}
@media (hover: hover) and (pointer: fine) {
	.lgzm-proceso__seg:hover {
		transform: scaleY(1.75);
	}
}
.lgzm-proceso__seg:active {
	transform: scaleY(1.75) scaleX(.99);
}

.lgzm-proceso__relleno {
	position: absolute;
	inset: 0;
	border-radius: inherit;
	background: var(--lgzm-accent-on-ink);
	/* Halo: hace que el borde de avance se lea como una luz que corre por
	   el riel y no como una barra que crece. No se anima, así que no
	   cuesta nada por fotograma. */
	box-shadow: 0 0 10px 0 rgba(124, 140, 255, .65);
	transform-origin: left center;
	transform: scaleX(0);
}
/* El segmento activo se llena en tiempo real: es el temporizador del
   autoavance hecho visible, en vez de que el salto de paso llegue por
   sorpresa. linear porque representa progreso, y el progreso no acelera
   ni frena. */
.lgzm-proceso__seg.is-corriendo .lgzm-proceso__relleno {
	transform: scaleX(1);
	transition: transform var(--lgzm-dur-dwell) linear;
}
.lgzm-proceso__seg.is-hecho .lgzm-proceso__relleno {
	transform: scaleX(1);
}
.lgzm-proceso__seg.is-instantaneo .lgzm-proceso__relleno {
	transition: none;
}

/* ---------- Contador tipo odómetro ----------
   Una sola pila de cifras enmascarada por una ventana de 1em: al cambiar
   de paso la pila rueda una posición. Es el gesto de progreso más legible
   que hay, y cuesta un translate sobre un único elemento. */
.lgzm-proceso__contador {
	font-family: 'Bricolage Grotesque', serif;
	font-weight: 800;
	font-size: clamp(40px, 35.35px + 1.387cqi, 52px);
	line-height: 1;
	letter-spacing: -0.02em;
	color: var(--lgzm-accent-on-ink);
	font-variant-numeric: tabular-nums;
	height: 1em;
	overflow: hidden;
	flex-shrink: 0;
}
.lgzm-proceso__cifras {
	display: block;
	/* 1em por cifra porque line-height es exactamente 1: la pila avanza
	   una altura de cifra por paso, sin depender de cuántas haya. */
	translate: 0 calc(var(--paso, 0) * -1em);
	transition: translate var(--lgzm-dur-contador) var(--lgzm-ease-in-out);
}
.lgzm-proceso__cifras span {
	display: block;
	line-height: 1;
}

/* ---------- Cuerpo del paso ---------- */

.lgzm-proceso__cuerpo {
	position: relative;
	flex: 1 0 auto;
	display: grid;
	/* Los tres pasos comparten celda, así que la altura la marca el más
	   largo y nada se mueve al cambiar. Centrado en vertical porque en
	   escritorio el panel es más alto que el texto: pegado arriba dejaba
	   un vacío raro debajo. */
	align-content: center;
}
.lgzm-proceso__paso {
	grid-area: 1 / 1;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 10px;
	pointer-events: none;
	/* visibility retrasada hasta el final de la salida: así el paso que se
	   va sigue pintado mientras su texto se desvanece, en vez de
	   desaparecer de golpe, y aun así deja de ser seleccionable. */
	visibility: hidden;
	transition: visibility 0s linear var(--lgzm-dur-exit);
}
.lgzm-proceso__paso.is-active {
	pointer-events: auto;
	visibility: visible;
	transition: visibility 0s;
}

/* Título y texto entran escalonados, no como un bloque: 120ms y 190ms
   después del barrido de la foto. El escalonado es lo que convierte tres
   cosas apareciendo a la vez en una frase que se va escribiendo. Salen
   los dos juntos y sin retardo — irse siempre va más rápido que llegar. */
.lgzm-proceso__titulo,
.lgzm-proceso__texto {
	margin: 0;
	opacity: 0;
	translate: 0 var(--entrada, 16px);
	transition: opacity var(--lgzm-dur-exit) var(--lgzm-ease-out), translate var(--lgzm-dur-exit) var(--lgzm-ease-out);
}
.lgzm-proceso__paso.is-active .lgzm-proceso__titulo,
.lgzm-proceso__paso.is-active .lgzm-proceso__texto {
	opacity: 1;
	translate: 0;
	transition-duration: 340ms;
}
.lgzm-proceso__paso.is-active .lgzm-proceso__titulo { transition-delay: 120ms; }
.lgzm-proceso__paso.is-active .lgzm-proceso__texto  { transition-delay: 190ms; }
/* Un fotograma sin transición para recolocar el texto entrante en su
   punto de partida cuando cambia el sentido de la marcha. */
.lgzm-proceso__paso.is-instantaneo .lgzm-proceso__titulo,
.lgzm-proceso__paso.is-instantaneo .lgzm-proceso__texto {
	transition: none;
}

.lgzm-proceso__titulo {
	color: var(--lgzm-on-ink);
	text-wrap: balance;
}
.lgzm-proceso__texto {
	color: rgba(255, 255, 255, .78);
	max-width: 46ch;
}

/* ---------- Movimiento reducido ----------
   Se cae TODO lo efectista —barrido, deriva, zoom, odómetro, escalonado—
   y queda un cruce de opacidad limpio. Que es menos movimiento, no cero:
   el cruce sigue evitando el corte seco. */
@media (prefers-reduced-motion: reduce) {
	.lgzm-proceso__foto {
		clip-path: none !important;
		translate: none !important;
		animation: none !important;
		opacity: 0;
		transition: opacity var(--lgzm-dur-surface) var(--lgzm-ease-out);
	}
	.lgzm-proceso__foto.is-active {
		opacity: 1;
	}
	.lgzm-proceso__cifras {
		transition: none;
	}
	.lgzm-proceso__titulo,
	.lgzm-proceso__texto {
		translate: none !important;
		transition: opacity var(--lgzm-dur-surface) var(--lgzm-ease-out);
	}
	.lgzm-proceso__paso.is-active .lgzm-proceso__titulo,
	.lgzm-proceso__paso.is-active .lgzm-proceso__texto {
		transition-delay: 0s;
	}
	.lgzm-proceso__seg:hover,
	.lgzm-proceso__seg:active {
		transform: none;
	}
	.lgzm-proceso__seg.is-corriendo .lgzm-proceso__relleno {
		transition: none;
	}
}

/* =========================================================================
   04 · Grupos
   ========================================================================= */

.lgzm-grupo-card {
	display: flex;
	flex-direction: column;
	gap: 10px;
	text-decoration: none;
	color: inherit;
}
@media (min-width: 640px) {
	.lgzm-grupo-card {
		gap: 14px;
	}
}
/* Cuadrada por debajo de 640px: con 4:5, las ocho cards en dos columnas
   ocupaban más de dos pantallas y el cambio perdía todo el sentido. A
   partir de tablet vuelve al 4:5 de Figma, que es donde el retrato luce. */
.lgzm-grupo-card__img {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	border-radius: var(--lgzm-radius-16);
}
@media (min-width: 640px) {
	.lgzm-grupo-card__img {
		aspect-ratio: 4 / 5;
		border-radius: var(--lgzm-radius-24);
	}
}
.lgzm-grupo-card__img--placeholder {
	background: var(--lgzm-platinum);
}

/* ---------- Card con mockup de prenda sin fondo (plan 211) ----------
   Tres cosas cambian respecto a la card con foto:
   1. object-fit: contain, no cover. cover recorta mangas y bajo; una
      prenda no puede perder bordes.
   2. Una superficie propia. Con la foto, el contenedor visual ERA la foto;
      con una prenda transparente sobre papel blanco la card se queda sin
      forma, sin esquinas redondeadas visibles y sin nada sobre lo que
      ocurra el hover.
   3. Padding, para que la prenda no toque los bordes de esa superficie.

   El color de la superficie va en una variable a propósito: si algún día
   llegan mockups CON fondo blanco en vez de con alfa, poner
   --lgzm-grupo-surface a var(--lgzm-paper) lo resuelve entero sin tocar
   nada más. */
.lgzm-grupo-card {
	--lgzm-grupo-surface: var(--lgzm-ink-wash);
}
.lgzm-grupo-card__img--mockup {
	object-fit: contain;
	background: var(--lgzm-grupo-surface);
	padding: 16px;
}
@media (min-width: 640px) {
	.lgzm-grupo-card__img--mockup {
		padding: 24px;
	}
}
/* El zoom del hover, más contenido que en una foto: una prenda con contain
   ya tiene aire alrededor y un 1.03 se nota igual sin salirse del padding. */
@media (hover: hover) and (pointer: fine) {
	.lgzm-grupo-card:hover .lgzm-grupo-card__img--mockup {
		transform: scale(1.03);
	}
	.lgzm-grupo-card__img--mockup {
		transition: transform var(--lgzm-dur-surface) var(--lgzm-ease-out);
	}
}
@media (prefers-reduced-motion: reduce) {
	.lgzm-grupo-card__img--mockup {
		transition: none;
	}
	.lgzm-grupo-card:hover .lgzm-grupo-card__img--mockup {
		transform: none;
	}
}
.lgzm-grupo-card__row {
	display: flex;
	align-items: center;
	gap: 8px;
}
.lgzm-grupo-card__title {
	flex: 1 0 0;
	min-width: 0;
	color: var(--lgzm-ink);
}
.lgzm-grupo-card__arrow {
	color: var(--lgzm-accent);
	flex-shrink: 0;
	display: inline-block;
	transition: transform var(--lgzm-dur-fast) var(--lgzm-ease-out);
}
.lgzm-grupo-card__arrow svg {
	display: block;
	width: 18px;
	height: 14px;
}
@media (hover: hover) and (pointer: fine) {
	.lgzm-grupo-card:hover .lgzm-grupo-card__arrow {
		transform: translateX(5px);
	}
}
@media (prefers-reduced-motion: reduce) {
	.lgzm-grupo-card__arrow {
		transition: none;
	}
}

/* Sin min-height fijo en móvil: 240px venía del diseño de card 4:5 de
   antes (imagen sola ya rondaba esa altura); con las cards cuadradas del
   plan 109 el resto de la fila natural mide menos, y ese mínimo obligaba
   a esta card (con height:100%, para igualar la fila) a estirarse por
   encima de su vecina real — se veía más alta que el resto, justo al
   revés de lo que pedía el plan (bug real reportado por el cliente,
   2026-09-02). A partir de 640px las cards vuelven a 4:5 y el mínimo
   vuelve a tener sentido. */
.lgzm-grupo-card--otro {
	height: 100%;
	align-items: center;
	justify-content: center;
	text-align: center;
	gap: 10px;
	border-radius: var(--lgzm-radius-24);
	background: var(--lgzm-accent-wash);
	padding: 20px;
}
@media (min-width: 640px) {
	.lgzm-grupo-card--otro {
		min-height: 240px;
	}
}
.lgzm-grupo-card--otro__cta {
	color: var(--lgzm-accent);
}

.lgzm-grupos__cta-wrap {
	display: flex;
	justify-content: center;
	margin-top: 32px;
}

/* =========================================================================
   06 · Diseños reales
   ========================================================================= */

.lgzm-diseno-card__img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	border-radius: var(--lgzm-radius-24);
}

/* =========================================================================
   07 · Reseñas
   ========================================================================= */

.lgzm-resenas {
	background: var(--lgzm-accent-wash);
}

.lgzm-resena-card {
	display: flex;
	flex-direction: column;
	height: 100%;
	box-sizing: border-box;
	border-radius: var(--lgzm-radius-24);
	background: var(--lgzm-paper);
	overflow: hidden;
}

/* La foto va a sangre dentro de la card, así que el redondeo lo tiene que
   recortar el contenedor (overflow: hidden de arriba) y no la propia
   imagen: si el radio se le pone a la <img>, en Safari asoma una línea de
   fondo de un píxel entre el borde y la foto. */
/* aspect-ratio más ancho que el 4:3 original (2026-09-03, petición del
   cliente: fotos "muy altas" en móvil, "un poco pasadas" en desktop). En
   móvil la card mide hasta 320px de ancho (components.css): a 4:3 la foto
   sola ya salía a 240px de alto, mucho para una card dentro de un
   carrusel horizontal — 16:9 la deja en 180px. En desktop (card de
   380px) el recorte pedido es menor, así que se queda en 3:2 (253px) en
   vez de saltar también a 16:9. */
/* min-height: 0 es imprescindible, no cosmético (bug real encontrado al
   bajar el aspect-ratio, 2026-09-03): el mínimo automático por defecto de
   un hijo flex es "auto" (no 0), y aquí eso hacía que la card entera se
   estirase hasta igualar a la más alta del carrusel (align-items:stretch
   de .lgzm-carousel__track) y luego esa altura de sobra fuera A PARAR a
   la foto en vez de al texto — ignorando aspect-ratio, flex-shrink:0 y
   hasta un flex-basis en px explícito por igual (comprobado inyectando
   cada uno por separado con !important en el navegador; solo min-height:0
   lo arregló). Con esto la foto vuelve a medir justo lo que dice su
   aspect-ratio y es .lgzm-resena-card__cuerpo quien absorbe la diferencia,
   que es el reparto que ya pedía su flex:1 0 auto. */
.lgzm-resena-card__media {
	position: relative;
	width: 100%;
	aspect-ratio: 16 / 9;
	min-height: 0;
	background: var(--lgzm-ink-wash);
	flex-shrink: 0;
}
@media (min-width: 1024px) {
	.lgzm-resena-card__media {
		aspect-ratio: 3 / 2;
	}
}
.lgzm-resena-card__foto {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.lgzm-resena-card__cuerpo {
	display: flex;
	flex-direction: column;
	gap: 12px;
	flex: 1 0 auto;
	padding: 20px 22px 22px;
}
/* Sin foto, la card necesita su padding superior completo para no quedar
   con el texto pegado al borde de arriba. */
.lgzm-resena-card:not(.lgzm-resena-card--con-foto) .lgzm-resena-card__cuerpo {
	padding-top: 26px;
}

.lgzm-resena-card__estrellas {
	margin: 0;
	color: var(--lgzm-accent);
	font-family: 'Geist', sans-serif;
	font-size: 16px;
	line-height: 25px;
}
.lgzm-resena-card__cita {
	margin: 0;
	color: var(--lgzm-ink);
}
/* ink-tertiary (rgba(3,6,61,.48), igual que en Figma) da ~3,5:1 sobre
   blanco a este tamaño de texto — no pasa AA (mínimo 4,5:1). Se usa
   ink-secondary en su lugar (§10: contraste mínimo AA en todo tiene
   prioridad sobre el token literal de Figma en este punto concreto). */
.lgzm-resena-card__nombre {
	margin: 0;
	margin-top: auto;
	padding-top: 4px;
	color: var(--lgzm-ink-secondary);
}

/* =========================================================================
   08 · Legazyum Brand
   =========================================================================
   Sneak-peek de la línea propia (petición del cliente 2026-09-08). La card
   es la de Diseños más un pie con nombre y precio; la foto conserva el 4:5
   del resto del sitio. */

.lgzm-producto-card {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

/* all: unset no: el <button> y el <a> tienen que compartir caja exacta para
   que las cards de un mismo carrusel no bailen según lleven URL de compra o
   no. Se normalizan las dos etiquetas juntas. */
.lgzm-producto-card__media {
	display: block;
	width: 100%;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
	line-height: 0;
	border-radius: var(--lgzm-radius-24);
	overflow: hidden;
}

.lgzm-producto-card__img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	transition: transform var(--lgzm-dur-surface) var(--lgzm-ease-out);
}
/* El zoom va en la imagen y el recorte en el contenedor: así la card no
   cambia de tamaño y no empuja a sus vecinas. Solo con puntero real, que en
   táctil el :hover se queda pegado tras cada toque. */
@media (hover: hover) and (pointer: fine) {
	.lgzm-producto-card__media:hover .lgzm-producto-card__img {
		transform: scale(1.03);
	}
}
@media (prefers-reduced-motion: reduce) {
	.lgzm-producto-card__img {
		transition: none;
	}
	.lgzm-producto-card__media:hover .lgzm-producto-card__img {
		transform: none;
	}
}

.lgzm-producto-card__pie {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
}
.lgzm-producto-card__nombre {
	color: var(--lgzm-ink);
	min-width: 0;
}
.lgzm-producto-card__precio {
	color: var(--lgzm-ink-secondary);
	flex-shrink: 0;
}

.lgzm-brand__cta-wrap {
	display: flex;
	justify-content: center;
	margin-top: 32px;
}

/* =========================================================================
   08 · Premios TikTok
   =========================================================================
   Rediseñado 2026-09-01 sobre la referencia del cliente: sección clara con
   mockup de móvil en el centro y una card de premio a cada lado. Antes era
   un panel oscuro con tres tarjetas de texto en fila. */

/* Fondo azul de marca (petición del cliente, 2026-09-10): antes era
   ink-wash, un gris casi imperceptible que no destacaba entre las secciones
   vecinas. Mismo tratamiento que el bloque del formulario (11 · Formulario,
   más abajo en este fichero): color en on-ink por defecto, y cada texto
   suelto directamente sobre la sección (no dentro de una tarjeta blanca)
   pasa a blanco translúcido al 85% — no al 82%, que en components.css ya se
   midió por fórmula real de WCAG y da 4.46:1, por debajo del mínimo AA de
   4.5:1 aunque a simple vista se lea bien. Las tarjetas de premio no se
   tocan: ya declaran su propio fondo y color (blanco/navy), así que quedan
   igual de legibles floten sobre lo que floten. */
.lgzm-tiktok-section {
	background: var(--lgzm-accent);
	color: var(--lgzm-on-ink);
}
.lgzm-tiktok__intro {
	color: rgba(255, 255, 255, 0.85);
}
.lgzm-tiktok__head {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	max-width: 640px;
	margin-inline: auto;
	text-align: center;
}
/* Escena: en móvil una columna (móvil arriba, carrusel de premios debajo);
   en escritorio, una sola fila con el mockup y los tres premios en
   horizontal: MÓVIL / NIVEL 1 / NIVEL 2 / NIVEL 3 (petición explícita del
   cliente, 2026-09-02, tras ver apilados verticalmente los tres premios en
   la primera versión — lo que quiere es la fila completa, no una columna
   al lado del móvil). El reparto en 3 columnas iguales para los premios
   pasa por el propio carrusel (ver más abajo .lgzm-carousel--tiktok-
   niveles): aquí la escena solo decide si hay o no una columna extra para
   el mockup. */
.lgzm-tiktok__escena {
	display: grid;
	grid-template-columns: 1fr;
	gap: 20px;
	margin-top: 32px;
	align-items: center;
}
@media (min-width: 1024px) {
	.lgzm-tiktok__escena:not(.lgzm-tiktok__escena--sin-movil) {
		grid-template-columns: auto 1fr;
		gap: 32px;
		margin-top: 48px;
		align-items: center;
	}
}

/* ---------- Carrusel de premios ----------
   Reutiliza el componente base (legazyum_carousel()): en móvil es un
   carrusel de scroll de verdad, como RTBs/Reseñas/etc. — petición del
   cliente (2026-09-02), antes los 3 premios solo se apilaban en columna.
   El ancho de card en móvil se declara en components.css, como el resto
   de variantes (bloque "Variantes de ancho de card").

   min-width: 0 es obligatorio y no cosmético: el carrusel es un hijo
   directo de una rejilla (.lgzm-tiktok__escena), y los hijos de grid/flex
   tienen por defecto min-width:auto — su anchura mínima es la de su
   contenido sin partir, que en un track de scroll con 3 cards de 280px en
   fila (sin wrap) son ~900px. Sin este min-width:0 esa anchura mínima
   ganaba a la columna "1fr" de la rejilla y la EMPUJABA a crecer más allá
   del viewport en vez de quedarse quieta y dejar que el propio track
   hiciera scroll por dentro — bug real visto en móvil al probar este
   cambio (2026-09-02): toda la web se veía encogida/movida porque el
   layout viewport se ensanchaba para caber el carrusel desbordado. */
.lgzm-carousel--tiktok-niveles {
	min-width: 0;
}

/* A sangre por debajo de 1024px, como RTBs/Reseñas: este carrusel es el
   único que vive dentro de .lgzm-container (lo necesita para compartir
   fila con el mockup en escritorio, ver más abajo), y eso lo hacía
   distinto a todos los demás carruseles del sitio — dos capas de margen
   en vez de una (el padding del contenedor + el propio del track), lo que
   además de duplicar el margen (ver commit anterior) dejaba ese margen
   pintado por .lgzm-container en vez de por el propio carrusel. El
   cliente lo detectó con el inspector (2026-09-02): con el padding de
   .lgzm-container desactivado el problema desaparecía. El margen negativo
   de aquí cancela exactamente el padding que .lgzm-container le mete a
   este hijo suyo, dejando que el carrusel vuelva a maquetarse pegado al
   borde real de la pantalla — igual que RTBs/Reseñas, que ni siquiera
   están dentro de .lgzm-container — y que sea otra vez el propio track
   (padding-inline, sin tocar aquí, hereda el de components.css) el que
   ponga el margen visible, igual que en todos los demás. */
.lgzm-carousel--tiktok-niveles {
	margin-inline: calc(-1 * var(--lgzm-margin-mobile));
}
@media (min-width: 600px) and (max-width: 1023.98px) {
	.lgzm-carousel--tiktok-niveles {
		margin-inline: calc(-1 * clamp(20px, 5vw, 56px));
	}
}
/* Mismo motivo que el ajuste ya existente de RTBs en components.css: por
   debajo de 1024px el padding fijo del track (20px) no crece con
   .lgzm-container, que a partir de 600px pasa a clamp(20px, 5vw, 56px) —
   sin este ajuste el margen de este carrusel se quedaba corto respecto al
   resto de la página en el rango tablet. */
@media (min-width: 600px) and (max-width: 1023.98px) {
	.lgzm-carousel--tiktok-niveles .lgzm-carousel__track {
		padding-inline: clamp(20px, 5vw, 56px);
		scroll-padding-inline: clamp(20px, 5vw, 56px);
	}
	.lgzm-carousel--tiktok-niveles .lgzm-carousel__controls {
		padding-inline: clamp(20px, 5vw, 56px);
	}
}

/* En escritorio deja de ser un carrusel de scroll: se reparte en 3
   columnas iguales, con o sin mockup al lado (mismo criterio que ya usan
   Diseños/Grupos — carousel.js detecta que el track ya no desborda y
   oculta los controles solo, sin JS propio). Aquí sí vuelve a vivir dentro
   de .lgzm-container (margin-inline a 0: cancela el break-out de arriba),
   porque en escritorio comparte fila con el mockup y necesita quedarse
   confinado a su columna de la rejilla — no tiene sentido a sangre. */
@media (min-width: 1024px) {
	.lgzm-carousel--tiktok-niveles {
		margin-inline: 0;
	}
	.lgzm-carousel--tiktok-niveles .lgzm-carousel__track {
		padding-inline: 0;
		scroll-padding-inline: 0;
		display: grid;
		grid-template-columns: repeat(3, 1fr);
		overflow: visible;
		scroll-snap-type: none;
	}
	.lgzm-carousel--tiktok-niveles .lgzm-carousel__item {
		width: auto;
	}
}

/* ---------- Mockup de móvil (CSS puro, sin PNG) ---------- */
.lgzm-tiktok__movil {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	justify-self: center;
}

/* ---------- Corazones flotantes detrás del móvil (2026-09-03, petición
   del cliente: referencia visual del "me gusta" de TikTok) ----------
   Puro decorado: van ANTES de .lgzm-movil en el marcado (así pintan
   primero = quedan detrás por orden natural, sin necesitar z-index) y el
   propio fondo opaco del móvil los tapa en el área que ocupa — solo se
   ven asomando alrededor, que es justo "detrás del móvil" y no "por
   encima". z-index explícito en los dos de todas formas: más robusto que
   fiarse solo del orden del DOM si algún día se reordena el marcado. */
.lgzm-tiktok__corazones {
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: visible;
	pointer-events: none;
}
.lgzm-movil {
	z-index: 1;
}
/* Posición base con custom properties por icono (puestas inline desde
   tiktok.php, una por corazón): así un solo bloque de CSS sirve para
   todos, en vez de una regla nth-child por cada uno.

   --lgzm-corazon-x se resuelve a partir de -x-movil/-x-escritorio (las
   dos, también inline) en vez de venir directa de fuera: el móvil real
   mide 220px de ancho en móvil (110 de mitad) y 320px en escritorio (160
   de mitad), y en un viewport de 375px solo quedan ~77px de margen a
   cada lado del propio móvil — un 'x' pensado para escritorio se sale de
   la pantalla en móvil (bug real: sacaba scroll horizontal), y uno
   pensado para móvil se queda otra vez por dentro del móvil grande de
   escritorio. Ningún clamp()/vw sirve aquí porque el ancho del móvil no
   es fluido, cambia de golpe en el mismo breakpoint de siempre
   (1024px) — así que el corte va con la misma media query. */
.lgzm-tiktok__corazon {
	--lgzm-corazon-x: var(--lgzm-corazon-x-movil);
	position: absolute;
	left: 50%;
	top: var(--lgzm-corazon-y);
	width: var(--lgzm-corazon-size);
	height: var(--lgzm-corazon-size);
	fill: #ff3b5c;
	opacity: 0;
	transform: translateX(calc(-50% + var(--lgzm-corazon-x))) scale(0.5);
	animation: lgzm-tiktok-corazon-flotar var(--lgzm-corazon-dur) ease-out infinite;
	animation-delay: var(--lgzm-corazon-delay);
}
@media (min-width: 1024px) {
	.lgzm-tiktok__corazon {
		--lgzm-corazon-x: var(--lgzm-corazon-x-escritorio);
	}
}
/* Sube y se desvanece, con una pequeña rotación de entrada/salida para
   que no se lea como un movimiento robótico en línea recta — igual que
   el "doble toque" real de TikTok, que nunca sube perfectamente recto. */
@keyframes lgzm-tiktok-corazon-flotar {
	0% {
		opacity: 0;
		transform: translateX(calc(-50% + var(--lgzm-corazon-x))) translateY(0) scale(0.5) rotate(-6deg);
	}
	12% {
		opacity: 0.95;
	}
	75% {
		opacity: 0.55;
	}
	100% {
		opacity: 0;
		transform: translateX(calc(-50% + var(--lgzm-corazon-x))) translateY(-280px) scale(1) rotate(6deg);
	}
}
/* Decoración pura, no informativa: con movimiento reducido se quita del
   todo en vez de dejarla estática — parada no aporta nada y ocupar sitio
   visual sin moverse se leería como un elemento roto. */
@media (prefers-reduced-motion: reduce) {
	.lgzm-tiktok__corazones {
		display: none;
	}
}
/* 220px y no 240 (2026-09-03, petición del cliente: "reducir un poco la
   altura del mockup en móvil"). Se baja el ancho, no el aspect-ratio: es
   lo que mantiene la silueta de móvil real (9:19) en vez de "achatarla",
   y de paso reduce el alto en la misma proporción (507px→464px). */
.lgzm-movil {
	position: relative;
	width: 220px;
	aspect-ratio: 9 / 19;
	padding: 10px;
	border-radius: 34px;
	background: #0b0d1f;
	box-shadow: 0 18px 48px rgba(3, 6, 61, 0.28), inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}
@media (min-width: 1024px) {
	.lgzm-movil {
		/* Antes 280px: con los premios agrupados a la derecha (ver arriba)
		   sobra sitio y el cliente pidió el mockup "un poco más grande"
		   (2026-09-02). */
		width: 320px;
	}
}
.lgzm-movil__notch {
	position: absolute;
	top: 14px;
	left: 50%;
	transform: translateX(-50%);
	width: 84px;
	height: 18px;
	border-radius: var(--lgzm-radius-pill);
	background: #0b0d1f;
	z-index: 2;
}
.lgzm-movil__pantalla {
	position: relative;
	width: 100%;
	height: 100%;
	border-radius: 26px;
	overflow: hidden;
	background: #000;
}
.lgzm-movil__clip {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity var(--lgzm-dur-surface) var(--lgzm-ease-out);
	pointer-events: none;
}
.lgzm-movil__clip.is-active {
	opacity: 1;
	pointer-events: auto;
}
.lgzm-movil__video {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.lgzm-movil__siguiente {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 1px solid var(--lgzm-ink-hairline);
	border-radius: var(--lgzm-radius-pill);
	background: var(--lgzm-paper);
	color: var(--lgzm-ink);
	cursor: pointer;
	transition: background-color var(--lgzm-dur-fast) var(--lgzm-ease-out), transform var(--lgzm-dur-press) var(--lgzm-ease-out);
}
@media (hover: hover) and (pointer: fine) {
	.lgzm-movil__siguiente:hover {
		background: var(--lgzm-ink-wash);
	}
}
.lgzm-movil__siguiente:active {
	transform: scale(0.94);
}
.lgzm-movil__ayuda {
	color: rgba(255, 255, 255, 0.85);
	text-align: center;
}

/* ---------- Cards de premio ---------- */
.lgzm-nivel {
	display: flex;
	flex-direction: column;
	gap: 14px;
	box-sizing: border-box;
	padding: 16px;
	/* Sin esto la card solo mide lo que ocupa su contenido: el carrusel
	   (flex en móvil, grid de 3 columnas en escritorio) ya estira el
	   .lgzm-carousel__item que la envuelve a la altura de la fila, pero la
	   card de dentro no lo heredaba, así que con textos de distinta
	   longitud las tres quedaban con bordes a distinta altura (reportado
	   por el cliente, 2026-09-02). */
	height: 100%;
	border-radius: var(--lgzm-radius-24);
	background: var(--lgzm-paper);
	color: var(--lgzm-ink);
	border: 1px solid var(--lgzm-ink-hairline);
	transition: transform var(--lgzm-dur-fast) var(--lgzm-ease-out), box-shadow var(--lgzm-dur-fast) var(--lgzm-ease-out);
}
@media (hover: hover) and (pointer: fine) {
	.lgzm-nivel:hover {
		transform: translateY(-4px);
		box-shadow: 0 12px 28px rgba(3, 6, 61, 0.1);
	}
}
@media (prefers-reduced-motion: reduce) {
	.lgzm-nivel:hover {
		transform: none;
	}
}
.lgzm-nivel__img {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	border-radius: var(--lgzm-radius-16);
}
.lgzm-nivel__texto-wrap {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.lgzm-nivel__badge {
	display: inline-flex;
	align-self: flex-start;
	padding: 6px 12px;
	border-radius: var(--lgzm-radius-pill);
	background: var(--lgzm-accent-wash);
	color: var(--lgzm-accent);
}
.lgzm-nivel__texto {
	color: var(--lgzm-ink-secondary);
}

/* Premio mayor: antes destacaba en color acento sobre una sección clara.
   Con la sección ya en ese mismo azul (2026-09-10), un fondo idéntico al
   de detrás dejaba la tarjeta sin borde visible — el degradado accent-
   sobre-accent la hacía desaparecer. Pasa a la tinta oscura del tema: sigue
   siendo la única tarjeta que no es blanca, y ahora sí se recorta con
   claridad contra el azul. */
.lgzm-nivel--destacado {
	background: var(--lgzm-ink);
	border-color: var(--lgzm-ink);
	color: var(--lgzm-on-ink);
}
.lgzm-nivel--destacado .lgzm-nivel__badge {
	background: rgba(255, 255, 255, 0.18);
	color: var(--lgzm-on-ink);
}
.lgzm-nivel--destacado .lgzm-nivel__texto {
	color: rgba(255, 255, 255, 0.82);
}

.lgzm-tiktok__legal {
	margin-top: 24px;
	text-align: center;
	color: rgba(255, 255, 255, 0.85);
}

/* ---------- Banda simplificada de la home (plan 209) ----------
   Estructura tomada de la referencia del cliente: fila de móviles con una
   franja de claim por encima. Los marcos son .lgzm-movil, el mismo
   componente del mockup grande, reducido con --lgzm-movil-escala. */

.lgzm-tiktok-banda {
	overflow: hidden;
	background: var(--lgzm-ink-wash);
}

.lgzm-tiktok-banda__escena {
	position: relative;
	display: flex;
	justify-content: center;
}

/* La fila se recorta a los lados a propósito: los móviles de los extremos
   asoman cortados, que es lo que da la sensación de "hay más". Por eso el
   overflow: hidden va en la sección y no aquí. */
.lgzm-tiktok-banda__fila {
	display: flex;
	justify-content: center;
	align-items: center;
	gap: 12px;
	margin: 0;
	padding: 0;
	list-style: none;
}
@media (min-width: 768px) {
	.lgzm-tiktok-banda__fila {
		gap: 24px;
	}
}

/* En móvil el marco baja a 130px: cuatro marcos de 220px (el tamaño del
   mockup grande) suman 880px y no caben ni de lejos en 375px. No se
   esconden móviles con media queries: se encogen, que mantiene la lectura
   de "fila de pantallas" en todos los anchos.

   El padding/radius/muesca de .lgzm-movil son valores fijos pensados para
   el mockup grande (220-320px). A 130px de ancho esos mismos px fijos
   pesan casi el doble en proporción: el marco negro se ve "grueso" y la
   muesca ocupa casi la mitad del ancho (reportado por el cliente,
   2026-09-10). Se escalan aquí, por tamaño de marco, para mantener la
   misma proporción que en el mockup grande; a 1024px+ (230px, ya cerca de
   los 220-320 del original) se vuelve a los valores base. */
.lgzm-tiktok-banda__movil .lgzm-movil {
	width: 130px;
	flex-shrink: 0;
	padding: 6px;
	border-radius: 20px;
}
.lgzm-tiktok-banda__movil .lgzm-movil__notch {
	width: 50px;
	height: 10px;
	top: 8px;
}
.lgzm-tiktok-banda__movil .lgzm-movil__pantalla {
	border-radius: 15px;
}
@media (min-width: 768px) {
	.lgzm-tiktok-banda__movil .lgzm-movil {
		width: 190px;
		padding: 8px;
		border-radius: 28px;
	}
	.lgzm-tiktok-banda__movil .lgzm-movil__notch {
		width: 70px;
		height: 14px;
		top: 11px;
	}
	.lgzm-tiktok-banda__movil .lgzm-movil__pantalla {
		border-radius: 22px;
	}
}
@media (min-width: 1024px) {
	.lgzm-tiktok-banda__movil .lgzm-movil {
		width: 230px;
		padding: 10px;
		border-radius: 34px;
	}
	.lgzm-tiktok-banda__movil .lgzm-movil__notch {
		width: 84px;
		height: 18px;
		top: 14px;
	}
	.lgzm-tiktok-banda__movil .lgzm-movil__pantalla {
		border-radius: 26px;
	}
}

/* El primero y el último, un poco más bajos: rompe la fila plana sin
   necesidad de rotaciones ni de sombras. */
.lgzm-tiktok-banda__movil:first-child,
.lgzm-tiktok-banda__movil:last-child {
	transform: translateY(16px);
}

/* La franja del claim, centrada sobre la fila. Azul de marca, NO el verde
   de la referencia: ese verde es el token de WhatsApp y usarlo aquí
   convertiría el canal en un color de marca. Ver RF-5 del plan. */
.lgzm-tiktok-banda__claim {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	/* z-index 2 y no auto: cada .lgzm-movil es position:relative con
	   z-index:1 —lo necesita para quedar por encima de los corazones del
	   mockup grande— y un posicionado sin z-index pierde contra él aunque
	   vaya después en el marcado. Bug real del 2026-09-09: el claim salía
	   partido por el móvil central y se leía "Gan… tus". */
	z-index: 2;
	/* 360/420px y no 560: una sola línea de texto en una caja de 560×132
	   tapaba los tres móviles. Píldora, además, como en la referencia del
	   cliente: con una línea, el radius-24 se leía como un bloque. */
	/* width: max-content y no dejar que encoja solo: al estar posicionado
	   con left:50%, el ancho disponible que calcula el navegador es solo el
	   que va del centro al borde, así que la píldora se quedaba en 188px y
	   partía el claim en tres líneas (medido en 375px, 2026-09-10). Con
	   max-content mide lo que mide el texto, y el max-width sigue poniendo
	   el techo. */
	width: max-content;
	max-width: min(360px, calc(100% - 2 * var(--lgzm-margin-mobile)));
	padding: 14px 24px;
	background: var(--lgzm-accent);
	color: var(--lgzm-on-ink);
	border-radius: var(--lgzm-radius-pill);
	text-align: center;
	/* Ahora la píldora es el único CTA de la banda (antes había además un
	   botón debajo, dos llamadas a lo mismo). De ahí el flex, la flecha y
	   los estados. */
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	text-decoration: none;
	transition: background-color var(--lgzm-dur-fast) var(--lgzm-ease-out), transform var(--lgzm-dur-press) var(--lgzm-ease-out);
}
a.lgzm-tiktok-banda__claim:hover {
	background: var(--lgzm-accent-hover);
}
a.lgzm-tiktok-banda__claim:active {
	transform: translate(-50%, -50%) scale(0.97);
}
.lgzm-tiktok-banda__flecha {
	display: inline-block;
	flex-shrink: 0;
	line-height: 0;
	transition: transform var(--lgzm-dur-fast) var(--lgzm-ease-out);
}
.lgzm-tiktok-banda__flecha svg {
	display: block;
	width: 20px;
	height: 16px;
}
@media (hover: hover) and (pointer: fine) {
	a.lgzm-tiktok-banda__claim:hover .lgzm-tiktok-banda__flecha {
		transform: translateX(4px);
	}
}
@media (prefers-reduced-motion: reduce) {
	.lgzm-tiktok-banda__flecha,
	a.lgzm-tiktok-banda__claim {
		transition: none;
	}
}
@media (min-width: 1024px) {
	.lgzm-tiktok-banda__claim {
		max-width: 420px;
		padding: 16px 32px;
	}
}
.lgzm-tiktok-banda__claim p {
	margin: 0;
}

.lgzm-tiktok-banda__cta {
	display: flex;
	justify-content: center;
	margin-top: 32px;
}

/* =========================================================================
   10 · FAQ
   ========================================================================= */

.lgzm-faq {
	display: flex;
	flex-direction: column;
	gap: 32px;
}
@media (min-width: 1024px) {
	.lgzm-faq {
		flex-direction: row;
		gap: 80px;
	}
}

.lgzm-faq__head {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 16px;
}
@media (min-width: 1024px) {
	.lgzm-faq__head {
		width: 360px;
		flex-shrink: 0;
	}
}
.lgzm-faq__head p {
	color: var(--lgzm-ink-secondary);
}

.lgzm-faq__list {
	display: flex;
	flex-direction: column;
	gap: 10px;
	flex: 1 0 0;
}

.lgzm-faq-item {
	border-radius: var(--lgzm-radius-24);
	border: 1px solid var(--lgzm-ink-hairline);
	padding: 22px 24px;
}
.lgzm-faq-item[open] {
	background: var(--lgzm-accent-wash);
	border-color: transparent;
	padding: 24px;
}
.lgzm-faq-item__summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	list-style: none;
	cursor: pointer;
	transition: color var(--lgzm-dur-fast) var(--lgzm-ease-out);
}
.lgzm-faq-item__summary::-webkit-details-marker {
	display: none;
}
.lgzm-faq-item__pregunta {
	color: var(--lgzm-ink);
	transition: color var(--lgzm-dur-fast) var(--lgzm-ease-out);
}
@media (hover: hover) and (pointer: fine) {
	.lgzm-faq-item:not([open]) .lgzm-faq-item__summary:hover .lgzm-faq-item__pregunta {
		color: var(--lgzm-accent);
	}
}
.lgzm-faq-item__icon {
	position: relative;
	width: 20px;
	height: 20px;
	flex-shrink: 0;
}
.lgzm-faq-item__icon::before,
.lgzm-faq-item__icon::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	background: var(--lgzm-accent);
	transform: translate(-50%, -50%);
}
.lgzm-faq-item__icon::before {
	width: 12px;
	height: 2px;
}
.lgzm-faq-item__icon::after {
	width: 2px;
	height: 12px;
}
.lgzm-faq-item[open] .lgzm-faq-item__icon::after {
	display: none;
}
.lgzm-faq-item__respuesta {
	margin: 12px 0 0;
	color: var(--lgzm-ink-secondary);
}

@media (prefers-reduced-motion: no-preference) {
	.lgzm-faq-item__respuesta {
		animation: lgzm-faq-fade 200ms var(--lgzm-ease-out);
	}
}
@keyframes lgzm-faq-fade {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

/* =========================================================================
   11 · Formulario
   =========================================================================
   Bloque azul desde el 2026-09-01: el cliente pidió que destacara, y tras
   mover la sección al puesto 9 (plan 101) es el cierre real de la página.
   Antes era ink-wash, indistinguible del resto. */

.lgzm-formulario {
	background: var(--lgzm-accent);
	color: var(--lgzm-on-ink);
}
.lgzm-formulario__inner {
	display: flex;
	flex-direction: column;
	gap: 32px;
}
@media (min-width: 1024px) {
	.lgzm-formulario__inner {
		flex-direction: row;
		/* stretch y no flex-start: el masonry necesita conocer una altura
		   real para poder llenarla (ver .lgzm-formulario__mosaico-masonry
		   más abajo, height:100% en vez de un valor fijo) — con
		   flex-start se quedaba "flotando" a una altura fija que casi
		   nunca coincidía con la del formulario, dejando azul liso debajo
		   cuando el formulario era más alto (bug real reportado por el
		   cliente, 2026-09-02). */
		align-items: stretch;
		gap: 56px;
	}
}

.lgzm-formulario__col {
	display: flex;
	flex-direction: column;
	gap: 24px;
	flex: 1 0 0;
	min-width: 0;
}
@media (min-width: 1024px) {
	.lgzm-formulario__col {
		max-width: 560px;
	}
}
/* Sin mosaico, la columna del formulario se centra en vez de quedarse
   pegada a la izquierda con medio bloque azul vacío al lado. */
.lgzm-formulario--sin-mosaico .lgzm-formulario__col {
	margin-inline: auto;
}

.lgzm-formulario__copy {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 14px;
}
/* 0.85 y no un valor más bajo (p. ej. 0.75, el que usan otros párrafos
   sobre superficie oscura en este tema): sobre --lgzm-accent en concreto
   es un azul relativamente claro, y 0.82 ya calculaba 4.46:1 — por debajo
   del mínimo AA de 4.5:1 aunque a simple vista se lea bien. Comprobado con
   la fórmula real de contraste (WCAG), no a ojo, tal y como pedía este
   plan. */
.lgzm-formulario__copy p {
	color: rgba(255, 255, 255, 0.85);
}

/* La tarjeta blanca. Todo el reestilado de los campos de Forminator (más
   abajo en este mismo fichero) da por hecho que están sobre blanco: no
   quitar este fondo sin revisar aquello. */
/* Sin offset vertical: con 18px de caída (como estaba antes) la sombra se
   acumulaba abajo y apenas se notaba arriba/a los lados, un halo que se
   leía "diagonal" en vez de una tarjeta flotando de forma pareja
   (petición del cliente, 2026-09-02). El blur grande por sí solo ya
   reparte la sombra por igual en las cuatro direcciones. */
.lgzm-formulario__form {
	padding: 20px;
	border-radius: var(--lgzm-radius-24);
	background: var(--lgzm-paper);
	color: var(--lgzm-ink);
	box-shadow: 0 0 40px rgba(3, 6, 61, 0.18);
}
@media (min-width: 640px) {
	.lgzm-formulario__form {
		padding: 28px;
	}
}
.lgzm-formulario__pendiente {
	padding: 24px;
	border: 1px dashed var(--lgzm-ink-hairline);
	border-radius: var(--lgzm-radius-16);
	color: var(--lgzm-ink-secondary);
}

/* ---------- Mosaico de fotos (columna derecha) ----------
   Dos bloques de marcado distintos, no uno que se oculta con CSS y basta:
   en móvil es un carrusel de scroll de verdad, reutilizando el componente
   base (petición del cliente, 2026-09-02 — antes era una rejilla de 2
   columnas que en móvil se veía "demasiado larga"). Desde 1024px se oculta
   y gana el masonry animado de más abajo ("como el header", misma
   petición).

   min-width: 0 y el margin-inline negativo: mismo bug que
   .lgzm-carousel--tiktok-niveles (ver ese comentario, sections.css) — este
   carrusel también vive dentro de .lgzm-container (comparte fila con la
   columna del formulario), así que sin min-width:0 el contenido sin
   partir del track empuja a toda la página a desbordar.

   A diferencia de tiktok-niveles, aquí SÍ se cancela el padding del
   contenedor con un margen negativo en vez de poner a 0 el padding del
   propio track: este carrusel no comparte fila con nada más en móvil (el
   mockup de tiktok sí), así que puede ir a sangre igual que RTBs/Reseñas
   — y por eso el padding-inline del track NO se toca aquí, se queda con
   el que ya trae el componente base, que es el que pone el margen visible
   una sola vez (no hay padding del contenedor que cancelar dos veces). */
.lgzm-carousel--formulario-mosaico {
	min-width: 0;
	flex: 1 0 0;
	margin-inline: calc(-1 * var(--lgzm-margin-mobile));
}
@media (min-width: 600px) and (max-width: 1023.98px) {
	.lgzm-carousel--formulario-mosaico {
		margin-inline: calc(-1 * clamp(20px, 5vw, 56px));
	}
	.lgzm-carousel--formulario-mosaico .lgzm-carousel__track {
		padding-inline: clamp(20px, 5vw, 56px);
		scroll-padding-inline: clamp(20px, 5vw, 56px);
	}
}
@media (min-width: 1024px) {
	.lgzm-carousel--formulario-mosaico {
		display: none;
	}
}

/* ---------- Mosaico de fotos, masonry animado (escritorio) ----------
   Solo desde 1024px (por debajo gana el carrusel de arriba). Mismo
   mecanismo que el fondo del hero (.lgzm-masonry-*, más arriba en este
   fichero, y legazyum_hero_masonry_columnas() en helpers.php): columnas
   con la lista de fotos duplicada, animadas -50% en bucle sin costura.

   A diferencia del hero, este masonry NO vive dentro de un contenedor con
   position:absolute+inset:0 que le dé su alto — aquí hace falta una
   altura explícita, por eso .lgzm-formulario__mosaico-masonry la fija
   directamente. El resto (.lgzm-masonry-col, __track, __img, la animación
   y sus variantes de duración/dirección) es exactamente el mismo CSS que
   ya usa el hero: no hace falta duplicarlo. */
.lgzm-formulario__mosaico-masonry {
	display: none;
}
@media (min-width: 1024px) {
	/* Ni un valor fijo (antes 640px) ni height:100%/min-height:0 (probados
	   y descartados los dos, 2026-09-02): dentro de un flex de altura
	   indefinida, el contenedor SIEMPRE usa el mayor "tamaño hipotético" de
	   TODOS sus hijos para calcular su propia altura — y el contenido real
	   del masonry (las fotos duplicadas para el bucle sin costura) es
	   enorme, así que por mucho min-height:0 que se le ponga, ese contenido
	   seguía contando. La única forma de que un hijo no cuente en absoluto
	   para ese cálculo es sacarlo del flujo normal: position:absolute. Por
	   eso el marcado real (template-parts/home/formulario.php) mete un
	   envoltorio extra .lgzm-formulario__mosaico-masonry-grid con todo el
	   contenido, y este elemento de aquí se queda vacío de "peso" —
	   position:relative, sin altura propia, y position:absolute+inset:0 en
	   el hijo. Es el mismo truco que ya usa el fondo del hero
	   (.lgzm-hero__masonry dentro de .lgzm-hero__media). */
	.lgzm-formulario__mosaico-masonry {
		display: block;
		position: relative;
		flex: 1 0 0;
		align-self: stretch;
	}
	.lgzm-formulario__mosaico-masonry-grid {
		position: absolute;
		inset: 0;
		display: grid;
		grid-template-columns: repeat(2, 1fr);
		gap: 16px;
		overflow: hidden;
	}
	/* Difuminado arriba/abajo, no un corte seco donde entran/salen las
	   fotos del bucle (petición del cliente, 2026-09-02). Probado antes
	   con mask-image: el navegador lo registraba en el CSS computado pero
	   no se veía nada en pantalla real (mask-image es más delicado entre
	   motores/versiones de lo que promete). Esta versión es la técnica de
	   toda la vida, sin sorpresas: una capa por encima con el color real
	   del fondo (--lgzm-accent) que se funde a transparente.

	   Sobre .lgzm-masonry-col (cada columna) y NO sobre -grid (el
	   contenedor de las dos): la columna 2 lleva su propio margin-top de
	   64px para el efecto "ladrillo" (más abajo en este mismo bloque) —
	   puesto en el contenedor compartido, el difuminado se posicionaba
	   contra el borde del contenedor, no contra donde esa columna
	   realmente empieza a mostrar fotos, así que en la 2ª columna no se
	   veía (bug real visto por el cliente, 2026-09-02). Cada columna ya
	   es su propio position:relative + overflow:hidden, así que esto
	   respeta el desplazamiento de cada una automáticamente. */
	.lgzm-formulario__mosaico-masonry-grid .lgzm-masonry-col::before,
	.lgzm-formulario__mosaico-masonry-grid .lgzm-masonry-col::after {
		content: '';
		position: absolute;
		left: 0;
		right: 0;
		height: 72px;
		pointer-events: none;
		z-index: 1;
	}
	/* -1px y no 0: redondeo de subpíxel entre el borde recortado
	   (overflow:hidden) de la columna y esta capa dejaba una línea de 1px
	   sin cubrir, con el azul liso del fondo asomando sin difuminar
	   (visto por el cliente, 2026-09-02). Solapar 1px de más no se nota
	   —el degradado empieza en el mismo color de fondo— y de sobra queda
	   cortado igualmente por el overflow:hidden de la columna. */
	.lgzm-formulario__mosaico-masonry-grid .lgzm-masonry-col::before {
		top: -1px;
		background: linear-gradient(to bottom, var(--lgzm-accent) 0%, transparent 100%);
	}
	.lgzm-formulario__mosaico-masonry-grid .lgzm-masonry-col::after {
		bottom: -1px;
		background: linear-gradient(to top, var(--lgzm-accent) 0%, transparent 100%);
	}
	/* Alturas variables, no las 4:5 fijas del hero (petición del cliente
	   con referencia visual, 2026-09-02: quería un masonry de verdad, no
	   una rejilla uniforme). Las fotos del CPT lgzm_diseno se sirven
	   siempre con recorte duro a 4:5 (lgzm-card, inc/setup.php) — no hay
	   forma de que varíen de verdad sin generar un tamaño de imagen nuevo
	   y regenerar las miniaturas ya subidas, un cambio mucho más grande.
	   En su lugar se recorta cada foto a una proporción distinta según su
	   posición (nth-child), reutilizando el mismo archivo 4:5 ya seguro —
	   el efecto visual de alturas variables sin tocar imágenes. */
	.lgzm-formulario__mosaico-masonry-grid .lgzm-masonry-col__img:nth-child(3n + 1) {
		aspect-ratio: 1 / 1;
	}
	.lgzm-formulario__mosaico-masonry-grid .lgzm-masonry-col__img:nth-child(3n + 2) {
		aspect-ratio: 3 / 4;
	}
	.lgzm-formulario__mosaico-masonry-grid .lgzm-masonry-col__img:nth-child(3n) {
		aspect-ratio: 4 / 5;
	}
	/* Desalineado a propósito: la referencia del cliente tiene las dos
	   columnas desplazadas entre sí (el "ladrillo" típico de un masonry
	   de verdad), no arrancando las dos a la misma altura como el hero
	   (2026-09-02). Solo en esta instancia, no en el hero. */
	.lgzm-formulario__mosaico-masonry-grid .lgzm-masonry-col--2 {
		margin-top: 64px;
	}
}

.lgzm-mosaico-item {
	position: relative;
	margin: 0;
	border-radius: var(--lgzm-radius-16);
	overflow: hidden;
}
.lgzm-mosaico-item__img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 5;
	object-fit: cover;
}
/* ---------- Reestilado de Forminator (§7.6) ----------
   Apunta a las clases estándar de Forminator (forminator-row/col/field/…).
   Verificar contra el HTML real una vez creado el formulario: el marcado
   exacto puede variar algo según la versión del plugin instalada. */

/* width + max-width al 100%, no solo display:flex: .forminator-row es
   flex, pero su padre (<form>, el que genera Forminator) es display:block
   — un contenedor flex dentro de un bloque normal usa "shrink-to-fit" para
   su width:auto (se comporta como un float/inline-block: se ajusta al
   ancho de su contenido en vez de estirarse), no "llenar el disponible"
   como haría un <div> normal. Con contenido que no puede partir línea
   dentro (el placeholder largo de Select2, más abajo) ese shrink-to-fit
   crecía más de la cuenta y arrastraba a los hijos con él — la raíz real
   de que el selector de "Tipo de grupo" se saliera del formulario en
   móvil (bug encontrado con el inspector, no a ojo, 2026-09-02). */
.lgzm-formulario__form .forminator-row {
	display: flex;
	flex-direction: column;
	gap: 12px;
	width: 100%;
	max-width: 100%;
}
@media (min-width: 640px) {
	.lgzm-formulario__form .forminator-row:has(.forminator-col + .forminator-col) {
		flex-direction: row;
	}
}
/* forminator-grid.open.min.css (del propio plugin) le pone margin-bottom:
   20px a cada .forminator-col menos al último — pensado para cuando las
   columnas se apilan (su sistema de rejilla, no el nuestro). Aquí las
   columnas van en una fila flex con gap, así que ese margen de fábrica
   solo sobraba: hacía que la primera columna de cada pareja "reservase"
   20px de más frente a la segunda, con alturas de campo por lo demás
   idénticas (encontrado con el inspector, 2026-09-02). */
.lgzm-formulario__form .forminator-col {
	margin-bottom: 0 !important;
}
/* flex-shrink:1 (no 0): el campo "Tipo de grupo" es un Select2 cuyo
   placeholder por defecto ("Por favor, selecciona una opción") no envuelve
   línea (white-space:nowrap de fábrica en Select2) — con flex-shrink:0 esa
   anchura de contenido sin partir empujaba la columna entera fuera de la
   fila y del formulario en móvil (bug real reportado por el cliente,
   2026-09-02). min-width:0 ya estaba, pero no basta si el hijo no puede
   encogerse en absoluto. */
.lgzm-formulario__form .forminator-col {
	flex: 1 1 0;
	min-width: 0;
	max-width: 100%;
}
/* 12px y no 14 (2026-09-03): con nueve campos, dos píxeles por hueco
   suman 16px de formulario — parte del arreglo de "los campos quedan
   muy altos" que pidió el cliente (plan 114). */
.lgzm-formulario__form > * + * {
	margin-top: 12px;
}

/* El campo siempre lleva su propio stroke (petición del cliente,
   2026-09-02, con referencia visual: cada campo se lee como su propia
   tarjeta, no solo al enfocarlo). Con el foco pasa a azul con un
   resplandor más marcado — dos capas: un anillo definido pegado al borde
   y un halo más difuso alrededor, que es lo que de verdad se lee como
   "glow" y no un simple cambio de color de borde. */
/* width:100% explícito y no dado por hecho: .forminator-field es
   display:flex pero NO es un flex-item (su padre .forminator-col es
   display:block, no display:flex), así que su width:auto sigue el
   algoritmo de "shrink-to-fit" (como un float o un inline-block) en vez
   de estirarse al ancho disponible. Con contenido que no puede partir
   línea (el placeholder largo de Select2, sin white-space:normal) ese
   shrink-to-fit crecía hasta el ancho del texto y empujaba toda la
   columna fuera del formulario en móvil — la causa real, más arriba de
   las de .forminator-col y .select2-container (bug real, 2026-09-02). */
/* Padding/gap reducidos (2026-09-03, plan 114): el cliente pidió
   explícitamente campos más bajos ("muy altos" en su feedback). De
   10px 16px 11px a 7px 16px 8px + gap 3→2 quita 7px por campo sin tocar
   el tamaño del texto ni el radio de la card. */
.lgzm-formulario__form .forminator-field {
	display: flex;
	flex-direction: column;
	gap: 2px;
	width: 100%;
	max-width: 100%;
	padding: 7px 16px 8px;
	background: var(--lgzm-paper);
	border: 1px solid rgba(47, 75, 255, 0.35);
	border-radius: var(--lgzm-radius-16);
	transition: border-color var(--lgzm-dur-fast) var(--lgzm-ease-out), box-shadow var(--lgzm-dur-fast) var(--lgzm-ease-out);
}
.lgzm-formulario__form .forminator-field:focus-within {
	border-color: var(--lgzm-accent);
	box-shadow: 0 0 0 2px var(--lgzm-paper), 0 0 0 5px var(--lgzm-accent), 0 0 28px 6px rgba(47, 75, 255, 0.45);
}
/* Error (2026-09-03, plan 114): faltaba del todo — Forminator marca el
   campo con .forminator-has_error en el contenedor pero, sin esto, la
   card se quedaba con su borde azul de siempre y el único aviso era el
   texto rojo debajo (encontrado enviando el formulario vacío, no a
   ojo). Va DESPUÉS de :focus-within a propósito y con la misma
   especificidad (2 clases): si el campo sigue enfocado al fallar la
   validación, gana el rojo — es el estado que de verdad necesita verse.
   rgb(229,25,25) es el mismo rojo que ya usa Forminator en el mensaje de
   error, no uno nuevo.
   transition: none es obligatorio, no cosmético: Forminator revalida el
   campo activo en tiempo real (cada pulsación) y eso reestilaba el nodo
   con la frecuencia suficiente para que la transición de border-color
   nunca llegara a completarse — se reiniciaba en el frame 0 una y otra
   vez (confirmado con element.getAnimations(): 5 CSSTransition
   "running" con localTime 0 de forma permanente), y el borde se quedaba
   congelado en azul PARA SIEMPRE por mucho !important que se le pusiera,
   porque una transición en curso pesa más que cualquier !important en la
   cascada. Sin transición no hay nada que Forminator pueda dejar a
   medias: el rojo aparece al instante. */
.lgzm-formulario__form .forminator-field.forminator-has_error {
	transition: none;
	border-color: rgb(229, 25, 25);
	box-shadow: 0 0 0 2px var(--lgzm-paper), 0 0 0 5px rgb(229, 25, 25), 0 0 20px 4px rgba(229, 25, 25, 0.35);
}
/* line-height 18→14 (2026-09-03): la etiqueta no necesita el interlineado
   de un párrafo, solo una línea de texto — otros 4px menos por campo.
   margin-bottom con !important: forminator-base.min.css le pone 10px de
   margen inferior a la etiqueta con más especificidad que este selector
   (encontrado midiendo el campo real: sobraban 10px exactos frente a lo
   calculado, 2026-09-03). Sin esto el recorte de altura de aquí arriba no
   se nota. */
.lgzm-formulario__form .forminator-label {
	font-family: 'Geist', sans-serif;
	font-weight: 400;
	font-size: 12px;
	line-height: 14px;
	color: var(--lgzm-ink-secondary);
	margin: 0 !important;
}
/* appearance: none es la parte que de verdad arregla "los campos siguen
   siendo cuadros dentro de los cards" (2026-09-02): border:0 no basta en
   un <input type="number"> ni en un <select> nativo — el navegador sigue
   pintando su propio control (flechas de incremento, caja del
   desplegable) POR ENCIMA del CSS de borde/fondo, con su aspecto nativo
   del sistema operativo. Sin appearance:none esa caja nativa es
   precisamente el "cuadrado dentro de la tarjeta" que se veía. !important
   porque forminator-base.min.css (del propio plugin) trae
   ".forminator-ui.forminator-custom-form[data-design="basic"]
   .forminator-input { appearance: auto; }" — 3 clases + 1 atributo, más
   específico que este selector nuestro de 2 clases, así que sin
   !important perdía la cascada y no se notaba el cambio (bug real visto
   en pruebas, 2026-09-02). */
/* line-height 25→22 (2026-09-03, plan 114): otros 3px menos por campo.
   font-size se queda en 16px — bajarlo dispara el zoom automático de
   Safari/iOS al enfocar un input, no es una opción. */
.lgzm-formulario__form .forminator-input,
.lgzm-formulario__form .forminator-textarea,
.lgzm-formulario__form select {
	font-family: 'Geist', sans-serif;
	font-weight: 400;
	font-size: 16px;
	line-height: 22px;
	color: var(--lgzm-ink-secondary);
	border: 0;
	padding: 0;
	background: transparent;
	width: 100%;
	appearance: none !important;
	-webkit-appearance: none !important;
	-moz-appearance: none !important;
}
/* La caja azul de esquinas más cuadradas DENTRO de la card, solo visible
   con el campo activo, no era ni appearance ni Select2: es el
   :focus-visible GLOBAL de base.css (outline: 2px solid var(--lgzm-
   accent); outline-offset:2px — se aplica a cualquier elemento enfocable
   de toda la web). El input lo hereda igual que cualquier botón o enlace,
   y sale COMO SEGUNDO rectángulo azul, separado del borde+glow de
   .forminator-field de aquí arriba, porque el outline no respeta el
   border-radius de la card (bug real confirmado con el inspector del
   cliente, 2026-09-02, no una sospecha). Se quita aquí porque el borde +
   glow de la card YA hace de indicador de foco — quitarlo del <input> no
   deja el campo sin foco visible, lo deja con uno solo. */
.lgzm-formulario__form .forminator-input:focus-visible,
.lgzm-formulario__form .forminator-textarea:focus-visible,
.lgzm-formulario__form select:focus-visible {
	outline: none;
}
.lgzm-formulario__form .forminator-textarea {
	min-height: 48px;
	resize: vertical;
}

/* "Tipo de grupo" se creó en Forminator como Select2 (no como Radio/
   Checkbox — ver el aviso del checklist más abajo, en los límites del
   plan 113), y Select2 no es un <select> normal: oculta el <select>
   nativo (a ese ya le llega el appearance:none de arriba, pero no se ve)
   y pinta su propia caja en <span class="select2-selection">, con su
   propio CSS por defecto (forminator-form-basic.select2.min.css) — otra
   fuente real del "cuadrado dentro de la tarjeta". Los !important son
   necesarios: Select2 fija el ancho por JS como estilo en línea
   (llegó a verse en 32px de ancho, un bug real visto en pruebas,
   2026-09-02) y su propio CSS ya trae bastante especificidad. */
/* min-width:0 además de width:100%: el CSS base de Select2 trae
   min-width:100% de fábrica, y dentro de una fila flex con contenido sin
   partir (el placeholder largo, ver .select2-selection__rendered más
   abajo) ese min-width se resolvía contra el ancho del CONTENIDO en vez
   del de la columna — el verdadero origen de que el selector se saliera
   del formulario en móvil (bug real, 2026-09-02; el flex-shrink de
   .forminator-col de aquí arriba no bastaba por sí solo). */
.lgzm-formulario__form .select2-container {
	width: 100% !important;
	min-width: 0 !important;
}
.lgzm-formulario__form .select2-selection {
	background: transparent !important;
	border: 0 !important;
	border-radius: 0 !important;
	min-height: auto !important;
	padding: 0 !important;
}
/* white-space:nowrap es el valor de fábrica de Select2 para esta lista, y
   con un placeholder largo ("Por favor, selecciona una opción") era lo
   que forzaba el ancho mínimo que acabó empujando la columna entera fuera
   del formulario en móvil (ver el comentario de .forminator-col más
   arriba, que es donde de verdad se arregla). overflow/text-overflow aquí
   son un cinturón de seguridad para que, si el texto aun así no cupiera,
   se recorte con puntos suspensivos en vez de desbordar visualmente. */
.lgzm-formulario__form .select2-selection__rendered {
	padding: 0 !important;
	padding-right: 24px !important;
	font-family: 'Geist', sans-serif;
	font-size: 16px;
	line-height: 22px;
	color: var(--lgzm-ink-secondary);
	white-space: nowrap !important;
	overflow: hidden !important;
	text-overflow: ellipsis !important;
}
.lgzm-formulario__form .select2-selection__placeholder {
	color: var(--lgzm-ink-secondary);
}
.lgzm-formulario__form .select2-selection__arrow {
	top: 50% !important;
	right: 0 !important;
	transform: translateY(-50%);
	color: var(--lgzm-ink-secondary);
}
/* Select2 también es enfocable (role="combobox", tabindex) y le llegaba
   el mismo outline global de base.css que a los inputs de arriba — mismo
   arreglo, mismo motivo. */
.lgzm-formulario__form .select2-selection:focus-visible,
.lgzm-formulario__form .select2-selection:focus {
	outline: none;
}

/* El mensaje de error ("Este campo es obligatorio") es de Forminator, no
   nuestro — su CSS lo genera por formulario con un id concreto
   (#forminator-module-46110 aquí), que gana por especificidad a cualquier
   selector nuestro de clases; !important es obligatorio, no cosmético.
   rgb(229,25,25) no es un color inventado: es el mismo rojo que ya usa
   Forminator en el asterisco de "obligatorio" y en los bordes de error —
   se reutiliza para no meter un segundo rojo en la página. */
.lgzm-formulario__form .forminator-error-message {
	margin-top: 4px !important;
	padding: 0 !important;
	background: transparent !important;
	color: rgb(229, 25, 25) !important;
	font-size: 12px;
}
.lgzm-formulario__form .forminator-response-message.forminator-error {
	margin-top: 12px !important;
	padding: 12px 16px !important;
	border-radius: var(--lgzm-radius-16) !important;
	background: rgba(229, 25, 25, 0.08) !important;
	box-shadow: none !important;
	color: rgb(178, 20, 20) !important;
}

/* El panel desplegable de Select2 ("Tipo de grupo") tampoco estaba
   vestido: usaba el recuadro por defecto del plugin (borde negro sin
   radio, sin sombra) — otra caja de Forminator suelta dentro de una
   página que ya no se parece a eso. Mismo motivo de !important que
   arriba: el CSS del plugin trae bastante especificidad propia. Este
   panel NO vive dentro de .lgzm-formulario__form en el DOM (Select2 lo
   añade aparte), así que va sin ese prefijo. */
.forminator-select-dropdown {
	border: 1px solid var(--lgzm-ink-hairline) !important;
	border-radius: var(--lgzm-radius-16) !important;
	background: var(--lgzm-paper) !important;
	box-shadow: 0 12px 32px rgba(3, 6, 61, 0.16) !important;
	overflow: hidden;
}
.forminator-select-dropdown .select2-results__option--highlighted {
	background: var(--lgzm-accent-wash) !important;
	color: var(--lgzm-ink) !important;
}
.forminator-select-dropdown .select2-results__option--selected {
	background: var(--lgzm-accent) !important;
	color: var(--lgzm-on-ink) !important;
}

/* Categoría: chips en píldora, nunca desplegable (§7.6). El campo debe
   crearse como Radio/Checkbox en Forminator, no como Select — ver
   checklist en template-parts/home/formulario.php. */
.lgzm-formulario__form .forminator-radio,
.lgzm-formulario__form .forminator-checkbox {
	background: none;
	border: 0;
	padding: 0;
}
.lgzm-formulario__form .forminator-radio ul,
.lgzm-formulario__form .forminator-checkbox ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
}
.lgzm-formulario__form .forminator-radio label,
.lgzm-formulario__form .forminator-checkbox label {
	display: inline-flex;
	align-items: center;
	padding: 10px 16px;
	border-radius: var(--lgzm-radius-pill);
	border: 1px solid var(--lgzm-ink-hairline);
	background: var(--lgzm-paper);
	color: var(--lgzm-ink);
	font-family: 'Geist', sans-serif;
	font-size: 14px;
	line-height: 21px;
	cursor: pointer;
}
/* :not(.forminator-consent):not(.forminator-privacy) — el checkbox de
   consentimiento comparte la clase forminator-checkbox con las chips de
   categoría (mismo <label>), así que sin esta exclusión esta regla
   también le ocultaba a él el input nativo, dejando la casilla invisible. */
.lgzm-formulario__form .forminator-radio input,
.lgzm-formulario__form .forminator-checkbox:not(.forminator-consent):not(.forminator-privacy) input {
	position: absolute;
	opacity: 0;
	width: 1px;
	height: 1px;
}
.lgzm-formulario__form .forminator-radio label:has(input:checked),
.lgzm-formulario__form .forminator-checkbox label:has(input:checked) {
	background: var(--lgzm-accent);
	border-color: var(--lgzm-accent);
	color: var(--lgzm-on-ink);
}
.lgzm-formulario__form .forminator-radio label:has(input:focus-visible),
.lgzm-formulario__form .forminator-checkbox label:has(input:focus-visible) {
	outline: 2px solid var(--lgzm-accent);
	outline-offset: 2px;
}

/* El botón de enviar viene envuelto en el mismo .forminator-field que los
   campos de texto: sin esto hereda el fondo/borde/padding de tarjeta que
   no le corresponde a un botón suelto. */
.lgzm-formulario__form .forminator-field:has(.forminator-button-submit) {
	padding: 0;
	background: none;
	border: 0;
	border-radius: 0;
	/* Más aire que el resto de campos (2026-09-03): con el gap general
	   ahora en 12px, el botón quedaba demasiado pegado al campo de
	   arriba para leerse como el cierre del formulario. */
	margin-top: 20px;
}

/* Ancho completo + "glow" (2026-09-03, plan 114): sombra del propio azul
   del botón, difusa y desplazada hacia abajo, más intensa en hover — es
   lo que pedía la referencia del cliente (img6). Hover solo con puntero
   real (mismo criterio que los inputs de arriba y que .lgzm-btn en
   components.css): en táctil el :hover se queda pegado tras cada toque,
   y aquí además mueve el botón (translateY), que sí se notaría fijo. */
.lgzm-formulario__form .forminator-button-submit {
	display: inline-flex;
	width: 100%;
	align-items: center;
	justify-content: center;
	font-family: 'Geist', sans-serif;
	font-weight: 600;
	font-size: 15px;
	line-height: 15px;
	padding: 18px 40px;
	border: 0;
	border-radius: var(--lgzm-radius-pill);
	background: var(--lgzm-accent);
	color: var(--lgzm-on-ink);
	cursor: pointer;
	box-shadow: 0 8px 24px rgba(47, 75, 255, 0.38);
	transition: background-color var(--lgzm-dur-fast) var(--lgzm-ease-out), box-shadow var(--lgzm-dur-fast) var(--lgzm-ease-out), transform var(--lgzm-dur-press) var(--lgzm-ease-out);
}
@media (hover: hover) and (pointer: fine) {
	.lgzm-formulario__form .forminator-button-submit:hover {
		background: var(--lgzm-accent-hover);
		box-shadow: 0 12px 32px rgba(47, 75, 255, 0.52);
		transform: translateY(-2px);
	}
}
.lgzm-formulario__form .forminator-button-submit:active {
	transform: scale(0.97);
	box-shadow: 0 4px 14px rgba(47, 75, 255, 0.34);
}
@media (prefers-reduced-motion: reduce) {
	.lgzm-formulario__form .forminator-button-submit:hover,
	.lgzm-formulario__form .forminator-button-submit:active {
		transform: none;
	}
}

.lgzm-formulario__form .forminator-error-message {
	color: #c0392b;
	font-size: 14px;
	margin-top: 4px;
}

/* Línea legal bajo el botón (2026-09-03, plan 114): sustituye al checkbox
   de consentimiento que el cliente pidió quitar. Aviso trasladado al
   cliente en el propio plan: la aceptación implícita no equivale
   legalmente a un consentimiento explícito y verificable; la validez de
   esta fórmula la tiene que confirmar su asesoría. */
.lgzm-formulario__legal {
	margin-top: 12px;
	text-align: center;
	color: var(--lgzm-ink-secondary);
}
.lgzm-formulario__legal a {
	color: var(--lgzm-accent);
	text-decoration: underline;
	text-underline-offset: 2px;
}

/* =========================================================================
   Categoría (§5.2) — taxonomy-tipo_grupo.php
   ========================================================================= */

/* Hero de categoría: mismo tratamiento visual que el de home, pero más
   bajo — no es una splash a pantalla completa, lleva miga de pan encima. */
/* Más corto que el hero de la home a propósito, y bajado otra vez el
   2026-09-11 (petición del cliente: que asome el principio de los mockups
   sin tener que scrollear).

   Los números están medidos, no elegidos: con 700px en escritorio el primer
   mockup de la galería empezaba en 901px y el pliegue de un portátil normal
   está en 900 — fallaba por UN píxel, que es lo que hacía que se viera
   cortado del todo. Con 580 empieza en 781 y asoma ~119px.
   En móvil pasa lo mismo pero depende de la pantalla: con 520px asomaba en
   un iPhone de 812 y NO en uno de 667. Con 420 asoma en los dos.
   Bajar el hero N píxeles sube el mockup exactamente N: entre uno y otro
   solo hay espaciado fijo. */
.lgzm-hero--categoria {
	min-height: 420px;
}
@media (min-width: 1024px) {
	.lgzm-hero--categoria {
		min-height: 580px;
	}
}

/* Color por defecto para cuando la miga va SOBRE PAPEL, no sobre foto
   (2026-09-10): hasta ahora el único color que existía era el blanco al
   60% pensado para ir dentro de un .lgzm-hero, y page-premios-tiktok.php
   —la única de las cuatro plantillas que usan esta miga sin hero a
   sangre, decisión explícita del plan 208— la reutilizaba tal cual: texto
   blanco sobre el blanco de la página, invisible. Confirmado con
   getComputedStyle, no a ojo: "Inicio / Premios TikTok" estaba ahí, con
   color rgba(255,255,255,.6), y no se veía. */
.lgzm-breadcrumb {
	display: flex;
	align-items: center;
	gap: 8px;
	color: var(--lgzm-ink-secondary);
}
.lgzm-breadcrumb a {
	color: inherit;
	text-decoration: none;
	transition: color var(--lgzm-dur-fast) var(--lgzm-ease-out);
}
.lgzm-breadcrumb a:hover {
	text-decoration: underline;
	color: var(--lgzm-ink);
}
/* El blanco al 60% se queda, pero SOLO dentro de un hero (las tres
   plantillas que sí llevan foto/scrim detrás): category/hero.php,
   page-nuestra-historia.php y page-legazyum-brand.php envuelven siempre la
   miga en .lgzm-hero__content, que es descendiente de .lgzm-hero. Nada
   visual cambia para esas tres. */
.lgzm-hero .lgzm-breadcrumb {
	color: rgba(255, 255, 255, 0.6);
}
.lgzm-hero .lgzm-breadcrumb a:hover {
	color: var(--lgzm-on-ink);
}

/* La galería es el contenido principal de la página de categoría desde el
   2026-09-01: va pegada a la cabecera, con menos aire arriba del que lleva
   una sección normal. */
.lgzm-galeria {
	padding-top: 32px;
}
@media (min-width: 1024px) {
	.lgzm-galeria {
		padding-top: 48px;
	}
}

/* Los diseños que pasan del corte inicial. display: none y no
   visibility/opacity: no deben ocupar sitio ni ser enfocables con Tab. */
.lgzm-lightbox-trigger.is-oculto {
	display: none;
}

.lgzm-galeria__acciones {
	display: flex;
	flex-direction: column;
	gap: 12px;
	align-items: center;
	margin-top: 28px;
}
@media (min-width: 640px) {
	.lgzm-galeria__acciones {
		flex-direction: row;
		justify-content: center;
	}
}

/* =========================================================================
   12 · Páginas internas (page.php y las plantillas de los planes 207/208/213)
   =========================================================================
   Añadido el 2026-09-08 (plan 202). No estaba en la maqueta: el diseño solo
   cubría home y categoría. */

.lgzm-pagina__head {
	margin-bottom: 24px;
}
@media (min-width: 1024px) {
	.lgzm-pagina__head {
		margin-bottom: 32px;
	}
}

/* Medida de lectura: un párrafo a 1200px de ancho es ilegible. 68ch es el
   rango cómodo (60-75 caracteres) y se aplica al contenido, no al
   contenedor, para que una imagen o una tabla del editor puedan salirse. */
.lgzm-pagina__contenido > * {
	max-width: 68ch;
}
.lgzm-pagina__contenido > * + * {
	margin-top: 1em;
}
.lgzm-pagina__contenido h2 {
	margin-top: 1.6em;
}
.lgzm-pagina__contenido img,
.lgzm-pagina__contenido figure {
	max-width: 100%;
	border-radius: var(--lgzm-radius-16);
}
.lgzm-pagina__contenido a {
	color: var(--lgzm-accent);
}

/* Hero de página interna. Reutiliza .lgzm-hero (bloque 01) para el fondo,
   el scrim y el color de texto; aquí solo se corrige la altura: el hero de
   la home mide 100svh porque es una portada, y una página de contenido con
   una portada a pantalla completa obliga a hacer scroll para leer la
   primera frase. */
.lgzm-hero--pagina {
	min-height: 60svh;
}
@media (min-width: 1024px) {
	.lgzm-hero--pagina {
		min-height: 480px;
	}
}

/* ---------- Página de Nuestra historia (plan 207, rediseñada 2026-09-09) ----------
   La primera versión era un párrafo de 721px de ancho y dos fotos dentro de
   una rejilla de 4 columnas fijas: media fila vacía y ningún ritmo. */

/* Entradilla: da entrada y rompe el muro de texto. 56ch y no 68: es texto
   grande, y a la misma medida en caracteres ocuparía demasiado ancho. */
.lgzm-historia__entradilla {
	max-width: 56ch;
	margin: 0 0 28px;
	color: var(--lgzm-ink);
}

.lgzm-historia__texto > p {
	max-width: 68ch;
	margin: 0;
}
.lgzm-historia__texto > p + p {
	margin-top: 1em;
}
/* Dos columnas solo en escritorio: una única columna de 721px es demasiado
   larga para leer cómoda. Por debajo de 1024px, columna única sin
   excepción — dos columnas en móvil serían ilegibles. */
@media (min-width: 1024px) {
	.lgzm-historia__texto {
		column-count: 2;
		column-gap: 48px;
	}
	.lgzm-historia__texto > p {
		max-width: none;
	}
	/* Sin esto, un párrafo puede partirse entre columnas dejando una línea
	   suelta arriba de la segunda. */
	.lgzm-historia__texto > p {
		break-inside: avoid;
	}
}

/* Cifras. Primer bloque tras el hero (2026-09-10): margin-bottom y no -top,
   para separarlas de la entradilla que viene justo después en vez de dejar
   un hueco extra encima (el padding de .lgzm-section ya abre aire arriba).
   En móvil van en columna, no tres números apretados en una fila. */
.lgzm-historia__cifras {
	display: grid;
	grid-template-columns: 1fr;
	gap: 20px;
	margin: 0 0 48px;
	padding: 28px 24px;
	list-style: none;
	background: var(--lgzm-ink-wash);
	border-radius: var(--lgzm-radius-24);
}
@media (min-width: 640px) {
	.lgzm-historia__cifras {
		grid-template-columns: repeat(3, 1fr);
		gap: 24px;
		padding: 36px 32px;
		text-align: center;
	}
}
.lgzm-historia__cifras li {
	display: flex;
	flex-direction: column;
	gap: 4px;
}
.lgzm-historia__cifra-num {
	color: var(--lgzm-accent);
}
.lgzm-historia__cifra-txt {
	color: var(--lgzm-ink-secondary);
}

/* auto-fit + minmax en vez de un número fijo de columnas: con 2 fotos salen
   dos columnas grandes y llenan la fila, con 4 salen cuatro, y en móvil una.
   Sin un media query por cada cantidad posible de fotos, que es lo que
   dejaba media fila vacía cuando el cliente subía solo dos. */
.lgzm-historia__galeria {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
	gap: 12px;
	margin-top: 48px;
}
@media (min-width: 768px) {
	.lgzm-historia__galeria {
		gap: 16px;
	}
}
.lgzm-historia__foto {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	border-radius: var(--lgzm-radius-16);
}

.lgzm-historia__cta {
	display: flex;
	justify-content: center;
	margin-top: 48px;
}

/* ---------- Página de Premios TikTok (plan 208) ---------- */

/* Envoltorio azul de la cabecera de la página (2026-09-10, petición del
   cliente). Rompe hacia arriba el padding-top:112px fijo de
   body:not(.lgzm-con-hero) #main (components.css) — esta plantilla no
   tiene hero, así que se lleva ese hueco genérico, y hasta ahora se
   quedaba en blanco por debajo de la cabecera flotante. El margin-top
   negativo cancela EXACTAMENTE ese padding (mismo mecanismo que ya usa
   .lgzm-carousel--tiktok-niveles más arriba en este fichero, con márgenes
   horizontales negativos para salirse de .lgzm-container) y el
   padding-top que sigue lo vuelve a reservar, ahora coloreado: mismo
   espacio total, mismo sitio para el contenido de debajo, solo que de la
   cabecera flotante para abajo ya no es transparente. Con esto y con
   .lgzm-tiktok-section (mismo --lgzm-accent, justo debajo) es un único
   campo de azul continuo, sin costura entre los dos. */
.lgzm-tiktok-pagina__franja {
	margin-top: -112px;
	padding-top: 112px;
	background: var(--lgzm-accent);
}
/* Blanco sobre el azul de esta franja, con ámbito: el mismo criterio que
   .lgzm-hero .lgzm-breadcrumb un poco más abajo en este fichero, pero
   aplicado aquí porque esta franja NO es un .lgzm-hero (esta página no
   tiene hero, ver el docblock de page-premios-tiktok.php). */
.lgzm-tiktok-pagina__franja .lgzm-breadcrumb {
	color: rgba(255, 255, 255, 0.6);
}
.lgzm-tiktok-pagina__franja .lgzm-breadcrumb a:hover {
	color: var(--lgzm-on-ink);
}

.lgzm-pagina__migas {
	padding-top: 24px;
}
.lgzm-pagina__titulo {
	margin: 12px 0 0;
}

.lgzm-tiktok-galeria__rejilla {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 12px;
	margin: 0;
	padding: 0;
	list-style: none;
}
@media (min-width: 768px) {
	.lgzm-tiktok-galeria__rejilla {
		grid-template-columns: repeat(4, 1fr);
		gap: 16px;
	}
}
.lgzm-tiktok-galeria__item {
	display: flex;
	flex-direction: column;
	gap: 8px;
}
/* 9:16, que es el formato nativo de TikTok: con 4:5 se recortarían por
   arriba y por abajo justo donde suele estar el texto del vídeo. */
.lgzm-tiktok-galeria__video {
	display: block;
	width: 100%;
	aspect-ratio: 9 / 16;
	object-fit: cover;
	border-radius: var(--lgzm-radius-16);
	background: var(--lgzm-ink-wash);
}
.lgzm-tiktok-galeria__autor {
	color: var(--lgzm-ink-secondary);
	margin: 0;
}

.lgzm-tiktok-pagina__cierre {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 16px;
	padding-block: 48px;
	text-align: center;
}
.lgzm-tiktok-pagina__legal {
	color: var(--lgzm-ink-tertiary);
	margin: 0;
}
.lgzm-tiktok-pagina__legal a {
	color: inherit;
}

/* ---------- Página de Legazyum Brand (plan 213) ---------- */

.lgzm-brand-pagina__cierre {
	display: flex;
	justify-content: center;
	padding-bottom: 48px;
}
