  /* ============================================================
     PORTFOLIO — Estética editorial japonesa, minimalista de lujo
     Paleta: #0a0a0a (casi negro) · #f5f2ee (blanco roto) · #c9a96e (dorado suave)
     ============================================================ */

  :root {
    --ink:        #0a0a0a;
    --paper:      #f5f2ee;
    --paper-soft: #ece8e1;
    --gold:       #c9a96e;
    --rule:       rgba(10, 10, 10, 0.12);
    /* 0.55 daba ~4.0:1 sobre papel — bajo WCAG AA.
       0.66 sube a ~4.8:1 para texto normal manteniendo el tono editorial. */
    --muted:      rgba(10, 10, 10, 0.66);
    --danger:     #a02e2e;
    /* Color muted INVERTIDO — para texto sobre fondo `--ink`
       (overlays, toasts, cursor). En light: tinta es oscura →
       muted = paper-tinted. En dark: tinta es clara → muted
       = paper-tinted (oscuro). Adapta automáticamente. */
    --muted-on-ink: rgba(245, 242, 238, 0.62);
    /* Tonos adaptables: en light son tinta semi-translúcida,
       en dark se invierten a papel semi-translúcido para mantener
       el mismo grado de presencia visual en ambos temas. */
    --rule-soft:  rgba(10, 10, 10, 0.06);
    --stripe:     rgba(10, 10, 10, 0.05);
    --rail:       rgba(10, 10, 10, 0.20);
    --kbd-bg:     rgba(10, 10, 10, 0.04);
    /* Modos de mezcla del grano / retrato — distintos en oscuro */
    --grain-blend: multiply;
    --portrait-blend: multiply;
    --grain-opacity: 0.035;

    --serif: "Cormorant Garamond", "Times New Roman", serif;
    --sans:  "Manrope", -apple-system, BlinkMacSystemFont, sans-serif;
    --mono:  "JetBrains Mono", ui-monospace, monospace;

    --ease:   cubic-bezier(0.2, 0.7, 0.2, 1);
    --ease-2: cubic-bezier(0.65, 0, 0.35, 1);
  }

  /* ============================================================
     MODO OSCURO — invierte tinta/papel, mantiene el oro.
     Activable con data-theme="dark" en <html> (toggle) y por
     defecto sigue prefers-color-scheme si el usuario no eligió.
     ============================================================ */
  html[data-theme="dark"] {
    --ink:        #f5f2ee;
    --paper:      #0a0a0a;
    --paper-soft: #161412;
    --rule:       rgba(245, 242, 238, 0.16);
    --muted:      rgba(245, 242, 238, 0.72);
    --danger:     #e87474;
    --muted-on-ink: rgba(10, 10, 10, 0.62);
    /* Tonos adaptables invertidos */
    --rule-soft:  rgba(245, 242, 238, 0.08);
    --stripe:     rgba(245, 242, 238, 0.07);
    --rail:       rgba(245, 242, 238, 0.28);
    --kbd-bg:     rgba(245, 242, 238, 0.06);
    /* En oscuro el grano se mezcla con screen, y el retrato
       en blanco y negro pierde el multiply (lighten queda mejor) */
    --grain-blend: screen;
    --portrait-blend: lighten;
    --grain-opacity: 0.06;
    color-scheme: dark;
  }
  /* Transición global de color SÓLO durante el cambio activo de tema.
     Se activa con `html.is-theme-transit` (añadido por JS al toggle,
     removido tras 500ms). Si la dejásemos siempre activa, reescribiría
     transition-property en TODOS los elementos y rompería las
     animaciones de entrada (loader, ensō, nav, chars del título). */
  html.is-theme-transit body,
  html.is-theme-transit body * {
    transition-property: background-color, color, border-color, fill, stroke;
    transition-duration: 0.5s;
    transition-timing-function: var(--ease);
  }

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

  html, body { margin: 0; padding: 0; }
  /* Reserva espacio para la scrollbar siempre — evita que el contenido
     se desplace lateralmente al entrar/salir de zonas con scroll. */
  html { scrollbar-gutter: stable; overflow-x: hidden; }

  /* Lenis · smooth scroll global ============================
     html.lenis     — flag global, evita "ratón sin scroll"
     html.lenis-smooth body  — el cuerpo es desplazado por JS
     ========================================================= */
  html.lenis,
  html.lenis body {
    height: auto;
  }
  html.lenis-stopped body { overflow: hidden; }
  .lenis.lenis-smooth { scroll-behavior: auto !important; }
  .lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }

  body {
    background: var(--paper);
    color: var(--ink);
    font-family: var(--sans);
    font-weight: 300;
    font-size: 16px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
    /* Ocultamos el cursor del sistema; usamos uno personalizado */
    cursor: none;
  }

  /* Sutil grano editorial para evitar que el blanco roto se sienta plano */
  body::before {
    content: "";
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 1;
    opacity: var(--grain-opacity, 0.035);
    mix-blend-mode: var(--grain-blend, multiply);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  }

  a { color: inherit; text-decoration: none; }
  /* Selección: gold + tinta oscura constante (gold sobre tinta clara
     da contraste insuficiente; fijamos el texto al negro). */
  ::selection { background: var(--gold); color: #0a0a0a; }

  /* ===== Cursor personalizado ===== */
  .cursor-dot,
  .cursor-ring {
    position: fixed;
    top: 0; left: 0;
    pointer-events: none;
    z-index: 9999;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    will-change: transform;
  }
  .cursor-dot {
    width: 5px; height: 5px;
    background: var(--ink);
    transition: opacity 0.2s var(--ease), transform 0.15s var(--ease);
  }
  .cursor-ring {
    width: 36px; height: 36px;
    border: 1px solid var(--ink);
    transition:
      width 0.35s var(--ease),
      height 0.35s var(--ease),
      border-color 0.35s var(--ease),
      background 0.35s var(--ease),
      opacity 0.2s var(--ease);
  }
  body.is-hover .cursor-ring {
    width: 64px; height: 64px;
    border-color: var(--gold);
    background: rgba(201, 169, 110, 0.08);
  }
  body.is-hover .cursor-dot { opacity: 0; }
  /* Ocultamos cursor cuando el ratón sale */
  body.cursor-hidden .cursor-dot,
  body.cursor-hidden .cursor-ring { opacity: 0; }

  /* En táctil/sin puntero, devolvemos cursor nativo */
  @media (hover: none), (pointer: coarse) {
    body { cursor: auto; }
    .cursor-dot, .cursor-ring { display: none; }
  }

  /* ============================================================
     A11Y — Skip link + foco visible global
     ============================================================ */
  /* Skip-link editorial: invisible hasta recibir foco con teclado.
     Al tabular desde la URL, es lo primero que aparece. */
  .skip-link {
    position: fixed;
    top: 14px;
    left: 14px;
    z-index: 300;
    padding: 12px 18px;
    background: var(--ink);
    color: var(--paper);
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    border: 1px solid var(--gold);
    transform: translateY(-140%);
    transition: transform 0.4s var(--ease-2);
  }
  .skip-link:focus-visible {
    transform: translateY(0);
    outline: none;
  }

  /* Foco global — anillo dorado fino, sin caja gruesa.
     Sólo cuando viene de teclado (focus-visible). */
  :focus { outline: none; }
  :focus-visible {
    outline: 2px solid var(--gold);
    outline-offset: 4px;
    border-radius: 2px;
  }
  /* Inputs y textarea: el subrayado dorado ya es feedback;
     evitamos el doble anillo y usamos un offset interior. */
  .form__field input:focus-visible,
  .form__field textarea:focus-visible {
    outline: none;
  }
  /* Cuando el usuario navega con teclado, mostramos el cursor del
     sistema — es la única forma de saber dónde está. */
  body:has(:focus-visible) { cursor: auto; }
  body:has(:focus-visible) .cursor-dot,
  body:has(:focus-visible) .cursor-ring { opacity: 0; }

  /* ============================================================
     POLISH/UX — Toggle de cursor, toast, hint del loader
     ============================================================ */
  /* Cuando el usuario apaga el cursor personalizado guardamos
     en localStorage y aplicamos esta clase al <body>. */
  body.cursor-off { cursor: auto; }
  body.cursor-off .cursor-dot,
  body.cursor-off .cursor-ring { display: none; }

  .cursor-toggle {
    position: fixed;
    left: clamp(18px, 2.4vw, 36px);
    bottom: clamp(18px, 2.4vw, 36px);
    z-index: 40;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    background: transparent;
    border: 1px solid var(--rule);
    color: var(--muted);
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    cursor: pointer;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    transition:
      color 0.4s var(--ease),
      border-color 0.4s var(--ease),
      background 0.4s var(--ease);
  }
  .cursor-toggle:hover { color: var(--ink); border-color: var(--ink); }
  .cursor-toggle__dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--gold);
    box-shadow: 0 0 0 3px rgba(201, 169, 110, 0.18);
    transition: background 0.4s var(--ease), box-shadow 0.4s var(--ease);
  }
  .cursor-toggle[aria-pressed="false"] .cursor-toggle__dot {
    background: transparent;
    box-shadow: inset 0 0 0 1px var(--muted);
  }
  /* En táctil no tiene sentido el toggle */
  @media (hover: none), (pointer: coarse) {
    .cursor-toggle { display: none; }
  }

  /* Hint dentro del loader — el del medio en el footer */
  .loader__hint {
    color: var(--muted);
  }
  .loader__hint kbd {
    display: inline-block;
    padding: 2px 7px;
    margin: 0 4px;
    border: 1px solid var(--rule);
    background: var(--kbd-bg);
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.1em;
    color: var(--ink);
  }
  @media (max-width: 700px) {
    .loader__hint { display: none; }
  }

  /* Toast editorial — slide desde abajo con marca dorada */
  .toast {
    position: fixed;
    left: 50%;
    bottom: clamp(24px, 4vw, 48px);
    z-index: 80;
    transform: translate(-50%, 24px);
    display: inline-flex;
    align-items: center;
    gap: 14px;
    padding: 14px 22px;
    background: var(--ink);
    color: var(--paper);
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    border: 1px solid var(--gold);
    opacity: 0;
    pointer-events: none;
    transition:
      transform 0.5s var(--ease-2),
      opacity 0.4s var(--ease);
  }
  .toast.is-on {
    transform: translate(-50%, 0);
    opacity: 1;
  }
  .toast::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--gold);
  }

  /* Magnetic buttons — el JS aplica translate3d via custom prop.
     CSS sólo expone la variable y suaviza la vuelta a 0. */
  [data-magnetic] {
    transform: translate3d(var(--mag-x, 0), var(--mag-y, 0), 0);
    transition: transform 0.45s var(--ease-2);
  }
  [data-magnetic].is-mag { transition: none; }

  /* ============================================================
     NAV · controles editoriales (idioma + tema)
     ============================================================ */
  .nav__right {
    display: flex;
    align-items: center;
    gap: clamp(20px, 3vw, 40px);
  }
  .nav__controls {
    display: flex;
    align-items: center;
    gap: 14px;
    padding-left: 18px;
    border-left: 1px solid var(--rule);
  }

  /* Botón de idioma — ES · EN, el activo en oro */
  .lang-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 2px;
    background: transparent;
    border: none;
    cursor: pointer;
    color: var(--muted);
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.22em;
    transition: color 0.4s var(--ease);
  }
  .lang-toggle [data-lang] {
    transition: color 0.4s var(--ease);
  }
  .lang-toggle .sep {
    opacity: 0.5;
  }
  html[data-lang="es"] .lang-toggle [data-lang="es"],
  html[data-lang="en"] .lang-toggle [data-lang="en"] {
    color: var(--gold);
  }
  html[data-lang="es"] .lang-toggle [data-lang="en"],
  html[data-lang="en"] .lang-toggle [data-lang="es"] {
    color: var(--muted);
  }
  .lang-toggle:hover [data-lang] { color: var(--ink); }
  .lang-toggle:hover [data-lang]:not([data-lang="en"]):not([data-lang="es"]) { color: var(--muted); }

  /* Botón de tema — glifo dual estilo ensō partido */
  .theme-toggle {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    background: transparent;
    border: none;
    color: var(--ink);
    cursor: pointer;
    border-radius: 50%;
    transition:
      transform 0.5s var(--ease-2),
      color 0.4s var(--ease);
  }
  .theme-toggle svg {
    transition: transform 0.6s var(--ease-2);
  }
  .theme-toggle:hover { color: var(--gold); }
  .theme-toggle:hover svg { transform: rotate(45deg); }
  /* Cuando el tema está en oscuro, giramos el glifo 180º para
     que la mitad sólida indique el estado opuesto */
  html[data-theme="dark"] .theme-toggle svg {
    transform: rotate(180deg);
  }
  html[data-theme="dark"] .theme-toggle:hover svg {
    transform: rotate(225deg);
  }
  /* Badge AUTO — punto dorado en la esquina cuando el tema sigue al sistema */
  .theme-toggle::after {
    content: "";
    position: absolute;
    top: -1px;
    right: -1px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--gold);
    box-shadow: 0 0 0 2px var(--paper);
    opacity: 0;
    transform: scale(0.5);
    transition:
      opacity 0.35s var(--ease),
      transform 0.45s var(--ease-2);
    pointer-events: none;
  }
  html[data-theme-auto] .theme-toggle::after {
    opacity: 1;
    transform: scale(1);
  }
  .theme-toggle[data-mode="auto"] { color: var(--gold); }

  @media (max-width: 880px) {
    .nav__controls { padding-left: 12px; gap: 10px; }
    .lang-toggle { font-size: 10px; letter-spacing: 0.18em; }
  }

  /* ===== Layout base ===== */
  .shell {
    max-width: 1440px;
    margin: 0 auto;
    padding: 0 clamp(24px, 5vw, 80px);
    position: relative;
    z-index: 2;
  }

  /* ===== Nav fija minimalista =====
     Estado inicial: desplazada hacia arriba + invisible.
     Una vez la pantalla de carga termina, JS le añade
     .is-revealed y entra deslizándose desde el techo. */
  .nav {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 50;
    padding: 28px clamp(24px, 5vw, 80px);
    display: flex;
    align-items: center;
    justify-content: space-between;
    color: var(--ink);
    transform: translateY(-110%);
    opacity: 0;
    transition:
      transform 1.1s var(--ease-2),
      opacity 0.7s var(--ease);
  }
  .nav.is-revealed {
    transform: translateY(0);
    opacity: 1;
  }
  /* Links en color ink directo. La página tiene fondo claro
     en toda su altura, así que no hace falta mix-blend. */
  .nav__links {
    color: var(--ink);
  }
  /* Logo = foto circular pequeña con ensō trazado alrededor.
     El padding interno separa la imagen del anillo dorado. */
  .nav__mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    position: relative;
    transition: transform 0.6s var(--ease-2);
  }
  .nav__mark img {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    object-fit: cover;
    display: block;
    filter: grayscale(1) contrast(1.05);
    transition: filter 0.6s var(--ease);
  }
  /* Anillo ensō alrededor del avatar */
  .nav__mark-enso {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    color: var(--gold);
    pointer-events: none;
    /* Rotación perpétua muy lenta, eco directo del ensō del hero */
    animation: nav-enso-spin 24s linear infinite;
  }
  @keyframes nav-enso-spin {
    to { transform: rotate(360deg); }
  }
  .nav__mark:hover { transform: rotate(-4deg); }
  .nav__mark:hover img { filter: grayscale(0.3) contrast(1.1); }
  .nav__links {
    display: flex;
    gap: 36px;
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
  }
  .nav__links a {
    position: relative;
    padding-bottom: 2px;
    white-space: nowrap;
  }
  .nav__links a::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 1px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.45s var(--ease);
  }
  .nav__links a:hover::after { transform: scaleX(1); }
  /* Estado activo (scrollspy) — subrayado permanente + punto dorado */
  .nav__links a.is-active::after { transform: scaleX(1); }
  .nav__links a.is-active::before {
    content: "";
    display: inline-block;
    width: 4px; height: 4px;
    border-radius: 50%;
    background: var(--gold);
    margin-right: 8px;
    vertical-align: 2px;
  }

  /* ===== Entrada con fade staggered ===== */
  .fade-up {
    opacity: 0;
    transform: translateY(20px);
    transition:
      opacity 1.1s var(--ease),
      transform 1.1s var(--ease);
  }
  .fade-up.is-in {
    opacity: 1;
    transform: translateY(0);
  }

  /* ============================================================
     HERO
     ============================================================ */
  .hero {
    min-height: 100vh;
    padding: 160px 0 80px;
    display: grid;
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr auto auto; /* meta · title · role · foot */
    gap: clamp(32px, 4vw, 56px);
    position: relative;
  }

  /* ===== Capa de fondo del hero ============================
     Tres elementos editoriales superpuestos:
       · .hero__grid    — columnas verticales finas
       · .hero__enso    — círculo trazado tipo “ensō” que rota lento
     Van por detrás del contenido (z-index: 0) y son
     pointer-events: none para no robar el cursor personalizado.
     ========================================================== */
  .hero__bg {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 0;
  }
  .hero > *:not(.hero__bg) { position: relative; z-index: 1; }

  /* Columnas — 12 líneas verticales muy ligeras, como guías */
  .hero__grid {
    position: absolute;
    inset: 0;
    background-image: repeating-linear-gradient(
      to right,
      transparent 0,
      transparent calc((100% / 12) - 1px),
      var(--rule-soft) calc((100% / 12) - 1px),
      var(--rule-soft) calc(100% / 12)
    );
    mask-image: linear-gradient(to bottom, transparent 0%, #000 25%, #000 75%, transparent 100%);
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 25%, #000 75%, transparent 100%);
    opacity: 0;
    animation: bg-fade-in 1.6s var(--ease) 0.4s forwards;
  }
  @keyframes bg-fade-in {
    to { opacity: 1; }
  }

  /* Círculo ensō trazado a mano alzada con stroke-dasharray
     animado. Reacciona al ratón con --mx / --my (parallax). */
  /* Wrapper de ENTRADA — sólo se mueve una vez, al revelarse.
     Estado inicial: empujado fuera por la derecha + invisible. */
  .hero__enso {
    position: absolute;
    top: 40%;
    right: -6vw;
    width: clamp(420px, 56vw, 820px);
    height: clamp(420px, 56vw, 820px);
    transform: translate(130%, -50%);
    opacity: 0;
    will-change: transform, opacity;
    transition:
      transform 1.6s var(--ease-2),
      opacity 1s var(--ease);
    pointer-events: none;
  }
  .hero__enso.is-revealed {
    transform: translate(0, -50%);
    opacity: 1;
  }

  /* Wrapper INTERNO — recibe los cambios de mouse/rotación cada frame.
     Sin transition, así no compite con la entrada del wrapper externo. */
  .hero__enso-inner {
    width: 100%;
    height: 100%;
    transform:
      translate(calc(var(--mx, 0) * 18px), calc(var(--my, 0) * 14px))
      rotate(var(--enso-rot, 0deg));
    will-change: transform;
  }
  .hero__enso svg {
    width: 100%;
    height: 100%;
    display: block;
  }
  .hero__enso circle {
    fill: none;
    stroke: var(--gold);
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-dasharray: 2800;
    stroke-dashoffset: 2800;
    animation: enso-draw 3.2s var(--ease-2) 0.8s forwards;
    transform-origin: 50% 50%;
  }
  @keyframes enso-draw {
    to { stroke-dashoffset: 320; }
  }
  /* Marca de tinta al centro del ensō, casi imperceptible */
  .hero__enso .ink {
    fill: rgba(201, 169, 110, 0.06);
    stroke: none;
  }

  @media (max-width: 880px) {
    .hero__enso { right: -30vw; top: 60%; }
  }

  .hero__meta {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--muted);
  }
  .hero__meta .dot {
    display: inline-block;
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--gold);
    margin-right: 10px;
    vertical-align: middle;
    box-shadow: 0 0 0 4px rgba(201, 169, 110, 0.18);
  }

  .hero__title {
    font-family: var(--serif);
    font-weight: 300;
    font-size: clamp(64px, 13vw, 200px);
    line-height: 0.92;
    letter-spacing: -0.02em;
    margin: 0;
    /* Parallax sutil */
    will-change: transform;
  }
  .hero__title em {
    font-style: italic;
    color: var(--gold);
    font-weight: 300;
  }
  .hero__title .ampersand {
    font-style: italic;
    font-family: var(--serif);
    color: var(--gold);
  }
  /* Líneas del título — cada una es una máscara individual.
     Padding extra para no recortar descendentes ni la inclinación
     de la cursiva. */
  .hero__title-line {
    display: block;
    overflow: hidden;
    padding: 0.04em 0.08em 0.22em 0;
    margin: 0 0 -0.05em;
  }
  .hero__title-line .line-inner { display: inline-block; }
  /* Letras individuales — estado inicial oculto bajo la máscara.
     Motion las anima a translateY(0) con stagger al cargar. */
  .hero__title .char {
    display: inline-block;
    transform: translateY(115%);
    opacity: 0;
    will-change: transform, opacity;
  }

  .hero__foot {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    gap: clamp(24px, 4vw, 64px);
    flex-wrap: wrap;
  }
  .hero__role {
    font-family: var(--serif);
    font-style: italic;
    font-weight: 300;
    font-size: clamp(22px, 2.8vw, 36px);
    line-height: 1.2;
    min-height: 1.5em;
    /* Marca tipográfica antes del texto */
    display: flex;
    align-items: baseline;
    gap: 18px;
  }
  .hero__role::before {
    content: "—";
    color: var(--gold);
    font-style: normal;
    font-family: var(--mono);
    font-size: 14px;
    letter-spacing: 0;
  }

  /* ===== Métricas del hero ===== */
  .hero__stats {
    display: grid;
    grid-template-columns: repeat(3, auto);
    gap: clamp(28px, 5vw, 72px);
    margin: 0;
    padding: 0;
  }
  .hero__stats > div {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  .hero__stats dt {
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--muted);
    margin: 0;
  }
  .hero__stats dd {
    font-family: var(--serif);
    font-weight: 400;
    font-size: clamp(20px, 2.2vw, 28px);
    line-height: 1;
    margin: 0;
  }
  .hero__stats dd em {
    font-style: italic;
    color: var(--gold);
    font-weight: 300;
  }

  /* ===== CTA del hero ===== */
  .hero__cta {
    display: inline-flex;
    align-items: center;
    gap: 18px;
    padding: 18px 28px 18px 32px;
    border: 1px solid var(--ink);
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--ink);
    position: relative;
    overflow: hidden;
    isolation: isolate;
    transition: color 0.5s var(--ease);
  }
  .hero__cta::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--ink);
    transform: scaleX(0);
    transform-origin: right center;
    transition: transform 0.55s var(--ease-2);
    z-index: -1;
  }
  .hero__cta:hover { color: var(--paper); }
  .hero__cta:hover::before {
    transform: scaleX(1);
    transform-origin: left center;
  }
  .hero__cta .arrow {
    font-family: var(--serif);
    font-style: italic;
    font-size: 16px;
    letter-spacing: 0;
    transition: transform 0.45s var(--ease);
  }
  .hero__cta:hover .arrow { transform: translateX(6px); }

  @media (max-width: 700px) {
    .hero__stats { grid-template-columns: 1fr 1fr; gap: 24px 32px; }
    .hero__foot { gap: 32px; }
    .hero__cta { width: 100%; justify-content: space-between; }
  }
  .typewriter {
    position: relative;
  }
  .typewriter__caret {
    display: inline-block;
    width: 2px;
    height: 0.85em;
    background: var(--gold);
    margin-left: 4px;
    vertical-align: -2px;
    animation: blink 1s steps(1) infinite;
  }
  @keyframes blink {
    50% { opacity: 0; }
  }


  /* ============================================================
     Encabezado de sección reutilizable
     ============================================================ */
  .section {
    padding: 140px 0;
    border-top: 1px solid var(--rule);
    position: relative;
  }
  .section__head {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: baseline;
    gap: 32px;
    margin-bottom: 80px;
  }
  .section__no {
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: 0.2em;
    color: var(--gold);
  }
  .section__title {
    font-family: var(--serif);
    font-weight: 300;
    font-style: italic;
    font-size: clamp(40px, 6vw, 88px);
    line-height: 1;
    letter-spacing: -0.01em;
    margin: 0;
  }

  /* ============================================================
     ABOUT
     ============================================================ */
  .about {
    display: grid;
    /* Fila 1: retrato (~280px) | skills (resto)
       Fila 2: texto a ancho completo */
    grid-template-columns: minmax(220px, 300px) 1fr;
    gap: clamp(40px, 6vw, 80px) clamp(40px, 8vw, 120px);
    align-items: start;
  }

  /* Texto editorial — ocupa toda la fila 2 */
  .about__text {
    grid-column: 1 / -1;
    margin-top: clamp(20px, 4vw, 56px);
    font-family: var(--serif);
    font-weight: 300;
    font-size: clamp(20px, 1.8vw, 26px);
    line-height: 1.5;
  }

  /* Cuerpo en 2 columnas tipográficas (revista) */
  .about__copy {
    column-count: 2;
    column-gap: clamp(40px, 5vw, 96px);
  }
  .about__copy p {
    margin: 0 0 1.2em;
    break-inside: avoid-column;
  }
  .about__copy p:last-child { margin-bottom: 0; }
  /* Cita destacada — pull quote de ancho completo */
  .about__text .about__quote {
    font-family: var(--serif);
    font-weight: 300;
    font-style: italic;
    font-size: clamp(28px, 3.4vw, 52px);
    line-height: 1.2;
    margin: 0 0 clamp(40px, 6vw, 72px);
    padding: 0 0 clamp(32px, 4vw, 56px);
    border-bottom: 1px solid var(--rule);
    letter-spacing: -0.01em;
    position: relative;
    max-width: 30ch;
  }
  /* Cada cláusula entra con clip-path wipe de izquierda a derecha */
  .quote-line {
    display: block;
    clip-path: inset(0 100% 0 0);
    transition: clip-path 1.2s var(--ease-2);
    will-change: clip-path;
  }
  .about__quote.is-in .quote-line { clip-path: inset(0); }
  /* Stagger entre las dos cláusulas */
  .about__quote.is-in .quote-line:nth-child(2) { transition-delay: 0.25s; }
  .about__text .about__quote::before,
  .about__text .about__quote::after {
    color: var(--gold);
    font-style: italic;
  }
  .about__text .about__quote::before { content: "« "; }
  .about__text .about__quote::after  { content: " »"; }
  .about__text .about__quote em {
    font-style: italic;
    color: var(--gold);
  }

  .about__text .lede::first-letter {
    font-family: var(--serif);
    font-style: italic;
    color: var(--gold);
    font-size: 3.2em;
    line-height: 0.85;
    float: left;
    margin: 0.05em 0.1em 0 0;
    font-weight: 400;
  }

  /* Retrato editorial — columna izquierda del about.
     Cuadrado, B&N con mix-blend-mode para fundirse con
     el papel. Pequeñas marcas doradas en la esquina
     superior izquierda como detalle de revista. */
  .portrait {
    margin: 0 0 44px;
    max-width: 280px;
  }
  .portrait__frame {
    position: relative;
    overflow: hidden;
    background: var(--paper-soft);
    aspect-ratio: 1 / 1;
  }
  .portrait__frame::before,
  .portrait__frame::after {
    content: "";
    position: absolute;
    top: 0; left: 0;
    background: var(--gold);
    z-index: 2;
  }
  .portrait__frame::before { width: 24px; height: 1px; }
  .portrait__frame::after  { width: 1px; height: 24px; }
  .portrait img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    filter: grayscale(1) contrast(1.05);
    mix-blend-mode: var(--portrait-blend, multiply);
    /* Estado inicial: completamente clippada por abajo. Cuando
       el reveal entra al viewport, clip-path baja del 100% al 0%
       y la imagen aparece desde arriba. */
    clip-path: inset(0 0 100% 0);
    transition:
      transform 1.4s var(--ease),
      filter 0.8s var(--ease),
      clip-path 1.6s var(--ease-2);
    will-change: transform, clip-path;
  }
  .portrait.is-revealed img {
    clip-path: inset(0 0 0% 0);
  }
  .portrait:hover img {
    transform: scale(1.04);
    filter: grayscale(0.4) contrast(1.1);
  }

  /* Línea dorada que acompaña al borde inferior del clip.
     Posición Y interpolada en sincronía con la imagen
     (0% → 100%) y al final desvanece. */
  .portrait__wipe {
    position: absolute;
    left: -2%;
    right: -2%;
    top: 0;
    height: 2px;
    background: var(--gold);
    z-index: 3;
    transform: translateY(0);
    opacity: 0;
    transition:
      transform 1.6s var(--ease-2),
      opacity 0.4s var(--ease);
    pointer-events: none;
  }
  .portrait.is-revealed .portrait__wipe {
    transform: translateY(calc(var(--portrait-h, 280px) - 2px));
    opacity: 0;
    /* opacidad: visible justo cuando la animación arranca, fade out
       al terminar — se controla con keyframes para coordinar timings */
    animation: portrait-wipe-flash 1.6s var(--ease-2) forwards;
  }
  @keyframes portrait-wipe-flash {
    0%   { opacity: 0; }
    8%   { opacity: 1; }
    85%  { opacity: 1; }
    100% { opacity: 0; }
  }
  .portrait:hover img {
    transform: scale(1.04);
    filter: grayscale(0.4) contrast(1.1);
  }
  .portrait figcaption {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: baseline;
    gap: 12px;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--rule);
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--muted);
  }
  .portrait__no { color: var(--gold); }

  .skills { display: grid; gap: 26px; }
  .skill {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: baseline;
    gap: 20px;
  }
  .skill__no {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.2em;
    color: var(--muted);
  }
  .skill__name {
    font-family: var(--serif);
    font-style: italic;
    font-size: 22px;
    font-weight: 400;
  }
  .skill__pct {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.18em;
    color: var(--muted);
  }
  .skill__bar {
    grid-column: 1 / -1;
    height: 1px;
    background: var(--rule);
    position: relative;
    overflow: hidden;
  }
  .skill__bar::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--ink);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 1.6s var(--ease-2);
  }
  .skill.is-in .skill__bar::after {
    transform: scaleX(var(--lvl, 0.5));
  }
  /* Acento dorado bajo la barra cuando llega */
  .skill__bar::before {
    content: "";
    position: absolute;
    left: 0; bottom: -1px;
    width: 8px; height: 3px;
    background: var(--gold);
    transform: translateX(calc(var(--lvl, 0.5) * (100% - 8px) * 100 - 0%));
    transform: translateX(0);
    opacity: 0;
    transition: opacity 0.6s var(--ease) 1.2s;
  }
  .skill.is-in .skill__bar::before { opacity: 1; }

  /* ============================================================
     TIMELINE · trayectoria
     Estructura editorial:
       columna izquierda → año en serif itálico + punto dorado
       columna derecha   → puesto, empresa, descripción y stack
     Una línea vertical fina une los puntos.
     ============================================================ */
  .timeline {
    list-style: none;
    margin: 0; padding: 0;
    display: grid;
    gap: clamp(60px, 8vw, 100px);
    position: relative;
  }
  /* Línea vertical contínua, justo a la altura del punto */
  .timeline::before {
    content: "";
    position: absolute;
    top: 8px;
    bottom: 8px;
    left: clamp(70px, 11vw, 130px); /* alineada con el punto dorado */
    width: 1px;
    background: var(--rule);
    transform: scaleY(var(--tl-progress, 0));
    transform-origin: top;
    transition: transform 1.6s var(--ease-2);
  }
  .timeline.is-in::before {
    --tl-progress: 1;
  }

  .timeline__item {
    display: grid;
    grid-template-columns: clamp(140px, 18vw, 220px) 1fr;
    gap: clamp(32px, 5vw, 80px);
    align-items: start;
    position: relative;
    opacity: 0;
    transform: translateY(24px);
    transition:
      opacity 0.9s var(--ease) 0.2s,
      transform 0.9s var(--ease-2) 0.2s;
  }
  .timeline.is-in .timeline__item { opacity: 1; transform: translateY(0); }
  .timeline.is-in .timeline__item:nth-child(2) {
    transition-delay: 0.45s, 0.45s;
  }

  /* Año + punto */
  .timeline__year {
    position: relative;
    font-family: var(--serif);
    font-style: italic;
    font-weight: 400;
    font-size: clamp(36px, 5vw, 64px);
    line-height: 1;
    color: var(--ink);
    padding-left: clamp(20px, 3vw, 36px);
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0 14px;
  }
  .timeline__year .dot {
    position: absolute;
    top: 0.4em;
    left: auto;
    right: 0;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--gold);
    box-shadow: 0 0 0 4px rgba(201, 169, 110, 0.18);
    /* Se posiciona justo sobre la línea vertical */
    transform: translateX(calc(100% + clamp(32px, 5vw, 80px) / 2 - 5px));
  }
  .timeline__year em { font-style: italic; color: var(--ink); }
  .timeline__year .sep {
    font-family: var(--mono);
    font-style: normal;
    font-size: 0.4em;
    color: var(--muted);
    letter-spacing: 0;
    transform: translateY(-0.5em);
  }
  .timeline__year .now {
    color: var(--gold);
    font-style: italic;
    font-size: 0.7em;
  }

  /* Cuerpo */
  .timeline__role h3 {
    font-family: var(--serif);
    font-weight: 400;
    font-size: clamp(24px, 2.6vw, 36px);
    line-height: 1.15;
    margin: 0 0 6px;
    letter-spacing: -0.005em;
  }
  .timeline__company {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--muted);
    margin: 0 0 22px;
  }
  .timeline__company em {
    color: var(--gold);
    font-style: italic;
    text-transform: none;
    letter-spacing: 0;
    font-family: var(--serif);
    font-size: 14px;
    margin-left: 8px;
  }
  .timeline__desc {
    font-family: var(--serif);
    font-weight: 300;
    font-size: clamp(18px, 1.5vw, 22px);
    line-height: 1.55;
    max-width: 52ch;
    margin: 0 0 28px;
  }
  .timeline__stack {
    list-style: none;
    margin: 0; padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px 0;
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--muted);
  }
  .timeline__stack li {
    padding: 0 14px;
    border-right: 1px solid var(--rule);
    line-height: 1;
  }
  .timeline__stack li:first-child { padding-left: 0; }
  .timeline__stack li:last-child { border-right: none; }

  @media (max-width: 700px) {
    .timeline::before { display: none; }
    .timeline__item {
      grid-template-columns: 1fr;
      gap: 18px;
    }
    .timeline__year { padding-left: 0; font-size: 40px; }
    .timeline__year .dot { display: none; }
  }

  /* ============================================================
     PROJECTS — grid asimétrico
     ============================================================ */
  .projects {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    grid-auto-rows: minmax(80px, auto);
    gap: clamp(24px, 3vw, 48px) clamp(20px, 3vw, 40px);
  }
  .project { position: relative; }

  /* Estados iniciales de entrada por dirección.
     Motion los anima a x:0/y:0 con opacity 1 al entrar
     en viewport. Se mantiene como CSS para evitar FOUC. */
  .project[data-reveal] {
    opacity: 0;
    will-change: transform, opacity;
  }
  .project[data-reveal="left"]   { transform: translate3d(-80px, 0, 0); }
  .project[data-reveal="top"]    { transform: translate3d(0, -60px, 0); }
  .project[data-reveal="bottom"] { transform: translate3d(0, 80px, 0); }

  /* Posicionado asimétrico de cada proyecto */
  .project--1 { grid-column: 1 / span 7; }
  .project--2 { grid-column: 8 / span 5; margin-top: clamp(60px, 12vw, 160px); }
  .project--3 { grid-column: 3 / span 8; margin-top: clamp(40px, 6vw, 80px); }

  .project__index {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--rule);
  }
  .project__index .no { color: var(--gold); }

  /* Placeholder de imagen rayado */
  .project__media {
    position: relative;
    aspect-ratio: 4 / 5;
    background: var(--paper-soft);
    overflow: hidden;
    border: 1px solid var(--rule);
  }
  .project--1 .project__media { aspect-ratio: 4 / 5; }
  .project--2 .project__media { aspect-ratio: 3 / 4; }
  .project--3 .project__media { aspect-ratio: 16 / 9; }

  .project__media::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: repeating-linear-gradient(
      45deg,
      transparent 0 14px,
      var(--stripe) 14px 15px
    );
    transition: transform 0.9s var(--ease);
  }

  /* Poster editorial — sustituye la imagen mientras no hay
     captura real. Tag superior (mono) + monograma serif gigante
     + hint inferior con el stack abreviado. */
  .project__poster {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: clamp(20px, 3vw, 36px);
    margin: 0;
    z-index: 1;
    transition: transform 0.9s var(--ease);
  }
  .project__poster-no {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--gold);
  }
  .project__poster-mark {
    font-family: var(--serif);
    font-style: italic;
    font-weight: 300;
    font-size: clamp(72px, 11vw, 140px);
    line-height: 0.9;
    color: var(--ink);
    align-self: center;
    margin: auto 0;
    letter-spacing: -0.02em;
    /* En el card del medio (más estrecho) bajamos un punto */
    text-align: center;
  }
  .project--3 .project__poster-mark {
    /* Card más ancha/baja → margen menor */
    font-size: clamp(56px, 8vw, 96px);
  }
  .project__poster-hint {
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--muted);
    text-align: right;
  }
  /* Hover sobre el poster: el monograma se desplaza ligeramente
     mientras el overlay sube por delante */
  .project:hover .project__poster {
    transform: scale(0.96);
    opacity: 0.6;
  }
  /* (Antes había .project__media::after con content: attr(data-label).
     Ahora la rotulación va dentro de .project__poster, así que ya no
     se necesita el pseudo. Lo mantengo eliminado para no tener
     duplicación visual.) */

  /* Overlay de stack al hover */
  .project__overlay {
    position: absolute;
    inset: 0;
    background: var(--ink);
    color: var(--paper);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: clamp(20px, 3vw, 36px);
    opacity: 0;
    transition: opacity 0.5s var(--ease);
    pointer-events: none;
  }
  .project:hover .project__overlay { opacity: 1; }
  .project:hover .project__media::before {
    transform: scale(1.04);
  }

  .project__overlay-top {
    display: flex;
    justify-content: space-between;
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--muted-on-ink);
  }
  .project__overlay-top .gold { color: var(--gold); }

  .project__stack {
    list-style: none;
    margin: 0; padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .project__stack li {
    font-family: var(--serif);
    font-style: italic;
    font-weight: 300;
    font-size: clamp(22px, 2.6vw, 36px);
    line-height: 1.15;
    transform: translateY(12px);
    opacity: 0;
    transition:
      transform 0.6s var(--ease),
      opacity 0.6s var(--ease);
  }
  .project:hover .project__stack li {
    transform: translateY(0);
    opacity: 1;
  }
  .project:hover .project__stack li:nth-child(1) { transition-delay: 0.10s; }
  .project:hover .project__stack li:nth-child(2) { transition-delay: 0.18s; }
  .project:hover .project__stack li:nth-child(3) { transition-delay: 0.26s; }
  .project:hover .project__stack li:nth-child(4) { transition-delay: 0.34s; }

  .project__meta {
    margin-top: 20px;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: baseline;
    gap: 16px;
  }
  .project__title {
    font-family: var(--serif);
    font-weight: 400;
    font-size: clamp(24px, 2.4vw, 32px);
    line-height: 1.1;
    margin: 0;
  }
  .project__title em { font-style: italic; color: var(--gold); }
  .project__year,
  .project__kind {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--muted);
    align-self: end;
    white-space: nowrap;
  }
  .project__kind { color: var(--gold); }
  .project__desc {
    margin: 8px 0 0;
    color: var(--muted);
    max-width: 38ch;
  }

  /* Nota editorial bajo el header de la sección de capacidades.
     Pequeña, mono, alineada con el subtítulo del section__head. */
  .section__note {
    font-family: var(--serif);
    font-style: italic;
    font-weight: 300;
    font-size: clamp(15px, 1.1vw, 17px);
    line-height: 1.55;
    color: var(--muted);
    max-width: 56ch;
    margin: -40px 0 56px;
    padding-left: clamp(0px, 6vw, 84px);
    position: relative;
  }
  .section__note::before {
    content: "—";
    color: var(--gold);
    font-style: normal;
    font-family: var(--mono);
    font-size: 14px;
    margin-right: 12px;
  }
  @media (max-width: 880px) {
    .section__note { padding-left: 0; margin-top: -24px; }
  }

  /* ============================================================
     CONTACT
     ============================================================ */
  .contact {
    padding: 160px 0 120px;
    border-top: 1px solid var(--rule);
  }
  .contact__inner {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 80px;
    align-items: end;
  }
  .contact__kicker {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--gold);
    margin-bottom: 24px;
  }
  .contact__big {
    font-family: var(--serif);
    font-style: italic;
    font-weight: 300;
    font-size: clamp(40px, 6vw, 96px);
    line-height: 1;
    letter-spacing: -0.01em;
    margin: 0 0 16px;
  }
  .contact__sub {
    font-family: var(--sans);
    color: var(--muted);
    max-width: 32ch;
    margin: 0 0 36px;
    font-size: 16px;
    line-height: 1.55;
  }
  .contact__email {
    font-family: var(--serif);
    font-size: clamp(28px, 4vw, 56px);
    font-weight: 400;
    line-height: 1.1;
    display: inline-block;
    position: relative;
    padding-bottom: 6px;
  }
  .contact__email::after {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 1px;
    background: var(--ink);
    transform: scaleX(1);
    transform-origin: right;
    transition: transform 0.6s var(--ease);
  }
  .contact__email:hover::after {
    transform: scaleX(0);
    transform-origin: left;
  }

  .contact__links {
    display: flex;
    flex-direction: column;
    gap: 14px;
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
  }
  .contact__links a {
    display: grid;
    grid-template-columns: 24px 1fr auto;
    align-items: center;
    gap: 16px;
    padding: 14px 0;
    border-bottom: 1px solid var(--rule);
    transition: padding 0.4s var(--ease), color 0.4s var(--ease);
  }
  .contact__links a:hover { padding-left: 12px; color: var(--gold); }
  .contact__links .arrow {
    transition: transform 0.4s var(--ease);
    font-family: var(--serif);
    font-style: italic;
    font-size: 18px;
    letter-spacing: 0;
  }
  .contact__links a:hover .arrow { transform: translateX(6px); }

  /* Estado "próximamente": el enlace no apunta a nada todavía. */
  .contact__links a.is-soon {
    color: var(--muted);
    cursor: not-allowed;
  }
  .contact__links a.is-soon:hover {
    padding-left: 0;
    color: var(--muted);
  }
  .contact__links a.is-soon .arrow {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--gold);
    font-style: normal;
  }
  .contact__links a.is-soon:hover .arrow { transform: none; }

  /* ============================================================
     FORMULARIO DE CONTACTO
     ============================================================ */
  .contact__form {
    margin-top: clamp(80px, 12vw, 140px);
    position: relative;
    border-top: 1px solid var(--rule);
  }

  .form__head {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: baseline;
    gap: 32px;
    padding: 36px 0 20px;
  }
  .form__head-no {
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: 0.2em;
    color: var(--gold);
  }
  .form__head-title {
    font-family: var(--serif);
    font-weight: 300;
    font-style: italic;
    font-size: clamp(28px, 3.4vw, 48px);
    line-height: 1;
    margin: 0;
    letter-spacing: -0.01em;
  }

  .form__row {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 32px;
    align-items: start;
    padding: 20px 0 0;
    border-top: 1px solid var(--rule);
  }
  .form__row:first-of-type { border-top: none; }

  .form__label {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--muted);
    display: flex;
    align-items: baseline;
    gap: 14px;
    padding-top: 18px;
    transition: color 0.4s var(--ease);
  }
  .form__label .num {
    display: inline-block;
    color: var(--muted);
    transition: color 0.5s var(--ease), transform 0.5s var(--ease);
  }
  .form__row:focus-within .form__label { color: var(--ink); }
  .form__row:focus-within .form__label .num { color: var(--gold); transform: translateX(2px); }
  .form__row.is-filled .form__label .num { color: var(--gold); }

  .form__field {
    position: relative;
    padding-bottom: 14px;
  }

  .form__field input,
  .form__field textarea {
    width: 100%;
    background: transparent;
    border: none;
    padding: 14px 0;
    font-family: var(--serif);
    font-weight: 400;
    font-size: clamp(20px, 2vw, 26px);
    line-height: 1.35;
    color: var(--ink);
    outline: none;
    cursor: text;
  }
  .form__field textarea {
    font-family: var(--sans);
    font-size: clamp(16px, 1.4vw, 18px);
    font-weight: 300;
    resize: vertical;
    min-height: 88px;
    line-height: 1.55;
  }
  .form__field input::placeholder,
  .form__field textarea::placeholder {
    color: var(--muted);
    opacity: 0.55;
    font-style: italic;
  }

  /* Línea base del campo + línea dorada de focus */
  .form__field::before {
    content: "";
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 1px;
    background: var(--rule);
  }
  .form__line {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 1px;
    background: var(--gold);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.6s var(--ease-2);
  }
  .form__row:focus-within .form__line,
  .form__row.is-filled .form__line {
    transform: scaleX(1);
  }

  /* ===== Estado de error del campo =====
     Línea roja sutil + mensaje editorial bajo el campo.
     Sólo aparece tras intentar enviar / blur con valor inválido. */
  .form__row.is-error .form__line {
    background: var(--danger);
    transform: scaleX(1);
  }
  .form__row.is-error .form__label,
  .form__row.is-error .form__label .num {
    color: var(--danger);
  }
  .form__error {
    display: block;
    margin-top: 10px;
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--danger);
    opacity: 0;
    transform: translateY(-4px);
    transition:
      opacity 0.35s var(--ease),
      transform 0.35s var(--ease);
    pointer-events: none;
  }
  .form__row.is-error .form__error {
    opacity: 1;
    transform: translateY(0);
  }
  .form__error::before {
    content: "↳ ";
    color: var(--danger);
    margin-right: 4px;
  }

  /* Contador de caracteres del mensaje */
  .form__count {
    position: absolute;
    right: 0; bottom: -22px;
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--muted);
    opacity: 0;
    transition: opacity 0.4s var(--ease);
  }
  .form__row--text:focus-within .form__count,
  .form__row--text.is-filled .form__count { opacity: 1; }

  .form__foot {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 56px 0 0;
    gap: 32px;
    flex-wrap: wrap;
  }

  .form__progress {
    display: flex;
    align-items: center;
    gap: 18px;
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--muted);
  }
  .form__progress-bar {
    width: 96px;
    height: 1px;
    background: var(--rule);
    position: relative;
    overflow: hidden;
  }
  .form__progress-bar::after {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--gold);
    transform: scaleX(var(--p, 0));
    transform-origin: left;
    transition: transform 0.55s var(--ease-2);
  }

  /* Botón de envío — reutiliza el lenguaje del CTA del hero */
  .form__submit {
    display: inline-flex;
    align-items: center;
    gap: 18px;
    padding: 18px 28px 18px 32px;
    border: 1px solid var(--ink);
    background: transparent;
    font: inherit;
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--ink);
    cursor: none;
    position: relative;
    overflow: hidden;
    isolation: isolate;
    transition: color 0.5s var(--ease), opacity 0.4s var(--ease), border-color 0.4s var(--ease);
  }
  .form__submit::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--ink);
    transform: scaleX(0);
    transform-origin: right center;
    transition: transform 0.6s var(--ease-2);
    z-index: -1;
  }
  .form__submit:hover:not(:disabled),
  .form__submit:focus-visible:not(:disabled) { color: var(--paper); }
  .form__submit:hover:not(:disabled)::before,
  .form__submit:focus-visible:not(:disabled)::before {
    transform: scaleX(1);
    transform-origin: left center;
  }
  .form__submit .arrow {
    font-family: var(--serif);
    font-style: italic;
    font-size: 16px;
    letter-spacing: 0;
    transition: transform 0.45s var(--ease);
  }
  .form__submit:hover:not(:disabled) .arrow { transform: translateX(6px); }
  .form__submit:disabled {
    opacity: 0.35;
    border-color: var(--muted);
    pointer-events: none;
  }

  /* Banner inline para errores de red (fetch falla, 5xx, etc.) */
  .form__net-error {
    margin: 0 0 20px 0;
    padding: 14px 18px;
    font-family: var(--mono);
    font-size: 12px;
    letter-spacing: 0.08em;
    line-height: 1.5;
    color: var(--danger, #b04a3a);
    border: 1px solid currentColor;
    background: color-mix(in oklch, var(--danger, #b04a3a) 6%, transparent);
  }

  /* Capa de éxito — aparece superpuesta sobre el formulario */
  .form__success {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 24px;
    background: var(--paper);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.7s var(--ease);
    z-index: 5;
    text-align: center;
    padding: 40px 20px;
  }
  .form__success.is-on {
    opacity: 1;
    pointer-events: auto;
  }
  .form__success-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    border-radius: 50%;
    border: 1px solid var(--gold);
    color: var(--gold);
    transform: scale(0.6);
    opacity: 0;
    transition: transform 0.8s var(--ease-2) 0.15s, opacity 0.6s var(--ease) 0.15s;
  }
  .form__success.is-on .form__success-mark {
    transform: scale(1);
    opacity: 1;
  }
  .form__success-text {
    font-family: var(--serif);
    font-size: clamp(24px, 2.6vw, 36px);
    line-height: 1.25;
    margin: 0;
    transform: translateY(8px);
    opacity: 0;
    transition: transform 0.7s var(--ease-2) 0.3s, opacity 0.6s var(--ease) 0.3s;
  }
  .form__success.is-on .form__success-text {
    transform: translateY(0);
    opacity: 1;
  }
  .form__success em {
    color: var(--gold);
    font-style: italic;
  }

  /* Cuando el cursor está sobre un input, ocultamos el cursor personalizado */
  body.is-text .cursor-dot,
  body.is-text .cursor-ring { opacity: 0; }

  @media (max-width: 700px) {
    .form__row { grid-template-columns: 1fr; gap: 8px; }
    .form__label { padding-top: 0; }
    .form__foot { flex-direction: column; align-items: stretch; }
    .form__submit { justify-content: space-between; }
  }

  /* ============================================================
     INDICADOR DE SCROLL · columna fija derecha
     Variables que controla el JS:
       --progress  → 0..1 (scroll global)
     ============================================================ */
  .scroll-ind {
    position: fixed;
    right: clamp(18px, 2.4vw, 36px);
    top: 50%;
    /* translate3d fuerza capa propia para estabilizar la pintura */
    transform: translate3d(0, -50%, 0);
    backface-visibility: hidden;
    z-index: 40;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 22px;
    pointer-events: none;
    width: 56px;            /* ancho fijo para estabilizar el layout */
    color: var(--ink);
    opacity: 0;
    animation: scroll-ind-in 1s var(--ease) 1.4s forwards;
    will-change: transform;
  }
  @keyframes scroll-ind-in {
    to { opacity: 1; }
  }

  /* Ensō miniatura que rota con el scroll */
  .scroll-ind__enso {
    pointer-events: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--gold);
  }
  .scroll-ind__enso svg {
    display: block;
    transform: rotate(calc(var(--progress, 0) * 540deg));
    transform-origin: 50% 50%;
    transition: transform 0.25s linear;
  }

  /* Raíl vertical con los cuatro nodos */
  .scroll-ind__rail {
    position: relative;
    width: 1px;
    height: clamp(220px, 38vh, 320px);
    background: var(--rail);
  }
  .scroll-ind__fill {
    position: absolute;
    top: 0; left: 0;
    width: 100%;
    height: 100%;
    background: var(--gold);
    transform-origin: top;
    transform: scaleY(var(--progress, 0));
    transition: transform 0.18s linear;
  }

  /* Cada nodo de sección */
  .scroll-ind__node {
    position: absolute;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 26px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: auto;
    text-decoration: none;
  }
  .scroll-ind__node[data-i="0"] { top: 0%; }
  .scroll-ind__node[data-i="1"] { top: 25%; }
  .scroll-ind__node[data-i="2"] { top: 50%; }
  .scroll-ind__node[data-i="3"] { top: 75%; }
  .scroll-ind__node[data-i="4"] { top: 100%; }

  .scroll-ind__node .dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--ink);
    border: 1px solid var(--ink);
    transition:
      background 0.45s var(--ease),
      border-color 0.45s var(--ease),
      transform 0.45s var(--ease-2),
      box-shadow 0.45s var(--ease);
  }

  /* Etiqueta lateral del nodo (mono) — aparece al hover y en activo */
  .scroll-ind__node .lbl {
    position: absolute;
    right: 24px;
    top: 50%;
    transform: translate(6px, -50%);
    font-family: var(--mono);
    font-style: normal;
    font-size: 10px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    white-space: nowrap;
    opacity: 0;
    transition:
      opacity 0.4s var(--ease),
      transform 0.5s var(--ease-2);
    color: var(--ink);
  }
  .scroll-ind__node .lbl .num { color: var(--gold); margin-right: 8px; }

  .scroll-ind__node:hover .dot,
  .scroll-ind__node.is-active .dot {
    background: var(--gold);
    border-color: var(--gold);
    transform: scale(1.5);
    box-shadow: 0 0 0 4px rgba(201, 169, 110, 0.18);
  }
  .scroll-ind__node:hover .lbl,
  .scroll-ind__node.is-active .lbl {
    opacity: 1;
    transform: translate(0, -50%);
  }

  /* Porcentaje numérico bajo el raíl */
  .scroll-ind__pct {
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.18em;
    color: var(--ink);
    display: inline-flex;
    align-items: baseline;
    gap: 1px;
    font-variant-numeric: tabular-nums;
  }
  .scroll-ind__pct i {
    font-style: normal;
    color: var(--gold);
    margin-left: 2px;
  }

  @media (max-width: 900px) {
    .scroll-ind { display: none; }
  }

  /* ============================================================
     FOOTER · cierre editorial con ensō y sello (hanko)
     ============================================================ */
  .footer {
    padding: clamp(80px, 12vw, 140px) 0 56px;
    display: flex;
    flex-direction: column;
    gap: clamp(40px, 6vw, 80px);
    border-top: 1px solid var(--rule);
  }

  /* Banda decorativa: regla · ensō · regla */
  .footer__band {
    display: flex;
    align-items: center;
    gap: clamp(20px, 3vw, 40px);
  }
  .footer__rule {
    flex: 1;
    height: 1px;
    background: var(--rule);
  }
  .footer__mark {
    color: var(--gold);
    display: flex;
    align-items: center;
    justify-content: center;
    /* Giro perpétuo muy lento, como el ensō del hero */
    animation: footer-spin 32s linear infinite;
  }
  @keyframes footer-spin {
    to { transform: rotate(360deg); }
  }
  .footer__mark svg { display: block; }

  /* Despedida grande + sello */
  .footer__sign {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 32px;
  }
  .footer__bye {
    font-family: var(--serif);
    font-weight: 300;
    font-size: clamp(48px, 9vw, 140px);
    line-height: 0.92;
    margin: 0;
    letter-spacing: -0.02em;
  }
  .footer__bye em {
    font-style: italic;
    color: var(--gold);
  }

  /* Sello tipo hanko — círculo dorado con monograma y año */
  .footer__seal {
    width: clamp(96px, 12vw, 128px);
    height: clamp(96px, 12vw, 128px);
    border: 1px solid var(--gold);
    border-radius: 50%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    color: var(--gold);
    position: relative;
    transition: transform 0.6s var(--ease);
  }
  .footer__seal:hover { transform: rotate(-8deg); }
  /* Punto central diminuto, detalle de hanko */
  .footer__seal::before {
    content: "";
    position: absolute;
    inset: 6px;
    border: 1px solid currentColor;
    border-radius: 50%;
    opacity: 0.18;
  }
  .footer__seal-mono {
    font-family: var(--serif);
    font-style: italic;
    font-size: clamp(28px, 3.6vw, 40px);
    line-height: 1;
    z-index: 1;
  }
  .footer__seal-year {
    font-family: var(--mono);
    font-size: 9px;
    letter-spacing: 0.3em;
    z-index: 1;
  }

  /* Créditos */
  .footer__credits {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--muted);
    padding-top: clamp(20px, 3vw, 32px);
    border-top: 1px solid var(--rule);
    gap: 24px;
    flex-wrap: wrap;
  }

  @media (max-width: 700px) {
    .footer__sign { grid-template-columns: 1fr; gap: 28px; }
    .footer__bye { font-size: clamp(54px, 14vw, 96px); }
  }

  /* ===== Responsive ===== */
  @media (max-width: 880px) {
    .nav__links { gap: 20px; }
    .nav__links a:not(:last-child) { display: none; }
    .about { grid-template-columns: 1fr; }
    .about__copy { column-count: 1; }
    .projects { grid-template-columns: 1fr; }
    .project--1, .project--2, .project--3 {
      grid-column: 1 / -1;
      margin-top: 0;
    }
    .contact__inner { grid-template-columns: 1fr; gap: 40px; }
    .section { padding: 100px 0; }
    .section__head { margin-bottom: 48px; }
  }

  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.01ms !important;
      transition-duration: 0.01ms !important;
    }
  }

  /* ============================================================
     LOADER — pantalla de carga editorial
     Sigue exactamente la misma lógica visual: serif itálico
     enorme, dorado como acento, mono para etiquetas, regla
     fina horizontal que avanza con el progreso.
     ============================================================ */
  .loader {
    position: fixed;
    inset: 0;
    z-index: 200;
    background: var(--paper);
    color: var(--ink);
    display: grid;
    grid-template-rows: auto 1fr auto;
    padding: clamp(28px, 5vw, 80px);
    will-change: transform;
    /* Salida tipo telón hacia arriba */
    transition: transform 1.1s var(--ease-2);
  }
  .loader.is-done {
    transform: translateY(-100%);
  }
  /* Bloqueamos el scroll mientras carga */
  body.is-loading { overflow: hidden; height: 100vh; }
  /* Ocultamos el contenido principal hasta el final de la carga */
  body.is-loading .nav,
  body.is-loading .shell { opacity: 0; }
  .nav, .shell { transition: opacity 0.6s var(--ease) 0.2s; }

  .loader__top,
  .loader__bot {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--muted);
  }
  .loader__top .gold { color: var(--gold); }
  .loader__top .dot {
    display: inline-block;
    width: 6px; height: 6px;
    border-radius: 50%;
    background: var(--gold);
    margin-right: 10px;
    vertical-align: middle;
    box-shadow: 0 0 0 4px rgba(201, 169, 110, 0.18);
    animation: pulse 1.4s var(--ease) infinite;
  }
  @keyframes pulse {
    0%, 100% { box-shadow: 0 0 0 4px rgba(201, 169, 110, 0.18); }
    50%      { box-shadow: 0 0 0 8px rgba(201, 169, 110, 0.05); }
  }

  .loader__center {
    display: grid;
    grid-template-rows: 1fr auto 1fr;
    align-items: center;
  }
  .loader__word {
    grid-row: 2;
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: end;
    gap: 32px;
    padding-bottom: 24px;
    border-bottom: 1px solid var(--rule);
    position: relative;
  }
  /* Regla de progreso superpuesta sobre el borde inferior */
  .loader__word::after {
    content: "";
    position: absolute;
    left: 0; bottom: -1px;
    height: 1px;
    width: var(--p, 0%);
    background: var(--ink);
    transition: width 0.18s linear;
  }
  .loader__title {
    font-family: var(--serif);
    font-style: italic;
    font-weight: 300;
    font-size: clamp(72px, 14vw, 220px);
    line-height: 0.9;
    letter-spacing: -0.02em;
    margin: 0;
  }
  .loader__title .amp { color: var(--gold); font-style: italic; }
  .loader__count {
    font-family: var(--serif);
    font-style: italic;
    font-weight: 300;
    font-size: clamp(40px, 7vw, 96px);
    line-height: 1;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
  }
  .loader__count .pct {
    font-family: var(--mono);
    font-style: normal;
    font-size: 14px;
    letter-spacing: 0.18em;
    color: var(--muted);
    transform: translateY(-0.6em);
  }

  /* Lista de tareas que se van "completando" */
  .loader__tasks {
    grid-row: 3;
    align-self: end;
    list-style: none;
    margin: 32px 0 0;
    padding: 0;
    display: grid;
    gap: 6px;
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--muted);
    max-width: 380px;
  }
  .loader__tasks li {
    display: grid;
    grid-template-columns: 24px 1fr auto;
    gap: 12px;
    align-items: center;
    opacity: 0.4;
    transition: opacity 0.5s var(--ease), color 0.5s var(--ease);
  }
  .loader__tasks li.is-done {
    opacity: 1;
    color: var(--ink);
  }
  .loader__tasks li .mark { color: var(--gold); }
  .loader__tasks li.is-done .state::before { content: "\2713  Listo"; }
  .loader__tasks li .state::before { content: "En curso"; }

  @media (max-width: 700px) {
    .loader__word { grid-template-columns: 1fr; gap: 16px; }
    .loader__tasks { max-width: 100%; }
  }