/* =========================================================================
   GXUS — sistema visual
   Proporciones derivadas de la medición de foxxel.co (ver ANALISIS-FOXXEL.md).
   Mobile-first. 3 breakpoints: 480 / 768 / 1024.
   ========================================================================= */

/* ---------- Fuentes autoalojadas. Nunca Google Fonts. ---------- */
@font-face{
  font-family:"Anton"; src:url("assets/fonts/anton-latin.woff2") format("woff2");
  font-weight:400; font-style:normal; font-display:swap;
}
@font-face{
  font-family:"JetBrains Mono"; src:url("assets/fonts/jetbrains-mono-latin.woff2") format("woff2");
  font-weight:400 700; font-style:normal; font-display:swap;
}

:root{
  /* --- Color. Un solo acento, y TODO lo demás derivado de él. ---
     Ni negro puro ni blanco puro ni un solo gris neutro: el negro lleva una
     pizca de rojo, el blanco es cálido y el gris es el acento desaturado.
     Es lo que separa una paleta de un tema oscuro por defecto.
     Ratios medidos (ver contraste.py): fg/bg 18,86 · muted/bg 7,62 ·
     acento/bg 5,30 · acento/surface 4,98 · negro/acento 5,55. */
  --bg:#0a0708;
  --surface:#151011;
  --line:#2b2325;
  --fg:#fff6f4;
  --muted:#a89d9e;
  --accent:#f0404d;
  --on-accent:#000;         /* blanco sobre el acento da 3,79:1 y FALLA AA */

  /* --- Tipografía --- */
  --f-display:"Anton",Impact,"Haettenschweiler",sans-serif;
  --f-mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  --f-body:system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;

  /* Fluida con clamp(), no un tamaño por breakpoint.
     +5 % sobre los valores de foxxel: Anton es más estrecha que Bebas Neue y
     necesita más cuerpo para ocupar la misma mancha. */
  /* 38vw, no 26vw. Medido: con 26vw la palabra ocupaba el 55 % del ancho a
     TODOS los tamaños, y en un móvil eso deja el hero flojo justo donde no
     sobra pantalla. El tope de 380px no se toca porque en escritorio el límite
     es vertical: allí sólo quedan 95px libres en el hero, contra 218-392px en
     un teléfono. Resultado: ~80 % de ancho en móvil y tablet, escritorio igual
     que antes. */
  --fs-hero:clamp(96px,38vw,380px);
  --fs-h2:clamp(56px,9.5vw,148px);
  --fs-h3:clamp(34px,5.3vw,78px);
  --fs-h4:clamp(26px,3.8vw,55px);
  --fs-lead:clamp(19px,1.7vw,26px);
  --fs-body:clamp(15px,1.05vw,16px);
  --fs-label:11px;          /* piso duro. Ni un píxel menos. */

  --lh-display:.86;
  --lh-body:1.7;
  --lh-label:1.5;
  --ls-display:-.01em;
  --ls-label:.3em;          /* foxxel usa .42em sobre Montserrat; en monoespaciada
                               .42em rompe la palabra. Ver nota en ANALISIS §ADOPTAR. */

  /* --- Espaciado. Escala fija: cero valores sueltos fuera de aquí.
         Los huecos escalan ×1,65 de móvil a escritorio, como foxxel. --- */
  --space-1:8px;
  --space-2:12px;
  --space-3:clamp(16px,1.6vw,24px);
  --space-4:clamp(24px,2.4vw,36px);
  --space-5:clamp(32px,3.4vw,52px);
  --space-6:clamp(40px,4.6vw,68px);
  --space-7:clamp(56px,6.6vw,96px);

  /* Padding de sección. El ratio vertical/horizontal replica el de foxxel:
     1,89 a 1440px (medido 1,93) y 3,20 a 360px (medido 3,25). */
  --pad-x:clamp(20px,5vw,80px);
  --pad-y:clamp(64px,9.5vw,136px);
  --maxw:1400px;

  /* --- Movimiento. Dos curvas, no seis.
     Ambas son expo-out: arrancan disparadas y aterrizan durante mucho rato.
     Es la mitad de la razón por la que el movimiento de gsap.com se lee como
     coreografía y no como transición por defecto. Una curva casi recta
     (.34,.68,.35,1) es lo que produce la sensación de "plantilla animada". --- */
  --e-hover:cubic-bezier(.23,1,.32,1);
  --e-in:cubic-bezier(.16,1,.3,1);
  --d-hover:.4s;
  --d-reveal:1.1s;

  --radius:14px;
  --radius-pill:999px;
}

/* ---------- Reset mínimo ---------- */
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:88px;-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--bg); color:var(--fg);
  font:400 var(--fs-body)/var(--lh-body) var(--f-body);
  overflow-x:hidden;
}
img,video{display:block;max-width:100%;height:auto}
ul,ol,dl,dd{margin:0;padding:0;list-style:none}
h1,h2,h3,h4,p,figure{margin:0}
a{color:inherit}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

.skip{
  position:absolute;left:var(--space-3);top:-100px;z-index:100;
  padding:12px 18px;background:var(--accent);color:var(--on-accent);
  font:700 var(--fs-label)/1 var(--f-mono);letter-spacing:var(--ls-label);
  text-transform:uppercase;text-decoration:none;border-radius:var(--radius-pill);
  transition:top var(--d-hover) var(--e-hover);
}
.skip:focus{top:var(--space-3)}

/* =========================================================================
   Primitivas tipográficas
   ========================================================================= */
.kicker{
  font:600 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:var(--ls-label);text-transform:uppercase;color:var(--accent);
  margin:0;
}
/* Etiqueta entre llaves en vez de con filete. Es el recurso de gsap.com
   ({ Why GSAP } / { GSAP Tools }): cuesta cero y tiene más carácter que una
   línea de 1px, que es la decoración que sale por defecto. */
.kicker--rule{display:inline-flex;align-items:baseline;gap:.55em}
.kicker--rule::before{content:"{"}
.kicker--rule::after{content:"}"}
.kicker--rule::before,.kicker--rule::after{
  font-family:var(--f-mono);font-size:1.5em;font-weight:400;line-height:0;
  color:var(--muted);flex:none;
}
.accent{color:var(--accent)}   /* siempre al 100 % de opacidad */

.sec__title,.hero__title,.release__title,.empty__head{
  font-family:var(--f-display);font-weight:400;line-height:var(--lh-display);
  letter-spacing:var(--ls-display);text-transform:uppercase;
}
.sec__title{font-size:var(--fs-h2)}
.lead{
  font-size:var(--fs-lead);line-height:1.45;color:var(--fg);
  max-width:28ch;margin-block:var(--space-4) 0;
}
.prose p{color:var(--muted);margin-block:0 var(--space-3)}
.prose p:last-child{margin-bottom:0}

/* =========================================================================
   Botones — dos formas y sólo dos
   ========================================================================= */
.btn{
  display:inline-flex;align-items:center;gap:var(--space-2);
  padding:15px 26px;border-radius:var(--radius-pill);
  font:700 var(--fs-label)/1 var(--f-mono);letter-spacing:.24em;
  text-transform:uppercase;text-decoration:none;white-space:nowrap;
  border:1px solid transparent;
  transition:transform var(--d-hover) var(--e-hover),
             box-shadow var(--d-hover) var(--e-hover),
             background-color var(--d-hover) var(--e-hover),
             border-color var(--d-hover) var(--e-hover);
}
.btn--primary{background:var(--accent);color:var(--on-accent)}
.btn--ghost{background:rgba(255,255,255,.05);color:var(--fg);border-color:var(--line)}

/* Hover: el botón no cambia de identidad, se levanta. Patrón medido en foxxel. */
@media (hover:hover){
  .btn:hover{transform:translateY(-2px)}
  .btn--primary:hover{box-shadow:0 22px 50px -18px var(--accent)}
  .btn--ghost:hover{border-color:var(--accent);background:rgba(255,255,255,.08)}
}
/* En táctil no hay hover que se quede pegado. */
@media (hover:none){
  .btn:hover,.btn:focus{transform:none;box-shadow:none}
  .btn:active{transform:scale(.98)}
}

/* =========================================================================
   Cabecera y menú (<details> nativo: cero JS)
   ========================================================================= */
.hdr{
  position:fixed;inset:0 0 auto;z-index:50;
  display:flex;align-items:center;gap:var(--space-3);
  padding:var(--space-3) var(--pad-x);
  background:linear-gradient(to bottom,rgba(0,0,0,.92),rgba(0,0,0,0));
}
.hdr__brand{
  font-family:var(--f-display);font-size:24px;letter-spacing:.02em;
  text-decoration:none;display:flex;align-items:center;gap:10px;margin-right:auto;
}
.hdr__dot{width:9px;height:9px;border-radius:50%;background:var(--accent);flex:none}
.hdr__cta{display:none}

.menu{position:relative}
.menu__btn{
  list-style:none;display:flex;align-items:center;gap:10px;cursor:pointer;
  padding:11px 18px;border:1px solid var(--line);border-radius:var(--radius-pill);
  background:rgba(255,255,255,.05);
  font:700 var(--fs-label)/1 var(--f-mono);letter-spacing:.24em;text-transform:uppercase;
}
.menu__btn::-webkit-details-marker{display:none}
.menu__bars{width:16px;height:9px;border-top:1.5px solid;border-bottom:1.5px solid;flex:none}
.menu[open] .menu__bars{border-bottom-color:var(--accent)}

.menu__panel{
  position:absolute;right:0;top:calc(100% + var(--space-2));
  width:min(92vw,420px);padding:var(--space-4);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:0 40px 80px -30px #000;
}
.menu__list li+li{border-top:1px solid var(--line)}
.menu__list a{
  display:grid;grid-template-columns:auto 1fr;gap:2px var(--space-3);
  align-items:baseline;padding:14px 4px;text-decoration:none;
  transition:transform var(--d-hover) var(--e-hover);
}
.menu__list b{
  grid-row:span 2;font:700 var(--fs-label)/1 var(--f-mono);
  letter-spacing:.12em;color:var(--accent);
}
.menu__list span{font-family:var(--f-display);font-size:26px;text-transform:uppercase;line-height:1}
.menu__list em{
  font:400 var(--fs-label)/1 var(--f-mono);letter-spacing:var(--ls-label);
  text-transform:uppercase;color:var(--muted);font-style:normal;
}
@media (hover:hover){ .menu__list a:hover{transform:translateX(8px)} }
.menu__meta{
  margin:var(--space-3) 0 0;padding-top:var(--space-3);border-top:1px solid var(--line);
  font:400 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.1em;text-transform:uppercase;color:var(--muted);
}
.menu__meta a{color:var(--accent);text-decoration:none}

/* =========================================================================
   Hero — la única sección con altura forzada
   ========================================================================= */
.hero{
  position:relative;min-height:100svh;display:flex;flex-direction:column;
  justify-content:flex-end;overflow:hidden;
}
/* Toda la fotografía va en blanco y negro: el único color de la página es el
   acento. Sin esto el vídeo del hero (láser verde) impone una segunda paleta y
   se lleva por delante la dirección de arte. */
.hero__media{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:-2;
  filter:grayscale(1) contrast(1.12) brightness(.62);
}
.hero__veil{
  position:absolute;inset:0;z-index:-1;
  background:linear-gradient(to top,rgba(0,0,0,.95) 6%,rgba(0,0,0,.35) 55%,rgba(0,0,0,.7) 100%);
}
.hero__body{
  padding:0 var(--pad-x) var(--space-6);
  max-width:var(--maxw);width:100%;margin-inline:auto;
}
/* Desviación documentada. En foxxel el nombre cubre el 98 % del ancho del
   contenedor, pero eso es una propiedad de tener SEIS letras en Bebas Neue
   (avance ≈0,815em): 6 × 0,815 × 259px = 1266px sobre un contenedor de 1296.
   GXUS tiene CUATRO letras y Anton avanza ≈0,62em. Igualar ese 98 % exigiría un
   cuerpo de ~506px (línea de 435px, no cabe en el hero) o repartir las letras
   con 180px de hueco, y entonces se lee «G X U S» y deja de ser una palabra.

   Corrección medida (2026-08-04): aquí ponía que se cubría «~75 % del
   contenedor, igual a 360px que a 1920px». Era falso: se cubría el 55 % en
   todos los anchos. Ahora se cubre ~80 % hasta 1000px, y de ahí arriba el tope
   de 380px lo baja hasta el 57 % a 1440px. Esa caída NO es un descuido: en
   escritorio el hero sólo tiene 95px verticales libres y un cuerpo mayor
   empujaría los CTA fuera de pantalla. En móvil sobran 218-392px, así que allí
   sí se llena. */
.hero__title{
  font-size:var(--fs-hero);margin:var(--space-4) 0 0;letter-spacing:-.005em;
}
.hero__lead{
  font-size:var(--fs-lead);line-height:1.4;max-width:30ch;
  margin:var(--space-4) 0 0;color:var(--fg);
}
.hero__meta{
  margin:var(--space-2) 0 0;
  font:400 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.18em;text-transform:uppercase;color:var(--muted);
}
.hero__meta a{color:var(--accent);text-decoration:none}
.hero__ctas{display:flex;flex-wrap:wrap;gap:var(--space-2);margin:var(--space-5) 0 0}

/* Marquesina: es la ÚNICA animación en bucle de la página. */
.marquee{
  border-block:1px solid var(--line);background:rgba(0,0,0,.6);
  overflow:hidden;padding-block:var(--space-3);
}
.marquee__track{display:flex;width:max-content;animation:marq 38s linear infinite}
.marquee__track span{
  display:flex;align-items:center;flex:none;
  font-family:var(--f-display);font-size:clamp(20px,2.4vw,30px);
  text-transform:uppercase;letter-spacing:.02em;color:var(--muted);
}
.marquee__track i{
  width:7px;height:7px;border-radius:50%;background:var(--accent);
  margin-inline:clamp(18px,2.4vw,34px);flex:none;
}
@keyframes marq{to{transform:translateX(-50%)}}

/* =========================================================================
   Estructura de sección
   ========================================================================= */
.sec{
  padding:var(--pad-y) var(--pad-x);
  max-width:var(--maxw);margin-inline:auto;
  /* Superior > inferior, ratio 1,15 — el título respira, el cierre aprieta. */
  padding-bottom:calc(var(--pad-y) / 1.15);
}
.sec+.sec{border-top:1px solid var(--line)}

/* Cabecera 78/22: título grande a la izquierda, meta pequeña a la derecha. */
.sec__head{margin-bottom:var(--space-6)}
.sec__title{margin-top:var(--space-4)}   /* Con line-height .86 la caja del inline sobresale hacia arriba y toca el kicker. */
.sec__meta{
  margin:var(--space-3) 0 0;
  font:400 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.18em;text-transform:uppercase;color:var(--muted);
}

/* =========================================================================
   Fechas
   ========================================================================= */
.dates li{
  display:grid;gap:var(--space-1);
  padding:var(--space-4) 0;border-bottom:1px solid var(--line);
}
.dates time{
  font:700 var(--fs-label)/1 var(--f-mono);letter-spacing:.2em;
  text-transform:uppercase;color:var(--accent);
}
.dates__name{font-family:var(--f-display);font-size:var(--fs-h4);text-transform:uppercase;line-height:1.05}
.dates__venue{color:var(--muted)}
.dates__cta{
  font:700 var(--fs-label)/1 var(--f-mono);letter-spacing:.2em;text-transform:uppercase;
  text-decoration:none;color:var(--accent);
}

.empty{
  border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);padding:var(--space-6) var(--space-5);
}
.empty__head{font-size:var(--fs-h3);margin-bottom:var(--space-4)}
.empty__body{color:var(--muted);max-width:38ch;margin-bottom:var(--space-5)}

/* =========================================================================
   Divisiones de dos columnas — reparto 50/50 con inclinación ±3 %
   ========================================================================= */
/* Apilado en móvil: 56px contra los 60px que mide foxxel (−6,7 %). */
.split{display:grid;gap:var(--space-7);align-items:start}

/* Estadísticas: rejilla con filetes de 1 px, sin contadores sociales. */
.stats{
  display:grid;grid-template-columns:1fr 1fr;gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:var(--radius);
  overflow:hidden;
}
.stats__cell{background:var(--bg);padding:var(--space-4) var(--space-3)}
.stats__num{
  font-family:var(--f-display);font-size:var(--fs-h3);line-height:1;
  text-transform:uppercase;margin:0 0 var(--space-3);
}
.stats__num--sm{font-size:var(--fs-h4)}
.stats__lbl{
  font:400 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.16em;text-transform:uppercase;color:var(--muted);
}

/* =========================================================================
   Posicionamiento — lista de filetes, el patrón de listado de gsap.com.
   Es el tercer ritmo de la página (título gigante · rejilla · lista) y existe
   para que #sobre no sea otra vez cabecera + dos columnas.
   ========================================================================= */
.logros{margin-top:var(--space-7)}
.logros__lista{margin-top:var(--space-4);border-top:1px solid var(--line)}
.logros__lista li{
  display:grid;grid-template-columns:auto 1fr;gap:2px var(--space-4);
  align-items:baseline;padding:var(--space-4) 0;border-bottom:1px solid var(--line);
}
/* Ancho mínimo fijo: sin él, «#19», «#2» y «#1» miden distinto y la segunda
   columna arranca en tres sitios diferentes. Se lee como descuido, no como
   composición. */
.logros__num{
  grid-row:span 2;font-family:var(--f-display);font-weight:400;
  font-size:clamp(38px,4.4vw,64px);line-height:.9;color:var(--accent);
  min-width:clamp(58px,6.2vw,100px);
}
.logros__que{font-family:var(--f-display);font-size:clamp(19px,1.9vw,26px);
  text-transform:uppercase;line-height:1.15;letter-spacing:.01em}
.logros__donde{
  font:400 var(--fs-label)/var(--lh-label) var(--f-mono);font-style:normal;
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
}
.logros__nota{
  margin:var(--space-3) 0 0;
  font:400 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
}

/* =========================================================================
   Música
   ========================================================================= */
.release__title{font-size:var(--fs-h3);margin:var(--space-4) 0 var(--space-4)}
.release__meta{border-top:1px solid var(--line)}
.release__meta li{
  display:flex;justify-content:space-between;gap:var(--space-3);
  padding:var(--space-3) 0;border-bottom:1px solid var(--line);
}
.release__meta b{
  font:400 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.16em;text-transform:uppercase;color:var(--muted);
}
.release__links{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-top:var(--space-5)}

/* =========================================================================
   Fachadas — cero bytes de terceros hasta que el usuario los pide
   ========================================================================= */
.facade{
  position:relative;border:1px solid var(--line);border-radius:var(--radius);
  background:var(--surface);overflow:hidden;
}
.facade--audio{padding:var(--space-5) var(--space-4);display:grid;gap:var(--space-3)}
/* El clip es vertical (540×960). No se recorta a 16/9 para "rellenar ancho":
   quedaría una banda de 60px de imagen. Se limita el ancho y se respeta el
   formato del material. */
/* Fragmento reproducible + enlace al set completo, en columna y centrados.
   El clip es apaisado 1080×590 (1,83:1, ni 16/9 ni 2:1). Se usa su proporción
   real en vez de forzar 16/9: forzarlo recortaría cabeza o mesa. */
.clip{display:grid;justify-items:center;gap:var(--space-5)}
.facade--clip{max-width:820px;width:100%}
.facade--clip img{
  width:100%;aspect-ratio:1080/590;object-fit:cover;opacity:.6;
  filter:grayscale(1) contrast(1.1);
  transition:opacity var(--d-hover) var(--e-hover),filter var(--d-hover) var(--e-hover);
}
/* Velo bajo el rótulo: el texto va sobre una foto, así que su contraste no lo
   garantiza la paleta — depende de qué haya en el píxel de debajo. */
.facade--clip .facade__btn--over{background:rgba(10,7,8,.45)}
@media (hover:hover){
  .facade--clip:hover img{opacity:.75;filter:grayscale(.5) contrast(1.05)}
}
.clip__mas{display:grid;justify-items:center;gap:var(--space-2);margin:0;text-align:center}
.clip__mas small{
  font:400 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
}
/* El vídeo ya reproducido conserva el formato del material, no se estira. */
.facade--clip video{aspect-ratio:1080/590;object-fit:contain;background:#000}
.facade__btn{display:flex;align-items:center;gap:var(--space-3);text-align:left}
.facade__btn--over{position:absolute;inset:0;justify-content:center;padding:var(--space-4)}
.facade__ico{
  width:52px;height:52px;border-radius:50%;background:var(--accent);flex:none;
  position:relative;transition:transform var(--d-hover) var(--e-hover);
}
.facade__ico::after{
  content:"";position:absolute;left:50%;top:50%;
  border:8px solid transparent;border-left:13px solid var(--on-accent);
  transform:translate(-35%,-50%);
}
.facade__txt{
  font:700 var(--fs-label)/1.3 var(--f-mono);letter-spacing:.2em;text-transform:uppercase;
  display:grid;gap:6px;
}
.facade__txt em{
  font-weight:400;font-style:normal;letter-spacing:.14em;color:var(--muted);
}
@media (hover:hover){ .facade__btn:hover .facade__ico{transform:scale(1.08)} }
.facade iframe{display:block;width:100%;border:0;background:#000}

/* =========================================================================
   Galería — 3 ratios en escritorio, 1 en móvil
   ========================================================================= */
/* La única cosa de la página que se sale de la columna de 1400px. Todo lo
   demás vive dentro de la misma caja con el mismo padding, y esa contención
   perfecta es justo lo que se lee como plantilla: basta con que UN elemento
   rompa el borde para que la página deje de parecer una rejilla rellenada.
   Se sangra hasta el padding, no hasta 100vw: 100vw incluye la barra de
   scroll y produce desbordamiento horizontal. */
.gal{
  display:grid;grid-template-columns:repeat(2,1fr);
  gap:clamp(8px,1vw,14px);
  margin-inline:calc(var(--pad-x) * -1);
}
.gal__i{overflow:hidden;border-radius:calc(var(--radius) - 6px);background:var(--surface)}
/* El <picture> no debe formar caja: si la forma, las reglas de proporción y de
   object-fit del <img> quedan colgando de un contenedor sin altura. */
.gal__i picture{display:contents}
.gal__i img{
  width:100%;height:100%;object-fit:cover;aspect-ratio:3/4;
  filter:grayscale(1) contrast(1.05);
  transition:filter 1.2s var(--e-in),transform 1.4s var(--e-in);
}
@media (hover:hover){
  .gal__i:hover img{filter:grayscale(0) contrast(1);transform:scale(1.04)}
}

/* =========================================================================
   Booking
   ========================================================================= */
/* Booking no se parece a las otras seis secciones, a propósito: es la que
   justifica la web. Repetir el mismo módulo siete veces es lo que hace que una
   web se lea como plantilla.
   La diferencia la marca el CAMBIO DE SUPERFICIE a sangre completa, y nada
   más. Aquí había además una barra de acento de 2px encima: sobraba. La
   superficie ya separa la sección, y una franja de color para señalar "esto
   es importante" es justo el recurso de plantilla que este rediseño venía a
   quitar. El filete de 1px de .sec+.sec sigue haciendo de junta, igual que
   entre las demás secciones. */
.sec--booking{
  background:var(--surface);
  max-width:none;padding-inline:max(var(--pad-x),calc(50vw - var(--maxw) / 2));
}
.sec--booking .stats__cell,
.sec--booking .contact__row,
.sec--booking .rider,
.sec--booking .form input,
.sec--booking .form select,
.sec--booking .form textarea{background:var(--bg)}

.form__row{display:grid;gap:var(--space-1);margin:0 0 var(--space-4)}
.form__pair{display:grid;gap:0}
.form label{
  font:600 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.16em;text-transform:uppercase;color:var(--muted);
}
.req{color:var(--accent)}
.form input,.form select,.form textarea{
  font:400 var(--fs-body)/1.5 var(--f-body);color:var(--fg);
  background:var(--surface);border:1px solid var(--line);border-radius:10px;
  padding:13px 14px;width:100%;
  transition:border-color var(--d-hover) var(--e-hover);
}
.form textarea{resize:vertical;min-height:130px}
.form input:focus,.form select:focus,.form textarea:focus{border-color:var(--accent)}
.form input::placeholder,.form textarea::placeholder{color:#6a6a6a}
/* Reserva el hueco del widget para que al cargar no empuje el botón de enviar
   hacia abajo (Turnstile mide 300×65 en su tamaño normal). */
.form__captcha{min-height:65px;margin:0 0 var(--space-4)}
.form__foot{display:grid;gap:var(--space-3);margin:0;justify-items:start}
.form__foot small{color:var(--muted);font-size:13px;line-height:1.6}
.form__foot a{color:var(--accent)}
/* Honeypot: fuera de pantalla por clase, nunca con style= inline. */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

.contact{display:grid;gap:var(--space-3);align-content:start}
.contact__row{
  display:grid;gap:4px;padding:var(--space-4);text-decoration:none;
  border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);
  transition:border-color var(--d-hover) var(--e-hover),transform var(--d-hover) var(--e-hover);
}
.contact__row b{
  font:400 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.2em;text-transform:uppercase;color:var(--muted);
}
.contact__row span{font-family:var(--f-display);font-size:clamp(22px,2.2vw,30px);text-transform:uppercase;line-height:1.1}
@media (hover:hover){
  .contact__row:hover{border-color:var(--accent);transform:translateY(-2px)}
}
.contact__docs{display:flex;flex-wrap:wrap;gap:var(--space-2);margin:var(--space-2) 0 0}

.rider{border:1px solid var(--line);border-radius:var(--radius);background:var(--surface)}
.rider>summary{
  cursor:pointer;padding:var(--space-4);
  font:700 var(--fs-label)/1 var(--f-mono);letter-spacing:.2em;text-transform:uppercase;
}
.rider>summary::marker{color:var(--accent)}
.rider h3{
  font:600 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.2em;text-transform:uppercase;color:var(--accent);
  margin:0 var(--space-4) var(--space-2);
}
.rider ul{margin:0 var(--space-4) var(--space-4);color:var(--muted)}
.rider li{padding:6px 0;border-bottom:1px solid var(--line)}
.rider>p{margin:0 var(--space-4) var(--space-4);color:var(--muted);font-size:14px}
.rider a{color:var(--accent)}

/* =========================================================================
   Páginas secundarias (legales, gracias)
   ========================================================================= */
.page{padding-top:calc(var(--pad-y) + 56px)}
.page .prose p{margin-bottom:var(--space-4)}
.page .prose a{color:var(--accent)}
.page .prose strong{color:var(--fg)}
.page h1{font-family:var(--f-display);font-weight:400;font-size:var(--fs-h2);
  line-height:var(--lh-display);letter-spacing:var(--ls-display);text-transform:uppercase;
  margin-top:var(--space-3)}
.page .prose{max-width:62ch}

/* =========================================================================
   Pie
   ========================================================================= */
.ftr{
  padding:var(--space-7) var(--pad-x) var(--space-5);
  max-width:var(--maxw);margin-inline:auto;border-top:1px solid var(--line);
}
.ftr__top{display:grid;gap:var(--space-6)}
.ftr__brand{font-family:var(--f-display);font-size:var(--fs-h4);text-transform:uppercase;line-height:1}
.ftr__tags{display:flex;flex-wrap:wrap;gap:var(--space-1);margin:var(--space-3) 0 0}
.ftr__tags span{
  padding:7px 14px;border:1px solid var(--line);border-radius:var(--radius-pill);
  font:400 var(--fs-label)/1 var(--f-mono);letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);
}
/* El contacto vive también aquí: sin él la columna de marca era 200px de vacío,
   y es el dato que tiene que seguir visible con el JS desactivado. */
.ftr__contact{display:grid;gap:var(--space-2);margin:var(--space-4) 0 0}
.ftr__contact a{
  justify-self:start;text-decoration:none;
  font:400 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
  border-bottom:1px solid var(--line);padding-bottom:6px;
  transition:color var(--d-hover) var(--e-hover),border-color var(--d-hover) var(--e-hover);
}
@media (hover:hover){ .ftr__contact a:hover{color:var(--fg);border-color:var(--accent)} }
.ftr__nav{margin-top:var(--space-3);display:grid;gap:var(--space-2)}
.ftr__nav a{text-decoration:none;color:var(--muted);transition:color var(--d-hover) var(--e-hover)}
@media (hover:hover){ .ftr__nav a:hover{color:var(--fg)} }
.ftr__bot{
  display:grid;gap:var(--space-3);margin-top:var(--space-6);
  padding-top:var(--space-4);border-top:1px solid var(--line);
}
.ftr__bot small,.ftr__legal a{
  font:400 var(--fs-label)/var(--lh-label) var(--f-mono);
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
}
.ftr__legal{display:flex;flex-wrap:wrap;gap:var(--space-4)}
.ftr__legal a{text-decoration:none}

/* =========================================================================
   Reveal on scroll — red de seguridad primero
   La regla que revela iguala en especificidad a la que oculta. Sin esto la
   página se queda en negro (ver CLAUDE.md §4.1).
   ========================================================================= */
/* Se animan los HIJOS directos, no el bloque entero: así la cabecera entra
   antes que el contenido y la sección se lee como una secuencia y no como una
   diapositiva. El retardo es de 90 ms, suficiente para percibirse y no para
   hacer esperar. */
html:not(.no-js) [data-reveal]>*{
  opacity:0;transform:translateY(38px);
  transition:opacity var(--d-reveal) var(--e-in),transform var(--d-reveal) var(--e-in);
}
html.no-js [data-reveal]>*,
html:not(.no-js) [data-reveal].is-visible>*{opacity:1;transform:none}
html:not(.no-js) [data-reveal].is-visible>*:nth-child(2){transition-delay:.12s}
html:not(.no-js) [data-reveal].is-visible>*:nth-child(3){transition-delay:.24s}

/* -------------------------------------------------------------------------
   Título ligado al scroll — el patrón central de gsap.com traducido a CSS.
   Allí el titular se ilumina CONFORME raspas: el reloj de la animación es la
   posición del scroll, no un evento de entrada. `animation-timeline: view()`
   hace exactamente eso sin una línea de JS (CLAUDE.md §1 lo autoriza).

   Es seguro por construcción: al 0 % de progreso el título ya está en --muted
   (7,62:1 sobre el fondo), nunca invisible. Si el navegador no soporta
   animation-timeline, se queda en --fg y no pasa nada. No puede dejar la
   página en negro, que es el fallo que persigue el §4.1.
   ------------------------------------------------------------------------- */
.sec__title{color:var(--fg)}

/* Capa 2: ligada al scroll de verdad. Sustituye a las transiciones de arriba
   donde el navegador la soporta; si no, no pasa nada y manda la capa 1.

   Los tramos van SIEMPRE dentro de `entry`, nunca mezclando entry con cover.
   Es lo que la hace segura: un elemento que ya ha entrado del todo está en
   entry 100%, o sea en el fotograma final, o sea visible. Entrar por #booking
   o pulsar Fin no puede dejar nada en negro (§4.1). Mezclar `entry X% cover Y%`
   parece equivalente y no lo es: el progreso depende del alto de la sección y
   una sección alta se queda a medias.

   El escalonado no se hace con animation-delay: en una línea de tiempo de
   scroll el retardo no cuenta segundos, desplaza el tramo. Cada hijo entra un
   poco más tarde en el RECORRIDO, no en el reloj. */
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    /* Los HIJOS de sección NO van ligados al scroll, y es una decisión medida,
       no una omisión. Con view() cada elemento es su propio sujeto, así que su
       progreso depende de su propia altura: un bloque alto colocado bajo en la
       pantalla llega al aterrizaje con sólo ~54 % de su recorrido hecho. Al
       entrar por #booking eso dejaba el formulario y el email al 20-30 % de
       opacidad — no pantalla negra, pero sí la sección que justifica la web
       llegando medio muerta. Se ve en capturas/estado-deeplink-booking.
       La entrada de sección se queda en la capa 1 (JS + transición), que tiene
       la comprobación inicial síncrona del §4.1 y una duración constante sea
       cual sea el tamaño del elemento.
       Ligado al scroll sólo va lo que NO puede esconder contenido. */

    /* Titular: cortina de arriba abajo + el color raspando de gris a blanco.
       Va al revés que el contenido, que sube: el titular se descubre bajando
       mientras lo de debajo asciende, y el contraste hace que se note.
       El recorte termina en insets NEGATIVOS a propósito: con line-height .86
       los rasgos de Anton se salen de su caja, y un inset(0) les cortaría la
       cabeza y los pies.

       El reloj es la SECCIÓN, no el titular. Con view() a secas el sujeto es el
       propio elemento, y un titular de 200px agota su recorrido de entrada en
       los últimos 200px de la pantalla: el efecto existe pero pasa donde nadie
       mira, y parece que no hay efecto. Atado a la sección, el mismo raspado
       dura ~300px de scroll y se ve.
       Cuidado con el recorrido de `entry`: para una sección MÁS ALTA que la
       ventana no dura lo que mide la sección, sino lo que mide la ventana —
       termina cuando el borde superior de la sección llega al de la pantalla,
       que ocurre antes. Medido: al entrar por un ancla la sección va por el
       ~88 % de su recorrido, no por el ~49 % que daba mi primer cálculo. Por
       eso el tramo puede llegar hasta el 55 % y seguir siendo seguro: el
       titular está entero mucho antes de que nadie aterrice sobre él.
       55 % × 900px ≈ 450px de scroll: el raspado dura y se ve. */
    .sec{view-timeline-name:--seccion}
    .sec__title{
      animation:titulo linear both;
      animation-timeline:--seccion;
      animation-range:entry 5% entry 55%;
    }

    /* Galería: cada foto se asienta desde un 6 % de más. Es transform puro, va
       en el compositor y no toca el hilo principal. */
    .gal__i img{
      animation:asentar linear both;
      animation-timeline:view();
      animation-range:entry 0% entry 80%;
    }
  }
}

/* El hero está sobre el pliegue: ahí no hay scroll que ligar, así que su
   entrada sí va por reloj. */
@media (prefers-reduced-motion:no-preference){
  .hero__body>*{animation:entrar .95s var(--e-in) both}
  .hero__body>*:nth-child(2){animation-delay:.08s}
  .hero__body>*:nth-child(3){animation-delay:.16s}
  .hero__body>*:nth-child(4){animation-delay:.24s}
  .hero__body>*:nth-child(5){animation-delay:.32s}
}

@keyframes entrar{
  from{opacity:0;transform:translateY(38px)}
  to{opacity:1;transform:none}
}
@keyframes titulo{
  from{color:var(--muted);clip-path:inset(-25% 0 100% 0)}
  to{color:var(--fg);clip-path:inset(-25% 0 -25% 0)}
}
/* Usa `scale`, no `transform`. La imagen ya usa transform para el hover, y una
   animación con fill:both congelaría ese transform para siempre — el hover
   dejaría de funcionar. Las propiedades independientes se componen con
   transform en vez de pisarlo. */
@keyframes asentar{
  from{scale:1.06}
  to{scale:1}
}

/* =========================================================================
   Objetivos táctiles. No es un breakpoint de ancho sino de DISPOSITIVO:
   (pointer:coarse) es el dedo, y el dedo no acierta en 14px.
   Medido antes de esto: el botón de menú 35px de alto, los enlaces del pie
   14-20px. El mínimo de WCAG 2.5.8 (AA) es 24×24 y el de 2.5.5 (AAA) 44×44.
   Se sube todo a 44 donde no cuesta maquetación, y a >=24 en las listas
   densas, donde 44 dejaría el pie con dos pantallas de alto.
   ========================================================================= */
@media (pointer:coarse){
  .btn{min-height:44px}
  .menu__btn{min-height:44px}
  .hdr__brand{min-height:44px}
  .facade__btn{min-height:44px}

  /* Enlaces sueltos de texto: el área crece con padding, no con tamaño de
     letra, así la tipografía no se descompone. */
  .hero__meta a,.menu__meta a,.form__foot a,.rider a,.clip__mas small a{
    display:inline-block;padding-block:6px;
  }
  /* Listas de enlaces: el hueco de la rejilla pasa a ser padding del propio
     enlace, así el área táctil crece sin que la lista se estire. */
  .ftr__nav{gap:0}
  .ftr__nav a{display:block;padding-block:11px}
  .ftr__legal{gap:0 var(--space-4)}
  .ftr__legal a{display:inline-block;padding-block:11px}
  .ftr__contact a{padding-block:10px}
  .dates__cta{display:inline-block;padding-block:10px}
}

/* =========================================================================
   Breakpoints. Tres. Ni uno más.
   ========================================================================= */
@media (min-width:480px){
  .form__pair{grid-template-columns:1fr 1fr;gap:var(--space-3)}
  .ftr__bot{grid-template-columns:1fr auto;align-items:center}
}

@media (min-width:768px){
  html{scroll-padding-top:104px}
  .hdr__cta{display:inline-flex}

  /* Cabecera de sección 78/22 alineada a la misma línea base. */
  .sec__head{display:grid;grid-template-columns:1fr auto;gap:var(--space-4);align-items:end}
  .sec__meta{margin-top:0;text-align:right}

  /* Galería: rejilla de 12 columnas y tres proporciones.
     Los tramos están elegidos para que las filas casen sin huecos:
     span-3 a 3/4 y span-6 a 3/2 dan la misma altura; tres span-4 a 1/1 también. */
  .gal{grid-template-columns:repeat(12,1fr)}
  .gal__i{grid-column:span 3}
  .gal__i--wide{grid-column:span 6}
  .gal__i--wide img{aspect-ratio:3/2}
  .gal__i--port{grid-column:span 4}
  .gal__i--port img{aspect-ratio:1}

  .stats{grid-template-columns:1fr 1fr}
  .empty{padding:var(--space-7) var(--space-6)}
  .ftr__top{grid-template-columns:1.3fr 1fr 1fr}
}

@media (min-width:1024px){
  /* Repartos medidos en foxxel: 51,2/48,8 · 47,5/52,5 · 53,5/46,5
     Gap de columna 66px contra los 72px de foxxel (−8 %, dentro de tolerancia);
     el de fila se queda en space-7 porque en móvil apilado foxxel medía 60px. */
  .split{grid-template-columns:1.05fr 1fr;gap:var(--space-7) var(--space-6)}
  .split--music{grid-template-columns:1fr 1.1fr;align-items:stretch}
  /* stretch, no min-height: el panel iguala la altura de su hermana, que la
     decide su contenido. Sin esto quedaban 380px de vacío a la derecha. */
  .facade--audio{align-content:center}
  .split--booking{grid-template-columns:1.15fr 1fr}
  .lead{max-width:34ch}
}

/* =========================================================================
   Reducir movimiento. Global, no siete selectores.
   ========================================================================= */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  /* Tiene que cubrir a los HIJOS, no sólo al bloque: la opacidad vive en
     [data-reveal]>* desde que la entrada se escalona. Cubrir sólo el padre deja
     14 elementos invisibles con "reducir movimiento" activo — medido. */
  [data-reveal],[data-reveal]>*{opacity:1!important;transform:none!important;transition:none!important}
  .sec__title{animation:none!important;color:var(--fg)!important}
  *,*::before,*::after{
    animation-duration:.01ms!important;animation-iteration-count:1!important;
    transition-duration:.01ms!important;scroll-behavior:auto!important;
  }
  .marquee__track{animation:none;transform:none}
}
