/**
 * Portada del sitio — estilos.
 *
 * PALETA: la de la marca (`themes/voedia/assets/marca.css`). Aquí no se
 * declara ningún color: los `--vh-*` son alias que apuntan a los `--vm-*`.
 *
 * Proporción de la guía —70 % claro, 20 % azul, 10 % rosa—: el fondo y las
 * superficies son claros, el azul marca lo que es de Voedia y el rosa se
 * reserva para lo que convierte. En esta pantalla eso es UN botón: el de
 * empezar a leer.
 *
 * Tipografía: Figtree para interfaz y titulares, Lora para el cuerpo.
 *
 * @package Voedia_Reader
 */

/* LOS TOKENS VAN EN `:root`, NO EN `.voedia-home`. LO SEGUNDO ERA UN FALLO.
 *
 * Estaban declarados en `.voedia-home`, y parecía razonable: son de la portada.
 * Pero `Voedia_Home` imprime el DIÁLOGO de ficha FUERA de ese envoltorio —cuelga
 * de `.entry-content`, hermano y no hijo—, y ahí ningún `--vh-*` existe.
 *
 * Con colores literales no se notaba. Al pasar a variables, el botón principal
 * del diálogo quedó con `background: var( --vh-rosa-cta )` sin resolver —o sea,
 * transparente— y `color: #fff`: BLANCO SOBRE NADA. Invisible, y sin un solo
 * error en consola.
 *
 * En `:root` valen en cualquier punto del documento y el problema no puede
 * volver, ni aquí ni en la próxima pieza que se pinte fuera del envoltorio. */
:root {
	/* NINGÚN COLOR PROPIO. Todo apunta a `themes/voedia/assets/marca.css`, que
	   es donde vive la paleta oficial. Antes esta hoja declaraba nueve colores
	   suyos y ninguno coincidía con la guía: el azul iba un dígito desviado
	   (`#3f97c1` contra `#3f97c2`) y el gris de texto también (`#605d5e`
	   contra `#615e5f`). Se sacaron a ojo de una captura, no del documento.

	   EL HÉROE DEJA DE SER MARINO. Era `#0f3a52`, un azul casi negro que no
	   está en la paleta. La guía manda la proporción 70/20/10 —setenta por
	   ciento de claro— y su HTML de referencia resuelve el héroe en BLANCO,
	   dejando el degradado para las bandas de campaña. Aquí se hace lo mismo:
	   una cubierta de editorial se lee mejor sobre claro que recortada contra
	   un fondo oscuro. */
	--vh-fondo: var( --vm-fondo );
	--vh-superficie: var( --vm-blanco );
	--vh-tinta: var( --vm-negro );
	--vh-texto: var( --vm-texto );
	--vh-tenue: var( --vm-texto-tenue );
	--vh-azul: var( --vm-azul );
	--vh-azul-tinta: var( --vm-azul-tinta );
	--vh-azul-osc: var( --vm-azul-osc );
	--vh-azul-tinte: var( --vm-azul-tenue );
	--vh-borde: var( --vm-borde );
	--vh-rosa: var( --vm-rosa );
	--vh-rosa-cta: var( --vm-rosa-cta );
	--vh-rosa-osc: var( --vm-rosa-osc );
	--vh-oliva: var( --vm-oliva-tinta );
	--vh-profundo: var( --vm-azul-osc );
	--vh-degradado: var( --vm-azul-degradado );
	--vh-sans: var( --vm-sans );
	--vh-serif: var( --vm-serif );
}

.voedia-home {
	background: var( --vh-fondo );
	color: var( --vh-texto );
	font-family: var( --vh-sans );

	/* Ya no hace falta salirse de ninguna columna: la plantilla de portada del
	   tema entrega el ancho completo. El truco de `100vw` con márgenes
	   negativos que había aquí era un parche contra una plantilla ajena. */
	padding-bottom: 3.5rem;
}

.voedia-home a { text-decoration: none; }
.voedia-home *, .voedia-home *::before, .voedia-home *::after { box-sizing: border-box; }

/* El fondo, el ancho y la ausencia de título los da ahora el tema: `theme.json`
   pinta el fondo y `templates/front-page.html` no imprime título de página.
   Aquí ya no queda nada que corregir del tema. */

/* --- Destacado -------------------------------------------------------- */

/* EL HÉROE, EN CLARO.
 *
 * Era azul marino con el texto en blanco. La guía manda 70 % de claro y su
 * HTML de referencia resuelve el héroe en blanco; además, la cubierta de un
 * libro —que es lo que aquí hay que mirar— se lee mejor sobre claro que
 * recortada contra un fondo oscuro.
 *
 * El fondo no es blanco liso sino un tinte azul muy suave que se disuelve
 * hacia el blanco: separa el héroe de la cabecera, que también es blanca, sin
 * necesidad de una línea. */
.vh-destacado {
	position: relative;
	overflow: hidden;
	background: linear-gradient( 175deg, var( --vm-azul-velo ) 0%, var( --vm-blanco ) 62% );
	color: var( --vh-texto );
	padding: clamp( 2.5rem, 7vw, 5rem ) clamp( 1rem, 5vw, 4rem );
	margin-bottom: clamp( 2rem, 4vw, 3.25rem );
	border-bottom: 1px solid var( --vh-borde );
}

/* Un halo azul detrás de la cubierta. Da profundidad sin necesidad de una
   imagen de fondo que habría que producir para cada destacado. */
.vh-destacado::after {
	content: "";
	position: absolute;
	top: 50%;
	right: 12%;
	width: min( 40rem, 60vw );
	aspect-ratio: 1;
	transform: translateY( -50% );
	background: radial-gradient( circle, rgba( 63, 151, 194, 0.16 ) 0%, rgba( 63, 151, 194, 0 ) 68% );
	pointer-events: none;
}

.vh-destacado-contenido {
	position: relative;
	z-index: 2;
	flex-direction: row-reverse;
	justify-content: space-between;
	display: flex;
	gap: clamp( 1.5rem, 4vw, 3.5rem );
	align-items: center;
	max-width: 74rem;
	margin: 0 auto;
}

/* --- El carrusel del héroe --------------------------------------------- */

/* LAS LÁMINAS SE APILAN EN LA MISMA CELDA DE UNA REJILLA.
 *
 * Ni `position: absolute` ni un carril que se desplaza. Con la rejilla, las tres
 * ocupan la misma celda y el alto de la pista es el de la más alta: al cambiar
 * de diapositiva la página NO da un salto, que es el defecto habitual de los
 * carruseles cuando un texto es más largo que otro.
 *
 * Y sin JavaScript se ven las tres apiladas y legibles, porque `.es-activa`
 * solo la pone el guion. */
.vh-destacado-pista {
	display: grid;
}

.vh-destacado-lamina {
	grid-area: 1 / 1;
	min-width: 0;
}

/* Solo cuando el guion ha tomado el mando se ocultan las que no tocan. Se hace
   con `opacity` + `visibility` y no con `display` para poder fundir.
 *
 * EL FUNDIDO VA ESCALONADO, y no es un capricho: las láminas comparten celda, así
 * que en un cruce simétrico los dos títulos —serif, grandes, a la misma altura—
 * se ven encima uno de otro medio segundo y parece un error de pintado. La que
 * sale se va deprisa (0,25 s) y la que entra espera a que se haya ido (0,22 s de
 * retardo) antes de aparecer. El cruce sigue siendo suave y ya no hay dos textos
 * a la vez. */
.vh-destacado--carrusel .vh-destacado-lamina {
	opacity: 0;
	visibility: hidden;
	transform: translateY( 0.5rem );
	transition:
		opacity 0.25s ease,
		transform 0.25s ease,
		visibility 0s linear 0.25s;
}

.vh-destacado--carrusel .vh-destacado-lamina.es-activa {
	opacity: 1;
	visibility: visible;
	transform: none;
	transition:
		opacity 0.35s ease 0.22s,
		transform 0.35s ease 0.22s,
		visibility 0s linear 0.22s;
}

.vh-destacado-mando {
	position: relative;
	z-index: 3;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 1rem;
	max-width: 74rem;
	margin: clamp( 1.5rem, 3vw, 2.5rem ) auto 0;
}

/* El círculo es pequeño; la zona de pulsación no.
 *
 * Con 2,75 rem de diámetro las dos flechas pesaban más que los indicadores y
 * competían con el botón principal del héroe, que es lo que de verdad hay que
 * pulsar. Se baja el círculo a 1,9 rem y el objetivo táctil de 44 px se
 * mantiene con relleno transparente alrededor, en vez de con tamaño visible:
 * se ve discreto y se sigue acertando con el dedo. */
/* El círculo es pequeño; la zona de pulsación no.
 *
 * Con 2,75 rem de diámetro visible, las dos flechas pesaban más que los
 * indicadores y competían con el botón principal del héroe, que es lo que de
 * verdad hay que pulsar.
 *
 * El botón conserva sus 2,75 rem —el objetivo táctil de 44 px— pero no se pinta:
 * el círculo lo dibuja un pseudoelemento más pequeño dentro. Así se ve discreto
 * y se sigue acertando con el dedo. Bajar el botón entero habría arreglado lo
 * uno rompiendo lo otro. */
.vh-destacado-flecha {
	position: relative;
	isolation: isolate;
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	border: 0;
	background: none;
	color: var( --vh-azul-tinta );
	font-size: 1rem;
	line-height: 1;
	cursor: pointer;
	transition: color 0.15s ease;
}

.vh-destacado-flecha::before {
	content: '';
	position: absolute;
	z-index: -1;
	/* 2,75 rem menos 0,45 por lado = 1,85 rem de círculo. */
	inset: 0.45rem;
	border: 1px solid var( --vh-borde );
	border-radius: 50%;
	background: var( --vm-blanco );
	transition: background 0.15s ease, border-color 0.15s ease;
}

.vh-destacado-flecha:hover { color: var( --vh-azul-osc ); }
.vh-destacado-flecha:hover::before { background: var( --vh-azul-tinte ); border-color: var( --vh-azul ); }
.vh-destacado-flecha:focus-visible { outline: 2px solid var( --vh-azul ); outline-offset: -0.3rem; border-radius: 50%; }

/* --- Indicador de desplazamiento --------------------------------------- */

/* Debajo del héroe, para que se vea que la página sigue.
 *
 * Es un botón de verdad y no un dibujo: al pulsarlo baja a la sección siguiente.
 * Un indicador que dice «hay más abajo» y no se puede pulsar es una promesa a
 * medias — la mitad de la gente lo intenta. */
.vh-destacado-bajar {
	position: relative;
	z-index: 3;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.35rem;
	margin: clamp( 1.2rem, 2.5vw, 2rem ) auto 0;
	padding: 0.5rem 0.9rem;
	border: 0;
	border-radius: 0.5rem;
	background: none;
	/* NO en `--vh-tenue`: el héroe arriba es el tinte azul `#e8f4fb`, y ahí el
	   gris secundario da 4,19:1 —por debajo del 4,5 que pide un texto de 12,7 px
	   en semi-negrita—. Con el gris de cuerpo son 5,73:1. Sobre el marino de
	   antes no se planteaba; sobre claro, sí. */
	color: var( --vh-texto );
	font-size: 0.66rem;
	font-weight: 600;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	cursor: pointer;
	transition: color 0.15s ease;
}

.vh-destacado-bajar:hover { color: var( --vh-azul-tinta ); }
.vh-destacado-bajar:focus-visible { outline: 2px solid var( --vh-azul ); outline-offset: 2px; }

.vh-destacado-bajar svg {
	width: 1.35rem;
	height: 1.35rem;
	display: block;
	animation: vh-bajar 2.2s ease-in-out infinite;
}

/* Un vaivén corto y lento: lo justo para que el ojo lo encuentre sin que
   compita con el carrusel, que ya se mueve. */
@keyframes vh-bajar {
	0%, 100% { transform: translateY( 0 ); opacity: 0.75; }
	50%      { transform: translateY( 0.3rem ); opacity: 1; }
}

@media ( prefers-reduced-motion: reduce ) {
	.vh-destacado-bajar svg { animation: none; }
}

.vh-destacado-puntos { display: flex; align-items: center; gap: 0.5rem; }

/* Los indicadores son barras y no círculos: una barra puede alojar dentro el
   avance del temporizador, y así el carrusel dice cuánto le queda en vez de
   cambiar de golpe sin avisar. */
.vh-destacado-punto {
	padding: 0.5rem 0.15rem;   /* zona de pulsación cómoda alrededor de la barra */
	border: 0;
	background: none;
	cursor: pointer;
}

.vh-destacado-punto-barra {
	display: block;
	width: 2.5rem;
	height: 3px;
	border-radius: 999px;
	background: var( --vh-borde );
	overflow: hidden;
}

.vh-destacado-punto-barra span {
	display: block;
	width: 100%;
	height: 100%;
	border-radius: inherit;
	background: var( --vh-azul );
	transform: scaleX( 0 );
	transform-origin: left center;
}

.vh-destacado-punto.es-activo .vh-destacado-punto-barra span {
	animation: vh-punto-avance 7s linear forwards;
}

.vh-destacado-punto:focus-visible { outline: 2px solid var( --vh-azul ); outline-offset: 2px; }

@keyframes vh-punto-avance {
	from { transform: scaleX( 0 ); }
	to   { transform: scaleX( 1 ); }
}

/* Quien pide menos movimiento no recibe ni fundido ni cuenta atrás; el guion ya
   se encarga de no pasar las diapositivas solo. */
@media ( prefers-reduced-motion: reduce ) {
	.vh-destacado--carrusel .vh-destacado-lamina { transition: none; }
	.vh-destacado-punto.es-activo .vh-destacado-punto-barra span { animation: none; transform: scaleX( 1 ); }
}

/* El cintillo lleva ahora el icono del formato: es la primera vez que el
   visitante ve la señal, y de ahí la reconoce en el resto de la plataforma. */
.vh-cintillo-icono {
	display: inline-block;
	width: 1.05rem;
	height: 1.05rem;
	vertical-align: -0.2em;
	margin-right: 0.35rem;
}

.vh-cintillo-icono svg { width: 100%; height: 100%; display: block; }

/* Sin maqueta en volumen, la cubierta se enseña entera: es la imagen más grande
   de la página y recortarle el título al autor se nota mucho más aquí que en la
   rejilla. Se conserva la caja de proporción de libro para que el héroe no
   cambie de alto según qué título toque. */
/* Sin maqueta en volumen, la cubierta se enseña entera: es la imagen más grande
   de la página y recortarle el título al autor se nota mucho más aquí que en la
   rejilla.
 *
 * EL FILO CLARO NO ES DECORACIÓN. El héroe tiene fondo oscuro y casi todas las
 * cubiertas del catálogo también: puestas una sobre otra, la del documental
 * —verde azulado muy oscuro— se fundía con el fondo y parecía que la lámina no
 * tenía imagen. Un filo claro de un píxel le devuelve el borde. La sombra
 * proyectada, que sobre fondo claro bastaba, aquí no dibuja nada. */
.vh-destacado-portada {
	width: clamp( 8.5rem, 19vw, 14rem );
	aspect-ratio: 2 / 3;
	object-fit: contain;
	border-radius: 0.4rem;
	box-shadow:
		0 0 0 1px rgba( 18, 36, 46, 0.08 ),
		0 1.4rem 2.8rem rgba( 0, 0, 0, 0.6 );
	flex: none;
}

/* La maqueta en volumen ya trae su propia sombra y su halo en el PNG: si se le
   añaden los nuestros se ve un recuadro con doble sombra. */
/* La maqueta es un PNG con transparencia: un filo le dibujaría un rectángulo
   alrededor del aire. Trae su propia sombra dentro de la imagen. */
.vh-destacado-portada--maqueta {
	width: clamp( 11rem, 26vw, 20rem );
	aspect-ratio: auto;
	border-radius: 0;
	box-shadow: none;
	object-fit: contain;
}

/* ---------------------------------------------------------------------------
   LA CUBIERTA DEL HÉROE
   ---------------------------------------------------------------------------
   HUBO AQUÍ UNA MAQUETA DE LIBRO EN VOLUMEN —giro en 3D, canto de hojas y tapa
   que se abría— y se retiró el 14 de agosto de 2026, el mismo día que se puso.
   El motivo, dicho por Ernesto: el giro DEFORMA la cubierta. Y es cierto: una
   cubierta es trabajo de diseño resuelto en dos dimensiones, y escorzarla la
   estropea por mucho que el volumen quede vistoso alrededor.

   Lo que queda: la cubierta en su PROPORCIÓN y su ÁNGULO originales, y el lujo
   puesto por la LUZ en vez de por la geometría. Un destello recorre la cubierta
   al entrar la lámina, como el reflejo sobre un estampado metálico. No deforma
   nada porque no toca la imagen: pasa por encima.

   LA PROPORCIÓN LA MANDA EL FICHERO. El envoltorio se ajusta a la imagen
   —`inline-block` y `height: auto`— en vez de imponer un 2/3 que antes obligaba
   a `object-fit: contain` y dejaba franjas vacías en las cubiertas cuadradas,
   que en este catálogo las hay. */
.vh-portada {
	position: relative;
	display: inline-block;
	flex: none;
	line-height: 0;               /* sin el hueco de línea bajo la imagen */
	isolation: isolate;           /* la mezcla del destello no toca el fondo */
	border-radius: 0.4rem;
	overflow: hidden;             /* recorta el destello al canto de la cubierta */
	box-shadow:
		0 0 0 1px rgba( 18, 36, 46, 0.08 ),
		0 1.4rem 2.8rem rgba( 0, 0, 0, 0.6 );
	transition: transform 0.5s cubic-bezier( 0.22, 1, 0.36, 1 ), box-shadow 0.5s ease;
}

/* La cubierta manda dentro del envoltorio: el filo y la sombra los pone él, y
   duplicados dibujan un recuadro flotando sobre la imagen. */
.vh-portada .vh-destacado-portada {
	display: block;
	width: clamp( 8.5rem, 19vw, 14rem );
	height: auto;
	max-height: 26rem;
	aspect-ratio: auto;
	object-fit: contain;
	border-radius: 0;
	box-shadow: none;
}

/* Las que traen maqueta pintada en el PNG van más grandes y sin filo: el filo
   dibujaría un rectángulo alrededor del aire transparente. */
.vh-portada--maqueta {
	border-radius: 0;
	box-shadow: none;
	overflow: visible;
}

.vh-portada--maqueta .vh-destacado-portada--maqueta {
	width: clamp( 11rem, 26vw, 20rem );
	max-height: none;
}

/* Al pasar el ratón la cubierta se levanta un poco y la sombra se abre. Es el
   único movimiento continuo, y solo ocurre cuando alguien la está mirando: el
   carrusel para su avance con el ratón encima. */
.vh-portada:hover {
	transform: translateY( -0.4rem );
	box-shadow:
		0 0 0 1px rgba( 18, 36, 46, 0.10 ),
		0 2rem 3.6rem rgba( 0, 0, 0, 0.66 );
}

.vh-portada--maqueta:hover { box-shadow: none; }

/* EL DESTELLO. Una banda de luz inclinada que cruza la cubierta de lado a lado.
   Va en un pseudoelemento y no en el `span` para poder animar solo la banda y
   dejar el `span` quieto haciendo de recorte.
   `filter: blur` le quita el filo de cuchillo: una banda dura se lee como una
   raya blanca; difuminada, como un reflejo. */
.vh-portada-destello {
	position: absolute;
	inset: 0;
	overflow: hidden;
	pointer-events: none;
}

.vh-portada-destello::before {
	content: "";
	position: absolute;
	top: -40%;
	bottom: -40%;
	left: 0;
	width: 42%;
	transform: translateX( -180% ) skewX( -16deg );
	background: linear-gradient(
		90deg,
		rgba( 255, 255, 255, 0 ) 0%,
		rgba( 255, 255, 255, 0.16 ) 32%,
		rgba( 255, 255, 255, 0.82 ) 50%,
		rgba( 255, 255, 255, 0.16 ) 68%,
		rgba( 255, 255, 255, 0 ) 100%
	);
	/* `screen` SUMA luz en vez de pintar blanco encima. Es la diferencia entre
	   un reflejo y un velo: sobre las zonas oscuras de la cubierta el destello
	   se nota, y sobre las claras no las lava. Con opacidad normal al 50 % la
	   medición del banco solo veía 2 puntos de subida sobre 255 — o sea, nada.
	   `isolation` en el envoltorio evita que la mezcla se coma el fondo del
	   héroe cuando el destello se sale por el canto. */
	mix-blend-mode: screen;
	filter: blur( 3px );
}

/* La entrada: la cubierta sube un poco y se asienta. Va antes que el destello
   —el reflejo llega cuando la pieza ya está quieta— porque al revés parece que
   la luz la empuja. */
@keyframes vh-portada-entra {
	from { transform: translateY( 1.1rem ) scale( 0.972 ); }
	to   { transform: none; }
}

@keyframes vh-portada-destella {
	from { transform: translateX( -180% ) skewX( -16deg ); }
	to   { transform: translateX( 320% ) skewX( -16deg ); }
}

.vh-portada.es-entrando {
	animation: vh-portada-entra 0.62s cubic-bezier( 0.22, 1, 0.36, 1 ) backwards;
}

.vh-portada.es-entrando .vh-portada-destello::before {
	animation: vh-portada-destella 1.05s cubic-bezier( 0.4, 0, 0.3, 1 ) 0.42s backwards;
}

/* Quien pide menos movimiento se queda con la cubierta quieta y su sombra. El
   destello es adorno; la cubierta es la información. */
@media ( prefers-reduced-motion: reduce ) {
	.vh-portada,
	.vh-portada.es-entrando,
	.vh-portada.es-entrando .vh-portada-destello::before {
		animation: none;
		transition: none;
	}

	.vh-portada:hover { transform: none; }
}

.vh-destacado-texto { min-width: 0; }

/* La etiqueta de la guía: 0,72 rem, 700, muy espaciada, en oliva. Va en el
   oliva OSCURO: el oficial `#9e9e52` da 2,81:1 sobre claro y es ilegible. */
.vh-cintillo {
	margin: 0 0 0.7rem;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var( --vh-oliva );
}

/* El titular pasa a Figtree. La guía es tajante: los titulares son Figtree y
   Lora es para el cuerpo editorial. El `letter-spacing` negativo es lo que le
   da a la marca su aire compacto y moderno. */
.vh-destacado-titulo {
	margin: 0 0 0.4rem;
	font-family: var( --vh-sans );
	font-weight: 700;
	font-size: clamp( 2rem, 4vw, 3.2rem );
	line-height: 1.1;
	letter-spacing: -0.03em;
	/* EL AZUL DE VOEDIA. Encargo de Ernesto: los titulares sobre claro van en el
	   azul de la paleta original. Aquí puede ir el azul de marca a secas porque
	   son 56 px en negrita: para WCAG eso es «texto grande» y le basta con 3:1
	   —da 3,27—. Donde el titular es pequeño hay que usar el azul oscuro; está
	   anotado en cada sitio. */
	color: var( --vh-azul );
}

.vh-destacado-autor {
	margin: 0 0 1.1rem;
	font-size: 0.95rem;
	color: var( --vh-tenue );
}

/* El resumen es cuerpo editorial: Lora, interlínea 1,7 como pide la guía. */
.vh-destacado-resumen {
	margin: 0 0 1.5rem;
	max-width: 40rem;
	font-family: var( --vh-serif );
	font-size: 1.03rem;
	line-height: 1.7;
	color: var( --vh-texto );
}

/* --- Botones ---------------------------------------------------------- */

.vh-acciones {
	display: flex;
	flex-wrap: wrap;
	gap: 0.65rem;
	margin: 0;
}

.vh-boton {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* 44 px: el mínimo para no fallar el toque en el móvil. */
	min-height: 2.75rem;
	padding: 0 1.35rem;
	border: 1px solid transparent;
	border-radius: var( --vm-r );
	font-family: var( --vh-sans );
	/* 1 rem y no los 0,95 de la guía. Con la base al 120 % que lleva este sitio
	   —decisión de accesibilidad, ver `voedia.css`—, 0,95 rem son 18,24 px, que
	   se quedan cuatro décimas por debajo de los 18,66 px que WCAG considera
	   «texto grande» en negrita. Justo por debajo del umbral, el botón fantasma
	   exige 4,5:1 y da 4,46 sobre el tinte del héroe. A 1 rem son 19,2 px, entra
	   en texto grande y el mínimo baja a 3:1. Cuatro décimas de rem arreglan lo
	   que si no obligaría a retocar el azul oficial de la marca. */
	font-size: 1rem;
	font-weight: 700;
	letter-spacing: 0.01em;
	line-height: 1;
	cursor: pointer;
	transition: background-color 0.22s ease, border-color 0.22s ease, box-shadow 0.22s ease, transform 0.22s ease;
}

/* EL BOTÓN PRINCIPAL PASA DE AZUL A ROSA.
 *
 * Es el cambio de la guía con más consecuencias y el más fácil de discutir, así
 * que conviene dejar escrito el porqué: la guía reserva el rosa `#c25678` para
 * lo que convierte —«máximo 1-2 por pieza»— y el azul para la identidad. Con
 * todo en azul, el botón de empezar a leer no se distingue de un enlace de
 * sección; en rosa, es lo único rosa de la pantalla.
 *
 * Va en `--vm-rosa-cta` y no en `--vm-rosa`: el oficial con texto blanco encima
 * da 4,29:1 y no llega al 4,5:1 que exige AA para este tamaño de letra. */
.vh-boton--principal {
	background: var( --vh-rosa-cta );
	color: #fff;
	box-shadow: 0 4px 24px rgba( 194, 86, 120, 0.38 );
}

.vh-boton--principal:hover {
	background: var( --vh-rosa-osc );
	color: #fff;
	box-shadow: 0 6px 32px rgba( 194, 86, 120, 0.50 );
	transform: translateY( -2px );
}

/* El fantasma de la guía: borde azul de marca, letra en azul oscuro. La letra
   NO va en `--vh-azul`: sobre blanco da 3,27:1 y suspende. */
.vh-boton--secundario {
	background: transparent;
	border: 1.5px solid var( --vh-azul );
	color: var( --vh-azul-tinta );
}

.vh-boton--secundario:hover { background: var( --vh-azul-tinte ); color: var( --vh-azul-tinta ); }

/* ══ EL BOTÓN QUE NO ES UN BOTÓN ═════════════════════════════════════════
 *
 * «Próximamente» es un estado, no una acción: el título aún no ha entrado y no
 * hay nada que comprar ni que leer. Se pinta con el mismo gris tenue que la
 * etiqueta «Próximamente» de la cubierta —a propósito: son la misma cosa dicha
 * dos veces, y si no se parecieran volverían a leerse como dos mensajes
 * distintos, que es justo lo que se venía a arreglar—.
 *
 * Ni fondo de llamada ni borde de acción ni cursor de mano: lo único que se
 * conserva del botón es la caja, para que la rejilla no se descuadre entre una
 * tarjeta que vende y otra que no. Lo pinta un `<span>`, así que tampoco entra
 * en el tabulador.
 *
 * El contraste se mide, no se estima (regla dura nº8): `--vm-texto-tenue` sobre
 * `--vm-fondo` es el par que ya usa el resumen de las tarjetas. */
.vh-boton--espera,
.vh-rejilla .vh-boton--espera {
	background: transparent;
	border: 1.5px dashed var( --vh-borde );
	color: var( --vh-tenue );
	box-shadow: none;
	cursor: default;
}

.vh-boton--espera:hover {
	background: transparent;
	border-color: var( --vh-borde );
	color: var( --vh-tenue );
	box-shadow: none;
	transform: none;
}

@media ( prefers-reduced-motion: reduce ) {
	.vh-boton { transition: none; }
	.vh-boton--principal:hover { transform: none; }
}

/* ══ EL ROSA ES ESCASO A PROPÓSITO ═══════════════════════════════════════
 *
 * La guía pone un techo explícito: «máximo 1-2 por pieza». La portada tiene
 * 31 tarjetas de catálogo y cada una lleva su botón; en rosa serían treinta y
 * un botones de conversión en una misma pantalla y el color dejaría de
 * significar nada — que es exactamente lo que la regla evita.
 *
 * Así que DENTRO DE LAS REJILLAS los botones van en fantasma azul, los dos
 * estilos. El rosa se reserva para los tres sitios donde de verdad hay una
 * decisión: el botón del héroe, el de la puerta de acceso y el «Añadir al
 * carrito» de la ficha de producto.
 *
 * No se toca el PHP: `principal` y `secundario` siguen diciendo QUÉ debería
 * hacer este usuario —leer lo que ya tiene, o comprar—, que es información de
 * producto y no de color. Lo que cambia es cómo se pinta esa información según
 * dónde esté.
 *
 * ⚠️ Para Juan Manuel: la alternativa es dejar «Comprar» en rosa también en la
 * rejilla. Vende más agresivo y salta el techo de la guía. Es decisión suya. */
.vh-rejilla .vh-boton--principal {
	background: transparent;
	border: 1.5px solid var( --vh-azul );
	color: var( --vh-azul-tinta );
	box-shadow: none;
}

.vh-rejilla .vh-boton--principal:hover {
	background: var( --vh-azul-tinte );
	color: var( --vh-azul-tinta );
	box-shadow: none;
	transform: none;
}

/* --- Secciones -------------------------------------------------------- */

.vh-seccion {
	max-width: 82rem;
	margin: 0 auto clamp( 2.25rem, 4vw, 3.25rem );
	padding: 0 clamp( 1rem, 5vw, 4rem );
}

.vh-seccion-cabecera {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
	margin-bottom: 1.1rem;
	padding-bottom: 0.6rem;
	border-bottom: 1px solid var( --vh-borde );
}

.vh-seccion-titulo {
	margin: 0;
	font-family: var( --vh-sans );
	font-size: 1.08rem;
	font-weight: 700;
	/* 20,7 px en negrita con la base al 120 %: por encima de los 18,66 px que
	   WCAG pide para «texto grande», así que el azul de marca vale. */
	color: var( --vh-azul );
}

.vh-seccion-entradilla {
	margin: 0;
	font-size: 0.85rem;
	color: var( --vh-tenue );
}

/* «Ver la tienda» y sus hermanos son ENLACES: el azul de marca como color de
   letra da 3,27:1 y suspende AA. Van en el azul oscuro, que es el mismo azul
   de la paleta preparado para llevar texto. */
.vh-seccion-cabecera a { color: var( --vh-azul-tinta ); font-size: 0.85rem; font-weight: 600; white-space: nowrap; }
.vh-seccion-cabecera a:hover { text-decoration: underline; }

/* --- Rejilla de títulos ----------------------------------------------- */

/* Rejilla de CUATRO columnas y las filas que hagan falta.
   Fija, no `auto-fit`: con reparto automático el número de columnas cambia
   según cuántos títulos haya, y la portada se veía distinta cada vez que se
   añadía un libro. Cuatro es una retícula estable en la que las cubiertas
   quedan a un tamaño en el que se lee el título. */
.vh-rejilla {
	display: grid;
	grid-template-columns: repeat( 4, minmax( 0, 1fr ) );
	gap: clamp( 1rem, 2vw, 1.75rem );
	margin: 0;
	padding: 0;
	list-style: none;
}

@media ( max-width: 1024px ) { .vh-rejilla { grid-template-columns: repeat( 3, minmax( 0, 1fr ) ); } }
@media ( max-width: 720px )  { .vh-rejilla { grid-template-columns: repeat( 2, minmax( 0, 1fr ) ); } }

.vh-tarjeta {
	display: flex;
	flex-direction: column;
	background: var( --vh-superficie );
	border: 1px solid var( --vh-borde );
	border-radius: 0.5rem;
	overflow: hidden;
	transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}

.vh-tarjeta:hover {
	transform: translateY( -3px );
	border-color: var( --vh-borde );
	box-shadow: var( --vm-sombra-alta );
}

/* LA CAJA DE LA CUBIERTA LA GOBIERNA `portada.css`.
 *
 * `.vh-tarjeta-marco` lleva además la clase `voedia-portada`, y de ahí saca la
 * proporción, el redondeo, el fondo desenfocado y el `object-fit: contain` que
 * hace que la cubierta se vea entera. Aquí solo queda lo que es propio de que
 * este marco sea, además, un botón.
 *
 * No se repiten `aspect-ratio` ni `object-fit`: estaban en las dos hojas y quien
 * ganaba dependía del orden en que se encolaran, que no es fijo. */
.vh-tarjeta-marco {
	/* IMPRESCINDIBLE, y no es decorativo: la etiqueta y la barra de progreso van
	   en `position: absolute` y se anclan a este marco. Sin `relative` aquí se
	   anclan al primer ancestro posicionado que encuentren, y la barra de
	   progreso aparece como una raya suelta cruzando la página. Pasó. */
	position: relative;
	display: block;
	width: 100%;
	border: 0;
	padding: 0;
	cursor: pointer;
	/* El redondeo lo pone `.voedia-portada`; la tarjeta ya recorta por fuera. */
	border-radius: 0;
}

/* ABAJO A LA IZQUIERDA, en la esquina contraria a la insignia de formato.
 *
 * Las dos estaban arriba: la de formato a la derecha y esta a la izquierda. En
 * pantalla ancha cabían; al estrechar, «En tu biblioteca» y «Audiolibro» se
 * encontraban en medio y la segunda caía debajo de la primera. En esquinas
 * opuestas no pueden encontrarse por estrecha que sea la tarjeta.
 *
 * El `bottom` deja hueco a la barra de progreso, que ocupa los tres píxeles de
 * abajo del todo. */
.vh-etiqueta {
	position: absolute;
	/* Por encima del filo interior del marco, que va en `z-index: 2`. */
	z-index: 3;
	bottom: 0.5rem;
	left: 0.45rem;
	max-width: calc( 100% - 0.9rem );
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	padding: 0.15rem 0.5rem;
	border-radius: 999px;
	font-size: 0.6rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

/* LOS DISTINTIVOS LLEVAN TEXTO BLANCO Y SON PEQUEÑOS —13 px—: necesitan 4,5:1.
   El azul de marca da 3,27:1 y suspende, así que ninguno lo usa.

   TRES ESTADOS, TRES PESOS VISUALES DISTINTOS, y el orden importa:

     · «En tu biblioteca» — oliva (5,31:1). Es del cliente, no del catálogo.
     · «Disponible»       — azul oscuro (4,99:1). El color de la marca: es lo
                            que se puede comprar y leer HOY.
     · «Próximamente»     — gris (5,19:1). A propósito el más apagado de los
                            tres: es una espera, no una oferta. Con un color
                            vivo competiría con lo que sí está disponible, y a
                            24 de agosto de 2026 lo llevan los 31 títulos.

   El gris además es lo que hace que el día que aparezca el primer «Disponible»
   se distinga de un vistazo entre treinta «Próximamente». */
.vh-etiqueta--mio          { background: var( --vh-oliva ); color: #fff; }
.vh-etiqueta--disponible   { background: var( --vh-azul-tinta ); color: #fff; }
.vh-etiqueta--proximamente { background: var( --vm-texto-tenue ); color: #fff; }

.vh-progreso {
	position: absolute;
	z-index: 3;   /* como la etiqueta: por encima del filo interior del marco */
	left: 0;
	right: 0;
	bottom: 0;
	height: 3px;
	background: rgba( 20, 36, 61, 0.20 );
}

.vh-progreso span { display: block; height: 100%; background: var( --vh-azul ); }

.vh-tarjeta-cuerpo {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
	flex: 1;
	padding: 0.75rem 0.8rem 0.85rem;
}

.vh-tarjeta-nombre {
	font-family: var( --vh-serif );
	font-size: 0.92rem;
	line-height: 1.3;
	/* AQUÍ EL AZUL DE MARCA NO VALE, y no es una excepción caprichosa: el título
	   de la rejilla mide 17,7 px en peso 300. Eso para WCAG es texto normal y
	   exige 4,5:1; el azul de marca da 3,27. En una cubierta de 31 tarjetas, un
	   título fino y bajo de contraste es justo el que no se lee. Va en el azul
	   oscuro, que es el mismo azul de la paleta oficial. */
	color: var( --vh-azul-tinta );
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.vh-tarjeta-autor { font-size: 0.72rem; color: var( --vh-tenue ); }

.vh-tarjeta-precio {
	margin-top: 0.15rem;
	font-size: 0.8rem;
	font-weight: 600;
	color: var( --vh-tinta );
}

/* El botón se pega abajo para que todas las tarjetas de la fila terminen a la
   misma altura aunque los títulos ocupen distinto. */
.vh-tarjeta-accion { margin-top: auto; padding-top: 0.65rem; }

.vh-tarjeta-accion .vh-boton {
	width: 100%;
	min-height: 2.4rem;
	font-size: 0.82rem;
	padding: 0 0.7rem;
}

/* --- Idiomas ---------------------------------------------------------- */

.vh-idiomas {
	display: flex;
	flex-wrap: wrap;
	gap: 0.55rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.vh-idiomas a {
	display: inline-flex;
	align-items: center;
	min-height: 2.5rem;
	padding: 0 1.15rem;
	border: 1px solid var( --vh-borde );
	border-radius: 999px;
	background: var( --vh-superficie );
	color: var( --vh-tinta );
	font-size: 0.85rem;
}

.vh-idiomas a:hover { border-color: var( --vh-azul ); color: var( --vh-azul-tinta ); background: var( --vh-azul-tinte ); }

/* --- Categorías ------------------------------------------------------- */

.vh-categorias {
	display: grid;
	grid-template-columns: repeat( 3, minmax( 0, 1fr ) );
	gap: clamp( 1rem, 2vw, 1.5rem );
	margin: 0;
	padding: 0;
	list-style: none;
}

@media ( max-width: 860px ) { .vh-categorias { grid-template-columns: 1fr; } }

/* LAS TRES TARJETAS SON EL ARGUMENTO DE LA PLATAFORMA.
 *
 * EN AZUL DE LA PALETA, por encargo de Ernesto (24 de agosto de 2026). Pasaron
 * por tres estados: pastel con un emoji, azul marino, blanco de tarjeta, y
 * ahora el azul oficial.
 *
 * ES EL AZUL PRIMARIO `#3f97c2`, el mismo de los titulares y el logotipo.
 * Encargo de Ernesto: que la tarjeta sea del mismo azul que el resto.
 *
 * ⚠️ EL TEXTO VA EN BLANCO POR DECISIÓN DE ERNESTO, Y NO LLEGA A AA. Queda
 * escrito aquí para que nadie lo descubra dentro de seis meses creyendo que es
 * un descuido:
 *
 *   párrafo blanco sobre `#3f97c2`  →  3,27:1   (AA pide 4,5:1)
 *   título  blanco sobre `#3f97c2`  →  3,27:1   (pasa: 25 px en negrita es
 *                                                «texto grande» y pide 3:1)
 *
 * Es decir: el TÍTULO cumple y el PÁRRAFO no. Sobre este azul no hay ningún
 * color claro que pueda cumplir —haría falta una luminancia de 0,0213 o menos,
 * y la del blanco es 1,0—, así que las alternativas eran solo dos y ninguna se
 * ha tomado por cuenta propia:
 *
 *   · texto oscuro sobre este mismo azul (5,43:1), que es lo que había antes;
 *   · o volver la tarjeta al azul oscuro `#3e7691`, donde el blanco da 4,99:1.
 *
 * Las dos son un token de distancia. `pruebas/home/marca.js` lo lleva anotado
 * como excepción con nombre y fecha, y lo IMPRIME en cada pasada: si algún día
 * se decide arreglarlo, el banco lo recuerda.
 *
 * El icono sale del logotipo de Voedia App, que ya lleva los tres formatos
 * dentro (libro abierto, auriculares, pantalla con el play), y va CENTRADO. */
.vh-categoria {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	padding: 1.8rem 1.6rem 1.6rem;
	border-radius: var( --vm-r-tarjeta );
	overflow: hidden;
	min-height: 15rem;
	background: var( --vm-azul );
	border: 1px solid var( --vm-azul );
	box-shadow: var( --vm-sombra );
	isolation: isolate;
	transition: transform 0.22s ease, border-color 0.22s ease, box-shadow 0.22s ease;
}

/* SIN HALO. Había un resplandor en la esquina superior derecha, distinto por
   formato, que servía para diferenciar las tres tarjetas cuando el icono era un
   SVG plano. Con las ilustraciones el formato se reconoce de un vistazo, y el
   resplandor dejaba una mancha más clara justo detrás del texto: parecía que el
   párrafo llevara su propio fondo. Tarjeta plana. */

.vh-categoria:hover {
	transform: translateY( -3px );
	border-color: var( --vm-azul );
	box-shadow: var( --vm-sombra-alta );
}

/* SIN PASTILLA DETRÁS. Los iconos que entregó Ernesto el 24 de agosto de 2026
   son ilustraciones completas, con su propio volumen y su propia silueta;
   meterlas en un cuadrado translúcido las encajonaba y les robaba tamaño. La
   pastilla existía para dar cuerpo a un SVG plano de 64 px, y ese SVG ya no
   está aquí —sigue en los distintivos pequeños, donde sí hace falta—.

   ALTO FIJO Y ANCHO LIBRE: los tres ficheros se exportan a la misma altura y
   cada uno conserva su proporción, así que los tres miden lo mismo de alto en
   la tarjeta. Con `width` fijo, el de documentales —que es apaisado— salía más
   bajo que los otros dos. */
.vh-categoria-icono {
	position: relative;
	display: flex;
	align-items: flex-end;
	justify-content: center;
	width: 100%;
	margin-bottom: 0.9rem;
	isolation: isolate;
	/* EL ICONO VA ARRIBA Y NO SE MUEVE. `order: -1` lo deja el primero de la
	   tarjeta pase lo que pase: si algún día el orden del marcado cambia —o un
	   filtro mete algo delante—, el icono sigue encima del texto. */
	order: -1;

	/* ALTURA COMÚN AUNQUE UN ICONO SEA MÁS ALTO QUE OTRO.
	 *
	 * El de documentales va un 20 % más grande (ver abajo), y sin esto su
	 * tarjeta empujaría el título 19 px más abajo que las otras dos: tres
	 * titulares a tres alturas distintas en una fila de tres tarjetas.
	 *
	 * La caja mide lo que el icono MÁS ALTO y los tres se apoyan en su borde
	 * inferior (`align-items: flex-end`), así que comparten línea de suelo y los
	 * títulos quedan alineados. */
	min-height: 6rem;
}

/* LA SOMBRA DEBAJO DEL ICONO. Una elipse difusa que lo posa sobre la tarjeta en
   lugar de dejarlo flotando pegado. Va en un pseudoelemento y no en el
   `filter` de la imagen a propósito: una sombra proyectada sigue el contorno
   del dibujo —auriculares, claqueta— y se lee como suciedad; una elipse por
   debajo se lee como suelo.

   `z-index: -1` para que quede DETRÁS del icono, e `isolation` en el padre para
   que ese índice negativo no se escape por encima del fondo de la tarjeta. */
/* EL DE DOCUMENTALES, UN 20 % MÁS GRANDE. Encargo de Ernesto.
 *
 * Rompe a propósito la regla de «los tres a la misma altura» que se fijó antes,
 * y el motivo es óptico: su composición es apaisada —466 × 320 frente a los
 * 334 × 320 del libro—, así que a igual altura ocupa menos superficie y el ojo
 * lo lee como más pequeño. Igualar la caja no iguala el peso visual.
 *
 * 5 rem × 1,2 = 6 rem. La caja de arriba ya reserva ese alto para los tres, así
 * que los títulos siguen alineados. */
.vh-categoria--documentary .vh-categoria-icono img { height: 6rem; }

/* Y su sombra crece con él: una elipse del mismo tamaño debajo de un icono
   mayor se lee como que el icono flota. */
.vh-categoria--documentary .vh-categoria-icono::after { width: 62%; height: 1rem; }

.vh-categoria-icono::after {
	content: '';
	position: absolute;
	z-index: -1;
	bottom: -0.35rem;
	left: 50%;
	transform: translateX( -50% );
	width: 54%;
	height: 0.85rem;
	border-radius: 50%;
	background: radial-gradient( ellipse, rgba( 0, 0, 0, 0.34 ) 0%, rgba( 0, 0, 0, 0 ) 70% );
	pointer-events: none;
}

/* LA ALTURA VA EN LA IMAGEN, NO EN LA CAJA, y el primer intento se equivocó.
 *
 * Iba `height: 100%` sobre una caja de rejilla de 7 rem. Chrome no resolvió ese
 * porcentaje —el elemento estaba centrado con `place-items`, así que su tamaño
 * lo pone el contenido— y las tres imágenes salieron a su tamaño natural, 320
 * px, desbordando la tarjeta. Medido en la página desplegada: la caja daba
 * 134 px y la imagen 320.
 *
 * Con una longitud fija no hay porcentaje que resolver. Y como los tres
 * ficheros se exportan a la MISMA altura, esto basta para que los tres midan lo
 * mismo; el ancho lo pone cada proporción. */
.vh-categoria-icono img {
	/* UN TERCIO DE LA TARJETA. La tarjeta mide 15 rem de alto mínimo, así que el
	   icono va a 5. Iba a 7 rem —casi la mitad— y se comía el sitio del texto.
	   Si cambia el `min-height` de `.vh-categoria`, este número va detrás. */
	height: 5rem;
	width: auto;
	max-width: 100%;
	display: block;
	object-fit: contain;
}

/* Título en Figtree, descripción en Lora: es lo que la guía pide literalmente
   para la sección de características. */
/* Sobre el azul oscuro NO HAY MARGEN PARA LA TRANSPARENCIA: es el mismo fondo
   del pie, y allí ya se comprobó que ni el blanco al 90 % llega a AA. Los dos
   textos van en blanco puro y la jerarquía la hacen el tamaño y el peso. */
/* TODO EN FIGTREE, y el párrafo fino. Antes el título iba en Figtree y el
   párrafo en Lora negrita: dos familias y dos pesos gruesos en una tarjeta de
   tres líneas, que es lo que se veía recargado. Lora es para cuerpo editorial
   —la reseña del héroe, la ficha del libro—; el texto de una tarjeta de
   interfaz es interfaz. */
.vh-categoria h3 {
	position: relative;
	margin: 0.2rem 0 0.4rem;
	font-family: var( --vh-sans );
	font-weight: 700;
	font-size: 1.3rem;
	line-height: 1.2;
	letter-spacing: -0.015em;
	color: var( --vm-blanco );
}

.vh-categoria p {
	position: relative;
	margin: 0 0 1.4rem;
	max-width: 20rem;
	font-family: var( --vh-sans );
	font-size: 0.95rem;
	font-weight: 400;
	line-height: 1.55;
	color: var( --vm-blanco );
}

/* El botón se pega abajo para que las tres tarjetas lo alineen aunque sus
   textos midan distinto. */
.vh-categoria-boton,
.vh-categoria-estado { margin-top: auto; }

/* EL BOTÓN DE LAS TARJETAS, EN ROSA. Encargo de Ernesto (24 de agosto de 2026).
 *
 * Eran fantasma —contorno blanco— para no competir con el único CTA de la
 * página. Ahora son de relleno rosa, que es lo que se pidió: son la entrada a
 * cada uno de los tres escaparates y merecen peso.
 *
 * ⚠️ CON UN FILO CLARO, Y NO ES ADORNO. Medido: el rosa `#bc5374` contra el
 * azul de la tarjeta `#3e7691` da **1,10:1**. Los dos colores tienen casi la
 * misma luminosidad, así que solo se distinguen por TONO: el texto blanco se
 * lee sin problema (4,54:1), pero la FORMA del botón es invisible para quien no
 * separa rojo de verde, y también en una pantalla en blanco y negro o a pleno
 * sol. WCAG pide 3:1 para el contorno de un control.
 *
 * El filo claro lo resuelve sin tocar el color: es claro contra los dos, así
 * que el botón tiene borde para todo el mundo. Es el mismo motivo por el que la
 * sombra sola no bastaba —una sombra rosa sobre azul tampoco crea un canto—. */
.vh-categoria-boton {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* 44 px, el mínimo para no fallar el toque en móvil. Antes eran 2,6 rem. */
	min-height: 2.75rem;
	padding: 0 1.75rem;
	border-radius: var( --vm-r );
	background: var( --vm-rosa-cta );
	border: 1px solid rgba( 255, 255, 255, 0.55 );
	color: var( --vm-blanco );
	font-family: var( --vh-sans );
	font-size: 0.95rem;
	font-weight: 700;
	letter-spacing: 0.01em;
	text-decoration: none;
	box-shadow: 0 4px 18px rgba( 0, 0, 0, 0.22 );
	transition: background-color 0.22s ease, box-shadow 0.22s ease, transform 0.22s ease;
}

.vh-categoria-boton:hover {
	background: var( --vm-rosa-osc );
	color: var( --vm-blanco );
	border-color: var( --vm-blanco );
	box-shadow: 0 8px 26px rgba( 0, 0, 0, 0.30 );
	transform: translateY( -2px );
}

.vh-categoria-boton:focus-visible {
	outline: 3px solid var( --vm-blanco );
	outline-offset: 3px;
}

@media ( prefers-reduced-motion: reduce ) {
	.vh-categoria-boton { transition: none; }
	.vh-categoria-boton:hover { transform: none; }
}

/* Sin títulos todavía: se dice, y no se pone un botón que lleva a un escaparate
   vacío. */
.vh-categoria-estado {
	position: relative;
	display: inline-block;
	padding: 0.4rem 0.8rem;
	border-radius: 999px;
	background: rgba( 255, 255, 255, 0.14 );
	border: 1px solid rgba( 255, 255, 255, 0.28 );
	font-family: var( --vh-sans );
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var( --vm-blanco );
}

@media ( prefers-reduced-motion: reduce ) {
	.vh-categoria { transition: none; }
	.vh-categoria:hover { transform: none; }
}

/* --- Continúa donde lo dejaste ---------------------------------------- */

/* Tarjeta horizontal: la cubierta pequeña a un lado y el avance al otro. Aquí
   el libro ya se conoce —es tuyo—, así que manda el «por dónde iba» y no la
   portada. */
/* Tres columnas por dos filas: seis títulos, que es lo que se imprime. La
   sección es un recordatorio de lo que tienes a medias, no la biblioteca
   entera — para eso está el enlace de la cabecera de la sección. */
.vh-rejilla--continuar { grid-template-columns: repeat( 3, minmax( 0, 1fr ) ); }

/* La tarjeta es horizontal (cubierta + texto), así que necesita más ancho que
   una de la rejilla normal: baja a dos columnas antes. */
@media ( max-width: 1200px ) { .vh-rejilla--continuar { grid-template-columns: repeat( 2, minmax( 0, 1fr ) ); } }
@media ( max-width: 720px )  { .vh-rejilla--continuar { grid-template-columns: 1fr; } }

.vh-rejilla--continuar .vh-tarjeta { flex-direction: row; align-items: stretch; }

/* En la fila horizontal la cubierta es un acompañante, no la protagonista: se
   fija su ancho y el marco interior se encarga de la proporción.
 *
 * La separación va en MARGEN y no en relleno, y es deliberado: la barra de
 * progreso se ancla al borde inferior del marco, así que con relleno quedaba
 * catorce píxeles por debajo de la cubierta, suelta sobre el blanco de la
 * tarjeta. Con margen, el marco mide exactamente lo que la cubierta y la barra
 * cae sobre ella, que es donde significa algo. */
.vh-rejilla--continuar .vh-tarjeta-marco {
	width: 5.5rem;
	flex: none;
	align-self: flex-start;
	margin: 0.7rem 0 0.7rem 0.7rem;
}

.vh-rejilla--continuar .vh-tarjeta-marco .voedia-portada { width: 100%; }

.vh-rejilla--continuar .vh-tarjeta-cuerpo { padding: 0.9rem 1rem; }

.vh-rejilla--continuar .vh-tarjeta-accion { padding-top: 0.6rem; }
.vh-rejilla--continuar .vh-tarjeta-accion .vh-boton { width: auto; }

/* --- Garantías -------------------------------------------------------- */

.vh-confianza {
	display: grid;
	grid-template-columns: repeat( 3, minmax( 0, 1fr ) );
	gap: 1rem;
	margin: 0;
	padding: 1.4rem;
	list-style: none;
	border-radius: 0.7rem;
	background: var( --vh-superficie );
	border: 1px solid var( --vh-borde );
}

@media ( max-width: 720px ) { .vh-confianza { grid-template-columns: 1fr; } }

.vh-confianza li { display: flex; align-items: center; gap: 0.8rem; }

.vh-confianza-icono {
	display: grid;
	place-items: center;
	width: 2.4rem;
	height: 2.4rem;
	flex: none;
	border-radius: 0.5rem;
	background: var( --vh-azul-tinte );
	font-size: 1.05rem;
}

.vh-confianza-texto { display: flex; flex-direction: column; }
.vh-confianza-texto strong { font-size: 0.88rem; color: var( --vh-tinta ); }
.vh-confianza-texto span { font-size: 0.79rem; color: var( --vh-tenue ); }

/* --- Vista previa ----------------------------------------------------- */

body.vh-sin-scroll { overflow: hidden; }

/* ⚠️ EL DIÁLOGO SE PINTA FUERA DE `.voedia-home`.
 *
 * Lo imprime `Voedia_Home` pero cuelga de `.entry-content`, hermano de la
 * portada y no hijo. Ahí los `--vh-*` NO EXISTEN: se declaran en `.voedia-home`.
 * Mientras esta hoja llevaba colores literales daba igual; en cuanto pasaron a
 * variables, el diálogo se quedó sin tipografía y sin color y heredó lo que
 * hubiera. Lo destapó una comprobación de que todos los titulares fueran
 * Figtree: salía uno que no, y era este.
 *
 * Por eso aquí se usan los `--vm-*` de la marca, que viven en `:root` y están
 * definidos en cualquier punto del documento. */
.vh-dialogo {
	position: fixed;
	inset: 0;
	z-index: 99980;
	display: grid;
	place-items: center;
	padding: 1rem;
}

.vh-dialogo[hidden] { display: none; }

.vh-dialogo-velo {
	position: absolute;
	inset: 0;
	background: rgba( 20, 36, 61, 0.45 );
	backdrop-filter: blur( 3px );
}

.vh-dialogo-caja {
	position: relative;
	display: flex;
	gap: 1.6rem;
	max-width: 46rem;
	max-height: 86vh;
	overflow-y: auto;
	padding: 1.9rem;
	border-radius: 0.6rem;
	background: var( --vm-blanco );
	color: var( --vm-negro );
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
	box-shadow: 0 30px 70px rgba( 20, 36, 61, 0.3 );
}

.vh-dialogo-cerrar {
	position: absolute;
	top: 0.5rem;
	right: 0.6rem;
	width: 2.5rem;
	height: 2.5rem;
	border: 0;
	border-radius: 0.35rem;
	background: transparent;
	color: var( --vm-texto );
	font-size: 1.5rem;
	line-height: 1;
	cursor: pointer;
}

.vh-dialogo-cerrar:hover { color: var( --vm-negro ); background: var( --vm-azul-tenue ); }

.vh-dialogo-portada {
	width: 10.5rem;
	aspect-ratio: 2 / 3;
	object-fit: contain;
	border-radius: 0.35rem;
	flex: none;
	filter: drop-shadow( 0 0.5rem 1.2rem rgba( 20, 36, 61, 0.28 ) );
}

.vh-dialogo-texto h2 {
	margin: 0 0 0.3rem;
	font-family: var( --vm-sans );
	font-weight: 700;
	font-size: 1.5rem;
	color: var( --vm-azul );
}

.vh-dialogo-autor { margin: 0 0 0.9rem; font-size: 0.85rem; color: var( --vm-texto-tenue ); }

.vh-dialogo-sinopsis {
	margin: 0 0 1.4rem;
	font-family: var( --vm-serif );
	font-size: 0.94rem;
	line-height: 1.7;
	color: var( --vm-texto );
}

/* --- Voedia Completo: la suscripción de catálogo ---------------------- */

/* DOS TARJETAS Y NADA MÁS. La tentación en una sección de precios es la rejilla
   de tres con la del medio agrandada, y aquí no hay tres: hay mensual y anual.
   Dos columnas iguales, y el anual se distingue por su distintivo y por su
   borde, no por ser más grande — inflar una de dos hace que la otra parezca un
   descarte. */
.vh-planes {
	display: grid;
	grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
	gap: clamp( 1rem, 2vw, 1.5rem );
	margin: 0;
	padding: 0;
	list-style: none;
}

@media ( max-width: 720px ) { .vh-planes { grid-template-columns: 1fr; } }

.vh-plan {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.5rem;
	padding: 1.6rem 1.5rem 1.5rem;
	border: 1px solid var( --vh-borde );
	border-radius: var( --vm-r-tarjeta );
	background: var( --vh-superficie );
	box-shadow: var( --vm-sombra );
}

/* El anual se marca con el azul de la identidad, no con el rosa: el rosa de esta
   pantalla es del botón y de nadie más (ver «EL ROSA ES ESCASO A PROPÓSITO»). */
.vh-plan--anio {
	border-color: var( --vh-azul-claro );
}

/* DISTINTIVO EN AZUL OSCURO CON LETRA BLANCA, Y ESTÁ MEDIDO (regla dura nº8).
   El par que pedía el cuerpo —`--vm-azul-tinta` sobre `--vm-azul-tenue`— da
   4,46:1 y se queda cuatro centésimas por debajo del 4,5:1 de AA, que es
   exactamente la trampa que ya documentó el botón fantasma. En sólido, el
   blanco sobre `--vm-azul-tinta` da 4,99:1 y además se lee como lo que es: una
   pegatina, no un enlace. */
/* FUERA DEL FLUJO, y por una razón que solo se ve en la captura: dentro del
   flujo, el distintivo empujaba hacia abajo todo el contenido de la tarjeta
   anual, y las dos columnas quedaban desalineadas —«MENSUAL» a una altura y
   «ANUAL» a otra— por la única razón de que una lleva pegatina y la otra no.
   Comprobado en `pruebas/home/capturas/plan-escritorio.png`. */
.vh-plan-distintivo {
	position: absolute;
	top: 1.15rem;
	right: 1.5rem;
	padding: 0.28rem 0.6rem;
	border-radius: 999px;
	background: var( --vh-azul-tinta );
	color: #fff;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.02em;
	text-transform: uppercase;
}

/* EL EMBLEMA DEL PLAN.
 *
 * ALTURA FIJA EN `rem`, NO EN PORCENTAJE. El 24 de agosto de 2026 las tres
 * ilustraciones de formato salieron a 320 px y desbordaron su tarjeta porque su
 * alto iba en `height: 100%` sobre una caja cuyo tamaño lo ponía el contenido:
 * Chrome no resuelve ese porcentaje y se queda con el tamaño natural de la
 * imagen. Con una longitud fija no hay porcentaje que resolver (doc 21 §12.10).
 *
 * ANCHO LIBRE: los dos emblemas se exportan a la misma altura y cada uno
 * conserva su proporción —293 y 302 px de ancho—, así que los dos miden lo
 * mismo de alto en la tarjeta, que es lo que hace que las dos columnas se lean
 * como pareja. */
.vh-plan-emblema {
	display: block;
	margin-bottom: 0.15rem;
}

/* 8 REM Y NO 5,5, QUE ERA LO PRIMERO. A 5,5 rem el emblema se leía como una
   pegatina puesta encima y las letras de su cinta no se distinguían; el precio,
   a 2,1 rem, pesaba más que la marca. A 8 rem es la identidad de la tarjeta y su
   texto se lee. Medido mirando la captura, no calculado. */
.vh-plan-emblema img {
	display: block;
	width: auto;
	height: 8rem;
}

@media ( max-width: 720px ) {
	.vh-plan-emblema img { height: 6.5rem; }
}

/* PARA EL LECTOR DE PANTALLA, NO PARA LA VISTA.
 *
 * `display: none` NO vale: lo que se esconde así tampoco lo lee un lector de
 * pantalla, y entonces la tarjeta se quedaría literalmente sin nombre de plan
 * —el emblema es una imagen decorativa—. Este es el recorte de un píxel de toda
 * la vida, el mismo que usa el propio WordPress. */
.vh-solo-lectores {
	position: absolute !important;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect( 0 0 0 0 );
	clip-path: inset( 50% );
	white-space: nowrap;
	border: 0;
}

.vh-plan-nombre {
	margin: 0;
	font-family: var( --vh-sans );
	font-size: 0.95rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var( --vh-tenue );
}

.vh-plan-precio {
	margin: 0;
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 0.4rem;
	font-family: var( --vh-sans );
	font-size: 2.1rem;
	font-weight: 700;
	line-height: 1.1;
	color: var( --vh-tinta );
}

.vh-plan-cadencia {
	font-size: 0.9rem;
	font-weight: 600;
	color: var( --vh-tenue );
}

.vh-plan-nota {
	margin: 0;
	font-size: 0.85rem;
	line-height: 1.55;
	color: var( --vh-tenue );
}

/* El botón, abajo del todo y a todo el ancho de la tarjeta: las dos tarjetas no
   tienen por qué medir lo mismo de texto, y con `margin-top: auto` los dos
   botones quedan alineados aunque una nota ocupe dos líneas y la otra una. */
.vh-plan-boton {
	width: 100%;
	margin-top: auto;
	padding-top: 0.9rem;
	padding-bottom: 0.9rem;
}

/* LO QUE INCLUYE, UNA SOLA VEZ Y NO EN CADA TARJETA. Repetir la misma lista de
   tres puntos en las dos columnas invita a compararlas buscando la diferencia,
   y no la hay: los dos planes dan exactamente lo mismo. Lo único que cambia es
   cada cuánto se paga. */
.vh-plan-incluye {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem 1.6rem;
	margin: 1.1rem 0 0;
	padding: 0;
	list-style: none;
	font-size: 0.85rem;
	color: var( --vh-texto );
}

.vh-plan-incluye li {
	display: flex;
	align-items: baseline;
	gap: 0.45rem;
}

.vh-plan-incluye li::before {
	content: "✓";
	color: var( --vh-azul-tinta );
	font-weight: 700;
}

/* ══ LA LÍNEA QUE DICE CUÁNTO HAY HOY ════════════════════════════════════
 *
 * No es letra pequeña de descargo: es la misma regla que el 26 de agosto de
 * 2026 retiró treinta títulos de la venta, aplicada aquí. Vender «todo el
 * catálogo» sin decir cuánto de ese catálogo se abre hoy sería la contradicción
 * entre la etiqueta y el botón, otra vez y en otro sitio.
 *
 * Va en el gris tenue sobre el fondo de la portada —5,02:1, el mismo par que
 * los resúmenes de las tarjetas— y no en rojo ni en un recuadro de aviso: es un
 * dato, no una alarma. */
.vh-plan-estado {
	margin: 1.1rem 0 0;
	font-size: 0.85rem;
	color: var( --vh-tenue );
}

/* Quien ya la tiene no ve precios. */
.vh-plan-activo {
	padding: 1.5rem;
	border: 1px solid var( --vh-azul-claro );
	border-radius: var( --vm-r-tarjeta );
	background: var( --vm-azul-velo );
}

.vh-plan-activo-titulo {
	margin: 0 0 0.3rem;
	font-family: var( --vh-sans );
	font-size: 1.05rem;
	font-weight: 700;
	color: var( --vh-azul-tinta );
}

.vh-plan-activo-texto {
	margin: 0 0 1rem;
	font-size: 0.9rem;
	color: var( --vh-texto );
}

/* --- Pantallas pequeñas ----------------------------------------------- */

@media ( max-width: 760px ) {
	/* LA CUBIERTA, CENTRADA Y MÁS GRANDE. Encargo de Ernesto (24 de agosto de
	   2026). Iba pegada a la izquierda y a 7,5 rem, que en una columna estrecha
	   la dejaba pequeña y descolgada: el resto del héroe ocupa todo el ancho y
	   ella no.
	 *
	 * Se centra solo LA CUBIERTA, no el texto. Un titular de tres líneas
	 * centrado se lee peor que alineado a la izquierda, y en móvil el titular es
	 * lo primero que hay que leer. Por eso el contenedor sigue en
	 * `align-items: flex-start` y la lámina se centra con `align-self`. */
	.vh-destacado-contenido { flex-direction: column; align-items: flex-start; }

	.vh-portada,
	.vh-destacado-portada--maqueta { align-self: center; }

	.vh-destacado-portada { width: 11rem; }

	/* La cubierta del héroe también encoge. Comparte clase con la regla de
	   arriba, así que basta con que el envoltorio no imponga nada.
	   `min()` para que en una pantalla de 320 px no se salga: manda lo que
	   quepa, no el número fijo. */
	.vh-portada .vh-destacado-portada { width: min( 11rem, 62vw ); max-height: 20rem; }

	.vh-dialogo-caja { flex-direction: column; padding: 1.25rem; }
	.vh-dialogo-portada { width: 7rem; align-self: center; }
	.vh-seccion-cabecera { flex-direction: column; align-items: flex-start; gap: 0.3rem; }
}

@media ( prefers-reduced-motion: reduce ) {
	.vh-tarjeta { transition: none; }
	.vh-tarjeta:hover { transform: none; }
}

/* EL ESTADO DEL TÍTULO, en el cintillo del héroe.
 *
 * Una pastilla pequeña delante del idioma. No lleva el mismo fondo sólido que
 * la etiqueta de la rejilla porque aquí no va sobre una imagen: va sobre el
 * héroe claro, donde un relleno de color pesaría más que el propio titular.
 * Basta el color de la letra y un filo. */
.vh-cintillo-estado {
	display: inline-block;
	margin-right: 0.55rem;
	padding: 0.08rem 0.5rem;
	border-radius: 999px;
	border: 1px solid currentColor;
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	vertical-align: 0.05em;
}

.vh-cintillo-estado--disponible   { color: var( --vh-azul-tinta ); }
.vh-cintillo-estado--mio          { color: var( --vh-oliva ); }
.vh-cintillo-estado--proximamente { color: var( --vm-texto-tenue ); }

/* EN QUÉ IDIOMA ESTÁ EL LIBRO, en el cintillo del héroe.
   Va detrás del formato y separado por un punto: son dos datos del mismo rango
   —qué es y en qué idioma está— y ninguno manda sobre el otro. Más tenue que el
   formato porque el formato ya lo dice el icono y este dato no tiene icono.

   LA DIFERENCIA SE HACE CON COLOR, NO CON OPACIDAD. Iba a `opacity: 0.72`, que
   sobre el héroe marino se leía sin problema y sobre el héroe claro de la marca
   da 2,76:1 —el separador, 1,75:1—. Medido sobre la página desplegada. Ahora es
   el gris secundario de la marca a plena opacidad: 4,51:1, y sigue pesando
   menos que el oliva del formato, que es lo que se buscaba. */
.vh-cintillo-idioma {
	color: var( --vm-texto-tenue );
	font-weight: 400;
}

.vh-cintillo-idioma::before {
	content: "·";
	margin: 0 0.45rem;
}
