/*
Theme Name: norfactory
Theme URI: https://norfactory.com
Description: Tema hijo de Twenty Twenty-Five para Norfactory. Dirección visual "blueprint técnico": bandas oscuras en los extremos, cuerpo claro, tipografía DM Sans + Inter + JetBrains Mono autoalojadas (más Bricolage Grotesque en los títulos de las tarjetas de servicios) y sistema de tarjeta con borde fino. Todo el diseño vive en ficheros: theme.json para los tokens y este archivo para lo que theme.json no cubre.
Author: Norfactory
Author URI: https://norfactory.com
Template: twentytwentyfive
Version: 1.95.57
Requires at least: 6.6
Tested up to: 7.1
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: norfactory-child
Tags: block-theme, custom-colors, custom-logo, full-site-editing
*/

/* -------------------------------------------------------------------------
   Índice
   1.  Base y accesibilidad
   2.  Tipografía de apoyo
   3.  Superficies: tarjetas, listas, imágenes
   4.  Bandas oscuras
   5.  Cabecera y navegación
   6.  Hero
   7.  Partner técnico: garantías
   8.  Servicios: rejilla de tarjetas
   9.  Proceso: línea de tiempo
   10. Etiquetas de garantía
   11. Proyectos
   12. FAQ
   13. Formulario de contacto
   14. Páginas legales
   15. Páginas de servicio
   16. Página 404
   17. Pie
   18. Movimiento reducido
   19. Impresión
   ------------------------------------------------------------------------- */

/* ---------------------------------------------------------------------------
   1. Base y accesibilidad
   --------------------------------------------------------------------------- */

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

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
}

/*
 * theme.json define :focus para enlaces y botones, pero eso también dibuja el
 * anillo al hacer clic con el ratón. Aquí se traslada a :focus-visible: foco de
 * teclado visible, ruido cero con el ratón.
 */
:where(a, button, input, select, textarea, summary, [tabindex]):focus:not(:focus-visible) {
	outline: none;
}

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--wp--preset--color--brand);
	outline-offset: 2px;
	border-radius: var(--wp--custom--radius--sm);
}

/* Sobre fondo oscuro el azul de marca no destaca: el anillo pasa a blanco. */
.nf-on-dark :where(a, button, summary, [tabindex]):focus-visible {
	outline-color: #FFFFFF;
}

/* Dentro de la tarjeta blanca del formulario se recupera el azul. */
.nf-on-dark .nf-form-card :where(a, button, input, select, textarea):focus-visible {
	outline-color: var(--wp--preset--color--brand);
}

/*
 * Margen lateral de la página: 50px, y 25px en móvil.
 *
 * Se hace redefiniendo las variables que el núcleo genera a partir de
 * theme.json, porque theme.json admite un solo valor y no un corte por ancho.
 * Van en body y no en :root: ahí es donde las declara el núcleo, y desde :root
 * las suyas ganarían por estar más cerca del elemento que las consume.
 *
 * El punto de corte es el mismo que usa el resto del tema para separar móvil.
 */
@media (max-width: 47.99em) {
	body {
		--wp--style--root--padding-left: 25px;
		--wp--style--root--padding-right: 25px;
	}
}

/* Anclas con cabecera fija: el destino no queda debajo de la barra. */
:target {
	scroll-margin-top: 6rem;
}

/*
 * Desplazamiento suave al seguir un ancla (menú, «Solicitar acceso», «Ver cómo
 * funciona el portal»). Solo si el sistema no pide menos movimiento: va dentro
 * de no-preference y no se anula después porque un selector html ganaría en
 * especificidad al * de la sección de movimiento reducido.
 */
@media (prefers-reduced-motion: no-preference) {
	html {
		scroll-behavior: smooth;
	}
}

/*
 * El blockGap global separa los bloques de primer nivel (cabecera, main, pie)
 * con una franja blanca. Este diseño encadena bandas de color, así que el
 * hueco se anula aquí y cada sección aporta su propio espaciado vertical.
 */
.wp-site-blocks > * {
	margin-block-start: 0;
}

/*
 * Ritmo vertical del texto largo (páginas legales, entradas, respuestas del
 * acordeón). El blockGap global es el mismo entre párrafos y entre secciones,
 * así que los títulos intermedios necesitan aire propio por arriba.
 */
:where(.wp-block-post-content, .nf-faq) :where(h2, h3, h4):not(:first-child) {
	margin-block-start: 1.8em;
}

/* Imágenes fluidas dentro de tarjetas. */
.nf-card img {
	display: block;
	height: auto;
	max-width: 100%;
}

/*
 * Aparición al entrar en pantalla (assets/js/aparecer.js, home y páginas de
 * servicio). El script elige los bloques y les pone .nf-aparece; al asomar
 * añade .is-visible con su retraso de escalonado y, al acabar, les quita las
 * dos clases.
 *
 * Solo se oculta nada cuando el script ha marcado <html> con nf-js-aparecer:
 * sin JavaScript el contenido se ve desde el principio. Va dentro de screen y
 * no-preference para que ni al imprimir ni con movimiento reducido quede nada
 * escondido.
 *
 * Sube 24px con translate y no con transform, para convivir con los hover de
 * las tarjetas, que usan transform. 0,6 s con una curva que frena al final.
 * Los hero no la usan: su contenido está quieto desde el principio para que
 * el único movimiento sea la entrada del túnel.
 */
@media screen and (prefers-reduced-motion: no-preference) {
	.nf-js-aparecer .nf-aparece {
		opacity: 0;
	}

	.nf-js-aparecer .nf-aparece.is-visible {
		animation: nf-aparecer 0.6s cubic-bezier(0.22, 1, 0.36, 1) var(--nf-aparece-retraso, 0s) both;
	}
}

@keyframes nf-aparecer {
	from {
		opacity: 0;
		translate: 0 24px;
	}

	to {
		opacity: 1;
		translate: none;
	}
}

/* ---------------------------------------------------------------------------
   2. Tipografía de apoyo
   --------------------------------------------------------------------------- */

/*
 * La mono es la voz técnica del sitio: numeración, metadatos y etiquetas.
 * Nunca se usa para texto corrido.
 */
.nf-mono {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: 0.02em;
}

/*
 * Tope de medida para texto largo: por debajo de 80 caracteres por línea, que
 * es lo que pide el brief.
 *
 * Los valores están calibrados midiendo en el navegador, no a ojo: la unidad ch
 * es el ancho del carácter «0», bastante mayor que la media de una minúscula,
 * así que 62ch daban 90 caracteres reales. 52ch se queda en unos 75.
 */
.nf-measure {
	max-width: 52ch;
}

.nf-lead {
	color: var(--wp--preset--color--muted);
	max-width: 50ch;
}

.nf-on-dark .nf-lead {
	color: var(--wp--custom--on-dark--muted);
}

/* Centrar una entradilla dentro de un contenedor centrado. */
.has-text-align-center.nf-measure,
.has-text-align-center.nf-lead {
	margin-inline: auto;
}

/*
 * Entradilla de sección. Ocupa todo el ancho ancho para alinear su borde
 * izquierdo con el de la rejilla que viene debajo, y limita la medida del
 * titular y del texto por separado en lugar de centrar el bloque entero.
 *
 * Titular y texto comparten un único tope de 36rem, fijado por el usuario, y
 * la columna de propuesta de la sección Partner usa el mismo: así todos los
 * titulares y entradillas alineados a la izquierda miden igual en la home.
 */
.nf-intro > h2,
.nf-intro > p,
.nf-split__intro > h2,
.nf-split__intro > p {
	max-width: 36rem;
}

/*
 * Entradilla centrada en una sola columna (banda de Control). Los anchos salen
 * de medir el texto con las fuentes del tema a tamaño de escritorio, no a ojo:
 *
 * - Titular (DM Sans 700, 44px): 1328px en una línea. Partido en «Externalizar
 *   la parte técnica / no debería hacerte perder el control» mide 575 y 743px,
 *   así que 48rem (768px) lo deja en dos líneas.
 * - Entradilla (Inter 400, 22px): 938px en una línea; con el tope común de
 *   36rem cae en dos de unos 490 y 445px.
 * - Las tres etiquetas suman unos 560px con su relleno: caben en una fila
 *   dentro de esos mismos 36rem.
 *
 * text-wrap: balance reparte las líneas a partes iguales en lugar de dejar una
 * viuda corta; donde no hay soporte, el tope de ancho ya evita lo peor.
 */
.nf-intro--center > h2 {
	margin-inline: auto;
	max-width: 48rem;
	text-wrap: balance;
}

.nf-intro--center > p {
	margin-inline: auto;
	text-wrap: balance;
}

/* Más aire que en las entradillas alineadas a la izquierda: sin columna al
   lado, los tres bloques necesitan separarse para leerse como grupos. El
   titular y el texto van a spacing-40 (desde el patrón). */
.nf-intro--center > .nf-pills {
	justify-content: center;
	margin-block-start: var(--wp--preset--spacing--50);
	margin-inline: auto;
	max-width: 36rem;
}

/* ---------------------------------------------------------------------------
   3. Superficies
   --------------------------------------------------------------------------- */

/*
 * Tarjeta única para todo el sitio: borde de 1px en lugar de sombra difusa.
 * La elevación solo aparece al pasar por encima o al recibir foco, que es
 * cuando comunica algo.
 */
.nf-card {
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--md);
	transition: border-color var(--wp--custom--transition),
		box-shadow var(--wp--custom--transition),
		transform var(--wp--custom--transition);
}

/*
 * Solo las tarjetas que comparten fila en una rejilla igualan altura. Dentro
 * de una columna suelta, la tarjeta se ajusta a su contenido y no queda
 * estirada con un hueco muerto debajo.
 */
.is-layout-grid > .nf-card {
	height: 100%;
}

.nf-card:hover,
.nf-card:focus-within {
	border-color: var(--wp--custom--border-strong);
	box-shadow: var(--wp--preset--shadow--lift);
	transform: translateY(-2px);
}

.nf-card h3,
.nf-card h4 {
	margin-block-start: 0;
}

.nf-card p:last-child {
	margin-block-end: 0;
}

/* Lista de comprobación sin depender de imágenes ni de iconos externos. */
.nf-checklist {
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-checklist li {
	padding-inline-start: 1.75rem;
	position: relative;
}

.nf-checklist li + li {
	margin-block-start: 0.75rem;
}

.nf-checklist li::before {
	color: var(--wp--preset--color--brand);
	content: "\2713";
	font-weight: 700;
	inset-inline-start: 0;
	position: absolute;
}

.nf-on-dark .nf-checklist li::before {
	color: var(--wp--custom--on-dark--accent);
}

/* Cuando la lista ocupa una columna entera y no acompaña a un texto. */
.nf-checklist--lg li {
	font-size: var(--wp--preset--font-size--large);
	letter-spacing: -0.01em;
	padding-inline-start: 2.25rem;
}

.nf-checklist--lg li + li {
	margin-block-start: 1.25rem;
}

/*
 * Captura de interfaz, presentada como la ventana en perspectiva de la landing
 * de agencias: el marco gira levemente sobre su eje vertical y se endereza al
 * pasar por encima.
 *
 * El reparto de papeles importa. La figura es el contenedor plano y semántico;
 * .nf-shot__stage es el sistema de referencia del aviso flotante, que asoma por
 * fuera sin inclinarse; .nf-shot__frame es lo único que se inclina y lo único
 * que recorta, con su overflow oculto, para que las esquinas redondeen bien
 * pese a que la barra lateral del portal llega oscura hasta el borde.
 *
 * El marco es además el contenedor de consulta de la ilustración: una consulta
 * @container no puede dar estilo al propio contenedor, así que las reglas por
 * ancho se aplican a .nf-portal, que va dentro.
 */
.nf-shot {
	margin: 0;
}

.nf-shot__stage {
	position: relative;
}

.nf-shot__frame {
	border: 1px solid var(--wp--preset--color--border);
	container: nf-portal / inline-size;
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: 0 30px 70px rgba(16, 20, 30, 0.14),
		0 8px 24px rgba(16, 20, 30, 0.06);
	overflow: hidden;
	/* Inclinación reforzada a petición del usuario (antes -6deg / 2deg con
	   perspectiva de 1400px). */
	transform: perspective(1200px) rotateY(-12deg) rotateX(4deg);
	transition: transform 500ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* :focus-within además de :hover, para quien navega con el teclado. */
.nf-shot:hover .nf-shot__frame,
.nf-shot:focus-within .nf-shot__frame {
	transform: perspective(1200px) rotateY(-4deg) rotateX(1deg);
}

/*
 * Ilustración del portal de soporte. Simplifica la captura real
 * (assets/img/portal-soporte.png): se quedan la barra lateral oscura, la
 * cabecera con el botón, las pestañas de estado y los tickets; se van el
 * buscador, las fechas y la mitad de la navegación.
 *
 * Todo se mide en em sobre un cuerpo de 13px, así que la ilustración escala
 * cambiando un único font-size. Por debajo de 34rem de marco la barra lateral
 * se pliega a una columna de iconos, como hacen las aplicaciones reales: logo,
 * iconos del menú y avatar, sin textos, y los rótulos de grupo pasan a ser
 * filetes. Por debajo de 24rem se ocultan también el subtítulo, dos pestañas y
 * la web de cada ticket.
 *
 * La ventana tiene alto fijo y la zona principal recorta: hay más tickets de
 * los que caben, así que el último asoma cortado y un fundido al pie sugiere
 * que la lista sigue.
 *
 * Los lados de cada ticket van en zigzag, como en el portal real. Es una
 * máscara con dos medias cajas (izquierda y derecha) que repiten en vertical
 * una tesela de --nf-zig de alto; en cada tesela, un degradado cónico deja
 * transparente un triángulo con la base en el borde y el vértice a media
 * tesela hacia dentro.
 *
 * Contraste de las etiquetas de estado (texto sobre su fondo): nuevo 6,74:1,
 * en curso 5,49:1, esperando 6,37:1, resuelto 4,84:1. Texto tenue sobre blanco
 * 5,45:1 y sobre el fondo de la ventana 4,77:1. En la barra lateral, texto
 * 8,63:1, rótulos 5,72:1 y elemento activo 13,05:1.
 */
.nf-portal {
	background-color: #EDF0F5;
	box-sizing: border-box;
	display: grid;
	font-family: var(--wp--preset--font-family--inter);
	font-size: 13px;
	grid-template-columns: 13.5em minmax(0, 1fr);
	height: 38em;
	line-height: 1.35;
}

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

.nf-portal ul {
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-portal svg {
	display: block;
	flex: 0 0 auto;
}

/* Barra lateral */
.nf-portal__side {
	background-image: linear-gradient(180deg, #111A36 0%, #0B1533 100%);
	color: #AEB8D0;
	display: flex;
	flex-direction: column;
	gap: 0.35em;
	padding: 1.25em 0.85em;
}

.nf-portal__brand {
	align-items: center;
	color: #FFFFFF;
	display: flex;
	font-weight: 600;
	gap: 0.6em;
	margin-block-end: 1.1em;
	padding-inline: 0.35em;
}

.nf-portal__logo {
	align-items: center;
	background-image: var(--wp--preset--gradient--brand);
	border-radius: 0.5em;
	color: #FFFFFF;
	display: inline-flex;
	height: 2.15em;
	justify-content: center;
	width: 2.15em;
}

.nf-portal__label {
	color: #8A95B0;
	font-size: 0.72em;
	font-weight: 600;
	letter-spacing: 0.1em;
	margin-block: 0.9em 0.2em;
	padding-inline: 0.55em;
	text-transform: uppercase;
}

.nf-portal__nav {
	display: grid;
	gap: 0.2em;
}

.nf-portal__nav-item {
	align-items: center;
	border-radius: 0.55em;
	display: flex;
	gap: 0.65em;
	padding: 0.6em 0.65em;
	white-space: nowrap;
}

.nf-portal__nav-item.is-active {
	background-color: rgba(255, 255, 255, 0.09);
	color: #FFFFFF;
	font-weight: 600;
}

.nf-portal__user {
	align-items: center;
	border-top: 1px solid rgba(255, 255, 255, 0.1);
	color: #FFFFFF;
	display: flex;
	font-size: 0.92em;
	font-weight: 600;
	gap: 0.6em;
	margin-block-start: auto;
	padding: 1em 0.35em 0;
}

.nf-portal__avatar {
	align-items: center;
	background-color: #25304D;
	border-radius: 0.45em;
	display: inline-flex;
	flex: 0 0 auto;
	font-size: 0.85em;
	height: 2.4em;
	justify-content: center;
	width: 2.4em;
}

.nf-portal__who {
	display: grid;
	gap: 0.4em;
}

/* Línea de relleno en lugar de un segundo dato: es una ilustración. */
.nf-portal__skel {
	background-color: rgba(255, 255, 255, 0.14);
	border-radius: 1em;
	display: block;
	height: 0.45em;
	width: 4.5em;
}

/* Zona principal */
.nf-portal__main {
	display: flex;
	flex-direction: column;
	gap: 1.1em;
	-webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 5em), transparent);
	mask-image: linear-gradient(180deg, #000 calc(100% - 5em), transparent);
	min-width: 0;
	overflow: hidden;
	padding: 1.4em 1.4em 0;
}

.nf-portal__top {
	align-items: flex-start;
	display: flex;
	gap: 1em;
	justify-content: space-between;
}

.nf-portal__title {
	color: var(--wp--preset--color--contrast);
	display: block;
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: 1.55em;
	font-weight: 700;
	letter-spacing: -0.02em;
	line-height: 1.1;
}

.nf-portal__subtitle {
	color: var(--wp--preset--color--muted);
	display: block;
	font-size: 0.9em;
	margin-block-start: 0.3em;
}

/* Marino y no el azul de marca: es un botón de ilustración y no debe
   confundirse con los CTA reales de la página. Repite el tono de la barra
   lateral; el blanco sobre #0B1533 da 17,96:1. */
.nf-portal__button {
	background-color: var(--wp--preset--color--deep);
	border-radius: 0.55em;
	color: #FFFFFF;
	flex: 0 0 auto;
	font-size: 0.92em;
	font-weight: 600;
	padding: 0.65em 0.95em;
	white-space: nowrap;
}

.nf-portal__tabs {
	align-self: flex-start;
	background-color: #E2E6EE;
	border-radius: 0.65em;
	display: flex;
	gap: 0.15em;
	max-width: 100%;
	overflow: hidden;
	padding: 0.25em;
}

.nf-portal__tab {
	border-radius: 0.45em;
	color: #4B5363;
	font-size: 0.9em;
	font-weight: 500;
	padding: 0.45em 0.7em;
	white-space: nowrap;
}

.nf-portal__tab.is-active {
	background-color: #FFFFFF;
	box-shadow: 0 1px 2px rgba(16, 20, 30, 0.08);
	color: var(--wp--preset--color--contrast);
	font-weight: 600;
}

.nf-portal__tickets {
	display: grid;
	flex: 0 0 auto;
	gap: 0.7em;
}

.nf-portal__ticket {
	--nf-zig: 0.9em;
	background-color: #FFFFFF;
	display: grid;
	gap: 1em;
	grid-template-columns: minmax(0, 1fr) auto;
	-webkit-mask:
		conic-gradient(from 225deg at calc(var(--nf-zig) / 2) 50%, transparent 25%, #000 0) left / 51% var(--nf-zig) repeat-y,
		conic-gradient(from 45deg at calc(100% - var(--nf-zig) / 2) 50%, transparent 25%, #000 0) right / 51% var(--nf-zig) repeat-y;
	mask:
		conic-gradient(from 225deg at calc(var(--nf-zig) / 2) 50%, transparent 25%, #000 0) left / 51% var(--nf-zig) repeat-y,
		conic-gradient(from 45deg at calc(100% - var(--nf-zig) / 2) 50%, transparent 25%, #000 0) right / 51% var(--nf-zig) repeat-y;
	padding: 0.95em 1.3em;
}

.nf-portal__info {
	display: grid;
	gap: 0.3em;
	min-width: 0;
}

.nf-portal__subject {
	color: var(--wp--preset--color--contrast);
	font-weight: 600;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.nf-portal__id {
	color: #6B7383;
	font-size: 0.9em;
	font-weight: 500;
	margin-inline-end: 0.2em;
}

.nf-portal__site {
	color: var(--wp--preset--color--muted);
	font-size: 0.9em;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Estado arriba y tiempo abajo, pegados al borde derecho, como en el portal. */
.nf-portal__meta {
	align-content: space-between;
	display: grid;
	gap: 0.4em;
	justify-items: end;
}

.nf-portal__badge {
	border-radius: 0.4em;
	font-size: 0.82em;
	font-weight: 600;
	padding: 0.25em 0.55em;
	white-space: nowrap;
}

.nf-portal__badge--new {
	background-color: #EEF0F4;
	color: #475467;
}

.nf-portal__badge--progress {
	background-color: #DBEAFE;
	color: #1D4ED8;
}

.nf-portal__badge--wait {
	background-color: #FEF3C7;
	color: #92400E;
}

.nf-portal__badge--done {
	background-color: #D1FAE5;
	color: #047857;
}

.nf-portal__time {
	color: var(--wp--preset--color--muted);
	font-size: 0.82em;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

/*
 * Aviso flotante. Va en el escenario y no en el marco: así no se inclina ni
 * queda recortado, y asoma por delante de la ventana como una notificación.
 *
 * Quieto: la levitación en bucle se retiró (movimiento de más de 5 s sin
 * forma de pausarlo) y se queda en la posición más baja que tenía.
 */
.nf-portal__toast {
	align-items: center;
	background-color: #FFFFFF;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--md);
	bottom: -1.5rem;
	box-shadow: 0 18px 40px rgba(16, 20, 30, 0.16);
	display: flex;
	font-family: var(--wp--preset--font-family--inter);
	font-size: 13px;
	gap: 0.75em;
	line-height: 1.3;
	padding: 0.8em 1.1em 0.8em 0.8em;
	position: absolute;
	right: -1.5rem;
}

.nf-portal__toast b {
	color: var(--wp--preset--color--contrast);
	display: block;
	font-weight: 600;
}

.nf-portal__toast b + span {
	color: var(--wp--preset--color--muted);
	font-size: 0.9em;
}

.nf-portal__toast-icon {
	align-items: center;
	background-color: #D1FAE5;
	border-radius: 50%;
	color: #047857;
	display: inline-flex;
	flex: 0 0 auto;
	height: 2.2em;
	justify-content: center;
	width: 2.2em;
}

@container nf-portal (max-width: 34rem) {
	.nf-portal {
		grid-template-columns: 3.75em minmax(0, 1fr);
	}

	.nf-portal__side {
		align-items: center;
		padding: 1.25em 0.5em;
	}

	.nf-portal__brand {
		margin-block-end: 0.6em;
		padding-inline: 0;
	}

	.nf-portal__brand > span:not(.nf-portal__logo),
	.nf-portal__nav-item span,
	.nf-portal__who {
		display: none;
	}

	.nf-portal__label {
		align-self: stretch;
		background-color: rgba(255, 255, 255, 0.1);
		font-size: 0;
		height: 1px;
		margin: 0.6em 0.35em;
		padding: 0;
	}

	.nf-portal__nav-item {
		justify-content: center;
		padding: 0.65em;
	}

	.nf-portal__user {
		align-self: stretch;
		justify-content: center;
		padding-inline: 0;
	}
}

@container nf-portal (max-width: 24rem) {
	.nf-portal {
		font-size: 12px;
	}

	.nf-portal__main {
		padding: 1.1em 1em 0;
	}

	.nf-portal__subtitle,
	.nf-portal__site,
	.nf-portal__tab:nth-child(n + 4) {
		display: none;
	}
}

/*
 * Por debajo de tablet el giro sobre una captura pequeña solo resta
 * legibilidad, así que se endereza.
 */
@media (max-width: 47.99em) {
	.nf-shot__frame {
		transform: none;
	}

	.nf-portal__toast {
		bottom: -1.25rem;
		right: 0.75rem;
	}
}

/*
 * El hero no usa el bloque de columnas sino su propia rejilla.
 *
 * El motivo es que core/columns fuerza `flex-wrap: nowrap !important` a partir
 * de 782px y reparte el ancho en porcentajes. Con una rejilla propia el corte
 * se elige y la ilustración puede llevar un tope fijo.
 */
.nf-hero__cols {
	display: grid;
	gap: var(--wp--preset--spacing--60);
	grid-template-columns: minmax(0, 1fr);
}

/* El diseño de flujo del núcleo separa a los hijos con margen: aquí sobra,
   porque el hueco lo pone la rejilla. */
.nf-hero__cols > * {
	margin-block: 0;
}

.nf-hero__col {
	max-width: 40rem;
}

/*
 * Mismo reparto que las aperturas de las páginas de servicio (.nf-page-hero__cols):
 * apilado, el texto va alineado a la izquierda; desde 1088px, dos columnas
 * repartidas a los extremos —40rem el texto, 28rem la ilustración—, de modo
 * que el texto arranca en el mismo borde que las secciones de debajo. Antes la
 * home centraba el conjunto (y el texto apilado) y no casaba con las demás
 * aperturas.
 */
@media (min-width: 68em) {
	.nf-hero__cols {
		align-items: center;
		column-gap: var(--wp--preset--spacing--70);
		grid-template-columns: minmax(0, 40rem) minmax(0, 28rem);
		justify-content: space-between;
	}
}

/*
 * Tramo destacado del titular, como el <em> del h1 de consultoria.htm. El color
 * sólido va primero: si el recorte del degradado sobre el texto no se aplica
 * —o el sistema fuerza sus propios colores— el texto sigue siendo legible en
 * lugar de quedarse transparente.
 */
.nf-hero__title em {
	color: var(--wp--preset--color--brand-navy);
	font-style: normal;
}

@supports ((background-clip: text) or (-webkit-background-clip: text)) {
	.nf-hero__title em {
		-webkit-background-clip: text;
		background-clip: text;
		background-image: linear-gradient(110deg, var(--wp--preset--color--brand) 0%, var(--wp--preset--color--brand-navy) 72%);
		color: transparent;
	}
}

@media (forced-colors: active) {
	.nf-hero__title em {
		color: CanvasText;
	}
}

/* ---------------------------------------------------------------------------
   4. Bandas oscuras
   --------------------------------------------------------------------------- */

/*
 * Todo lo que va sobre #0B1533 se envuelve en .nf-on-dark. Los colores de
 * texto se fijan aquí una sola vez en lugar de repetirlos bloque a bloque.
 */
.nf-on-dark {
	color: var(--wp--custom--on-dark--text);
}

.nf-on-dark :where(h1, h2, h3, h4, h5) {
	color: #FFFFFF;
}

.nf-on-dark :where(p, li, figcaption) {
	color: var(--wp--custom--on-dark--text);
}

.nf-on-dark :where(a):not(.wp-element-button):not(.wp-block-navigation-item__content) {
	color: #FFFFFF;
	text-decoration-color: rgba(255, 255, 255, 0.45);
	text-underline-offset: 0.2em;
}

.nf-on-dark :where(a):not(.wp-element-button):not(.wp-block-navigation-item__content):hover {
	color: var(--wp--custom--on-dark--accent);
	text-decoration-color: currentColor;
}

/* Botón secundario (contorno) sobre oscuro. */
.nf-on-dark .is-style-outline > .wp-element-button,
.nf-on-dark .wp-block-button.is-style-outline .wp-block-button__link {
	background-color: transparent;
	border-color: rgba(255, 255, 255, 0.35);
	color: #FFFFFF;
}

.nf-on-dark .is-style-outline > .wp-element-button:hover,
.nf-on-dark .wp-block-button.is-style-outline .wp-block-button__link:hover {
	background-color: rgba(255, 255, 255, 0.08);
	border-color: #FFFFFF;
	color: #FFFFFF;
}

.nf-on-dark .wp-block-separator {
	border-color: var(--wp--custom--on-dark--border);
	color: var(--wp--custom--on-dark--border);
}

/* ---------------------------------------------------------------------------
   5. Cabecera y navegación
   --------------------------------------------------------------------------- */

/*
 * La cabecera arranca transparente sobre el hero y se vuelve sólida al bajar.
 *
 * El estado por defecto es el sólido, no el transparente, a propósito: si el
 * JavaScript no llega a ejecutarse la barra queda legible sobre cualquier
 * sección en lugar de dejar el texto flotando sobre el contenido. La clase
 * .is-top la pone assets/js/header.js mientras estamos arriba del todo.
 */
/*
 * Para que la transparencia enseñe el degradado del hero y no el blanco del
 * body, la cabecera tiene que ir superpuesta, no apilada encima. El margen
 * negativo sube la sección siguiente justo su altura; el z-index la mantiene
 * por delante.
 *
 * Lo pegajoso vive en el contenedor de la plantilla parcial —hijo directo de
 * .wp-site-blocks— y no en .nf-header: position:sticky solo puede desplazarse
 * dentro de su padre, y el padre de .nf-header es una caja de altura fija.
 */
/*
 * --nf-header-height tiene que valer exactamente lo que ocupa la barra: es a la
 * vez el alto de la barra, el margen negativo que la superpone y el hueco que
 * se reserva en las páginas interiores. Si el valor se queda corto, la sección
 * siguiente empieza unos píxeles más abajo del borde superior y la rejilla del
 * hero arranca desplazada.
 *
 * Por eso la barra no se deja crecer con su contenido: el alto lo fija
 * min-height, la rejilla centra las piezas en vertical y el borde inferior va
 * como sombra interior, que no suma alto. La barra no lleva relleno vertical:
 * se sumaba a la pieza más alta —el enlace del menú, unos 41px— y la barra
 * pasaba de los 64px, así que todo el contenido bajaba ese sobrante. Es un
 * único valor en todos los anchos: 64px dan de sobra para el menú y el botón.
 */
:root {
	--nf-header-height: 4rem;
}

.wp-site-blocks > header {
	margin-block-end: calc(var(--nf-header-height) * -1);
	position: sticky;
	top: 0;
	z-index: 20;
}

/*
 * El fondo esmerilado va en un pseudoelemento y no en .nf-header. Un elemento
 * con backdrop-filter pasa a ser el bloque contenedor de sus descendientes con
 * position:fixed, igual que si llevara transform. El panel del menú móvil es
 * uno de ellos: con el filtro en la barra, el panel medía lo que la barra
 * —64px de alto— en vez de la ventana, y su overflow:auto lo convertía en una
 * franja con scroll propio. Solo pasaba tras bajar un poco, porque arriba del
 * todo .is-top apaga el filtro. Un pseudoelemento no contiene a nadie.
 *
 * El grupo interior va con position:relative para pintarse por encima del
 * pseudoelemento sin recurrir a z-index; relative no crea bloque contenedor
 * para los fixed.
 */
.nf-header {
	position: relative;
}

.nf-header::before {
	-webkit-backdrop-filter: saturate(180%) blur(12px);
	backdrop-filter: saturate(180%) blur(12px);
	background-color: rgba(255, 255, 255, 0.82);
	box-shadow: inset 0 -1px 0 var(--wp--preset--color--border),
		0 1px 2px rgba(11, 21, 51, 0.05);
	content: "";
	inset: 0;
	pointer-events: none;
	position: absolute;
	transition: background-color var(--wp--custom--transition),
		box-shadow var(--wp--custom--transition);
}

.nf-header > .wp-block-group {
	position: relative;
}

/* Sin soporte de desenfoque, el fondo se vuelve opaco para no perder lectura. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	.nf-header::before {
		background-color: #FFFFFF;
	}
}

.nf-header.is-top::before {
	/*
	 * El desenfoque hay que apagarlo explícitamente: backdrop-filter actúa
	 * sobre lo que queda detrás de la caja aunque su fondo sea transparente,
	 * así que dejarlo puesto deja una banda esmerilada en lugar de un hueco.
	 */
	-webkit-backdrop-filter: none;
	backdrop-filter: none;
	background-color: transparent;
	box-shadow: none;
}

/* La barra admin de WordPress ya desplaza el body; sticky lo respeta. */
.admin-bar .wp-site-blocks > header {
	top: 32px;
}

@media (max-width: 782px) {
	.admin-bar .wp-site-blocks > header {
		top: 46px;
	}
}

/*
 * Tres columnas: logotipo, navegación y llamada a la acción.
 *
 * Rejilla y no flex con space-between: con tres piezas de anchos distintos,
 * space-between centra la del medio solo por casualidad. Con `1fr auto 1fr`
 * los dos carriles laterales miden exactamente lo mismo y la navegación queda
 * centrada respecto al contenedor, mida lo que mida el logotipo o el botón.
 */
.nf-header__inner {
	align-items: center;
	column-gap: var(--wp--preset--spacing--40);
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	min-height: var(--nf-header-height);
}

/*
 * El grupo lleva la disposición «flujo» del núcleo, que separa cada hijo del
 * anterior con un margen superior. Aquí los hijos son columnas de una rejilla,
 * así que ese margen no separa nada: solo estiraba la fila —20px de más— y
 * dejaba la barra más alta que --nf-header-height.
 */
.nf-header__inner > * {
	margin-block: 0;
}

.nf-header__inner > .nf-header__cta {
	justify-self: end;
}

/*
 * «Área clientes» lleva al portal de soporte, fuera de esta web.
 *
 * Cabecera y pie van en neutros (15/09/2026): salen en todas las páginas y
 * cada página de servicio tiene su propio color de categoría, así que un azul
 * aquí se repetía por toda la web y chocaba con los verdes, morados, ámbar y
 * rojos.
 *
 * Va al revés que un botón macizo (16/09/2026): sin fondo y con el filete negro
 * del texto, para que la barra pese lo menos posible sobre el hero; al pasar se
 * invierte y se rellena de negro. Negro sobre el blanco de la cabecera: 19,55:1;
 * blanco sobre #0B0C10 en el hover: 19,55:1.
 *
 * El relleno se fija aquí, y no en el patrón como antes, porque hay que
 * descontarle el borde: así la caja mide lo mismo con fondo y sin él.
 */
.nf-header__cta .wp-block-button__link {
	background-color: transparent;
	border: 1px solid var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--contrast);
	padding: calc(0.6rem - 1px) calc(1.1rem - 1px);
	transition: background-color var(--wp--custom--transition),
		color var(--wp--custom--transition);
}

.nf-header__cta .wp-block-button__link:hover,
.nf-header__cta .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--contrast);
	color: #FFFFFF;
}

/*
 * Las plantillas interiores siguen siendo las del tema padre y no saben de la
 * cabecera superpuesta. Hasta que se rehagan (tanda 2), se les reserva el
 * hueco por arriba para que el título no quede debajo de la barra.
 */
body:not(.home) .wp-site-blocks > main {
	padding-block-start: var(--nf-header-height);
}

/*
 * Logotipo. El PNG mide 382×69 y se declara con esos atributos para que el
 * navegador reserve el hueco exacto y no haya salto de maquetación; la altura
 * visible se fija aquí. Sobre las bandas oscuras va la versión blanca; la
 * oscura entra en superficies claras y al imprimir (ver sección 15).
 */
.nf-logo {
	line-height: 0;
	margin: 0;
}

.nf-logo a {
	display: inline-block;
	text-decoration: none;
}

.nf-logo__img {
	height: 1.75rem;
	width: auto;
}

.nf-logo--lg {
	margin-block-end: 1.25rem;
}

.nf-logo--lg .nf-logo__img {
	height: 2.125rem;
}

.nf-nav .wp-block-navigation-item__content {
	color: var(--wp--preset--color--contrast);
	padding-block: 0.35rem;
}

/* Neutro, como el resto de la cabecera: al pasar, el texto se aclara al gris
   tenue (5,45:1 sobre blanco). */
.nf-nav .wp-block-navigation-item__content:hover,
.nf-nav .current-menu-item > .wp-block-navigation-item__content {
	color: var(--wp--preset--color--muted);
}

/*
 * Submenú de «Servicios»: las cinco páginas de servicio colgando del menú. En
 * la barra, un panel con icono, nombre y una línea de apoyo por servicio —la
 * «mega-row» de la maqueta de referencia (diseños/diseno.css)—; dentro del
 * desplegable, una fila plegable (más abajo, con el resto del panel móvil).
 *
 * Abrir y cerrar es cosa del núcleo: al pasar por encima con ratón y con el
 * botón de la flecha para teclado y pantalla táctil. Por eso aquí no se tocan
 * visibility, opacity, width ni height del panel —son suyas y colapsan la caja
 * cuando está cerrado—; solo se le da forma. El ancho lo fijan las filas, no el
 * contenedor, para no pelear con el `width: auto` que el núcleo pone al abrir.
 *
 * «Servicios» no lleva enlace: era el único del menú que repetía destino con
 * las páginas de dentro. El núcleo pinta entonces un <a> sin href, que ni
 * navega ni recoge el foco; quien va con teclado llega directo al botón.
 *
 * Los iconos son los mismos SVG de Lucide que usan las tarjetas de servicios,
 * pintados como máscara para que tomen el color del texto: una <img> no puede.
 * Cada fila declara el suyo en --nf-sub-icono y el pseudoelemento lo recorta.
 */
.nf-sub--desarrollo {
	--nf-sub-icono: url("assets/icons/lucide/code-xml.svg");
}

.nf-sub--hosting {
	--nf-sub-icono: url("assets/icons/lucide/server.svg");
}

.nf-sub--ecommerce {
	--nf-sub-icono: url("assets/icons/lucide/shopping-cart.svg");
}

.nf-sub--ia {
	--nf-sub-icono: url("assets/icons/lucide/brain.svg");
}

.nf-sub--seguridad {
	--nf-sub-icono: url("assets/icons/lucide/shield-check.svg");
}

.nf-nav .nf-sub > .wp-block-navigation-item__content::before {
	background-color: var(--wp--preset--color--muted);
	block-size: 1.125rem;
	content: "";
	inline-size: 1.125rem;
	-webkit-mask-image: var(--nf-sub-icono);
	mask-image: var(--nf-sub-icono);
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-size: contain;
	mask-size: contain;
	transition: background-color var(--wp--custom--transition);
}

.nf-nav .nf-sub .wp-block-navigation-item__label {
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	letter-spacing: -0.005em;
	line-height: 1.3;
}

/* El núcleo esconde la descripción de los enlaces; aquí es parte de la fila. */
.nf-nav .nf-sub .wp-block-navigation-item__description {
	color: var(--wp--preset--color--muted);
	display: block;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 400;
	line-height: 1.35;
}

/*
 * En modo de colores forzados las máscaras desaparecen —el navegador sustituye
 * los fondos— y las filas se quedarían sin icono. Se repintan con el color de
 * texto del sistema, que sí se respeta.
 */
@media (forced-colors: active) {
	.nf-nav .nf-sub > .wp-block-navigation-item__content::before {
		background-color: CanvasText;
	}
}

/*
 * El panel, solo con el menú horizontal a la vista. Por debajo de 1000 px el
 * menú es el desplegable, y estas reglas —posición absoluta, ancho fijo, el
 * translate que centra el panel bajo su enlace— sacaban la lista fuera de la
 * pantalla: allí manda el bloque del panel móvil.
 */
@media (min-width: 56.25em) {
	/*
	 * La flecha: el núcleo le da una caja de 0.6em, así que el SVG se salía y
	 * quedaba descolocado. Aquí la caja mide 1rem y el icono va centrado dentro
	 * con flex.
	 */
	.nf-nav .nf-nav__servicios.wp-block-navigation-item > .wp-block-navigation__submenu-icon {
		align-items: center;
		block-size: 1rem;
		color: var(--wp--preset--color--muted);
		display: flex;
		inline-size: 1rem;
		justify-content: center;
		margin-inline-start: 0.125rem;
		padding: 0;
		transition: color var(--wp--custom--transition);
	}

	.nf-nav .nf-nav__servicios.wp-block-navigation-item > .wp-block-navigation__submenu-icon svg {
		block-size: 12px;
		inline-size: 12px;
		transition: transform var(--wp--custom--transition);
	}

	.nf-nav .nf-nav__servicios.wp-block-navigation-item:hover > .wp-block-navigation__submenu-icon,
	.nf-nav .nf-nav__servicios.wp-block-navigation-item:focus-within > .wp-block-navigation__submenu-icon {
		color: var(--wp--preset--color--contrast);
	}

	/* Sin enlace no hay mano: el cursor de siempre deja claro que el título no
	   lleva a ninguna parte. */
	.nf-nav .nf-nav__servicios.wp-block-navigation-item > .wp-block-navigation-item__content {
		cursor: default;
	}

	/*
	 * Puente sobre el hueco que queda entre el título y el panel. El núcleo abre
	 * y cierra con pointerenter/pointerleave sobre el <li>, así que sin él el
	 * menú se cerraba al bajar el ratón hacia la lista. El pseudoelemento
	 * pertenece al <li> y cuenta como parte de él, de modo que el puntero nunca
	 * llega a salir.
	 */
	.nf-nav .nf-nav__servicios.wp-block-navigation-item {
		position: relative;
	}

	.nf-nav .nf-nav__servicios.wp-block-navigation-item::after {
		block-size: 0.75rem;
		content: "";
		inset-block-start: 100%;
		inset-inline: 0;
		position: absolute;
	}

	/* El selector arranca en el contenedor de la lista para ganar a las reglas
	   del núcleo, que colocan el panel a `left: -1px` con tres clases. */
	.nf-nav .wp-block-navigation__container > .nf-nav__servicios > .wp-block-navigation__submenu-container {
		background-color: var(--wp--preset--color--base);
		border: 1px solid var(--wp--preset--color--border);
		border-radius: var(--wp--custom--radius--md);
		box-shadow: var(--wp--preset--shadow--lift);
		gap: 0;
		inset-block-start: calc(100% + 0.625rem);
		inset-inline-start: 50%;
		padding: 0.375rem;
		transform: translateX(-50%);
	}

	/* Fila: icono a la izquierda, nombre y línea de apoyo apilados. El selector
	   es largo porque el núcleo estila la misma caja con cinco clases. */
	.nf-nav .nf-nav__servicios > .wp-block-navigation__submenu-container > .nf-sub.wp-block-navigation-item > .wp-block-navigation-item__content {
		align-items: start;
		border-radius: var(--wp--custom--radius--sm);
		column-gap: 0.75rem;
		display: grid;
		grid-template-columns: 1.125rem 1fr;
		inline-size: 20.5rem;
		padding: 0.625rem 0.75rem;
		row-gap: 0.125rem;
		transition: background-color var(--wp--custom--transition);
	}

	.nf-nav .nf-nav__servicios > .wp-block-navigation__submenu-container > .nf-sub.wp-block-navigation-item > .wp-block-navigation-item__content::before {
		grid-row: 1 / span 2;
		margin-block-start: 0.0625rem;
	}

	/* Al pasar por la fila, el fondo suave de siempre y el icono en azul de
	   marca: el único color del panel, como en la maqueta. */
	.nf-nav .nf-nav__servicios > .wp-block-navigation__submenu-container > .nf-sub.wp-block-navigation-item > .wp-block-navigation-item__content:hover,
	.nf-nav .nf-nav__servicios > .wp-block-navigation__submenu-container > .nf-sub.wp-block-navigation-item > .wp-block-navigation-item__content:focus-visible {
		background-color: var(--wp--preset--color--surface);
	}

	.nf-nav .nf-nav__servicios > .wp-block-navigation__submenu-container > .nf-sub.wp-block-navigation-item > .wp-block-navigation-item__content:hover::before,
	.nf-nav .nf-nav__servicios > .wp-block-navigation__submenu-container > .nf-sub.wp-block-navigation-item > .wp-block-navigation-item__content:focus-visible::before {
		background-color: var(--wp--preset--color--brand);
	}
}

/*
 * Botón de menú: tres barras de 2px alineadas a la derecha, la del medio más
 * corta (20 · 14 · 20px, separadas 5px), sobre una zona táctil de 40px con
 * fondo suave al pasar por encima.
 *
 * El SVG del núcleo se oculta y las barras se dibujan con el propio botón:
 * los pseudoelementos hacen la de arriba y la de abajo, y un degradado de
 * fondo la del medio. Así el icono no depende de la geometría del bloque.
 *
 * El margen negativo saca del contenedor los 8px de aire que quedan a la
 * derecha de las barras: el borde de las barras cae en el margen del
 * contenido, igual que el logotipo por la izquierda, y el fondo del hover
 * sobresale un poco hacia el margen.
 *
 * El aspa del panel (más abajo) reutiliza estas medidas: --nf-burger fija la
 * caja de los dos botones y --nf-burger-bar la distancia de cada barra
 * exterior al centro.
 */
:root {
	--nf-burger: 40px;
	--nf-burger-bar: 7px;
}

.nf-nav .wp-block-navigation__responsive-container-open {
	background-image: linear-gradient(currentColor, currentColor);
	background-position: right 8px center;
	background-repeat: no-repeat;
	background-size: 14px 2px;
	block-size: var(--nf-burger);
	border-radius: var(--wp--custom--radius--md);
	inline-size: var(--nf-burger);
	margin-inline-end: -8px;
	position: relative;
	transition: background-color var(--wp--custom--transition);
}

.nf-nav .wp-block-navigation__responsive-container-open:hover {
	background-color: var(--wp--preset--color--surface);
}

.nf-nav .wp-block-navigation__responsive-container-open svg {
	display: none;
}

.nf-nav .wp-block-navigation__responsive-container-open::before,
.nf-nav .wp-block-navigation__responsive-container-open::after {
	background-color: currentColor;
	block-size: 2px;
	border-radius: 2px;
	content: "";
	inline-size: 20px;
	inset-block-start: calc(50% - 1px);
	inset-inline-end: 8px;
	position: absolute;
}

.nf-nav .wp-block-navigation__responsive-container-open::before {
	transform: translateY(calc(var(--nf-burger-bar) * -1));
}

.nf-nav .wp-block-navigation__responsive-container-open::after {
	transform: translateY(var(--nf-burger-bar));
}

/*
 * En modo de colores forzados el navegador sustituye los fondos, así que las
 * barras se quedarían invisibles. Se repintan con el color de texto del
 * sistema, que sí se respeta.
 */
@media (forced-colors: active) {
	.nf-nav .wp-block-navigation__responsive-container-open,
	.nf-nav .wp-block-navigation__responsive-container-close {
		background-image: linear-gradient(CanvasText, CanvasText);
	}

	.nf-nav .wp-block-navigation__responsive-container-open::before,
	.nf-nav .wp-block-navigation__responsive-container-open::after,
	.nf-nav .wp-block-navigation__responsive-container-close::before,
	.nf-nav .wp-block-navigation__responsive-container-close::after {
		background-color: CanvasText;
	}
}

/*
 * Menú desplegable en móvil.
 *
 * El panel repite la geometría de la cabecera para que abrirlo no parezca un
 * cambio de página: logotipo a la izquierda, aspa justo donde estaba el botón
 * de menú y un filete a la altura del borde de la barra. Debajo, los enlaces
 * en filas grandes con su número en mono y una flecha, y al pie las dos
 * salidas —Contacto y Área clientes— como botones.
 *
 * El núcleo solo pone la lista y el aspa; lo demás sale de pseudoelementos,
 * así que no hay que tocar el marcado del bloque. Todo cuelga de .is-menu-open
 * y no afecta al menú horizontal.
 *
 * --nf-menu-top es el hueco que deja la caja del botón de menú centrada en la
 * barra: con ese relleno superior el aspa cae encima de él. En horizontal ya
 * coinciden, porque el panel usa el mismo margen lateral que la cabecera. Con
 * la barra de WordPress el núcleo baja el diálogo lo mismo que baja la
 * cabecera; el filete lo sigue con sus propias reglas.
 */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open {
	--nf-menu-top: calc((var(--nf-header-height) - var(--nf-burger)) / 2);
	background-color: var(--wp--preset--color--base);
	padding-bottom: calc(var(--wp--preset--spacing--40) + env(safe-area-inset-bottom, 0px));
	padding-top: var(--nf-menu-top);
}

/* Filete a la altura del borde inferior de la cabecera, de lado a lado. */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open::before {
	background-color: var(--wp--preset--color--border);
	block-size: 1px;
	content: "";
	inset-block-start: var(--nf-header-height);
	inset-inline: 0;
	position: absolute;
}

.admin-bar .nf-nav .wp-block-navigation__responsive-container.is-menu-open::before {
	inset-block-start: calc(var(--nf-header-height) + 46px);
}

@media (min-width: 782px) {
	.admin-bar .nf-nav .wp-block-navigation__responsive-container.is-menu-open::before {
		inset-block-start: calc(var(--nf-header-height) + 32px);
	}
}

/*
 * La malla de plano del hero, en la parte baja y fundida hacia arriba, detrás
 * de los botones. z-index negativo: el panel es fixed con z-index, así que
 * forma su propio contexto y la malla queda sobre su fondo pero por debajo
 * del contenido.
 */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open::after {
	background-image:
		linear-gradient(to right, rgba(11, 21, 51, 0.045) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(11, 21, 51, 0.045) 1px, transparent 1px);
	background-position: center bottom;
	background-size: 64px 64px;
	block-size: 40%;
	content: "";
	inset-block-end: 0;
	inset-inline: 0;
	-webkit-mask-image: linear-gradient(to top, #000 10%, transparent);
	mask-image: linear-gradient(to top, #000 10%, transparent);
	pointer-events: none;
	position: absolute;
	z-index: -1;
}

/*
 * Logotipo decorativo: el de verdad sigue en la cabecera, tapado por el panel.
 * Mismo alto y misma posición que aquel —28px, centrado en la barra—, medida
 * desde el diálogo, que empieza --nf-menu-top más abajo.
 */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog::before {
	background: url("assets/img/logo-dark.png") no-repeat left center / contain;
	block-size: 1.75rem;
	content: "";
	inline-size: calc(1.75rem * 382 / 69);
	inset-block-start: calc((var(--nf-burger) - 1.75rem) / 2);
	inset-inline-start: 0;
	position: absolute;
}

/*
 * El aspa ocupa la misma caja de 40px que el botón de menú, en el mismo sitio
 * (también con los 8px hacia fuera), y parte de su dibujo: al abrir, las
 * barras de arriba y de abajo bajan y suben al centro girando hasta cruzarse
 * y la del medio se recoge hacia la derecha.
 *
 * Las barras giran sobre su centro, no sobre el extremo derecho: dos barras
 * alineadas a la derecha que giran sobre ese extremo se juntan en un «>», no
 * en una X. Por eso el aspa queda centrada en la caja y el recorrido incluye
 * los 2px que las barras del menú están desplazadas hacia la derecha.
 */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
	background-image: linear-gradient(currentColor, currentColor);
	background-position: right 8px center;
	background-repeat: no-repeat;
	background-size: 0 2px;
	block-size: var(--nf-burger);
	border-radius: var(--wp--custom--radius--md);
	inline-size: var(--nf-burger);
	right: -8px;
	transition: background-color var(--wp--custom--transition);
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close:hover {
	background-color: var(--wp--preset--color--surface);
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close svg {
	display: none;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close::before,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close::after {
	background-color: currentColor;
	block-size: 2px;
	border-radius: 2px;
	content: "";
	inline-size: 20px;
	inset-block-start: calc(50% - 1px);
	inset-inline-start: calc(50% - 10px);
	position: absolute;
	transform: translate(0, 0) rotate(45deg);
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close::after {
	transform: translate(0, 0) rotate(-45deg);
}

/*
 * La cadena de cajas del núcleo se estira hasta el alto del panel para que los
 * botones puedan irse al pie; si no caben, el panel hace scroll como siempre.
 * La lista se alinea a la izquierda aunque el menú de escritorio vaya
 * centrado, y en tableta no pasa de 36rem para que la flecha no se aleje.
 */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-close,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
	align-items: stretch;
	display: flex;
	flex: 1 0 auto;
	flex-direction: column;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
	padding-top: calc(var(--nf-header-height) + var(--wp--preset--spacing--30) - var(--nf-menu-top));
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
	gap: 0;
	inline-size: 100%;
	max-inline-size: 36rem;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
	align-items: stretch;
	border-block-end: 1px solid var(--wp--preset--color--border);
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	align-items: baseline;
	color: var(--wp--preset--color--contrast);
	display: flex;
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 600;
	gap: 1rem;
	letter-spacing: -0.015em;
	line-height: 1.2;
	padding-block: 1.125rem;
	transition: color var(--wp--custom--transition);
}

/* La misma flecha de texto que los enlaces «Ver…» de Servicios y Partner. */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content::after {
	color: var(--wp--preset--color--muted);
	content: "\2192";
	content: "\2192" / "";
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 400;
	margin-inline-start: auto;
	transition: color var(--wp--custom--transition),
		transform var(--wp--custom--transition);
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:hover,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:focus-visible,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .current-menu-item > .wp-block-navigation-item__content,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:hover::after,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:focus-visible::after,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .current-menu-item > .wp-block-navigation-item__content::after {
	color: var(--wp--preset--color--contrast);
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:hover::after,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content:focus-visible::after {
	transform: translateX(3px);
}

/*
 * «Servicios» en el panel: fila plegable con las cinco páginas dentro, como el
 * acordeón de la maqueta de referencia.
 *
 * El núcleo, dentro del panel, esconde el botón de la flecha y deja el submenú
 * siempre desplegado. Aquí se hace lo contrario: vuelve el botón —que ya trae
 * su aria-expanded y su lógica— y el submenú se muestra solo cuando está
 * abierto. Toda la mecánica sigue siendo suya; esto es CSS.
 *
 * Los selectores son largos porque las reglas del núcleo para el panel llevan
 * cuatro y cinco clases: hay que ganarlas por especificidad, sin !important.
 *
 * La fila pasa a rejilla de dos columnas: el enlace ocupa la primera —sigue
 * llevando a la sección de servicios de la portada—, el botón la segunda y el
 * submenú la fila entera de debajo. El selector de esa rejilla pide además
 * .wp-block-navigation-item porque el núcleo copia la clase del bloque en el
 * <ul> del submenú, y sin ese apellido la lista también se partiría en dos
 * columnas.
 */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .nf-nav__servicios.wp-block-navigation-item {
	align-items: center;
	display: grid;
	grid-template-columns: 1fr auto;
}

/* Sin la flecha de las demás filas: en la de «Servicios» la marca el chevron
   del botón, y las de dentro no la llevan. */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__servicios > .wp-block-navigation-item__content::after,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-sub > .wp-block-navigation-item__content::after {
	content: none;
}

/* El botón se estira a lo alto y a lo ancho de la fila —el título ya no es
   enlace, así que no le quita sitio a nada— y deja el chevron a la derecha,
   donde las demás filas llevan su flecha. */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .nf-nav__servicios > .wp-block-navigation__submenu-icon {
	align-items: center;
	align-self: stretch;
	background-color: transparent;
	border: 0;
	color: var(--wp--preset--color--muted);
	cursor: pointer;
	display: flex;
	inline-size: 5rem;
	justify-content: flex-end;
	padding: 0;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__servicios > .wp-block-navigation-item__content {
	cursor: default;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__servicios > .wp-block-navigation__submenu-icon svg {
	block-size: 20px;
	inline-size: 20px;
}

/* Cerrado y abierto. El núcleo ya gira el chevron con [aria-expanded="true"]. */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .nf-nav__servicios > .wp-block-navigation__submenu-container {
	display: none;
	gap: 0;
	grid-column: 1 / -1;
	padding: 0 0 0.75rem;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .nf-nav__servicios > .wp-block-navigation-submenu__toggle[aria-expanded="true"] ~ .wp-block-navigation__submenu-container {
	display: flex;
}

/* Filas del submenú: sangradas bajo su título, sin el filete ni el tamaño de
   las de primer nivel. La línea de apoyo se queda fuera —cinco descripciones
   más harían del panel una lista interminable—; en el panel de escritorio sí
   sale. */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__servicios .nf-sub.wp-block-navigation-item {
	border-block-end: 0;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__servicios > .wp-block-navigation__submenu-container > .nf-sub.wp-block-navigation-item > .wp-block-navigation-item__content {
	align-items: center;
	column-gap: 0.75rem;
	display: grid;
	grid-template-columns: 1.125rem 1fr;
	inline-size: auto;
	padding: 0.75rem 0 0.75rem 0.5rem;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__servicios .nf-sub .wp-block-navigation-item__label {
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 500;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__servicios .nf-sub .wp-block-navigation-item__description {
	display: none;
}

/* Sin JavaScript el botón del núcleo no abre nada: la lista se queda tendida,
   que es preferible a dejar las cinco páginas fuera de alcance. */
@media (scripting: none) {
	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .nf-nav__servicios > .wp-block-navigation__submenu-container {
		display: flex;
	}

	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .nf-nav__servicios > .wp-block-navigation__submenu-icon {
		display: none;
	}
}

/*
 * Salidas al pie, en neutros como el resto de la cabecera. Contacto, en negro
 * (blanco sobre #0B0C10: 19,55:1; sobre #2E323B en hover: 12,84:1); Área
 * clientes, en claro con borde, para que no haya dos botones iguales (negro
 * sobre #F6F7F9: 18,24:1; sobre #E8EAEF en hover: 16,24:1).
 * El borde transparente es para colores forzados: ahí el fondo desaparece y
 * el borde es lo que sigue dibujando el botón.
 */
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__contacto {
	margin-block-start: auto;
	padding-block-start: var(--wp--preset--spacing--50);
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__cta {
	padding-block-start: 0.75rem;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open :is(.nf-nav__contacto, .nf-nav__cta) {
	border-block-end: 0;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open :is(.nf-nav__contacto, .nf-nav__cta) > .wp-block-navigation-item__content {
	background-color: var(--wp--preset--color--contrast);
	border: 1px solid transparent;
	border-radius: var(--wp--custom--radius--sm);
	color: #FFFFFF;
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 600;
	justify-content: center;
	letter-spacing: -0.005em;
	padding: 0.9375rem 1.5rem;
	transition: background-color var(--wp--custom--transition);
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open :is(.nf-nav__contacto, .nf-nav__cta) > .wp-block-navigation-item__content::after {
	content: none;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__contacto > .wp-block-navigation-item__content:hover,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__contacto > .wp-block-navigation-item__content:focus-visible,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__contacto.current-menu-item > .wp-block-navigation-item__content {
	background-color: #2E323B;
	color: #FFFFFF;
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__cta > .wp-block-navigation-item__content {
	background-color: var(--wp--preset--color--surface);
	border-color: var(--wp--custom--border-strong);
	color: var(--wp--preset--color--contrast);
}

.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__cta > .wp-block-navigation-item__content:hover,
.nf-nav .wp-block-navigation__responsive-container.is-menu-open .nf-nav__cta > .wp-block-navigation-item__content:focus-visible {
	background-color: var(--wp--preset--color--border);
	color: var(--wp--preset--color--contrast);
}

/*
 * Entrada: las filas suben escalonadas y el aspa se forma desde las barras
 * del botón de menú (a 5,25px por encima y por debajo del centro). Solo con
 * movimiento permitido; sin él, todo aparece ya en su sitio.
 */
@media (prefers-reduced-motion: no-preference) {
	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
		animation: nf-menu-fila 420ms cubic-bezier(0.22, 1, 0.36, 1) 60ms both;
	}

	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:nth-child(2) {
		animation-delay: 95ms;
	}

	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:nth-child(3) {
		animation-delay: 130ms;
	}

	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:nth-child(4) {
		animation-delay: 165ms;
	}

	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:nth-child(5) {
		animation-delay: 200ms;
	}

	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:nth-child(6) {
		animation-delay: 235ms;
	}

	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:nth-child(n+7) {
		animation-delay: 270ms;
	}

	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
		animation: nf-menu-aspa-medio 200ms ease-out both;
	}

	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close::before {
		animation: nf-menu-aspa-a 350ms cubic-bezier(0.22, 1, 0.36, 1) both;
	}

	.nf-nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close::after {
		animation: nf-menu-aspa-b 350ms cubic-bezier(0.22, 1, 0.36, 1) both;
	}
}

@keyframes nf-menu-fila {
	from {
		opacity: 0;
		transform: translateY(12px);
	}

	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* Las barras del menú están 2px a la derecha del centro de la caja. */
@keyframes nf-menu-aspa-a {
	from {
		transform: translate(2px, calc(var(--nf-burger-bar) * -1)) rotate(0deg);
	}

	to {
		transform: translate(0, 0) rotate(45deg);
	}
}

@keyframes nf-menu-aspa-b {
	from {
		transform: translate(2px, var(--nf-burger-bar)) rotate(0deg);
	}

	to {
		transform: translate(0, 0) rotate(-45deg);
	}
}

@keyframes nf-menu-aspa-medio {
	from {
		background-size: 14px 2px;
	}

	to {
		background-size: 0 2px;
	}
}

/*
 * Hasta dónde llega el desplegable. El núcleo saca el menú horizontal a partir
 * de 600 px, pero ahí no cabía: se partía en varias filas y la barra llegaba a
 * medir 274 px de alto. Las dos reglas de dentro son las suyas, devueltas a su
 * estado anterior; llevan .nf-nav delante para ganar en especificidad sin tocar
 * el bloque.
 *
 * El umbral estuvo en 1000 px mientras el menú tenía seis enlaces (pedían unos
 * 850 px). Al quitar «Soporte» y «Preguntas» (16/09/2026) quedan cuatro —
 * Servicios, Cómo trabajamos, Proyectos y Contacto— y la cuenta baja a unos
 * 815: logotipo 155 + enlaces con sus huecos 400 + botón 130, más los márgenes
 * de la página. Así que el corte pasa a 900 px (56,25em), que deja el menú
 * completo en tabletas apaisadas con unos 85 px de holgura.
 *
 * Es una estimación, no una medida: si en el navegador la barra se parte en dos
 * filas cerca de los 900 px, súbelo un poco. El número vive en los tres @media
 * de aquí abajo y en el del panel de «Servicios» (sección 5).
 *
 * De 900 a 1200 px los enlaces van más juntos —1rem en vez de 1,5— para ganar
 * ese margen justo donde escasea; de ahí en adelante vuelve el hueco de siempre.
 */
@media (min-width: 56.25em) and (max-width: 74.99em) {
	.nf-nav .wp-block-navigation__container {
		gap: 1rem;
	}
}

@media (min-width: 600px) and (max-width: 56.24em) {
	.nf-nav .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}

	.nf-nav .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}
}

/*
 * Mientras el menú es un desplegable, la cabecera se queda en dos piezas:
 * logotipo y botón de menú. El botón «Área clientes» se retira de la barra y
 * sigue disponible como último enlace dentro del desplegable.
 *
 * El selector del botón lleva tres clases porque el layout flex del núcleo
 * (.wp-block-buttons.is-layout-flex) también declara display.
 */
@media (max-width: 56.24em) {
	.nf-header__inner {
		grid-template-columns: 1fr auto;
	}

	.nf-header__inner .wp-block-buttons.nf-header__cta {
		display: none;
	}
}

/*
 * Con el menú horizontal el botón «Área clientes» ya está en la barra, así que
 * su enlace gemelo dentro del desplegable sobra.
 *
 * El selector es largo a propósito: el núcleo declara el display de los
 * elementos del menú desde dentro de .is-menu-open, y con menos clases la
 * regla no ganaba y el enlace salía duplicado.
 */
@media (min-width: 56.25em) {
	.nf-nav .wp-block-navigation__responsive-container .nf-nav__cta.wp-block-navigation-item {
		display: none;
	}
}

/* ---------------------------------------------------------------------------
   6. Hero
   --------------------------------------------------------------------------- */

/*
 * Degradado claro: blanco bajo la cabecera y gris azulado hacia abajo.
 *
 * El primer tramo es blanco plano, no un degradado que ya empieza a teñir: así
 * la cabecera transparente se apoya en blanco limpio. Retiré el halo de marca
 * que había detrás del titular porque, con el blanco arriba, un velo azul en la
 * parte superior iba justo en contra.
 *
 * Termina en #EDF1F9 y no más claro para que el corte con la banda siguiente
 * (#F6F7F9) lo marque el propio salto de tono. Sobre ese fondo la entradilla en
 * gris da 4,82:1, así que sigue cumpliendo AA.
 */
.nf-hero {
	/*
	 * Ocupa siempre la altura visible. En svh y no en vh: en móvil, vh mide la
	 * ventana con la barra del navegador retraída, así que con la barra a la
	 * vista el hero se saldría por abajo. svh usa la ventana más pequeña
	 * posible, de modo que entra siempre y no da saltos cuando la barra
	 * aparece o desaparece. La primera declaración queda de reserva para
	 * navegadores sin svh.
	 */
	min-height: 100vh;
	min-height: 100svh;

	/*
	 * El relleno superior incluye la altura de la cabecera superpuesta y el
	 * inferior no. Esa asimetría es justo lo que centra el contenido en el
	 * hueco que se ve —del borde de la barra al final del hero— y no en la
	 * caja entera.
	 */
	padding-block: calc(var(--nf-header-height) + var(--wp--preset--spacing--60))
		var(--wp--preset--spacing--60);

	/* Centrado vertical; al ser min-height, si el contenido crece el hero crece. */
	display: flex;
	flex-direction: column;
	justify-content: center;

	background-image:
		linear-gradient(180deg, #FFFFFF 0%, #FFFFFF 22%, #F7FAFD 52%, #EDF1F9 100%);
	overflow: hidden;
	position: relative;

	/*
	 * Velo que apaga la malla alrededor del texto (ver .nf-hero::after).
	 *
	 * La malla vive en los bordes y en el fondo, y se atenúa en una elipse
	 * alrededor del texto. Antes era lo contrario —densa arriba, apagada justo
	 * donde está el titular—, lo que dejaba liso todo el tercio inferior del
	 * hero a pantalla completa.
	 *
	 * En el centro tapa el 75 % y no el 100 %, para que el fondo del túnel se
	 * intuya detrás del titular. Medido con la malla aclarada hacia el fondo:
	 * donde una línea cruza la zona del texto, la entradilla gris sigue por
	 * encima de 4,6:1, y el velo apenas influye (el peor punto está en su
	 * borde, no en el centro).
	 */
	--nf-hero-veil: radial-gradient(62% 50% at 50% 52%, rgba(0, 0, 0, 0.75) 30%, transparent 82%);
}

/*
 * La malla, en líneas oscuras sobre el fondo claro, va en perspectiva (ver
 * .nf-hero::before) y el velo la retira del centro para que no compita con el
 * texto.
 */
/* Con sesión iniciada, la barra de WordPress se come ese alto de ventana. */
.admin-bar .nf-hero {
	min-height: calc(100vh - 32px);
	min-height: calc(100svh - 32px);
}

@media (max-width: 782px) {
	.admin-bar .nf-hero {
		min-height: calc(100vh - 46px);
		min-height: calc(100svh - 46px);
	}
}

/*
 * Malla en perspectiva: un túnel visto desde dentro, con la referencia de
 * diseños/rejilla.png. La pared del fondo es un rectángulo pequeño (el 12 %
 * de cada lado) algo desplazado a la izquierda y abajo: el punto de fuga está
 * al 42 % del ancho y al 56 % del alto. Techo, suelo y paredes fugan hacia él
 * desde los bordes, que hacen de boca. No se aleja más del centro para que
 * las celdas de las cuatro paredes se parezcan: al 33 % / 64 % la pared
 * derecha las tenía casi tres veces más grandes que el suelo.
 *
 * Es un dibujo y no planos girados con transform 3D: la proyección se calcula
 * una vez (assets/img/malla-perspectiva.svg), pesa unos 3 KB, la comparten
 * todas las aperturas y no depende del alto de cada hero. Los anillos de
 * profundidad van en progresión geométrica (escala 0,9^i, veinte pasos hasta
 * el fondo, que queda al 12 %).
 *
 * Cada pared lleva su propio número de líneas de fuga. Los anillos son
 * comunes, pero la profundidad de la primera fila en pantalla es proporcional
 * a lo lejos que queda cada borde del punto de fuga: con las mismas divisiones
 * en todas, las celdas junto a la boca salían estiradas. Cada pared se divide
 * para que esa primera fila sea cuadrada: techo 32, suelo 40, pared izquierda
 * 13 y derecha 10 en el apaisado (celdas de unos 50, 40, 69 y 90 px en un
 * hero de 1600 × 900).
 *
 * Se estira a la caja del hero (preserveAspectRatio="none"), lo que sigue
 * siendo una perspectiva correcta: el fondo toma la proporción del hero, como
 * lo haría un túnel cuya boca es la ventana. Las líneas no engordan al
 * estirarse por vector-effect="non-scaling-stroke". En pantallas en vertical
 * se usa una versión calculada igual para 900 × 1600 (techo 10, suelo 13,
 * izquierda 42, derecha 31), para que las celdas no salgan como tiras.
 *
 * El lienzo es algo mayor que el hero: el hero ampliado 1/0,81 desde el punto
 * de fuga, con dos anillos más por fuera. Lo pide la entrada (ver nf-tunel),
 * que arranca con la malla a 0,81 y sin ese sobrante dejaría los bordes en
 * blanco. De ahí los márgenes negativos, que son (1/0,81 − 1) por la distancia
 * de cada borde al punto de fuga, y el hero recorta lo que sobra.
 *
 * Aclarado hacia el fondo, como la niebla de un pasillo largo: la máscara deja
 * las líneas enteras en la boca y las atenúa hasta el 25 % en el punto de
 * fuga. Hacia el fondo se juntan unas veinte líneas en cada sentido y, con
 * todas a la misma intensidad, formaban una mancha gris detrás del titular.
 * Son dos degradados lineales, uno a lo ancho y otro a lo alto, sumados: se
 * aproximan a la forma rectangular de los anillos mejor que un radial. Los
 * porcentajes son los bordes del hero dentro del lienzo (7,98 % y 88,98 % a lo
 * ancho, 10,64 % y 91,64 % a lo alto) y el punto de fuga; 0,134 en cada uno da
 * 0,25 al sumarse. Todas las líneas, aristas incluidas, van al 5,5 %: con más,
 * las aristas de las esquinas bajaban la entradilla a 4,3:1 donde la cruzan.
 */
.nf-hero::before {
	background: url("assets/img/malla-perspectiva.svg") no-repeat 0 0 / 100% 100%;
	content: "";
	inset: -13.14% -13.6% -10.32% -9.85%;
	-webkit-mask-image:
		linear-gradient(to right, #000 7.98%, rgba(0, 0, 0, 0.134) 42%, #000 88.98%),
		linear-gradient(to bottom, #000 10.64%, rgba(0, 0, 0, 0.134) 56%, #000 91.64%);
	mask-image:
		linear-gradient(to right, #000 7.98%, rgba(0, 0, 0, 0.134) 42%, #000 88.98%),
		linear-gradient(to bottom, #000 10.64%, rgba(0, 0, 0, 0.134) 56%, #000 91.64%);
	pointer-events: none;
	position: absolute;
}

@media (orientation: portrait) {
	.nf-hero::before {
		background-image: url("assets/img/malla-perspectiva-vertical.svg");
	}
}

/*
 * Entrada al túnel. Al cargar, la malla avanza dos anillos (de 0,81 a 1 desde
 * el punto de fuga) mientras aparece, frena al final y se queda quieta. Como
 * cada anillo mide el 90 % del anterior, al terminar todo cae exactamente en
 * el dibujo en reposo.
 *
 * Una sola vez y no en bucle: dura menos de 5 s, así que no necesita control
 * para pausarla (WCAG 2.2.2), y la calma posterior casa con lo que vende la
 * marca. 2,8 s con una curva que hace casi todo el recorrido en el primer
 * segundo; la aparición, 1,2 s. Solo se anima transform y opacity, que
 * resuelve el compositor.
 *
 * Solo sin preferencia de movimiento reducido: con ella la malla está quieta
 * desde el principio. El origen es el punto de fuga dentro del lienzo, que
 * coincide con el del hero (42 %, 56 %); si se regenera el dibujo con otro,
 * hay que cambiarlo aquí.
 */
@media (prefers-reduced-motion: no-preference) {
	.nf-hero::before,
	.nf-page-hero::before {
		animation:
			nf-tunel 3.3s cubic-bezier(0.16, 1, 0.3, 1) both,
			nf-tunel-luz 1.7s ease-out both;
		transform-origin: 42% 56%;
	}
}

@keyframes nf-tunel {
	from {
		transform: scale(0.81);
	}

	to {
		transform: scale(1);
	}
}

@keyframes nf-tunel-luz {
	from {
		opacity: 0;
	}

	to {
		opacity: 1;
	}
}

/*
 * El velo: una copia del fondo del propio hero, opaca en la elipse del texto y
 * transparente hacia los bordes, pintada encima de la malla y por debajo del
 * contenido.
 */
.nf-hero::after {
	background-image: inherit;
	content: "";
	inset: 0;
	-webkit-mask-image: var(--nf-hero-veil);
	mask-image: var(--nf-hero-veil);
	pointer-events: none;
	position: absolute;
}

.nf-hero > * {
	position: relative;
	z-index: 1;
}

/* ---------------------------------------------------------------------------
   7. Partner técnico: garantías
   --------------------------------------------------------------------------- */

/*
 * Reparto editorial en dos columnas, con la geometría del «editorial split» de
 * diseños/diseno: columnas iguales, la izquierda fija mientras se leen las
 * filas de la derecha y todo apilado por debajo de 48em (768px).
 *
 * Adaptaciones a los tokens del tema: el hueco de 64px es spacing-60 (que
 * llega a 4rem en escritorio) y el top: 100px del sticky se calcula desde la
 * altura real de nuestra cabecera. El titular no toma el tamaño display del
 * diseño: igualaba al h1 del hero y rompía la jerarquía, así que usa el h2 del
 * resto de secciones.
 *
 * La disposición «flujo» del núcleo mete margen superior a cada hermano, y
 * dentro de la rejilla descuadra la segunda columna: se anula aquí.
 */
.nf-split {
	align-items: start;
	display: grid;
	gap: var(--wp--preset--spacing--50);
	grid-template-columns: minmax(0, 1fr);
}

.nf-split > * {
	margin-block: 0;
}

@media (min-width: 48em) {
	.nf-split {
		gap: var(--wp--preset--spacing--60);
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.nf-split__intro {
		position: sticky;
		top: calc(var(--nf-header-height) + 2.25rem);
	}
}

.admin-bar .nf-split__intro {
	top: calc(var(--nf-header-height) + 2.25rem + 32px);
}

/*
 * Segundo tramo del titular en color de acento, como el <em> del h1 del hero.
 * Va en línea y no en bloque: así el titular se reparte con el ancho de la
 * columna y el tramo puede partirse, en lugar de forzar una línea propia.
 *
 * Sobre oscuro, el acento on-dark da 5,01:1 en la parada más clara del
 * degradado.
 */
.nf-split__intro h2 em {
	color: var(--wp--preset--color--brand);
	font-style: normal;
}

.nf-on-dark .nf-split__intro h2 em {
	color: var(--wp--custom--on-dark--accent);
}

/*
 * Las garantías: filas con filete arriba y abajo de la lista y entre cada una.
 * Cabeza en línea (icono de 20px, 10px de hueco y título en Bricolage
 * Grotesque, como en el diseño) y el texto sangrado para arrancar justo donde
 * empieza el título. El diseño sangra 34px; aquí sale de sumar icono y hueco,
 * así que no se descuadra si cambia uno de los dos.
 *
 * En la home va sobre el degradado profundo (.nf-on-dark); los colores claros
 * de la base quedan para usarla sobre fondo claro.
 *
 * Contraste sobre fondo claro (#F6F7F9): título 18,24:1, texto muted 5,09:1,
 * enlace en azul de marca 4,82:1 y 6,25:1 en hover.
 *
 * Sobre el degradado profundo, medido en la parada más clara (#1E3A8A), que
 * es el peor caso: título blanco 10,36:1, texto on-dark muted 5,21:1, enlace
 * blanco 10,36:1 y en hover on-dark accent 5,01:1, igual que el icono.
 */
.nf-assurances {
	--nf-assurance-icon: 20px;
	--nf-assurance-gap: 10px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-assurance {
	align-items: center;
	border-bottom: 1px solid var(--wp--custom--border-strong);
	column-gap: var(--nf-assurance-gap);
	display: grid;
	grid-template-columns: var(--nf-assurance-icon) minmax(0, 1fr);
	padding-block: 1.375rem;
}

.nf-assurance:first-child {
	border-top: 1px solid var(--wp--custom--border-strong);
}

.nf-assurance__text,
.nf-assurance__link {
	grid-column: 2;
}

.nf-assurance__icon {
	color: var(--wp--preset--color--brand);
	line-height: 0;
}

.nf-assurance__icon svg {
	display: block;
}

.nf-assurance__title {
	font-family: var(--wp--preset--font-family--bricolage);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 600;
	letter-spacing: 0;
	line-height: 1.3;
	margin: 0;
}

.nf-assurance__text {
	color: var(--wp--preset--color--muted);
	line-height: 1.6;
	margin: 0.5rem 0 0;
}

/* Enlace suelto, como el de las tarjetas de servicios: sin subrayado y con la
   flecha que avanza al pasar. */
.nf-assurance__link {
	align-items: center;
	color: var(--wp--preset--color--brand);
	display: inline-flex;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	gap: 0.5rem;
	justify-self: start;
	margin-block-start: 0.75rem;
	text-decoration: none;
	transition: color var(--wp--custom--transition);
}

.nf-assurance__link:hover,
.nf-assurance__link:focus-visible {
	color: var(--wp--custom--brand-dark);
	text-decoration: none;
}

.nf-assurance__link span {
	transition: transform var(--wp--custom--transition);
}

.nf-assurance__link:hover span,
.nf-assurance__link:focus-visible span {
	transform: translateX(3px);
}

/*
 * Sobre oscuro. El texto necesita el selector compuesto: .nf-on-dark :where(p)
 * y .nf-assurance__text empatan en especificidad y ganaría el gris claro de
 * aquí, que va después. El enlace ya lo resuelve la regla general de enlaces
 * sobre oscuro (blanco y acento al pasar).
 */
.nf-on-dark .nf-assurance,
.nf-on-dark .nf-assurance:first-child {
	border-color: var(--wp--custom--on-dark--border);
}

.nf-on-dark .nf-assurance__icon {
	color: var(--wp--custom--on-dark--accent);
}

.nf-on-dark .nf-assurance__text {
	color: var(--wp--custom--on-dark--muted);
}

@media (forced-colors: active) {
	.nf-split__intro h2 em {
		color: CanvasText;
	}
}

/* ---------------------------------------------------------------------------
   8. Servicios: rejilla de tarjetas
   --------------------------------------------------------------------------- */

/*
 * Calca la maqueta de diseños/servicios.jpg en la disposición: tres tarjetas
 * arriba y dos más anchas abajo.
 *
 * En reposo todas las tarjetas comparten fondo: el gris de superficie de las
 * demás secciones, con el color de texto normal para el título y el color de
 * su categoría para los toques (icono, checks y enlace). Al pasar por encima,
 * cada una invierte el contraste sobre un degradado oscuro de ese mismo color, con la misma receta que el
 * degradado profundo de la banda de contacto: tres paradas a 160°.
 *
 * Los colores de cada pieza se declaran como propiedades locales y el hover
 * solo las reasigna: las piezas llevan transition sobre color, así que el
 * cambio de valor de la propiedad se anima igual que un cambio directo.
 *
 * En hover los grises son blanco translúcido y no un tono fijo: un gris
 * azulado se veía sucio sobre el rojo o el ámbar, y en el verde no llegaba a
 * AA. El blanco translúcido toma el matiz de cada fondo.
 *
 * Contraste en hover, medido sobre la parada más clara de cada degradado, que
 * es el peor caso:
 *
 *   categoría     parada clara   blanco   blanco 88%   blanco 76%
 *                                título   lista        descripción
 *   desarrollo    #1E3A8A        10,36     8,38         6,72
 *   hosting       #065F46         7,68     6,36         5,19
 *   e-commerce    #4C1D95        10,95     8,80         6,94
 *   IA y datos    #78350F         9,07     7,43         5,99
 *   seguridad     #7F1D1D        10,02     8,07         6,38
 *
 * En reposo, sobre #F6F7F9, el título da 18,24:1 y el texto muted 5,09:1. Los
 * acentos de cada categoría:
 *
 *   categoría     acento
 *   desarrollo    #1D4ED8   6,25:1
 *   hosting       #047857   5,12:1
 *   e-commerce    #6D28D9   6,63:1
 *   IA y datos    #B45309   4,68:1
 *   seguridad     #B91C1C   6,04:1
 *
 * (Mínimos AA: 4,5:1 para texto; 3:1 para el icono.)
 *
 * Las categorías no reasignan --nf-accent directamente sino --nf-cat-accent,
 * que la tarjeta lee con el azul de marca como respaldo. Así no compiten en
 * especificidad con el hover, que es quien reasigna --nf-accent a blanco, y
 * una tarjeta sin categoría sigue funcionando.
 */

.nf-service--desarrollo {
	--nf-cat-accent: #1D4ED8;
	--nf-gradient: linear-gradient(160deg, #0B1533 0%, #15295C 62%, #1E3A8A 100%);
}

.nf-service--hosting {
	--nf-cat-accent: #047857;
	--nf-gradient: linear-gradient(160deg, #022C22 0%, #064E3B 62%, #065F46 100%);
}

.nf-service--ecommerce {
	--nf-cat-accent: #6D28D9;
	--nf-gradient: linear-gradient(160deg, #1E0B4B 0%, #3B1880 62%, #4C1D95 100%);
}

.nf-service--ia {
	--nf-cat-accent: #B45309;
	--nf-gradient: linear-gradient(160deg, #2B1103 0%, #5C2A0B 62%, #78350F 100%);
}

.nf-service--seguridad {
	--nf-cat-accent: #B91C1C;
	--nf-gradient: linear-gradient(160deg, #2D0707 0%, #651919 62%, #7F1D1D 100%);
}

.nf-services {
	display: grid;
	gap: var(--wp--preset--spacing--40);
	grid-template-columns: 1fr;
	list-style: none;
	margin: 0;
	padding: 0;
}

/*
 * Desde tablet, dos por fila. La quinta no tiene pareja, así que ocupa el
 * ancho entero en lugar de dejar un hueco.
 */
@media (min-width: 40em) {
	.nf-services {
		grid-template-columns: repeat(2, 1fr);
	}

	.nf-services > :nth-child(5) {
		grid-column: 1 / -1;
	}
}

/* En escritorio, el reparto de la maqueta: tres arriba y dos abajo sobre una
   rejilla de seis columnas. Está pensado para cinco tarjetas. */
@media (min-width: 62em) {
	.nf-services {
		grid-template-columns: repeat(6, 1fr);
	}

	.nf-services > * {
		grid-column: span 2;
	}

	.nf-services > :nth-child(4),
	.nf-services > :nth-child(5) {
		grid-column: span 3;
	}
}

/*
 * La tarjeta es contenedor de consulta: su reparto interno depende de lo que
 * mide ella, no de la ventana. Una misma tarjeta es estrecha en escritorio
 * pequeño y ancha en tablet, y las consultas por ventana obligaban a perseguir
 * cada caso con nth-child.
 *
 * El contenido va en .nf-service__inner porque una consulta de contenedor no
 * puede dar estilo al propio contenedor, solo a lo que lleva dentro.
 */
.nf-service {
	--nf-title: var(--wp--preset--color--contrast);
	--nf-body: var(--wp--preset--color--muted);
	--nf-item: var(--wp--preset--color--contrast);
	--nf-accent: var(--nf-cat-accent, var(--wp--preset--color--brand));
	--nf-fade: 240ms cubic-bezier(0.2, 0.6, 0.3, 1);

	background-color: var(--wp--preset--color--surface);
	border-radius: var(--wp--custom--radius--lg);
	container-type: inline-size;
	display: flex;
	flex-direction: column;
	isolation: isolate;
	padding: var(--wp--preset--spacing--50);
	position: relative;
	transition: box-shadow var(--nf-fade),
		transform var(--nf-fade);
}

/*
 * El degradado va en una capa aparte que se funde con opacity: un
 * background-image no se puede animar, así que cambiarlo directamente en el
 * hover sería un salto seco de gris a azul.
 *
 * Con el radio heredado, la capa sigue la esquina redondeada de la tarjeta.
 *
 * isolation encierra el z-index negativo dentro de la tarjeta: queda por
 * encima del fondo gris y por debajo del contenido.
 */
.nf-service::before {
	background-image: var(--nf-gradient, var(--wp--preset--gradient--deep));
	border-radius: inherit;
	content: "";
	inset: 0;
	opacity: 0;
	pointer-events: none;
	position: absolute;
	transition: opacity var(--nf-fade);
	z-index: -1;
}

.nf-service:hover,
.nf-service:focus-within {
	--nf-title: #FFFFFF;
	--nf-body: rgba(255, 255, 255, 0.76);
	--nf-item: rgba(255, 255, 255, 0.88);
	--nf-accent: #FFFFFF;

	box-shadow: var(--wp--preset--shadow--lift);
	/* Un acercamiento en lugar de la elevación de las demás tarjetas: con el
	   cambio a oscuro, la tarjeta viene hacia delante como un bloque. Va al
	   mismo ritmo que el fundido para que ambos cambios se lean como uno.
	   1,04 es el tope: en las tarjetas anchas de abajo son unos 13px por lado,
	   y la separación entre tarjetas es de 24px; más, y pisaría a la vecina.
	   El z-index la pone por delante mientras crece. */
	transform: scale(1.04);
	z-index: 1;
}

.nf-service:hover::before,
.nf-service:focus-within::before {
	opacity: 1;
}

/*
 * Dos repartos, según el ancho de la tarjeta:
 *
 *   estrecha (menos de 21rem)   todo apilado; la ilustración, bajo la lista
 *   a partir de 21rem           lista a la izquierda, ilustración a su derecha
 *
 * Las cinco tarjetas comparten estructura sea cual sea su ancho: las dos
 * anchas de abajo no pasan la ilustración a una columna propia, porque eso las
 * hacía parecer otro componente al lado de las tres de arriba. La estrecha
 * solo aparece cuando la lista ya no cabe junto a la ilustración sin partir
 * «Aplicaciones a medida».
 *
 * La última fila es flexible y el enlace se apoya en su fondo: así, en una
 * misma fila de tarjetas, todos los enlaces quedan alineados abajo aunque los
 * textos midan distinto.
 */
.nf-service__inner {
	column-gap: var(--wp--preset--spacing--40);
	display: grid;
	flex: 1 1 auto;
	grid-template-areas:
		"head"
		"text"
		"list"
		"art"
		"link";
	grid-template-columns: minmax(0, 1fr);
	grid-template-rows: auto auto auto auto 1fr;
}

/*
 * Título a la izquierda e icono a su derecha, en una cabecera propia. Si el
 * icono fuera una celda más de la rejilla compartiría columna con la
 * ilustración, que mide 8rem, y le robaría ese ancho al título aunque el icono
 * solo ocupe 3rem.
 *
 * El icono se centra en vertical respecto al bloque del título completo: con
 * títulos de una línea queda a la altura del renglón, y con los de dos, entre
 * ambos.
 */
.nf-service__head {
	align-items: center;
	display: flex;
	gap: var(--wp--preset--spacing--30);
	grid-area: head;
	justify-content: space-between;
	margin-block-end: 0.6rem;
}

/*
 * El icono va sin recuadro. La caja de 3rem se conserva aunque no se vea: es
 * la que centra el icono y de cuyo centro salen los anillos.
 */
.nf-service__icon {
	align-items: center;
	color: var(--nf-accent);
	display: inline-flex;
	transition: color var(--nf-fade);
	flex: 0 0 auto;
	height: 3rem;
	justify-content: center;
	position: relative;
	width: 3rem;
}

/*
 * A 34px el trazo 2 de Lucide escalaría hasta 2,83 y el icono se vería
 * grueso. Con 1,4 el trazo visible se queda en unos 2px, el mismo peso que
 * los iconos de «Así trabajamos».
 */
.nf-service__icon svg {
	stroke-width: 1.4;
}

/*
 * Al entrar en la tarjeta, dos anillos concéntricos salen del icono, crecen y
 * se desvanecen. Se repiten mientras el puntero siga sobre la tarjeta y se
 * cortan al salir.
 *
 * Los dos comparten un ciclo de 1,7s y el segundo sale 0,65s después del
 * primero. Como 0,65 no es la mitad del ciclo, las ondas no llegan a
 * intervalos regulares: salen dos bastante seguidas y luego hay algo más de
 * hueco (1,05s) hasta la siguiente pareja.
 *
 * El anillo es blanco translúcido y no del color del icono porque solo se ve
 * en el estado activo, con la tarjeta ya sobre su degradado oscuro.
 *
 * Arrancan en 1 —los 48px de la caja, por fuera del dibujo del icono de 34px—
 * y terminan en 2,5, unos 120px de diámetro. Aparecen con un fundido muy corto
 * para que el reinicio de cada vuelta no se vea como un parpadeo, y sin
 * fill-mode el segundo conserva la opacidad 0 de reposo mientras espera.
 */
.nf-service__icon::before,
.nf-service__icon::after {
	border: 1.5px solid rgba(255, 255, 255, 0.65);
	border-radius: 50%;
	box-sizing: border-box;
	content: "";
	inset: 0;
	opacity: 0;
	pointer-events: none;
	position: absolute;
	transform: scale(1);
}

.nf-service:hover .nf-service__icon::before,
.nf-service:focus-within .nf-service__icon::before {
	animation: nf-ripple 1.7s ease-out infinite;
}

.nf-service:hover .nf-service__icon::after,
.nf-service:focus-within .nf-service__icon::after {
	animation: nf-ripple 1.7s ease-out 0.65s infinite;
}

@keyframes nf-ripple {
	0% {
		opacity: 0;
		transform: scale(1);
	}

	8% {
		opacity: 1;
	}

	100% {
		opacity: 0;
		transform: scale(2.5);
	}
}

/*
 * Los títulos de las tarjetas llevan Bricolage Grotesque en lugar de la
 * DM Sans del resto de encabezados: una grotesca con más carácter que
 * distingue cada servicio dentro de la rejilla.
 */
.nf-service__title {
	color: var(--nf-title);
	font-family: var(--wp--preset--font-family--bricolage);
	font-size: var(--wp--preset--font-size--x-large);
	margin: 0;
	max-width: 20ch;
	transition: color var(--nf-fade);
}

.nf-service__text {
	color: var(--nf-body);
	font-size: var(--wp--preset--font-size--small);
	grid-area: text;
	transition: color var(--nf-fade);
	margin: 0 0 1.5rem;
	max-width: 44ch;
}

/*
 * La ilustración mide lo mismo en todas las tarjetas, sea cual sea su reparto:
 * si creciera con la tarjeta, las dos anchas de abajo la llevarían más grande
 * que las tres de arriba y la rejilla perdería coherencia.
 *
 * Es una caja fija y no solo un ancho porque los ficheros no tienen la misma
 * proporción (el de seguridad es cuadrado, el de desarrollo es apaisado): con
 * el mismo ancho, el cuadrado saldría bastante más alto. object-fit la encaja
 * entera en la caja y así todas ocupan lo mismo a la vista.
 *
 * 8rem es el tope que permite la lista al lado: en la tarjeta más estrecha que
 * lo usa, lo que queda al lado es justo lo que ocupa «Aplicaciones a medida».
 */
.nf-service__art {
	block-size: 7rem;
	display: block;
	grid-area: art;
	inline-size: 8rem;
	justify-self: end;
	margin-block-start: 1.25rem;
}

.nf-service__art img {
	display: block;
	height: 100%;
	object-fit: contain;
	width: 100%;
}

@container (min-width: 21rem) {
	.nf-service__inner {
		grid-template-areas:
			"head head"
			"text text"
			"list art"
			"link link";
		grid-template-columns: minmax(0, 1fr) auto;
		grid-template-rows: auto auto auto 1fr;
	}

	.nf-service__art {
		align-self: center;
		margin-block-start: 0;
	}
}

.nf-service__list {
	align-self: center;
	display: grid;
	gap: 0.6rem;
	grid-area: list;
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-service__list li {
	color: var(--nf-item);
	font-size: var(--wp--preset--font-size--small);
	padding-inline-start: 1.6rem;
	position: relative;
	transition: color var(--nf-fade);
}

.nf-service__list li::before {
	color: var(--nf-accent);
	transition: color var(--nf-fade);
	content: "\2713";
	font-weight: 700;
	inset-inline-start: 0;
	position: absolute;
}

/* El enlace se apoya en el fondo de la última fila, que es la flexible. */
.nf-service .nf-service__link {
	align-items: center;
	align-self: end;
	color: var(--nf-accent);
	display: inline-flex;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	gap: 0.5rem;
	grid-area: link;
	justify-self: start;
	padding-block-start: 1.5rem;
	text-decoration: none;
	transition: color var(--nf-fade);
	width: fit-content;
}

/*
 * Toda la tarjeta es clicable, pero sigue habiendo un solo enlace: el «Ver …».
 * Su ::after se estira sobre la tarjeta entera —el contenedor posicionado más
 * cercano— y es lo que recibe el clic. Envolver la tarjeta en un <a> también
 * funcionaría, pero un lector de pantalla leería título, descripción y lista
 * como texto del enlace; así el enlace se anuncia solo con su nombre.
 *
 * El precio es que el texto de la tarjeta no se puede seleccionar arrastrando.
 *
 * Como el enlace cubre la tarjeta, está en hover siempre que lo esté ella: por
 * eso no tiene un tono de hover propio, y la flecha se mueve al pasar por
 * cualquier punto de la tarjeta.
 */
.nf-service .nf-service__link::after {
	border-radius: var(--wp--custom--radius--lg);
	content: "";
	inset: 0;
	position: absolute;
}

/*
 * El anillo de foco rodea la tarjeta y no solo el texto del enlace: es la
 * tarjeta lo que se activa. Va en el color de la categoría porque cae fuera de
 * la tarjeta, sobre el fondo claro de la sección, donde el blanco del estado
 * activo no se vería.
 */
.nf-service .nf-service__link:focus-visible {
	outline: none;
}

.nf-service .nf-service__link:focus-visible::after {
	outline: 2px solid var(--nf-cat-accent, var(--wp--preset--color--brand));
	outline-offset: 4px;
}

.nf-service__link span {
	transition: transform var(--nf-fade);
}

.nf-service:hover .nf-service__link span,
.nf-service:focus-within .nf-service__link span {
	transform: translateX(3px);
}

/* ---------------------------------------------------------------------------
   9. Proceso: línea de tiempo
   --------------------------------------------------------------------------- */

/*
 * Va dentro de un contenedor ancho y se centra dentro de él con su propia
 * medida, como en el diseño de referencia.
 *
 * El hilo es uno solo para toda la lista y no un trozo por paso: así no
 * quedan costuras entre marcadores. Arranca y se corta a la altura del centro
 * del primer y del último marcador, y son los propios marcadores —de fondo
 * opaco— los que lo tapan a su paso.
 */
.nf-flow {
	list-style: none;
	margin-block: 0;
	margin-inline: auto;
	max-width: 44rem;
	padding: 0;
	position: relative;
}

.nf-flow::before {
	background-image: linear-gradient(
		180deg,
		var(--wp--custom--border-strong) 0%,
		var(--wp--custom--border-strong) 55%,
		var(--wp--preset--color--border) 100%
	);
	bottom: 2.125rem;
	content: "";
	inset-block-start: 2.125rem;
	inset-inline-start: 2.125rem;
	position: absolute;
	width: 2px;
}

.nf-flow__item {
	min-height: 4.25rem;
	padding-block-end: var(--wp--preset--spacing--40);
	padding-inline-start: 6.25rem;
	position: relative;
}

.nf-flow__item:last-child {
	padding-block-end: 0;
}

.nf-flow__marker {
	align-items: center;
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: var(--wp--preset--shadow--soft);
	color: var(--wp--preset--color--brand-navy);
	display: flex;
	height: 4.25rem;
	inset-block-start: 0;
	inset-inline-start: 0;
	justify-content: center;
	position: absolute;
	transition: border-color var(--wp--custom--transition),
		box-shadow var(--wp--custom--transition),
		transform var(--wp--custom--transition);
	width: 4.25rem;
}

/* El paso entero es la zona sensible: el marcador es pequeño para apuntarlo. */
.nf-flow__item:hover .nf-flow__marker {
	border-color: var(--wp--custom--border-strong);
	box-shadow: var(--wp--preset--shadow--lift);
	transform: translateY(-3px);
}

/* En línea el SVG arrastra el hueco de la línea base y descentra el icono. */
.nf-flow__icon {
	display: flex;
}

/*
 * Lucide dibuja a 24px con trazo 2. Aquí el icono va a 28px y el trazo escala
 * con él hasta 2,33, más grueso que en las tarjetas de servicios. Con 1,75 el
 * trazo visible vuelve a unos 2px y los dos juegos de iconos pesan igual.
 * La propiedad CSS manda sobre el atributo del SVG.
 */
.nf-flow__icon svg {
	stroke-width: 1.75;
}

.nf-flow__number {
	align-items: center;
	background-color: var(--wp--preset--color--brand);
	border-radius: var(--wp--custom--radius--pill);
	color: #FFFFFF;
	display: flex;
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.75rem;
	font-weight: 700;
	height: 1.625rem;
	inset-block-start: -0.5rem;
	inset-inline-end: -0.5rem;
	justify-content: center;
	position: absolute;
	width: 1.625rem;
}

/*
 * La separación entre el borde del marcador y el título se da con relleno y no
 * con margen: un margen en el título se colapsaría hacia fuera del paso y
 * arrastraría con él al marcador, que va posicionado respecto al paso.
 */
.nf-flow__body {
	padding-block-start: 0.75rem;
}

.nf-flow__title {
	font-size: var(--wp--preset--font-size--large);
	font-weight: 700;
	letter-spacing: -0.015em;
	line-height: 1.3;
	margin: 0 0 0.5rem;
}

.nf-flow__text {
	color: var(--wp--preset--color--muted);
	margin: 0;
	max-width: 46ch;
}

/*
 * Dentro de la columna derecha de un reparto editorial (página de desarrollo)
 * la línea de tiempo arranca en el borde de la columna en lugar de centrarse.
 */
.nf-split__list .nf-flow {
	margin-inline: 0;
}

/* En móvil el marcador encoge y el hilo se recoloca a su nuevo centro. */
@media (max-width: 640px) {
	.nf-flow::before {
		bottom: 1.8125rem;
		inset-block-start: 1.8125rem;
		inset-inline-start: 1.8125rem;
	}

	.nf-flow__item {
		min-height: 3.625rem;
		padding-inline-start: 5.125rem;
	}

	.nf-flow__marker {
		height: 3.625rem;
		width: 3.625rem;
	}

	.nf-flow__body {
		padding-block-start: 0.45rem;
	}
}

/* ---------------------------------------------------------------------------
   10. Etiquetas de garantía
   --------------------------------------------------------------------------- */

/* Debajo de una entradilla, más aire que el hueco de flujo entre titular y texto. */
.nf-intro > .nf-pills {
	margin-block-start: var(--wp--preset--spacing--40);
}

.nf-pills {
	display: flex;
	flex-wrap: wrap;
	gap: 0.65rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-pill {
	align-items: center;
	border: 1px solid var(--wp--custom--on-dark--border);
	border-radius: var(--wp--custom--radius--pill);
	display: inline-flex;
	font-size: var(--wp--preset--font-size--small);
	gap: 0.5rem;
	padding: 0.55rem 1.1rem;
}

.nf-pill__check {
	color: var(--wp--custom--on-dark--accent);
	font-weight: 700;
}

/* ---------------------------------------------------------------------------
   11. Proyectos
   --------------------------------------------------------------------------- */

/*
 * Rejilla de casos, con el layout de los «cases» de diseños/diseno: dos
 * columnas desde 48em (una por debajo), tarjeta blanca con borde fino y
 * esquinas redondeadas, miniatura de 180px arriba y cuerpo con etiquetas,
 * título, texto y tecnologías. La tarjeta no es enlace, así que no se eleva al
 * pasar por encima.
 *
 * Cada categoría reutiliza el color de su tarjeta de Servicios. --nf-glow tiñe
 * la miniatura; --nf-tag-text es el color del texto de la primera etiqueta,
 * que va sobre ese mismo color al 10 % sobre blanco:
 *
 *   categoría     texto      contraste
 *   desarrollo    #1D4ED8    5,72:1
 *   hosting       #047857    4,78:1
 *   e-commerce    #6D28D9    6,04:1
 *   IA y datos    #92400E    6,2:1   (el ámbar de Servicios daba 4,39:1)
 *   seguridad     #B91C1C    5,45:1
 *
 * Etiquetas grises: muted sobre surface-alt, 4,86:1.
 */
.nf-project--desarrollo {
	--nf-accent: #1D4ED8;
	--nf-tag-text: #1D4ED8;
	--nf-glow: rgba(59, 130, 246, 0.55);
}

.nf-project--hosting {
	--nf-accent: #047857;
	--nf-tag-text: #047857;
	--nf-glow: rgba(16, 185, 129, 0.5);
}

.nf-project--ecommerce {
	--nf-accent: #6D28D9;
	--nf-tag-text: #6D28D9;
	--nf-glow: rgba(139, 92, 246, 0.55);
}

.nf-project--ia {
	--nf-accent: #B45309;
	--nf-tag-text: #92400E;
	--nf-glow: rgba(245, 158, 11, 0.5);
}

.nf-project--seguridad {
	--nf-accent: #B91C1C;
	--nf-tag-text: #B91C1C;
	--nf-glow: rgba(239, 68, 68, 0.5);
}

.nf-projects {
	display: grid;
	gap: var(--wp--preset--spacing--40);
	grid-template-columns: minmax(0, 1fr);
	list-style: none;
	margin: 0;
	padding: 0;
}

@media (min-width: 48em) {
	.nf-projects {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* La tarjeta entera va en DM Sans; solo la descripción vuelve a Inter. */
.nf-project {
	--nf-accent: var(--wp--preset--color--brand);
	--nf-tag-text: var(--wp--preset--color--brand);
	--nf-glow: rgba(59, 130, 246, 0.55);
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	display: flex;
	flex-direction: column;
	font-family: var(--wp--preset--font-family--dm-sans);
	overflow: hidden;
	position: relative;
}

/*
 * Tipo de caso (Soporte / Proyecto), sobre la esquina de la miniatura: es lo
 * primero que se lee de cada tarjeta. Va fuera de la miniatura, que es
 * decorativa y está oculta a los lectores de pantalla, y se coloca encima con
 * posición absoluta.
 *
 * Las dos variantes van en cristal translúcido con texto blanco: sobre la
 * parada más clara de la miniatura (#15295C) dan 9,69:1.
 */
.nf-project__type {
	align-items: center;
	backdrop-filter: blur(6px);
	background-color: rgba(255, 255, 255, 0.12);
	border: 1px solid rgba(255, 255, 255, 0.24);
	border-radius: var(--wp--custom--radius--pill);
	color: #FFFFFF;
	display: inline-flex;
	font-size: 0.8125rem;
	font-weight: 600;
	gap: 0.4rem;
	left: 1rem;
	line-height: 1;
	padding: 0.45rem 0.75rem 0.45rem 0.6rem;
	position: absolute;
	top: 1rem;
}

.nf-project__type svg {
	display: block;
}

/*
 * Miniatura. Sin imagen, una ilustración en CSS: el degradado profundo de las
 * bandas oscuras, un resplandor del color de la categoría, una malla fina como
 * la del hero y el icono de la línea de servicio en un cristal. Con imagen, la
 * foto cubre la caja y el resplandor queda por encima, muy suave, para que
 * todas las miniaturas sigan pareciendo de la misma familia.
 */
.nf-project__thumb {
	align-items: center;
	background-image:
		radial-gradient(circle at 18% 22%, var(--nf-glow), transparent 42%),
		radial-gradient(circle at 86% 18%, rgba(59, 130, 246, 0.28), transparent 36%),
		linear-gradient(135deg, #0B1533 0%, #15295C 100%);
	display: flex;
	height: 11.25rem;
	justify-content: center;
	overflow: hidden;
	position: relative;
}

.nf-project__thumb::before {
	background-image:
		linear-gradient(rgba(255, 255, 255, 0.06) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, 0.06) 1px, transparent 1px);
	background-size: 24px 24px;
	content: "";
	inset: 0;
	-webkit-mask-image: radial-gradient(ellipse at center, #000 20%, transparent 75%);
	mask-image: radial-gradient(ellipse at center, #000 20%, transparent 75%);
	pointer-events: none;
	position: absolute;
}

.nf-project__thumb img {
	height: 100%;
	inset: 0;
	object-fit: cover;
	position: absolute;
	width: 100%;
}

/*
 * Con imagen, la miniatura toma la proporción 16:9 de las ilustraciones en vez
 * de la altura fija de la variante sin imagen: son diagramas con contenido de
 * borde a borde y recortarlos a 11,25rem se comería casi la mitad del alto.
 */
.nf-project__thumb--img {
	aspect-ratio: 16 / 9;
	height: auto;
}

.nf-project__mark {
	align-items: center;
	backdrop-filter: blur(6px);
	background-color: rgba(255, 255, 255, 0.08);
	border: 1px solid rgba(255, 255, 255, 0.16);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: inset 0 1px rgba(255, 255, 255, 0.1);
	color: rgba(255, 255, 255, 0.92);
	display: inline-flex;
	height: 4.5rem;
	justify-content: center;
	position: relative;
	width: 4.5rem;
}

/* Mismo peso de trazo que los iconos de Servicios. */
.nf-project__mark svg {
	display: block;
	stroke-width: 1.4;
}

.nf-project__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	padding: 1.5rem;
}

.nf-project ul {
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-project__tags {
	display: flex;
	flex-wrap: wrap;
	gap: 0.375rem;
}

.nf-project__tags li {
	background-color: var(--wp--preset--color--surface-alt);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--muted);
	font-size: 0.75rem;
	font-weight: 600;
	line-height: 1.2;
	padding: 0.35rem 0.65rem;
}

.nf-project__tags li:first-child {
	background-color: #EEF0F4;
	background-color: color-mix(in srgb, var(--nf-accent) 10%, #FFFFFF);
	color: var(--nf-tag-text);
}

.nf-project__title {
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 700;
	letter-spacing: -0.01em;
	line-height: 1.25;
	margin: 1rem 0 0.75rem;
}

.nf-project__text {
	color: var(--wp--preset--color--muted);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.55;
	margin: 0 0 1.25rem;
}

/* Al pie de la tarjeta aunque el texto de la vecina sea más largo. */
.nf-project__stack {
	border-top: 1px solid var(--wp--preset--color--border);
	margin-block-start: auto;
	padding-block-start: 1rem;
}

.nf-project__stack-label {
	color: var(--wp--preset--color--muted);
	display: block;
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	margin-block-end: 0.5rem;
	text-transform: uppercase;
}

.nf-project__stack ul {
	display: flex;
	flex-wrap: wrap;
	gap: 0.375rem;
}

.nf-project__stack li {
	border: 1px solid var(--wp--custom--border-strong);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--contrast);
	font-size: 0.75rem;
	line-height: 1.2;
	padding: 0.25rem 0.65rem;
}

/* ---------------------------------------------------------------------------
   12. FAQ
   --------------------------------------------------------------------------- */

/*
 * Acordeón con <details>/<summary>: accesible por teclado y sin JavaScript.
 * El bloque core/details genera este marcado; aquí solo se le da forma.
 *
 * Estilo de la FAQ de diseños/diseno: columna de 720px centrada (el ancho de
 * contenido del tema, que da el diseño «constrained» del grupo padre), cada
 * pregunta en su caja con borde fino y 8px de separación, el borde en azul de
 * marca mientras está abierta y un + / − en azul a la derecha.
 *
 * Contraste: pregunta 19,55:1 sobre blanco, respuesta muted 5,45:1, signo en
 * azul de marca 5,17:1.
 */
.nf-faq .wp-block-details {
	border: 1px solid var(--wp--custom--border-strong);
	border-radius: var(--wp--custom--radius--md);
	margin: 0;
	overflow: hidden;
	transition: border-color var(--wp--custom--transition);
}

.nf-faq .wp-block-details + .wp-block-details {
	margin-block-start: 0.5rem;
}

.nf-faq .wp-block-details:hover {
	border-color: var(--wp--custom--border-control);
}

.nf-faq .wp-block-details[open] {
	border-color: var(--wp--preset--color--brand);
}

/* <summary> no es un elemento de título, así que la regla de theme.json para
   h1-h6 no lo alcanza: la familia de titulares se le aplica aquí. */
.nf-faq summary {
	align-items: center;
	color: var(--wp--preset--color--contrast);
	cursor: pointer;
	display: flex;
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 600;
	gap: 0.75rem;
	justify-content: space-between;
	letter-spacing: -0.01em;
	line-height: 1.4;
	list-style: none;
	padding: 1.125rem 1.25rem;
}

.nf-faq summary::-webkit-details-marker {
	display: none;
}

/* La caja recorta con overflow, así que el foco se dibuja por dentro. */
.nf-faq summary:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand);
	outline-offset: -2px;
}

.nf-faq summary::after {
	color: var(--wp--preset--color--brand);
	content: "+";
	flex: 0 0 auto;
	font-size: 1.25rem;
	font-weight: 400;
	line-height: 1;
}

.nf-faq details[open] summary::after {
	content: "\2212";
}

.nf-faq .wp-block-details > :not(summary) {
	color: var(--wp--preset--color--muted);
	line-height: 1.7;
	margin: 0;
	padding: 0 1.25rem 1.125rem;
}

/* ---------------------------------------------------------------------------
   13. Formulario de contacto
   --------------------------------------------------------------------------- */

/*
 * Las bandas oscuras de contacto (el formulario en /contacto/ y el cierre de
 * la home) van a sangre, y los dos halos azules desenfocados del diseño se
 * anclan a sus esquinas.
 */
.nf-contacto {
	isolation: isolate;
	overflow: hidden;
	position: relative;
}

/*
 * Los halos son decoración pura, así que van en pseudoelementos. El z-index
 * negativo los deja por delante del degradado de la banda y por detrás del
 * contenido; isolation los encierra en la banda para que ese -1 no se cuele
 * por debajo de la página.
 */
.nf-contacto::before,
.nf-contacto::after {
	border-radius: 50%;
	content: "";
	filter: blur(70px);
	opacity: 0.42;
	pointer-events: none;
	position: absolute;
	z-index: -1;
}

.nf-contacto::before {
	background-color: var(--wp--preset--color--brand);
	height: 28.75rem;
	inset-block-start: -11.875rem;
	inset-inline-start: -6.875rem;
	width: 28.75rem;
}

.nf-contacto::after {
	background-color: var(--wp--custom--brand-bright);
	height: 26.25rem;
	inset-block-end: -13.125rem;
	inset-inline-end: -5.625rem;
	width: 26.25rem;
}

/*
 * Tarjeta blanca sobre la banda oscura. Hay que devolver los colores claros
 * que impone .nf-on-dark, y se hace con selectores explícitos en lugar de
 * con !important.
 */
.nf-form-card {
	background-color: var(--wp--preset--color--base);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: 0 28px 64px -28px rgba(2, 8, 26, 0.65);
	padding: clamp(1.5rem, 4vw, 2.25rem);
}

.nf-on-dark .nf-form-card,
.nf-on-dark .nf-form-card :where(p, li, label, legend) {
	color: var(--wp--preset--color--contrast);
}

.nf-on-dark .nf-form-card :where(a):not(.wp-element-button) {
	color: var(--wp--preset--color--brand);
	text-decoration-color: currentColor;
}

.nf-form {
	display: grid;
	gap: 1rem;
}

/* Dos campos por fila cuando caben; uno debajo de otro cuando no. */
.nf-form__row {
	display: grid;
	gap: 1rem;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
}

.nf-field {
	display: grid;
	gap: 0.35rem;
	margin: 0;
}

.nf-field label {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	line-height: 1.35;
}

.nf-field__req {
	color: var(--wp--preset--color--brand);
}

/*
 * El campo en reposo es gris y solo el que tienes entre manos se pone blanco:
 * el formulario se lee como una lista tranquila y el foco canta sin necesidad
 * de un borde grueso.
 *
 * Tres detalles sostienen el tamaño de los campos:
 *
 * - border-box, porque el tema no lo impone de forma global: sin él el 100%
 *   sería solo la caja de contenido y el relleno más el borde sacarían cada
 *   campo 33px fuera de la tarjeta, rompiendo además las filas de dos.
 * - line-height propia: la del cuerpo es 1,65 y en un control de una sola
 *   línea deja el texto flotando con el alto descuadrado.
 * - min-height común: input, select y textarea calculan su alto de formas
 *   distintas y sin un suelo compartido no quedan a la misma altura.
 */
.nf-field :where(input, select, textarea) {
	background-color: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--custom--border-strong);
	border-radius: var(--wp--custom--radius--md);
	box-sizing: border-box;
	color: var(--wp--preset--color--contrast);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.4;
	min-height: 3rem;
	padding: 0.75rem 0.9rem;
	transition: background-color var(--wp--custom--transition),
		border-color var(--wp--custom--transition),
		box-shadow var(--wp--custom--transition);
	width: 100%;
}

/* El desplegable no hereda el tipo del sistema en todos los navegadores. */
.nf-field select {
	font-family: inherit;
}

.nf-field :where(input, select, textarea)::placeholder {
	color: var(--wp--custom--muted-soft);
}

/*
 * El anillo sustituye al contorno global de foco: se ve igual de bien con
 * teclado y con ratón, y dos marcas superpuestas quedarían sucias.
 */
.nf-field :where(input, select, textarea):focus {
	background-color: var(--wp--preset--color--base);
	border-color: var(--wp--preset--color--brand);
	box-shadow: 0 0 0 4px color-mix(in srgb, var(--wp--preset--color--brand) 14%, transparent);
	outline: none;
}

.nf-field textarea {
	min-height: 8.5rem;
	padding-block: 0.8rem;
	resize: vertical;
}

.nf-field :where(input, select, textarea)[aria-invalid="true"] {
	border-color: #B42318;
}

/*
 * Mensaje de error bajo el campo. Vacío no ocupa sitio: el contenedor existe
 * siempre para que aria-describedby tenga a dónde apuntar. #B42318 sobre la
 * tarjeta blanca da 6,57:1.
 */
.nf-field__error {
	color: #B42318;
	font-size: 0.8125rem;
	font-weight: 500;
	line-height: 1.35;
}

.nf-field__error:empty {
	display: none;
}

/* En la casilla, el mensaje va bajo el texto, no bajo el cuadro. */
.nf-field--check .nf-field__error {
	grid-column: 2;
}

/* Casilla de consentimiento: la etiqueta es texto normal, no un título. */
.nf-field--check {
	align-items: start;
	column-gap: 0.65rem;
	grid-template-columns: auto 1fr;
}

.nf-field--check input {
	accent-color: var(--wp--preset--color--brand);
	block-size: 1.05rem;
	inline-size: 1.05rem;
	margin-block-start: 0.2rem;
	min-height: 0;
	padding: 0;
	width: auto;
}

.nf-field--check label {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 400;
}

/* Trampa antispam: fuera de la vista pero sin display:none, que algunos bots detectan. */
.nf-form__trap {
	height: 1px;
	margin: 0;
	overflow: hidden;
	position: absolute;
	width: 1px;
	inset-inline-start: -9999px;
}

.nf-form__submit {
	margin: 0.25rem 0 0;
}

/*
 * El botón que cierra el formulario es el único azul marino del sitio: es el
 * final del recorrido y conviene que pese más que un botón de marca normal.
 */
.nf-form__submit .wp-element-button {
	background-color: var(--wp--preset--color--brand-navy);
	border: 0;
	box-shadow: 0 8px 20px rgba(30, 58, 138, 0.30);
	cursor: pointer;
	font-family: inherit;
	transition: background-color var(--wp--custom--transition),
		box-shadow var(--wp--custom--transition),
		transform var(--wp--custom--transition);
	width: 100%;
}

.nf-form__submit .wp-element-button:hover {
	background-color: var(--wp--custom--navy-dark);
	box-shadow: 0 14px 32px rgba(30, 58, 138, 0.42);
	transform: translateY(-2px);
}

/*
 * Nota bajo el botón: quién lee el formulario y en cuánto se responde. Discreta
 * y centrada bajo el botón, que ocupa todo el ancho. El icono va en un círculo
 * con el azul de marca muy claro; el azul sobre ese fondo da 4,49:1 (es un
 * icono: basta 3:1) y el texto gris, 5,45:1.
 */
.nf-on-dark .nf-form-card .nf-form__human,
.nf-form__human {
	align-items: center;
	color: var(--wp--preset--color--muted);
	display: flex;
	font-size: 0.8125rem;
	gap: 0.5rem;
	justify-content: center;
	line-height: 1.4;
	margin: 0;
	text-align: center;
}

.nf-form__human-icon {
	align-items: center;
	background-color: #E9EFFD;
	border-radius: 50%;
	color: var(--wp--preset--color--brand);
	display: inline-flex;
	flex: 0 0 auto;
	height: 1.5rem;
	justify-content: center;
	width: 1.5rem;
}

.nf-form__human-icon svg {
	display: block;
}

/*
 * Información básica de protección de datos, en un párrafo corrido de letra
 * pequeña y gris, separado del formulario por un filete. El selector lleva
 * .nf-on-dark .nf-form-card delante para ganar a la regla que devuelve el
 * color oscuro a los textos de la tarjeta. Gris sobre blanco: 5,45:1.
 */
.nf-on-dark .nf-form-card .nf-form__legal,
.nf-form__legal {
	border-top: 1px solid var(--wp--preset--color--border);
	color: var(--wp--preset--color--muted);
	font-size: 0.75rem;
	line-height: 1.55;
	margin: 1.25rem 0 0;
	padding-block-start: 1rem;
}

/* Enviando: el botón se bloquea hasta que llega la página de resultado. */
.nf-form__submit .wp-element-button:disabled {
	box-shadow: none;
	cursor: progress;
	opacity: 0.75;
	transform: none;
}

.nf-alert {
	border-radius: var(--wp--custom--radius--md);
	font-size: var(--wp--preset--font-size--small);
	margin-block-end: 1.25rem;
	padding: 0.9rem 1.1rem;
}

.nf-alert p {
	margin: 0;
}

.nf-on-dark .nf-alert--ok,
.nf-alert--ok {
	background-color: #ECFDF3;
	border: 1px solid #A6E9C5;
	color: #07543A;
}

.nf-on-dark .nf-alert--error,
.nf-alert--error {
	background-color: #FEF3F2;
	border: 1px solid #FCC9C4;
	color: #912018;
}

.nf-contacto__email {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--small);
	margin: var(--wp--preset--spacing--40) 0 0;
}

/* Filete apagado que se enciende al pasar, en lugar de un subrayado. */
.nf-on-dark .nf-contacto__email a {
	border-block-end: 1px solid var(--wp--custom--on-dark--border);
	color: #FFFFFF;
	display: inline-block;
	font-weight: 600;
	padding-block-end: 0.2rem;
	text-decoration: none;
	transition: border-color var(--wp--custom--transition);
}

.nf-on-dark .nf-contacto__email a:hover {
	border-block-end-color: #FFFFFF;
	color: #FFFFFF;
}

/* ---------------------------------------------------------------------------
   14. Páginas legales
   --------------------------------------------------------------------------- */

/*
 * Plantilla «Texto legal» (templates/page-legal.html): banda gris de entrada
 * con migas y título, y debajo dos columnas, índice fijo a la izquierda y
 * texto a la derecha. Todo va en una caja común de 64rem centrada —15rem de
 * índice, 4rem de hueco y 45rem (720px, la medida de lectura del tema) de
 * texto—, así que el título arranca alineado con el índice.
 *
 * La banda sube por detrás de la cabecera, que arriba del todo es
 * transparente: la página empieza en gris y no con una franja blanca. Por eso
 * se anula aquí la reserva de hueco que llevan las páginas interiores.
 */
body:not(.home) .wp-site-blocks > main.nf-legal-page {
	padding-block-start: 0;
}

.wp-block-group.nf-legal__wrap {
	box-sizing: border-box;
	margin-inline: auto;
	max-width: 64rem;
	width: 100%;
}

.nf-legal-hero {
	border-bottom: 1px solid var(--wp--preset--color--border);
	padding-block: calc(var(--nf-header-height) + var(--wp--preset--spacing--50)) var(--wp--preset--spacing--50);
}

.nf-legal-hero .nf-legal__wrap > * {
	margin-block: 0;
}

.nf-legal-hero__title {
	letter-spacing: -0.025em;
	line-height: 1.16;
}

.nf-legal-hero .nf-legal__wrap > .nf-legal-hero__title {
	margin-block-start: 0.75rem;
}

/* Migas de pan: separador dibujado, no escrito, para que no se lea. */
.nf-breadcrumb ol {
	display: flex;
	flex-wrap: wrap;
	font-size: var(--wp--preset--font-size--small);
	gap: 0.25rem 0.5rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-breadcrumb li {
	align-items: center;
	color: var(--wp--preset--color--muted);
	display: inline-flex;
	gap: 0.5rem;
}

.nf-breadcrumb li + li::before {
	color: var(--wp--custom--muted-soft);
	content: "/";
}

.nf-breadcrumb a {
	color: var(--wp--preset--color--muted);
	text-decoration: none;
}

.nf-breadcrumb a:hover {
	color: var(--wp--preset--color--brand);
}

.nf-legal-body {
	padding-block: var(--wp--preset--spacing--60) var(--wp--preset--spacing--80);
}

.nf-legal {
	display: grid;
	gap: var(--wp--preset--spacing--50);
	grid-template-columns: minmax(0, 1fr);
}

.nf-legal > * {
	margin-block: 0;
}

@media (min-width: 62em) {
	.nf-legal {
		align-items: start;
		column-gap: 4rem;
		grid-template-columns: 15rem minmax(0, 1fr);
	}

	.nf-legal__toc {
		max-height: calc(100vh - var(--nf-header-height) - 4rem);
		overflow-y: auto;
		position: sticky;
		top: calc(var(--nf-header-height) + 2rem);
	}

	.admin-bar .nf-legal__toc {
		top: calc(var(--nf-header-height) + 2rem + 32px);
	}
}

/*
 * Índice. En móvil es una caja gris sobre el texto; en escritorio, una lista
 * con un filete a la izquierda que se vuelve azul en el apartado que se lee.
 * Enlace en gris 5,45:1 sobre blanco y 5,09:1 sobre gris; activo en azul de
 * marca, 5,17:1.
 */
.nf-legal__toc {
	background-color: var(--wp--preset--color--surface);
	border-radius: var(--wp--custom--radius--md);
	font-family: var(--wp--preset--font-family--dm-sans);
	padding: 1rem 1.25rem;
}

@media (min-width: 62em) {
	.nf-legal__toc {
		background-color: transparent;
		padding: 0;
	}
}

.nf-legal__toc-title {
	color: var(--wp--preset--color--muted);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	margin: 0 0 0.75rem;
	text-transform: uppercase;
}

.nf-legal__toc ol {
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-legal__toc a {
	border-inline-start: 2px solid var(--wp--custom--border-strong);
	color: var(--wp--preset--color--muted);
	display: block;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.4;
	padding: 0.45rem 0 0.45rem 0.9rem;
	text-decoration: none;
	transition: border-color var(--wp--custom--transition),
		color var(--wp--custom--transition);
}

.nf-legal__toc a:hover {
	color: var(--wp--preset--color--contrast);
}

.nf-legal__toc a[aria-current] {
	border-inline-start-color: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--brand);
	font-weight: 600;
}

/*
 * Texto legal. Medida de 720px y ritmo propio: cada apartado (h2) se separa
 * del anterior con aire y un filete, los subapartados (h3) quedan más
 * pegados a su texto y las listas llevan la viñeta en azul.
 */
.nf-legal__content {
	max-width: 45rem;
}

.nf-legal__content h2 {
	border-top: 1px solid var(--wp--preset--color--border);
	font-size: var(--wp--preset--font-size--x-large);
	margin-block: 3rem 1rem;
	padding-block-start: 2.5rem;
	scroll-margin-top: calc(var(--nf-header-height) + 1.5rem);
}

.nf-legal__content h3 {
	font-size: var(--wp--preset--font-size--large);
	margin-block: 2rem 0.75rem;
}

.nf-legal__content :where(p, li) {
	line-height: 1.7;
}

.nf-legal__content > :where(p, ul, ol) {
	margin-block: 0 1rem;
}

.nf-legal__content ul {
	padding-inline-start: 1.25rem;
}

.nf-legal__content li + li {
	margin-block-start: 0.4rem;
}

.nf-legal__content li::marker {
	color: var(--wp--preset--color--brand);
}

.nf-legal__content > :first-child {
	margin-block-start: 0;
}

/*
 * Datos del titular ([nf_titular] y [nf_titular_boton], ver functions.php).
 * Mientras no llegan, cada dato es una barra tenue con el ancho aproximado del
 * texto, para que la línea no salte al rellenarse. Mientras se están pidiendo
 * (clase en <html> que ponen functions.php o titular.js), la barra lleva un
 * aviso; con el botón a la espera va vacía. Sin JavaScript el botón no haría
 * nada, así que no se muestra.
 *
 * Aviso: gris muted sobre el gris de la barra, 4,53:1 (AA); el brillo solo
 * aclara el fondo, así que el contraste nunca baja. El texto
 * alternativo vacío del content evita que un lector de pantalla lo lea tres
 * veces; la primera declaración es para navegadores sin esa sintaxis.
 */
.nf-titular:not([data-nf-listo]) {
	background-color: var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--sm);
	box-sizing: border-box;
	color: var(--wp--preset--color--muted);
	display: inline-block;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1;
	max-inline-size: 100%;
	min-block-size: 1em;
	min-inline-size: var(--nf-titular-ancho, 12ch);
	overflow: hidden;
	padding: 0.2em 0.5em;
	text-overflow: ellipsis;
	vertical-align: middle;
	white-space: nowrap;
}

/*
 * Brillo que recorre la barra mientras carga. Con movimiento reducido, la
 * sección 18 deja una sola pasada casi instantánea que termina con la barra
 * lisa (el brillo acaba fuera, a la derecha).
 */
:where(.nf-titular-auto, .nf-titular-cargando) .nf-titular:not([data-nf-listo]) {
	animation: nf-titular-brillo 1.6s ease-in-out infinite;
	background-image: linear-gradient(100deg, transparent 30%, rgb(255 255 255 / 0.75) 50%, transparent 70%);
	background-repeat: no-repeat;
	background-size: 200% 100%;
}

:where(.nf-titular-auto, .nf-titular-cargando) .nf-titular:not([data-nf-listo])::after {
	content: "Verificando sistema antibots…";
	content: "Verificando sistema antibots…" / "";
}

@keyframes nf-titular-brillo {
	from {
		background-position: 150% 0;
	}

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

.nf-titular[data-nf-titular="nombre"] {
	--nf-titular-ancho: 11rem;
}

.nf-titular[data-nf-titular="nif"] {
	--nf-titular-ancho: 5.5rem;
}

.nf-titular[data-nf-titular="domicilio"] {
	--nf-titular-ancho: 17rem;
}

/*
 * Botón «Ver datos del titular»: discreto a propósito, centrado bajo la lista.
 * Sin la clase wp-element-button para no heredar el botón azul de theme.json.
 * Texto muted sobre blanco, 5,4:1; el borde toma el color del texto al 35 %.
 */
.nf-legal__content > .nf-titular__acciones {
	margin-block: 0 1.5rem;
	text-align: center;
}

.nf-titular__boton {
	appearance: none;
	background-color: transparent;
	border: 1px solid color-mix(in srgb, currentColor 35%, transparent);
	border-radius: 999px;
	color: var(--wp--preset--color--muted);
	cursor: pointer;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	letter-spacing: 0.01em;
	line-height: 1.2;
	padding: 0.45em 1.1em;
	transition: border-color 0.2s ease, color 0.2s ease;
}

.nf-titular__boton:hover {
	border-color: currentColor;
	color: var(--wp--preset--color--contrast);
}

.nf-titular__boton[aria-disabled="true"] {
	cursor: progress;
	opacity: 0.7;
}

/* Se llega con un clic: los datos se piden solos (ver titular.js). */
.nf-titular-auto .nf-titular__acciones {
	display: none;
}

@media (scripting: none) {
	.nf-titular__acciones {
		display: none;
	}
}

/* ---------------------------------------------------------------------------
   15. Páginas de servicio
   --------------------------------------------------------------------------- */

/*
 * Páginas de servicio: /desarrollo-web-y-soluciones-a-medida/,
 * /hosting-dominio-y-mantenimiento/, /desarrollo-de-tiendas-online/,
 * /inteligencia-artificial-y-automatizaciones/ y /ciberseguridad-y-backups/
 * (templates/page-<slug>.html y los patrones desarrollo-*, hosting-*,
 * ecommerce-*, ia-* y seguridad-*). La maqueta sale de diseños/ejemplo-desarrollo-web-y-apss.html
 * con los tokens del tema; lo que ya existía en la home (.nf-split,
 * .nf-intro, .nf-flow, .nf-checklist, halos de .nf-contacto) se reutiliza tal
 * cual. Las piezas nuevas no llevan nada propio de desarrollo, para que las
 * próximas páginas de servicio las compartan.
 *
 * Ritmo de fondos: apertura clara · qué desarrollamos blanco · formas de
 * colaborar gris · proyectos empezados oscuro · integración blanco · proceso
 * gris · partner blanco · cierre oscuro.
 *
 * Como en las legales, la apertura sube por detrás de la cabecera, que arriba
 * del todo es transparente: se anula la reserva de hueco de las interiores.
 */
body:not(.home) .wp-site-blocks > main.nf-landing {
	padding-block-start: 0;
}

/*
 * Color de categoría. Cada página de servicio se tiñe entera con el color de
 * su tarjeta en Servicios de la home: botones, enlaces, iconos, destacados,
 * bordes al pasar, bandas oscuras y halos. No hay reglas duplicadas: la clase
 * del <main> redefine las variables del tema que usan todas esas piezas, y
 * como las variables se heredan, solo cambia lo que va dentro de la página
 * (la cabecera y el pie siguen en azul).
 *
 * Desarrollo no lleva clase: su color de categoría es el azul de marca.
 *
 * Hosting (.nf-cat-hosting), verdes de la tarjeta de Hosting. Contraste:
 *   blanco sobre el botón #047857 5,48:1 y sobre el hover #065F46 7,68:1
 *   verde #047857 sobre blanco 5,48:1 y sobre gris 5,12:1
 *   verde oscuro #065F46 sobre el tinte #E3F4EC (iconos) 6,74:1
 *   sobre la parada más clara de la banda (#065F46), con el velo de las
 *   tarjetas: acento #A7F3D0 5,4:1, texto tenue #C6DDD3 4,84:1,
 *   texto #DCEBE4 6,24:1; acento sobre su caja de icono 4,23:1
 *   entradilla muted sobre el final del degradado de la apertura (#EDF6F2)
 *   4,95:1
 */
.nf-cat-hosting {
	--wp--preset--color--brand: #047857;
	--wp--preset--color--brand-navy: #064E3B;
	--wp--preset--color--accent-1: #E3F4EC;
	--wp--custom--brand-dark: #065F46;
	--wp--custom--brand-bright: #10B981;
	--wp--preset--gradient--brand: linear-gradient(120deg, #065F46 0%, #047857 48%, #059669 100%);
	--wp--preset--gradient--deep: linear-gradient(160deg, #022C22 0%, #064E3B 62%, #065F46 100%);
	--wp--preset--gradient--deep-soft: linear-gradient(180deg, #022C22 0%, #053B2E 100%);
	--wp--custom--on-dark--text: #DCEBE4;
	--wp--custom--on-dark--muted: #C6DDD3;
	--wp--custom--on-dark--accent: #A7F3D0;
	--nf-hero-tint-1: #F6FAF8;
	--nf-hero-tint-2: #EDF6F2;
}

/*
 * E-commerce (.nf-cat-ecommerce), morados de la tarjeta de E-commerce.
 * Contraste:
 *   blanco sobre el botón #6D28D9 7,1:1 y sobre el hover #5B21B6 8,98:1
 *   morado #6D28D9 sobre blanco 7,1:1 y sobre gris 6,63:1
 *   morado oscuro #5B21B6 sobre el tinte #F1ECFD (iconos) 7,77:1
 *   sobre la parada más clara de la banda (#4C1D95), con el velo de las
 *   tarjetas: acento #DDD6FE 7,09:1, texto tenue #C9BEE6 5,62:1, texto
 *   #E6E0F5 8,53:1; acento sobre su caja de icono 5,52:1
 *   entradilla muted sobre el final del degradado de la apertura (#F3EFFC)
 *   4,82:1
 */
.nf-cat-ecommerce {
	--wp--preset--color--brand: #6D28D9;
	--wp--preset--color--brand-navy: #4C1D95;
	--wp--preset--color--accent-1: #F1ECFD;
	--wp--custom--brand-dark: #5B21B6;
	--wp--custom--brand-bright: #8B5CF6;
	--wp--preset--gradient--brand: linear-gradient(120deg, #5B21B6 0%, #6D28D9 48%, #7C3AED 100%);
	--wp--preset--gradient--deep: linear-gradient(160deg, #1E0B4B 0%, #3B1880 62%, #4C1D95 100%);
	--wp--preset--gradient--deep-soft: linear-gradient(180deg, #1E0B4B 0%, #2E1266 100%);
	--wp--custom--on-dark--text: #E6E0F5;
	--wp--custom--on-dark--muted: #C9BEE6;
	--wp--custom--on-dark--accent: #DDD6FE;
	--nf-hero-tint-1: #F9F7FD;
	--nf-hero-tint-2: #F3EFFC;
}

/*
 * IA (.nf-cat-ia), ámbar de la tarjeta de IA. Contraste:
 *   blanco sobre el botón #B45309 5,02:1 y sobre el hover #92400E 7,09:1
 *   ámbar #B45309 sobre blanco 5,02:1 y sobre gris 4,68:1
 *   ámbar oscuro #92400E sobre el tinte #FDF3E7 (iconos) 6,47:1
 *   sobre la parada más clara de la banda (#78350F), con el velo de las
 *   tarjetas: acento #FDE68A 6,51:1, texto tenue #E8D3C1 5,6:1, texto
 *   #F3E6DA 7,41:1; acento sobre su caja de icono 5,01:1
 *   entradilla muted sobre el final del degradado de la apertura (#FCF5EE)
 *   5,05:1
 */
.nf-cat-ia {
	--wp--preset--color--brand: #B45309;
	--wp--preset--color--brand-navy: #78350F;
	--wp--preset--color--accent-1: #FDF3E7;
	--wp--custom--brand-dark: #92400E;
	--wp--custom--brand-bright: #D97706;
	--wp--preset--gradient--brand: linear-gradient(120deg, #92400E 0%, #B45309 48%, #D97706 100%);
	--wp--preset--gradient--deep: linear-gradient(160deg, #2B1103 0%, #5C2A0B 62%, #78350F 100%);
	--wp--preset--gradient--deep-soft: linear-gradient(180deg, #2B1103 0%, #4A1F08 100%);
	--wp--custom--on-dark--text: #F3E6DA;
	--wp--custom--on-dark--muted: #E8D3C1;
	--wp--custom--on-dark--accent: #FDE68A;
	--nf-hero-tint-1: #FCF8F3;
	--nf-hero-tint-2: #FCF5EE;
}

/*
 * Seguridad (.nf-cat-seguridad), rojos de la tarjeta de Seguridad. Contraste:
 *   blanco sobre el botón #B91C1C 6,47:1 y sobre el hover #991B1B 8,31:1
 *   rojo #B91C1C sobre gris 6,04:1
 *   rojo oscuro #991B1B sobre el tinte #FDF0F0 (iconos) 7,48:1
 *   sobre la parada más clara de la banda (#7F1D1D), con el velo de las
 *   tarjetas: acento #FECACA 6,27:1, texto tenue #E8C7C7 5,79:1, texto
 *   #F5E4E4 8,16:1; acento sobre su caja de icono 4,92:1
 *   entradilla muted sobre el final del degradado de la apertura (#FDF4F4)
 *   5,04:1
 */
.nf-cat-seguridad {
	--wp--preset--color--brand: #B91C1C;
	--wp--preset--color--brand-navy: #7F1D1D;
	--wp--preset--color--accent-1: #FDF0F0;
	--wp--custom--brand-dark: #991B1B;
	--wp--custom--brand-bright: #DC2626;
	--wp--preset--gradient--brand: linear-gradient(120deg, #991B1B 0%, #B91C1C 48%, #DC2626 100%);
	--wp--preset--gradient--deep: linear-gradient(160deg, #2D0707 0%, #651919 62%, #7F1D1D 100%);
	--wp--preset--gradient--deep-soft: linear-gradient(180deg, #2D0707 0%, #4A1010 100%);
	--wp--custom--on-dark--text: #F5E4E4;
	--wp--custom--on-dark--muted: #E8C7C7;
	--wp--custom--on-dark--accent: #FECACA;
	--nf-hero-tint-1: #FDF8F8;
	--nf-hero-tint-2: #FDF4F4;
}

/*
 * Apertura. El degradado claro, la malla en perspectiva y la altura de ventana del
 * hero de la home (mismo razonamiento: svh, relleno asimétrico que centra el
 * contenido en el hueco bajo la cabecera y descuento de la barra de
 * WordPress). El velo apaga la malla alrededor del texto, que va a la
 * izquierda.
 *
 * Sobre la parada más oscura (#EDF1F9): entradilla y texto muted 4,82:1,
 * rasgos en contraste 17,27:1.
 */
.nf-page-hero {
	background-image: linear-gradient(180deg, #FFFFFF 0%, #FFFFFF 22%, var(--nf-hero-tint-1, #F7FAFD) 52%, var(--nf-hero-tint-2, #EDF1F9) 100%);
	border-bottom: 1px solid var(--wp--preset--color--border);
	display: flex;
	flex-direction: column;
	justify-content: center;
	min-height: 100vh;
	min-height: 100svh;
	overflow: hidden;
	padding-block: calc(var(--nf-header-height) + var(--wp--preset--spacing--60)) var(--wp--preset--spacing--60);
	position: relative;
}

.admin-bar .nf-page-hero {
	min-height: calc(100vh - 32px);
	min-height: calc(100svh - 32px);
}

@media (max-width: 782px) {
	.admin-bar .nf-page-hero {
		min-height: calc(100vh - 46px);
		min-height: calc(100svh - 46px);
	}
}

/* La misma malla en perspectiva que la home (ver .nf-hero::before). */
.nf-page-hero::before {
	background: url("assets/img/malla-perspectiva.svg") no-repeat 0 0 / 100% 100%;
	content: "";
	inset: -13.14% -13.6% -10.32% -9.85%;
	-webkit-mask-image:
		linear-gradient(to right, #000 7.98%, rgba(0, 0, 0, 0.134) 42%, #000 88.98%),
		linear-gradient(to bottom, #000 10.64%, rgba(0, 0, 0, 0.134) 56%, #000 91.64%);
	mask-image:
		linear-gradient(to right, #000 7.98%, rgba(0, 0, 0, 0.134) 42%, #000 88.98%),
		linear-gradient(to bottom, #000 10.64%, rgba(0, 0, 0, 0.134) 56%, #000 91.64%);
	pointer-events: none;
	position: absolute;
}

@media (orientation: portrait) {
	.nf-page-hero::before {
		background-image: url("assets/img/malla-perspectiva-vertical.svg");
	}
}

/*
 * Velo sobre la malla alrededor del texto, como .nf-hero::after y también al
 * 75 % en el centro. Peor punto medido: donde una línea cruza el borde
 * inferior izquierdo de la columna de texto (los rasgos), 4,54:1 sobre el
 * tono más oscuro de la apertura.
 */
.nf-page-hero::after {
	background-image: inherit;
	content: "";
	inset: 0;
	-webkit-mask-image: radial-gradient(60% 60% at 30% 55%, rgba(0, 0, 0, 0.75) 30%, transparent 85%);
	mask-image: radial-gradient(60% 60% at 30% 55%, rgba(0, 0, 0, 0.75) 30%, transparent 85%);
	pointer-events: none;
	position: absolute;
}

/* z-index para quedar por encima del velo, que se pinta después. */
.nf-page-hero > * {
	position: relative;
	z-index: 1;
}

.nf-page-hero__cols {
	display: grid;
	gap: var(--wp--preset--spacing--60);
	grid-template-columns: minmax(0, 1fr);
}

.nf-page-hero__cols > * {
	margin-block: 0;
}

.nf-page-hero__col {
	max-width: 40rem;
}

.nf-page-hero__col > .nf-breadcrumb {
	margin-block: 0;
}

/*
 * Dos columnas desde 1088px repartidas a los extremos, igual que el hero de la
 * home: el texto arranca en el mismo borde que las secciones de debajo y las
 * migas no quedan flotando en mitad de la página.
 */
@media (min-width: 68em) {
	.nf-page-hero__cols {
		align-items: center;
		column-gap: var(--wp--preset--spacing--70);
		grid-template-columns: minmax(0, 40rem) minmax(0, 28rem);
		justify-content: space-between;
	}
}

/*
 * Rasgos del servicio bajo los botones: la fila «hero-stats» del ejemplo, sin
 * cifras. Un filete los separa de los botones para que no se lean como un
 * tercer botón.
 */
.nf-page-hero__col > .nf-traits {
	margin-block: var(--wp--preset--spacing--50) 0;
}

.nf-traits {
	border-top: 1px solid var(--wp--custom--border-strong);
	display: flex;
	flex-wrap: wrap;
	gap: 1rem 2.25rem;
	list-style: none;
	margin: 0;
	padding: 1.5rem 0 0;
}

.nf-trait {
	display: grid;
	gap: 0.2rem;
}

.nf-trait strong {
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	letter-spacing: -0.01em;
	line-height: 1.2;
}

.nf-trait span {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.35;
}

/*
 * Ficha con dos tarjetas apiladas detrás (.hero-visual del ejemplo), en todas
 * las aperturas: la home y las páginas de servicio. La ficha va en el
 * degradado profundo y las
 * tarjetas de atrás son su sombra de color: asoman abajo a la derecha, en el
 * hueco que les reserva el relleno del contenedor. Las tres llevan la misma
 * inclinación que la ilustración del portal y se enderezan al pasar por encima.
 *
 * Contraste, sobre la parada más clara del degradado (#101E44): título blanco
 * 16,26:1, texto a 62 % 6,99:1, estado en acento 7,87:1, fase pendiente a
 * 60 % 6,59:1 y marca verde de fase hecha 8,46:1.
 */
.nf-stack {
	box-sizing: border-box;
	justify-self: center;
	max-width: 28rem;
	padding: 0 2.25rem 2rem 0;
	position: relative;
	width: 100%;
}

.nf-stack__card,
.nf-brief {
	transform: perspective(1200px) rotateY(-12deg) rotateX(4deg);
	transition: transform 500ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.nf-stack__card {
	background-image: linear-gradient(160deg, rgba(30, 58, 138, 0.16) 0%, rgba(37, 99, 235, 0.08) 100%);
	background-image: linear-gradient(160deg, color-mix(in srgb, var(--wp--preset--color--brand-navy) 16%, transparent) 0%, color-mix(in srgb, var(--wp--preset--color--brand) 8%, transparent) 100%);
	border: 1px solid rgba(30, 58, 138, 0.16);
	border-color: color-mix(in srgb, var(--wp--preset--color--brand-navy) 16%, transparent);
	border-radius: var(--wp--custom--radius--lg);
	inset: 0 2.25rem 2rem 0;
	position: absolute;
}

.nf-stack__card--1 {
	translate: 1.125rem 1rem;
}

.nf-stack__card--2 {
	opacity: 0.55;
	translate: 2.25rem 2rem;
}

.nf-stack:hover :is(.nf-stack__card, .nf-brief) {
	transform: perspective(1200px) rotateY(-4deg) rotateX(1deg);
}

.nf-brief {
	background-image: var(--wp--preset--gradient--deep-soft);
	border: 1px solid rgba(255, 255, 255, 0.14);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: 0 32px 64px rgba(11, 21, 51, 0.3),
		inset 0 1px rgba(255, 255, 255, 0.07);
	box-sizing: border-box;
	color: rgba(255, 255, 255, 0.72);
	font-family: var(--wp--preset--font-family--inter);
	line-height: 1.35;
	padding: clamp(1.1rem, 2vw, 1.5rem);
	position: relative;
}

.nf-brief ul,
.nf-brief ol {
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-brief svg {
	display: block;
}

.nf-brief__top {
	align-items: flex-start;
	display: flex;
	gap: 1rem;
	justify-content: space-between;
	margin-block-end: 1.25rem;
}

.nf-brief__label {
	color: rgba(255, 255, 255, 0.62);
	display: block;
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.6875rem;
	letter-spacing: 0.04em;
	margin-block-end: 0.45rem;
}

.nf-brief__title {
	color: #FFFFFF;
	display: block;
	font-family: var(--wp--preset--font-family--bricolage);
	font-size: 1.5rem;
	font-weight: 600;
	letter-spacing: -0.01em;
	line-height: 1.1;
}

.nf-brief__status {
	background-color: rgba(147, 180, 251, 0.12);
	background-color: color-mix(in srgb, var(--wp--custom--on-dark--accent) 12%, transparent);
	border: 1px solid rgba(147, 180, 251, 0.32);
	border-color: color-mix(in srgb, var(--wp--custom--on-dark--accent) 32%, transparent);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--custom--on-dark--accent);
	flex: 0 0 auto;
	font-size: 0.75rem;
	font-weight: 600;
	line-height: 1;
	padding: 0.45rem 0.75rem;
	white-space: nowrap;
}

.nf-brief__who {
	align-items: center;
	background-color: rgba(255, 255, 255, 0.06);
	border: 1px solid rgba(255, 255, 255, 0.1);
	border-radius: var(--wp--custom--radius--md);
	display: grid;
	gap: 0.85rem;
	grid-template-columns: 2.75rem minmax(0, 1fr);
	padding: 0.85rem;
}

.nf-brief__avatar {
	align-items: center;
	background-image: var(--wp--preset--gradient--brand);
	border-radius: var(--wp--custom--radius--md);
	color: #FFFFFF;
	display: flex;
	height: 2.75rem;
	justify-content: center;
	width: 2.75rem;
}

.nf-brief__who-text b {
	color: #FFFFFF;
	display: block;
	font-size: 0.9375rem;
	font-weight: 600;
	line-height: 1.25;
}

.nf-brief__who-text span {
	color: rgba(255, 255, 255, 0.62);
	display: block;
	font-size: 0.8125rem;
	margin-block-start: 0.2rem;
}

/* Con la lista delante: .nf-brief ul deja el margen a cero. */
.nf-brief ul.nf-brief__stack {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	margin-block-start: 1rem;
}

.nf-brief__stack li {
	background-color: rgba(255, 255, 255, 0.07);
	border: 1px solid rgba(255, 255, 255, 0.12);
	border-radius: var(--wp--custom--radius--pill);
	color: rgba(255, 255, 255, 0.8);
	font-size: 0.75rem;
	font-weight: 600;
	line-height: 1;
	padding: 0.45rem 0.7rem;
}

.nf-brief ol.nf-brief__phases {
	border-top: 1px dashed rgba(255, 255, 255, 0.14);
	display: grid;
	gap: 0.6rem;
	margin-block-start: 1.25rem;
	padding-block-start: 1rem;
}

/*
 * Ficha de soporte de la home: no lleva píldoras, así que sus seis filas van
 * más separadas. Con 0,95rem medía lo mismo que las de servicio (unos 413 px
 * frente a 401 y 428); el 15/09/2026 el usuario la pidió un poco más alta y
 * 1,25rem suma 24 px entre los cinco huecos (unos 437 px).
 */
.nf-hero .nf-brief ol.nf-brief__phases {
	gap: 1.25rem;
}

/* Cada fase: marca, nombre y, en la que está en curso, el aviso a la derecha. */
.nf-brief__phase {
	align-items: center;
	display: grid;
	font-size: 0.8125rem;
	gap: 0.65rem;
	grid-template-columns: 1.125rem minmax(0, 1fr) auto;
}

.nf-brief__phase::before {
	align-items: center;
	border: 1px solid rgba(255, 255, 255, 0.28);
	border-radius: 50%;
	box-sizing: border-box;
	content: "";
	display: flex;
	font-size: 0.625rem;
	font-weight: 700;
	height: 1.125rem;
	justify-content: center;
	width: 1.125rem;
}

.nf-brief__phase.is-hecho {
	color: rgba(255, 255, 255, 0.85);
}

.nf-brief__phase.is-hecho::before {
	background-color: rgba(52, 211, 153, 0.16);
	border-color: rgba(52, 211, 153, 0.55);
	color: #34D399;
	content: "\2713";
	content: "\2713" / "";
}

.nf-brief__phase.is-curso {
	color: #FFFFFF;
	font-weight: 600;
}

.nf-brief__phase.is-curso::before {
	background-image: radial-gradient(circle, var(--wp--custom--on-dark--accent) 0 28%, transparent 32%);
	border-color: var(--wp--custom--on-dark--accent);
}

.nf-brief__phase.is-curso::after {
	color: var(--wp--custom--on-dark--accent);
	content: "en curso";
	content: "en curso" / "";
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.6875rem;
	font-weight: 500;
}

.nf-brief__phase.is-pendiente {
	color: rgba(255, 255, 255, 0.6);
}

/*
 * En espera (ficha de soporte de la home): ámbar, para no confundirla con una
 * pendiente sin empezar ni con la que está en curso. #FBBF24 sobre la parada
 * más clara del degradado (#101E44): 9,74:1.
 */
.nf-brief__phase.is-espera {
	color: rgba(255, 255, 255, 0.85);
}

.nf-brief__phase.is-espera::before {
	background-color: rgba(251, 191, 36, 0.16);
	border-color: rgba(251, 191, 36, 0.6);
}

.nf-brief__phase.is-espera[data-nota]::after {
	color: #FBBF24;
}

/*
 * Nota a la derecha de cada fila desde data-nota (panel de hosting: «en
 * línea», «actualizando»…). Gana a la nota fija «en curso» del panel de
 * desarrollo. A 62 %: 6,99:1; en curso, en el acento: 7,87:1.
 */
.nf-brief__phase[data-nota]::after {
	color: rgba(255, 255, 255, 0.62);
	content: attr(data-nota);
	content: attr(data-nota) / "";
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.6875rem;
	font-weight: 500;
}

/*
 * Notas de estado en color en las fichas de la home (tickets) y de hosting
 * (proyectos alojados): verde lo resuelto o en línea, con el verde de la marca
 * de fase hecha. En las demás fichas las notas siguen en gris, porque ahí
 * describen pasos y no estados. Sobre la parada más clara del degradado: 8,46:1
 * en la home (#101E44) y 6,54:1 en hosting (#053B2E).
 */
.nf-hero .nf-brief__phase.is-hecho[data-nota]::after,
.nf-cat-hosting .nf-brief__phase.is-hecho[data-nota]::after {
	color: #34D399;
}

/*
 * En hosting, lo que se está actualizando va en azul, marca incluida: el acento
 * de la página es verde y se confundiría con «en línea». #93C5FD sobre
 * #053B2E: 6,97:1. «Renueva en 12 días» usa el estado en espera (ámbar,
 * 7,53:1).
 */
.nf-cat-hosting .nf-brief__phase.is-curso::before {
	background-image: radial-gradient(circle, #93C5FD 0 28%, transparent 32%);
	border-color: #93C5FD;
}

.nf-cat-hosting .nf-brief__phase.is-curso[data-nota]::after {
	color: #93C5FD;
}

.nf-brief__phase.is-curso[data-nota]::after {
	color: var(--wp--custom--on-dark--accent);
}

.nf-brief__phase.is-pendiente::before {
	border-style: dashed;
}

/*
 * En móvil la ficha se retira. Es una ilustración de apoyo y ahí compite con
 * el titular por la primera pantalla; en la home, el portal se explica con su
 * captura en «Todo el soporte centralizado».
 */
@media (max-width: 47.99em) {
	.nf-stack {
		display: none;
	}
}

@media (max-width: 67.99em) {
	.nf-stack__card,
	.nf-brief {
		transform: none;
	}
}

/*
 * Icono en caja tintada: el de las tarjetas de colaboración, el acordeón, los
 * compromisos y el esquema de papeles. Azul oscuro de marca sobre el tinte: 5,78:1. Con 22-24px el trazo 2
 * de Lucide engorda; 1,75 lo deja en el peso de los iconos de «Así trabajamos».
 */
.nf-mode__icon,
.nf-catalog__icon {
	align-items: center;
	background-color: var(--wp--preset--color--accent-1);
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--custom--brand-dark);
	display: flex;
	flex: 0 0 auto;
	height: 2.75rem;
	justify-content: center;
	width: 2.75rem;
}

:is(.nf-mode__icon, .nf-catalog__icon, .nf-value__icon, .nf-role__icon) svg {
	display: block;
	stroke-width: 1.75;
}

/* Formas de colaborar: tarjeta blanca con borde fino sobre gris; título
   19,55:1 y texto 5,45:1 sobre el blanco de la tarjeta. */
.nf-modes {
	display: grid;
	gap: var(--wp--preset--spacing--40);
	grid-template-columns: minmax(0, 1fr);
	list-style: none;
	margin: 0;
	padding: 0;
}

@media (min-width: 48em) {
	.nf-modes {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* Seis tarjetas: tres por fila en escritorio. */
@media (min-width: 62em) {
	.nf-modes--3 {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* Cuatro tarjetas en fila solo cuando caben con aire (1200px); antes, 2 × 2. */
@media (min-width: 75em) {
	.nf-modes--4 {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

/*
 * Tarjeta que lleva a otra sección (índice de la página de IA). Como las
 * tarjetas de Servicios de la home, hay un único enlace y su ::after cubre la
 * tarjeta, que es la zona clicable; el anillo de foco rodea la tarjeta entera.
 * El enlace va al pie aunque los textos midan distinto.
 */
.nf-mode--link {
	display: flex;
	flex-direction: column;
	position: relative;
}

.nf-mode__link {
	align-items: center;
	color: var(--wp--preset--color--brand);
	display: inline-flex;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	gap: 0.4rem;
	margin-block-start: auto;
	padding-block-start: 1.25rem;
	text-decoration: none;
}

.nf-mode__link::after {
	border-radius: var(--wp--custom--radius--lg);
	content: "";
	inset: 0;
	position: absolute;
}

.nf-mode__link:hover,
.nf-mode__link:focus-visible {
	color: var(--wp--custom--brand-dark);
	text-decoration: none;
}

.nf-mode__link:focus-visible {
	outline: none;
}

.nf-mode__link:focus-visible::after {
	outline: 2px solid var(--wp--preset--color--brand);
	outline-offset: 4px;
}

.nf-mode__link span[aria-hidden] {
	transition: transform var(--wp--custom--transition);
}

.nf-mode--link:hover .nf-mode__link span[aria-hidden] {
	transform: translateY(3px);
}

.nf-mode {
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	padding: clamp(1.5rem, 3vw, 2.25rem);
	transition: border-color var(--wp--custom--transition),
		box-shadow var(--wp--custom--transition),
		transform var(--wp--custom--transition);
}

/*
 * Al pasar por encima, borde en azul de marca y la tarjeta se eleva con la
 * sombra del tema, como en las «engagement options» del ejemplo (a petición
 * del usuario, 14/09/2026). El borde azul sobre el gris de la sección da
 * 4,82:1. Sin movimiento reducido, solo cambian borde y sombra (sección 18).
 */
.nf-mode:hover {
	border-color: var(--wp--preset--color--brand);
	box-shadow: var(--wp--preset--shadow--lift);
	transform: translateY(-4px);
}

.nf-mode__icon {
	margin-block-end: 1.25rem;
}

.nf-mode__title {
	font-family: var(--wp--preset--font-family--bricolage);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 600;
	letter-spacing: 0;
	line-height: 1.25;
	margin: 0 0 0.6rem;
}

.nf-mode__text {
	color: var(--wp--preset--color--muted);
	margin: 0;
	max-width: 46ch;
}

/*
 * «Desarrollo para proyectos que necesitan algo más»: la lista editorial
 * desplegable del ejemplo (.ed-acc-item) con <details>, en la columna derecha
 * del reparto editorial. Cada fila es el <summary> completo, así que toda ella
 * abre y cierra: icono, título y flecha arriba y la línea corta debajo (desde
 * 640px, alineada con el título). Al abrir, una explicación más larga y las
 * etiquetas.
 *
 * Mientras fue una sección a todo el ancho, desde 992px la fila iba en una
 * sola línea; en la columna no cabe, así que ese reparto se retiró al fusionar
 * las dos secciones (14/09/2026).
 *
 * Abierta, la fila toma el fondo gris y la flecha pasa a botón azul girado.
 * Título en azul al pasar y abierta: 5,17:1 sobre blanco y 4,82:1 sobre gris.
 * Donde el navegador sabe animar el alto de <details> (::details-content con
 * interpolate-size), se despliega con suavidad; en el resto, abre en seco.
 */
.nf-catalog {
	border-top: 1px solid var(--wp--custom--border-strong);
}

.nf-catalog__item {
	border-bottom: 1px solid var(--wp--custom--border-strong);
	transition: background-color var(--wp--custom--transition);
}

.nf-catalog__item[open] {
	background-color: var(--wp--preset--color--surface);
}

.nf-catalog__head {
	align-items: center;
	column-gap: 1rem;
	cursor: pointer;
	display: grid;
	grid-template-areas:
		"icon title toggle"
		"text text text";
	grid-template-columns: 2.75rem minmax(0, 1fr) 2.25rem;
	list-style: none;
	padding: 1.5rem 0.75rem;
	row-gap: 0.75rem;
}

.nf-catalog__head::-webkit-details-marker {
	display: none;
}

.nf-catalog__head:focus-visible {
	outline: 2px solid var(--wp--preset--color--brand);
	outline-offset: -2px;
}

.nf-catalog__icon {
	grid-area: icon;
}

.nf-catalog__title {
	font-family: var(--wp--preset--font-family--bricolage);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 600;
	grid-area: title;
	letter-spacing: 0;
	line-height: 1.25;
	margin: 0;
	transition: color var(--wp--custom--transition);
}

.nf-catalog__text {
	color: var(--wp--preset--color--muted);
	grid-area: text;
	line-height: 1.55;
}

.nf-catalog__toggle {
	align-items: center;
	border: 1px solid var(--wp--custom--border-strong);
	border-radius: 50%;
	box-sizing: border-box;
	color: var(--wp--preset--color--muted);
	display: flex;
	grid-area: toggle;
	height: 2.25rem;
	justify-content: center;
	justify-self: end;
	transition: background-color var(--wp--custom--transition),
		border-color var(--wp--custom--transition),
		color var(--wp--custom--transition),
		transform 280ms cubic-bezier(0.22, 1, 0.36, 1);
	width: 2.25rem;
}

.nf-catalog__toggle svg {
	display: block;
}

.nf-catalog__head:hover .nf-catalog__title,
.nf-catalog__item[open] .nf-catalog__title {
	color: var(--wp--preset--color--brand);
}

.nf-catalog__head:hover .nf-catalog__toggle {
	border-color: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--brand);
}

.nf-catalog__item[open] .nf-catalog__toggle {
	background-color: var(--wp--preset--color--brand);
	border-color: var(--wp--preset--color--brand);
	color: #FFFFFF;
	transform: rotate(180deg);
}

@media (min-width: 40em) {
	.nf-catalog__head {
		grid-template-areas:
			"icon title toggle"
			". text .";
	}
}

/*
 * Contenido desplegado: explicación y etiquetas, alineadas con el título de la
 * fila (desde 640px, relleno = relleno de la fila + icono + hueco de columna).
 * Texto en contraste sobre el gris de la fila abierta: 18,24:1.
 */
.nf-catalog__body {
	padding: 0 0.75rem 1.75rem;
}

.nf-catalog__more {
	color: var(--wp--preset--color--contrast);
	line-height: 1.6;
	margin: 0 0 1rem;
	max-width: 52ch;
}

@media (min-width: 40em) {
	.nf-catalog__body {
		padding-inline-start: calc(0.75rem + 2.75rem + 1rem);
	}
}

.nf-catalog__tags {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-catalog__tags li {
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--custom--border-strong);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	line-height: 1.2;
	padding: 0.4rem 0.85rem;
}

@supports (interpolate-size: allow-keywords) {
	.nf-catalog {
		interpolate-size: allow-keywords;
	}

	.nf-catalog__item::details-content {
		block-size: 0;
		overflow: clip;
		transition: block-size 380ms cubic-bezier(0.22, 1, 0.36, 1),
			content-visibility 380ms allow-discrete;
	}

	.nf-catalog__item[open]::details-content {
		block-size: auto;
	}
}

/*
 * Tarjetas de valores («Why build with us» del ejemplo): compromisos, sobre
 * blanco, y situaciones de proyectos empezados, sobre la banda oscura.
 *
 * Sobre blanco van en el gris de superficie sin borde, como las tarjetas de
 * Servicios en reposo: título 18,24:1, texto muted 5,09:1 e icono en azul
 * oscuro sobre su tinte 5,78:1.
 *
 * Sobre oscuro, translúcidas con borde fino. Medido con el velo de la tarjeta
 * sobre la parada más clara del degradado (#28438F en la mezcla): título blanco
 * 9,17:1, texto on-dark muted 4,61:1, icono en acento sobre su caja 3,62:1
 * (icono: basta 3:1).
 */
.nf-values {
	display: grid;
	gap: var(--wp--preset--spacing--40);
	grid-template-columns: minmax(0, 1fr);
	list-style: none;
	margin: 0;
	padding: 0;
}

@media (min-width: 40em) {
	.nf-values {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/* Número impar de tarjetas a dos por fila: la última ocupa la fila entera. */
	.nf-values--3 > :last-child:nth-child(odd),
	.nf-values--5 > :last-child:nth-child(odd) {
		grid-column: 1 / -1;
	}
}

@media (min-width: 62em) {
	.nf-values--3 {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.nf-values--3 > :last-child:nth-child(odd),
	.nf-values--5 > :last-child:nth-child(odd) {
		grid-column: auto;
	}

	.nf-values--5 {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.nf-values--4 {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

/* Cinco tarjetas en una fila cuando caben con aire (1200px). */
@media (min-width: 75em) {
	.nf-values--5 {
		grid-template-columns: repeat(5, minmax(0, 1fr));
	}
}

.nf-value,
.nf-tech-panel {
	background-color: var(--wp--preset--color--surface);
	border-radius: var(--wp--custom--radius--lg);
	box-sizing: border-box;
}

.nf-value {
	padding: clamp(1.5rem, 2.5vw, 2rem);
}

.nf-value__icon {
	align-items: center;
	background-color: var(--wp--preset--color--accent-1);
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--custom--brand-dark);
	display: flex;
	height: 2.75rem;
	justify-content: center;
	margin-block-end: 1.25rem;
	width: 2.75rem;
}

.nf-value__title {
	font-family: var(--wp--preset--font-family--bricolage);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 600;
	letter-spacing: 0;
	line-height: 1.3;
	margin: 0 0 0.5rem;
}

.nf-value__text {
	color: var(--wp--preset--color--muted);
	line-height: 1.6;
	margin: 0;
}

.nf-on-dark .nf-value {
	background-color: var(--wp--custom--on-dark--surface);
	border: 1px solid var(--wp--custom--on-dark--border);
}

.nf-on-dark .nf-value__icon {
	background-color: rgba(147, 180, 251, 0.12);
	background-color: color-mix(in srgb, var(--wp--custom--on-dark--accent) 12%, transparent);
	color: var(--wp--custom--on-dark--accent);
}

.nf-on-dark .nf-value__text {
	color: var(--wp--custom--on-dark--muted);
}

/*
 * Panel de tecnologías, bajo los compromisos y con su mismo material: la
 * explicación a la izquierda y las tecnologías con la nota a la derecha desde
 * 992px; apilado por debajo. Etiquetas en contraste sobre blanco 19,55:1 y
 * nota en azul de marca sobre gris 4,82:1.
 */
.nf-tech-panel {
	display: grid;
	gap: var(--wp--preset--spacing--40) var(--wp--preset--spacing--60);
	grid-template-columns: minmax(0, 1fr);
	margin-block-start: var(--wp--preset--spacing--40);
	padding: clamp(1.5rem, 3vw, 2.5rem);
}

@media (min-width: 62em) {
	.nf-tech-panel {
		align-items: center;
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.nf-tech-panel__intro .nf-value__title {
	font-size: var(--wp--preset--font-size--x-large);
	line-height: 1.25;
	max-width: 24ch;
}

.nf-tech {
	display: flex;
	flex-wrap: wrap;
	gap: 0.45rem;
	list-style: none;
	margin: 0 0 1.25rem;
	padding: 0;
}

.nf-tech li {
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--custom--border-strong);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.2;
	padding: 0.45rem 0.85rem;
}

.nf-tech-panel__note {
	border-top: 1px solid var(--wp--custom--border-strong);
	color: var(--wp--preset--color--brand);
	font-weight: 500;
	margin: 0;
	padding-block-start: 1.25rem;
}

/*
 * EN RESERVA DESDE EL 18/09/2026: el patrón que usa estas clases
 * (patterns/hosting-planes.php) salió de la plantilla de hosting y hoy no se
 * pinta en ninguna página. Se conservan para reactivarlo.
 *
 * Planes de hosting: tres tarjetas blancas con borde fino, en una columna
 * centrada hasta 992px y en fila desde ahí. El precio va entre filetes y el
 * botón se apoya en el pie de la tarjeta, así que los tres quedan alineados
 * aunque las listas midan distinto. Al pasar, el mismo borde azul y la misma
 * elevación que las tarjetas de colaboración.
 *
 * Cabecera centrada: emoji sin fondo, nombre, para quién es y precio con el
 * IVA debajo. Bajo el precio, tres cifras clave en columnas separadas por
 * filetes (lo que diferencia un plan de otro de un vistazo) y después la lista,
 * alineada a la izquierda y completa en cada plan aunque se repita (lo pidió
 * el usuario: así se ve todo lo que incluye). La nota de las horas va en
 * .nf-plans__note, bajo la rejilla. El emoji crece y se inclina un poco al
 * pasar por la tarjeta.
 *
 * Los checks y el borde al pasar toman --nf-plan-accent, que es el color de
 * marca: en una página con color de categoría (.nf-cat-hosting) ya es el suyo.
 *
 * Contraste sobre blanco: nombre y precio 19,55:1, textos muted 5,45:1; checks
 * y borde en azul 5,17:1 o en verde #047857 5,48:1.
 */
.nf-plans {
	--nf-plan-accent: var(--wp--preset--color--brand);
	display: grid;
	gap: var(--wp--preset--spacing--40);
	grid-template-columns: minmax(0, 1fr);
	list-style: none;
	margin: 0 auto;
	max-width: 28rem;
	padding: 0;
}

@media (min-width: 62em) {
	.nf-plans {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		max-width: none;
	}
}

.nf-plan {
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	padding: clamp(1.5rem, 3vw, 2.25rem);
	transition: border-color var(--wp--custom--transition),
		box-shadow var(--wp--custom--transition),
		transform var(--wp--custom--transition);
}

.nf-plan:hover {
	border-color: var(--nf-plan-accent);
	box-shadow: var(--wp--preset--shadow--lift);
	transform: translateY(-4px);
}

/*
 * El emoji lo dibuja la fuente de emojis del sistema, así que su aspecto varía
 * algo entre Windows, macOS y móvil. Una sombra suave lo despega del blanco.
 */
.nf-plan__emoji {
	align-self: center;
	display: block;
	filter: drop-shadow(0 6px 8px rgba(11, 21, 51, 0.14));
	font-size: 2.75rem;
	line-height: 1;
	margin-block-end: 1rem;
	transition: transform 240ms cubic-bezier(0.2, 0.6, 0.3, 1);
}

.nf-plan:hover .nf-plan__emoji {
	transform: scale(1.12) rotate(-6deg);
}

.nf-plan__name {
	font-family: var(--wp--preset--font-family--bricolage);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 600;
	letter-spacing: 0;
	line-height: 1.25;
	margin: 0 0 0.4rem;
	text-align: center;
}

.nf-plan__text {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	margin: 0;
	text-align: center;
}

.nf-plan__price {
	align-items: baseline;
	border-block: 1px solid var(--wp--preset--color--border);
	display: flex;
	flex-wrap: wrap;
	font-family: var(--wp--preset--font-family--dm-sans);
	gap: 0.35rem;
	justify-content: center;
	margin: 1.5rem 0 0;
	padding-block: 1.25rem;
}

/*
 * Cifras clave. Cada par va con la etiqueta (dt) antes del valor (dd), que es
 * el orden correcto para un lector de pantalla; column-reverse pone el valor
 * arriba a la vista.
 */
.nf-plan__stats {
	border-bottom: 1px solid var(--wp--preset--color--border);
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	margin: 0 0 1.5rem;
	padding-block: 1.25rem;
	text-align: center;
}

.nf-plan__stats > div {
	display: flex;
	flex-direction: column-reverse;
	gap: 0.25rem;
	justify-content: flex-end;
	padding-inline: 0.35rem;
}

.nf-plan__stats > div + div {
	border-inline-start: 1px solid var(--wp--preset--color--border);
}

.nf-plan__stats dt {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.3;
}

.nf-plan__stats dd {
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 700;
	letter-spacing: -0.01em;
	line-height: 1.1;
	margin: 0;
	white-space: nowrap;
}

.nf-plan__amount {
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--xx-large);
	font-weight: 700;
	letter-spacing: -0.025em;
	line-height: 1;
}

.nf-plan__period {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
}

/* El IVA, en su propia línea bajo el importe. */
.nf-plan__tax {
	color: var(--wp--preset--color--muted);
	flex-basis: 100%;
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--x-small);
	text-align: center;
}

.nf-plan__list {
	margin-block-end: 1.75rem;
}

.nf-plan__list li {
	font-size: var(--wp--preset--font-size--small);
}

.nf-plan__list li::before {
	color: var(--nf-plan-accent);
}

.nf-plan__list li + li {
	margin-block-start: 0.6rem;
}

.nf-plan__action {
	margin-block-start: auto;
}

.nf-plan__action .wp-block-button,
.nf-plan__action .wp-element-button {
	box-sizing: border-box;
	text-align: center;
	width: 100%;
}

/*
 * «Soporte sobre la web, no solo sobre el servidor» (hosting-soporte.php).
 *
 * Nota bajo la lista: muted sobre gris 5,09:1.
 */
.nf-duo__text > .nf-duo__note {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	margin-block: 1.25rem 0;
}

/*
 * Comparación en dos columnas desde 640px. El hosting convencional va apagado
 * (sin fondo, borde discontinuo y guiones); el plan, en blanco con el borde en
 * el color de la categoría y checks. Guion y texto muted sobre gris 5,09:1;
 * borde verde sobre gris 5,12:1.
 */
.nf-compare {
	display: grid;
	gap: var(--wp--preset--spacing--40);
	grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 40em) {
	.nf-compare {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.nf-compare__col {
	border-radius: var(--wp--custom--radius--lg);
	box-sizing: border-box;
	padding: clamp(1.25rem, 3vw, 2rem);
}

.nf-compare__col--basic {
	border: 1px dashed var(--wp--custom--border-control);
	color: var(--wp--preset--color--muted);
}

.nf-compare__col--plan {
	background-color: var(--wp--preset--color--base);
	border: 2px solid var(--wp--preset--color--brand);
	box-shadow: var(--wp--preset--shadow--lift);
}

.nf-compare__title {
	font-family: var(--wp--preset--font-family--bricolage);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 600;
	letter-spacing: 0;
	line-height: 1.3;
	margin: 0 0 1rem;
}

.nf-compare__col--basic .nf-compare__title {
	color: var(--wp--preset--color--muted);
}

.nf-compare__list {
	font-size: var(--wp--preset--font-size--small);
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-compare__list li + li {
	margin-block-start: 0.75rem;
}

.nf-compare__col--basic .nf-compare__list li {
	padding-inline-start: 1.75rem;
	position: relative;
}

.nf-compare__col--basic .nf-compare__list li::before {
	content: "\2013";
	content: "\2013" / "";
	inset-inline-start: 0.25rem;
	position: absolute;
}

/*
 * Plataformas de e-commerce: criterios de elección en la tarjeta de la
 * derecha (reutiliza la columna destacada de .nf-compare).
 */
.nf-criteria__intro {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	margin: -0.5rem 0 1rem;
}

/*
 * Pasos encadenados («Una tienda preparada para crecer contigo»): lista
 * ordenada en tarjetas blancas, en columna en móvil, de tres en tres desde
 * 640px y en fila desde 992px, donde una flecha en el color de la categoría
 * une cada paso con el anterior (decorativa: content alternativo vacío).
 * Flecha morada sobre gris 6,63:1; títulos 19,55:1 sobre blanco.
 */
.nf-steps__caption {
	color: var(--wp--preset--color--muted);
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	margin: 0 0 1.25rem;
	text-align: center;
}

.nf-steps__caption--end {
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 500;
	margin: var(--wp--preset--spacing--50) 0 0;
}

.nf-steps {
	display: grid;
	gap: 0.75rem;
	grid-template-columns: minmax(0, 1fr);
	list-style: none;
	margin: 0;
	padding: 0;
}

@media (min-width: 40em) {
	.nf-steps {
		gap: 1rem;
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (min-width: 62em) {
	.nf-steps {
		column-gap: 2.25rem;
		grid-template-columns: repeat(6, minmax(0, 1fr));
	}
}

.nf-step {
	align-items: center;
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	gap: 0.65rem;
	padding: 1.25rem 0.75rem;
	position: relative;
	text-align: center;
}

.nf-step__icon {
	align-items: center;
	background-color: var(--wp--preset--color--accent-1);
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--custom--brand-dark);
	display: flex;
	height: 2.75rem;
	justify-content: center;
	width: 2.75rem;
}

.nf-step__icon svg {
	display: block;
	stroke-width: 1.75;
}

.nf-step__title {
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 600;
	line-height: 1.25;
}

@media (min-width: 62em) {
	.nf-step + .nf-step::before {
		color: var(--wp--preset--color--brand);
		content: "\2192";
		content: "\2192" / "";
		font-size: 1.25rem;
		inset-block-start: 50%;
		inset-inline-start: -1.7rem;
		line-height: 1;
		position: absolute;
		transform: translateY(-50%);
	}
}

/* Nota bajo el botón de las bandas de cierre: tenue sobre oscuro. */
.nf-on-dark .nf-cierre__note {
	color: var(--wp--custom--on-dark--muted);
	font-size: var(--wp--preset--font-size--small);
}

/*
 * Frase de remate centrada bajo una rejilla (chatbots de la página de IA).
 * Contraste sobre blanco 19,55:1.
 */
.nf-tagline {
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 500;
	margin: var(--wp--preset--spacing--50) auto 0;
	max-width: 40rem;
	text-align: center;
}

/*
 * Remate y piezas en la columna fija de un reparto editorial (automatización
 * y proceso de la página de IA). Remate en contraste sobre gris 18,24:1.
 */
.nf-split__tagline {
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 600;
	max-width: 36rem;
}

/* Sobre banda oscura (ciberseguridad gestionada): blanco, 10:1 o más. */
.nf-on-dark .nf-split__tagline {
	color: #FFFFFF;
}

.nf-split__intro > .nf-split__tech {
	margin-block: 0 1.25rem;
	max-width: 36rem;
}

.nf-split__intro > p.nf-split__tagline:last-child {
	margin-block-end: 0;
}

/*
 * Dos paneles de dashboard, lado a lado desde 992px: gris de superficie sobre
 * blanco, como las tarjetas de valores. El remate va al pie del panel, así que
 * los dos quedan alineados aunque sus listas midan distinto. Título 18,24:1 y
 * textos muted 5,09:1 sobre gris; checks en el color de la categoría.
 */
.nf-dash {
	display: grid;
	gap: var(--wp--preset--spacing--40);
	grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 62em) {
	.nf-dash {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.nf-dash__panel {
	background-color: var(--wp--preset--color--surface);
	border-radius: var(--wp--custom--radius--lg);
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	padding: clamp(1.5rem, 3vw, 2.5rem);
}

.nf-dash__title {
	font-family: var(--wp--preset--font-family--bricolage);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 600;
	letter-spacing: 0;
	line-height: 1.25;
	margin: 0 0 0.5rem;
}

.nf-dash__text {
	color: var(--wp--preset--color--muted);
	margin: 0 0 1.5rem;
}

.nf-dash__list {
	margin-block-end: 1.5rem;
}

.nf-dash__list li {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
}

.nf-dash__list strong {
	color: var(--wp--preset--color--contrast);
	font-weight: 600;
}

.nf-dash__remate {
	border-top: 1px solid var(--wp--custom--border-strong);
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--dm-sans);
	font-weight: 600;
	margin: auto 0 0;
	padding-block-start: 1.25rem;
}

/*
 * Nota bajo la entradilla de una columna fija (aviso de los planes de hosting
 * en la página de ciberseguridad): pequeña, gris y separada por un filete.
 * Muted sobre blanco 5,45:1; el enlace, en el color de la categoría.
 */
.nf-split__intro > .nf-split__note {
	border-top: 1px solid var(--wp--custom--border-strong);
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	max-width: 36rem;
	padding-block-start: 1.25rem;
}

/*
 * Comparación a todo el ancho, bajo un reparto editorial (capas de la página
 * de ciberseguridad): no pasa de 60rem y va centrada.
 */
.nf-compare--wide {
	margin-inline: auto;
	max-width: 60rem;
}

/*
 * Tarjeta de la regla 3-2-1 (backups): blanca sobre gris, con tres cifras en
 * columnas separadas por filetes. Cada par lleva la etiqueta (dt) antes del
 * valor (dd) para los lectores de pantalla y column-reverse pone la cifra
 * arriba. Cifras en el color de la categoría (rojo #B91C1C sobre blanco
 * 6,47:1), etiquetas y texto muted 5,45:1.
 */
.nf-rule {
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: var(--wp--preset--shadow--lift);
	box-sizing: border-box;
	padding: clamp(1.5rem, 3vw, 2.5rem);
}

.nf-rule__title {
	font-family: var(--wp--preset--font-family--bricolage);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 600;
	letter-spacing: 0;
	line-height: 1.25;
	margin: 0 0 1.25rem;
}

.nf-rule__stats {
	border-block: 1px solid var(--wp--preset--color--border);
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	margin: 0 0 1.25rem;
	padding-block: 1.25rem;
	text-align: center;
}

.nf-rule__stats > div {
	display: flex;
	flex-direction: column-reverse;
	gap: 0.35rem;
	justify-content: flex-end;
	padding-inline: 0.5rem;
}

.nf-rule__stats > div + div {
	border-inline-start: 1px solid var(--wp--preset--color--border);
}

.nf-rule__stats dt {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.3;
}

.nf-rule__stats dd {
	color: var(--wp--preset--color--brand);
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: var(--wp--preset--font-size--display);
	font-weight: 700;
	letter-spacing: -0.03em;
	line-height: 1;
	margin: 0;
}

.nf-rule__text {
	color: var(--wp--preset--color--muted);
	margin: 0;
}

/* Nota de las horas de soporte, centrada bajo la rejilla. */
.nf-plans__note {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.6;
	margin: var(--wp--preset--spacing--50) auto 0;
	max-width: 46rem;
	text-align: center;
}

.nf-plans__note p {
	margin: 0;
}

.nf-plans__note p + p {
	margin-block-start: 0.5rem;
}

.nf-plans__note strong {
	color: var(--wp--preset--color--contrast);
	font-weight: 600;
}

/*
 * «Desarrollo que se integra con tu agencia»: texto a la izquierda y esquema a
 * la derecha desde 992px; apilado por debajo.
 */
.nf-duo {
	align-items: center;
	display: grid;
	gap: var(--wp--preset--spacing--60);
	grid-template-columns: minmax(0, 1fr);
}

.nf-duo > * {
	margin-block: 0;
}

@media (min-width: 62em) {
	.nf-duo {
		column-gap: var(--wp--preset--spacing--70);
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

.nf-duo__text > h2,
.nf-duo__text > p {
	max-width: 36rem;
}

.nf-duo__text > .nf-duo__list {
	margin-block: 0;
}

.nf-duo__list li + li {
	margin-block-start: 1rem;
}

/*
 * Esquema de papeles: el cliente arriba, vuestra agencia en blanco y
 * Norfactory en el degradado profundo, unidos por un hilo que pasa a
 * discontinuo entre la agencia y Norfactory, que trabaja en segundo plano.
 * Va sobre gris con la malla fina de las miniaturas de Proyectos.
 *
 * Contraste: textos de las cajas blancas 19,6:1 y muted 5,45:1; texto blanco
 * sobre la parada más clara del degradado (#1E3A8A) 10,36:1.
 */
.nf-roles {
	background-color: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	box-sizing: border-box;
	display: grid;
	isolation: isolate;
	justify-items: center;
	overflow: hidden;
	padding: clamp(1.5rem, 4vw, 3rem) clamp(1rem, 4vw, 3rem);
	position: relative;
}

.nf-roles::before {
	background-image:
		linear-gradient(rgba(11, 21, 51, 0.05) 1px, transparent 1px),
		linear-gradient(90deg, rgba(11, 21, 51, 0.05) 1px, transparent 1px);
	background-size: 24px 24px;
	content: "";
	inset: 0;
	-webkit-mask-image: radial-gradient(ellipse at center, #000 20%, transparent 75%);
	mask-image: radial-gradient(ellipse at center, #000 20%, transparent 75%);
	pointer-events: none;
	position: absolute;
	z-index: -1;
}

.nf-roles > * {
	position: relative;
}

.nf-roles > * + * {
	margin-block-start: 1.75rem;
}

.nf-roles > * + *::before {
	block-size: 1.75rem;
	border-inline-start: 2px solid var(--wp--custom--border-strong);
	bottom: 100%;
	content: "";
	inset-inline-start: calc(50% - 1px);
	position: absolute;
}

.nf-roles > .nf-roles__link::before,
.nf-roles > .nf-role--us::before {
	border-inline-start-style: dashed;
}

.nf-roles__client,
.nf-roles__link {
	align-items: center;
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--custom--border-strong);
	border-radius: var(--wp--custom--radius--pill);
	display: inline-flex;
	gap: 0.45rem;
	line-height: 1.2;
	margin-block-end: 0;
	padding: 0.45rem 0.9rem;
	text-align: center;
}

/* Es un <p>: sin esto arrastra el margen superior del navegador. */
.nf-roles__client {
	color: var(--wp--preset--color--contrast);
	margin-block-start: 0;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

.nf-roles__link {
	border-style: dashed;
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--x-small);
}

:is(.nf-roles__client, .nf-roles__link) svg {
	color: var(--wp--preset--color--muted);
	display: block;
	flex: 0 0 auto;
}

.nf-role {
	align-items: center;
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: var(--wp--preset--shadow--soft);
	box-sizing: border-box;
	display: grid;
	gap: 1rem;
	grid-template-columns: 3rem minmax(0, 1fr);
	max-width: 24rem;
	padding: 1.25rem 1.4rem;
	width: 100%;
}

.nf-role--us {
	background-image: var(--wp--preset--gradient--deep);
	border-color: transparent;
	box-shadow: 0 24px 48px -20px rgba(11, 21, 51, 0.45);
}

.nf-role__icon {
	align-items: center;
	background-color: var(--wp--preset--color--accent-1);
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--custom--brand-dark);
	display: flex;
	height: 3rem;
	justify-content: center;
	width: 3rem;
}

.nf-role--us .nf-role__icon {
	background-color: rgba(147, 180, 251, 0.14);
	background-color: color-mix(in srgb, var(--wp--custom--on-dark--accent) 14%, transparent);
	color: var(--wp--custom--on-dark--accent);
}

.nf-role__text {
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: var(--wp--preset--font-size--large);
	letter-spacing: -0.01em;
	line-height: 1.3;
	margin: 0;
}

.nf-role--us .nf-role__text {
	color: #FFFFFF;
}

/* ---------------------------------------------------------------------------
   16. Página 404
   --------------------------------------------------------------------------- */

/*
 * Página de error (templates/404.html y patterns/error-404.php). Es la misma
 * apertura que las páginas de servicio —alto de ventana, malla en túnel, velo
 * y degradado claro—, así que aquí solo está lo que cambia: el contenido va en
 * una columna centrada, porque no hay ilustración a la derecha que equilibre
 * el texto, y el número hace de elemento gráfico.
 */
.nf-404__wrap {
	margin-inline: auto;
	max-width: 46rem;
	text-align: center;
}

/*
 * El velo de la apertura, centrado con el texto: en las páginas de servicio se
 * abre sobre la columna izquierda (30 % / 55 %) porque la derecha la ocupa la
 * ilustración. Un poco por encima del centro, que es donde cae el bloque de
 * número y titular.
 */
.nf-404::after {
	-webkit-mask-image: radial-gradient(62% 62% at 50% 46%, rgba(0, 0, 0, 0.75) 30%, transparent 85%);
	mask-image: radial-gradient(62% 62% at 50% 46%, rgba(0, 0, 0, 0.75) 30%, transparent 85%);
}

/*
 * El número, con el degradado del tramo destacado de los titulares (ver
 * .nf-hero__title em) y el mismo respaldo: el color sólido va primero, por si
 * el recorte sobre el texto no se aplica. Es decorativo y va con aria-hidden;
 * quien no ve la pantalla oye el titular, y el código de estado lo manda
 * WordPress en la cabecera HTTP.
 */
.nf-404__code {
	color: var(--wp--preset--color--brand-navy);
	font-family: var(--wp--preset--font-family--dm-sans);
	font-size: clamp(5rem, 13vw, 9rem);
	font-weight: 700;
	letter-spacing: -0.04em;
	line-height: 1;
	margin: 0;
}

@supports ((background-clip: text) or (-webkit-background-clip: text)) {
	.nf-404__code {
		-webkit-background-clip: text;
		background-clip: text;
		background-image: linear-gradient(110deg, var(--wp--preset--color--brand) 0%, var(--wp--preset--color--brand-navy) 72%);
		color: transparent;
	}
}

@media (forced-colors: active) {
	.nf-404__code {
		color: CanvasText;
	}
}

.nf-404__lead {
	margin-inline: auto;
	max-width: 36rem;
}

/*
 * Salidas del error. Van tras un filete, como los rasgos de las aperturas
 * (.nf-traits), para que no se lean como una tercera llamada a la acción: son
 * enlaces de repesca hacia el resto del sitio.
 */
.nf-404__links {
	border-top: 1px solid var(--wp--custom--border-strong);
	margin-block-start: var(--wp--preset--spacing--60);
	padding-block-start: var(--wp--preset--spacing--50);
}

.nf-404__links-title {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	margin: 0 0 1rem;
}

.nf-404__links ul {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem 1.75rem;
	justify-content: center;
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-404__links a {
	align-items: center;
	color: var(--wp--preset--color--contrast);
	display: inline-flex;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	gap: 0.4rem;
	text-decoration: none;
	transition: color var(--wp--custom--transition);
}

/* La misma flecha de texto que los enlaces «Ver…» de Servicios y del menú. */
.nf-404__links a::after {
	color: var(--wp--preset--color--muted);
	content: "\2192";
	content: "\2192" / "";
	font-family: var(--wp--preset--font-family--inter);
	font-weight: 400;
	transition: color var(--wp--custom--transition),
		transform var(--wp--custom--transition);
}

.nf-404__links a:hover,
.nf-404__links a:focus-visible {
	color: var(--wp--preset--color--brand);
}

.nf-404__links a:hover::after,
.nf-404__links a:focus-visible::after {
	color: var(--wp--preset--color--brand);
	transform: translateX(3px);
}

/* ---------------------------------------------------------------------------
   17. Pie
   --------------------------------------------------------------------------- */

/*
 * El pie cierra en claro: gris de superficie, no la banda oscura. El filo
 * superior es para las plantillas que no terminan en la banda de contacto —
 * ahí el pie llegaría sobre blanco y sin el filo no habría corte visible.
 *
 * Todo en Inter (16/09/2026). Los títulos de columna y el subpié iban en la
 * mono y sonaban a panel de control; la familia se declara aquí y otra vez en
 * los títulos, porque theme.json da la suya a los encabezados.
 *
 * La jerarquía la marca el color, no el tamaño: los títulos en el negro del
 * texto, los enlaces en el gris tenue y de vuelta al negro al pasar por
 * encima. Gris tenue sobre #F0F2F5: 4,86:1; negro sobre el mismo fondo:
 * 17,80:1.
 */
.nf-footer {
	background-color: var(--wp--preset--color--surface-alt);
	border-top: 1px solid var(--wp--preset--color--border);
	font-family: var(--wp--preset--font-family--inter);
}

/*
 * Las cuatro columnas, en rejilla propia y no en el flex del bloque: así la
 * primera puede ser más ancha que las otras tres sin repartir porcentajes a
 * mano, y el paso a dos columnas y a una sola no depende del corte único de
 * 781 px que trae el núcleo.
 *
 * El selector lleva las dos clases del bloque porque el núcleo declara el
 * display de .wp-block-columns desde su propio layout.
 */
.nf-footer .wp-block-columns.nf-footer__cols {
	display: grid;
	gap: var(--wp--preset--spacing--50);
	grid-template-columns: 1fr;
}

@media (min-width: 40em) {
	.nf-footer .wp-block-columns.nf-footer__cols {
		column-gap: var(--wp--preset--spacing--40);
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 56.25em) {
	.nf-footer .wp-block-columns.nf-footer__cols {
		column-gap: var(--wp--preset--spacing--60);
		grid-template-columns: 1.6fr 1fr 1fr 1fr;
	}
}

/* El bloque de columnas trae su propio flex-basis y márgenes; en la rejilla
   sobran. */
.nf-footer .nf-footer__brand,
.nf-footer .nf-footer__col {
	flex-basis: auto;
	margin: 0;
}

.nf-footer__tagline {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.6;
	margin-block: 0;
	max-width: 34ch;
}

/*
 * El correo, en la columna de marca. La dirección va en el mismo gris tenue que
 * los enlaces de las listas y se pone negra al pasar por encima; el sobre, en
 * negro desde el principio, para que la fila se reconozca de un vistazo sin
 * darle al texto más peso del que tiene el resto del pie.
 *
 * El icono se centra con la línea por su propia caja, con flex, y no por la
 * línea base, que con un SVG no dice nada.
 */
.nf-footer__mail {
	margin-block: 1.125rem 0;
}

.nf-footer__mail a {
	align-items: center;
	color: var(--wp--preset--color--muted);
	display: inline-flex;
	font-size: var(--wp--preset--font-size--small);
	gap: 0.5rem;
	text-decoration: none;
	transition: color var(--wp--custom--transition);
}

.nf-footer__mail a:hover,
.nf-footer__mail a:focus-visible {
	color: var(--wp--preset--color--contrast);
}

.nf-footer__mail-icon {
	align-items: center;
	color: var(--wp--preset--color--contrast);
	display: inline-flex;
	flex: 0 0 auto;
	justify-content: center;
}

.nf-footer__heading {
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--inter);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	letter-spacing: 0.08em;
	line-height: 1.2;
	margin-block: 0 1.125rem;
	text-transform: uppercase;
}

/*
 * El tema padre da a los elementos de cualquier lista un `margin-top: 0.5rem`
 * (core/list en su theme.json). Aquí sobra: separa el primer enlace de su
 * título más de la cuenta y, en el subpié, baja los enlaces legales fuera del
 * centro. Se anula en los dos sitios y la separación la pone `li + li`.
 */
.nf-footer__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-footer__list li {
	margin: 0;
}

.nf-footer__list li + li {
	margin-block-start: 0.625rem;
}

/*
 * El azul de enlace convertiría la columna en una mancha: aquí los enlaces son
 * texto normal y solo el puntero los marca.
 */
.nf-footer__list a {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.4;
	text-decoration: none;
	transition: color var(--wp--custom--transition);
}

.nf-footer__list a:hover,
.nf-footer__list a:focus-visible {
	color: var(--wp--preset--color--contrast);
}

/*
 * Subpié: a un lado el aviso de siempre, al otro los dos enlaces legales. Con
 * el envoltorio en flex del bloque, cuando no caben en una línea la lista se
 * va debajo y ambos quedan alineados a la izquierda.
 *
 * Es él quien cierra el pie: mide 50 px de alto, con el texto centrado, y el
 * grupo de arriba ya no pone relleno inferior. El relleno de medio rem solo
 * entra en juego cuando el contenido se parte en dos líneas y la caja tiene que
 * crecer; para que esos 50 px sigan siendo el alto total y no el del contenido,
 * la caja se mide con el borde incluido —el sitio no trae border-box global—.
 */
.nf-footer__bottom {
	align-items: center;
	border-top: 1px solid var(--wp--preset--color--border);
	box-sizing: border-box;
	font-family: var(--wp--preset--font-family--inter);
	min-block-size: 50px;
	padding-block: 0.5rem;
}

/* Misma altura de línea en los dos lados del subpié: así los textos caen a la
   misma altura, y no solo sus cajas. */
.nf-footer__copy,
.nf-footer__legal a {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: 0;
	line-height: 1.5;
}

.nf-footer__legal {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1.5rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.nf-footer__legal li {
	margin: 0;
}

.nf-footer__legal a {
	text-decoration: none;
	transition: color var(--wp--custom--transition);
}

.nf-footer__legal a:hover,
.nf-footer__legal a:focus-visible {
	color: var(--wp--preset--color--contrast);
}

/* ---------------------------------------------------------------------------
   18. Movimiento reducido
   --------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms;
		animation-iteration-count: 1;
		scroll-behavior: auto;
		transition-duration: 0.01ms;
	}

	.nf-card:hover,
	.nf-card:focus-within,
	.nf-service:hover,
	.nf-service:focus-within,
	.nf-mode:hover,
	.nf-mode--link:hover .nf-mode__link span[aria-hidden],
	.nf-plan:hover,
	.nf-plan:hover .nf-plan__emoji,
	.nf-flow__item:hover .nf-flow__marker {
		transform: none;
	}

	/* La onda de los iconos de servicio es puro movimiento: sin él no queda nada
	   que mostrar, así que se retira. */
	.nf-service:hover .nf-service__icon::before,
	.nf-service:hover .nf-service__icon::after,
	.nf-service:focus-within .nf-service__icon::before,
	.nf-service:focus-within .nf-service__icon::after {
		animation: none;
	}


	.nf-service:hover .nf-service__link span,
	.nf-service:focus-within .nf-service__link span,
	.nf-assurance__link:hover span,
	.nf-assurance__link:focus-visible span {
		transform: none;
	}
}

/* ---------------------------------------------------------------------------
   19. Impresión
   --------------------------------------------------------------------------- */

/*
 * Al imprimir, el navegador descarta los fondos: lo que va sobre la banda
 * oscura saldría en texto claro sobre papel blanco. Aquí se recupera el color
 * de tinta y se retira lo que solo tiene sentido en pantalla.
 */
@media print {
	.nf-on-dark,
	.nf-on-dark :where(h1, h2, h3, h4, h5, p, li, figcaption),
	.nf-on-dark :where(a):not(.wp-element-button) {
		color: var(--wp--preset--color--contrast);
	}

	.wp-site-blocks > header {
		margin-block-end: 0;
		position: static;
	}

	.nf-header::before {
		display: none;
	}

	/* En papel no hay ventana que llenar ni barra superpuesta que esquivar. */
	.nf-hero,
	.nf-page-hero {
		display: block;
		min-height: 0;
		padding-block: var(--wp--preset--spacing--60);
	}

	.nf-hero::before,
	.nf-hero::after,
	.nf-page-hero::before,
	.nf-page-hero::after {
		display: none;
	}

	/* Navegación, botones y formulario no sirven en papel. */
	.nf-nav,
	.nf-header__cta,
	.nf-form,
	.nf-titular__acciones,
	.wp-block-buttons {
		display: none;
	}

	/*
	 * El número del 404 se recorta sobre un degradado y, sin fondos, saldría
	 * transparente: en papel vuelve a ser tinta.
	 */
	.nf-404__code {
		background-image: none;
		color: var(--wp--preset--color--contrast);
	}

	.nf-card,
	.nf-shot__frame {
		box-shadow: none;
	}

	.nf-shot__frame {
		transform: none;
	}

}
