@font-face{font-family:Geist;src:url('fonts/geist.woff2') format('woff2');font-weight:100 900;font-display:swap}
@font-face{font-family:'Geist Mono';src:url('fonts/geist-mono.woff2') format('woff2');font-weight:400;font-display:swap}

/* ---------- Tokens ----------
   Marca: off-white, grafito y ámbar (único acento). El ámbar nunca es color de texto sobre claro.
   Forma: controles pulsables en píldora; superficies y diagramas con 6px (4px en nodos pequeños).
   Movimiento (Emil Kowalski): ease-out marcado para entradas, ease-in-out para desplazamientos en pantalla,
   160ms al pulsar y 200ms en hover. La escena del HomeLab es el único tramo en grafito. */
:root{
  color-scheme:light;
  --paper:#f3f3ed;
  --paper-deep:#e9e9e1;
  --paper-raise:#fbfbf7;
  --ink:#111310;
  --ink-soft:#4d4e47;
  --ink-faint:#66675f;
  --rule:#d5d5cb;
  --rule-strong:#7d7e75;
  --amber:#d9ad55;
  --amber-wash:#efe2bf;
  --lab-muted:#b9b9ae; /* Texto sobre grafito: contraste 9,4:1. */
  --lab-line:#3a3c35; /* Separadores decorativos del bloque grafito. */
  --lab-surface:#1b1d19; /* Cajas de los esquemas sobre grafito. */
  --lab-transition-ink:#000; /* Contraste durante los tonos intermedios del cambio de tema. */
  --lab-transition-paper:#fff; /* Con negro, garantiza al menos 4,5:1 en el tramo intermedio. */
  --hero-wave:rgba(17,19,16,.16); /* Líneas de fondo de la portada: decorativas, sin requisito de contraste. */
  --lab-dot:rgba(185,185,174,.16); /* Retícula de puntos del HomeLab: decorativa, sin requisito de contraste. */
  --lab-glare:rgba(243,243,237,.1); /* Reflejo de las tarjetas del HomeLab bajo el puntero: decorativo. */
  --sans:Geist,'Segoe UI',system-ui,sans-serif;
  --mono:'Geist Mono',ui-monospace,Consolas,monospace;
  --max:1280px;
  --gutter:clamp(20px,4.4vw,64px);
  --chapter:clamp(96px,12vw,192px);
  --text-body:clamp(17px,.18vw + 16.4px,19px);
  --ease-out:cubic-bezier(.23,1,.32,1);
  --ease-in-out:cubic-bezier(.77,0,.175,1);
  --press:160ms;
  --hover:200ms;
}

/* ---------- Base ---------- */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
body{background:var(--paper);color:var(--ink);font:400 var(--text-body)/1.6 var(--sans);overflow-wrap:break-word;-webkit-font-smoothing:antialiased}
img,svg{display:block;max-width:100%}
ul,ol{list-style:none}
a{color:inherit;text-underline-offset:.22em;text-decoration-thickness:1px}
button{font:inherit;color:inherit;background:none;border:0;border-radius:0;cursor:pointer;text-align:inherit;-webkit-tap-highlight-color:transparent}
strong,b{font-weight:600}
[hidden]{display:none!important}
:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
main:focus,.hero:focus{outline:none}
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.skip-link{position:absolute;top:8px;left:var(--gutter);z-index:40;padding:10px 16px;background:var(--ink);color:var(--paper);transform:translateY(-200%)}
.skip-link:focus{transform:none}
.wrap{width:100%;max-width:calc(var(--max) + 2 * var(--gutter));margin-inline:auto;padding-inline:var(--gutter)}

/* Mientras llega GSAP, la portada no parpadea: boot.js retira esta clase como muy tarde a los 3 s. */
.motion-pending .hero-identity,.motion-pending .hero-title,.motion-pending .hero-lead,.motion-pending .hero-actions{visibility:hidden}

/* Piezas creadas por SplitText: la máscara deja sitio a los trazos descendentes. */
.t-line-mask{padding-bottom:.08em;margin-bottom:-.08em}
.t-word{will-change:transform}

/* ---------- Pulsación (común a todo lo pulsable) ---------- */
.button,.text-link,.nav-link,.nav-toggle,.copy-email{transition:transform var(--press) var(--ease-out)}
.button:active,.text-link:active,.nav-link:active,.nav-toggle:active,.copy-email:active{transform:scale(.97)}

/* ---------- Enlaces y botones ---------- */
.button{display:inline-flex;align-items:center;min-height:52px;padding:0 26px;border-radius:999px;background:var(--ink);color:var(--paper);font-size:16px;font-weight:500;text-decoration:none;transition:transform var(--press) var(--ease-out),background-color var(--hover) ease}
.magnet{display:inline-flex;align-items:center;gap:10px}
.text-link{display:inline-flex;align-items:center;gap:8px;min-height:44px;font-size:16px;font-weight:500;text-decoration:underline;text-decoration-color:var(--rule-strong);transition:transform var(--press) var(--ease-out),text-decoration-color var(--hover) ease}
.link-arrow{display:inline-block;transition:transform var(--hover) var(--ease-out)}
@media (hover:hover) and (pointer:fine){
  .button:hover{background:#2c2e29}
  .button:hover .arrow-down{transform:translateY(3px)}
  .text-link:hover{text-decoration-color:currentColor}
  .text-link:hover .arrow-right{transform:translateX(3px)}
  .text-link:hover .arrow-up{transform:translateY(-3px)}
  .text-link:hover .arrow-out{transform:translate(2px,-2px)}
}

/* ---------- Navegación en píldora ---------- */
.site-header{position:fixed;top:12px;right:0;left:0;z-index:30;padding-inline:var(--gutter);pointer-events:none}
.nav-pill{position:relative;display:flex;align-items:center;justify-content:space-between;gap:20px;max-width:var(--max);margin-inline:auto;padding:6px 6px 6px 18px;border:1px solid transparent;border-radius:999px;pointer-events:none;transition:max-width 450ms var(--ease-in-out),box-shadow var(--hover) ease}
.site-header.is-compact .nav-pill{max-width:760px;border-color:var(--rule);background:rgba(243,243,237,.9);box-shadow:0 16px 40px -22px rgba(17,19,16,.55);-webkit-backdrop-filter:blur(14px) saturate(140%);backdrop-filter:blur(14px) saturate(140%);pointer-events:auto}
@supports not (backdrop-filter:blur(1px)){.site-header.is-compact .nav-pill{background:var(--paper)}}
.brand{display:inline-flex;align-items:center;gap:10px;min-height:44px;font-size:15px;font-weight:600;letter-spacing:-.02em;text-decoration:none;white-space:nowrap;visibility:hidden;opacity:0;pointer-events:none}
.site-header.is-compact .brand{visibility:visible;opacity:1;pointer-events:auto}
@media (prefers-reduced-motion:no-preference){.site-header.is-compact .brand{transition:opacity 180ms ease-out}}
/* El ojo de la P toca el borde del viewBox: sin overflow visible, el navegador recorta la fracción de píxel que redondea su caja. */
.brand-mark{flex:none;width:auto;height:20px;overflow:visible}
.site-nav{position:relative;pointer-events:auto}
.nav-list,.nav-active{display:flex;gap:2px}
.nav-link,.nav-active span{display:inline-flex;align-items:center;min-height:44px;padding:0 16px;border-radius:999px;font-size:15px;font-weight:450;white-space:nowrap}
.nav-link{text-decoration:none}
/* Copia de la lista en grafito, recortada al enlace activo: el color cambia sin saltos entre enlaces. */
.nav-active{position:absolute;inset:0;border-radius:999px;background:var(--ink);color:var(--paper);clip-path:inset(0 100% 0 0 round 999px);opacity:0;pointer-events:none}
.nav-toggle{display:none;align-items:center;min-height:44px;padding:0 18px;border-radius:999px;background:var(--ink);color:var(--paper);font-size:15px;font-weight:500;pointer-events:auto}
@media (min-width:600px) and (max-width:899px){
  .nav-pill{gap:10px;padding-left:12px}
  .brand{gap:8px;font-size:14px}
  .nav-list,.nav-active{gap:0}
  .nav-link,.nav-active span{padding-inline:10px;font-size:14px}
}
@media (max-width:599px){
  .site-header:not(.has-menu) .brand{display:none}
  .site-header:not(.has-menu) .nav-pill{padding:0;justify-content:flex-end}
  .site-header:not(.has-menu) .nav-list{flex-wrap:wrap;justify-content:flex-end}
  .site-header.has-menu .nav-toggle{display:inline-flex}
  .site-header.has-menu .site-nav{display:none;position:absolute;top:calc(100% + 8px);right:0;left:0;padding:8px;border:1px solid rgba(17,19,16,.12);border-radius:24px;background:var(--paper-raise);box-shadow:0 20px 40px -24px rgba(17,19,16,.5)}
  .site-header.has-menu .site-nav.is-open{display:block}
  .site-header.has-menu .nav-list{flex-direction:column}
  .nav-active{display:none}
}
@media (hover:hover) and (pointer:fine){.nav-link:hover{background:rgba(17,19,16,.06)}}

/* ---------- Portada: solo texto, el titular a todo el ancho ---------- */
.hero{position:relative;isolation:isolate;padding-top:calc(84px + clamp(40px,6vw,88px));padding-bottom:clamp(64px,8vw,120px)}
/* Ondas de fondo (24-sep, idea de Waves de React Bits, valores del boceto aprobado): lienzo que crea motion.js solo
   con movimiento; se desvanece hacia abajo a la izquierda para no tocar el texto. */
.hero-waves{position:absolute;inset:0;z-index:-1;pointer-events:none;-webkit-mask-image:radial-gradient(130% 95% at 88% 0%,#000 35%,transparent 82%);mask-image:radial-gradient(130% 95% at 88% 0%,#000 35%,transparent 82%)}
/* El nombre es el h1 de la página (búsquedas por «Hugo Peral»); hereda la tipografía para no cambiar el aspecto. */
.hero-identity{display:grid;justify-items:start;gap:8px;font-size:inherit;font-weight:inherit}
.hero-name{display:inline-flex;align-items:center;gap:12px;font-size:clamp(20px,1.8vw,24px);font-weight:550;letter-spacing:-.025em}
.hero-mark{flex:none;width:auto;height:28px;overflow:visible}
.hero-role{font-size:15px;font-weight:450;color:var(--ink-soft)}
/* El contenedor conserva sus medidas mientras su identidad se muestra en la cabecera. */
.hero-signature.is-in-header .hero-identity{visibility:hidden!important;opacity:0!important}
.hero-title{margin-top:clamp(18px,2.4vw,28px);font-size:clamp(34px,10.2vw,64px);font-weight:560;line-height:1.02;letter-spacing:-.045em}
.hero-line{display:block}
.hero-lead{max-width:34em;margin-top:clamp(18px,2.4vw,28px);color:var(--ink-soft)}
.hero-actions{display:flex;flex-wrap:wrap;align-items:center;gap:12px 28px;margin-top:clamp(26px,3vw,40px)}
/* Escritorio: la portada llena la pantalla con el texto abajo; entradilla y acciones comparten fila. */
@media (min-width:900px){
  .hero{display:flex;align-items:flex-end;min-height:100vh;padding-bottom:clamp(56px,7vw,104px)}
  .hero>.wrap{flex:1}
  .hero-title{font-size:clamp(56px,7.4vw,120px)}
  .hero-foot{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:32px 64px;margin-top:clamp(28px,3.4vw,48px)}
  .hero-foot .hero-lead{margin-top:0}
  .hero-foot .hero-actions{flex:none;margin-top:0}
}

/* ---------- Capítulos ---------- */
.chapter{padding-block:var(--chapter)}
.chapter-head{margin-bottom:clamp(40px,6vw,88px)}
.chapter-title{font-size:clamp(36px,6vw,96px);font-weight:560;line-height:1;letter-spacing:-.045em;text-wrap:balance}
.chapter-intro,.contact-intro{max-width:40ch;margin-top:clamp(16px,2vw,26px);font-size:clamp(18px,1.3vw,21px);color:var(--ink-soft)}
.list-label{margin-top:28px;font:400 13px/1.4 var(--mono);letter-spacing:.04em;color:var(--ink-faint)}
.tech-list,.tool-list{display:flex;flex-wrap:wrap;gap:6px}
.tech-list{margin-top:10px}
.tech-list li,.tool-list li{padding:4px 12px;border:1px solid var(--rule-strong);border-radius:999px;font:400 13px/1.5 var(--mono);white-space:nowrap}

/* Evidencias: rejilla asimétrica sin huecos (la primera ocupa dos columnas de cuatro). */
.evidence{display:grid;gap:1px;margin-top:24px;overflow:hidden;border:1px solid var(--rule);border-radius:6px;background:var(--rule)}
.evidence-item{display:grid;align-content:start;gap:6px;padding:20px;background:var(--paper-raise)}
.evidence dt{font-size:18px;font-weight:600;line-height:1.25;letter-spacing:-.01em}
.evidence dd{font-size:15px;line-height:1.55;color:var(--ink-soft)}
/* Puente: la última celda anuncia la escena que viene justo debajo y enlaza con ella. Dato clave: la primera celda de Newton (contrato tras las prácticas). Son las únicas celdas de experiencia en ámbar. */
.evidence-bridge,.evidence-key{background:var(--amber-wash)}
.evidence-bridge dd,.evidence-key dd{color:var(--ink)}
.bridge-link{display:inline-flex;align-items:center;gap:6px;margin-left:4px;font-weight:500;text-decoration:underline;text-decoration-color:var(--ink-soft);white-space:nowrap}
@media (min-width:720px){
  .evidence{grid-template-columns:repeat(4,minmax(0,1fr))}
  .evidence-item{grid-column:span 1}
  .evidence-wide{grid-column:span 2}
  .evidence-pair .evidence-item{grid-column:span 2}
  .evidence-bridge,.evidence-key{grid-column:1/-1}
}
@media (hover:hover) and (pointer:fine){
  .bridge-link:hover{text-decoration-color:currentColor}
  .bridge-link:hover .arrow-down{transform:translateY(3px)}
}

/* ---------- Experiencia: tarjetas y escena de Clavei ---------- */
.stack{position:relative}
.stack-card{position:relative;z-index:2;background:var(--paper)}
.card-grid{display:grid;gap:24px;padding-block:clamp(36px,4.5vw,64px);border-top:1px solid var(--rule)}
.employer h3{font-size:clamp(30px,3.2vw,48px);font-weight:560;line-height:1.04;letter-spacing:-.04em}
.employer-meta{margin-top:12px;font-size:15px;line-height:1.6;color:var(--ink-soft)}
.role{font-size:clamp(20px,1.8vw,24px);font-weight:540;line-height:1.3;letter-spacing:-.015em}
.role-summary{max-width:44em;margin-top:12px;color:var(--ink-soft)}
.card-note{max-width:44em;margin-top:20px}
@media (min-width:960px){.card-grid{grid-template-columns:minmax(0,4fr) minmax(0,8fr);column-gap:clamp(32px,4vw,64px)}}

/* Tarjeta que se apoya sobre la escena anterior: motion.js la hace subir con el scroll, sin alargarlo. */
.card-rise{border-radius:8px 8px 0 0;box-shadow:0 -30px 60px -40px rgba(17,19,16,.5)}
.card-rise .card-grid{border-top-color:transparent}

.case-scene{position:relative;z-index:1;background:var(--paper)}
.case-grid{display:grid;gap:clamp(32px,4vw,56px);padding-block:clamp(40px,6vw,80px);transform-origin:50% 30%}
.case-title{font-size:clamp(30px,3.4vw,52px);font-weight:560;line-height:1.04;letter-spacing:-.04em}
.case-story>p{max-width:36em;margin-top:18px;color:var(--ink-soft)}
.case-story .case-words{color:var(--ink);font-size:clamp(18px,1.3vw,21px)}
.case-story strong{color:var(--ink)}
@media (min-width:900px){.case-grid{grid-template-columns:minmax(0,5fr) minmax(0,7fr);align-items:center}}

/* Sin caja propia: las zonas del escenario usan las mismas superficies que las celdas de evidencias. */
.process{container-type:inline-size;min-width:0}
.scene-kicker{font-size:15px;font-weight:500;color:var(--ink-soft);margin-bottom:12px}

/* Hilo de cada empleo (escritorio): una línea vertical une la tarjeta con su escena, con un marcador ámbar
   en el nombre de la empresa y uno hueco en el rótulo de la escena. Termina girando en el cierre del capítulo. */
.experience{--rail-x:calc(max(0px,(100% - var(--max) - 2 * var(--gutter)) / 2) + var(--gutter) / 2)}
@media (min-width:1100px){
  .card-grid,.case-grid{position:relative}
  .stack-card::before,.case-scene::before{content:'';position:absolute;top:0;bottom:0;left:var(--rail-x);width:1px;background:var(--rule-strong)}
  .employer h3::before,.scene-kicker::before{content:'';position:absolute;left:calc(var(--gutter) / 2);transform:translateX(-50%)}
  .employer h3::before{width:11px;height:11px;margin-top:calc(.52em - 5.5px);background:var(--amber)}
  .scene-kicker::before{width:9px;height:9px;margin-top:calc(.8em - 4.5px);border:1.5px solid var(--ink);border-radius:50%;background:var(--paper)}
}
/* Fases como pasos (24-sep, idea de Stepper de React Bits, valores del boceto aprobado). motion.js añade a cada
   pestaña su indicador y las líneas entre pasos. La elegida lleva el punto ámbar; las anteriores (.is-done), un check
   que se dibuja, y la línea se rellena hasta ella. Sin JavaScript la lista sigue oculta. */
.process-tabs{display:flex;align-items:flex-start}
.process-tab{display:grid;justify-items:center;gap:10px;min-width:0;padding:4px 6px}
.process-tab:focus-visible{outline:none}
.process-tab:focus-visible .step-ind{outline:2px solid var(--ink);outline-offset:3px}
.step-ind{position:relative;display:grid;place-items:center;width:34px;height:34px;border-radius:50%;background:var(--paper-deep);color:var(--ink-faint);font:600 14px var(--mono)}
.step-num,.step-dot,.step-check{grid-area:1/1}
.step-dot{width:12px;height:12px;border-radius:50%;background:var(--amber);opacity:0;transform:scale(.4)}
.step-check{width:17px;height:17px;fill:none;stroke:var(--paper);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;opacity:0}
.step-check path{stroke-dasharray:1 1;stroke-dashoffset:1}
.step-label{font-size:15px;font-weight:500;color:var(--ink-faint);white-space:nowrap}
.process-tab[aria-selected='true'] .step-ind,.process-tab.is-done .step-ind{background:var(--ink);color:var(--paper)}
.process-tab[aria-selected='true'] .step-num,.process-tab.is-done .step-num{opacity:0}
.process-tab[aria-selected='true'] .step-dot{opacity:1;transform:scale(1)}
.process-tab.is-done .step-check{opacity:1}
.process-tab.is-done .step-check path{stroke-dashoffset:0}
.process-tab[aria-selected='true'] .step-label,.process-tab.is-done .step-label{color:var(--ink)}
.step-conn{position:relative;flex:1;height:2px;margin:20px 10px 0;overflow:hidden;border-radius:2px;background:var(--rule)}
.step-fill{position:absolute;inset:0 auto 0 0;width:0;background:var(--ink)}
.step-conn.is-done .step-fill{width:100%}
/* El esquema también elige fase: cada zona es un atajo para el puntero; el teclado usa los pasos. */
.process.is-enhanced .st-zone{cursor:pointer}
@media (prefers-reduced-motion:no-preference){
  .step-ind{transition:background-color .3s ease,color .3s ease,transform .16s var(--ease-out)}
  .process-tab:active .step-ind{transform:scale(.92)}
  .step-dot{transition:opacity .25s ease,transform .3s var(--ease-out)}
  .step-label{transition:color .3s ease}
  .process-tab.is-done .step-check path{transition:stroke-dashoffset .3s ease-out .1s}
  .step-fill{transition:width .4s ease}
}
@media (hover:hover) and (pointer:fine){.process.is-enhanced .st-zone:not(.is-active):hover .st-panel{stroke:var(--rule-strong)}}
/* Escenario del despliegue: tres zonas (configurar, validar, desplegar) que se construyen por fases.
   Los trazos que se dibujan usan pathLength="1": se animan con stroke-dashoffset sin medir geometría. */
.process-stage{margin-top:20px}
.stage-svg{width:100%;height:auto;overflow:visible}
.st-zone{transition:opacity 400ms ease}
.st-panel{fill:var(--paper-raise);stroke:var(--rule);stroke-width:1.2;transition:stroke var(--hover) ease}
.st-dot{fill:none;stroke:var(--rule-strong);stroke-width:1.5;transition:fill 300ms ease,stroke 300ms ease}
.st-track,.st-link-track{fill:none;stroke:var(--rule);stroke-width:2;stroke-linecap:round}
.st-link-track{stroke:var(--rule-strong);stroke-width:1.4;stroke-dasharray:2 4}
.st-draw{fill:none;stroke-dasharray:1 1;stroke-dashoffset:0;stroke-linecap:round;stroke-linejoin:round}
.st-meter{stroke:var(--ink);stroke-width:2}
.st-link{stroke:var(--ink);stroke-width:1.6}
.st-row{fill:var(--paper)}
.st-scan{fill:var(--amber-wash)}
.st-glyph{fill:none;stroke:var(--ink);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.st-bar-track{fill:var(--rule)}
.st-bar{fill:var(--ink)}
.st-skel{fill:none;stroke:var(--rule-strong);stroke-width:3;stroke-linecap:round}
.st-ring{fill:var(--paper-raise);stroke:var(--rule-strong);stroke-width:1.3}
.st-check{stroke:var(--ink);stroke-width:1.8}
.st-hub{fill:var(--amber-wash);stroke:var(--ink);stroke-width:1.4}
.st-pulse{fill:none;stroke:var(--amber);stroke-width:2;opacity:0}
.st-fan{stroke:var(--ink-soft);stroke-width:1.4}
.st-screen{fill:var(--paper);stroke:var(--ink);stroke-width:1.6}
/* Con JavaScript: la zona activa manda, las completadas se quedan en segundo plano y las siguientes esperan. */
.process.is-enhanced .st-zone{opacity:.42}
.process.is-enhanced .st-zone.is-done{opacity:.78}
.process.is-enhanced .st-zone.is-active{opacity:1}
.st-zone.is-active .st-panel{stroke:var(--ink)}
.st-zone.is-active .st-dot{fill:var(--amber);stroke:var(--ink)}
.st-zone.is-done .st-dot{fill:var(--ink);stroke:var(--ink)}

.process-scene{display:grid;gap:14px;margin-top:18px}
.phase{display:grid;align-content:start;gap:4px;min-width:0;padding-top:12px;border-top:2px solid var(--rule);transition:border-color 300ms ease}
.process.is-enhanced .phase.is-active{border-top-color:var(--ink)}
.item-name{font-size:16px;font-weight:560;line-height:1.25;letter-spacing:-.02em}
.item-note{font-size:14px;line-height:1.45;color:var(--ink-soft)}
.process-notes{display:grid;gap:22px;margin-top:22px;padding-top:22px;border-top:1px solid var(--rule-strong)}
.process-note h4{font-size:clamp(20px,2vw,24px);font-weight:560;line-height:1.2;letter-spacing:-.02em}
.process-note p{max-width:40em;margin-top:8px;font-size:17px;color:var(--ink-soft)}
.process.is-enhanced .process-notes{gap:0}
.process.is-enhanced .process-note{grid-area:1/1}
.process.is-enhanced .process-note:not(.is-active){visibility:hidden;opacity:0}
@media (prefers-reduced-motion:no-preference){.process.is-enhanced .process-note{transition:opacity 180ms ease}}
/* Los rótulos se alinean con las zonas del escenario (200 + 30 + 200 + 30 + 200 del viewBox). */
@container (min-width:520px){
  .process-scene{grid-template-columns:200fr 200fr 200fr;column-gap:calc(100% * 30 / 660)}
}

/* ---------- Separador: la línea cierra Experiencia a todo el ancho; la frase abre Proyectos ---------- */
.experience{padding-bottom:0}
.chapter-close{overflow:hidden;padding-top:clamp(56px,7vw,104px)}
.close-track{position:relative;height:20px}
.close-line{position:absolute;top:9px;left:0;right:calc(var(--gutter) + 10px);height:2px;background:var(--ink);transform-origin:left center}
.close-mark{position:absolute;top:2px;right:var(--gutter);width:16px;height:16px;background:var(--amber);transform:rotate(45deg)}
.close-caption{margin-bottom:clamp(40px,5vw,72px);font-size:clamp(28px,4.5vw,64px);font-weight:500;line-height:1.15;letter-spacing:-.04em}
.projects{padding-top:clamp(40px,5vw,72px)}

/* ---------- Proyectos: HomeLab abre el tramo grafito, sin fijación ---------- */
.lab-scene{--lab-bg:var(--ink);--lab-fg:var(--paper);--lab-secondary:var(--lab-muted);--lab-border:var(--lab-line);--lab-accent:var(--amber);--lab-raise:var(--lab-surface);position:relative;z-index:1;overflow:clip;padding-block:clamp(56px,7vw,104px);background:var(--lab-bg);color:var(--lab-fg)}
.lab-scene :focus-visible{outline-color:var(--lab-fg)}
/* Retícula de puntos (idea de DotGrid, React Bits): fija en CSS, un punto cada 26 px centrado en su celda.
   Con puntero fino, motion.js pone encima un lienzo pequeño (.lab-field) que sigue al cursor y redibuja los puntos
   cercanos apartados, más grandes y en ámbar. El overflow:clip de .lab-scene evita que el lienzo asome fuera. */
.lab-scene::before{content:'';position:absolute;inset:0;z-index:0;pointer-events:none;background-image:radial-gradient(circle,var(--lab-dot) 1.2px,transparent 1.7px);background-size:26px 26px}
.lab-field{position:absolute;top:0;left:0;z-index:0;pointer-events:none}
.lab-scene>.wrap{position:relative;z-index:1}
.lab-grid{display:grid;gap:clamp(32px,4vw,56px)}
.lab-copy{display:grid;gap:24px;align-items:end}
.lab-heading,.lab-overview,.lab-capabilities{min-width:0}
.kicker{font:400 12px/1.5 var(--mono);color:var(--lab-secondary)}
.lab-title{margin-top:14px;font-size:clamp(64px,9vw,124px);font-weight:500;line-height:.95;letter-spacing:-.07em}
.lab-statement{max-width:22em;font-size:clamp(21px,2vw,28px);font-weight:500;line-height:1.25;letter-spacing:-.025em}
.lab-intro{max-width:38em;margin-top:14px;font-size:17px;line-height:1.6;color:var(--lab-secondary)}
@media (min-width:900px){.lab-copy{grid-template-columns:1fr 1fr;gap:clamp(36px,5vw,72px)}}

/* Tarjetas vivas (24-sep): cuatro tarjetas separadas sobre la retícula. Con puntero fino se inclinan y reflejan
   la luz (motion.js, ideas de TiltedCard y GlareHover). La tarjeta es opaca (Hugo, 24-sep): la retícula y sus
   puntos ámbar solo se ven entre tarjetas, no a través. Sin JavaScript, la tarjeta es la superficie y se lee de
   corrido; con él, gira para enseñar el detalle (ver «Volteo», más abajo). */
.lab-capabilities{display:grid;gap:14px}
.lab-capability{--glare:transparent;--lab-card:var(--lab-bg);position:relative;display:flex;flex-direction:column;min-width:0;padding:clamp(22px,2.5vw,36px);border:1px solid var(--lab-border);border-radius:14px;background:radial-gradient(circle at var(--glare-x,50%) var(--glare-y,0%),var(--glare),transparent 45%) no-repeat,var(--lab-card);isolation:isolate}
.lab-capability.is-hot{--glare:var(--lab-glare)}
/* Borde de luz de la tarjeta abierta (idea de StarBorder): un degradado cónico recortado al borde. Gira solo con
   movimiento y con el bloque a la vista (.is-in-view); sin @property se queda quieto. */
@property --lab-star{syntax:'<angle>';inherits:false;initial-value:0deg}
@keyframes lab-star{to{--lab-star:360deg}}
.lab-capability::before,.cap-back::before{--lab-star:0deg;content:'';position:absolute;z-index:1;inset:-1px;padding:1.5px;border-radius:inherit;background:conic-gradient(from var(--lab-star),transparent 0 60%,var(--lab-accent) 74%,transparent 88%);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:0;pointer-events:none}
.lab-capability.is-open::before,.lab-capability.is-open .cap-back::before{opacity:1}
.lab-capability:has(.capability-trigger:focus-visible),.lab-capability:has(.cap-close:focus-visible){z-index:2;outline:2px solid var(--lab-fg);outline-offset:-5px}
/* Volteo (24-sep, variante M del boceto): motion.js reparte la tarjeta en anverso y reverso (.cap-face), que llevan
   el fondo, el borde y el reflejo; la tarjeta solo da la profundidad y el borde de luz pasa al reverso. El reverso va
   girado 180° dentro de una tarjeta que gira 180°: en pantalla queda derecho y el reflejo usa las mismas coordenadas
   en las dos caras. Las dos caras comparten celda: la tarjeta mide lo que la más alta. */
.lab-capabilities.is-enhanced .lab-capability{display:grid;padding:0;border:0;background:none;perspective:1600px}
.lab-capabilities.is-enhanced .lab-capability::before{content:none}
.cap-flip{position:relative;display:grid;min-width:0;transform-style:preserve-3d}
.cap-face{grid-area:1/1;position:relative;display:flex;flex-direction:column;min-width:0;padding:clamp(22px,2.5vw,36px);border:1px solid var(--lab-border);border-radius:14px;background:radial-gradient(circle at var(--glare-x,50%) var(--glare-y,0%),var(--glare),transparent 45%) no-repeat,var(--lab-card);-webkit-backface-visibility:hidden;backface-visibility:hidden}
.cap-back{transform:rotateY(180deg)}
.capability-head{font-size:inherit;font-weight:inherit}
.capability-trigger{display:flex;align-items:center;justify-content:space-between;gap:16px;width:100%;min-height:44px;text-align:left;cursor:default}
.lab-capabilities.is-enhanced .capability-trigger{cursor:pointer}
.capability-trigger:focus-visible{outline:none}
/* El botón cubre el bloque completo; no hay controles anidados en su superficie. */
.capability-trigger::after{content:'';position:absolute;z-index:2;inset:0}
.capability-area{font:400 13px/1.5 var(--mono);color:var(--lab-secondary)}
.capability-action{display:none;flex:none;align-items:center;gap:10px;font:400 11px/1.3 var(--mono);color:var(--lab-secondary)}
.lab-capabilities.is-enhanced .capability-action{display:inline-flex}
/* El anverso siempre dice «Ver detalle» y el reverso, «Volver»; al abrir, solo el círculo pasa a ámbar. */
.capability-action-close{display:none}
.cap-close .capability-action-close{display:inline}
.capability-toggle{position:relative;flex:none;width:30px;height:30px;border:1px solid var(--lab-border);border-radius:50%;color:var(--lab-fg)}
.capability-toggle::before,.capability-toggle::after{content:'';position:absolute;top:13px;left:8px;width:12px;height:1px;background:currentColor}
.capability-toggle::after{transform:rotate(90deg)}
.lab-capability.is-open .capability-toggle,.cap-close .capability-toggle{border-color:var(--lab-accent);background:var(--lab-accent);color:var(--lab-bg)}
.lab-capability.is-open .capability-toggle::after,.cap-close .capability-toggle::after{transform:rotate(0deg)}
.capability-visual{display:grid;gap:18px;margin-block:20px 24px}
.capability-tools{display:flex;flex-wrap:wrap;align-content:start;align-items:baseline;gap:6px 18px;min-width:0;min-height:2.45em;font-size:clamp(22px,2vw,29px);font-weight:500;line-height:1.18;letter-spacing:-.035em}
.capability-tools span+span{color:var(--lab-secondary)}
.cap-svg{display:block;width:100%;height:auto;max-height:280px;aspect-ratio:24/13;overflow:visible}
.capability-text{margin-top:auto}
.capability-preview,.capability-copy{max-width:42em;font-size:16px;line-height:1.55;color:var(--lab-secondary)}
.capability-detail{margin-top:12px}
.lab-capabilities.is-enhanced .lab-capability:not(.is-open) .cap-svg{opacity:.82}
/* Reverso: «Volver» en el sitio de «Ver detalle» y, centrados, el titular, el detalle en gris con las piezas clave
   en blanco y la línea de tecnologías. El nombre pequeño de la cabecera se oculta: ya está en el titular. */
.cap-back-head{display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:44px}
.cap-back-head .capability-area{visibility:hidden}
.cap-close{display:flex;flex:none;align-items:center;min-height:44px;cursor:pointer}
.cap-close:focus-visible{outline:none}
.cap-close::after{content:'';position:absolute;z-index:2;inset:0}
.cap-center{display:flex;flex:1;flex-direction:column;align-items:center;justify-content:center;gap:22px;padding:18px 0 8px;text-align:center}
.cap-title{font-size:clamp(30px,3.8vw,44px);font-weight:500;line-height:1.02;letter-spacing:-.045em;text-wrap:balance}
.cap-center .capability-detail{margin:0}
.cap-center .capability-copy{max-width:24em;font-size:clamp(18px,2vw,22px);line-height:1.5;letter-spacing:-.014em;text-wrap:balance}
.cap-key{font-weight:500;color:var(--lab-fg)}
.cap-line{font:400 12px/1.5 var(--mono);letter-spacing:.02em;color:var(--lab-secondary)}
.cap-tool+.cap-tool::before{content:'·';margin:0 .7em;color:var(--lab-accent)}
/* Aparición de las palabras al girar: el desplazamiento va en una variable (translate), no en transform. */
.cap-word{display:inline-block}
.cap-word,.cap-reveal{translate:0 var(--cap-shift,0px)}
@media (min-width:760px){.lab-capabilities{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:459px){
  .capability-visual{gap:12px;margin-block:16px 20px}
  .capability-tools{font-size:23px;gap:6px 14px}
  .capability-action-open,.capability-action-close{display:none!important}
}
@media (prefers-reduced-motion:no-preference){
  .lab-capability::before,.cap-back::before{transition:opacity 260ms var(--ease-out)}
  .lab-capabilities.is-in-view .lab-capability.is-open::before,.lab-capabilities.is-in-view .lab-capability.is-open .cap-back::before{animation:lab-star 4.5s linear infinite}
  .capability-toggle{transition:background-color 180ms ease,border-color 180ms ease,transform var(--press) var(--ease-out)}
  .capability-toggle::after{transition:transform 180ms var(--ease-out)}
  .capability-trigger:active .capability-toggle,.cap-close:active .capability-toggle{transform:scale(.9)}
  .cap-svg{transition:opacity 220ms ease}
  :root[data-input='keyboard'] .lab-capability::before,
  :root[data-input='keyboard'] .cap-back::before,
  :root[data-input='keyboard'] .capability-toggle,
  :root[data-input='keyboard'] .capability-toggle::after,
  :root[data-input='keyboard'] .cap-svg{transition:none}
}
@media (hover:hover) and (pointer:fine){
  .lab-capability:not(.is-open):hover .capability-toggle{border-color:var(--lab-secondary)}
  .lab-capabilities.is-enhanced .lab-capability:hover .cap-svg{opacity:1}
}

/* Esquemas del HomeLab: a la izquierda quién actúa, en el centro la herramienta y a la derecha el efecto.
   El marcado es el estado final (sin JS, con movimiento reducido o al terminar) y el ámbar solo marca la acción.
   Las superposiciones .cap-flash y los paquetes solo aparecen durante la animación.
   Textos de 14 a 16 u; TEMP/check-schematic-text.py comprueba que caben y no se solapan. */
.cap-t{font:400 16px var(--mono);fill:var(--lab-fg)}
.cap-t.is-sm{font-size:15px}
.cap-t.is-xs{font-size:14px}
.cap-t.is-muted{fill:var(--lab-secondary)}
.cap-t.is-accent{fill:var(--lab-accent)}
.cap-box{fill:var(--lab-raise);stroke:var(--lab-secondary);stroke-width:1.2}
.cap-box.is-accent-edge{stroke:var(--lab-accent)}
.cap-frame{fill:none;stroke:var(--lab-secondary);stroke-width:1.2}
.cap-zone{fill:none;stroke:var(--lab-border);stroke-width:1.3;stroke-dasharray:5 5}
.cap-rule{fill:none;stroke:var(--lab-border);stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
.cap-line,.cap-strong,.cap-accent,.cap-tube,.cap-ping{fill:none;stroke-linecap:round;stroke-linejoin:round}
.cap-line{stroke:var(--lab-secondary);stroke-width:1.5}
.cap-strong{stroke:var(--lab-fg);stroke-width:2}
.cap-accent{stroke:var(--lab-accent);stroke-width:2}
.cap-tube{stroke:var(--lab-accent);stroke-width:12;stroke-opacity:.16}
.cap-ping{stroke:var(--lab-accent);stroke-width:1.5}
.cap-faint{stroke-opacity:.45}
.cap-soft{stroke-opacity:.55}
.cap-dash{stroke-dasharray:3 6}
.cap-cut{fill:var(--lab-bg)}
.cap-core{fill:var(--lab-accent)}
.cap-dot{fill:var(--lab-secondary)}
.cap-solid{fill:var(--lab-fg)}
.cap-edge{fill:none;stroke:var(--lab-accent);stroke-width:1.6}
.cap-glow{fill:var(--lab-accent);stroke:none}
.cap-draw{stroke-dasharray:1 1;stroke-dashoffset:0}
.cap-flash,.cap-packet{opacity:0}
.cap-packet{fill:var(--lab-accent)}

/* Criterios del HomeLab: una franja breve debajo de las cuatro áreas. */
.lab-decisions{margin-top:clamp(28px,4vw,48px)}
.decisions-title{font-size:15px;font-weight:500;color:var(--lab-secondary)}
.decision-row{display:grid;gap:22px;margin-top:20px}
.decision{position:relative;padding-left:16px}
.decision-rule{position:absolute;top:4px;bottom:4px;left:0;width:1px;background:var(--lab-border);transform-origin:center top}
.decision-area{font:400 11px/1.5 var(--mono);color:var(--lab-accent)}
.decision h5{margin-top:5px;font-size:18px;font-weight:500;line-height:1.3;letter-spacing:-.02em}
.decision h5+p{max-width:36em;margin-top:6px;font-size:14px;line-height:1.55;color:var(--lab-secondary)}
@media (min-width:760px){.decision-row{grid-template-columns:repeat(3,minmax(0,1fr));gap:32px}}

/* Fichas de proyectos: identidad a la izquierda, trabajo y alcance a la derecha. */
.lab-projects{margin-top:clamp(56px,7vw,104px)}
.project-card{display:grid;gap:28px;padding-block:clamp(32px,4.5vw,64px);border-top:1px solid var(--lab-border)}
.project-card:last-child{padding-bottom:0}
.project-card-head,.project-card-body{min-width:0}
.project-kicker{font:400 12px/1.5 var(--mono);color:var(--lab-accent)}
.project-name{margin-top:16px;font-size:clamp(44px,5.2vw,72px);font-weight:500;line-height:1;letter-spacing:-.055em}
.panel-title{max-width:27em;font-size:clamp(22px,2.25vw,30px);font-weight:500;line-height:1.2;letter-spacing:-.025em}
.panel-lead{max-width:46em;margin-top:16px;font-size:17px;line-height:1.65;color:var(--lab-secondary)}
.project-card .tech-list{gap:6px 16px;max-width:24em;margin-top:24px}
.project-card .tech-list li{padding:0;border:0;border-radius:0;font-size:12px;color:var(--lab-secondary)}
.project-card .evidence{grid-template-columns:minmax(0,1fr);gap:24px;margin-top:28px;overflow:visible;border:0;border-radius:0;background:none}
.project-card .evidence-item{grid-column:auto;gap:0;min-width:0;padding:0;background:none}
.project-card .evidence dt{font-size:15px;font-weight:500;line-height:1.4}
.project-card .evidence dd{margin-top:8px;font-size:14px;line-height:1.6;color:var(--lab-secondary)}
@media (min-width:760px){
  .project-card{grid-template-columns:minmax(0,3fr) minmax(0,7fr);gap:clamp(32px,5vw,72px)}
  .project-card .evidence{grid-template-columns:repeat(2,minmax(0,1fr))}
  .project-card .evidence-wide{grid-column:1/-1}
}
@media (min-width:1100px){
  .project-card .evidence{grid-template-columns:repeat(3,minmax(0,1fr))}
  .project-card .evidence-pair{grid-template-columns:repeat(2,minmax(0,1fr))}
  .project-card .evidence-wide{grid-column:auto}
}

/* ---------- Herramientas: titular con ficha, cinta y bento ---------- */
.tools-visual{display:block}
/* Ancho fijo de 11ch, el de siempre, para todas las palabras del ciclo. Con relleno de .2em y tracking de -.04em,
   hasta 11 caracteres («Claude Code») caben dentro: 11 × .56 + .4 = 6,56 ≤ 6,6em. Así el título ni cambia de línea
   mientras se descifra ni rompe antes que con la píldora original (26-sep: «Claude Code» la ensanchaba, el título
   saltaba de una a dos líneas y movía toda la página; reservar el ancho con más relleno lo dejaba en dos líneas). */
.token{display:inline-flex;white-space:nowrap;align-items:center;justify-content:center;min-width:11ch;height:.8em;margin-inline:.1em;padding:0 .2em;border-radius:999px;background:var(--ink);color:var(--paper);font:400 .34em/1 var(--mono);letter-spacing:-.04em;vertical-align:.12em}
.marquee{overflow:hidden;margin-bottom:clamp(48px,6vw,88px);padding-block:clamp(14px,1.8vw,22px);border-block:1px solid var(--rule);-webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)}
/* Separación con padding y no con gap: las dos copias miden exactamente la mitad y el bucle no salta. */
.marquee-track{display:flex;width:max-content;white-space:nowrap}
.marquee-track span{padding-right:clamp(28px,3vw,52px);font-size:clamp(28px,3.8vw,60px);font-weight:540;line-height:1.1;letter-spacing:-.035em}
.marquee-track span:nth-child(even){color:var(--ink-faint)}
.bento{display:grid;grid-auto-flow:dense;gap:12px}
.cell{display:flex;flex-direction:column;gap:14px;padding:clamp(22px,2.6vw,36px);border:1px solid var(--rule);border-radius:6px;background:var(--paper-raise)}
.cell h3{font-size:clamp(22px,2.1vw,30px);font-weight:560;line-height:1.12;letter-spacing:-.025em}
.cell-where{font:400 13px/1.4 var(--mono);color:var(--ink-faint)}
.cell-context{margin-top:auto;padding-top:6px;color:var(--ink-soft)}
.cell-amber{border-color:transparent;background:var(--amber-wash)}
.cell-amber .cell-where{color:var(--ink-soft)}
.cell-amber .tool-list li{border-color:var(--ink-soft)}
.cell-deep{background:var(--paper-deep)}
/* Sitios que encienden (25-sep, boceto 3): site.js convierte el rótulo de dónde en botones. Al pasar o pulsar un
   sitio, sus herramientas pasan a tinta y el resto baja al 25 %. El apoyo va en discontinua, sin «· apoyo» ni
   leyenda (Hugo la quitó el 26-sep); la frase oculta de cada tarjeta lo dice a los lectores de pantalla. */
.cell{position:relative;isolation:isolate}
.tool-list li.is-apoyo{border-style:dashed;color:var(--ink-soft)}
.cell-sites{display:flex;flex-wrap:wrap;gap:6px}
.cell-site{padding:3px 10px;border:1px solid transparent;border-radius:999px;background:none;color:var(--ink-faint);font:400 13px/1.4 var(--mono);cursor:pointer}
.cell-site::before{content:'';display:inline-block;width:6px;height:6px;margin-right:7px;border-radius:50%;background:var(--amber);vertical-align:1px}
.cell-site:hover,.cell-site[aria-pressed=true]{border-color:var(--ink);color:var(--ink)}
.cell-amber .cell-site{color:var(--ink-soft)}
.cell.is-lit .tool-list li{opacity:.25}
.cell.is-lit .tool-list li.is-on{opacity:1;background:var(--ink);border-color:var(--ink);color:var(--paper)}
.cell.is-lit .tool-list li.is-on.is-apoyo{background:none;color:var(--ink)}
@media (pointer:coarse){.cell-site{min-height:36px}} /* Único cambio sobre el boceto: botones a la medida del dedo. */
@media (min-width:900px){
  .bento{grid-template-columns:repeat(3,minmax(0,1fr))}
  .cell-wide{grid-column:span 2}
  .cell-full{grid-column:1/-1} /* Agentes de IA: quinta celda, fila propia para no dejar huecos. */
}
@media (hover:hover) and (pointer:fine){
  .cell{transition:transform var(--hover) var(--ease-out),border-color var(--hover) ease}
  .cell:hover{transform:translateY(-3px);border-color:var(--rule-strong)}
}
@media (prefers-reduced-motion:no-preference){
  .tool-list li{transition:opacity .25s,background-color .25s,border-color .25s,color .25s}
  .cell-site{transition:background-color .2s,color .2s,border-color .2s}
}
/* Foco ámbar que sigue al cursor (idea de MagicBento/SpotlightCard de React Bits); site.js da --mx y --my. */
@media (hover:hover) and (pointer:fine) and (prefers-reduced-motion:no-preference){
  .cell::before{content:'';position:absolute;inset:0;z-index:-1;border-radius:inherit;pointer-events:none;opacity:0;transition:opacity .3s;background:radial-gradient(420px circle at var(--mx,50%) var(--my,50%),rgba(217,173,85,.16),transparent 60%)}
  .cell:hover::before{opacity:1}
}

/* ---------- Formación: título fijado y línea de tiempo ---------- */
.edu-grid{display:grid;gap:clamp(40px,5vw,80px)}
.languages{display:flex;flex-wrap:wrap;gap:16px 32px;margin-top:32px}
.languages dt{font-size:14px;color:var(--ink-faint)}
.languages dd{font-size:18px;font-weight:540}
.timeline-wrap{position:relative;padding-left:40px}
.timeline-line{position:absolute;top:10px;bottom:24px;left:5px;width:1px;background:var(--rule)}
.timeline-fill{position:absolute;inset:0;background:var(--ink);transform-origin:center top}
.timeline-item{position:relative;padding-bottom:clamp(34px,4vw,56px)}
.timeline-item::before{content:'';position:absolute;top:.4em;left:-40px;width:11px;height:11px;border:1.5px solid var(--ink);border-radius:50%;background:var(--ink);transition:background-color 300ms ease}
.timeline.is-enhanced .timeline-item::before{background:var(--paper)}
.timeline.is-enhanced .timeline-item.is-reached::before{background:var(--ink)}
.edu-period{font:400 14px/1.4 var(--mono);color:var(--ink-faint)}
.timeline-item h3{margin-top:6px;font-size:clamp(22px,2.2vw,30px);font-weight:560;line-height:1.15;letter-spacing:-.025em}
.timeline-item h3+p{max-width:40em;margin-top:6px;color:var(--ink-soft)}
.edu-state{display:inline-flex;margin-top:14px;padding:4px 12px;border:1px solid var(--rule-strong);border-radius:999px;font-size:14px;font-weight:500}
.state-done{border-color:var(--ink);background:var(--ink);color:var(--paper)}
.next-goal{padding:22px 24px;border-radius:6px;background:var(--amber-wash)}
@media (min-width:900px){.edu-grid{grid-template-columns:minmax(0,5fr) minmax(0,7fr);align-items:start}}

/* ---------- Contacto: la acción a pantalla grande ---------- */
.contact{display:flex;align-items:center;min-height:90vh}
.contact>.wrap{flex:1}
.contact-intro{color:var(--ink)}
.contact-email{display:inline-block;margin-top:clamp(36px,6vw,80px);padding-bottom:.08em;background:linear-gradient(currentColor,currentColor) 0 100%/0% 3px no-repeat;font-size:clamp(32px,8.4vw,136px);font-weight:560;line-height:1;letter-spacing:-.05em;text-decoration:none;transition:background-size 450ms var(--ease-out)}
.contact-actions{display:flex;flex-wrap:wrap;align-items:center;gap:10px 28px;margin-top:32px}
.copy-email{min-height:48px;padding:0 22px;border:1px solid var(--rule-strong);border-radius:999px;font-size:16px;font-weight:500;transition:transform var(--press) var(--ease-out),background-color var(--hover) ease}
/* Al copiar, el relleno cubre el botón, la etiqueta sale hacia arriba y se dibuja el check. */
.copy-email{position:relative;overflow:hidden;isolation:isolate}
.copy-fill{position:absolute;inset:0;z-index:-1;background:var(--ink);transform:scaleX(0);transform-origin:left center}
.copy-label{display:block}
.copy-check{position:absolute;top:50%;left:50%;width:24px;height:24px;margin:-12px 0 0 -12px;fill:none;stroke:var(--paper);stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:1 1;stroke-dashoffset:1;opacity:0}
.contact-email.is-copied{background-size:100% 3px}
@media (hover:hover) and (pointer:fine){
  .contact-email:hover{background-size:100% 3px}
  .copy-email:hover{background:var(--paper-deep)}
}

/* ---------- Pie ---------- */
.site-footer{border-top:1px solid var(--rule)}
.footer-row{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 24px;padding-block:20px 28px;font-size:14px;color:var(--ink-soft)}
.footer-row .text-link{font-size:14px;color:var(--ink)}

/* ---------- 404 (27-sep): boceto B de Hugo, 404 en Bodoni Moda (OFL) convertido a trazado, sin cargar la fuente.
   Composición de la de McAlpine: en móvil, mensaje en medio y 404 abajo; en escritorio, 404 detrás y mensaje en el
   hueco del 0 (al 82 % de su ancho, mínimo 190 px: por debajo, composición de móvil). Generado con TEMP/apply-404.cjs. */
.nf{position:relative;display:grid;grid-template-rows:1fr auto 1fr;row-gap:60px;min-height:100svh;padding:30px 20px 20px;overflow:hidden;color:var(--ink)}
.nf-mark{position:absolute;top:24px;left:24px;z-index:2;display:block;color:var(--ink)}
.nf-mark svg{display:block;width:auto;height:22px;overflow:visible}
.nf-inner{grid-row:2;max-width:15rem;margin-inline:auto;text-align:center}
.nf-title{font-size:24px;font-weight:500;line-height:1.08;letter-spacing:-.035em;text-wrap:balance}
.nf-text{margin-top:12px;font-size:15px;line-height:1.5;color:var(--ink-soft);text-wrap:balance}
.nf-button{display:inline-flex;align-items:center;justify-content:center;margin-top:24px;padding:9px 26px;border:1px solid var(--ink);border-radius:999px;color:var(--ink);font-size:14px;font-weight:500;text-decoration:none;transition:background-color .2s,color .2s}
.nf-button:hover{background:var(--ink);color:var(--paper)}
.nf-visual{grid-row:3;display:flex;align-items:flex-end;justify-content:center}
.nf-visual svg{display:block;width:100%;height:auto;max-height:45svh;fill:var(--ink)}
@media (min-width:1348px) and (min-height:616px){
  .nf{display:block;padding:0}
  .nf-visual{position:absolute;inset:20px}
  .nf-visual svg{height:100%;max-height:none}
  .nf-inner{position:absolute;top:50%;left:50%;z-index:1;width:min(0.1453 * (100vw - 40px),0.3301 * (100svh - 40px));max-width:none;transform:translate(-50%,-50%)}
  .nf-title{font-size:28px}
}
@keyframes nf-rise{from{opacity:0;transform:translateY(9%)}to{opacity:1;transform:none}}
@keyframes nf-fade{from{opacity:0;translate:0 10px}to{opacity:1;translate:0 0}}
@media (prefers-reduced-motion:no-preference){
  .nf-digit{transform-box:fill-box;animation:nf-rise .95s cubic-bezier(.23,1,.32,1) both}
  .nf-digit:nth-child(2){animation-delay:.09s}
  .nf-digit:nth-child(3){animation-delay:.18s}
  .nf-inner>*{animation:nf-fade .7s cubic-bezier(.23,1,.32,1) both}
  .nf-inner>:nth-child(1){animation-delay:.42s}
  .nf-inner>:nth-child(2){animation-delay:.5s}
  .nf-inner>:nth-child(3){animation-delay:.58s}
}

/* ---------- Movimiento reducido: sin desplazamientos; los cambios de estado siguen siendo visibles ---------- */
@media (prefers-reduced-motion:reduce){
  .nav-pill,.link-arrow,.st-zone,.st-panel,.st-dot,.phase{transition:none}
  .button:active,.text-link:active,.nav-link:active,.nav-toggle:active,.copy-email:active,.lab-capability:has(.capability-trigger:active),.lab-capability:has(.cap-close:active){transform:none}
  .cell:hover{transform:none}
}

/* ---------- Impresión ---------- */
@media print{
  .site-header,.skip-link,.marquee,.chapter-close,.process-tabs,.copy-email,.lab-scene::before,.lab-field,.hero-waves{display:none!important}
  #smooth-wrapper,#smooth-content{position:static!important;transform:none!important;height:auto!important;overflow:visible!important}
  .hero{padding-top:24px}
  .hero-signature .hero-identity{visibility:visible!important;opacity:1!important;transform:none!important}
  .lab-scene{--lab-bg:var(--paper)!important;--lab-fg:var(--ink)!important;--lab-secondary:var(--ink-soft)!important;--lab-border:var(--rule)!important;--lab-accent:var(--ink)!important;--lab-raise:var(--paper)!important;padding-block:24px}
  .lab-capabilities.is-enhanced .capability-action{display:none}
  .lab-capability::before,.cap-back::before,.cap-back-head{display:none}
  /* Volteo: las dos caras, una debajo de otra y sin girar. */
  .cap-flip{gap:10px;transform:none!important}
  .cap-face{grid-area:auto;transform:none!important;-webkit-backface-visibility:visible;backface-visibility:visible}
  .cap-word,.cap-reveal{opacity:1!important;filter:none!important;translate:none!important}
  .cap-svg{opacity:1!important}
  .lab-capability,.project-card,.decision{break-inside:avoid}
  .lab-capability,.project-card,.lab-intro,.tools-visual{visibility:visible!important;opacity:1!important;transform:none!important}
  .process-note,.st-zone{visibility:visible!important;opacity:1!important}
  .process.is-enhanced .process-notes{display:block}
  .process.is-enhanced .process-note+.process-note{margin-top:16px}
  .contact{min-height:0}
  /* Herramientas: todas las píldoras a la vista, sin foco ni encendido. */
  .cell::before{display:none}
  .cell.is-lit .tool-list li,.cell.is-lit .tool-list li.is-on{opacity:1;background:none;border-color:var(--rule-strong);color:var(--ink)}
}
