/* ==========================================================================
   YALA — hoja de estilos única
   1. Tokens · 2. Reset · 3. Tipografía · 4. Header · 5. Hero · 6. Secciones
   7. Habilidades · 8. Proceso · 9. Pilares · 10. Contacto · 11. Botones
   12. Footer · 13. Responsive · 14. Movimiento reducido · 15. Paleta
   ========================================================================== */

/* 1. Tokens ----------------------------------------------------------------
   Toda la paleta del sitio vive en este bloque y sólo aquí: ninguna otra regla
   de la hoja escribe un color a mano. Cambiar la marca es cambiar estas líneas.

   Van en dos capas, a propósito:

     · «Paleta base» son los colores tal cual, con nombre de color. Es lo que se
       toca el día que la marca cambie de tono.
     · «Roles» dicen para qué sirve cada color —texto, fondo, borde, acento—.
       Es lo único que se usa al maquetar.

   Maquetar siempre contra un rol, nunca contra la paleta base. Así redefinir el
   naranja no obliga a repasar la hoja regla por regla, y un rol puede pasar a
   otro color sin tocar nada más.

   Las transparencias salen del propio color con color-mix(), no de un rgba()
   escrito a mano: de esa forma también siguen a la paleta cuando cambie.

   `paleta.html` pinta este bloque entero: es la forma rápida de ver el efecto
   de un cambio antes de repasar el sitio.
   -------------------------------------------------------------------------- */
:root {
    /* --- Paleta base · marca ---------------------------------------------- */
    --brand-orange: #FF5A00;        /* acento de marca (manual de identidad) */
    --brand-orange-deep: #D94D00;   /* el mismo naranja, un punto más hondo */
    --brand-orange-tint: #FFF1E9;   /* el mismo naranja lavado, para fondos */
    --brand-ink: #161922;           /* titulares y fondos oscuros */
    --brand-ink-raised: #1E222D;    /* un peldaño por encima del ink */
    --brand-gray: #373737;          /* texto corrido */

    /* --- Paleta base · neutros -------------------------------------------- */
    /* De más claro a más oscuro. Del 200 en adelante son grises de apoyo: se
       leen bien sobre fondo oscuro o como texto secundario, nunca como cuerpo
       de texto sobre blanco. */
    --neutral-000: #FFFFFF;
    --neutral-050: #F5F5F5;
    --neutral-100: #E3E4E8;
    --neutral-200: #B9BCC4;
    --neutral-300: #8F929C;
    --neutral-400: #7C8090;
    --neutral-500: #6B6F7A;
    --neutral-900: #000000;         /* sólo el fondo del video de intro */

    /* --- Roles · fondos ---------------------------------------------------- */
    --color-bg: var(--neutral-000);
    --color-bg-alt: var(--neutral-050);
    --color-bg-dark: var(--brand-ink);
    --color-bg-dark-raised: var(--brand-ink-raised);
    --color-bg-accent-soft: var(--brand-orange-tint);
    --color-surface: var(--neutral-000);
    --color-backdrop: var(--neutral-900);

    /* --- Roles · texto ----------------------------------------------------- */
    --color-text: var(--brand-ink);          /* titulares y texto fuerte */
    --color-body: var(--brand-gray);         /* párrafos */
    --color-muted: var(--neutral-500);       /* etiquetas y apoyos */
    --color-text-on-dark: var(--neutral-000);
    --color-body-on-dark: var(--neutral-200);
    --color-muted-on-dark: var(--neutral-400);

    /* --- Roles · acento ---------------------------------------------------- */
    --color-accent: var(--brand-orange);
    --color-accent-deep: var(--brand-orange-deep);
    --color-on-accent: var(--neutral-000);   /* lo que va encima del acento */

    /* --- Roles · líneas, velos y sombras ----------------------------------- */
    --color-border: var(--neutral-100);
    --color-border-soft: color-mix(in srgb, var(--brand-ink) 9%, transparent);
    --color-border-strong: color-mix(in srgb, var(--brand-ink) 16%, transparent);
    --color-border-on-dark: color-mix(in srgb, var(--neutral-000) 14%, transparent);
    --color-rule-on-dark: color-mix(in srgb, var(--neutral-000) 12%, transparent);

    /* Profundidad de campo de la ruleta: los nombres fuera de foco */
    --color-blur-far: var(--neutral-200);
    --color-blur-near: var(--neutral-300);

    /* Cristal sobre fondo oscuro: el botón de saltar la intro */
    --color-glass: color-mix(in srgb, var(--neutral-000) 12%, transparent);
    --color-glass-hover: color-mix(in srgb, var(--neutral-000) 28%, transparent);
    --color-glass-line: color-mix(in srgb, var(--neutral-000) 35%, transparent);

    /* Velo del header al hacer scroll */
    --color-veil: color-mix(in srgb, var(--neutral-000) 92%, transparent);

    --shadow-card: 0 18px 40px color-mix(in srgb, var(--brand-ink) 8%, transparent);

    /* --- Fotografía: velos, píldoras y cristal -------------------------------
       Una foto no se pone cruda debajo de un texto: el velo (scrim) es lo que
       garantiza que el titular se lea sea cual sea la imagen que acabe ahí.
       Se define aquí para que todas las secciones con foto oscurezcan igual. */
    /* El tramo central es el exigente: ahí acaban los titulares largos, y la
       palabra en cursiva va en naranja, que contrasta menos que el blanco.
       Para que ese naranja llegue a 3:1 incluso sobre un píxel blanco de la
       foto, el velo tiene que cubrir un 80 % largo; a la derecha se aclara
       para que la imagen se siga viendo. */
    --scrim-foto:
        linear-gradient(to right,
            color-mix(in srgb, var(--brand-ink) 92%, transparent) 0%,
            color-mix(in srgb, var(--brand-ink) 84%, transparent) 62%,
            color-mix(in srgb, var(--brand-ink) 50%, transparent) 100%);
    /* Banda superior de las cabeceras: el menú flota encima en blanco y el
       velo horizontal es más suave justo a la derecha, donde están los
       enlaces. Con una foto clara bajaban de 4,5:1; esta banda los sostiene. */
    --scrim-foto-cabecera:
        linear-gradient(to bottom,
            color-mix(in srgb, var(--brand-ink) 70%, transparent) 0,
            color-mix(in srgb, var(--brand-ink) 0%, transparent) 220px);
    /* Píldora de sección («• Nuestros pilares») */
    --color-pill: color-mix(in srgb, var(--brand-ink) 7%, transparent);
    --color-pill-on-dark: color-mix(in srgb, var(--neutral-000) 13%, transparent);

    /* --- Tramas y huecos de foto --------------------------------------------
       La retícula y los halos del fondo de las secciones oscuras sin foto, y
       el gris tenue que ocupa el marco de una foto mientras se descarga. */
    --art-dot-on-dark: color-mix(in srgb, var(--neutral-000) 7%, transparent);
    --art-glow-accent: color-mix(in srgb, var(--brand-orange) 20%, transparent);
    --art-glow-soft: color-mix(in srgb, var(--brand-orange) 9%, transparent);
    --art-surface: color-mix(in srgb, var(--brand-ink) 4%, transparent);

    /* Halos naranjas de los anillos animados */
    --halo-hero:
        drop-shadow(0 0 15px color-mix(in srgb, var(--brand-orange) 60%, transparent))
        drop-shadow(0 0 30px color-mix(in srgb, var(--brand-orange) 40%, transparent));
    --halo-ring: drop-shadow(0 0 18px color-mix(in srgb, var(--brand-orange) 25%, transparent));

    /* --- Iconos ------------------------------------------------------------ */
    /* Flecha diagonal de los botones. Va incrustada y no como archivo porque se
       pinta con mask: el color lo pone el botón, no el SVG. */
    --icon-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7.5 16.5 16.5 7.5'/%3E%3Cpath d='M8.75 7.5h7.75v7.75'/%3E%3C/svg%3E");

    /* --- Tipografía -------------------------------------------------------- */
    --font-sans: "Instrument Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
    --font-serif: "Instrument Serif", Georgia, "Times New Roman", serif;

    /* --- Medidas ----------------------------------------------------------- */
    --wrap: 1500px;
    /* El margen lateral nunca es menor que la zona segura del iPhone: con
       viewport-fit=cover (ver partials/head.html) la página llega a los bordes,
       y en horizontal el texto se metería bajo la muesca. En vertical y en
       cualquier otro dispositivo env() vale 0 y manda el 5 %. */
    --gutter: max(5%, env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
    /* Alto del header: incluye la zona segura superior del iPhone, que el
       header suma a su relleno (viewport-fit=cover). En el resto vale 0. */
    --header-h: calc(92px + env(safe-area-inset-top, 0px));

    /* --- Movimiento -------------------------------------------------------- */
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* 2. Reset ----------------------------------------------------------------- */
*,
*::before,
*::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* El lienzo —lo que queda fuera del <body>— lleva el oscuro del footer. Es lo
   que Safari en iPhone pinta bajo su barra flotante y en el rebote al final
   de la página: sin esto salía una franja blanca debajo del footer. El <body>
   sigue siendo blanco y cubre todo el contenido, así que no cambia nada más. */
html {
    background-color: var(--color-bg-dark);
    scroll-behavior: smooth;
    -webkit-text-size-adjust: 100%;
}

/* …y el rebote de arriba sigue blanco, como la cabecera: una franja blanca
   justo encima del documento. Queda en coordenadas negativas, así que ni se
   ve ni se puede llegar a ella con el scroll; sólo asoma al tirar hacia abajo. */
body::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 100%;
    height: 100vh;
    background-color: var(--color-bg);
    pointer-events: none;
}

body {
    font-family: var(--font-sans);
    color: var(--color-text);
    background-color: var(--color-bg);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

img,
video {
    max-width: 100%;
    display: block;
}

a {
    color: inherit;
}

/* Bloquea el scroll mientras corre la intro o el menú móvil está abierto */
body.is-locked {
    overflow: hidden;
}

/* Enlace de salto para lectores de pantalla y navegación por teclado */
.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 10000;
    background: var(--color-bg-dark);
    color: var(--color-text-on-dark);
    padding: 0.9rem 1.4rem;
    font-size: 0.95rem;
    text-decoration: none;
}

.skip-link:focus {
    left: 1rem;
    top: 1rem;
}

/* Texto que sólo leen los lectores de pantalla: la etiqueta de un botón que
   únicamente muestra un icono, por ejemplo. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

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

/* 3. Tipografía ------------------------------------------------------------ */
h1,
h2,
h3,
h4 {
    font-family: var(--font-serif);
    font-weight: 400;
    letter-spacing: -0.02em;
    line-height: 1.05;
    color: var(--color-text);
    text-wrap: balance;
}

h1 {
    font-size: clamp(2.25rem, 6vw, 3.5rem);
    margin-bottom: 1rem;
}

h2 {
    font-size: clamp(2rem, 5vw, 3.25rem);
    margin-bottom: 1.5rem;
}

h3 {
    font-size: clamp(1.5rem, 3vw, 2.125rem);
    margin-bottom: 1rem;
}

h4 {
    font-family: var(--font-sans);
    font-size: 1.0625rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    margin-bottom: 0.75rem;
}

em {
    font-style: italic;
}

p {
    font-size: 1.0625rem;
    color: var(--color-body);
    text-wrap: pretty;
}

p + p {
    margin-top: 1.25rem;
}

strong {
    color: var(--color-text);
    font-weight: 700;
}

/* Etiqueta pequeña en mayúsculas que encabeza cada sección */
/* Píldora de sección: un punto naranja y el nombre del bloque. Sustituye al
   filete anterior — sobre fotografía un filete se pierde y una píldora no. */
.eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.45rem 1rem 0.45rem 0.85rem;
    border-radius: 999px;
    background: var(--color-pill);
    font-family: var(--font-sans);
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    color: var(--color-text);
    margin-bottom: 1.5rem;
}

.eyebrow::before {
    content: "";
    flex: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--color-accent);
}

/* Sobre fondo oscuro o sobre foto, la píldora se aclara en vez de oscurecerse */
.section-dark .eyebrow,
.section-photo .eyebrow {
    background: var(--color-pill-on-dark);
    color: var(--color-text-on-dark);
}

/* Frase de cierre de cada bloque */
.kicker {
    font-family: var(--font-serif);
    font-size: clamp(1.25rem, 2.4vw, 1.75rem);
    line-height: 1.3;
    color: var(--color-text);
    margin-top: 2rem;
    padding-left: 1.5rem;
    border-left: 3px solid var(--color-accent);
}

.lead {
    font-size: clamp(1.125rem, 2vw, 1.375rem);
    line-height: 1.5;
    color: var(--color-body);
}

/* Un kicker que cierra una sección entera, no un párrafo */
.kicker.is-standalone {
    margin-top: 3.5rem;
}

/* Ancho de lectura cómodo para los bloques introductorios */
.measure {
    max-width: 46ch;
}

/* Párrafo que sólo contiene el botón de llamada a la acción */
.cta {
    margin-top: 2.5rem;
}

/* Animaciones de entrada */
/* Entrada al hacer scroll. El recorrido es corto a propósito: 24 px se leen
   como "llega", 40 se leían como "salta". Los bloques hermanos entran en
   cascada —el JS numera cada uno en --reveal-i— en vez de todos a la vez. */
.fade-up {
    opacity: 0;
    transform: translateY(24px);
    transition:
        opacity 0.8s var(--ease-out) calc(var(--reveal-i, 0) * 110ms),
        transform 1s var(--ease-out) calc(var(--reveal-i, 0) * 110ms);
}

.fade-up.visible {
    opacity: 1;
    transform: translateY(0);
}

/* 4. Header ---------------------------------------------------------------- */
header {
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 1000;
    /* Con viewport-fit=cover la página llega hasta arriba: el header suma la
       zona segura superior para no quedar bajo la hora y la batería. */
    padding: calc(1.75rem + env(safe-area-inset-top, 0px)) 0 1.75rem;
    transition: padding 0.4s ease;
}

/* El velo que aparece al hacer scroll va en un pseudo-elemento y NO en el
   header. Un elemento con backdrop-filter pasa a ser la referencia de sus
   hijos position: fixed, y el menú móvil es uno de ellos: con el velo en el
   header, el menú a pantalla completa quedaba encogido a la franja del header
   en cuanto se hacía scroll —sin fondo y con los enlaces por encima de la
   página—. Aquí el filtro afecta al ::before, que no tiene hijos. */
header::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-color: var(--color-veil);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    box-shadow: 0 1px 0 var(--color-border);
    opacity: 0;
    transition: opacity 0.4s ease;
    pointer-events: none;
}

header.scrolled {
    padding: calc(0.9rem + env(safe-area-inset-top, 0px)) 0 0.9rem;
}

header.scrolled::before {
    opacity: 1;
}

.nav-container {
    max-width: var(--wrap);
    margin: 0 auto;
    padding: 0 var(--gutter);
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.logo img {
    height: 32px;
    width: auto;
}

/* El logotipo va en dos versiones. Por defecto manda la de color; la blanca
   sólo aparece cuando el header flota sobre una cabecera con fotografía, que
   es oscura: el logotipo morado ahí no se lee.

   Se resuelve con :has() en vez de una clase en el <body> para que dependa de
   lo que la página realmente contiene y no de que alguien recuerde ponerla.
   Al hacer scroll el header se cubre con el velo claro y todo vuelve al ink. */
.logo {
    position: relative;
    display: inline-block;
}

/* La blanca va encima de la de color y se cruzan con un fundido, al mismo
   ritmo que el velo del header: un cambio seco se notaba como un parpadeo. */
.logo-color,
.logo-claro {
    transition: opacity 0.4s ease;
}

.logo-claro {
    position: absolute;
    inset: 0;
    opacity: 0;
}

/* Con el menú móvil abierto (el JS pone .is-locked en el <body>) el fondo ya no
   es la foto sino el blanco del menú: ahí todo vuelve al ink, o los enlaces
   quedarían blanco sobre blanco. */
body:has(.page-header.section-photo):not(.is-locked) header:not(.scrolled) .logo-color {
    opacity: 0;
}

body:has(.page-header.section-photo):not(.is-locked) header:not(.scrolled) .logo-claro {
    opacity: 1;
}

body:has(.page-header.section-photo):not(.is-locked) header:not(.scrolled) .nav-links a {
    color: var(--color-text-on-dark);
}

body:has(.page-header.section-photo):not(.is-locked) header:not(.scrolled) .nav-toggle span {
    background: var(--color-text-on-dark);
}

.nav-links {
    display: flex;
    align-items: center;
}

.nav-links a {
    color: var(--color-text);
    text-decoration: none;
    margin-left: 2.5rem;
    font-weight: 500;
    font-size: 0.9rem;
    letter-spacing: 0.03em;
    position: relative;
    padding: 0.25rem 0;
    transition: color 0.3s ease;
}

/* Subrayado que crece desde la izquierda al pasar el cursor */
.nav-links a::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 1.5px;
    background: var(--color-accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.4s var(--ease-out);
}

.nav-links a:hover::after,
.nav-links a.is-active::after {
    transform: scaleX(1);
}

.nav-links a.is-active {
    color: var(--color-accent);
}

/* Botón hamburguesa: sólo visible en móvil */
.nav-toggle {
    display: none;
    width: 44px;
    height: 44px;
    background: none;
    border: 0;
    cursor: pointer;
    position: relative;
    z-index: 1200;
}

.nav-toggle span {
    display: block;
    width: 24px;
    height: 2px;
    margin: 5px auto;
    background: var(--color-bg-dark);
    transition: transform 0.35s var(--ease-out), opacity 0.2s ease, background-color 0.4s ease;
}

.nav-toggle[aria-expanded="true"] span:nth-child(1) {
    transform: translateY(7px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] span:nth-child(2) {
    opacity: 0;
}

.nav-toggle[aria-expanded="true"] span:nth-child(3) {
    transform: translateY(-7px) rotate(-45deg);
}

/* 4b. Intro de video (sólo home) ------------------------------------------- */
/* El sitio se renderiza debajo; el splash únicamente lo tapa mientras corre.  */
#intro-splash {
    position: fixed;
    inset: 0;
    background-color: var(--color-backdrop);
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity 1.1s var(--ease-out), visibility 1.1s;
}

#intro-splash video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

body.intro-finished #intro-splash {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

.intro-skip {
    position: absolute;
    right: clamp(1rem, 4vw, 2.5rem);
    /* El intro ocupa toda la pantalla, también bajo la barra de Safari: el
       botón sube lo que mida esa zona para seguir siendo pulsable. */
    bottom: calc(clamp(1rem, 4vw, 2.5rem) + env(safe-area-inset-bottom, 0px));
    background: var(--color-glass);
    border: 1px solid var(--color-glass-line);
    color: var(--color-text-on-dark);
    font-family: var(--font-sans);
    font-size: 0.75rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    padding: 0.7rem 1.4rem;
    border-radius: 50px;
    cursor: pointer;
    transition: background-color 0.3s ease;
}

.intro-skip:hover {
    background: var(--color-glass-hover);
}

/* 5. Hero ------------------------------------------------------------------ */
.hero {
    position: relative;
    min-height: 100vh;
    min-height: 100svh;
    display: flex;
    align-items: center;
    overflow: hidden;
    background-color: var(--color-bg);
    /* El hueco de abajo es el que ocupa .hero-scroll: sin él, con la ventana
       algo baja el texto centrado se metía debajo del indicador. */
    padding: calc(var(--header-h) + 3rem) 0 clamp(6.5rem, 12vh, 9rem);
}

/* Video del logo animado, al fondo del hero por la derecha.
   El archivo desktop es 16:9 y el de móvil 9:16, así que la caja declara
   su aspect-ratio en vez de una altura fija: con una caja cuadrada el video
   quedaba reducido a una franja con bandas vacías. El fondo del video es
   blanco y el del hero también, así que se funden sin costura; multiply
   además evita cualquier borde si el archivo trae un blanco no puro. */
.hero-animated-bg {
    position: absolute;
    right: -4%;
    top: 50%;
    transform: translateY(-50%);
    width: min(56vw, 880px);
    aspect-ratio: 16 / 9;
    object-fit: contain;
    z-index: 1;
    pointer-events: none;
    mix-blend-mode: multiply;
}

@keyframes rotate-slow {
    0%   { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}


.hero-content {
    position: relative;
    z-index: 3;
    max-width: var(--wrap);
    width: 100%;
    margin: 0 auto;
    padding: 0 var(--gutter);
    padding-left: clamp(var(--gutter), 12vw, 15%);
}

/* Animaciones de entrada del hero — escalonadas para que se aprecie
   el paso del video intro al contenido. fill-mode:both inicia el estado
   «from» (invisible) antes de que empiece cada animación, sin JS extra. */
@keyframes hero-enter {
    from { opacity: 0; transform: translateY(18px); }
    to   { opacity: 1; transform: none; }
}

/* Mientras dura la intro, la entrada del titular espera en pausa: si no,
   corría detrás del video y al terminar éste ya había acabado. Arranca en el
   momento en que la intro empieza a desvanecerse (.intro-finished), así que el
   paso del video al titular se ve. Con :has() vale desde el primer fotograma,
   antes de que cargue el JS; si la intro no se muestra, el splash se retira
   enseguida y la animación corre como siempre. */
body:has(#intro-splash):not(.intro-finished) .hero-brand,
body:has(#intro-splash):not(.intro-finished) .hero-title,
body:has(#intro-splash):not(.intro-finished) .hero-columns {
    animation-play-state: paused;
}

.hero-brand {
    font-family: var(--font-sans);
    font-size: clamp(2.25rem, 5vw, 3.25rem);
    font-weight: 800;
    color: var(--color-text);
    letter-spacing: -0.03em;
    line-height: 1;
    text-transform: uppercase;
    animation: hero-enter 0.7s var(--ease-out) 0.15s both;
}

.hero-title {
    font-family: var(--font-serif);
    font-size: clamp(2rem, 5vw, 3.25rem);
    line-height: 1.08;
    font-weight: 400;
    color: var(--color-text);
    letter-spacing: -0.02em;
    margin-bottom: clamp(2.5rem, 6vw, 4rem);
    max-width: 20ch;
    animation: hero-enter 0.9s var(--ease-out) 0.4s both;
}

.hero-columns {
    display: flex;
    flex-wrap: wrap;
    gap: clamp(2rem, 5vw, 4rem);
    align-items: flex-start;
    animation: hero-enter 0.8s var(--ease-out) 0.75s both;
}

.hero-col-left {
    flex: 1 1 220px;
    max-width: 250px;
}

.hero-col-left p {
    font-size: 1.0625rem;
    font-weight: 700;
    line-height: 1.4;
    color: var(--color-body);
    padding-bottom: 1.9rem;
    border-bottom: 2px solid var(--color-body);
}

.hero-col-right {
    flex: 2 1 340px;
    max-width: 550px;
}

.hero-col-right p {
    font-size: clamp(1rem, 1.6vw, 1.25rem);
    line-height: 1.6;
}

.hero-highlight {
    color: var(--color-text);
    font-weight: 700;
}

/* Indicador de scroll al pie del hero */
.hero-scroll {
    position: absolute;
    bottom: 2.5rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 3;
    font-size: 0.7rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--color-muted);
    text-decoration: none;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
}

.hero-scroll::after {
    content: "";
    width: 1px;
    height: 32px;
    background: linear-gradient(var(--color-accent), transparent);
    animation: scroll-hint 2s ease-in-out infinite;
}

@keyframes scroll-hint {
    0%, 100% { opacity: 0.3; transform: scaleY(0.6); }
    50%      { opacity: 1;   transform: scaleY(1); }
}

/* Ventana muy baja: ni reservando hueco cabe el indicador */
@media (max-height: 620px) {
    .hero-scroll {
        display: none;
    }
}

/* 6. Secciones y layout ---------------------------------------------------- */
.container {
    max-width: var(--wrap);
    margin: 0 auto;
    padding: 0 var(--gutter);
}

.container-narrow {
    max-width: 900px;
    margin: 0 auto;
    padding: 0 var(--gutter);
}

.section {
    padding: clamp(4.5rem, 10vw, 8rem) 0;
}

.section-dark {
    background: var(--color-bg-dark);
    position: relative;
    overflow: hidden;
}

/* Fondo generado: retícula de puntos —la sección habla de datos— y dos halos
   naranjas que dan profundidad. Va en ::before para no meter un div de adorno
   en el HTML. Cuando haya fotografía, se sustituye por una imagen aquí mismo
   y el resto de la sección no se entera. */
.section-dark::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(circle at 82% 12%, var(--art-glow-accent), transparent 42%),
        radial-gradient(circle at 8% 92%, var(--art-glow-soft), transparent 48%),
        radial-gradient(var(--art-dot-on-dark) 1px, transparent 1px);
    background-size: auto, auto, 26px 26px;
    pointer-events: none;
}

/* El contenido va por encima del fondo generado */
.section-dark > * {
    position: relative;
    z-index: 1;
}

.section-dark h2,
.section-dark h3,
.section-dark .kicker {
    color: var(--color-text-on-dark);
}

.section-dark p {
    color: var(--color-body-on-dark);
}

.section-dark strong {
    color: var(--color-text-on-dark);
}

.section-light {
    background: var(--color-bg-alt);
}

/* Cabecera de las páginas interiores */
.page-header.is-plain {
    border-bottom: 0;
    min-height: 60vh;
}

.page-header {
    padding: calc(var(--header-h) + clamp(3rem, 8vw, 6rem)) 0 clamp(3rem, 6vw, 5rem);
    border-bottom: 1px solid var(--color-border);
}

.page-header .lead {
    max-width: 46ch;
    margin-top: 1.5rem;
}

.page-header h1 em {
    color: var(--color-accent);
}

/* Dos columnas: título pegajoso a la izquierda, contenido a la derecha */
.split-screen {
    max-width: var(--wrap);
    margin: 0 auto;
    padding: 0 var(--gutter);
    display: flex;
    flex-wrap: wrap;
    gap: clamp(2rem, 6vw, 5rem);
}

.split-left {
    flex: 1 1 320px;
    position: sticky;
    top: calc(var(--header-h) + 2rem);
    align-self: flex-start;
}

.split-right {
    flex: 2 1 480px;
    min-width: 0;
}

/* 7. Habilidades ----------------------------------------------------------- */
/* Índice de las 8 habilidades, al inicio de la página */
/* 2 x 4 en escritorio y 4 x 2 en tablet: las 8 habilidades llenan la retícula
   exacta, sin celdas vacías asomando el color del borde. */
.skills-index {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1px;
    background: var(--color-border);
    border: 1px solid var(--color-border);
    margin-top: clamp(2.5rem, 5vw, 4rem);
}

.skills-index a {
    background: var(--color-surface);
    padding: 1.75rem 1.5rem;
    text-decoration: none;
    display: flex;
    align-items: baseline;
    gap: 0.75rem;
    transition: background-color 0.3s ease, color 0.3s ease;
}

.skills-index a:hover {
    background: var(--color-bg-dark);
    color: var(--color-text-on-dark);
}

.skills-index .num {
    font-family: var(--font-sans);
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--color-accent);
    letter-spacing: 0.08em;
}

.skills-index .name {
    font-family: var(--font-serif);
    font-size: 1.25rem;
    line-height: 1.2;
}

@media (min-width: 993px) {
    .skills-index {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

@media (max-width: 480px) {
    .skills-index {
        grid-template-columns: 1fr;
    }
}

/* Ruleta de habilidades (home) --------------------------------------------- */
/* Los círculos giran en vertical y el que cruza el centro queda enfocado
   dentro del anillo naranja, que permanece fijo. */
/* Por defecto es una lista estática legible. La ruleta sólo se activa cuando el
   JS añade .is-live, así que sin JavaScript nada queda oculto ni borroso. */
.wheel {
    --wheel-h: 620px;
    --wheel-step: 200px;
    --wheel-circle: 330px;
    /* El SVG dibuja el aro a radio 75 dentro de un viewBox de 200, o sea al 75%
       de su caja. Para que el aro naranja calce exactamente sobre el círculo
       gris, la caja tiene que ser 4/3 del diámetro de ese círculo. */
    --wheel-ring: calc(var(--wheel-circle) * 4 / 3);
    --wheel-base: calc((var(--wheel-h) - var(--wheel-step)) / 2);

    position: relative;
    margin-top: clamp(2rem, 4vw, 3rem);
}

.wheel:not(.is-live) .wheel-ring {
    display: none;
}

.wheel.is-live {
    height: var(--wheel-h);
    overflow: hidden;
}

/* Difuminado superior e inferior: los círculos entran y salen sin corte seco */
.wheel.is-live::before,
.wheel.is-live::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 24%;
    z-index: 2;
    pointer-events: none;
}

.wheel.is-live::before {
    top: 0;
    background: linear-gradient(to bottom, var(--color-bg-alt), transparent);
}

.wheel.is-live::after {
    bottom: 0;
    background: linear-gradient(to top, var(--color-bg-alt), transparent);
}

.wheel-ring {
    position: absolute;
    left: 50%;
    top: 50%;
    width: var(--wheel-ring);
    height: var(--wheel-ring);
    transform: translate(-50%, -50%);
    z-index: 3;
    pointer-events: none;
    color: var(--color-accent);
    filter: var(--halo-ring);
}

.wheel-ring svg {
    width: 100%;
    height: 100%;
}

/* Los puntos orbitan la circunferencia completa; al cruzar el arco sólido
   quedan sobre el mismo naranja y se pierden de vista. */
.ring-orbit {
    transform-box: view-box;
    transform-origin: 50% 50%;
    animation: rotate-slow 16s linear infinite;
}

.wheel-track {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.wheel.is-live .wheel-track {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    z-index: 1;
    transform: translateY(var(--wheel-base));
    animation: wheel-spin var(--wheel-duration, 24s) linear infinite;
}

@keyframes wheel-spin {
    from { transform: translateY(var(--wheel-base)); }
    to   { transform: translateY(calc(var(--wheel-base) - var(--wheel-loop, 0px))); }
}

.wheel.is-paused .wheel-track {
    animation-play-state: paused;
}

.wheel-item {
    position: relative;
    flex: 0 0 auto;
    width: 100%;
    height: var(--wheel-step);
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
}

/* Circunferencia tenue de cada habilidad; se solapan entre sí */
.wheel-item::before {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    width: var(--wheel-circle);
    height: var(--wheel-circle);
    transform: translate(-50%, -50%);
    border: 1px solid var(--color-border-soft);
    border-radius: 50%;
    transition: border-color 0.5s ease;
}

.wheel-item.is-active::before {
    border-color: var(--color-border-strong);
}

.wheel-name {
    position: relative;
    font-family: var(--font-serif);
    font-size: clamp(1.375rem, 2.6vw, 2rem);
    line-height: 1.15;
    text-align: center;
    /* Ceñido al aro visible (no a su caja SVG) para que los nombres largos
       partan en dos líneas en vez de desbordarse por los lados */
    max-width: calc(var(--wheel-circle) - 90px);
    color: var(--color-text);
    transition: color 0.45s ease, filter 0.45s ease, transform 0.45s var(--ease-out);
}

/* La profundidad de campo sólo tiene sentido con la ruleta en marcha */
.wheel.is-live .wheel-name {
    color: var(--color-blur-far);
    filter: blur(3px);
    transform: scale(0.94);
}

.wheel-item.is-near .wheel-name {
    color: var(--color-blur-near);
    filter: blur(1.4px);
    transform: scale(0.97);
}

.wheel-item.is-active .wheel-name {
    color: var(--color-text);
    filter: none;
    transform: scale(1);
}

@media (max-width: 768px) {
    .wheel {
        --wheel-h: 470px;
        --wheel-step: 150px;
        --wheel-circle: 240px;
    }

    /* Con el aro más pequeño, el nombre se reduce para caber dentro */
    .wheel-name {
        font-size: 1.0625rem;
        max-width: calc(var(--wheel-circle) - 62px);
    }
}

/* Cada habilidad en detalle */
.skill {
    border-top: 1px solid var(--color-border);
    padding: clamp(3rem, 7vw, 5.5rem) 0;
    scroll-margin-top: var(--header-h);
}

.skill:first-of-type {
    border-top: 0;
}

.skill-grid {
    max-width: var(--wrap);
    margin: 0 auto;
    padding: 0 var(--gutter);
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: clamp(2rem, 5vw, 4.5rem);
    align-items: start;
}

.skill-num {
    font-family: var(--font-sans);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    color: var(--color-accent);
    display: block;
    margin-bottom: 1rem;
}

.skill-head h2 {
    margin-bottom: 0;
}

.skill-claim {
    font-family: var(--font-serif);
    font-size: clamp(1.375rem, 2.6vw, 1.875rem);
    line-height: 1.25;
    color: var(--color-text);
    margin-bottom: 1.75rem;
}

/* Foto de apoyo -------------------------------------------------------------
   El marco fija la proporción (8:5) y recorta con cover, así que cambiar una
   foto por otra de distinta medida no mueve la maqueta. Mientras se descarga
   se ve el gris tenue del fondo, no un hueco blanco.
   -------------------------------------------------------------------------- */
.media {
    aspect-ratio: 8 / 5;
    border-radius: 14px;
    overflow: hidden;
    background: var(--art-surface);
    border: 1px solid var(--color-border-soft);
}

.media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Sobre fondo oscuro el marco cambia, no el dibujo */
.section-dark .media {
    background: color-mix(in srgb, var(--neutral-000) 4%, transparent);
    border-color: var(--color-border-on-dark);
}

/* En la ficha de cada habilidad el arte cuelga bajo el título */
.skill-media {
    margin-top: clamp(1.75rem, 4vw, 2.5rem);
}

/* En una columna partida el arte va bajo el titular de la izquierda */
.split-media {
    margin-top: clamp(1.75rem, 4vw, 2.5rem);
    max-width: 420px;
}

/* Marca de cada tarjeta: un dibujo pequeño encima del título. No lleva marco
   —no es un .media— porque la tarjeta ya tiene el suyo. */
.card-icon {
    width: 44px;
    height: 44px;
    color: var(--color-accent);
    margin-bottom: 1.25rem;
}

.card-icon svg {
    display: block;
    width: 100%;
    height: 100%;
}

/* En móvil la ficha se apila: número, título, foto y texto. La foto se queda
   —ilustra la disciplina antes de leerla— pero con menos aire encima. */
@media (max-width: 860px) {
    .skill-media {
        margin-top: 1.25rem;
    }
}

/* 8. Proceso (Cómo trabajamos) --------------------------------------------- */
.steps {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 1px;
    background: var(--color-border-on-dark);
    border: 1px solid var(--color-border-on-dark);
    margin-top: clamp(2.5rem, 5vw, 4rem);
}

.step {
    background: var(--color-bg-dark);
    padding: clamp(2rem, 3vw, 2.75rem);
    transition: background-color 0.4s ease;
}

.step:hover {
    background: var(--color-bg-dark-raised);
}

.step-num {
    font-family: var(--font-sans);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    color: var(--color-accent);
    display: block;
    margin-bottom: 1.25rem;
}

.step h3 {
    font-size: clamp(1.25rem, 2vw, 1.5rem);
    margin-bottom: 0.9rem;
}

.step p {
    font-size: 1rem;
}

/* 9. Pilares y tarjetas ---------------------------------------------------- */
.grid-3 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: clamp(1.5rem, 3vw, 2rem);
    margin-top: clamp(2.5rem, 5vw, 4rem);
}

.card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: 18px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    /* La tarjeta también es .fade-up, y esta regla va después en la hoja: si
       no repitiera aquí la opacidad y el retardo, la pisaría y la tarjeta
       aparecería de golpe en vez de entrar. */
    transition:
        opacity 0.8s var(--ease-out) calc(var(--reveal-i, 0) * 110ms),
        transform 0.8s var(--ease-out) calc(var(--reveal-i, 0) * 110ms),
        box-shadow 0.6s var(--ease-out),
        border-color 0.6s var(--ease-out);
}

/* La foto de la tarjeta. Recorta con cover, así que la imagen que se ponga
   aquí encaja sea cual sea su medida mientras sea apaisada. */
.card-figure {
    aspect-ratio: 16 / 10;
    overflow: hidden;
    background: var(--art-surface);
}

.card-figure img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Al pasar el cursor la imagen se acerca apenas; el marco no se mueve porque
   la tarjeta recorta con overflow: hidden. Va lento a propósito: un zoom
   rápido se lee como un tirón, uno lento como profundidad. */
.card:hover .card-figure img,
.card:focus-within .card-figure img {
    transform: scale(1.04);
}

.card-body {
    padding: clamp(1.75rem, 3vw, 2.25rem);
    flex: 1;
}

/* Sección con fotografía a sangre -------------------------------------------
   La foto va como <img> y no como background-image por dos razones: el
   navegador puede priorizar su carga, y `npm run build` comprueba que la ruta
   exista —con un background-image en el CSS, una foto que falte pasaría
   desapercibida hasta verla en producción—.

   El velo (--scrim-foto) es obligatorio: sin él el titular depende de lo
   oscura que sea la foto que toque, y eso no se puede garantizar.
   -------------------------------------------------------------------------- */
.section-photo {
    position: relative;
    overflow: hidden;
    background: var(--color-bg-dark);
    isolation: isolate;
}

.section-photo .section-bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: -2;
}

.section-photo::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--scrim-foto);
    z-index: -1;
    pointer-events: none;
}

.page-header.section-photo::before {
    background: var(--scrim-foto-cabecera), var(--scrim-foto);
}

.section-photo h1,
.section-photo h2,
.section-photo h3,
.section-photo .kicker {
    color: var(--color-text-on-dark);
}

.section-photo p {
    color: var(--color-body-on-dark);
}

.section-photo strong {
    color: var(--color-text-on-dark);
}

/* Comportamiento común de las fotografías -----------------------------------
   Tres efectos, los tres sutiles y los tres desactivados con movimiento
   reducido:

   1. Carga: la foto entra con un fundido en vez de pintarse a trozos. El JS
      marca .is-loaded cuando termina la descarga. La regla que oculta sólo
      existe bajo .js-media, que el JS pone al final: sin JS no se oculta nada.
   2. Entrada: dentro de un bloque .fade-up, la foto llega un 6 % más grande y
      se asienta mientras el bloque sube. Va en la propiedad `scale`, no en
      `transform`, para no pelearse con el zoom del hover —que sí usa
      transform—: las dos se componen.
   3. Cabeceras: la foto de fondo se asienta al cargar y, si el navegador
      soporta animaciones ligadas al scroll, se desplaza algo más despacio que
      la página. Donde no las soporta simplemente no se mueve.
   -------------------------------------------------------------------------- */
.media img,
.card-figure img,
.section-photo .section-bg {
    transition:
        opacity 0.7s var(--ease-out),
        scale 1.6s var(--ease-out) calc(var(--reveal-i, 0) * 110ms),
        transform 1.2s var(--ease-out);
}

.js-media .media img:not(.is-loaded),
.js-media .card-figure img:not(.is-loaded),
.js-media .section-photo .section-bg:not(.is-loaded) {
    opacity: 0;
}

.fade-up:not(.visible) .media img,
.fade-up:not(.visible) .card-figure img {
    scale: 1.06;
}

@keyframes foto-asienta {
    from { scale: 1.08; }
    to   { scale: 1; }
}

@keyframes foto-deriva {
    from { translate: 0 -5%; }
    to   { translate: 0 5%; }
}

.section-photo .section-bg.is-loaded {
    animation: foto-asienta 2.4s var(--ease-out) both;
}

@supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
        /* La foto sobra un 7 % por arriba y por abajo: es el margen que
           recorre al desplazarse, así nunca asoma el borde. */
        .section-photo .section-bg {
            top: -7%;
            bottom: -7%;
            height: auto;
        }

        .section-photo .section-bg.is-loaded {
            animation:
                foto-asienta 2.4s var(--ease-out) both,
                foto-deriva linear both;
            animation-timeline: auto, view();
        }
    }
}

.card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-card);
    border-color: var(--color-border-strong);
}

.card h3 {
    font-size: clamp(1.375rem, 2vw, 1.75rem);
}

.card-claim {
    font-weight: 700;
    color: var(--color-text);
    margin-bottom: 0.75rem;
}

/* 10. Contacto ------------------------------------------------------------- */
.contact-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: clamp(2rem, 4vw, 3rem);
    margin-top: clamp(2.5rem, 5vw, 4rem);
}

.contact-item h4 {
    color: var(--color-muted);
    text-transform: uppercase;
    font-size: 0.75rem;
    letter-spacing: 0.16em;
}

/* Marcador para los datos que aún no están confirmados */
.contact-pending {
    font-family: var(--font-serif);
    font-size: 1.5rem;
    color: var(--color-muted);
}

.contact-item a {
    font-family: var(--font-serif);
    font-size: clamp(1.25rem, 2.5vw, 1.75rem);
    color: var(--color-text);
    text-decoration: none;
    border-bottom: 1px solid var(--color-border);
    transition: border-color 0.3s ease, color 0.3s ease;
}

.contact-item a:hover {
    color: var(--color-accent);
    border-color: var(--color-accent);
}

/* 11. Botones ---------------------------------------------------------------
   Píldora con el texto + círculo suelto con la flecha. Es el botón de YALA: no
   hay otro, y todas las variantes salen de aquí.

   El HTML no cambia — sigue siendo <a class="btn btn-primary">Texto</a>—:
   la píldora es el propio enlace y los dos trozos de la derecha son sus
   pseudo-elementos (::before pinta el círculo, ::after la flecha encima). Así
   no hay envoltorios que recordar cada vez que se añade un botón, y el enlace
   entero —círculo incluido— es una sola zona clicable.

   Una variante sólo redefine estas cinco variables, en reposo y otra vez en
   :hover. Nada más: la forma, el tamaño y las transiciones ya están resueltos.

       --btn-bg       fondo de la píldora
       --btn-fg       texto de la píldora
       --btn-line     borde de la píldora (transparente si va rellena)
       --btn-dot      fondo del círculo   (por defecto, el de la píldora)
       --btn-dot-fg   color de la flecha  (por defecto, el del texto)

   Las variables no se animan, pero sí lo hacen las propiedades que las leen:
   cambiar --btn-bg en :hover transiciona el background-color con normalidad.
   -------------------------------------------------------------------------- */
.btn {
    /* Reposo. Cada variante pisa lo que necesite. */
    --btn-bg: var(--color-accent);
    --btn-fg: var(--color-on-accent);
    --btn-line: transparent;
    --btn-dot: var(--btn-bg);
    --btn-dot-fg: var(--btn-fg);

    /* Alto de la píldora; el círculo es un poco menor, como en el manual. */
    --btn-h: 3.5rem;
    --btn-dot-size: calc(var(--btn-h) * 0.86);
    --btn-gap: 0.4rem;

    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--btn-h);
    padding: 0.5rem 2.25rem;
    /* El círculo va posicionado fuera de la píldora: este margen es el hueco
       que reserva en el flujo para que no se le eche encima lo que venga
       después. */
    margin-right: calc(var(--btn-dot-size) + var(--btn-gap));
    border-radius: 999px;
    border: 1px solid var(--btn-line);
    background-color: var(--btn-bg);
    color: var(--btn-fg);
    font-family: var(--font-sans);
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.35s ease, color 0.35s ease,
                border-color 0.35s ease, transform 0.35s var(--ease-out);
}

/* El círculo */
.btn::before {
    content: "";
    position: absolute;
    left: calc(100% + var(--btn-gap));
    top: 50%;
    width: var(--btn-dot-size);
    height: var(--btn-dot-size);
    transform: translateY(-50%);
    border-radius: 50%;
    background-color: var(--btn-dot);
    transition: background-color 0.35s ease;
}

/* La flecha, recortada del fondo con mask para que la pinte --btn-dot-fg */
.btn::after {
    content: "";
    position: absolute;
    left: calc(100% + var(--btn-gap));
    top: 50%;
    width: var(--btn-dot-size);
    height: var(--btn-dot-size);
    transform: translate(0, -50%);
    background-color: var(--btn-dot-fg);
    -webkit-mask: var(--icon-arrow) center / 42% 42% no-repeat;
    mask: var(--icon-arrow) center / 42% 42% no-repeat;
    transition: background-color 0.35s ease, transform 0.35s var(--ease-out);
}

/* Al pasar el cursor el botón se levanta y la flecha sale hacia su esquina */
.btn:hover,
.btn:focus-visible {
    transform: translateY(-2px);
}

.btn:hover::after,
.btn:focus-visible::after {
    transform: translate(3px, calc(-50% - 3px));
}

/* El foco enmarca la píldora; el aro por defecto no rodearía el círculo */
.btn:focus-visible {
    outline-offset: 4px;
}

/* --- Variantes ------------------------------------------------------------ */

/* Naranja de marca. Es el botón de las llamadas a la acción principales. */
.btn-primary {
    --btn-bg: var(--color-accent);
    --btn-fg: var(--color-on-accent);
}

.btn-primary:hover,
.btn-primary:focus-visible {
    --btn-bg: var(--color-bg-dark);
    --btn-fg: var(--color-text-on-dark);
}

/* Oscuro, el de las capturas del manual: píldora ink, flecha blanca. */
.btn-dark {
    --btn-bg: var(--color-bg-dark);
    --btn-fg: var(--color-text-on-dark);
}

.btn-dark:hover,
.btn-dark:focus-visible {
    --btn-bg: var(--color-accent);
    --btn-fg: var(--color-on-accent);
}

/* Contorneado: la píldora va vacía y sólo el círculo tiene cuerpo. */
.btn-ghost {
    --btn-bg: transparent;
    --btn-fg: var(--color-text);
    --btn-line: var(--color-text);
    --btn-dot: var(--color-bg-dark);
    --btn-dot-fg: var(--color-text-on-dark);
}

.btn-ghost:hover,
.btn-ghost:focus-visible {
    --btn-bg: var(--color-bg-dark);
    --btn-fg: var(--color-text-on-dark);
    --btn-line: var(--color-bg-dark);
    --btn-dot: var(--color-accent);
    --btn-dot-fg: var(--color-on-accent);
}

/* Sólo el círculo con la flecha, sin píldora. El texto sigue en el HTML dentro
   de un .sr-only: lo necesitan los lectores de pantalla aunque no se vea. */
.btn-circle {
    padding: 0;
    margin-right: 0;
    width: var(--btn-h);
    min-height: var(--btn-h);
    border-radius: 50%;
    background-color: transparent;
    border-color: transparent;
}

.btn-circle::before,
.btn-circle::after {
    left: 50%;
    width: var(--btn-h);
    height: var(--btn-h);
}

.btn-circle::before {
    transform: translate(-50%, -50%);
}

.btn-circle::after {
    transform: translate(-50%, -50%);
}

.btn-circle:hover::after,
.btn-circle:focus-visible::after {
    transform: translate(calc(-50% + 3px), calc(-50% - 3px));
}

/* --- Sobre fondo oscuro --------------------------------------------------- */
/* En una sección oscura el hover no puede irse al ink: desaparecería. Como todo
   son variables, invertir el botón es redefinirlas; no hay que duplicar reglas. */
.section-dark .btn-primary:hover,
.section-dark .btn-primary:focus-visible,
footer .btn-primary:hover,
footer .btn-primary:focus-visible {
    --btn-bg: var(--color-text-on-dark);
    --btn-fg: var(--color-text);
}

.section-dark .btn-ghost,
footer .btn-ghost {
    --btn-fg: var(--color-text-on-dark);
    --btn-line: var(--color-text-on-dark);
    --btn-dot: var(--color-text-on-dark);
    --btn-dot-fg: var(--color-text);
}

.section-dark .btn-ghost:hover,
.section-dark .btn-ghost:focus-visible,
footer .btn-ghost:hover,
footer .btn-ghost:focus-visible {
    --btn-bg: var(--color-text-on-dark);
    --btn-fg: var(--color-text);
    --btn-line: var(--color-text-on-dark);
    --btn-dot: var(--color-accent);
    --btn-dot-fg: var(--color-on-accent);
}

.section-dark .btn-dark,
footer .btn-dark {
    --btn-bg: var(--color-text-on-dark);
    --btn-fg: var(--color-text);
}

.section-dark .btn-dark:hover,
.section-dark .btn-dark:focus-visible,
footer .btn-dark:hover,
footer .btn-dark:focus-visible {
    --btn-bg: var(--color-accent);
    --btn-fg: var(--color-on-accent);
}

/* --- Pulsado -------------------------------------------------------------- */
/* Al hacer clic, cualquier botón —variante y fondo aparte— se apoya y pasa al
   naranja hondo. Va después de los bloques de fondo oscuro y con su misma
   especificidad, para que gane a los hover que allí se redefinen. */
.btn:active,
.section-dark .btn:active,
footer .btn:active {
    --btn-bg: var(--color-accent-deep);
    --btn-fg: var(--color-on-accent);
    --btn-line: var(--color-accent-deep);
    --btn-dot: var(--color-accent-deep);
    --btn-dot-fg: var(--color-on-accent);
    transform: translateY(0);
}

/* --- Pantallas estrechas -------------------------------------------------- */
/* Píldora + círculo ocupan bastante a lo ancho: en móvil el botón encoge para
   no desbordar el margen de la página. */
@media (max-width: 480px) {
    .btn {
        --btn-h: 3rem;
        --btn-gap: 0.3rem;
        padding: 0.5rem 1.4rem;
        font-size: 0.875rem;
        max-width: calc(100% - var(--btn-dot-size) - var(--btn-gap));
    }
}

/* 12. Footer --------------------------------------------------------------- */
/* Con viewport-fit=cover el footer llega por debajo de la barra flotante de
   Safari en iPhone: al final del scroll es su propio fondo oscuro el que queda
   ahí detrás, en vez de la franja blanca que Safari pintaba por su cuenta. El
   relleno suma la zona segura inferior para que el texto no quede tapado. */
footer {
    background-color: var(--color-bg-dark);
    color: var(--color-text-on-dark);
    padding: clamp(4rem, 8vw, 7rem) 0 calc(3rem + env(safe-area-inset-bottom, 0px));
}

.footer-container {
    max-width: var(--wrap);
    margin: 0 auto;
    padding: 0 var(--gutter);
    display: grid;
    grid-template-columns: 2fr 1fr 1fr;
    gap: clamp(2rem, 5vw, 4rem);
}

.footer-logo {
    height: 34px;
    width: auto;
    filter: brightness(0) invert(1);
}

.footer-tagline {
    font-family: var(--font-serif);
    font-size: 1.25rem;
    color: var(--color-text-on-dark);
    margin-top: 1.5rem;
    max-width: 26ch;
}

.footer-col h4 {
    font-family: var(--font-sans);
    font-size: 0.75rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    margin-bottom: 1.5rem;
    color: var(--color-muted-on-dark);
}

.footer-col a {
    display: block;
    color: var(--color-text-on-dark);
    text-decoration: none;
    margin-bottom: 0.9rem;
    font-size: 1rem;
    transition: color 0.3s ease;
}

.footer-col a:hover {
    color: var(--color-accent);
}

/* Red social todavía sin perfil: ocupa el mismo hueco que un enlace pero no
   finge serlo (ver la lista SOCIAL de build.js). */
.footer-pending {
    display: block;
    margin-bottom: 0.9rem;
    font-size: 1rem;
    color: var(--color-muted-on-dark);
}

.footer-bottom {
    max-width: var(--wrap);
    margin: clamp(3rem, 6vw, 5rem) auto 0;
    padding: 2rem var(--gutter) 0;
    border-top: 1px solid var(--color-rule-on-dark);
    font-size: 0.85rem;
    color: var(--color-muted-on-dark);
}

/* La regla general de <p> fija color y tamaño; aquí manda el contenedor */
.footer-bottom p {
    color: inherit;
    font-size: inherit;
}

/* 13. Responsive ----------------------------------------------------------- */
@media (max-width: 992px) {
    :root {
        --header-h: calc(76px + env(safe-area-inset-top, 0px));
    }

    .split-left {
        position: static;
    }

    .skill-grid {
        grid-template-columns: 1fr;
    }

    .footer-container {
        grid-template-columns: 1fr 1fr;
    }

    .footer-col:first-child {
        grid-column: 1 / -1;
    }

    .nav-toggle {
        display: block;
    }

    /* El logo se mantiene por encima del menú desplegado */
    .logo {
        position: relative;
        z-index: 1200;
    }

    /* Menú desplegable a pantalla completa */
    .nav-links {
        position: fixed;
        inset: 0;
        background: var(--color-bg);
        flex-direction: column;
        justify-content: center;
        align-items: flex-start;
        padding: 0 var(--gutter);
        gap: 0.5rem;
        transform: translateX(100%);
        /* Cerrado no sólo está fuera de pantalla: con visibility oculta deja de
           ser enfocable con el tabulador, que si no llevaba a enlaces invisibles.
           visibility es una propiedad discreta: al cerrar se retrasa hasta que
           termina el desplazamiento, y al abrir cambia en el acto. */
        visibility: hidden;
        transition: transform 0.5s var(--ease-out), visibility 0s linear 0.5s;
        z-index: 1100;
    }

    .nav-links.is-open {
        transform: translateX(0);
        visibility: visible;
        transition: transform 0.5s var(--ease-out), visibility 0s;
    }

    .nav-links a {
        margin-left: 0;
        font-family: var(--font-serif);
        font-size: clamp(2rem, 8vw, 2.75rem);
        font-weight: 400;
        padding: 0.4rem 0;
    }

    .nav-links a::after {
        display: none;
    }

    .hero-scroll {
        display: none;
    }
}

/* El corte es 767px, el mismo que usa el JS para elegir el archivo: por debajo
   sirve el video vertical (9:16), así que la caja cambia de proporción con él.
   Si se mueve uno hay que mover el otro o el video vuelve a salir deformado. */
@media (max-width: 767px) {
    /* En móvil el video ocupa el hueco blanco de la derecha del titular, que
       en todos los teléfonos acaba hacia x≈255 px.

       Ojo: en el video vertical el dibujo NO va centrado en el cuadro, sino
       desplazado a la derecha (del 59 % al 96 % del ancho) y a media altura
       (del 39 % al 59 %). Por eso la caja se alinea al mismo margen que el
       texto (--gutter): con ella corrida fuera de pantalla, el trazo quedaba
       cortado contra el borde.

       En vertical se ancla al titular y no al hero: el contenido va centrado,
       así que un `top` en % dejaba el logo a una altura distinta en cada
       teléfono. El centro del titular cae unos 150 px por encima del centro
       del hero, y el dibujo está al 49 % de la altura del cuadro.

       La caja solapa algo del párrafo, pero es fondo blanco sobre fondo
       blanco. Un video con otro fondo obligaría a revisarlo. */
    .hero-animated-bg {
        width: min(46vw, 190px);
        aspect-ratio: 9 / 16;
        right: var(--gutter);
        top: calc(50% - 9.5rem);
        transform: translateY(-49%);
        opacity: 0.9;
    }
}

/* En los móviles más estrechos el trazo de la izquierda del logo rozaría el
   final de «marcas que importan.»: se encoge lo justo para dejar aire. */
@media (max-width: 360px) {
    .hero-animated-bg {
        width: 40vw;
    }
}

@media (max-width: 600px) {
    .hero-content {
        padding-left: var(--gutter);
    }

    .hero-col-left {
        max-width: 100%;
    }

    .footer-container {
        grid-template-columns: 1fr;
    }
}

/* 14. Movimiento reducido -------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }

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

    .fade-up {
        opacity: 1;
        transform: none;
    }

    /* Sin animaciones de entrada en el hero */
    .hero-brand,
    .hero-title,
    .hero-columns {
        animation: none;
        opacity: 1;
        transform: none;
    }
}

/* 15. Paleta (sólo paleta.html) ---------------------------------------------
   Página interna de diseño, fuera del menú y con robots: noindex. Pinta el
   bloque 1 en vivo —cada muestra dice qué token muestra y el JS le pregunta su
   valor a la hoja— para poder ver de un vistazo el efecto de un cambio de
   paleta sin recorrer el sitio entero.
   -------------------------------------------------------------------------- */
.swatches {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 1.5rem 1.25rem;
    margin: 2rem 0 0;
    padding: 0;
    list-style: none;
}

.swatch-chip {
    position: relative;
    display: block;
    height: 88px;
    border-radius: 12px;
    border: 1px solid var(--color-border-soft);
    overflow: hidden;
    /* Tablero de fondo: así una muestra translúcida se ve como translúcida y no
       como un color plano. */
    background-color: var(--color-bg);
    background-image:
        linear-gradient(45deg, var(--color-border) 25%, transparent 25%),
        linear-gradient(-45deg, var(--color-border) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, var(--color-border) 75%),
        linear-gradient(-45deg, transparent 75%, var(--color-border) 75%);
    background-size: 16px 16px;
    background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}

/* El color lo pone el JS a partir del data-token de la muestra */
.swatch-fill {
    position: absolute;
    inset: 0;
}

.swatch-name {
    display: block;
    font-weight: 600;
    font-size: 0.9375rem;
    color: var(--color-text);
    margin-top: 0.75rem;
}

.swatch-token,
.swatch-value {
    display: block;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.75rem;
    line-height: 1.5;
    color: var(--color-muted);
    word-break: break-all;
}

.swatch-token {
    color: var(--color-accent);
}

/* Fila de botones de ejemplo. El hueco extra a la derecha de cada uno es el
   círculo, que vive fuera de la píldora. */
.btn-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.75rem 2rem;
    margin-top: 2.5rem;
}

.btn-sample {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    align-items: flex-start;
}

.btn-sample code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.75rem;
    color: var(--color-muted);
}

.section-dark .btn-sample code {
    color: var(--color-muted-on-dark);
}

/* Nota al pie de una sección de la guía */
.note {
    margin-top: 2.5rem;
    padding: 1.25rem 1.5rem;
    border-left: 3px solid var(--color-accent);
    background: var(--color-bg-accent-soft);
}

.note p {
    font-size: 0.9375rem;
}

.note code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.875rem;
    color: var(--color-text);
}
