/**
 * main.css — Tema juanda-portfolio
 *
 * Grueso de los estilos del tema (bento grids, animaciones, responsive).
 * Fuente de verdad de diseño: design/design-guide.md.
 *
 * Este archivo se comparte entre todas las secciones de la Home; cada tarea
 * (T02–T06) añade sus bloques sin eliminar los de las anteriores. Los
 * custom properties de :root son el sistema de diseño único: colores,
 * tipografía y easings NO deben hardcodearse repetidamente en el resto del
 * archivo.
 *
 * Índice:
 *   1. Custom properties (sistema de diseño)
 *   2. Utilidades genéricas
 *   3. Cabecera / navegación (site-header, site-nav — markup de header.php, T01)
 *   4. Sección Hero (T02)
 *   5. Sección Sobre mí / Especialización (T03)
 *   6. Sección Servicios / Soluciones IA & Automatización (T04)
 *   7. Sección Proyectos WordPress Destacados (T05)
 *   8. Sección Contacto / CTA Final (T06)
 *   9. Media queries responsive
 *   10. Accesibilidad: prefers-reduced-motion
 */

/* ==========================================================================
   1. Custom properties — sistema de diseño (design-guide.md §3.1, §3.5)
   ========================================================================== */

:root {
	/* Colores base */
	--color-dark: #121212;
	--color-light: #e5e5e5;
	--color-white: #ffffff;

	/* Acentos (design-guide.md §3.1 — no deben superar ~10% del área visible) */
	--color-accent-lime: #ccff00;
	--color-accent-yellow: #ffff00;
	--color-accent-mint: #dfff00;

	/* Texto de cuerpo según fondo */
	--color-text-on-light: #333333;
	--color-text-on-dark: #b0b0b0;

	/* Tarjetas y bordes */
	--color-card-bg-dark: #1a1a1a;
	--color-card-border-dark: #2a2a2a;
	--color-card-border-light: #e0e0e0;
	--color-border-input: #333333; /* Borde inferior de inputs en reposo, design-guide.md §2.5 */

	/* Color de error de formulario: no está en design-guide.md (solo define
	   éxito/hover en lima/amarillo/menta), se usa un rojo estándar con
	   contraste AA sobre --color-dark para los mensajes de error del
	   formulario de contacto (T06). */
	--color-error: #ff6b6b;

	/* Tipografía (design-guide.md §3.5) */
	--font-display: 'Space Grotesk', 'Helvetica Neue', Arial, sans-serif;
	--font-body: 'Inter', 'Helvetica Neue', Arial, sans-serif;
	--font-mono: 'JetBrains Mono', 'Courier New', monospace;

	/* Escalas tipográficas fluidas */
	--fs-h1: clamp(4.5rem, 3.5rem + 4vw, 6rem); /* 72px – 96px, design-guide.md §2.1 */
	--fs-h2: clamp(2rem, 1.6rem + 2vw, 3rem); /* hasta 48px, design-guide.md §2.2/2.3/2.4 */
	--fs-h2-contact: clamp(2.25rem, 1.6rem + 3vw, 3.5rem); /* hasta 56px, design-guide.md §2.5 */

	/* Easing / transiciones */
	--ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);
	--ease-out: cubic-bezier(0.16, 1, 0.3, 1);

	/* Forma */
	--radius-pill: 999px;
	--radius-lg: 20px;
	--radius-md: 16px;

	/* Layout */
	--nav-height: 84px;
	--content-max-width: 1440px;
}

/* ==========================================================================
   2. Utilidades genéricas
   ========================================================================== */

html {
	scroll-behavior: smooth;
}

body {
	font-family: var(--font-body);
	background-color: var(--color-dark);
	color: var(--color-white);
}

/* Permite que los anclajes (#servicios, #proyectos, #contacto) no queden
   tapados bajo la nav fija al hacer scroll. */
section[id] {
	scroll-margin-top: var(--nav-height);
}

/* Oculta contenido visualmente mientras lo mantiene accesible para lectores
   de pantalla (usado por el H1 del Hero para desacoplar el texto animado
   del texto accesible). */
.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* Botón pill-shape reutilizable (design-guide.md §2.1 y §3.2). */
.btn-primary {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 1rem;
	line-height: 1;
	color: var(--color-dark);
	background-color: var(--color-accent-lime);
	padding: 16px 40px;
	border: none;
	border-radius: var(--radius-pill);
	cursor: pointer;
	text-decoration: none;
	transition: all 0.3s var(--ease-bounce);
}

.btn-primary:hover,
.btn-primary:focus-visible {
	background-color: var(--color-accent-mint);
	transform: translateY(-2px);
	box-shadow: 0 8px 24px rgba(204, 255, 0, 0.3);
}

.btn-primary:focus-visible {
	outline: 2px solid var(--color-white);
	outline-offset: 3px;
}

/* ==========================================================================
   3. Cabecera / navegación (markup en header.php, T01)
   ========================================================================== */

.site-header {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 1000;
}

.site-nav {
	display: flex;
	align-items: center;
	justify-content: space-between;
	min-height: var(--nav-height);
	padding: 0 clamp(1.5rem, 5vw, 3rem);
	background-color: rgba(18, 18, 18, 0.8);
	backdrop-filter: blur(12px);
	-webkit-backdrop-filter: blur(12px);
}

.site-nav__logo {
	display: inline-flex;
	align-items: center;
}

.site-nav__logo-text {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.25rem;
	color: var(--color-white);
}

.site-nav__menu {
	display: flex;
	align-items: center;
	gap: 2.5rem;
}

.site-nav__link {
	position: relative;
	display: inline-block;
	font-family: var(--font-body);
	font-weight: 500;
	font-size: 0.95rem;
	color: rgba(255, 255, 255, 0.7);
	padding: 0.35rem 0;
	transition: color 0.3s ease;
}

.site-nav__link::after {
	content: '';
	position: absolute;
	left: 0;
	bottom: -2px;
	width: 0;
	height: 2px;
	background-color: var(--color-accent-lime);
	transition: width 0.3s ease;
}

.site-nav__link:hover,
.site-nav__link:focus-visible {
	color: var(--color-white);
}

.site-nav__link:hover::after,
.site-nav__link:focus-visible::after {
	width: 100%;
}

.site-nav__toggle {
	display: none;
	flex-direction: column;
	justify-content: center;
	gap: 5px;
	padding: 8px;
	background: transparent;
}

.site-nav__toggle-bar {
	display: block;
	width: 24px;
	height: 2px;
	background-color: var(--color-white);
	transition: transform 0.3s ease, opacity 0.3s ease;
}

/* ==========================================================================
   4. Sección Hero (T02) — design-guide.md §2.1
   ========================================================================== */

.hero {
	position: relative;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
	justify-content: center;
	background-color: var(--color-dark);
	overflow: hidden;
	padding-top: var(--nav-height);
}

.hero__grid {
	flex: 1;
	display: grid;
	grid-template-columns: 1.15fr 0.85fr;
	align-items: center;
	gap: clamp(2rem, 5vw, 4rem);
	width: 100%;
	max-width: var(--content-max-width);
	margin: 0 auto;
	padding: clamp(2rem, 6vh, 4rem) clamp(1.5rem, 5vw, 5rem);
}

.hero__content {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 2.5rem;
}

.hero__title {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: var(--fs-h1);
	line-height: 1.05;
	letter-spacing: -0.02em;
	color: var(--color-white);
}

.hero__highlight {
	color: var(--color-accent-lime);
	text-shadow: 0 0 24px rgba(204, 255, 0, 0.35);
}

/* Cursor de escritura, insertado dinámicamente por assets/js/main.js.
   Si el JS no llega a ejecutarse, simplemente no existe: no depende de él
   ningún contenido, solo el efecto visual de "|" parpadeante. */
.hero__cursor {
	display: inline-block;
	width: 3px;
	height: 0.85em;
	margin-left: 4px;
	background-color: var(--color-accent-lime);
	vertical-align: text-bottom;
	animation: hero-cursor-blink 0.8s steps(1) infinite;
}

.hero__cursor.is-done {
	opacity: 0;
	animation: none;
}

@keyframes hero-cursor-blink {
	50% {
		opacity: 0;
	}
}

.hero__cta {
	/* Hereda el estilo de .btn-primary; sin overrides adicionales. */
}

.hero__visual {
	position: relative;
	width: 100%;
	height: min(70vh, 640px);
}

.hero__canvas {
	display: block;
	width: 100%;
	height: 100%;
}

.hero__scroll-indicator {
	position: absolute;
	left: 50%;
	bottom: clamp(1.5rem, 4vh, 2.5rem);
	transform: translateX(-50%);
	display: flex;
	justify-content: center;
}

.hero__scroll-line {
	width: 2px;
	height: 56px;
	background-color: var(--color-accent-yellow);
	opacity: 0.3;
	transform-origin: top center;
	animation: hero-scroll-pulse 2s ease-in-out infinite;
}

@keyframes hero-scroll-pulse {
	0%,
	100% {
		transform: scaleY(1);
		opacity: 0.3;
	}

	50% {
		transform: scaleY(1.3);
		opacity: 1;
	}
}

/* ==========================================================================
   5. Sección Sobre mí / Especialización (T03) — design-guide.md §2.2
   ========================================================================== */

.about {
	background-color: var(--color-light);
	padding: clamp(4rem, 8vw, 7rem) 0;
}

.about__container {
	max-width: var(--content-max-width);
	margin: 0 auto;
	padding: 0 clamp(1.5rem, 5vw, 5rem);
}

.about__title {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: var(--fs-h2);
	color: var(--color-dark);
	margin-bottom: 2.5rem;
}

/* Bento grid 2×2 asimétrico: columna de la foto/stack más estrecha que la
   columna de texto/métricas (design-guide.md dixit "asimétrico"). */
.about__grid {
	display: grid;
	grid-template-columns: 0.9fr 1.4fr;
	gap: 1.5rem;
}

/* Tarjeta bento genérica (texto, stack, métricas). El marco de la foto NO
   usa esta clase: tiene su propia especificación de marco oscuro (ver
   .about__frame más abajo), no es una "tarjeta bento" blanca estándar. */
.about__card {
	background-color: var(--color-white);
	border-radius: var(--radius-md);
	border: 1px solid var(--color-card-border-light);
	box-shadow: 0 4px 24px rgba(0, 0, 0, 0.04);
	padding: clamp(1.5rem, 3vw, 2.5rem);
	/* Solo se anima color de borde + box-shadow (no dimensiones), para que
	   el hover no provoque Content Layout Shift. */
	transition: border-color 0.3s var(--ease-out), box-shadow 0.3s var(--ease-out);
}

/* El "borde de 2px lima" del hover se simula con un anillo de box-shadow de
   1px sumado al borde real de 1px, en vez de aumentar border-width: así no
   se desplaza el contenido de la tarjeta ni las columnas vecinas (evita CLS). */
.about__card:hover,
.about__card:focus-within {
	border-color: var(--color-accent-lime);
	box-shadow: 0 4px 24px rgba(0, 0, 0, 0.04), 0 0 0 1px var(--color-accent-lime);
}

.about__card-title {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: 1.5rem;
	color: var(--color-dark);
	margin-bottom: 1rem;
}

.about__text {
	font-family: var(--font-body);
	font-weight: 400;
	font-size: 1.125rem; /* 18px */
	line-height: 1.6;
	color: var(--color-text-on-light);
}

/* Listas inline "A · B · C" (stack tecnológico y métricas), separadas por
   un punto medio generado con CSS para mantener el texto en elementos <li>
   semánticos en vez de concatenar todo en un único nodo de texto. */
.about__inline-list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 0;
	font-family: var(--font-body);
	font-size: 1rem;
	color: var(--color-text-on-light);
}

.about__inline-list li {
	font-weight: 500;
}

.about__inline-list li:not(:first-child) {
	margin-left: 0.5rem;
}

.about__inline-list li:not(:first-child)::before {
	content: '\00b7';
	display: inline-block;
	margin-right: 0.5rem;
	color: var(--color-dark);
}

.about__metrics-list li {
	font-weight: 600;
}

/* Marco de la foto de perfil placeholder (design-guide.md §2.2). */
.about__frame {
	display: flex;
}

.about__photo-placeholder {
	width: 100%;
	aspect-ratio: 4 / 5;
	border-radius: var(--radius-lg);
	border: 3px solid var(--color-dark);
	background-color: var(--color-card-bg-dark);
	display: flex;
	align-items: center;
	justify-content: center;
}

.about__photo-initials {
	font-family: var(--font-display);
	font-weight: 700;
	/* ~25–30% de la altura del bloque (aproximado con vw, ya que el bloque
	   escala con el ancho de columna del grid, no exactamente con el
	   viewport; el clamp mantiene el tamaño legible en los extremos). */
	font-size: clamp(2.75rem, 6vw, 5rem);
	color: var(--color-accent-lime);
	line-height: 1;
}

/* ==========================================================================
   6. Sección Servicios / Soluciones IA & Automatización (T04) — design-guide.md §2.3
   ========================================================================== */

.services {
	background-color: var(--color-dark);
	padding: clamp(4rem, 8vw, 7rem) 0;
}

.services__container {
	max-width: var(--content-max-width);
	margin: 0 auto;
	padding: 0 clamp(1.5rem, 5vw, 5rem);
}

.services__title {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: var(--fs-h2);
	color: var(--color-white);
	margin-bottom: 2.5rem;
}

/* Bento Grid 3 columnas con tarjeta central destacada (design-guide.md §2.3). */
.services__grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1.5rem;
	align-items: stretch;
}

.services__card {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.25rem;
	background-color: var(--color-card-bg-dark);
	border-radius: var(--radius-lg);
	border: 1px solid var(--color-card-border-dark);
	padding: clamp(1.75rem, 3vw, 2.5rem);
	/* Tarjetas Servicios (design-guide.md §3.2): borde + escala + brillo sutil. */
	transition: border-color 0.4s var(--ease-out), transform 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out);
}

.services__card:hover,
.services__card:focus-within {
	border-color: var(--color-accent-lime);
	transform: scale(1.02);
}

/* Tarjeta destacada central: fondo idéntico a las estándar (nunca relleno
   lima, ver CLAUDE.md §7 / presupuesto de acento ~10% del área visible),
   borde 2px lima y brillo animado infinito (design-guide.md §2.3 y §3.3
   "Tarjeta IA activa"). */
.services__card--featured {
	border: 2px solid var(--color-accent-lime);
	box-shadow: 0 0 40px rgba(204, 255, 0, 0.08);
	animation: services-glow-pulse 2.75s ease-in-out infinite alternate;
}

/* La tarjeta destacada ya tiene borde lime en reposo: el hover no cambia el
   color de borde (no hay contraste que mostrar), solo aporta la misma
   escala sutil que las tarjetas estándar. */
.services__card--featured:hover,
.services__card--featured:focus-within {
	border-color: var(--color-accent-lime);
}

@keyframes services-glow-pulse {
	0% {
		box-shadow: 0 0 40px rgba(204, 255, 0, 0.08);
	}

	100% {
		box-shadow: 0 0 64px rgba(204, 255, 0, 0.22);
	}
}

/* Badge "Destacado": pill lima, texto oscuro, superpuesta al borde superior
   de la tarjeta (design-guide.md §3.1 — uso de #DFFF00/#CCFF00 en badges de
   "destacado"; aquí se usa el lima principal según lo cerrado en T04). */
.services__badge {
	position: absolute;
	top: -14px;
	right: 1.75rem;
	display: inline-flex;
	align-items: center;
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 12px;
	line-height: 1;
	color: var(--color-dark);
	background-color: var(--color-accent-lime);
	padding: 4px 12px;
	border-radius: var(--radius-pill);
}

/* Iconos de línea (design-guide.md §2.3): trazo fino en lima, con animación
   de "dibujado" (stroke-dasharray/stroke-dashoffset) al hover/focus-within
   de la tarjeta contenedora. El valor 120 es holgado respecto a la longitud
   real de cualquier trazo dentro del viewBox 48×48 de estos iconos, de modo
   que en reposo el trazo queda completamente oculto. */
.services__icon {
	width: 48px;
	height: 48px;
}

.services__icon svg {
	width: 100%;
	height: 100%;
}

.services__icon svg * {
	stroke-dasharray: 120;
	stroke-dashoffset: 120;
	transition: stroke-dashoffset 0.5s var(--ease-out);
}

.services__card:hover .services__icon svg *,
.services__card:focus-within .services__icon svg * {
	stroke-dashoffset: 0;
}

.services__card-title {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: 1.75rem; /* 28px, design-guide.md §2.3 */
	color: var(--color-white);
}

.services__card-text {
	font-family: var(--font-body);
	font-weight: 400;
	font-size: 1rem; /* 16px, design-guide.md §2.3 */
	line-height: 1.6;
	color: var(--color-text-on-dark);
	flex: 1;
}

/* Enlace "Ver más" / "Solicitar demo": la flecha vive en un <span> aparte
   para poder desplazarla 8px a la derecha en hover sin mover el texto
   (design-guide.md §2.3). */
.services__card-link {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	margin-top: auto;
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 1rem;
	color: var(--color-accent-lime);
}

.services__card-link-arrow {
	display: inline-block;
	transition: transform 0.3s var(--ease-out);
}

.services__card-link:hover .services__card-link-arrow,
.services__card-link:focus-visible .services__card-link-arrow {
	transform: translateX(8px);
}

.services__card-link:focus-visible {
	outline: 2px solid var(--color-accent-lime);
	outline-offset: 4px;
}

/* ==========================================================================
   7. Sección Proyectos WordPress Destacados (T05) — design-guide.md §2.4
   ========================================================================== */

.projects {
	background-color: var(--color-light);
	padding: clamp(4rem, 8vw, 7rem) 0;
}

.projects__container {
	max-width: var(--content-max-width);
	margin: 0 auto;
	padding: 0 clamp(1.5rem, 5vw, 5rem);
}

.projects__title {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: var(--fs-h2);
	color: var(--color-dark);
	margin-bottom: 2.5rem;
}

/* Grid de 2 columnas con filas uniformes (NO masonry real con column-count):
   los 4 placeholders de preview comparten el mismo aspect-ratio (4/3) y el
   contenido de cada tarjeta tiene una altura similar, así que un grid simple
   ya reproduce el efecto de mosaico sin la complejidad ni los problemas de
   orden de lectura para lectores de pantalla que introduce column-count. */
.projects__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 1.5rem;
}

.projects__card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1rem;
	padding-bottom: 1.25rem;
	border-bottom: 3px solid transparent;
	/* Hover de tarjeta completa, no solo del preview (design-guide.md §2.4). */
	transition: border-color 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out);
}

.projects__card:hover,
.projects__card:focus-within {
	border-bottom-color: var(--color-accent-lime);
	box-shadow: 0 20px 60px rgba(0, 0, 0, 0.12);
}

/* Preview de proyecto: capa base sólida + icono de línea + overlay oscuro
   que se desvanece al hover, más la pill de tecnología. */
.projects__preview {
	position: relative;
	width: 100%;
	aspect-ratio: 4 / 3;
	border-radius: var(--radius-md);
	overflow: hidden;
	transition: transform 0.4s var(--ease-out);
}

.projects__card:hover .projects__preview,
.projects__card:focus-within .projects__preview {
	transform: scale(1.05);
}

.projects__preview-base {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background-color: var(--color-card-bg-dark);
}

.projects__preview-base svg {
	width: clamp(48px, 8vw, 72px);
	height: clamp(48px, 8vw, 72px);
}

.projects__preview-overlay {
	position: absolute;
	inset: 0;
	background-color: var(--color-dark);
	opacity: 0.6;
	transition: opacity 0.4s var(--ease-out);
}

.projects__card:hover .projects__preview-overlay,
.projects__card:focus-within .projects__preview-overlay {
	opacity: 0;
}

/* Tag de tecnología (design-guide.md §2.4): oculto en reposo, aparece sobre
   el preview al hover/focus-within de la tarjeta completa. */
.projects__tag {
	position: absolute;
	left: 1rem;
	bottom: 1rem;
	display: inline-flex;
	align-items: center;
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 12px;
	line-height: 1;
	color: var(--color-accent-lime);
	background-color: var(--color-dark);
	padding: 4px 12px;
	border-radius: var(--radius-pill);
	opacity: 0;
	transform: translateY(8px);
	transition: opacity 0.4s var(--ease-out), transform 0.4s var(--ease-out);
}

.projects__card:hover .projects__tag,
.projects__card:focus-within .projects__tag {
	opacity: 1;
	transform: translateY(0);
}

.projects__card-title {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: 1.5rem; /* 24px, design-guide.md §2.4 */
	color: var(--color-dark);
}

.projects__card-text {
	font-family: var(--font-body);
	font-weight: 400;
	font-size: 1rem;
	line-height: 1.6;
	color: var(--color-text-on-light);
}

/* Enlace "Ver caso": misma solución que .services__card-link (T04), la
   flecha vive en un <span> aparte para desplazarse 8px en hover sin mover el
   texto. Área de toque mínima 44px en móvil, ver media query de abajo. */
.projects__card-link {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	margin-top: auto;
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 1rem;
	color: var(--color-dark);
}

.projects__card-link-arrow {
	display: inline-block;
	transition: transform 0.3s var(--ease-out);
}

.projects__card-link:hover .projects__card-link-arrow,
.projects__card-link:focus-visible .projects__card-link-arrow {
	transform: translateX(8px);
}

.projects__card-link:focus-visible {
	outline: 2px solid var(--color-dark);
	outline-offset: 4px;
}

/* ==========================================================================
   8. Sección Contacto / CTA Final (T06) — design-guide.md §2.5
   ========================================================================== */

.contact {
	background-color: var(--color-dark);
	padding: clamp(4rem, 8vw, 7rem) 0;
}

.contact__container {
	max-width: var(--content-max-width);
	margin: 0 auto;
	padding: 0 clamp(1.5rem, 5vw, 5rem);
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: clamp(2.5rem, 6vw, 5rem);
	align-items: start;
}

.contact__intro {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.75rem;
}

.contact__title {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: var(--fs-h2-contact);
	line-height: 1.15;
	color: var(--color-white);
}

/* Span CTA "extraordinario" (design-guide.md §2.5 y §3.3): brillo sutil
   pulsante, oscilando entre un text-shadow bajo y uno alto. Bajo
   prefers-reduced-motion se fija en el valor bajo, ver sección 10. */
.contact__highlight {
	color: var(--color-accent-yellow);
	animation: contact-glow-pulse 2.75s ease-in-out infinite alternate;
}

@keyframes contact-glow-pulse {
	0% {
		text-shadow: 0 0 8px rgba(255, 255, 0, 0.25);
	}

	100% {
		text-shadow: 0 0 18px rgba(255, 255, 0, 0.55);
	}
}

.contact__email {
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 1.125rem;
	color: var(--color-white);
	transition: color 0.2s ease;
}

.contact__email:hover,
.contact__email:focus-visible {
	color: var(--color-accent-lime);
}

.contact__email:focus-visible {
	outline: 2px solid var(--color-accent-lime);
	outline-offset: 4px;
}

.contact__panel {
	display: flex;
	flex-direction: column;
	gap: 2.5rem;
}

.contact__form {
	display: flex;
	flex-direction: column;
	gap: 2rem;
}

/* Honeypot anti-spam (campo "web"): oculto "off-screen", nunca con
   type="hidden" ni display:none (ver comentario en section-contact.php). */
.contact__honeypot {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* Campo con label flotante (design-guide.md §3.2). El <label> vive justo
   después del <input>/<textarea> en el DOM para poder usar el combinador de
   hermano adyacente sin depender de JS. */
.contact__field {
	position: relative;
	padding-top: 1.5rem;
}

.contact__input {
	display: block;
	width: 100%;
	background-color: transparent;
	border: none;
	border-bottom: 2px solid var(--color-border-input);
	color: var(--color-white);
	font-family: var(--font-body);
	font-size: 1rem;
	padding: 0.5rem 0;
	transition: border-color 0.3s ease;
}

.contact__textarea {
	resize: vertical;
	min-height: 3.5rem;
}

.contact__input:focus {
	outline: none;
	border-bottom-color: var(--color-accent-lime);
}

.contact__label {
	position: absolute;
	left: 0;
	top: calc(1.5rem + 0.5rem);
	font-family: var(--font-body);
	font-size: 1rem;
	color: var(--color-text-on-dark);
	transform-origin: left top;
	transition: transform 0.2s ease, color 0.2s ease;
	pointer-events: none;
}

.contact__input:focus + .contact__label,
.contact__input:not(:placeholder-shown) + .contact__label {
	transform: translateY(-1.5rem) scale(0.8);
}

.contact__input:focus + .contact__label {
	color: var(--color-accent-lime);
}

.contact__submit {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	font-family: var(--font-body);
	font-weight: 700;
	font-size: 1rem;
	color: var(--color-dark);
	background-color: var(--color-accent-lime);
	border: none;
	border-radius: var(--radius-md);
	padding: 1rem 1.5rem;
	cursor: pointer;
	transition: background-color 0.3s ease;
}

.contact__submit:hover,
.contact__submit:focus-visible {
	background-color: var(--color-accent-mint);
}

.contact__submit:focus-visible {
	outline: 2px solid var(--color-white);
	outline-offset: 3px;
}

.contact__submit:disabled {
	cursor: not-allowed;
}

.contact__submit-label {
	transition: opacity 0.2s ease;
}

/* Spinner tricolor "procesando" (design-guide.md §3.2/§3.3): oculto por
   defecto, se superpone al botón mediante .is-loading (añadida por
   assets/js/main.js durante el fetch()). */
.contact__spinner {
	display: none;
	align-items: center;
	justify-content: center;
	gap: 8px;
}

.contact__submit.is-loading .contact__submit-label {
	opacity: 0;
}

.contact__submit.is-loading .contact__spinner {
	position: absolute;
	inset: 0;
	display: flex;
}

.contact__spinner-dot {
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background-color: var(--color-accent-lime);
	animation: contact-dot-pulse 1.2s infinite ease-in-out;
}

.contact__spinner-dot:nth-child(1) {
	background-color: var(--color-accent-lime);
	animation-delay: 0s;
}

.contact__spinner-dot:nth-child(2) {
	background-color: var(--color-accent-yellow);
	animation-delay: 0.2s;
}

.contact__spinner-dot:nth-child(3) {
	background-color: var(--color-accent-mint);
	animation-delay: 0.4s;
}

@keyframes contact-dot-pulse {
	0%,
	80%,
	100% {
		transform: scale(0.6);
		opacity: 0.5;
	}

	40% {
		transform: scale(1);
		opacity: 1;
	}
}

/* Mensaje de éxito/error tras el envío (role="status" + aria-live="polite"
   en el markup). Vacío por defecto: sin caja visible hasta que JS o el
   fallback de query string (?contacto=ok|error) lo rellenen. */
.contact__feedback {
	font-family: var(--font-body);
	font-size: 0.95rem;
	line-height: 1.6;
}

.contact__feedback:empty {
	display: none;
}

.contact__feedback--success,
.contact__feedback--error {
	padding: 0.85rem 1rem;
	border-radius: var(--radius-md);
	border: 1px solid transparent;
}

.contact__feedback--success {
	color: var(--color-accent-mint);
	background-color: rgba(223, 255, 0, 0.08);
	border-color: rgba(223, 255, 0, 0.3);
}

.contact__feedback--error {
	color: var(--color-error);
	background-color: rgba(255, 107, 107, 0.08);
	border-color: rgba(255, 107, 107, 0.3);
}

.contact__social {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	padding-top: 2rem;
	border-top: 1px solid var(--color-card-border-dark);
}

.contact__social-label {
	font-family: var(--font-body);
	font-size: 0.95rem;
	color: var(--color-text-on-dark);
}

.contact__social-links {
	display: flex;
	gap: 1rem;
}

/* Links sociales (design-guide.md §2.5/§3.1): iconos outline blancos en
   reposo, relleno lima al hover/focus, transición 200ms. */
.contact__social-link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	border-radius: 50%;
	border: 1px solid var(--color-card-border-dark);
	transition: border-color 0.2s ease;
}

.contact__social-link:hover,
.contact__social-link:focus-visible {
	border-color: var(--color-accent-lime);
}

.contact__social-link:focus-visible {
	outline: 2px solid var(--color-accent-lime);
	outline-offset: 3px;
}

.contact__social-icon {
	display: inline-flex;
	width: 24px;
	height: 24px;
}

.contact__social-icon svg {
	width: 100%;
	height: 100%;
	transition: fill 0.2s ease;
}

.contact__social-link:hover .contact__social-icon svg,
.contact__social-link:focus-visible .contact__social-icon svg {
	fill: var(--color-accent-lime);
}

/* ==========================================================================
   9. Media queries responsive (design-guide.md §3.4)
   ========================================================================== */

/* Tablet (768px–1199px): nav colapsa a hamburger, hero mantiene 2 columnas
   pero con proporciones más equilibradas. */
@media (max-width: 1199px) {
	.site-nav__toggle {
		display: flex;
	}

	.site-nav__menu-wrap {
		position: fixed;
		inset: var(--nav-height) 0 0 0;
		display: flex;
		background-color: rgba(18, 18, 18, 0.98);
		backdrop-filter: blur(12px);
		-webkit-backdrop-filter: blur(12px);
		opacity: 0;
		transform: translateY(-8px);
		pointer-events: none;
		transition: opacity 0.3s ease, transform 0.3s ease;
	}

	.site-nav__menu-wrap.is-open {
		opacity: 1;
		transform: translateY(0);
		pointer-events: auto;
	}

	.site-nav__menu {
		flex-direction: column;
		justify-content: center;
		align-items: center;
		width: 100%;
		gap: 2rem;
	}

	.site-nav__link {
		font-size: 1.25rem;
	}

	.site-header.nav-open .site-nav__toggle-bar:nth-child(1) {
		transform: translateY(7px) rotate(45deg);
	}

	.site-header.nav-open .site-nav__toggle-bar:nth-child(2) {
		opacity: 0;
	}

	.site-header.nav-open .site-nav__toggle-bar:nth-child(3) {
		transform: translateY(-7px) rotate(-45deg);
	}

	.hero__grid {
		grid-template-columns: 1fr 1fr;
		gap: 2rem;
	}

	.hero__visual {
		height: min(50vh, 480px);
	}

	.about__grid {
		grid-template-columns: 1fr 1.2fr;
		gap: 1.25rem;
	}

	/* Tablet: Grid 2 columnas servicios (design-guide.md §3.4). La 3ª tarjeta
	   pasa a una segunda fila. */
	.services__grid {
		grid-template-columns: repeat(2, 1fr);
	}

	/* Tablet: proyectos en 1 columna ancha (design-guide.md §3.4). Los
	   previews mantienen su aspect-ratio 4/3, ahora a ancho completo. */
	.projects__grid {
		grid-template-columns: 1fr;
	}

	/* Tablet: el split 50/50 de Contacto se mantiene en 2 columnas (mismo
	   criterio que Sobre mí), solo se reduce el gap para ganar espacio. */
	.contact__container {
		gap: 2rem;
	}
}

/* Móvil (< 768px): single column, hero apilado (texto arriba, visual abajo). */
@media (max-width: 767px) {
	.hero__grid {
		grid-template-columns: 1fr;
	}

	.hero__content {
		align-items: flex-start;
		gap: 2rem;
	}

	.hero__cta {
		width: 100%;
		text-align: center;
	}

	.hero__visual {
		height: min(45vh, 380px);
	}

	.hero__scroll-indicator {
		display: none;
	}

	/* Single column, tarjetas full-width apiladas (design-guide.md §3.4). */
	.about__grid {
		grid-template-columns: 1fr;
	}

	.about__photo-placeholder {
		max-width: 320px;
		margin: 0 auto;
	}

	/* Móvil: single column, tarjetas full-width apiladas (design-guide.md §3.4). */
	.services__grid {
		grid-template-columns: 1fr;
	}

	.services__badge {
		right: 1.25rem;
	}

	/* Móvil: el grid de proyectos ya hereda 1 columna del breakpoint tablet
	   (arriba); aquí solo se garantiza el área de toque mínima de 44px del
	   enlace "Ver caso" (design-guide.md §3.4 / accesibilidad táctil). */
	.projects__card-link {
		min-height: 44px;
		align-items: center;
	}

	/* Móvil: single column, formulario e info de contacto apilados
	   (design-guide.md §3.4). */
	.contact__container {
		grid-template-columns: 1fr;
		gap: 3rem;
	}
}

/* ==========================================================================
   Accesibilidad: prefers-reduced-motion
   ========================================================================== */

/* La regla global en style.css ya neutraliza duración/iteración de todas las
   animaciones y transiciones CSS del tema. Aquí solo reforzamos el estado
   final deseado para elementos cuyo "reposo" visual importa (p. ej. que el
   indicador de scroll quede visible pero inmóvil, no oculto a medias). */
@media (prefers-reduced-motion: reduce) {
	.hero__scroll-line {
		animation: none;
		transform: scaleY(1);
		opacity: 0.3;
	}

	.hero__cursor {
		display: none;
	}

	/* Tarjeta destacada de Servicios: el brillo animado infinito queda
	   desactivado y se conserva el box-shadow estático base (obligatorio,
	   ver CLAUDE.md §7 y design-guide.md §3.3 "Tarjeta IA activa"). */
	.services__card--featured {
		animation: none;
		box-shadow: 0 0 40px rgba(204, 255, 0, 0.08);
	}

	/* La escala 1.02 en hover de las tarjetas de Servicios se considera
	   movimiento: bajo reduced-motion solo queda el cambio de borde. */
	.services__card:hover,
	.services__card:focus-within {
		transform: none;
	}

	/* El "dibujado" del icono (stroke-dasharray/stroke-dashoffset) se
	   muestra directamente en su estado final sin animar el trazo. */
	.services__icon svg * {
		transition: none;
	}

	/* Preview de Proyectos (design-guide.md §2.4 y §3.2): sin la animación de
	   escala del bloque ni el desvanecido del overlay, la tarjeta necesita una
	   alternativa estática que siga comunicando el estado "interactivo" sin
	   depender del movimiento — overlay atenuado fijo (ni al 60% de reposo ni
	   a 0% de hover, un punto intermedio permanente) y tag de tecnología
	   siempre visible, sin animación de aparición. */
	.projects__preview,
	.projects__card:hover .projects__preview,
	.projects__card:focus-within .projects__preview {
		transform: none;
	}

	.projects__preview-overlay,
	.projects__card:hover .projects__preview-overlay,
	.projects__card:focus-within .projects__preview-overlay {
		opacity: 0.35;
	}

	.projects__tag {
		opacity: 1;
		transform: none;
	}

	/* Span "extraordinario" de Contacto (design-guide.md §2.5/§3.3): el
	   brillo pulsante queda fijo en su valor bajo, nunca en el pico. */
	.contact__highlight {
		animation: none;
		text-shadow: 0 0 8px rgba(255, 255, 0, 0.25);
	}

	/* Spinner tricolor del botón de envío: bajo reduced-motion no se
	   considera aceptable un movimiento infinito de puntos, así que se
	   sustituye por un estado estático simple — opacidad reducida del botón
	   + texto "Enviando…" (ya inyectado por assets/js/main.js en
	   .contact__submit-label independientemente del motion preference). */
	.contact__submit.is-loading {
		opacity: 0.7;
	}

	.contact__submit.is-loading .contact__submit-label {
		opacity: 1;
	}

	.contact__submit.is-loading .contact__spinner {
		display: none;
	}
}
