/**
 * Karmarc — hoja de estilos única.
 *
 * Orden: tokens, base, utilidades, cabecera, pie, componentes, galería,
 * lightbox, y por último los ajustes de pantalla pequeña.
 */

/* ---------------------------------------------------------------- tokens */

:root {
	--rojo: #e2342b;
	--rojo-oscuro: #b8261f;
	--negro: #1a1a1a;
	--grafito: #3d3d3d;
	--gris: #6b6b6b;
	--borde: #e2e2e0;
	--hueso: #f6f5f3;
	--blanco: #fff;

	--fuente: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
		"Helvetica Neue", Arial, sans-serif;

	--ancho: 1200px;
	--ancho-texto: 74ch;
	--margen: clamp(1rem, 4vw, 2.5rem);
	--hueco: 0.5rem;

	--transicion: 180ms ease;
}

/* ------------------------------------------------------------------ base */

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
}

/*
 * Margen de parada para los enlaces de ancla.
 *
 * La cabecera es fija (4,5 rem), así que sin esto el navegador deja el destino
 * justo debajo de ella y el título al que se salta queda TAPADO. Se reserva un
 * poco más que la altura de la cabecera para que además respire.
 */
:target,
section[id],
[id^="titulo-"] {
	scroll-margin-top: 6rem;
}

body {
	margin: 0;
	font-family: var(--fuente);
	font-size: 1.0625rem;
	line-height: 1.65;
	color: var(--negro);
	background: var(--blanco);
	-webkit-font-smoothing: antialiased;
}

img,
picture,
video,
canvas,
svg {
	display: block;
	max-width: 100%;
	height: auto;
}

h1,
h2,
h3,
h4 {
	line-height: 1.15;
	letter-spacing: -0.02em;
	font-weight: 700;
	margin: 0 0 0.5em;
	text-wrap: balance;
}

h1 {
	font-size: clamp(2rem, 5vw, 3.25rem);
}

h2 {
	font-size: clamp(1.5rem, 3vw, 2.125rem);
}

h3 {
	font-size: clamp(1.2rem, 2vw, 1.4rem);
}

p {
	margin: 0 0 1.2em;
}

a {
	color: var(--rojo);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.15em;
}

a:hover {
	color: var(--rojo-oscuro);
}

:focus-visible {
	outline: 3px solid var(--rojo);
	outline-offset: 2px;
}

/* ------------------------------------------------------------ utilidades */

.contenedor {
	width: 100%;
	max-width: var(--ancho);
	margin-inline: auto;
	padding-inline: var(--margen);
}

.seccion {
	padding-block: clamp(2.5rem, 6vw, 5rem);
}

.seccion--estrecha {
	max-width: 46rem;
}

/*
 * Entradilla que va justo debajo de la cabecera de página.
 *
 * Con la clase .seccion normal se acumulaban tres separaciones seguidas —la de
 * la cabecera, la de la entradilla y la de la banda siguiente— y quedaba un
 * hueco enorme entre el título y el contenido. Aquí el espacio es la mitad.
 */
.entradilla-pagina {
	padding-block: clamp(2.25rem, 4.5vw, 3.25rem) 0;
}

/*
 * Entradilla centrada, y algo más estrecha que el texto de lectura: un párrafo
 * centrado necesita líneas más cortas para que el ojo encuentre el principio
 * del siguiente renglón.
 */
.entradilla-pagina .pagina__entradilla {
	max-width: 62ch;
	margin: 0 auto;
	text-align: center;
}

.entradilla-pagina .pagina__entradilla p {
	text-align: center;
}

.seccion__titulo {
	font-size: clamp(1.35rem, 2.5vw, 1.75rem);
	margin-bottom: 1.2rem;
}

.prosa {
	max-width: var(--ancho-texto);
}

/*
 * Criterio de alineación del sitio.
 *
 * - Las CABECERAS de página van centradas: título y entradilla. Es un bloque
 *   corto que presenta la página, y centrado se lee como una portadilla.
 * - El TEXTO DE LECTURA va siempre a la izquierda. Un párrafo largo centrado
 *   obliga a buscar dónde empieza cada renglón.
 * - El bloque de texto se centra en la página aunque su contenido vaya a la
 *   izquierda: con max-width y sin margen automático, se quedaba pegado al
 *   borde izquierdo y la página parecía descompensada.
 *
 * La única cabecera que sigue a la izquierda es el hero de la portada, que no
 * es una portadilla sino la entrada al sitio y lleva botones alineados.
 */
.prosa,
.prosa p,
.prosa li,
.prosa h2,
.prosa h3 {
	text-align: left;
}

.pagina__contenido.prosa,
.entradilla-pagina .prosa,
.solucion-texto.prosa {
	margin-inline: auto;
}

.prosa > * + * {
	margin-top: 1.2em;
}

/*
 * WordPress marca con .screen-reader-text lo que solo debe oírse, no verse:
 * el título de la paginación, el de la barra de búsqueda, los «saltar a»…
 * Si el tema no define esa clase, todo eso aparece como texto suelto. Es lo que
 * hacía que la paginación se viese con un «Paginación de entradas» enorme.
 */
.visualmente-oculto,
.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.saltar-al-contenido {
	position: absolute;
	top: -100%;
	left: 0;
	z-index: 100;
	padding: 0.75rem 1.25rem;
	background: var(--negro);
	color: var(--blanco);
}

.saltar-al-contenido:focus {
	top: 0;
}

/* --------------------------------------------------------------- botones */

.boton {
	display: inline-block;
	padding: 0.7rem 1.4rem;
	border: 2px solid transparent;
	border-radius: 6px;
	font-weight: 600;
	font-size: 0.95rem;
	line-height: 1.2;
	text-decoration: none;
	cursor: pointer;
	transition: background var(--transicion), color var(--transicion),
		border-color var(--transicion);
}

.boton--principal {
	background: var(--rojo);
	border-color: var(--rojo);
	color: var(--blanco);
}

.boton--principal:hover {
	background: var(--rojo-oscuro);
	border-color: var(--rojo-oscuro);
	color: var(--blanco);
}

.boton--secundario {
	border-color: var(--negro);
	color: var(--negro);
}

.boton--secundario:hover {
	background: var(--negro);
	color: var(--blanco);
}

/* Para usar sobre fondo oscuro o sobre la foto del hero. */
.boton--fantasma {
	border-color: rgb(255 255 255 / 55%);
	color: var(--blanco);
}

.boton--fantasma:hover {
	background: var(--blanco);
	border-color: var(--blanco);
	color: var(--negro);
}

/* ------------------------------------------------------------------ hero */

/*
 * El hero ocupa la pantalla entera menos la cabecera fija.
 *
 * 100svh y no 100vh: en el móvil, vh cuenta con la barra del navegador
 * retraída, así que con vh el hero se sale por abajo y asoma la sección
 * siguiente justo lo que queríamos evitar. svh usa la altura *pequeña*, la que
 * de verdad se ve.
 */
.hero {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: center;
	min-height: calc(100svh - 4.5rem);
	padding-block: clamp(3rem, 8vw, 6rem) clamp(5rem, 9vw, 7rem);
	background: var(--negro);
	color: var(--blanco);
	overflow: hidden;
}

/* ------------------------------------------------------------ descubrir */

.hero__descubrir {
	position: absolute;
	bottom: clamp(1.5rem, 4vw, 2.5rem);
	left: 50%;
	transform: translateX(-50%);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.75rem;
	color: rgb(255 255 255 / 70%);
	text-decoration: none;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	transition: color var(--transicion);
}

.hero__descubrir:hover {
	color: var(--blanco);
}

/*
 * Una línea vertical que se recorre a sí misma, en lugar de la típica flecha
 * que rebota. El recorrido sugiere el gesto de bajar sin dar saltos, que en
 * una web sobria canta menos.
 */
/*
 * DOS PÍXELES, NO UNO.
 *
 * El padre se centra con translateX(-50%), lo que deja este elemento a caballo
 * entre dos píxeles del monitor. Con 1 px de ancho, Firefox de escritorio
 * reparte la línea al 50 % entre ambos: la gris aún se intuye porque es
 * constante, pero la marca roja, que además se mueve, queda tan pálida que no
 * se ve. Parecía que la animación no funcionara.
 *
 * En móvil no pasaba: con doble densidad, ese píxel son dos reales.
 *
 * Con 2 px el reparto deja una columna entera a plena intensidad y se ve
 * siempre. Comprobado en Firefox de escritorio con las dos anchuras.
 */
.hero__descubrir-linea {
	position: relative;
	display: block;
	width: 2px;
	height: 3rem;
	background: rgb(255 255 255 / 25%);
	overflow: hidden;
}

.hero__descubrir-linea::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	top: 0;
	height: 40%;
	background: var(--rojo);
	animation: karmarc-recorrer 2s ease-in-out infinite;
}

@keyframes karmarc-recorrer {
	0% {
		transform: translateY(-100%);
	}
	60%,
	100% {
		transform: translateY(250%);
	}
}

/* ------------------------------------------- cabecera de página interior */

/*
 * Banda BAJA a propósito. Da continuidad visual con la portada y con las
 * páginas de solución, pero sin competir con ellas: si fuese alta, cada página
 * interior parecería otra portada y el sitio perdería jerarquía.
 */
.cabecera-pagina {
	position: relative;
	display: flex;
	align-items: flex-end;
	min-height: clamp(9rem, 20vw, 14rem);
	padding-block: clamp(1.5rem, 4vw, 2.5rem);
	background: var(--hueso);
	overflow: hidden;
}

.cabecera-pagina--con-imagen {
	background: var(--negro);
	color: var(--blanco);
}

.cabecera-pagina__imagen {
	position: absolute;
	inset: 0;
}

.cabecera-pagina__imagen img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

/*
 * El velo aquí es MÁS denso que en el hero: la banda es baja y el título cae
 * sobre cualquier parte de la foto, así que no se puede contar con que haya
 * una zona tranquila donde apoyarlo.
 */
.cabecera-pagina__velo {
	position: absolute;
	inset: 0;
	background: linear-gradient(
		to top,
		rgb(16 16 16 / 88%),
		rgb(16 16 16 / 62%)
	);
}

.cabecera-pagina__interior {
	position: relative;
	width: 100%;
	text-align: center;
}

.cabecera-pagina__eyebrow {
	margin: 0 0 0.4rem;
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--rojo);
}

.cabecera-pagina__titulo {
	margin: 0;
	font-size: clamp(1.7rem, 4vw, 2.6rem);
}

.cabecera-pagina--con-imagen .cabecera-pagina__titulo {
	color: var(--blanco);
}

.hero__fondo {
	position: absolute;
	inset: 0;
	background-size: cover;
	background-position: center;
}

/*
 * Velo en degradado sobre la foto.
 *
 * Es lo que permite usar CUALQUIER fotografía de fondo —clara, oscura, con el
 * cielo blanco— sin que el titular deje de leerse. Más denso por la izquierda,
 * que es donde cae el texto, y más transparente por la derecha para que la
 * imagen siga viéndose.
 */
.hero__velo {
	position: absolute;
	inset: 0;
	background: linear-gradient(
			to right,
			rgb(16 16 16 / 88%),
			rgb(16 16 16 / 62%) 55%,
			rgb(16 16 16 / 35%)
		),
		linear-gradient(to top, rgb(16 16 16 / 55%), rgb(16 16 16 / 0%) 50%);
}

.hero__interior {
	position: relative;
	max-width: 46rem;
}

.hero__eyebrow {
	margin: 0 0 0.9rem;
	font-size: 0.82rem;
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--rojo);
}

/*
 * La marca roja delante de la línea superior ata visualmente el hero con el
 * resto de la identidad sin meter el logo por segunda vez.
 *
 * Hay cuatro variantes, todas dibujadas con degradados sobre un pseudoelemento:
 * ni imágenes ni iconos que descargar. Se cambia una clase en el hero y ya.
 */
.hero__eyebrow::before {
	content: "";
	display: inline-block;
	margin-inline-end: 0.75rem;
	vertical-align: middle;
	background: var(--rojo);
	width: 2rem;
	height: 2px;
}

/*
 * Boquilla depositando dos capas.
 *
 * Sustituye a la línea roja original, que era idéntica a la de Jorton.
 *
 * Se dibuja con dos piezas sobre un elemento vacío: el cuerpo de la boquilla y,
 * debajo, dos capas de material. Ni imagen ni tipografía de iconos.
 *
 * DECISIONES DE FORMA, que salieron de ir comparándolas en pantalla:
 *
 * - La punta va a la DERECHA y las capas salen hacia la izquierda: así se lee
 *   como una boquilla que ha avanzado dejando material detrás. Al revés parece
 *   que va a pasar por encima de lo ya depositado.
 * - DOS capas y no una: una sola dice «deposita», dos dicen «apila», que es de
 *   lo que va el oficio. Tres iguales, en cambio, son el icono de menú de
 *   hamburguesa.
 * - La de abajo sobresale por la derecha, para que se vea el escalón entre la
 *   capa terminada y la que se está depositando.
 * - Sin el tramo recto de la punta: a este tamaño no llegaba a distinguirse y
 *   la silueta queda más limpia sin él.
 * - La marca va elevada para que la capa de abajo caiga a la altura del centro
 *   del texto, que es donde iba la línea original.
 */
.hero__marca {
	position: relative;
	display: inline-block;
	/* La capa de abajo mide todo el ancho de la marca; la de arriba, 6 px menos.
	   Tocando solo este valor se alargan las dos manteniendo el escalón. */
	width: 2.5rem;
	height: 17px;
	margin-inline-end: 0.7rem;
	/* En positivo eleva la base del elemento sobre la línea de escritura: 0,25 em
	   es lo que separa esa base del centro óptico del texto. */
	vertical-align: 0.25em;
}

.hero__marca::before,
.hero__marca::after {
	content: "";
	position: absolute;
	background: var(--rojo);
}

/* El cuerpo: recto arriba y hombros que bajan hasta la base. */
.hero__marca::before {
	top: 0;
	right: 1px;
	width: 12px;
	height: 10px;
	clip-path: polygon(0 0, 100% 0, 100% 45%, 65% 100%, 35% 100%, 0 45%);
}

/*
 * Las dos capas, como dos fondos del MISMO pseudoelemento: solo hay dos
 * disponibles y el otro lo ocupa el cuerpo de la boquilla.
 */
.hero__marca::after {
	left: 0;
	right: 0;
	bottom: 0;
	height: 6px;
	background: linear-gradient(var(--rojo), var(--rojo)) left bottom / 100% 2px
			no-repeat,
		linear-gradient(var(--rojo), var(--rojo)) left top / calc(100% - 6px) 2px
			no-repeat;
}

/* El eyebrow que lleva la marca ya no pinta la línea. */
.hero__eyebrow--marca::before {
	content: none;
}

/* Marca de cota: la acotación de una medida en un plano. */
.hero__eyebrow--cota::before {
	width: 2rem;
	height: 10px;
	background: linear-gradient(var(--rojo), var(--rojo)) center / 100% 2px
		no-repeat;
	border-inline: 2px solid var(--rojo);
}

/* Cruz de referencia: la marca de registro de los planos. */
.hero__eyebrow--cruz::before {
	width: 14px;
	height: 14px;
	background: linear-gradient(var(--rojo), var(--rojo)) center / 2px 100%
			no-repeat,
		linear-gradient(var(--rojo), var(--rojo)) center / 100% 2px no-repeat;
}

/* Barra vertical: el mismo recurso que marca los destacados del sitio. */
.hero__eyebrow--barra::before {
	width: 3px;
	height: 1.1rem;
	margin-inline-end: 0.65rem;
}

.hero__titulo {
	margin: 0;
	font-size: clamp(2.1rem, 5.5vw, 3.6rem);
	color: var(--blanco);
}

.hero__texto {
	max-width: 40rem;
	margin: 1.1rem 0 0;
	font-size: clamp(1rem, 1.6vw, 1.15rem);
	color: rgb(255 255 255 / 86%);
}

.hero__acciones {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	margin: 2rem 0 0;
}

/* --------------------------------------------------------------- bandas */

.banda {
	padding-block: clamp(3rem, 7vw, 5.5rem);
}

.banda--clara {
	background: var(--blanco);
}

.banda--clara + .banda--clara {
	padding-top: 0;
}

.banda--oscura {
	background: var(--negro);
	color: rgb(255 255 255 / 84%);
}

.banda--oscura .banda__titulo {
	color: var(--blanco);
}

/*
 * Cabecera de banda a dos columnas cuando lleva entradilla.
 *
 * Con el título arriba y la entradilla debajo limitada a una medida de lectura,
 * quedaba media banda vacía a la derecha. Repartiéndolos en dos columnas se
 * ocupa el ancho completo Y el texto conserva una línea legible, que es lo que
 * de verdad importa: un párrafo a 1200 px de ancho no hay quien lo siga.
 */
.banda__cabecera {
	margin-bottom: clamp(1.75rem, 4vw, 2.75rem);
}

@media (min-width: 60rem) {
	.banda__cabecera:has(.banda__entradilla) {
		display: grid;
		grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
		gap: clamp(2rem, 5vw, 4rem);
		align-items: start;
	}

	.banda__cabecera:has(.banda__entradilla) .banda__titulo {
		margin-bottom: 0;
	}
}

.banda__cabecera--con-enlace {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
}

.banda__titulo {
	margin: 0;
}

.banda__entradilla {
	max-width: 78ch;
	margin: 0.6rem 0 0;
	font-size: 1.05rem;
}

.banda__enlace {
	font-weight: 600;
	font-size: 0.95rem;
}

/* ---------------------------------------------------------- soluciones */

/*
 * Tres columnas, no cuatro.
 *
 * Con cinco soluciones, una rejilla de cuatro deja la quinta sola en su fila;
 * con tres quedan 3 + 2, que se lee mucho mejor. Además caben descripciones
 * más largas sin que la ficha se estire.
 */
.soluciones {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
	gap: clamp(1.5rem, 3vw, 2.5rem);
}

/* ------------------------------------------------------------- citas */

/*
 * La cita destacada rompe el bloque de texto y da un punto de apoyo visual en
 * una página que, si no, sería un muro de párrafos.
 */
.prosa .wp-block-pullquote {
	margin-block: 2.5rem;
	padding: 0;
	border: 0;
	border-left: 4px solid var(--rojo);
	padding-left: clamp(1.25rem, 3vw, 2rem);
	text-align: left;
}

.prosa .wp-block-pullquote blockquote {
	margin: 0;
	padding: 0;
	border: 0;
}

.prosa .wp-block-pullquote p {
	margin: 0;
	font-size: clamp(1.3rem, 3vw, 1.75rem);
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -0.02em;
	color: var(--negro);
	text-wrap: balance;
}

.prosa blockquote:not(.wp-block-pullquote blockquote) {
	margin-block: 1.75rem;
	padding-left: 1.25rem;
	border-left: 3px solid var(--borde);
	color: var(--grafito);
	font-style: italic;
}

.prosa ul,
.prosa ol {
	padding-left: 1.25rem;
}

.prosa li + li {
	margin-top: 0.6rem;
}

/* --------------------------------------------------- tablas de contenido */

.prosa table {
	width: 100%;
	border-collapse: collapse;
	margin-block: 1.5rem;
	font-size: 0.95rem;
}

.prosa th,
.prosa td {
	padding: 0.7rem 0.9rem;
	text-align: start;
	vertical-align: top;
	border-bottom: 1px solid var(--borde);
}

.prosa thead th {
	background: var(--hueso);
	font-size: 0.8rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--grafito);
}

.prosa tbody th,
.prosa td:first-child {
	font-weight: 600;
	white-space: nowrap;
}

/* Las tablas anchas se desplazan dentro de su caja, nunca la página entera. */
.prosa .wp-block-table {
	overflow-x: auto;
}

.solucion {
	position: relative;
	display: flex;
	flex-direction: column;
	background: var(--hueso);
	border: 1px solid var(--borde);
	border-top: 3px solid var(--negro);
	border-radius: 3px;
	overflow: hidden;
	transition: border-color var(--transicion), box-shadow var(--transicion),
		transform var(--transicion);
}

.solucion:hover {
	border-top-color: var(--rojo);
	box-shadow: 0 12px 28px rgb(26 26 26 / 10%);
	transform: translateY(-3px);
}

.solucion__imagen {
	display: block;
	aspect-ratio: 16 / 10;
	overflow: hidden;
	background: var(--borde);
}

.solucion__imagen img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 500ms ease;
}

.solucion:hover .solucion__imagen img {
	transform: scale(1.05);
}

.solucion__cuerpo {
	display: flex;
	flex-direction: column;
	flex-grow: 1;
	padding: 1.5rem;
}

.solucion__titulo {
	font-size: 1.12rem;
	margin-bottom: 0.5rem;
}

.solucion__titulo a {
	color: var(--negro);
	text-decoration: none;
}

/*
 * Enlace estirado: el <a> del título cubre toda la ficha, así que se puede
 * pinchar en cualquier punto. Sigue habiendo un único enlace real, que es lo
 * que conviene para el teclado y para los lectores de pantalla.
 */
.solucion__titulo a::after {
	content: "";
	position: absolute;
	inset: 0;
}

.solucion:hover .solucion__titulo a {
	color: var(--rojo);
}

.solucion__texto {
	font-size: 0.95rem;
	color: var(--grafito);
	margin-bottom: 1rem;
}

/* Empuja el "ver proyectos" al fondo para que todas las fichas casen abajo. */
.solucion__enlace {
	margin: auto 0 0;
	font-size: 0.88rem;
	font-weight: 600;
	color: var(--rojo);
}

.solucion__enlace::after {
	content: " →";
}

/* -------------------------------------------------------------- pasos */

/*
 * Dos columnas en pantalla ancha, no cuatro.
 *
 * Los textos de los pasos son largos a propósito —explican el método, que es
 * lo que separa a un proveedor de un aficionado— y en cuatro columnas
 * quedarían en tiras estrechas e ilegibles.
 */
.pasos {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr));
	gap: clamp(1.75rem, 4vw, 3rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

.paso {
	padding-top: 1.25rem;
	border-top: 1px solid rgb(255 255 255 / 22%);
}

.paso__numero {
	display: block;
	font-size: 0.85rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	color: var(--rojo);
	margin-bottom: 0.6rem;
}

.paso__titulo {
	font-size: 1.1rem;
	color: var(--blanco);
	margin-bottom: 0.4rem;
}

.paso__texto {
	margin: 0;
	font-size: 0.95rem;
}

/* ---------------------------------------------------------- materiales */

/*
 * Flexbox y no rejilla, para poder centrar la última fila.
 *
 * Son cinco materiales —los que de verdad se han trabajado— así que en tres
 * columnas la última fila lleva dos y con una rejilla quedaban descolgadas a la
 * izquierda. Con flex y justify-content: center se colocan en el medio y la
 * fila corta parece deliberada.
 *
 * El flex-grow va a 0 a propósito: si creciera, esas dos últimas fichas se
 * repartirían todo el ancho y saldrían más grandes que las de arriba.
 */
.materiales {
	--hueco-materiales: clamp(1rem, 2.5vw, 1.75rem);
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--hueco-materiales);
}

.material {
	flex: 0 1 100%;
}

@media (min-width: 40rem) {
	.material {
		flex-basis: calc((100% - var(--hueco-materiales)) / 2);
	}
}

@media (min-width: 62rem) {
	.material {
		flex-basis: calc((100% - 2 * var(--hueco-materiales)) / 3);
	}
}

.material {
	display: flex;
	flex-direction: column;
	padding: 1.5rem;
	background: var(--hueso);
	border: 1px solid var(--borde);
	border-radius: 6px;
	transition: border-color var(--transicion), box-shadow var(--transicion);
}

.material:hover {
	border-color: var(--rojo);
	box-shadow: 0 10px 24px rgb(26 26 26 / 8%);
}

/*
 * El nombre del material es el dato que se busca al ojear la página, así que
 * va grande y en rojo: se localiza de un vistazo sin tener que leer la ficha.
 */
.material__nombre {
	margin: 0;
	font-size: 1.5rem;
	color: var(--rojo);
}

.material__resumen {
	margin: 0.1rem 0 0.9rem;
	font-size: 0.82rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--gris);
}

.material__aporta {
	margin: 0 0 1rem;
	font-size: 0.95rem;
	color: var(--grafito);
}

/* Empuja el "cuándo conviene" al fondo para que todas las fichas casen abajo. */
.material__cuando {
	margin: auto 0 0;
	padding-top: 0.9rem;
	border-top: 1px solid var(--borde);
	font-size: 0.9rem;
}

.material__etiqueta {
	display: block;
	margin-bottom: 0.2rem;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--gris);
}

/* Aclara que la lista de arriba es la habitual, no todo lo que se puede hacer. */
.materiales__nota {
	max-width: 70ch;
	/* 'auto' a los lados: el bloque va centrado, como el resto del sitio. */
	margin: clamp(1.5rem, 3vw, 2rem) auto 0;
	padding-left: 1.1rem;
	border-left: 3px solid var(--rojo);
	font-size: 0.97rem;
	color: var(--grafito);
}

/* --------------------------------------------------------- tecnologías */

.tecnologias {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
	gap: clamp(2rem, 4vw, 3.5rem);
}

.tecnologia {
	padding-top: 1.25rem;
	border-top: 3px solid var(--rojo);
}

.tecnologia__titulo {
	font-size: 1.25rem;
	color: var(--blanco);
	margin-bottom: 0.6rem;
}

.tecnologia p {
	font-size: 0.97rem;
}

.tecnologia p:last-child {
	margin-bottom: 0;
}

/* ------------------------------------------------------ banda de imagen */

/*
 * Respiro visual entre dos bloques de texto. Altura contenida: es una pausa,
 * no una sección con contenido propio.
 */
.banda-imagen {
	margin: 0;
	height: clamp(12rem, 30vw, 22rem);
	overflow: hidden;
	background: var(--hueso);
}

.banda-imagen img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

/* --------------------------------------------------------- destacado */

.destacado {
	display: grid;
	grid-template-columns: minmax(0, 15rem) minmax(0, 1fr);
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: start;
	padding: clamp(1.75rem, 4vw, 2.75rem);
	background: var(--hueso);
	border-inline-start: 4px solid var(--rojo);
	border-radius: 0 6px 6px 0;
}

/*
 * Variante sin cifra: una sola columna.
 *
 * El bloque normal reserva 15rem para el número de la izquierda. Sin
 * cifra que poner, esa columna quedaría vacía y el texto arrancando a
 * media caja.
 */
.destacado--simple {
	grid-template-columns: minmax(0, 1fr);
	max-width: var(--ancho-texto);
	margin-inline: auto;
}

.destacado__cifra {
	font-size: clamp(2rem, 5vw, 3.25rem);
	font-weight: 800;
	line-height: 1;
	letter-spacing: -0.03em;
	color: var(--rojo);
}

.destacado__titulo {
	margin-top: 0;
	font-size: clamp(1.3rem, 3vw, 1.75rem);
}

.destacado__cuerpo p:last-child {
	margin-bottom: 0;
}

@media (max-width: 48rem) {
	.destacado {
		grid-template-columns: 1fr;
	}
}

/* --------------------------------------------------------- capacidades */

.capacidades {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
	gap: clamp(1.5rem, 3vw, 2.5rem);
	margin: 0;
}

.capacidad {
	padding-inline-start: 1.1rem;
	border-inline-start: 3px solid var(--rojo);
}

.capacidad__clave {
	font-size: 0.8rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: rgb(255 255 255 / 55%);
	margin-bottom: 0.35rem;
}

.capacidad__valor {
	margin: 0;
	font-size: 1.05rem;
	font-weight: 600;
	color: var(--blanco);
}

/* ------------------------------------------------------- franja de CTA */

.franja-cta {
	padding-block: clamp(2.5rem, 5vw, 3.5rem);
	background: var(--rojo);
	color: var(--blanco);
}

.franja-cta__interior {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
}

.franja-cta__titulo {
	margin: 0;
	font-size: clamp(1.35rem, 3vw, 1.9rem);
	color: var(--blanco);
}

.franja-cta__texto {
	max-width: 66ch;
	margin: 0.5rem 0 0;
	color: rgb(255 255 255 / 92%);
}

.franja-cta__accion {
	margin: 0;
	flex-shrink: 0;
}

.franja-cta__texto-bloque {
	max-width: 40rem;
}

.franja-cta__datos {
	display: flex;
	flex-wrap: wrap;
	gap: 0 2rem;
	margin-top: 1rem;
}

.franja-cta__datos .dato {
	border-top: 0;
	padding-block: 0.35rem;
}

.franja-cta__acciones {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	flex-shrink: 0;
}

.pie__wa {
	margin-top: 0.9rem;
}

.pie__enlace-wa {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-weight: 600;
	text-decoration: none;
}

.pie__enlace-wa:hover {
	color: var(--rojo);
}

/*
 * El botón sobre el rojo se invierte: rojo sobre rojo sería invisible.
 */
.franja-cta .boton--principal {
	background: var(--blanco);
	border-color: var(--blanco);
	color: var(--rojo);
}

.franja-cta .boton--principal:hover {
	background: var(--negro);
	border-color: var(--negro);
	color: var(--blanco);
}

/* El pie va justo después de la franja roja: sin hueco entre ambos. */
.franja-cta + .pie {
	margin-top: 0;
}

/* -------------------------------------------------------------- cabecera */

.cabecera {
	position: sticky;
	top: 0;
	z-index: 50;
	background: var(--blanco);
	border-bottom: 1px solid var(--borde);
}

.cabecera__interior {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	min-height: 4.5rem;
}

.cabecera__nombre {
	font-size: 1.35rem;
	font-weight: 800;
	letter-spacing: -0.03em;
	color: var(--negro);
	text-decoration: none;
}

/*
 * El logo es muy apaisado (1062x256, casi 4:1). Se limita por ALTURA y se deja
 * el ancho automático: así conserva su proporción y no invade el menú por muy
 * ancho que sea el archivo que se suba el día de mañana.
 */
.cabecera__marca {
	display: flex;
	align-items: center;
	flex-shrink: 0;
}

.custom-logo-link {
	display: block;
	line-height: 0;
}

.custom-logo {
	width: auto;
	height: auto;
	max-height: 2.5rem;
	max-width: min(14rem, 45vw);
	object-fit: contain;
}

.cabecera__nav {
	display: flex;
	align-items: center;
	gap: 2rem;
}

.cabecera__nav .menu {
	display: flex;
	align-items: center;
	gap: 1.75rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.cabecera__nav .menu a {
	color: var(--negro);
	text-decoration: none;
	font-weight: 500;
	font-size: 0.98rem;
}

.cabecera__nav .menu a:hover,
.cabecera__nav .menu .current-menu-item > a {
	color: var(--rojo);
}

/*
 * Selector de idioma. Dos códigos de dos letras separados por una barra fina:
 * ocupa poco y no compite con el menú, que es lo que tiene que leerse primero.
 * El nombre completo del idioma va oculto, para quien navegue con lector.
 */
.idiomas__lista {
	display: flex;
	align-items: center;
	list-style: none;
	margin: 0;
	padding: 0;
}

.idiomas__elemento + .idiomas__elemento {
	margin-inline-start: 0.55rem;
	padding-inline-start: 0.55rem;
	border-inline-start: 1px solid var(--borde);
}

.idiomas__actual,
.idiomas__enlace {
	font-size: 0.78rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-decoration: none;
}

.idiomas__actual {
	color: var(--negro);
}

.idiomas__enlace {
	color: var(--gris);
}

.idiomas__enlace:hover,
.idiomas__enlace:focus-visible {
	color: var(--rojo);
}

.cabecera__boton {
	display: none;
	width: 2.75rem;
	height: 2.75rem;
	padding: 0;
	background: none;
	border: 1px solid var(--borde);
	border-radius: 6px;
	cursor: pointer;
}

.cabecera__boton-barras,
.cabecera__boton-barras::before,
.cabecera__boton-barras::after {
	display: block;
	width: 1.15rem;
	height: 2px;
	margin-inline: auto;
	background: var(--negro);
	transition: transform var(--transicion), opacity var(--transicion);
}

.cabecera__boton-barras::before,
.cabecera__boton-barras::after {
	content: "";
	position: relative;
}

.cabecera__boton-barras::before {
	top: -6px;
}

.cabecera__boton-barras::after {
	top: 4px;
}

.cabecera__boton[aria-expanded="true"] .cabecera__boton-barras {
	background: transparent;
}

.cabecera__boton[aria-expanded="true"] .cabecera__boton-barras::before {
	transform: translateY(6px) rotate(45deg);
}

.cabecera__boton[aria-expanded="true"] .cabecera__boton-barras::after {
	transform: translateY(-4px) rotate(-45deg);
}

.cabecera__aviso {
	margin: 0;
	font-size: 0.85rem;
}

/* ------------------------------------------------------------- submenús */

.cabecera__nav .menu li {
	position: relative;
}

.cabecera__nav .menu .sub-menu {
	position: absolute;
	top: 100%;
	left: -1rem;
	z-index: 20;
	min-width: 15rem;
	margin: 0;
	padding: 0.5rem 0;
	list-style: none;
	background: var(--blanco);
	border: 1px solid var(--borde);
	border-radius: 3px;
	box-shadow: 0 14px 30px rgb(26 26 26 / 12%);
	/*
	 * Oculto con visibility + opacity en lugar de display:none para que la
	 * transición funcione y para que el submenú siga siendo alcanzable por el
	 * teclado en el momento en que el padre recibe el foco.
	 */
	opacity: 0;
	visibility: hidden;
	transform: translateY(-0.4rem);
	transition: opacity var(--transicion), transform var(--transicion),
		visibility var(--transicion);
}

.cabecera__nav .menu li:hover > .sub-menu,
.cabecera__nav .menu li:focus-within > .sub-menu {
	opacity: 1;
	visibility: visible;
	transform: none;
}

.cabecera__nav .menu .sub-menu a {
	display: block;
	padding: 0.5rem 1rem;
	font-size: 0.93rem;
}

.cabecera__nav .menu .sub-menu a:hover {
	background: var(--hueso);
}

/* La flechita del padre solo cuando de verdad tiene hijos. */
.cabecera__nav .menu .menu-item-has-children > a::after {
	content: "";
	display: inline-block;
	width: 0.4rem;
	height: 0.4rem;
	margin-inline-start: 0.4rem;
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: translateY(-0.15em) rotate(45deg);
}

/* --------------------------------------------------------- animaciones */

/*
 * El estado oculto SOLO se aplica si hay JavaScript (clase .con-js, puesta en
 * el <head> antes del primer pintado). Sin JS no hay animación pero tampoco
 * hay contenido invisible, que es el fallo clásico de este patrón.
 */
.con-js .revelar,
.con-js .revelar-grupo > * {
	opacity: 0;
	transform: translateY(1.5rem);
}

.con-js .revelar.es-visible,
.con-js .revelar-grupo > .es-visible {
	opacity: 1;
	transform: none;
	transition: opacity 700ms cubic-bezier(0.22, 0.61, 0.36, 1),
		transform 700ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ---------------------------------------------------------------- página */

.pagina__cabecera {
	margin-bottom: 2.5rem;
}

.pagina__titulo {
	margin-bottom: 0.3em;
}

.pagina__imagen {
	margin: 0 0 2.5rem;
}

/*
 * Separación arriba Y abajo.
 *
 * Solo tenía padding inferior, así que en las páginas que usan esta plantilla
 * —«El taller», entre otras— el primer párrafo quedaba pegado al borde de la
 * banda de cabecera.
 */
.pagina__contenido {
	padding-block: clamp(2.25rem, 4.5vw, 3.25rem) clamp(2.5rem, 5vw, 4rem);
}

/* -------------------------------------------------------------- proyecto */

.proyecto__cabecera {
	position: relative;
	margin-bottom: clamp(2rem, 5vw, 3.5rem);
}

/*
 * Altura DEFINIDA, no aspect-ratio.
 *
 * Antes esto era `aspect-ratio: 2/1` + `max-height: 60vh`, y la imagen salía
 * pegada a la izquierda con una banda gris a la derecha: al toparse la altura
 * con el max-height, la del contenedor deja de ser definida y el `height: 100%`
 * del hijo no tiene contra qué resolverse. Con una altura concreta el problema
 * desaparece, y clamp() la mantiene proporcionada en cualquier pantalla.
 */
.proyecto__imagen {
	position: relative;
	width: 100%;
	height: clamp(16rem, 42vw, 32rem);
	overflow: hidden;
	background: var(--hueso);
}

/*
 * Posicionada en absoluto contra el contenedor: llena el hueco exacto sea cual
 * sea el tamaño real del archivo, sin depender de cómo resuelvan los
 * porcentajes ni de si otra hoja de estilos le mete `height: auto`.
 *
 * object-position se puede afinar por proyecto si alguna pieza queda mal
 * encuadrada al recortar.
 */
.proyecto__imagen img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

/*
 * El titular se superpone a la imagen con un degradado por debajo: así el
 * texto se lee sobre cualquier foto, clara u oscura, sin depender de que la
 * imagen tenga una zona tranquila donde caiga el título.
 */
.tiene-cabecera .proyecto__titular {
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	padding-block: clamp(2rem, 6vw, 4rem) clamp(1.25rem, 3vw, 2rem);
	background: linear-gradient(
		to top,
		rgb(0 0 0 / 82%),
		rgb(0 0 0 / 45%) 45%,
		rgb(0 0 0 / 0%)
	);
	color: var(--blanco);
}

.tiene-cabecera .proyecto__titulo,
.tiene-cabecera .proyecto__categoria a {
	color: var(--blanco);
}

.proyecto__titular {
	padding-top: 2rem;
}

.proyecto__categoria {
	margin: 0 0 0.4rem;
	font-size: 0.85rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.proyecto__categoria a {
	color: var(--rojo);
	text-decoration: none;
}

.proyecto__titulo {
	margin: 0;
}

.proyecto__resultado {
	max-width: 58ch;
	margin: 0.75rem 0 0;
	font-size: clamp(1rem, 2vw, 1.2rem);
	font-weight: 500;
}

.proyecto__cuerpo {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 20rem;
	gap: clamp(2rem, 5vw, 4rem);
	align-items: start;
	margin-bottom: clamp(2.5rem, 6vw, 4rem);
}

.caso + .caso {
	margin-top: 2rem;
}

.caso__titulo {
	font-size: 0.85rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--rojo);
	margin-bottom: 0.6rem;
}

.proyecto__ficha {
	position: sticky;
	top: 6rem;
	padding: 1.75rem;
	background: var(--hueso);
	border: 1px solid var(--borde);
	border-radius: 3px;
}

.proyecto__ficha-titulo {
	font-size: 0.85rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--gris);
	margin-bottom: 1rem;
}

.ficha {
	margin: 0 0 1.5rem;
}

.ficha__fila {
	display: flex;
	justify-content: space-between;
	gap: 1rem;
	padding-block: 0.6rem;
	border-top: 1px solid var(--borde);
}

.ficha__clave {
	font-size: 0.9rem;
	color: var(--gris);
}

.ficha__valor {
	margin: 0;
	font-size: 0.9rem;
	font-weight: 600;
	text-align: right;
}

.ficha__cta {
	display: block;
	text-align: center;
}

.proyecto__galeria {
	padding-bottom: clamp(2.5rem, 6vw, 4rem);
}

.proyecto__navegacion {
	display: flex;
	justify-content: space-between;
	gap: 1.5rem;
	padding-block: 2rem;
	border-top: 1px solid var(--borde);
}

.proyecto__salto {
	max-width: 22rem;
	text-decoration: none;
	color: var(--negro);
}

.proyecto__salto--siguiente {
	margin-inline-start: auto;
	text-align: right;
}

.proyecto__salto-etiqueta {
	display: block;
	font-size: 0.78rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--gris);
}

.proyecto__salto-titulo {
	font-weight: 600;
}

.proyecto__salto:hover .proyecto__salto-titulo {
	color: var(--rojo);
}

/* ------------------------------------------------- listado de proyectos */

.filtros {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-bottom: 2.5rem;
}

.filtros__opcion {
	padding: 0.45rem 1rem;
	border: 1px solid var(--borde);
	border-radius: 100px;
	font-size: 0.9rem;
	color: var(--grafito);
	text-decoration: none;
	transition: background var(--transicion), color var(--transicion),
		border-color var(--transicion);
}

.filtros__opcion:hover {
	border-color: var(--negro);
	color: var(--negro);
}

.filtros__opcion.es-actual {
	background: var(--negro);
	border-color: var(--negro);
	color: var(--blanco);
}

/*
 * Columnas EXPLÍCITAS, no auto-fill.
 *
 * Con auto-fill el número de columnas depende del ancho y no se puede saber
 * desde CSS, así que tampoco se puede detectar cuándo la última fila se queda
 * con una sola tarjeta. Fijándolas, sí.
 */
.rejilla-proyectos {
	display: grid;
	grid-template-columns: 1fr;
	gap: clamp(1.25rem, 3vw, 2rem);
}

@media (min-width: 40rem) {
	.rejilla-proyectos {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 62rem) {
	.rejilla-proyectos {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	/*
	 * Tarjeta huérfana.
	 *
	 * Si la última tarjeta cae en la primera columna, es que se ha quedado sola
	 * en su fila. Se lleva al centro: pegada a la izquierda con dos huecos
	 * vacíos a la derecha parece que falta algo por cargar.
	 */
	.rejilla-proyectos > :last-child:nth-child(3n + 1) {
		grid-column: 2;
	}
}

.proyecto-tarjeta__enlace {
	display: block;
	color: inherit;
	text-decoration: none;
}

.proyecto-tarjeta__imagen {
	aspect-ratio: 4 / 3;
	overflow: hidden;
	background: var(--hueso);
}

.proyecto-tarjeta__imagen img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 400ms ease;
}

.proyecto-tarjeta__enlace:hover .proyecto-tarjeta__imagen img {
	transform: scale(1.04);
}

.proyecto-tarjeta__titulo {
	font-size: 1.15rem;
	margin: 0.9rem 0 0.35rem;
}

.proyecto-tarjeta__enlace:hover .proyecto-tarjeta__titulo {
	color: var(--rojo);
}

.proyecto-tarjeta__texto {
	margin: 0;
	font-size: 0.95rem;
	color: var(--grafito);
}

.lista-entradas {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
	gap: 2rem;
}

/* ------------------------------------------------------------ paginación */

.pagination {
	margin-top: clamp(2.5rem, 6vw, 4rem);
	padding-top: clamp(1.5rem, 4vw, 2.5rem);
	border-top: 1px solid var(--borde);
}

.pagination .nav-links {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
}

/*
 * Cada número es un objetivo cuadrado de 2,75 rem: es el tamaño mínimo que se
 * acierta con el dedo sin ampliar, y da igual que el número sea «1» o «12».
 */
.pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 2.75rem;
	height: 2.75rem;
	padding-inline: 0.75rem;
	border: 1px solid var(--borde);
	border-radius: 6px;
	font-size: 0.95rem;
	font-weight: 600;
	color: var(--negro);
	text-decoration: none;
	transition: background var(--transicion), border-color var(--transicion),
		color var(--transicion);
}

.pagination a.page-numbers:hover {
	border-color: var(--negro);
	background: var(--hueso);
	color: var(--negro);
}

/* La página actual no es un enlace: se marca en negro y sin borde. */
.pagination .page-numbers.current {
	background: var(--negro);
	border-color: var(--negro);
	color: var(--blanco);
}

/* Los puntos suspensivos no son un botón: ni borde ni caja. */
.pagination .page-numbers.dots {
	min-width: 1.5rem;
	padding-inline: 0;
	border-color: transparent;
	color: var(--gris);
}

/*
 * Anterior y siguiente llevan su flecha y algo más de aire. Se separan del
 * grupo de números para que se lean como lo que son: el movimiento principal.
 */
.pagination .prev,
.pagination .next {
	padding-inline: 1.1rem;
	border-color: var(--negro);
}

.pagination .prev:hover,
.pagination .next:hover {
	background: var(--negro);
	color: var(--blanco);
}

.pagination .prev {
	margin-inline-end: 0.4rem;
}

.pagination .next {
	margin-inline-start: 0.4rem;
}

.pagination .prev::before {
	content: "←";
	margin-inline-end: 0.45rem;
}

.pagination .next::after {
	content: "→";
	margin-inline-start: 0.45rem;
}

@media (max-width: 30rem) {
	/* En pantalla estrecha el texto sobra: la flecha se entiende sola. */
	.pagination .prev,
	.pagination .next {
		padding-inline: 0;
		font-size: 0;
	}

	.pagination .prev::before,
	.pagination .next::after {
		margin: 0;
		font-size: 1.1rem;
	}
}

/* --------------------------------------------------- galería justificada */

/*
 * El truco entero está aquí, y no hay JavaScript detrás.
 *
 * Cada elemento recibe desde PHP su relación de aspecto en --r. Al hacer que
 * TANTO flex-grow COMO flex-basis sean proporcionales a --r, el ancho final de
 * cada imagen también lo es. Y si el ancho es proporcional a la proporción,
 * la altura resultante (ancho / r) es la MISMA para todas las de la fila:
 * eso es exactamente una galería justificada.
 *
 * --fila es solo la altura orientativa de partida; flexbox la ajusta al
 * justificar cada fila al ancho disponible.
 */
/*
 * --fila es la altura de fila de partida. Cuanto más baja, más fotos entran
 * por fila y más pequeñas salen. A 240 px las imágenes salían demasiado
 * grandes: una galería es para ojear, y para eso conviene ver muchas a la vez
 * y ampliar en el lightbox la que interese.
 */
.galeria {
	display: flex;
	flex-wrap: wrap;
	gap: var(--hueco);
	--fila: 175px;
}

.galeria__item {
	position: relative;
	flex-grow: var(--r);
	flex-basis: calc(var(--r) * var(--fila));
	overflow: hidden;
	background: var(--hueso);
	cursor: zoom-in;
}

.galeria__img {
	width: 100%;
	height: 100%;
	aspect-ratio: var(--r);
	object-fit: cover;
	transition: transform 400ms ease, opacity var(--transicion);
}

.galeria__item::after {
	content: "";
	position: absolute;
	inset: 0;
	background: rgb(26 26 26 / 0%);
	transition: background var(--transicion);
}

.galeria__item:hover .galeria__img {
	transform: scale(1.03);
}

.galeria__item:hover::after {
	background: rgb(26 26 26 / 18%);
}

/*
 * Relleno de la última fila.
 *
 * Sin él, las imágenes de la última fila se estirarían para ocupar todo el
 * ancho y quedarían desproporcionadas frente al resto. Este elemento vacío
 * tiene un flex-grow enorme, así que absorbe todo el espacio sobrante.
 */
.galeria__relleno {
	flex-grow: 999999;
	flex-basis: 0;
	height: 0;
}

/* -------------------------------------------------------------- lightbox */

.lightbox {
	width: 100vw;
	max-width: 100vw;
	height: 100dvh;
	max-height: 100dvh;
	padding: 0;
	border: 0;
	background: rgb(12 12 12 / 96%);
	color: var(--blanco);
	overflow: hidden;
}

.lightbox::backdrop {
	background: rgb(12 12 12 / 90%);
}

.lightbox__figura {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	height: 100%;
	margin: 0;
	padding: clamp(1rem, 4vw, 3rem);
}

.lightbox__img {
	max-width: 100%;
	max-height: calc(100dvh - 8rem);
	width: auto;
	height: auto;
	object-fit: contain;
}

.lightbox__pie {
	max-width: 60ch;
	margin-top: 1rem;
	font-size: 0.9rem;
	color: rgb(255 255 255 / 78%);
	text-align: center;
}

.lightbox__pie:empty {
	display: none;
}

.lightbox__contador {
	position: absolute;
	bottom: 1rem;
	left: 50%;
	transform: translateX(-50%);
	margin: 0;
	font-size: 0.85rem;
	color: rgb(255 255 255 / 65%);
}

.lightbox__cerrar,
.lightbox__nav {
	position: absolute;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgb(255 255 255 / 8%);
	border: 0;
	color: var(--blanco);
	cursor: pointer;
	transition: background var(--transicion);
}

.lightbox__cerrar:hover,
.lightbox__nav:hover {
	background: rgb(255 255 255 / 20%);
}

.lightbox__cerrar {
	top: 1rem;
	right: 1rem;
	width: 2.75rem;
	height: 2.75rem;
	font-size: 1.8rem;
	line-height: 1;
	border-radius: 50%;
}

.lightbox__nav {
	top: 50%;
	transform: translateY(-50%);
	width: 3.25rem;
	height: 3.25rem;
	font-size: 2.4rem;
	line-height: 1;
	border-radius: 50%;
}

.lightbox__nav--anterior {
	left: 1rem;
}

.lightbox__nav--siguiente {
	right: 1rem;
}

.lightbox__nav[hidden] {
	display: none;
}

/* ------------------------------------------ cabecera de una solución */

.solucion-cabecera {
	position: relative;
	padding-block: clamp(2.5rem, 6vw, 4.5rem);
	background: var(--hueso);
	overflow: hidden;
}

.solucion-cabecera--con-imagen {
	background: var(--negro);
	color: var(--blanco);
}

.solucion-cabecera__imagen {
	position: absolute;
	inset: 0;
}

.solucion-cabecera__imagen img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.solucion-cabecera__velo {
	position: absolute;
	inset: 0;
	background: linear-gradient(
		to top,
		rgb(16 16 16 / 88%),
		rgb(16 16 16 / 68%)
	);
}

.solucion-cabecera__interior {
	position: relative;
	max-width: 48rem;
	margin-inline: auto;
	text-align: center;
}

.solucion-cabecera__eyebrow {
	margin: 0 0 0.6rem;
	font-size: 0.8rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.solucion-cabecera__eyebrow a {
	color: var(--rojo);
	text-decoration: none;
}

.solucion-cabecera--con-imagen .solucion-cabecera__titulo {
	color: var(--blanco);
}

.solucion-cabecera__titulo {
	margin: 0;
}

.solucion-cabecera__texto {
	margin-top: 0.9rem;
	font-size: 1.05rem;
}

.solucion-cabecera--con-imagen .solucion-cabecera__texto {
	color: rgb(255 255 255 / 88%);
}

.otras-soluciones {
	margin-top: clamp(3rem, 7vw, 5rem);
	padding-top: clamp(2rem, 4vw, 3rem);
	border-top: 1px solid var(--borde);
}

/* -------------------------------------------------------------- avisos */

.aviso {
	max-width: 44rem;
	padding: 1.5rem 1.75rem;
	border-radius: 3px;
	border-inline-start: 4px solid;
}

.aviso__titulo {
	font-size: 1.2rem;
	margin-bottom: 0.4rem;
}

.aviso p:last-child {
	margin-bottom: 0;
}

/* El acento es el rojo de la marca, también en el aviso de éxito: el verde de
   "correcto" no pinta nada en una paleta que no lo tiene. */
.aviso--exito {
	background: var(--hueso);
	border-color: var(--rojo);
}

.aviso--error {
	margin-bottom: 2rem;
	background: #fdf1f0;
	border-color: var(--rojo);
}

/* --------------------------------------------------------- formulario */

.formulario {
	max-width: 46rem;
}

.formulario__rejilla {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1.25rem;
}

.campo--completo {
	grid-column: 1 / -1;
}

.campo__etiqueta {
	display: block;
	margin-bottom: 0.35rem;
	font-size: 0.9rem;
	font-weight: 600;
}

.campo__requerido {
	color: var(--rojo);
}

.campo__control {
	width: 100%;
	padding: 0.7rem 0.85rem;
	font: inherit;
	font-size: 1rem;
	color: var(--negro);
	background: var(--blanco);
	border: 1px solid var(--borde);
	border-radius: 3px;
	transition: border-color var(--transicion), box-shadow var(--transicion);
}

.campo__control:focus {
	outline: none;
	border-color: var(--negro);
	box-shadow: 0 0 0 3px rgb(226 52 43 / 18%);
}

textarea.campo__control {
	resize: vertical;
	min-height: 9rem;
}

.tiene-error .campo__control {
	border-color: var(--rojo);
}

.campo__error {
	margin: 0.35rem 0 0;
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--rojo);
}

.campo--consentimiento {
	margin-top: 1.25rem;
}

.consentimiento {
	display: flex;
	align-items: flex-start;
	gap: 0.6rem;
	font-size: 0.9rem;
	color: var(--grafito);
	cursor: pointer;
}

.consentimiento input {
	flex-shrink: 0;
	margin-top: 0.25rem;
	width: 1.05rem;
	height: 1.05rem;
	accent-color: var(--rojo);
}

.formulario__acciones {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem;
	margin-top: 1.75rem;
}

.formulario__nota {
	font-size: 0.85rem;
	color: var(--gris);
}

/*
 * La trampa para bots.
 *
 * Se saca de la pantalla en lugar de usar display:none, porque hay bots que ya
 * detectan y evitan los campos ocultos con display. Para el teclado y los
 * lectores de pantalla queda fuera de alcance por tabindex y aria-hidden, no
 * por CSS.
 */
.trampa {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* --------------------------------------------------- datos de contacto */

.dato {
	padding-block: 0.6rem;
	border-top: 1px solid var(--borde);
}

/*
 * Iconos en SVG en línea.
 *
 * Heredan el color del texto (fill: currentColor) y se alinean con él, así que
 * no hace falta ajustarlos en cada sitio donde se usan.
 */
.icono {
	display: inline-block;
	width: 1.35em;
	height: 1.35em;
	margin-inline-end: 0.45em;
	vertical-align: -0.3em;
	flex-shrink: 0;
}

.dato__etiqueta {
	display: block;
	margin-bottom: 0.15rem;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--gris);
}

.dato__etiqueta .icono {
	color: var(--rojo);
}

/*
 * El botón que descubre el dato se estiliza como un enlace, no como un botón:
 * lo que va a aparecer es un enlace, y así el cambio al pulsar no da un salto
 * visual.
 */
.dato__boton {
	padding: 0;
	font: inherit;
	font-size: 1.02rem;
	font-weight: 600;
	color: var(--rojo);
	background: none;
	border: 0;
	border-bottom: 1px dashed currentColor;
	cursor: pointer;
}

.dato__boton:hover {
	color: var(--rojo-oscuro);
}

.dato__valor {
	font-size: 1.02rem;
	font-weight: 600;
	text-decoration: none;
	outline: none;
}

/* Sobre fondo oscuro (pie y franja roja) el rojo no contrasta: va en blanco. */
.pie .dato,
.franja-cta .dato {
	border-color: rgb(255 255 255 / 20%);
}

.pie .dato__boton,
.pie .dato__valor,
.franja-cta .dato__boton,
.franja-cta .dato__valor {
	color: var(--blanco);
}

.franja-cta .dato__etiqueta {
	color: rgb(255 255 255 / 70%);
}

/* --------------------------------------------------------- WhatsApp */

/*
 * WhatsApp en la paleta de la marca, no en su verde corporativo.
 *
 * El verde de WhatsApp desentona con el rojo y el negro del sitio, y además
 * competía con el botón de presupuesto por la misma atención. El icono ya
 * identifica el servicio de sobra: no hace falta el color.
 */
.boton--wa {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	background: var(--negro);
	border-color: var(--negro);
	color: var(--blanco);
}

.boton--wa:hover {
	background: var(--grafito);
	border-color: var(--grafito);
	color: var(--blanco);
}

/* Sobre la franja roja se invierte, que negro sobre rojo pesa demasiado. */
.franja-cta .boton--wa {
	background: transparent;
	border-color: rgb(255 255 255 / 60%);
	color: var(--blanco);
}

.franja-cta .boton--wa:hover {
	background: var(--blanco);
	border-color: var(--blanco);
	color: var(--rojo);
}

.icono-wa {
	flex-shrink: 0;
}

/*
 * Botón flotante.
 *
 * Se aparta del borde inferior lo suficiente para no chocar con la barra del
 * navegador en el móvil, y va por debajo del lightbox en el orden de capas
 * para no quedarse encima de una foto ampliada.
 */
.wa-flotante {
	position: fixed;
	right: clamp(1rem, 3vw, 1.75rem);
	bottom: clamp(1rem, 3vw, 1.75rem);
	z-index: 40;
}

.wa-flotante__enlace {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	padding: 0.85rem 1.15rem;
	background: var(--negro);
	color: var(--blanco);
	border-radius: 100px;
	font-weight: 700;
	font-size: 0.95rem;
	text-decoration: none;
	box-shadow: 0 8px 22px rgb(0 0 0 / 22%);
	transition: transform var(--transicion), background var(--transicion),
		box-shadow var(--transicion);
}

.wa-flotante__enlace:hover {
	transform: translateY(-2px);
	background: var(--rojo);
	color: var(--blanco);
	box-shadow: 0 12px 28px rgb(0 0 0 / 28%);
}

@media (max-width: 34rem) {
	/* En pantallas estrechas, solo el icono: el rótulo taparía contenido. */
	.wa-flotante__texto {
		display: none;
	}

	.wa-flotante__enlace {
		padding: 0.9rem;
	}
}

/* ------------------------------------------------------------ contacto */

/*
 * La entradilla de página no separa por abajo —lo hace la banda siguiente en
 * el resto de páginas— pero aquí debajo no hay banda, sino esta rejilla. Así
 * que la separación la pone ella.
 */
.contacto {
	display: grid;
	grid-template-columns: minmax(0, 21rem) minmax(0, 1fr);
	gap: clamp(2rem, 5vw, 4rem);
	align-items: start;
	padding-block: clamp(2.5rem, 6vw, 4rem);
}

/*
 * El formulario, enmarcado.
 *
 * Sin marco, los campos flotaban sobre el fondo blanco de la página y no se
 * leía dónde empieza y dónde acaba lo que hay que rellenar. El marco lo
 * delimita sin llamar la atención: un borde fino, esquinas suaves y una sombra
 * apenas perceptible que lo despega del fondo.
 */
.contacto__formulario {
	padding: clamp(1.5rem, 4vw, 2.5rem);
	background: var(--blanco);
	border: 1px solid var(--borde);
	border-radius: 8px;
	/*
	 * Dos sombras superpuestas: una corta y cerrada que marca el borde, y otra
	 * larga y difusa que separa el bloque del fondo. Una sola sombra grande
	 * queda como una mancha gris; dos capas dan profundidad sin ensuciar.
	 */
	box-shadow: 0 1px 3px rgb(26 26 26 / 6%), 0 12px 32px rgb(26 26 26 / 10%);
}

/* Dentro del marco, el formulario ya no necesita su propio ancho máximo. */
.contacto__formulario .formulario {
	max-width: none;
}

/* El aviso de enviado ocupa el sitio del formulario: sin doble marco. */
.contacto__formulario .aviso {
	max-width: none;
	padding: 0 0 0 1.25rem;
	background: transparent;
}

.contacto__bloque + .contacto__bloque {
	margin-top: 2rem;
}

.contacto__bloque--wa {
	padding: 1.5rem;
	background: var(--hueso);
	border: 1px solid var(--borde);
	border-radius: 6px;
}

.contacto__titulo {
	font-size: 0.82rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--gris);
	margin-bottom: 0.6rem;
}

.contacto__nota {
	font-size: 0.93rem;
	color: var(--grafito);
}

.contacto__aviso {
	margin-top: 1rem;
	font-size: 0.82rem;
	line-height: 1.5;
	color: var(--gris);
}

.contacto__direccion {
	margin-bottom: 0.4rem;
	font-weight: 600;
}

.contacto__direccion a {
	color: inherit;
	text-decoration-color: var(--borde);
	text-underline-offset: 0.2em;
}

.contacto__direccion a:hover {
	color: var(--rojo);
	text-decoration-color: currentColor;
}

/* ----------------------------------------------- compromiso de respuesta */

/*
 * Va en la columna estrecha, bajo los datos de contacto, así que es compacto:
 * una franja roja y una línea de texto. Ahí se lee mientras uno decide por qué
 * vía escribir, que es cuando aparece la duda de si le van a contestar.
 */
.compromiso {
	margin: 1.5rem 0 0;
	padding: 0.9rem 1rem;
	background: var(--hueso);
	border-inline-start: 3px solid var(--rojo);
	border-radius: 0 4px 4px 0;
}

.compromiso__titulo {
	margin: 0 0 0.25rem;
	font-size: 0.76rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--rojo);
}

.compromiso__texto {
	margin: 0;
	font-size: 0.92rem;
	font-weight: 600;
	color: var(--grafito);
}

@media (max-width: 60rem) {
	.contacto {
		grid-template-columns: 1fr;
	}

	/* En móvil, primero el formulario: quien llega aquí viene a escribir. */
	.contacto__formulario {
		order: -1;
	}
}

/* ------------------------------------------------------------------- pie */

.pie {
	margin-top: clamp(3rem, 8vw, 6rem);
	background: var(--negro);
	color: rgb(255 255 255 / 82%);
}

.pie a {
	color: var(--blanco);
}

.pie__interior {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
	gap: 2.5rem;
	padding-block: clamp(2.5rem, 6vw, 4rem);
}

.pie__nombre {
	margin: 0 0 0.3rem;
	font-size: 1.35rem;
	font-weight: 800;
	letter-spacing: -0.03em;
	color: var(--blanco);
}

.pie__lema {
	margin: 0;
	font-size: 0.95rem;
}

.pie__titulo {
	font-size: 0.8rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: rgb(255 255 255 / 55%);
	margin-bottom: 0.75rem;
}

.pie__menu {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.4rem;
}

.pie__legal {
	border-top: 1px solid rgb(255 255 255 / 12%);
	padding-block: 1.25rem;
	font-size: 0.85rem;
}

.pie__legal p {
	margin: 0;
}

/* ------------------------------------------------------ pantalla pequeña */

@media (max-width: 60rem) {
	.proyecto__cuerpo {
		grid-template-columns: 1fr;
	}

	.proyecto__ficha {
		position: static;
	}
}

@media (max-width: 48rem) {
	.galeria {
		--fila: 115px;
	}

	.cabecera__boton {
		display: block;
	}

	.cabecera__nav {
		display: none;
		position: absolute;
		inset-inline: 0;
		top: 100%;
		flex-direction: column;
		align-items: stretch;
		gap: 0;
		padding: 1rem var(--margen) 1.5rem;
		background: var(--blanco);
		border-bottom: 1px solid var(--borde);
	}

	.cabecera__nav.esta-abierto {
		display: flex;
	}

	.cabecera__nav .menu {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
	}

	.cabecera__nav .menu a {
		display: block;
		padding-block: 0.7rem;
		border-bottom: 1px solid var(--borde);
	}

	/*
	 * En móvil no hay hover: los submenús se muestran desplegados y sangrados
	 * en lugar de flotando, que es lo único que funciona con el dedo.
	 */
	.cabecera__nav .menu .sub-menu {
		position: static;
		min-width: 0;
		padding: 0;
		opacity: 1;
		visibility: visible;
		transform: none;
		border: 0;
		border-radius: 0;
		box-shadow: none;
		background: transparent;
	}

	.cabecera__nav .menu .sub-menu a {
		padding-inline-start: 1rem;
		color: var(--grafito);
	}

	.cabecera__nav .menu .menu-item-has-children > a::after {
		display: none;
	}

	/*
	 * En el desplegable el selector va justo encima del botón, centrado y
	 * separado del último elemento del menú.
	 */
	.idiomas {
		margin-top: 1rem;
	}

	.idiomas__lista {
		justify-content: center;
	}

	.cabecera__cta {
		margin-top: 1rem;
		text-align: center;
	}

	.proyecto__imagen {
		aspect-ratio: 4 / 3;
	}

	.proyecto__navegacion {
		flex-direction: column;
	}

	.proyecto__salto--siguiente {
		text-align: left;
		margin-inline-start: 0;
	}

	/* En móvil los campos van uno debajo de otro, sin excepción. */
	.formulario__rejilla {
		grid-template-columns: 1fr;
	}
}

/* Quien pide menos movimiento, menos movimiento tiene. */
@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
	}

	/*
	 * Además de quitar la transición, se anula el estado de partida: si por lo
	 * que sea el observador no llegara a marcar un elemento, aquí se vería
	 * igualmente en vez de quedarse invisible.
	 */
	.con-js .revelar,
	.con-js .revelar-grupo > * {
		opacity: 1;
		transform: none;
	}
}
