/* =============================================================
   Eduardo Santamaria — Portafolio
   Rejilla estricta, línea de 1px como elemento de diseño,
   papel claro, tinta casi negra y un único color señal.
   ============================================================= */

/* =============================================================
   1. Tokens
   ============================================================= */
:root {
  color-scheme: light;

  --bg:        #f2f1ec;
  --paper:     #ffffff;
  --ink:       #0b0b0b;
  --ink-2:     #56564f;
  --ink-3:     #97968e;
  --accent:    #ff3b19;

  --line:      rgba(11, 11, 11, .15);
  --line-2:    rgba(11, 11, 11, .34);

  /* Muchas bandas invierten el bloque: fondo --ink, texto --bg. Como esos dos
     giran con el tema, la inversión se mantiene sola; lo único que hay que
     declarar aparte es el gris apagado que va *encima* de esa banda. */
  --inv-mute:  rgba(242, 241, 236, .55);
  --inv-mute-2:rgba(242, 241, 236, .35);
  --inv-velo:  rgba(11, 11, 11, .74);   /* respaldo de un texto sobre foto */

  --plate:     #e4e3dd;                 /* fondo de una celda con fotografía */
  --gris:      0;                       /* 1 = las piezas se ven en blanco y negro */

  --sans:  "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --disp:  "Archivo", "Inter", system-ui, sans-serif;
  --mono:  "JetBrains Mono", ui-monospace, "SFMono-Regular", Consolas, monospace;

  --ease-out:  cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in:   cubic-bezier(0.7, 0, 0.84, 0);
  --ease-soft: cubic-bezier(0.25, 0.46, 0.45, 0.94);

  --gutter: 1.25rem;
  --topbar: 52px;
}

/* -------------------------------------------------------------
   Tema oscuro. No es un modo del sitio: es un tono que se le pone
   a una sección. La página alterna papel y negro al bajar, y el
   contraste entre ambos es la mitad del efecto.
   ------------------------------------------------------------- */
.tema-oscuro {
  color-scheme: dark;

  --bg:        #080808;
  --paper:     #121212;
  --ink:       #f2f1ec;
  --ink-2:     #a3a29a;
  --ink-3:     #6d6c66;

  --line:      rgba(242, 241, 236, .13);
  --line-2:    rgba(242, 241, 236, .26);

  --inv-mute:  rgba(11, 11, 11, .55);
  --inv-mute-2:rgba(11, 11, 11, .38);
  --inv-velo:  rgba(242, 241, 236, .86);

  --plate:     #131313;
  --gris:      1;
}

/* OJO: esta clase SÓLO cambia los tokens de color. No pinta fondo.
   Lo pintaba, y era un fallo serio: el guion se la pone también a capas
   que cubren toda la pantalla —la retícula del cursor es `position:fixed;
   inset:0`—, así que al entrar el ratón en el archivo esa capa se
   encendía con fondo negro opaco y tapaba la página entera. Sólo se veía
   el cursor. Quien pinta el fondo es cada sección, en la regla de abajo. */

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

html {
  -webkit-text-size-adjust: 100%;
  tab-size: 2;
  overflow-x: clip;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--topbar) + 8px);
}

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
  overscroll-behavior-y: none;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
p { text-wrap: pretty; }
ul, ol { list-style: none; padding: 0; }

button {
  font: inherit; color: inherit; cursor: pointer;
  border: 0; background: none; padding: 0;
  text-align: left; border-radius: 0;
}

h1, h2, h3, h4 { font-family: var(--disp); line-height: 1.02; letter-spacing: -0.03em; font-weight: 800; }

::selection { background: var(--accent); color: var(--paper); }

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

/* Nada de esquinas redondeadas en todo el documento: es parte del estilo. */
* { border-radius: 0; }

/* =============================================================
   3. Utilidades
   ============================================================= */
.skip-link {
  position: fixed; top: -100px; left: 1rem; z-index: 9999;
  padding: .6rem 1rem; background: var(--ink); color: var(--paper);
  font-family: var(--mono); font-size: .75rem;
}
.skip-link:focus { top: 1rem; }

.tag {
  display: inline-flex; align-items: center; gap: .5em;
  font-family: var(--mono); font-size: .7rem; font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink-2);
}
.tag i { font-style: normal; color: var(--ink-3); }

/* Línea horizontal que se dibuja al entrar en pantalla */
.rule { height: 1px; width: 100%; background: var(--line-2); transform-origin: 0 50%; }
.js .rule { transform: scaleX(0); }
.js .rule.is-drawn { transform: scaleX(1); transition: transform 1.1s var(--ease-out); }

/* =============================================================
   4. Splash
   ============================================================= */
.splash {
  position: fixed; inset: 0; z-index: 900;
  background: var(--ink); color: var(--bg);
  display: grid; place-items: center;
  /* Red de seguridad: se va sola a los 4,5 s aunque falle el guion. */
  animation: splashSafety .01s 4.5s forwards;
}
@keyframes splashSafety { to { opacity: 0; pointer-events: none; visibility: hidden; } }
/* Sin JavaScript no hay nada que cargar: fuera la pantalla de entrada. */
html:not(.js) .splash { display: none; }

.splash.is-out {
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .6s var(--ease-out), visibility 0s .6s;
}
.splash-inner {
  display: flex; align-items: baseline; gap: 1.2rem;
  font-family: var(--mono); text-transform: uppercase;
}
.splash-label { font-size: .7rem; letter-spacing: .3em; opacity: .55; }
.splash-num { font-size: clamp(3rem, 16vw, 9rem); font-weight: 700; letter-spacing: -.04em; line-height: 1; }
.splash-bar {
  position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
  background: var(--accent); transform: scaleX(0); transform-origin: 0 50%;
}

/* =============================================================
   5. Retícula del cursor + HUD
   ============================================================= */
.crosshair { position: fixed; inset: 0; z-index: 300; pointer-events: none; opacity: 0; transition: opacity .3s var(--ease-out); }
.crosshair.is-on { opacity: 1; }
.crosshair-x, .crosshair-y { position: absolute; background: var(--line-2); will-change: transform; }
.crosshair-x { left: 0; top: 0; width: 100%; height: 1px; }
.crosshair-y { top: 0; left: 0; width: 1px; height: 100%; }

/* El indicador sólo se enciende sobre el archivo: así nunca se cruza
   con un texto que estés leyendo en otra parte de la página. */
.hud {
  position: fixed; left: 0; bottom: 0; z-index: 310;
  display: none; pointer-events: none;
  opacity: 0; transform: translateY(6px);
  transition: opacity .35s var(--ease-out), transform .35s var(--ease-out);
  font-family: var(--mono); font-size: .625rem; letter-spacing: .1em;
}
.hud.is-on { opacity: 1; transform: none; }
.hud-cell {
  display: block; padding: .35rem .6rem;
  background: var(--ink); color: var(--bg);
}
.hud-cell + .hud-cell { border-top: 1px solid var(--inv-mute-2); }

@media (hover: hover) and (pointer: fine) and (min-width: 960px) {
  .hud { display: block; }
}

/* =============================================================
   6. Cabecera
   ============================================================= */
.topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 400;
  height: var(--topbar);
  display: flex; align-items: center; justify-content: center;
  gap: 1rem; padding: 0 var(--gutter);
  /* Pinta su propio fondo y su propio texto: ya no los hereda de
     .tema-oscuro, que ahora sólo cambia los tokens. */
  background: var(--bg);
  color: var(--ink);
  border-bottom: 1px solid var(--line-2);
}

/* Las capas que cubren toda la pantalla nunca llevan color de fondo, pase
   lo que pase con los temas. Es la red que evita que vuelva a ocurrir.
   Se anula el COLOR, no el atajo `background`: el grano necesita conservar
   su imagen de fondo. */
.crosshair, .hud, .grano { background-color: transparent !important; }

.topbar-nav { display: flex; justify-content: center; gap: 1.1rem; }
.topbar-nav a {
  position: relative;
  font-family: var(--mono); font-size: .6rem; letter-spacing: .06em;
  text-transform: uppercase; padding-bottom: 2px; white-space: nowrap;
}
.topbar-nav a i {
  font-style: normal; color: var(--ink-3); margin-right: .35em;
}
.topbar-nav a::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 100%; height: 1px; background: var(--ink);
  transform: scaleX(0); transform-origin: 100% 50%;
  transition: transform .45s var(--ease-out);
}
.topbar-nav a:hover::after { transform: scaleX(1); transform-origin: 0 50%; }
.topbar-nav a i { display: none; }

@media (min-width: 720px) {
  .topbar-nav { gap: 2.2rem; }
  .topbar-nav a { font-size: .7rem; letter-spacing: .1em; }
  .topbar-nav a i { display: inline; }
}

/* =============================================================
   7. Hero
   ============================================================= */
.hero {
  position: relative;
  /* Aísla la mezcla: el retrato se funde con el fondo de esta sección
     y con nada de fuera de ella. */
  isolation: isolate;
  overflow: hidden;
  padding: calc(var(--topbar) + 3.5rem) var(--gutter) 2.5rem;
  min-height: 100svh;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 2rem;
}
.hero .rule-top { margin-bottom: auto; }

/* --- El retrato ------------------------------------------------------
   La fotografía está sobre negro puro. Con mix-blend-mode: screen el
   negro desaparece contra el fondo de la sección: no hace falta recorte
   y el pelo queda perfecto, que es donde siempre se nota el recorte malo.
   OJO: ni .hero-fondo ni .hero-retrato pueden llevar transform, filter,
   opacity ni z-index. Cualquiera de esos crea un contexto de apilado y
   la mezcla dejaría de ver el fondo de la sección. El movimiento va
   siempre sobre la propia <img>. */
.hero-fondo { position: absolute; inset: 0; pointer-events: none; }

/* En pantalla estrecha la figura manda arriba y el texto cae debajo;
   en ancha se va al lado derecho y el titular la cruza. */
.hero-retrato {
  position: absolute; top: 0; right: 0; left: 0;
  height: 64%;
  overflow: hidden;
}
.hero-retrato img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 20%;
  mix-blend-mode: screen;
  will-change: transform;
}

/* Oscurece la parte baja (y en ancho también el borde izquierdo) para que
   el titular siempre caiga sobre negro, se cruce o no con la figura. */
.hero-velo {
  position: absolute; inset: 0;
  background: linear-gradient(to top, #080808 14%, rgba(8, 8, 8, .74) 42%, rgba(8, 8, 8, 0) 80%);
}

@media (min-width: 900px) {
  .hero-retrato {
    left: auto; bottom: 0; height: auto;
    width: min(62vw, 720px);
  }
  .hero-retrato img { object-position: 50% 26%; }
  .hero-velo {
    background:
      linear-gradient(to top,   #080808 6%, rgba(8, 8, 8, .74) 30%, rgba(8, 8, 8, 0) 64%),
      linear-gradient(to right, #080808 10%, rgba(8, 8, 8, 0) 52%);
  }
}

.hero-cuerpo {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; gap: 2rem;
}

.hero-kicker {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  font-family: var(--mono); font-size: .7rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-2);
  padding-top: 1.5rem;
}
.hero-kicker i { font-style: normal; color: var(--ink-3); }

@media (min-width: 900px) {
  /* Aire abajo, que el titular no toque el borde. */
  .hero { padding-bottom: 4.5rem; }
}

.hero-title {
  font-family: var(--disp); font-weight: 900; text-transform: uppercase;
  /* Medida calculada para que "SANTAMARÍA" quepa siempre en una línea,
     desde un móvil de 320 px hasta una pantalla grande. */
  font-size: clamp(2rem, 9.8vw, 9.5rem);
  line-height: .88; letter-spacing: -.045em;
}
/* Cada línea es su propia ventana: las letras entran desde abajo
   sin asomarse nunca al párrafo siguiente. */
.hero-line {
  display: block; overflow: hidden;
  padding-bottom: .07em; margin-bottom: -.07em;
}

.hero-body {
  display: grid; gap: 2rem;
  border-top: 1px solid var(--line-2); padding-top: 1.5rem;
}
.hero-deck {
  font-size: clamp(1rem, 2.4vw, 1.2rem); line-height: 1.5;
  max-width: 46ch; color: var(--ink-2);
}

.hero-stats { display: flex; flex-wrap: wrap; gap: 1.75rem 2.5rem; }
.hero-stats li { display: flex; flex-direction: column; gap: .1rem; }
.hero-stats b {
  font-family: var(--disp); font-weight: 800; font-size: clamp(2rem, 5vw, 3rem);
  line-height: 1; letter-spacing: -.04em; font-variant-numeric: tabular-nums;
}
.hero-stats span {
  font-family: var(--mono); font-size: .625rem; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink-3);
}

.hero-foot { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1rem; }
.hero-loc {
  font-family: var(--mono); font-size: .65rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-3); margin-left: auto;
}
.hero-loc i { font-style: normal; }

.btn {
  display: inline-flex; align-items: center; gap: .8em;
  padding: .85rem 1.3rem;
  background: var(--ink); color: var(--bg);
  font-family: var(--mono); font-size: .72rem; font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase;
  border: 1px solid var(--ink);
  transition: background .3s var(--ease-out), color .3s var(--ease-out);
}
.btn i { font-style: normal; transition: transform .4s var(--ease-out); }
.btn:hover { background: var(--accent); color: var(--paper); border-color: var(--accent); }
.btn:hover i { transform: translate(2px, 2px); }

.btn-ghost { background: none; color: var(--ink); }
.btn-ghost:hover { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.btn-ghost:hover i { transform: translateX(4px); }

/* =============================================================
   8. Marquesina
   ============================================================= */
.marquee {
  /* Flex sin envoltura: el original y su copia van siempre en la misma fila. */
  display: flex; flex-wrap: nowrap; overflow: hidden;
  border-top: 1px solid var(--line-2);
  border-bottom: 1px solid var(--line-2);
  background: var(--ink); color: var(--bg);
  padding: .8rem 0;
}
.marquee-track {
  flex: none;
  display: inline-flex; align-items: center; gap: 2.5rem;
  white-space: nowrap; will-change: transform;
  padding-right: 2.5rem;
}
.marquee-track span {
  font-family: var(--disp); font-weight: 700; text-transform: uppercase;
  font-size: clamp(1.1rem, 3.2vw, 2rem); letter-spacing: -.02em;
}
.marquee-track .marquee-sep { color: var(--accent); font-size: 1em; }

/* =============================================================
   9. Bloques
   ============================================================= */
.block {
  padding: 4rem var(--gutter) 4.5rem;
  border-top: 1px solid var(--line-2);
}
.block-head { display: grid; gap: 1.1rem; margin-bottom: 2.5rem; }
.block-title {
  font-size: clamp(1.75rem, 5.4vw, 3.6rem);
  line-height: 1.02; letter-spacing: -.035em; max-width: 20ch;
  text-wrap: balance;
}
.block-sub {
  font-family: var(--mono); font-size: .75rem; letter-spacing: .04em;
  color: var(--ink-2); max-width: 52ch;
}

.block-cols { display: grid; gap: 1.25rem; max-width: 70ch; color: var(--ink-2); }

/* Reveal universal — sólo se esconde si hay JavaScript para volver a mostrarlo. */
.js [data-reveal] {
  opacity: 0; transform: translateY(34px);
  transition: opacity .85s var(--ease-soft), transform .85s var(--ease-soft);
}
.js [data-reveal].is-revealed { opacity: 1; transform: none; }
/* Defensa: si un elemento lleva reveal Y split, que nunca quede invisible. */
.js [data-reveal][data-split] { opacity: 1; transform: none; }

/* Texto partido */
.split-word, .split-char { display: inline-block; will-change: transform; }

/* =============================================================
   10. Pilares y pasos
   ============================================================= */
.pillars { display: grid; gap: 1px; background: var(--line-2); margin-top: 3rem; }
.pillars li { background: var(--bg); padding: 1.75rem 0 1.75rem; }
.pillar-num {
  font-family: var(--mono); font-size: .7rem; letter-spacing: .14em;
  color: var(--accent); display: block; margin-bottom: .75rem;
}
.pillars h3 { font-size: 1.15rem; font-weight: 700; margin-bottom: .5rem; letter-spacing: -.02em; }
.pillars p { color: var(--ink-2); font-size: .95rem; max-width: 42ch; }

.steps { display: grid; gap: 1px; background: var(--line-2); }
.steps li {
  background: var(--bg); padding: 1.5rem 0;
  display: grid; grid-template-columns: 2.75rem 1fr; gap: 0 1rem; align-items: start;
}
.step-num {
  font-family: var(--mono); font-size: .78rem; font-weight: 700;
  letter-spacing: .06em; color: var(--accent); padding-top: .25rem;
}
.steps h3 { font-size: clamp(1.25rem, 3.6vw, 1.9rem); font-weight: 800; margin-bottom: .4rem; }
.steps p { color: var(--ink-2); font-size: .95rem; max-width: 54ch; }
.step-meta {
  grid-column: 2; margin-top: .6rem;
  font-family: var(--mono); font-size: .65rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-3);
}

/* =============================================================
   11. Oficio
   ============================================================= */
.specs { display: grid; gap: 1px; background: var(--line-2); }
.spec { background: var(--bg); padding: 1.6rem 0; }
.spec-key {
  display: block; margin-bottom: 1rem;
  font-family: var(--mono); font-size: .65rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-3);
}
.spec-list { display: grid; gap: .5rem; }
.spec-list li {
  font-family: var(--disp); font-weight: 600; font-size: 1.05rem; letter-spacing: -.015em;
}
/* Viñeta cuadrada, del mismo lenguaje que la retícula del sitio. Se la
   ponen las listas normales; las de herramientas ya llevan monograma y
   las de trayecto llevan su fecha delante. */
.spec-list:not(.spec-list-time) li { display: flex; align-items: baseline; gap: .7em; }
.spec-list:not(.spec-list-time) li::before {
  content: ""; flex: none;
  width: 5px; height: 5px; margin-top: .1em;
  background: var(--accent);
  transform: translateY(-.15em);
}
.spec-herramientas .spec-list li::before { display: none; }
.spec-list-time li { display: grid; gap: .1rem; }
.spec-list-time i {
  font-family: var(--mono); font-style: normal; font-weight: 400;
  font-size: .65rem; letter-spacing: .1em; color: var(--accent);
}

/* =============================================================
   12. Filtros
   ============================================================= */
.filtros {
  display: flex; flex-wrap: wrap; gap: 1px;
  background: var(--line-2); border: 1px solid var(--line-2);
  margin-bottom: 1px;
}
.filtro {
  flex: 1 1 auto;
  display: inline-flex; align-items: center; justify-content: space-between; gap: .7rem;
  padding: .7rem .85rem; background: var(--bg);
  font-family: var(--mono); font-size: .66rem; letter-spacing: .08em;
  text-transform: uppercase; white-space: nowrap;
  transition: background .25s var(--ease-out), color .25s var(--ease-out);
}
.filtro i { font-style: normal; color: var(--ink-3); font-size: .6rem; transition: color .25s var(--ease-out); }
.filtro:hover { background: var(--paper); }
.filtro.is-on { background: var(--ink); color: var(--bg); }
.filtro.is-on i { color: var(--accent); }

/* =============================================================
   12b. ARCHIVO — el campo espacial
   ============================================================= */
/* Con guion, el archivo espacial ES la vista del portafolio. La rejilla
   plana y sus filtros siguen en el HTML como reserva para quien lo tenga
   desactivado, y entonces son lo único que se ve. */
.js .archivo-vivo .reserva { display: none; }
html:not(.js) .arch-riel { display: none; }

/* El carril mide el recorrido: cuánto scroll se gasta atravesando el
   archivo antes de que la página continúe. */
.arch-riel {
  position: relative;
  height: 300vh;
  margin: 2.5rem calc(var(--gutter) * -1) 2rem;
}

/* La escena se queda pegada mientras dura el carril. Es sticky y no un
   pin de ScrollTrigger a propósito: sticky no envuelve el elemento en
   contenedores nuevos ni pelea con el scroll de inercia. */
.arch-escena {
  position: sticky; top: 0;
  height: 100svh; min-height: 520px;
  overflow: hidden;
  background: var(--bg);
  cursor: grab;
  touch-action: pan-y;      /* el gesto horizontal lo lleva el guion */
}
.arch-escena.is-arrastrando { cursor: grabbing; }
.arch-escena.is-arrastrando .obj { pointer-events: none; }

.arch-campo { position: absolute; inset: 0; }

/* Cada proyecto es un objeto suelto en el plano. Lleva su medida real en
   píxeles de mundo; la escala de profundidad la pone el guion. */
.obj {
  position: absolute; top: 0; left: 0;
  display: none;                 /* lo enciende el guion al entrar en cuadro */
  transform-origin: 0 0;
  will-change: transform;
  padding: 0; border: 0; background: var(--plate);
  overflow: hidden;
  transition: opacity .45s var(--ease-out);
}
.obj img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center top;
  /* El blanco y negro no es un efecto: es lo que hace que 138 imágenes de
     origen dispar se lean como una sola composición. El color vuelve en
     la pieza que estás mirando. */
  filter: grayscale(1) contrast(1.05);
  transition: filter .55s var(--ease-out), transform .7s var(--ease-out);
}
.obj::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(242, 241, 236, .16);
  transition: box-shadow .35s var(--ease-out);
}

/* Un logotipo lleva transparencia y es tinta oscura: sobre negro
   desaparecería. Conserva su lámina de papel y su aire. */
.obj[data-modo="marca"] { background: #f2f1ec; }
.obj[data-modo="marca"] img { object-fit: contain; padding: 11%; }

/* Al mirar una pieza, el archivo se retira. */
/* OJO: esto va con :has() y no con una clase puesta por el guion. Con
   clase, si el objeto que estabas mirando se salía de cuadro el navegador
   no llegaba a lanzar el "pointerout", la clase se quedaba pegada y TODO
   el archivo se quedaba al 30 % —que sobre negro es indistinguible de la
   nada—. Con :has() el estado lo lleva el navegador y no puede atascarse. */
.arch-campo:has(.obj:hover) .obj { opacity: .45; }
.arch-campo:has(.obj:hover) .obj:hover { opacity: 1; }
.obj:hover img, .obj:focus-visible img { filter: none; transform: scale(1.03); }
.obj:hover::after, .obj:focus-visible::after { box-shadow: inset 0 0 0 1px var(--accent); }

/* --- La consola: familias, pieza centrada y recuento --------------------
   Va dentro de la escena, sobre un degradado, para que el archivo llegue
   hasta el borde inferior y no quede recortado por una barra. */
.arch-hud {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 900;
  display: flex; flex-direction: column; align-items: center; gap: .85rem;
  padding: 3.5rem var(--gutter) 1.4rem;
  background: linear-gradient(to top, var(--bg) 26%, rgba(8, 8, 8, .78) 58%, transparent);
  pointer-events: none;          /* el archivo se arrastra a través del HUD */
}
.arch-hud > * { pointer-events: auto; }

.arch-familias { display: flex; flex-wrap: wrap; justify-content: center; gap: .4rem; }
.fam {
  display: inline-flex; align-items: baseline; gap: .5rem;
  padding: .45rem .85rem;
  border: 1px solid var(--line-2);
  font-family: var(--mono); font-size: .62rem; letter-spacing: .12em;
  text-transform: uppercase; white-space: nowrap;
  transition: background .3s var(--ease-out), color .3s var(--ease-out), border-color .3s var(--ease-out);
}
.fam i { font-style: normal; font-size: .55rem; color: var(--ink-3); transition: color .3s var(--ease-out); }
.fam:hover { border-color: var(--ink); }
.fam.is-on { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.fam.is-on i { color: var(--accent); }

.arch-pie { text-align: center; }
.arch-pie b {
  display: block;
  font-family: var(--disp); font-weight: 800; text-transform: uppercase;
  font-size: clamp(1.1rem, 2.8vw, 2.2rem); letter-spacing: -.035em; line-height: 1;
}
.arch-pie span {
  font-family: var(--mono); font-size: .6rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-3);
}
.arch-pie i, .arch-pie em { font-style: normal; }
.arch-pie i:not(:empty)::after { content: " · "; }

.arch-cuenta {
  font-family: var(--mono); font-size: .55rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-3);
}
.arch-cuenta i { font-style: normal; color: var(--accent); }

@media (max-width: 719px) {
  .arch-riel { height: 240vh; }
  .arch-hud { padding-top: 2.5rem; gap: .6rem; }
  .fam { padding: .38rem .6rem; font-size: .56rem; letter-spacing: .08em; }
}

/* =============================================================
   13. La rejilla de marcas
   ============================================================= */
.grid-wrap { border: 1px solid var(--line-2); }
.grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px; background: var(--line);
}

/* Banda que abre cada disciplina cuando el filtro está en "Todo".
   Ocupa la fila entera de la rejilla y da el ritmo de lectura. */
.grid-cab {
  grid-column: 1 / -1;
  display: flex; align-items: baseline; gap: .9rem;
  padding: .9rem 1rem;
  background: var(--ink); color: var(--bg);
}
.grid-cab-num {
  font-family: var(--mono); font-size: .6rem; letter-spacing: .16em;
  color: var(--accent); flex: none;
}
.grid-cab-tit {
  font-family: var(--disp); font-weight: 800; text-transform: uppercase;
  font-size: clamp(1rem, 3.2vw, 1.9rem); letter-spacing: -.03em; line-height: 1;
}
.grid-cab-n {
  margin-left: auto; flex: none;
  font-family: var(--mono); font-size: .58rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--inv-mute);
  white-space: nowrap;
}
.grid-cab.is-hidden { display: none; }

.mark {
  position: relative; display: block; overflow: hidden;
  background: var(--paper);
  aspect-ratio: 4 / 3;
  transition: background .3s var(--ease-out);
}
.mark::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  box-shadow: inset 0 0 0 1px var(--ink);
  opacity: 0; transition: opacity .3s var(--ease-out);
}
.mark:hover::after, .mark:focus-visible::after { opacity: 1; }

.mark-idx {
  position: absolute; top: .55rem; left: .65rem; z-index: 2;
  font-family: var(--mono); font-size: .58rem; letter-spacing: .1em;
  color: var(--ink-3); transition: color .3s var(--ease-out);
}
.mark:hover .mark-idx { color: var(--accent); }

/* Cuántas piezas tiene el proyecto */
.mark-n {
  position: absolute; top: .55rem; right: .65rem; z-index: 2;
  font-family: var(--mono); font-size: .55rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3);
}

.mark-plate {
  position: absolute; inset: 17% 11%;
  display: block;
  transition: transform .5s var(--ease-out);
}
.mark[data-modo="marca"]:hover .mark-plate { transform: translateY(-7%); }

/* --- Piezas que no son logotipos: la imagen llena la celda ---
   El fondo es un gris de papel, no tinta: mientras cargan, una rejilla
   de huecos negros pesa demasiado. */
.mark[data-modo="pieza"] { background: var(--plate); }
.mark[data-modo="pieza"] .mark-plate { inset: 0; }
/* Encuadre por arriba: en una maqueta de web alta interesa la cabecera,
   no una franja del medio. */
.mark[data-modo="pieza"] .mark-plate img { object-fit: cover; object-position: center top; }
.mark[data-modo="pieza"]:hover .mark-plate img { transform: scale(1.05); }
/* Sobre una fotografía el texto necesita respaldo */
.mark[data-modo="pieza"] .mark-idx,
.mark[data-modo="pieza"] .mark-n {
  padding: .18rem .38rem;
  background: var(--inv-velo); color: var(--bg);
}
.mark[data-modo="pieza"] .mark-n { color: var(--bg); opacity: .82; }
.mark[data-modo="pieza"]:hover .mark-idx { color: var(--bg); background: var(--accent); }
/* La caja ocupa el hueco completo y es object-fit quien encaja el dibujo:
   así ningún logotipo alto se sale de su celda. */
.mark-plate img {
  width: 100%; height: 100%;
  object-fit: contain; object-position: center;
  transition: transform .55s var(--ease-out);
}
.mark:hover .mark-plate img { transform: scale(1.055); }

/* Una sola línea, para tapar lo mínimo del logotipo. */
.mark-meta {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 3;
  display: flex; align-items: baseline; gap: .6rem;
  padding: .42rem .6rem .48rem;
  background: var(--ink); color: var(--bg);
  border-top: 3px solid var(--brand, var(--accent));
  transform: translateY(101%);
  transition: transform .42s var(--ease-out);
}
.mark:hover .mark-meta, .mark:focus-visible .mark-meta { transform: none; }

.mark-name {
  flex: 1 1 auto; min-width: 0;
  font-family: var(--disp); font-weight: 700;
  font-size: .78rem; letter-spacing: -.015em; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mark-tag {
  flex: none;
  font-family: var(--mono); font-size: .55rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--inv-mute);
  white-space: nowrap;
}
.mark-tag i { display: none; font-style: normal; }

/* Filtrado */
.mark.is-hidden { display: none; }
.grid-empty {
  padding: 3rem 1rem; text-align: center; background: var(--paper);
  font-family: var(--mono); font-size: .75rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3);
}

.grid-note {
  margin-top: 1.25rem;
  font-family: var(--mono); font-size: .625rem; line-height: 1.7;
  letter-spacing: .04em; color: var(--ink-3); max-width: 62ch;
}

/* =============================================================
   14. Contacto
   ============================================================= */
.mailto {
  display: block; margin: 1rem 0 3rem;
  border-bottom: 2px solid var(--line-2);
  padding-bottom: 1rem;
  transition: color .35s var(--ease-out), border-color .35s var(--ease-out);
}
.mailto-big {
  display: flex; align-items: baseline; gap: .25em;
  font-family: var(--disp); font-weight: 800;
  font-size: clamp(2.4rem, 11vw, 7rem);
  letter-spacing: -.045em; line-height: 1;
}
.mailto-big i { font-style: normal; transition: transform .45s var(--ease-out); }
.mailto-mail {
  display: block; margin-top: .9rem;
  font-family: var(--mono); font-size: clamp(.72rem, 2.6vw, .95rem);
  letter-spacing: .04em; color: var(--ink-2);
  overflow-wrap: anywhere;
}
.mailto:hover { color: var(--accent); border-color: var(--accent); }
.mailto:hover .mailto-mail { color: var(--accent); }
.mailto:hover .mailto-big i { transform: translateX(.2em); }

/* Las columnas salen de los hijos que haya, no de un número fijo. El fondo
   de esta rejilla es la línea de 1px que separa los bloques; con columnas
   fijas, quitar un bloque dejaba una columna vacía enseñando ese fondo
   como un rectángulo gris. */
.contact-grid {
  display: grid; gap: 1px; background: var(--line-2);
  grid-auto-flow: column; grid-auto-columns: 1fr;
}
.contact-grid > div { background: var(--bg); padding: 1.4rem 0; }
.contact-grid p { font-family: var(--disp); font-weight: 600; font-size: 1.05rem; line-height: 1.45; }
.contact-grid a { border-bottom: 1px solid var(--line-2); transition: border-color .3s var(--ease-out); }
.contact-grid a:hover { border-color: var(--accent); }

/* =============================================================
   15. Pie
   ============================================================= */
.foot {
  border-top: 1px solid var(--line-2);
  padding: 2rem var(--gutter) 2.5rem;
}
.foot-row {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: .5rem 1rem;
  font-family: var(--mono); font-size: .68rem; letter-spacing: .12em;
  text-transform: uppercase; margin-bottom: 1.25rem;
}
.foot-row i { font-style: normal; color: var(--ink-3); }
.foot-legal {
  font-family: var(--mono); font-size: .6rem; line-height: 1.8;
  letter-spacing: .03em; color: var(--ink-3); max-width: 68ch;
}

/* =============================================================
   16. Visor (ficha ampliada)
   ============================================================= */
.visor {
  /* Centrada sobre la pantalla, no sobre el documento: da igual por dónde
     vayas leyendo, la ficha siempre se abre en medio. */
  position: fixed; inset: 0; margin: auto;
  width: min(1100px, 94vw); max-width: none;
  max-height: 92vh; height: fit-content; padding: 0;
  border: 1px solid var(--ink); background: var(--bg); color: var(--ink);
  border-top: 3px solid var(--brand, var(--accent));
  overflow: hidden;
}
/* OJO: el display va SÓLO en el estado abierto. Si se pone en `.visor` a
   secas se pisa el `display:none` que el navegador aplica a un <dialog>
   cerrado, y la ficha se queda pintada dentro de la página. */
.visor[open] { display: flex; flex-direction: column; }
.visor:not([open]) { display: none; }
.visor::backdrop { background: rgba(11, 11, 11, .72); }

.visor-close {
  position: absolute; top: 0; right: 0; z-index: 5;
  display: inline-flex; align-items: center; gap: .6em;
  padding: .7rem 1rem; background: var(--ink); color: var(--bg);
  font-family: var(--mono); font-size: .65rem; letter-spacing: .12em; text-transform: uppercase;
  transition: background .25s var(--ease-out);
}
.visor-close:hover { background: var(--accent); }
.visor-close i { font-style: normal; }

/* Ver la pieza a lo ancho de toda la ventana: útil en las maquetas de web,
   que son largas y se quedan pequeñas en la columna estrecha. */
.visor-zoom {
  position: absolute; top: 0; left: 0; z-index: 5;
  display: inline-flex; align-items: center; gap: .6em;
  padding: .7rem 1rem; background: var(--ink); color: var(--bg);
  font-family: var(--mono); font-size: .65rem; letter-spacing: .12em; text-transform: uppercase;
  transition: background .25s var(--ease-out);
}
.visor-zoom:hover { background: var(--accent); }
.visor-zoom i { font-style: normal; }

.visor.is-expandido .visor-meta { display: none; }
.visor.is-expandido .visor-inner { grid-template-columns: 1fr; }
.visor.is-expandido .visor-fig { border-right: 0; max-height: 84vh; }

.visor-inner { display: grid; flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.visor-fig {
  background: var(--paper); border-bottom: 1px solid var(--line-2);
  display: grid; place-items: center; padding: 1.75rem 1.25rem;
  min-height: 34vh; max-height: 66vh; overflow: hidden;
}
/* El tope va en unidades de pantalla, no en porcentaje: dentro de una
   rejilla de alto automático un 100% no tiene contra qué resolverse y la
   imagen se saldría de su caja. */
.visor-fig img { max-width: 100%; max-height: 56vh; width: auto; height: auto; object-fit: contain; }

/* Dentro del visor el color siempre vuelve: el blanco y negro es un
   recurso de la rejilla, no de la ficha. */
.visor { --gris: 0; }
/* Un logotipo es tinta con transparencia: sobre negro no se vería.
   Una fotografía, en cambio, pide negro. */
.visor[data-modo="marca"] .visor-fig { background: #f2f1ec; }
.visor[data-modo="pieza"] .visor-fig { background: #0d0d0d; }

.visor-meta { padding: 1.5rem var(--gutter) 1.25rem; }
.visor-idx {
  font-family: var(--mono); font-size: .68rem; letter-spacing: .16em; color: var(--accent);
}
.visor-meta h3 {
  font-size: clamp(1.5rem, 5vw, 2.4rem); font-weight: 800;
  letter-spacing: -.035em; margin: .35rem 0 1.1rem;
}
.visor-meta dl { display: grid; gap: 1px; background: var(--line-2); border-top: 1px solid var(--line-2); }
.visor-meta dl > div {
  background: var(--bg); padding: .7rem 0;
  display: flex; justify-content: space-between; gap: 1rem;
}
.visor-meta dt {
  font-family: var(--mono); font-size: .62rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-3);
}
.visor-meta dd { font-family: var(--disp); font-weight: 600; font-size: .95rem; text-align: right; }

/* Tira de piezas del proyecto */
.visor-tiras { margin-top: 1.4rem; border-top: 1px solid var(--line-2); padding-top: .85rem; }
.visor-tiras-key {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  margin-bottom: .6rem;
  font-family: var(--mono); font-size: .62rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-3);
}
.visor-tiras-key b { color: var(--accent); font-weight: 400; }
.visor-tiras-scroll {
  display: flex; flex-wrap: nowrap; gap: 1px;
  overflow-x: auto; overflow-y: visible;
  background: var(--line-2); padding: 1px;
  scrollbar-width: thin;
}
.visor-tira {
  flex: none; width: 62px; height: 46px; padding: 0;
  background: var(--paper); position: relative;
  transition: opacity .25s var(--ease-out);
  opacity: .55;
}
.visor-tira img { width: 100%; height: 100%; object-fit: contain; }
.visor-tira:hover { opacity: 1; }
.visor-tira.is-on { opacity: 1; box-shadow: inset 0 0 0 2px var(--accent); }

/* Piezas muy altas (maquetas de web): la imagen se muestra a su ancho
   completo y se recorre con el ratón dentro del propio visor. */
.visor-fig.is-alto { align-items: start; overflow-y: auto; padding: 0; }
.visor-fig.is-alto img { width: 100%; height: auto; max-width: none; max-height: none; }

.visor-nav {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: var(--line-2); border-top: 1px solid var(--line-2);
}
.visor-nav button {
  background: var(--bg); padding: .9rem var(--gutter);
  font-family: var(--mono); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase;
  transition: background .25s var(--ease-out), color .25s var(--ease-out);
}
.visor-nav button:last-child { text-align: right; }
.visor-nav button:hover { background: var(--ink); color: var(--bg); }
.visor-nav i { font-style: normal; }

/* =============================================================
   16b. Grano
   ============================================================= */
/* Una capa de ruido finísima sobre todo el documento. Sobre el papel
   da textura de impresión; sobre el negro, grano de película. Es de las
   cosas que no se ven pero se notan si faltan. */
.grano {
  position: fixed; inset: 0; z-index: 250;
  pointer-events: none; opacity: .04;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}
html:not(.js) .grano { display: none; }

/* =============================================================
   16c. Alternancia claro / oscuro
   ============================================================= */
/* La cabecera es fija: no hereda el tema de la sección que tiene
   debajo, así que se lo pone el guion al pasar por cada una. */
.topbar {
  transition: background .55s var(--ease-soft),
              color .55s var(--ease-soft),
              border-color .55s var(--ease-soft),
              transform .5s var(--ease-out);
}
/* Se aparta al bajar y vuelve al subir: mientras se explora el archivo
   no hay nada encima del trabajo. */
.topbar.is-fuera { transform: translateY(-101%); }

/* Cada sección se pinta a sí misma. Antes todas se apoyaban en el fondo
   del <body>; en cuanto el documento alterna tonos eso deja de valer,
   porque el cuerpo sólo puede ser de un color. Con var(--bg) la misma
   regla sirve para las claras y para las oscuras: el token ya ha girado.
   La marquesina se queda fuera: es una banda invertida a propósito. */
.hero, .block, .foot { background: var(--bg); color: var(--ink); }

/* El cuerpo toma el color de los extremos (portada y pie son oscuros),
   para que el rebote del scroll no enseñe una franja de papel. */
.js body { background: #080808; }

/* --- Piezas en blanco y negro dentro de los tramos oscuros -----------
   El color vuelve al pasar el cursor. Es el gesto de las referencias y
   aquí funciona porque cada disciplina se filtra por separado: una
   rejilla es toda de logotipos o toda de fotografías, nunca mezclada. */
.mark-plate img {
  filter: grayscale(var(--gris, 0));
  transition: transform .55s var(--ease-out), filter .55s var(--ease-out);
}
.mark:hover .mark-plate img,
.mark:focus-visible .mark-plate img { --gris: 0; }

/* Un logotipo lleva transparencia y suele ser tinta oscura: sobre negro
   desaparecería. Su celda conserva el papel y queda como una tarjeta
   blanca flotando sobre el negro. */
.tema-oscuro .mark[data-modo="marca"] { background: #f2f1ec; }
.tema-oscuro .mark[data-modo="marca"] .mark-idx,
.tema-oscuro .mark[data-modo="marca"] .mark-n { color: #97968e; }

/* La retícula de separación entre celdas: sobre negro, una línea clara. */
.tema-oscuro .grid { background: var(--line); }

/* =============================================================
   16d. Movimiento por velocidad de scroll
   ============================================================= */
/* El guion escribe --vel (grados) mientras se desplaza la página.
   Deformar el contenedor y no las 138 celdas mantiene el coste bajo.
   El muro 3D se queda fuera a propósito: lleva su propia perspectiva y
   deformarlo desde el padre le rompería la escena. */
/* El titular queda fuera a propósito: su transform lo escribe GSAP con
   la salida en 3D, y dos dueños de la misma propiedad se pisan. */
.js .grid-wrap { transform: skewY(calc(var(--vel, 0) * .5deg)); }
.js .marquee   { transform: skewY(calc(var(--vel, 0) * -.4deg)); }

/* =============================================================
   16e. Profundidad: entradas y relevos en 3D
   ============================================================= */
/* Cada bloque marcado con data-3d llega girado hacia atrás, se queda
   plano mientras se lee y se hunde al salir, dando paso al siguiente.
   La perspectiva va dentro del propio transform (GSAP la escribe como
   transformPerspective), así ningún padre necesita crear una escena 3D
   que rompería los `position: sticky` de las etiquetas laterales. */
.js [data-3d] { will-change: transform, opacity; }

/* Sin JavaScript no hay nada que animar y todo queda plano y visible. */
html:not(.js) [data-3d] { transform: none; opacity: 1; }

/* =============================================================
   16h. Iconos y monogramas
   ============================================================= */
/* Trazo fino, sin relleno, del color del texto: los iconos son parte de
   la tipografía, no ilustraciones pegadas. */
.ico {
  width: 1em; height: 1em; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
  opacity: .7;
}

/* Vuelta al inicio. Al margen izquierdo, para no descentrar el menú. */
.topbar-inicio {
  position: absolute; left: var(--gutter); top: 50%;
  transform: translateY(-50%);
  display: inline-flex; align-items: center; gap: .5em;
  font-family: var(--mono); font-size: .6rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-2);
  transition: color .3s var(--ease-out);
}
.topbar-inicio:hover { color: var(--ink); }
.topbar-inicio:hover .ico { opacity: 1; }
.topbar-inicio span { display: none; }
@media (min-width: 720px) {
  .topbar-inicio { font-size: .7rem; }
  .topbar-inicio span { display: inline; }
}

/* --- Glitch de la portada ---------------------------------------------
   Antes esto era un filtro sobre la foto, y se notaba: el filtro afecta
   sólo a su caja y dibujaba un rectángulo alrededor del retrato. Ahora
   son capas de verdad —dos copias desplazadas y unas franjas a todo lo
   ancho— que se funden con el fondo como la propia foto. Nada de esto
   toca el texto: vive entero dentro de .hero-fondo, que se pinta debajo
   de .hero-cuerpo.

   El transform de las copias lo escribe el guion en ráfagas; el de la
   foto principal lo lleva GSAP. Por eso son elementos distintos: dos
   dueños para la misma propiedad acaban siempre en pelea. */
.hero-eco {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 26%;
  mix-blend-mode: screen;
  opacity: 0;
  pointer-events: none;
  clip-path: inset(100% 0 0 0);
  will-change: transform, clip-path, opacity;
}
/* Teñidas hacia rojo y hacia cian: es el corte de canales que da el
   aspecto de señal rota. */
.hero-eco-a { filter: sepia(1) hue-rotate(-42deg) saturate(7) brightness(1.1); }
.hero-eco-b { filter: sepia(1) hue-rotate(145deg) saturate(6) brightness(1.1); }

.hero-bandas { position: absolute; inset: 0; pointer-events: none; }
.hero-bandas i {
  position: absolute; left: -6%; right: -6%;
  display: block; height: 2%; opacity: 0;
  background: linear-gradient(90deg,
    rgba(255, 59, 25, 0) 0%, rgba(255, 59, 25, .55) 18%,
    rgba(120, 225, 255, .5) 52%, rgba(255, 59, 25, .35) 78%, rgba(255, 59, 25, 0) 100%);
  mix-blend-mode: screen;
  will-change: transform, opacity;
}

/* El nombre se tiñe mientras se revuelve, igual que el correo del pie. */
.hero-line.is-revuelto { color: var(--accent); }

/* Monograma de herramienta. No uso logotipos de marca: son marcas
   ajenas y ocho colores distintos romperían la unidad de la página. */
.mono-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.65em; height: 1.65em; margin-right: .6em;
  flex: none; vertical-align: -.42em;
  border: 1px solid var(--line-2);
  font-family: var(--mono); font-size: .62em; font-weight: 500;
  letter-spacing: .02em; color: var(--ink-2);
  transition: border-color .3s var(--ease-out), color .3s var(--ease-out);
}
.spec-herramientas .spec-list li { display: flex; align-items: center; }
.spec-herramientas .spec-list li:hover .mono-ico { border-color: var(--accent); color: var(--accent); }

/* Correo y WhatsApp con su icono delante */
.mailto-mail { display: inline-flex; align-items: center; gap: .55em; }
.con-enlace {
  display: inline-flex; align-items: center; gap: .5em;
  transition: color .3s var(--ease-out);
}
.con-enlace:hover { color: var(--accent); }

/* =============================================================
   17. Responsive
   ============================================================= */
@media (min-width: 540px) {
  :root { --gutter: 1.75rem; }
  .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .filtro { flex: 0 1 auto; }
}

@media (min-width: 720px) {
  :root { --gutter: 2.25rem; --topbar: 60px; }
  .block { padding: 5.5rem var(--gutter) 6rem; }
  .grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .mark-name { font-size: .86rem; }
  .mark-tag { font-size: .58rem; }
  .mark-tag i { display: inline; margin-right: .55em; color: var(--inv-mute-2); }

  .pillars { grid-template-columns: repeat(3, 1fr); }
  .pillars li { padding: 1.9rem 1.5rem; }
  .pillars li:first-child { padding-left: 0; }

  .specs { grid-template-columns: repeat(3, 1fr); }
  .spec { padding: 1.8rem 1.5rem; }
  .spec:first-child { padding-left: 0; }

  /* Sin número fijo de columnas: las pone grid-auto-columns según los
     bloques que haya. Con `repeat(3, 1fr)` y sólo dos bloques quedaba una
     columna vacía enseñando el fondo de la rejilla como un rectángulo. */
  .contact-grid > div { padding: 1.5rem 1.5rem; }
  .contact-grid > div:first-child { padding-left: 0; }

  .steps li { grid-template-columns: 4rem 1fr 12rem; align-items: baseline; padding: 1.9rem 0; }
  .step-meta { grid-column: 3; margin-top: 0; text-align: right; }

  .visor-inner { grid-template-columns: 1.45fr 1fr; overflow: hidden; }
  .visor-fig { border-bottom: 0; border-right: 1px solid var(--line-2); min-height: 46vh; max-height: 76vh; }
  .visor-fig img { max-height: 64vh; }
  .visor-fig.is-alto img { max-height: none; }
  .visor-meta { padding: 2.5rem 2rem 1.75rem; overflow-y: auto; min-height: 0; }
  .visor-nav { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 960px) {
  :root { --gutter: 3rem; }
  .hero { gap: 2.5rem; }
  .hero-body { grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 3rem; }
  .hero-stats { justify-content: flex-end; }
  .grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .block-head { grid-template-columns: 12rem minmax(0, 1fr); align-items: start; gap: 1rem 2rem; }
  .block-head .tag { position: sticky; top: calc(var(--topbar) + 1.5rem); }
  .block-head .block-sub { grid-column: 2; }
  .block-cols { grid-template-columns: repeat(2, 1fr); max-width: none; gap: 2.5rem; padding-left: 14rem; }
  .pillars, .steps, .specs, .contact-grid { margin-left: 14rem; }
  .filtros, .grid-wrap, .grid-note { margin-left: 14rem; }
  .mailto { margin-left: 14rem; }
}

@media (min-width: 1280px) {
  :root { --gutter: 4rem; }
  .grid { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .block-head { grid-template-columns: 16rem minmax(0, 1fr); }
  .block-cols, .pillars, .steps, .specs, .contact-grid,
  .filtros, .grid-wrap, .grid-note, .mailto { margin-left: 18rem; }
  .block-cols { padding-left: 0; margin-left: 18rem; }
}

@media (min-width: 1600px) {
  .grid { grid-template-columns: repeat(7, minmax(0, 1fr)); }
}

/* =============================================================
   18. Movimiento reducido
   Sólo se desactiva lo intrusivo. Los micro-efectos (hover,
   fundidos, marquesina) se mantienen a propósito.
   ============================================================= */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .crosshair { display: none; }
  /* Sin inercia no hay velocidad que publicar, pero por si acaso: nada
     de deformación, ni de indicador latiendo, ni de retrato invisible. */
  .grid-wrap, .marquee { transform: none !important; }
  [data-3d] { transform: none !important; opacity: 1 !important; }
  .hero-eco, .hero-bandas { display: none !important; }
  .obj { transform: none !important; }
  .hero-retrato img { opacity: 1 !important; transform: none !important; }
}

/* =============================================================
   19. Impresión
   ============================================================= */
@media print {
  .splash, .crosshair, .hud, .topbar, .marquee, .visor { display: none !important; }
  body { background: #fff; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}
