/* SPACE — SPORTS & LIVE EXPERIENCES
   sections.css · v1
   Bloques de seccion de las 6 paginas + los estados de animacion.
   CONTRATO DE VISIBILIDAD: el estado por defecto de TODO es visible. Los
   estados iniciales de animacion viven SOLO detras de `.js-anim` en el <html>.
   Sin JS (o con JS roto) no hay nada oculto. */

/* 1. SECTION-HEAD */

.section-head{
  display: grid;
  gap: var(--sp-4);
  margin-block-end: var(--gap-lg);
  max-width: 46rem;
}

.section-head__title{
  font-family: var(--ff-display);
  font-size: var(--fs-h1);
  font-weight: var(--fw-bold);
  line-height: var(--lh-h1);
  letter-spacing: var(--tr-h);
  color: var(--fg);
  text-wrap: balance;
}

.section-head__text{
  font-size: var(--fs-lead);
  line-height: var(--lh-lead);
  color: var(--fg-dim);
  max-width: var(--measure);
}

/* Titular a la izquierda, texto a la derecha */
.section-head--split{ max-width: none; align-items: end; }
@media (min-width: 900px){
  .section-head--split{
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--gap-lg);
  }
  .section-head--split .eyebrow{ grid-column: 1 / -1; }
}

/* 2. HERO — texto a la izquierda, panel cortado a la derecha */

.hero{
  position: relative;
  isolation: isolate;
  display: grid;
  align-items: center;
  min-height: 640px;
  padding-block: calc(var(--nav-h) + var(--sp-8)) var(--section-y-tight);
  background: var(--bg);
  overflow: clip;

  /* Distancia real del borde del viewport a la primera letra. El wrap se
     centra, asi que por encima de --wrap hay margen extra que hay que
     descontar; por debajo manda el gutter. */
  --hero-inset: max(var(--gutter), calc((100vw - var(--wrap)) / 2 + var(--gutter)));
  /* Canal libre que se reserva entre la ultima letra y la imagen. */
  --hero-channel: clamp(2.5rem, 5vw, 5.5rem);
}

@supports (height: 100svh){
  .hero{ min-height: clamp(600px, 88svh, 1040px); }
}

.hero__inner{
  position: relative;
  z-index: var(--z-content);
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.hero__content{
  display: grid;
  justify-items: start;
  gap: var(--sp-5);
  max-width: 40rem;
}

.hero__kicker{
  font-family: var(--ff-display);
  font-size: var(--fs-h3);
  font-weight: var(--fw-semi);
  line-height: var(--lh-h3);
  letter-spacing: var(--tr-h3);
  color: var(--fg-soft);
}

.hero__title{
  font-family: var(--ff-display);
  font-size: var(--fs-h1);
  font-weight: var(--fw-black);
  line-height: var(--lh-h1);
  letter-spacing: var(--tr-h);
  color: var(--fg);
  text-wrap: balance;
  overflow-wrap: break-word;
}

/* Solo el hub llega al tamano mega */
.hero--full .hero__title,
.hero__title--mega{
  font-size: var(--fs-mega);
  line-height: var(--lh-mega);
  letter-spacing: var(--tr-mega);
}

.hero__title-accent{ color: var(--accent); }

.hero__lead{
  font-size: var(--fs-lead);
  line-height: var(--lh-lead);
  color: var(--fg-dim);
  max-width: var(--measure);
}

.hero__actions{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap);
  margin-block-start: var(--sp-3);
}

.hero__meta{
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5) var(--gap-lg);
  margin-block-start: var(--sp-5);
  padding-block-start: var(--sp-5);
  border-top: var(--bw) solid var(--hairline);
  width: 100%;
}

/* Numero de vertical (01..05) en la esquina del hero */
.hero__index{
  font-family: var(--ff-display);
  font-size: var(--fs-index);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tr-label);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

/* Panel de imagen: en movil va debajo, a sangre y con el corte horizontal */
.hero__media{
  position: relative;
  z-index: var(--z-media);
  width: 100vw;
  max-width: 100vw;
  margin-inline: calc(50% - 50vw);
  margin-block-start: var(--sp-7);
  aspect-ratio: 16 / 11;
  background: var(--surface);
}

.hero__media img,
.hero__media video{
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Velo: el texto sobre foto tiene que pasar AA */
.hero__scrim{
  position: absolute;
  inset: 0;
  z-index: var(--z-media);
  background: var(--ink);
  opacity: var(--scrim-op);
  pointer-events: none;
}

/* Panel oscuro cortado del hub, sobre la fotografia */
.hero__panel{
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  z-index: var(--z-media);
  width: 100%;
  background: var(--ink);
  opacity: 0.82;
  pointer-events: none;
}

/* Isotipo como marca de agua. Nunca un "orbe" flotante. */
.hero__mark{
  position: absolute;
  z-index: var(--z-base);
  inset-block-start: 50%;
  inset-inline-end: -6%;
  width: min(52vw, 620px);
  height: auto;
  transform: translateY(-50%);
  opacity: var(--mask-op);
  pointer-events: none;
  user-select: none;
}

/* Pista de scroll ESTATICA: nada se mueve con la pagina quieta */
.hero__scroll{
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  margin-block-start: var(--sp-6);
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: var(--fw-med);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--fg-mute);
}
.hero__scroll::after{
  content: "";
  width: 44px;
  height: var(--bw);
  background: var(--accent);
}

@media (min-width: 900px){
  /* ANCHO DEL TEXTO: se corta donde empieza la imagen, MENOS el canal.
     Antes era `min(52%, 44rem)` medido contra .hero__inner (tope 1440px)
     mientras la imagen es el 54% de .hero (el viewport entero). Dos
     porcentajes contra cajas distintas: medido a 1280px la caja de texto
     se metia 74px DENTRO de la imagen, y solo no se pisaban por el corte
     diagonal y por donde caian los saltos de linea — el titulo quedaba a
     3px de la foto. Ahora se mide todo contra el viewport, como la imagen. */
  .hero__content{
    max-width: min(
      44rem,
      calc(46vw - var(--hero-channel) - var(--hero-inset))
    );
  }

  .hero__media{
    position: absolute;
    inset-block: 0;
    inset-inline-end: 0;
    width: 54%;
    margin: 0;
    aspect-ratio: auto;
    height: 100%;
  }
}

/* --- hero--full: imagen a sangre completa con el corte encima (hub) --- */

.hero--full{ padding-block-end: var(--section-y-tight); }

.hero--full .hero__media{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  aspect-ratio: auto;
  z-index: var(--z-base);
  clip-path: none;
}

/* En el hub la imagen va a sangre y el borde no es un corte duro sino el
   degradado del velo (opaco hasta el 32%, ya translucido al 58%). El texto
   se queda dentro de la parte opaca con margen, en vez de morir encima de
   la zona donde la foto ya se ve. Mismo criterio que .hero--cut: se mide
   contra el viewport. Por debajo de 900px lo anula el bloque de movil. */
.hero--full .hero__content{
  max-width: min(
    56rem,
    calc(52vw - var(--hero-channel) - var(--hero-inset))
  );
}

@media (max-width: 899.98px){
  .hero--full .hero__content{ max-width: none; }
  .hero--full .hero__panel{ opacity: 0.86; }
}

@media (min-width: 900px){
  .hero--full .hero__panel{ width: 78%; }
}

/* 3. OVERVIEW — titular + entrada + cifras */

.overview{
  position: relative;
  padding-block: var(--section-y);
  background: var(--bg);
  border-top: var(--bw) solid var(--hairline);
}

.overview__grid{
  display: grid;
  gap: var(--gap-lg);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

@media (min-width: 900px){
  .overview__grid{ grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
}

.overview__title{
  font-family: var(--ff-display);
  font-size: var(--fs-h1);
  font-weight: var(--fw-bold);
  line-height: var(--lh-h1);
  letter-spacing: var(--tr-h);
  color: var(--fg);
  text-wrap: balance;
}

.overview__text{
  font-size: var(--fs-lead);
  line-height: var(--lh-lead);
  color: var(--fg-dim);
  max-width: var(--measure);
}

.overview__aside{ display: grid; gap: var(--gap); }

.overview__stats{
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap) var(--gap-lg);
  margin-block-start: var(--sp-6);
  padding-block-start: var(--sp-6);
  border-top: var(--bw) solid var(--hairline);
}

.overview__media{
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--surface);
}
.overview__media img{ width: 100%; height: 100%; object-fit: cover; }

/* 4. VERTICALS — los 5 accesos del hub. Rejilla de 6 columnas: 3 arriba de
   2 columnas y 2 abajo de 3. */

.verticals{
  display: grid;
  gap: var(--bw);
  grid-template-columns: minmax(0, 1fr);
  background: var(--hairline);
  border-block: var(--bw) solid var(--hairline);
  list-style: none;
  padding: 0;
  margin: 0;
}

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

@media (min-width: 1100px){
  .verticals{ grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .verticals > *:nth-child(-n+3){ grid-column: span 2; }
  .verticals > *:nth-child(n+4){ grid-column: span 3; }
}

.verticals__item{
  position: relative;
  display: grid;
  align-content: start;
  gap: var(--sp-3);
  min-height: clamp(15rem, 26vw, 21rem);
  padding: var(--sp-6) var(--sp-5) var(--sp-7);
  background: var(--bg);
  transition: background-color var(--d-mid) var(--ease);
  overflow: hidden;
}

.verticals__item:hover,
.verticals__item:focus-visible{ background: var(--surface); }

/* Hairline superior teal que se dibuja al entrar */
.verticals__item::before{
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  height: var(--bw-thick);
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--d-slow) var(--ease);
}
.verticals__item:hover::before,
.verticals__item:focus-visible::before{ transform: scaleX(1); }

.verticals__num{
  font-family: var(--ff-display);
  font-size: var(--fs-index);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tr-label);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.verticals__title{
  font-family: var(--ff-display);
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  line-height: var(--lh-h2);
  letter-spacing: var(--tr-h);
  color: var(--fg);
}

.verticals__text{
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--fg-dim);
  max-width: var(--measure-sm);
}

.verticals__arrow{
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  margin-block-start: var(--sp-4);
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: var(--fw-med);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--fg-mute);
  transition: color var(--d-fast) var(--ease);
}
.verticals__arrow::after{
  content: "";
  width: 2rem;
  height: var(--bw);
  background: currentColor;
  transition: transform var(--d-mid) var(--ease);
  transform-origin: left center;
}
.verticals__item:hover .verticals__arrow,
.verticals__item:focus-visible .verticals__arrow{ color: var(--accent); }
.verticals__item:hover .verticals__arrow::after{ transform: scaleX(1.4); }

/* 5. BAND — scroll horizontal del hub (solo index.html)
   Por defecto: APILADO VERTICAL y visible. El horizontal lo enciende motion.js
   con `.is-horizontal`, solo si viewport >= 900px y sin `prefers-reduced-motion`. */

.band{
  position: relative;
  background: var(--bg-2);
  border-top: var(--bw) solid var(--hairline);
}

.band__head{ padding-block: var(--section-y-tight); }

.band__viewport{ position: relative; width: 100%; }

.band__track{
  display: grid;
  gap: var(--bw);
  background: var(--hairline);
}

.band__panel{
  position: relative;
  display: grid;
  align-content: end;
  gap: var(--sp-4);
  min-height: clamp(20rem, 52vw, 34rem);
  padding: var(--sp-7) var(--gutter);
  background: var(--bg-2);
  overflow: hidden;
}

.band__panel-media{
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
}
.band__panel-media img{ width: 100%; height: 100%; object-fit: cover; }
.band__panel-media::after{
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: var(--scrim-op);
}

.band__panel > :not(.band__panel-media){ position: relative; z-index: var(--z-content); }

.band__panel-index{
  font-family: var(--ff-display);
  font-size: var(--fs-index);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tr-label);
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.band__panel-title{
  font-family: var(--ff-display);
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  line-height: var(--lh-h2);
  letter-spacing: var(--tr-h);
  color: var(--fg);
}

.band__panel-text{
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--fg-dim);
  max-width: var(--measure-sm);
}

.band__progress{
  position: relative;
  height: var(--bw);
  margin-inline: var(--gutter);
  margin-block: var(--sp-6);
  background: var(--hairline);
  overflow: hidden;
}
.band__progress-bar{
  display: block;
  height: 100%;
  background: var(--accent);
  transform: scaleX(var(--band-p, 0));
  transform-origin: left center;
}

/* 6. CTA-STRIP — franja de cierre */

.cta-strip{
  position: relative;
  isolation: isolate;
  overflow: clip;
  padding-block: var(--section-y);
  background: var(--accent-bg-deep);
  border-top: var(--bw) solid var(--hairline);
}

.cta-strip__media{
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  z-index: var(--z-base);
  width: 100%;
}
.cta-strip__media img{ width: 100%; height: 100%; object-fit: cover; }
.cta-strip__media::after{
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: var(--scrim-op);
}

.cta-strip__inner{
  position: relative;
  z-index: var(--z-content);
  display: grid;
  gap: var(--sp-6);
  justify-items: start;
}

.cta-strip__title{
  font-family: var(--ff-display);
  font-size: var(--fs-h1);
  font-weight: var(--fw-black);
  line-height: var(--lh-h1);
  letter-spacing: var(--tr-h);
  text-transform: uppercase;
  color: var(--fg);
  max-width: 18ch;
}

.cta-strip__text{
  font-size: var(--fs-lead);
  line-height: var(--lh-lead);
  color: var(--fg-dim);
  max-width: var(--measure);
}

.cta-strip__actions{
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap);
}

@media (min-width: 900px){
  .cta-strip__media{ width: 52%; }
  .cta-strip__inner{ max-width: 52%; }
}

/* 7. CONTACT-SECTION — envuelve al formulario */

.contact-section{
  position: relative;
  padding-block: var(--section-y);
  background: var(--bg-2);
  border-top: var(--bw) solid var(--hairline);
}

.contact-section__grid{
  display: grid;
  gap: var(--gap-lg);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}

@media (min-width: 900px){
  .contact-section__grid{ grid-template-columns: minmax(0, 4fr) minmax(0, 6fr); }
}

.contact-section__intro{ display: grid; gap: var(--sp-5); align-content: start; }

.contact-section__title{
  font-family: var(--ff-display);
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  line-height: var(--lh-h2);
  letter-spacing: var(--tr-h);
  color: var(--fg);
}

.contact-section__meta{
  display: grid;
  gap: var(--sp-3);
  padding-block-start: var(--sp-5);
  border-top: var(--bw) solid var(--hairline);
  font-size: var(--fs-label);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--fg-mute);
  font-style: normal;
}

/* 8. ESTADOS DE ANIMACION — todos detras de `.js-anim`
   Sin `.js-anim` en el <html> no se aplica NADA de esto y todo se ve.
   Es el contrato de visibilidad del SPEC §5.2.1. */

/* --- reveal: entrada escalonada, delay por --i (maximo 6 por grupo) --- */
.js-anim .reveal{
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity var(--d-in) var(--ease),
    transform var(--d-in) var(--ease);
  transition-delay: calc(var(--i, 0) * var(--stagger));
}
.js-anim .reveal.is-in{ opacity: 1; transform: none; }

.js-anim .reveal--left{ transform: translateX(-24px); }
.js-anim .reveal--right{ transform: translateX(24px); }
.js-anim .reveal--flat{ transform: none; }

/* Revelado por corte: la mascara se abre en el sentido del cut */
.js-anim .reveal--cut{
  opacity: 1;
  transform: none;
  clip-path: inset(0 100% 0 0);
  transition: clip-path var(--d-slow) var(--ease-cut);
  will-change: clip-path;
}
.js-anim .reveal--cut.is-in{ clip-path: inset(0 0 0 0); will-change: auto; }

/* --- split-in: el titular entra en dos mitades que se ensamblan --- */
.split{ display: block; position: relative; }
.split__a,
.split__b{ display: block; }

.js-anim .split__a{
  opacity: 0;
  transform: translateX(-6%);
  transition: opacity var(--d-slow) var(--ease), transform var(--d-slow) var(--ease);
}
.js-anim .split__b{
  opacity: 0;
  transform: translateX(6%);
  transition: opacity var(--d-slow) var(--ease), transform var(--d-slow) var(--ease);
  transition-delay: 80ms;
}
.js-anim .split.is-in .split__a,
.js-anim .split.is-in .split__b{ opacity: 1; transform: none; }

/* --- hero-cut: el corte se abre con el scroll. motion.js escribe --cut-p
   (0..1) en el .hero; con 0 (el valor del token) el panel se ve entero. --- */
.js-anim .hero--cut .hero__media{
  --cut-x: calc(clamp(2.5rem, 9vw, 9.5rem) * (1 - var(--cut-p, 0)));
  will-change: clip-path;
}
.js-anim .hero--cut.is-settled .hero__media{ will-change: auto; }

/* --- parallax suave: solo transform, valor en px escrito por motion.js --- */
.js-anim .parallax{
  transform: translate3d(0, var(--py, 0px), 0);
  will-change: transform;
}

/* --- draw: trazo SVG de telemetria. Base = trazo completo visible --- */
.js-anim .draw{
  stroke-dasharray: var(--len, 1200);
  stroke-dashoffset: var(--len, 1200);
  transition: stroke-dashoffset var(--d-draw) var(--ease-cut);
}
.js-anim .draw.is-in{ stroke-dashoffset: 0; }

/* --- count-up: el numero final esta en el HTML, el JS solo lo anima --- */
.count-up{ font-variant-numeric: tabular-nums; }

/* --- band en horizontal: lo enciende motion.js --- */
.js-anim .band.is-horizontal{ height: calc(var(--band-count, 5) * 92vh); }
.js-anim .band.is-horizontal .band__viewport{
  position: sticky;
  inset-block-start: 0;
  height: 100vh;
  display: flex;
  align-items: stretch;
  overflow: hidden;
}
.js-anim .band.is-horizontal .band__track{
  display: flex;
  gap: var(--bw);
  height: 100%;
  transform: translate3d(calc(-1 * var(--band-x, 0px)), 0, 0);
  will-change: transform;
}
.js-anim .band.is-horizontal .band__panel{
  flex: 0 0 clamp(24rem, 42vw, 44rem);
  height: 100%;
  min-height: 0;
  align-content: end;
}

@supports (height: 100svh){
  .js-anim .band.is-horizontal .band__viewport{ height: 100svh; }
}

/* 9. ANULACIONES — el hub cae a vertical (SPEC §5.3 y §11.3) */

@media (max-width: 899.98px){
  .js-anim .band.is-horizontal{ height: auto; }
  .js-anim .band.is-horizontal .band__viewport{ position: static; height: auto; overflow: visible; display: block; }
  .js-anim .band.is-horizontal .band__track{ display: grid; transform: none; will-change: auto; }
  .js-anim .band.is-horizontal .band__panel{ flex: none; height: auto; min-height: clamp(20rem, 52vw, 34rem); }
}

@media (prefers-reduced-motion: reduce){
  .js-anim .reveal,
  .js-anim .reveal--cut,
  .js-anim .reveal--left,
  .js-anim .reveal--right,
  .js-anim .split__a,
  .js-anim .split__b,
  .js-anim .parallax{
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    visibility: visible !important;
    will-change: auto !important;
  }

  .js-anim .draw{
    stroke-dasharray: none !important;
    stroke-dashoffset: 0 !important;
  }

  .js-anim .hero--cut .hero__media{ will-change: auto !important; }

  .js-anim .band.is-horizontal{ height: auto !important; }
  .js-anim .band.is-horizontal .band__viewport{
    position: static !important;
    height: auto !important;
    overflow: visible !important;
    display: block !important;
  }
  .js-anim .band.is-horizontal .band__track{
    display: grid !important;
    transform: none !important;
    will-change: auto !important;
  }
  .js-anim .band.is-horizontal .band__panel{
    flex: none !important;
    height: auto !important;
    min-height: clamp(20rem, 52vw, 34rem);
  }
}

/* ==================================================================
   9. PIEZAS PROPIAS DE CADA VERTICAL
   El sitio actual de SPACE repite la misma plantilla en las 5 paginas.
   Estos bloques existen para que aqui NO pase: cada vertical tiene una
   pieza visual que solo aparece en su pagina. Sin colores nuevos:
   todo sale de los tokens.
   ================================================================== */

/* --- 9.1 SALESBOARD (Ticketing) — panel de control en HTML/CSS puro.
   No es una captura de software: son barras y cifras reales del marcado. --- */
.salesboard{
  display: grid;
  gap: var(--sp-6);
  padding: clamp(var(--sp-5), 3vw, var(--sp-8));
  background: var(--surface);
  border: var(--bw) solid var(--hairline);
  border-inline-start: var(--bw-thick) solid var(--accent);
}
.salesboard__head{
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-5);
  align-items: baseline;
  justify-content: space-between;
  padding-bottom: var(--sp-4);
  border-bottom: var(--bw) solid var(--hairline);
}
.salesboard__title{
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: var(--fw-med);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--fg-mute);
}
.salesboard__live{
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-label);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--accent);
}
.salesboard__live::before{
  content: "";
  inline-size: 7px;
  block-size: 7px;
  border-radius: var(--r-round);
  background: var(--accent);
}
.salesboard__rows{ display: grid; gap: var(--sp-5); }
.salesboard__row{ display: grid; gap: var(--sp-2); }
.salesboard__meta{
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-4);
  font-size: var(--fs-small);
  color: var(--fg-dim);
}
.salesboard__meta b{ font-weight: var(--fw-med); color: var(--fg); }
.salesboard__bar{
  block-size: 6px;
  background: var(--bg-2);
  overflow: hidden;
}
.salesboard__fill{
  display: block;
  block-size: 100%;
  inline-size: var(--p, 50%);
  background: var(--accent-deep);
}
.salesboard__row--peak .salesboard__fill{ background: var(--accent); }
.salesboard__foot{
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  padding-top: var(--sp-5);
  border-top: var(--bw) solid var(--hairline);
}

/* --- 9.2 TIMELINE (Sports Experiences) — de la llegada a la salida --- */
.timeline{
  display: grid;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: tl;
}
.timeline__item{
  position: relative;
  display: grid;
  gap: var(--sp-2);
  padding: clamp(var(--sp-5), 3vw, var(--sp-7)) 0 clamp(var(--sp-5), 3vw, var(--sp-7)) clamp(var(--sp-6), 6vw, var(--sp-9));
  border-top: var(--bw) solid var(--hairline);
}
.timeline__item:last-child{ border-bottom: var(--bw) solid var(--hairline); }
/* La linea de recorrido: un hairline vertical con el nodo encima. */
.timeline__item::before{
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: clamp(var(--sp-2), 1.6vw, var(--sp-4));
  inline-size: var(--bw);
  background: var(--hairline);
}
.timeline__item:first-child::before{ inset-block-start: 50%; }
.timeline__item:last-child::before{ inset-block-end: 50%; }
.timeline__item::after{
  content: "";
  position: absolute;
  inset-block-start: calc(50% - 4px);
  inset-inline-start: calc(clamp(var(--sp-2), 1.6vw, var(--sp-4)) - 3px);
  inline-size: 7px;
  block-size: 7px;
  background: var(--accent);
}
.timeline__step{
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: var(--fw-med);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--accent);
}
.timeline__title{
  font-family: var(--ff-display);
  font-size: var(--fs-h3);
  font-weight: var(--fw-semi);
  line-height: var(--lh-h3);
  color: var(--fg);
}
.timeline__text{ max-inline-size: var(--measure-sm); color: var(--fg-dim); }

/* --- 9.3 TELEMETRY (Motorsport Training) — traza que se dibuja sola.
   Sin etiquetas numericas: no tenemos datos reales y no se inventan. --- */
.telemetry{
  display: grid;
  gap: var(--sp-4);
  padding: clamp(var(--sp-5), 3vw, var(--sp-7));
  background: var(--bg-2);
  border: var(--bw) solid var(--hairline);
}
.telemetry__svg{
  display: block;
  inline-size: 100%;
  block-size: auto;
  overflow: visible;
}
.telemetry__grid{ stroke: var(--hairline); stroke-width: 1; }
.telemetry__trace{ stroke: var(--accent); stroke-width: 2; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.telemetry__trace--ghost{ stroke: var(--accent-deep); stroke-width: 1.5; }
.telemetry__axis{
  display: flex;
  justify-content: space-between;
  gap: var(--sp-4);
  font-size: var(--fs-label);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--fg-mute);
}
.telemetry__legend{
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
  font-size: var(--fs-small);
  color: var(--fg-dim);
}
.telemetry__key{ display: inline-flex; align-items: center; gap: var(--sp-2); }
.telemetry__swatch{ inline-size: 18px; block-size: 2px; background: var(--accent); }
.telemetry__swatch--ghost{ background: var(--accent-deep); }

/* --- 9.4 FIGURE-WIDE — respiro visual a todo el ancho.
   Lo usan las paginas donde la imagen manda (Hospitality sobre todo). --- */
.figure-wide{ position: relative; margin: 0; }
.figure-wide img{
  display: block;
  inline-size: 100%;
  block-size: clamp(18rem, 56vh, 40rem);
  object-fit: cover;
}
.figure-wide__caption{
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-5);
  padding: var(--sp-4) var(--gutter);
  font-size: var(--fs-label);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--fg);
  background: linear-gradient(to top, var(--ink), transparent);
  inline-size: 100%;
}
.figure-wide__caption span:first-child{ color: var(--accent); }

/* --- 9.5 CROSSLINKS — navegacion entre verticales al pie de cada pagina --- */
.crosslinks{
  display: grid;
  gap: 0;
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: var(--bw) solid var(--hairline);
}
.crosslinks__link{
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-3) var(--sp-5);
  padding-block: clamp(var(--sp-4), 2.4vw, var(--sp-6));
  border-bottom: var(--bw) solid var(--hairline);
  color: var(--fg);
  text-decoration: none;
  transition: color var(--d-fast) var(--ease), padding-inline-start var(--d-fast) var(--ease);
}
.crosslinks__link:hover,
.crosslinks__link:focus-visible{ color: var(--accent); padding-inline-start: var(--sp-4); }
.crosslinks__num{
  font-size: var(--fs-label);
  letter-spacing: var(--tr-label);
  color: var(--accent);
  min-inline-size: 2.5rem;
}
.crosslinks__title{
  font-family: var(--ff-display);
  font-size: var(--fs-h3);
  font-weight: var(--fw-semi);
}
.crosslinks__text{ margin-inline-start: auto; color: var(--fg-mute); font-size: var(--fs-small); }

@media (prefers-reduced-motion: reduce){
  .crosslinks__link{ transition: none; }
  .crosslinks__link:hover,
  .crosslinks__link:focus-visible{ padding-inline-start: 0; }
}

/* ==================================================================
   10. CORRECCIONES VERIFICADAS EN NAVEGADOR
   Cada bloque de aqui responde a un defecto que se vio en pantalla,
   no a una suposicion. Se anota que se midio.
   ================================================================== */

/* 10.1 La barra de progreso de la banda quedaba al final de un bloque de
   3510px de alto: no se veia nunca mientras se recorria la banda.
   Con sticky se ancla al borde inferior de la ventana mientras la banda
   esta en pantalla. Solo en modo horizontal; apilada no tiene sentido. */
.js-anim .band.is-horizontal .band__progress{
  position: sticky;
  inset-block-end: var(--sp-6);
  z-index: var(--z-content);
  margin-block: calc(-1 * var(--sp-6)) var(--sp-6);
}
.band:not(.is-horizontal) .band__progress{ display: none; }

/* 10.2 El velo uniforme del hero del hub no bastaba: el titular a gran
   tamano se apoya sobre la parte izquierda de la foto. Se oscurece ese
   lado y se deja limpio el derecho, que es donde manda la imagen.
   Es un velo de legibilidad sobre FOTO, no un degradado sobre texto. */
.hero--full .hero__scrim{
  background: linear-gradient(
    100deg,
    var(--ink) 0%,
    var(--ink) 32%,
    color-mix(in srgb, var(--ink) 70%, transparent) 58%,
    color-mix(in srgb, var(--ink) 25%, transparent) 100%
  );
  opacity: 0.92;
}
@supports not (color: color-mix(in srgb, red, blue)){
  .hero--full .hero__scrim{ background: var(--ink); opacity: var(--scrim-op); }
}

/* 10.3 Los paneles de la banda necesitan velo propio: el titular va
   encima de la fotografia y sin esto se pierde con imagenes claras. */
.band__panel-media::after{
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, var(--ink) 4%, color-mix(in srgb, var(--ink) 10%, transparent) 62%);
  pointer-events: none;
}
@supports not (color: color-mix(in srgb, red, blue)){
  .band__panel-media::after{ background: linear-gradient(to top, var(--ink), transparent 62%); }
}

/* 10.4 CONTRASTE MEDIDO: --accent-deep (#0F6073) sobre negro da 2.85:1.
   Para una hairline decorativa vale, pero la traza fantasma de la telemetria
   y las barras del panel de ventas SON informacion: necesitan 3:1 minimo.
   --teal-500 sobre negro da 5.0:1. Medido, no estimado. */
.telemetry__trace--ghost{ stroke: var(--teal-500); }
.telemetry__swatch--ghost{ background: var(--teal-500); }
.salesboard__fill{ background: var(--teal-500); }

/* ==================================================================
   11. MOVIL — revision dedicada
   Todo lo de aqui sale de medir el sitio a 390px en un navegador real,
   no de suponer. Cada bloque anota que estaba mal.
   ================================================================== */

@media (max-width: 899.98px){

  /* 11.1 EL VELO DEL HERO TAPABA LA FOTO ENTERA.
     El degradado a 100deg estaba calibrado para escritorio, donde el texto
     ocupa el 60% izquierdo. A 390px de ancho el texto va de borde a borde,
     asi que ese mismo velo dejaba el hero en negro absoluto: no se veia
     ninguna imagen. En movil el velo pasa a VERTICAL: oscuro arriba, donde
     va el texto, y limpio abajo, donde manda la fotografia. */
  .hero--full .hero__scrim{
    background: linear-gradient(
      to bottom,
      color-mix(in srgb, var(--ink) 94%, transparent) 0%,
      color-mix(in srgb, var(--ink) 80%, transparent) 40%,
      color-mix(in srgb, var(--ink) 28%, transparent) 74%,
      color-mix(in srgb, var(--ink) 70%, transparent) 100%
    );
    opacity: 1;
  }
  @supports not (color: color-mix(in srgb, red, blue)){
    .hero--full .hero__scrim{
      background: linear-gradient(to bottom, var(--ink), transparent 74%, var(--ink));
      opacity: 0.9;
    }
  }
  .hero--full{ align-items: start; }
  .hero--full .hero__inner{ padding-block-start: var(--sp-6); }

  /* 11.2 LOGO DEL HEADER: centrado y mas grande.
     Estaba a 34px arrinconado a la izquierda y no se leia. Ahora la marca
     se saca del flujo y se centra; el boton de menu se queda a la derecha. */
  .nav__inner{
    position: relative;
    justify-content: flex-end;
    padding-inline: var(--gutter);
  }
  .nav__brand{
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 50%;
    transform: translateX(-50%);
    width: var(--brand-w-m);
    padding-inline: var(--sp-3);
  }
  .nav__logo{ height: var(--logo-h-m); }
  .nav.is-stuck .nav__logo{ height: calc(var(--logo-h-m) * 0.72); }
  .nav__toggle{ margin-inline-start: 0; }

  /* 11.3 OBJETIVOS TACTILES.
     Medido: los enlaces del menu movil tenian 31px de alto y los del pie 23px.
     El minimo comodo es 44px. */
  .nav__drawer-link{
    align-items: center;
    min-block-size: 56px;
    padding-block: var(--sp-4);
  }
  .footer__link{
    display: block;
    padding-block: var(--sp-3);
    min-block-size: 44px;
  }
  .footer__nav li + li{ border-top: var(--bw) solid var(--hairline); }
  .footer__social-link{ min-inline-size: 44px; min-block-size: 44px; }

  /* 11.4 LA LISTA DE VERTICALES SE VEIA DESALINEADA.
     `.crosslinks__text` lleva `margin-inline-start:auto`, que en escritorio
     manda la descripcion al margen derecho. En movil eso dejaba cada fila
     con el titulo a la izquierda y la descripcion pegada a la derecha,
     en zigzag. Aqui se apila todo contra el mismo margen. */
  .crosslinks__link{
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--sp-1) var(--sp-4);
    align-items: baseline;
  }
  .crosslinks__num{ grid-row: 1; grid-column: 1; min-inline-size: 0; }
  .crosslinks__title{ grid-row: 1; grid-column: 2; }
  .crosslinks__text{
    grid-row: 2;
    grid-column: 2;
    margin-inline-start: 0;
    text-align: start;
  }

  /* 11.5 LAS CIFRAS ROMPIAN 2 + 1.
     Con flex-wrap quedaban "05 04" arriba y "01" solo debajo, descolgado.
     Tres columnas iguales: leen como una sola unidad. */
  .stats,
  .overview__stats{
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--sp-4);
  }
  .stat{ padding-inline-start: var(--sp-3); }
  .stat__num{ font-size: clamp(1.75rem, 9vw, 2.75rem); }
  .stat__label{ font-size: 0.6875rem; }

  /* 11.6 RITMO VERTICAL.
     A 390px las paginas median entre 5.300 y 7.500px: demasiado desierto
     entre bloques. Se aprieta el aire sin tocar la jerarquia. */
  .band__panel{ min-block-size: clamp(19rem, 62vw, 26rem); }
  .figure-wide img{ block-size: clamp(14rem, 46vh, 22rem); }

  /* 11.7 La cinta debe leerse como cinta, no como texto cortado. */
  .marquee__item{ font-size: clamp(0.9375rem, 4.4vw, 1.25rem); }
}

/* ==================================================================
   12. HERO CINETICO — movimiento real, en movil tambien
   El hero admite video (assets/video/hero.mp4). La capa cinetica da el
   movimiento por si sola: destellos que recorren el hero por la MISMA
   diagonal de 19 grados de la marca, mas una deriva lenta de la imagen.
   Solo transform y opacity: todo en el compositor.

   No es un sistema de particulas: son cuatro barras deliberadas siguiendo
   la geometria del logo. Ver DESIGN.md §5.2.
   ================================================================== */

.hero__stage{
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
  overflow: clip;
}

/* La imagen es SIEMPRE el contenido visible. El video, si carga, se pone
   encima. Si el video falla o no existe, no se pierde nada de nada. */
.hero__stage img,
.hero__video{
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}
.hero__video{
  opacity: 0;
  transition: opacity var(--d-slow) var(--ease);
}
.hero__video.is-playing{ opacity: 1; }

/* Deriva lenta de la imagen: plano vivo sin necesidad de video. */
.js-anim .hero__stage img{
  animation: hero-drift 26s var(--ease) infinite alternate;
  transform-origin: 62% 45%;
}
@keyframes hero-drift{
  from{ transform: scale(1.03) translate3d(0, 0, 0); }
  to  { transform: scale(1.13) translate3d(-1.5%, -1.5%, 0); }
}

/* --- Destellos por la diagonal de la marca --- */
.hero__kinetic{
  position: absolute;
  inset: -25% -12%;
  z-index: var(--z-media);
  pointer-events: none;
  overflow: clip;
}
.hero__streak{
  position: absolute;
  inset-block: -12%;
  inline-size: clamp(2px, 0.35vw, 5px);
  background: linear-gradient(
    to bottom,
    transparent 0%,
    var(--accent) 38%,
    var(--accent-hi) 50%,
    var(--accent) 62%,
    transparent 100%
  );
  opacity: 0;
  transform: rotate(var(--cut-deg)) translate3d(0, -130%, 0);
  will-change: transform, opacity;
}

/* Cuatro destellos, cada uno con su carril, su ritmo y su retardo.
   Nada de aleatoriedad: carriles elegidos para que crucen el hero sin
   taparse entre si. */
.js-anim .hero__streak{ animation: streak var(--dur, 4.2s) linear var(--delay, 0s) infinite; }
.hero__streak:nth-child(1){ inset-inline-start: 18%; --dur: 4.6s; --delay: 0s;   }
.hero__streak:nth-child(2){ inset-inline-start: 46%; --dur: 6.2s; --delay: 1.4s; }
.hero__streak:nth-child(3){ inset-inline-start: 68%; --dur: 3.8s; --delay: 2.6s; }
.hero__streak:nth-child(4){ inset-inline-start: 88%; --dur: 5.4s; --delay: 0.7s; }

@keyframes streak{
  0%   { opacity: 0;    transform: rotate(var(--cut-deg)) translate3d(0, -130%, 0); }
  12%  { opacity: 0.85; }
  70%  { opacity: 0.5;  }
  100% { opacity: 0;    transform: rotate(var(--cut-deg)) translate3d(0, 130%, 0); }
}

/* Fuera de pantalla no se gasta ni un frame: motion.js quita .is-live. */
.hero__kinetic:not(.is-live) .hero__streak{ animation-play-state: paused; }
.hero__stage:not(.is-live) img{ animation-play-state: paused; }

/* En movil, menos destellos y mas finos: no deben competir con el texto. */
@media (max-width: 599.98px){
  .hero__streak:nth-child(3){ display: none; }
  .hero__streak{ inline-size: 2px; }
}

@media (prefers-reduced-motion: reduce){
  .js-anim .hero__stage img,
  .js-anim .hero__streak{ animation: none !important; }
  .js-anim .hero__stage img{ transform: none !important; }
  .hero__streak{ opacity: 0.25; transform: rotate(var(--cut-deg)) !important; }
  .hero__video{ opacity: 0 !important; }
}

/* 12.1 El enlace de cada panel de la banda medía 31px de alto: en movil
   eso obliga a apuntar a una linea de texto. Se estira sobre todo el panel
   sin cambiar el marcado ni la semantica del enlace. */
/* `.band__panel` YA es position:relative en el bloque 5, asi que el ::after
   se ancla al panel entero. OJO: no tocar el position de .band__panel-media,
   que es absolute:inset-0 a proposito — ponerlo en relative lo devuelve al
   flujo y duplica el alto de cada panel (medido: el hub paso de 5.944 a
   7.932px en movil). */
/* `.band__panel-title` era position:relative solo para apilarse sobre la
   imagen, pero eso hacia que el ::after se anclara al titulo (350x30) en vez
   de al panel (390x304). Como el panel es un grid, el titulo se apila igual
   con z-index sin necesitar posicionamiento. */
/* Se probo estirar un ::after del enlace sobre todo el panel, pero el
   navegador no devuelve el enlace al pulsar sobre un pseudo-elemento: el
   panel PARECERIA pulsable y no lo seria, que es peor que no hacerlo.
   Se agranda el area del propio enlace: 31px -> 46px, por encima del
   minimo comodo de 44. */
.band__panel-title a{ display: inline-block; padding-block: var(--sp-2); }

/* ==================================================================
   13. FORMULARIO DE CONTACTO — contraste y compactado
   Medido: los campos eran una hairline sobre negro, sin superficie, y la
   seccion ocupaba ~880px para cinco campos. No se veia donde pulsar.
   ================================================================== */

.contact__form{ gap: var(--sp-4); }
.contact__row{ gap: var(--sp-4); }

/* Superficie real: el campo deja de ser una linea y pasa a ser una caja.
   Sobre --ink-3 el texto blanco da 20:1 y el label 6:1. */
.contact__input,
.contact__select,
.contact__textarea{
  padding: var(--sp-3) var(--sp-4);
  background: var(--ink-3);
  border: var(--bw) solid var(--line);
  border-bottom-width: var(--bw);
  color: var(--fg);
  transition:
    border-color var(--d-fast) var(--ease),
    background-color var(--d-fast) var(--ease);
}
.contact__input:hover,
.contact__select:hover,
.contact__textarea:hover{ background: var(--ink-4); }

.contact__input:focus,
.contact__select:focus,
.contact__textarea:focus{
  background: var(--ink-4);
  border-color: var(--accent);
  outline: var(--bw-thick) solid var(--accent);
  outline-offset: 1px;
}

.contact__input::placeholder,
.contact__textarea::placeholder{ color: var(--paper-mute); }

/* El label sube de --fg-mute a --fg-dim: de 6.6:1 a 13.4:1 sobre negro. */
.contact__label{
  color: var(--fg-dim);
  margin-block-end: calc(var(--sp-1) * -1);
}

.contact__field{ gap: var(--sp-2); }

/* El textarea medía ~180px de alto. Con 4 filas basta y la seccion respira. */
.contact__textarea{ min-block-size: 7.5rem; resize: vertical; }

.contact__hint{ margin-block-start: calc(var(--sp-1) * -1); }

/* Estados: el error engorda el borde y lo pone en blanco puro (la marca no
   tiene rojo); el acierto marca el borde en teal. */
.contact__field.is-invalid .contact__input,
.contact__field.is-invalid .contact__select,
.contact__field.is-invalid .contact__textarea{
  border-color: var(--alert);
  border-width: var(--bw-thick);
}
.contact__field.is-valid .contact__input,
.contact__field.is-valid .contact__select,
.contact__field.is-valid .contact__textarea{ border-color: var(--ok); }

/* La columna izquierda quedaba medio vacia: se sube el bloque y se aprieta. */
.contact-section__grid{ align-items: start; }
.contact-section__intro{ position: sticky; inset-block-start: calc(var(--nav-h) + var(--sp-5)); }

@media (max-width: 899.98px){
  .contact-section__intro{ position: static; }
  .contact__form{ gap: var(--sp-3); }
  .contact__row{ gap: var(--sp-3); }
  .contact__textarea{ min-block-size: 6.5rem; }
}


/* ==================================================================
   14. ENTRADAS — mas presencia, en movil y en escritorio
   Antes solo 1 elemento del hub tenia entrada. El movimiento de entrada
   es lo que separa una pagina viva de un documento.
   Todo sigue detras de `.js-anim`: sin JS no hay nada oculto.
   ================================================================== */

/* Entrada de bloque: sube y aparece. Un pelo mas de recorrido que el
   reveal base, para que se note tambien en pantallas pequenas. */
.js-anim .reveal{ transform: translateY(28px); }

/* Variante para titulares: entra con la mascara abriendose por la
   diagonal, no con un fade. Es el lenguaje del sitio. */
/* OJO: el clip va en el HIJO, nunca en el elemento observado.
   Un clip-path de area cero hace que el propio IntersectionObserver deje de
   ver el elemento (Chrome calcula la interseccion DESPUES del clip), asi que
   la entrada no se dispara nunca y el contenido se queda oculto para siempre.
   Medido: 0 disparos sobre 5 elementos. */
.js-anim .reveal--wipe > *{
  display: block;
  clip-path: polygon(0 0, 0 0, 0 100%, 0 100%);
  transition: clip-path var(--d-slow) var(--ease-cut);
  transition-delay: calc(var(--i, 0) * var(--stagger));
  will-change: clip-path;
}
.js-anim .reveal--wipe.is-in > *{
  clip-path: polygon(0 0, 130% 0, 100% 100%, 0 100%);
  will-change: auto;
}

/* Media que entra desde su propio corte: la imagen se descubre en diagonal. */
/* Mismo motivo que en --wipe: el clip va en los hijos. */
.js-anim .reveal--media > *{
  clip-path: polygon(0 0, 0 0, 0 100%, 0 100%);
  transition: clip-path 900ms var(--ease-cut);
  transition-delay: calc(var(--i, 0) * var(--stagger));
  will-change: clip-path;
}
.js-anim .reveal--media.is-in > *{
  clip-path: polygon(0 0, 118% 0, 100% 100%, 0 100%);
  will-change: auto;
}

/* Filas de lista: entran desde la izquierda, escalonadas. Se lee como una
   cascada, que es justo lo que se quiere en la lista de verticales. */
.js-anim .reveal--row{
  opacity: 0;
  transform: translateX(-18px);
  transition:
    opacity var(--d-in) var(--ease),
    transform var(--d-in) var(--ease);
  transition-delay: calc(var(--i, 0) * 55ms);
}
.js-anim .reveal--row.is-in{ opacity: 1; transform: none; }

/* En movil el recorrido lateral se acorta: en 390px un desplazamiento de
   18px ya se nota y no arriesga desbordes. */
@media (max-width: 599.98px){
  .js-anim .reveal--row{ transform: translateX(-10px); }
  .js-anim .reveal{ transform: translateY(20px); }
}

@media (prefers-reduced-motion: reduce){
  .js-anim .reveal--row,
  .js-anim .reveal--wipe > *,
  .js-anim .reveal--media > *{
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
    transition: none !important;
  }
}


/* ==================================================================
   15. FRANJA DE CIERRE CON EL MISMO MOTOR DEL HERO
   La tarjeta "What's your next step" comparte video y destellos con el
   hero: es la misma marca abriendo y cerrando la pagina.
   ================================================================== */

/* OJO: `.cta-strip__media` es `position:absolute` en el bloque 6 a proposito.
   Ponerlo en `relative` lo devuelve al flujo y, como sus hijos son absolutos,
   se queda con ALTO CERO: la imagen y el video desaparecen. Es el mismo fallo
   que ya paso con `.band__panel-media`. Aqui solo se anade el recorte. */
.cta-strip__media{ overflow: clip; }
/* El velo plano heredado sobra: ahora hay uno radial propio (.cta-strip__scrim)
   pensado para un titular centrado. Los dos juntos dejaban la franja casi negra. */
.cta-strip__media::after{ display: none; }
.cta-strip__media .hero__stage{ position: absolute; inset: 0; }
.cta-strip__media .hero__kinetic{ inset: -30% -15%; }

/* Aqui los destellos son mas discretos: el titular manda. */
.cta-strip__media .hero__streak{ inline-size: 2px; opacity: 0; }
.js-anim .cta-strip__media .hero__streak{ animation-duration: calc(var(--dur, 4.2s) * 1.35); }

/* Velo propio: el titular va centrado, asi que se oscurece el centro. */
.cta-strip__scrim{
  position: absolute;
  inset: 0;
  z-index: var(--z-media);
  pointer-events: none;
  background: radial-gradient(
    120% 90% at 50% 50%,
    color-mix(in srgb, var(--ink) 78%, transparent) 0%,
    color-mix(in srgb, var(--ink) 55%, transparent) 55%,
    color-mix(in srgb, var(--ink) 88%, transparent) 100%
  );
}
@supports not (color: color-mix(in srgb, red, blue)){
  .cta-strip__scrim{ background: var(--ink); opacity: var(--scrim-op); }
}

/* ==================================================================
   16. LOGO DE ESCRITORIO — mas grande y con mas aire
   Estaba a 58px dentro de una barra de 96px y quedaba pequeno frente a
   los seis enlaces. El bloque de marca ya sobresale por debajo (la muesca),
   asi que admite un logo bastante mayor sin tocar el alto del nav.
   ================================================================== */
@media (min-width: 900px){
  .nav__brand{
    width: var(--brand-w-d);
    padding-inline: var(--sp-6);
  }
  .nav__logo{ height: var(--logo-h-d); }
  .nav.is-stuck .nav__logo{ height: calc(var(--logo-h-d) * 0.68); }

  /* Mas separacion entre la marca y el menu, y entre los propios enlaces. */
  .nav__inner{ gap: clamp(var(--sp-5), 3vw, var(--sp-8)); }
  .nav__list{ gap: clamp(var(--sp-4), 2vw, var(--sp-6)); }
}

/* Entre 900 y 1200px los seis enlaces + una marca grande van justos:
   se recorta el aire antes de que nada se solape. */
@media (min-width: 900px) and (max-width: 1199.98px){
  .nav__brand{ width: clamp(150px, 15vw, 190px); padding-inline: var(--sp-4); }
  .nav__logo{ height: clamp(38px, 4vw, 52px); }
  .nav__inner{ gap: var(--sp-4); }
  .nav__list{ gap: var(--sp-3); }
}

/* 13.1 Ajuste tras verlo en pantalla: con --ink-3 la caja del campo apenas
   se despegaba del fondo. Sube a --ink-4 y el borde a --line-2. Y se recorta
   el aire vertical: la seccion medía 880px para cinco campos. */
.contact__input,
.contact__select,
.contact__textarea{
  background: var(--ink-4);
  border-color: var(--field-border);
}
.contact__input:hover,
.contact__select:hover,
.contact__textarea:hover{ border-color: var(--fg-mute); }
.contact-section{ padding-block: var(--section-y-tight); }
.contact__textarea{ min-block-size: 6.5rem; }

/* ==================================================================
   17. SHEEN — reflejo de entrada sobre las tarjetas con imagen
   Un destello cruza la tarjeta por la diagonal de 19 grados cuando entra
   en pantalla. UNA sola pasada: no es un brillo permanente. Es el mismo
   gesto del isotipo facetado del logo cuando le da la luz.

   Reglas que cumple:
   - El destello es un ::after: no toca la caja del elemento observado, asi
     que no interfiere con el IntersectionObserver (ver §14).
   - Solo transform y opacity.
   - `animation-iteration-count: 1` + `both`: al terminar no queda nada vivo.
   - Sin `.js-anim` no existe. Con reduced-motion, tampoco.
   ================================================================== */

/* `.sheen` NO toca el position. Es la cuarta vez en este proyecto que un
   override de `position` rompe un `absolute` deliberado: aqui puso
   `.band__panel-media` en `relative`, la imagen volvio al flujo y el texto
   de la tarjeta se fue DEBAJO de la foto en vez de ir encima.
   Quien necesite contexto de posicionamiento se lo declara el mismo. */
.sheen{ overflow: clip; }
.grid-gallery__item.sheen{ position: relative; }

.sheen::after{
  content: "";
  position: absolute;
  inset-block: -35%;
  inset-inline-start: -55%;
  inline-size: 38%;
  z-index: var(--z-content);
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(
    to right,
    transparent 0%,
    color-mix(in srgb, var(--paper) 22%, transparent) 42%,
    color-mix(in srgb, var(--accent-hi) 34%, transparent) 52%,
    color-mix(in srgb, var(--paper) 16%, transparent) 62%,
    transparent 100%
  );
  transform: rotate(var(--cut-deg));
}
@supports not (color: color-mix(in srgb, red, blue)){
  .sheen::after{
    background: linear-gradient(to right, transparent, var(--accent-hi) 52%, transparent);
    opacity: 0;
  }
}

/* Se dispara cuando el propio elemento entra, o cuando entra su contenedor
   (los paneles de la banda llevan el reveal en el panel, no en la imagen). */
.js-anim .sheen.is-in::after,
.js-anim .is-in .sheen::after{
  animation: sheen-sweep 1150ms var(--ease) 1 both;
  animation-delay: calc(160ms + var(--i, 0) * 90ms);
}

@keyframes sheen-sweep{
  0%   { opacity: 0;   transform: rotate(var(--cut-deg)) translate3d(0, 0, 0); }
  14%  { opacity: 0.9; }
  70%  { opacity: 0.55; }
  100% { opacity: 0;   transform: rotate(var(--cut-deg)) translate3d(430%, 0, 0); }
}

/* La imagen acompana con una entrada suave de escala: el conjunto se lee
   como un plano que se asienta, no como un elemento que aparece de golpe. */
.js-anim .sheen img{
  transform: scale(1.06);
  transition: transform 1100ms var(--ease);
}
.js-anim .sheen.is-in img,
.js-anim .is-in .sheen img{ transform: scale(1); }

@media (prefers-reduced-motion: reduce){
  .sheen::after{ display: none; }
  .js-anim .sheen img{ transform: none !important; transition: none !important; }
}

/* 17.1 GUARDA: la escala inicial de `.sheen img` SOLO puede existir donde
   hay un disparador que la deshaga. Si un `.sheen` no es un reveal ni cuelga
   de uno, nadie le pone `.is-in` y la imagen se queda encogida para siempre
   (medido: la franja de cierre quedaba en scale 1.03). Aqui se anula. */
.js-anim .sheen:not(.reveal):not(.reveal--media):not(.reveal--row):not(.reveal--wipe) img{
  transform: none;
}
.js-anim .reveal .sheen img,
.js-anim .sheen.reveal img,
.js-anim .sheen.reveal--media img{ transform: scale(1.06); }
.js-anim .is-in .sheen img,
.js-anim .sheen.is-in img{ transform: scale(1); }

/* ==================================================================
   18. TEXTO DENTRO DE LAS TARJETAS — entra escalonado tras la imagen
   La tarjeta se descubre, la luz la cruza y ENTONCES entra el texto:
   numero, titulo y descripcion, uno detras de otro. Se lee como una
   secuencia, no como un bloque que aparece entero.

   Todo cuelga de `.is-in`, que ya se dispara en las 6 paginas (verificado).
   Sin `.js-anim` nada de esto existe y el texto esta puesto desde el inicio.
   ================================================================== */

.js-anim .band__panel .band__panel-index,
.js-anim .band__panel .band__panel-title,
.js-anim .band__panel .band__panel-text,
.js-anim .figure-wide .figure-wide__caption span,
.js-anim .grid-gallery__item .grid-gallery__label{
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 620ms var(--ease),
    transform 620ms var(--ease);
}

.js-anim .band__panel.is-in .band__panel-index,
.js-anim .band__panel.is-in .band__panel-title,
.js-anim .band__panel.is-in .band__panel-text,
.js-anim .figure-wide.is-in .figure-wide__caption span,
.js-anim .grid-gallery__item.is-in .grid-gallery__label{
  opacity: 1;
  transform: none;
}

/* El escalonado arranca cuando el barrido de luz ya va por la mitad. */
.js-anim .band__panel.is-in .band__panel-index{ transition-delay: calc(320ms + var(--i, 0) * 90ms); }
.js-anim .band__panel.is-in .band__panel-title{ transition-delay: calc(400ms + var(--i, 0) * 90ms); }
.js-anim .band__panel.is-in .band__panel-text { transition-delay: calc(480ms + var(--i, 0) * 90ms); }

.js-anim .figure-wide.is-in .figure-wide__caption span:first-child{ transition-delay: 420ms; }
.js-anim .figure-wide.is-in .figure-wide__caption span:last-child { transition-delay: 500ms; }
.js-anim .grid-gallery__item.is-in .grid-gallery__label{ transition-delay: calc(400ms + var(--i, 0) * 90ms); }

@media (prefers-reduced-motion: reduce){
  .js-anim .band__panel .band__panel-index,
  .js-anim .band__panel .band__panel-title,
  .js-anim .band__panel .band__panel-text,
  .js-anim .figure-wide .figure-wide__caption span,
  .js-anim .grid-gallery__item .grid-gallery__label{
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}


/* ==================================================================
   19. LOGO DEL PIE — mas grande
   Medido: 40px de alto en escritorio y 28px en movil. Para la marca que
   cierra la pagina se queda corto; el pie tiene sitio de sobra.
   ================================================================== */
.footer__logo{ height: clamp(72px, 6.5vw, 104px); }

@media (max-width: 599.98px){
  .footer__logo{ height: 84px; }
}

/* ==================================================================
   20. LINEA DEL HEADER AL HACER SCROLL (movil)
   Una hairline teal en el borde inferior de la barra, que solo aparece
   cuando la pagina se ha movido. Sirve de separacion real entre la barra
   y el contenido, que en movil van los dos sobre negro y se confunden.
   Pasa POR DETRAS de la muesca de la marca: la marca la interrumpe, que es
   justo el gesto del logo.
   ================================================================== */
@media (max-width: 899.98px){
  .nav::after{
    content: "";
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    block-size: var(--bw-thick);
    background: var(--accent);
    opacity: 0;
    transform: scaleX(0.2);
    transform-origin: left center;
    transition:
      opacity var(--d-mid) var(--ease),
      transform 520ms var(--ease-cut);
    pointer-events: none;
  }
  .nav.is-stuck::after{ opacity: 1; transform: scaleX(1); }

  /* Con el cajon abierto la linea sobra: el cajon ya ocupa la pantalla. */
  .nav.is-open::after{ opacity: 0; }
}

@media (max-width: 899.98px) and (prefers-reduced-motion: reduce){
  .nav::after{ transition: none; transform: scaleX(1); }
}

/* 19.1 El boton flotante de "subir" se solapaba con el texto de la derecha
   de la barra inferior del pie (visto en pantalla a 1440). Se reserva sitio. */
.footer__bottom{ padding-inline-end: calc(var(--gutter) + 4.5rem); }
@media (max-width: 599.98px){
  .footer__bottom{ padding-inline-end: calc(var(--gutter) + 3.5rem); }
}

/* 21. VELO DE LA TARJETA: legibilidad del texto sobre la imagen.
   Con el texto ya dentro de la tarjeta, el fondo (mapa de asientos, estelas,
   retícula) le pasaba por encima. El velo se refuerza SOLO en la franja
   inferior, donde va el texto, y deja limpia la parte alta de la imagen. */
.band__panel-media::after{
  background: linear-gradient(
    to top,
    var(--ink) 0%,
    color-mix(in srgb, var(--ink) 82%, transparent) 26%,
    color-mix(in srgb, var(--ink) 45%, transparent) 48%,
    color-mix(in srgb, var(--ink) 18%, transparent) 72%,
    color-mix(in srgb, var(--ink) 30%, transparent) 100%
  );
  opacity: 1;
}
@supports not (color: color-mix(in srgb, red, blue)){
  .band__panel-media::after{
    background: linear-gradient(to top, var(--ink) 0%, var(--ink) 30%, transparent 75%);
    opacity: 0.92;
  }
}

/* 22. PIE SIN LA COLUMNA "FOLLOW"
   La rejilla declaraba tres columnas y, al quitar los iconos sociales, la
   tercera quedaba vacia y todo el pie se descolgaba a la izquierda.
   Con dos columnas la marca queda a la izquierda y el menu a la derecha. */
@media (min-width: 900px){
  .footer__inner{ grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
  .footer__inner > :last-child{ justify-self: end; text-align: end; }
}

/* ==================================================================
   23. HEADER MOVIL — alineacion y linea viva
   Tres cosas que se vieron en el movil real:
   (1) el logo quedaba alto respecto del boton de menu,
   (2) la linea teal se cortaba al pasar por detras de la marca,
   (3) pedia "vida": un latido muy leve.
   ================================================================== */
@media (max-width: 899.98px){

  /* (1) El bloque de marca mide 100% + muesca y empujaba el logo hacia
     arriba. Se centra el logo en la ALTURA UTIL de la barra, que es donde
     esta el boton de menu. */
  /* La caja mide (nav-h + muesca) y el contenido se centra en lo que queda
     tras el relleno inferior. Para que el centro del logo caiga en nav-h/2,
     ese relleno tiene que ser EXACTAMENTE la muesca, no el doble.
     Medido antes: centro del logo en 33px, centro del menu en 48px. */
  .nav__brand{
    display: grid;
    place-items: center;
    padding-block-end: var(--notch-m);
  }
  .nav{ --notch-m: calc(var(--brand-w-m) * 0.5 * var(--cut-tan)); }
  .nav__brand{ height: calc(var(--nav-h) + var(--notch-m)); }
  .nav.is-stuck .nav__brand{ height: calc(var(--nav-h-stuck) + var(--notch-m)); }

  /* (2) La linea iba por debajo de la marca y la muesca la tapaba.
     Subiendola por encima, cruza el header ENTERA de borde a borde. */
  .nav::after{ z-index: calc(var(--z-content) + 1); }

  /* (3) La linea NO es recta: baja por la muesca de la marca y vuelve a
     subir, siguiendo el mismo triangulo del logo. Se recorta con clip-path
     sobre una banda que llega hasta la punta de la muesca. */
  .nav::after{
    block-size: calc(var(--notch-m) + var(--bw-thick));
    inset-block-end: calc(-1 * var(--notch-m));
    --mitad: calc(var(--brand-w-m) / 2);
    clip-path: polygon(
      0 0,
      calc(50% - var(--mitad)) 0,
      50% var(--notch-m),
      calc(50% + var(--mitad)) 0,
      100% 0,
      100% var(--bw-thick),
      calc(50% + var(--mitad)) var(--bw-thick),
      50% calc(var(--notch-m) + var(--bw-thick)),
      calc(50% - var(--mitad)) var(--bw-thick),
      0 var(--bw-thick)
    );
    transform-origin: center top;
  }

  /* Latido delicado. El scaleY sobre 2px daba saltos por el redondeo a pixel
     entero; la opacidad es continua y se siente suave de verdad. La curva es
     una sinusoide (ease-in-out simetrico), no la curva de interfaz. */
  .nav.is-stuck::after{ animation: nav-latido 4.6s cubic-bezier(.37,0,.63,1) infinite; }
}

@keyframes nav-latido{
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}

@media (prefers-reduced-motion: reduce){
  .nav.is-stuck::after{ animation: none; }
}

/* 23.1 Fuera la pista de "SCROLL": el usuario ya sabe hacer scroll y
   ocupaba una linea entera del hero. */
.hero__scroll{ display: none; }

/* ==================================================================
   24. LIQUID GLASS — chat y formulario
   NOTA DE CRITERIO: la regla de marca decia "nada de glass". Se cambia a
   peticion expresa del cliente. Para que no caiga en el glass generico se
   aplica con disciplina: el cristal SOLO en superficies flotantes (el panel
   del chat y la caja del formulario), nunca en el contenido de la pagina;
   el tinte sale de la paleta de SPACE; y el borde superior lleva el brillo
   de luz que es lo que separa un cristal real de un div borroso.
   ================================================================== */

:root{
  --glass-bg:     color-mix(in srgb, var(--ink-3) 62%, transparent);
  --glass-bg-2:   color-mix(in srgb, var(--ink-4) 55%, transparent);
  --glass-line:   color-mix(in srgb, var(--paper) 14%, transparent);
  --glass-shine:  color-mix(in srgb, var(--paper) 30%, transparent);
  --glass-blur:   18px;
}

/* Superficie de cristal reutilizable. */
.glass{
  position: relative;
  background: var(--glass-bg);
  border: var(--bw) solid var(--glass-line);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(150%);
  backdrop-filter: blur(var(--glass-blur)) saturate(150%);
}
/* El filo de luz: una hairline mas clara arriba, que es como se lee el
   grosor de un cristal. Sin esto es solo un fondo borroso. */
.glass::before{
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 1px;
  background: linear-gradient(90deg, transparent, var(--glass-shine) 22%, var(--glass-shine) 78%, transparent);
  pointer-events: none;
}
/* Si el navegador no puede desenfocar, el cristal pasa a solido opaco:
   nunca se queda un panel semitransparente e ilegible. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){
  .glass{ background: var(--ink-3); }
}


/* ---------------- 24.1 CHAT: cristal y mas compacto ---------------- */

.chat__panel{
  background: var(--glass-bg);
  border: var(--bw) solid var(--glass-line);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(150%);
  backdrop-filter: blur(var(--glass-blur)) saturate(150%);
  /* Mas compacto: 380 -> 344 de ancho y 560 -> 480 de alto. */
  inline-size: min(90vw, 344px);
  block-size: min(66vh, 480px);
  border-radius: 18px;
  overflow: hidden;
  /* El corte de marca se conserva, pero suavizado para no pelear con el
     radio del cristal. */
  clip-path: polygon(0 18px, 18px 0, 100% 0, 100% 100%, 0 100%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){
  .chat__panel{ background: var(--ink-2); }
}

.chat__head{
  padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-4);
  background: color-mix(in srgb, var(--ink-3) 55%, transparent);
  border-bottom: var(--bw) solid var(--glass-line);
}
.chat__who{ font-size: 0.9375rem; }
.chat__sub{ font-size: 0.625rem; }

.chat__thread{
  gap: var(--sp-2);
  padding: var(--sp-4) var(--sp-3);
}
.chat__msg{
  max-inline-size: 86%;
  padding: var(--sp-2) var(--sp-3);
  font-size: 0.875rem;
  line-height: 1.45;
  border-radius: 12px;
}
.chat__msg--bot{
  background: color-mix(in srgb, var(--ink-4) 72%, transparent);
  border-inline-start: 2px solid var(--accent);
  border-start-start-radius: 4px;
}
.chat__msg--user{
  background: var(--accent);
  border-end-end-radius: 4px;
}
.chat__typing{ padding: var(--sp-2) var(--sp-3); border-radius: 12px; }

.chat__form{
  padding: var(--sp-2) var(--sp-2) var(--sp-3);
  border-top: var(--bw) solid var(--glass-line);
  background: color-mix(in srgb, var(--ink-3) 45%, transparent);
}
.chat__in{
  padding: var(--sp-2) var(--sp-3);
  background: color-mix(in srgb, var(--ink) 55%, transparent);
  border-radius: 10px;
  font-size: 16px;   /* 16px exactos: por debajo, iOS hace zoom al enfocar */
}
.chat__send{ inline-size: 42px; border-radius: 10px; }
.chat__fab{ inline-size: 52px; block-size: 52px; }

/* ---- MOVIL: el teclado ya no descuadra el panel ----
   El fallo: con 66vh y position:fixed, al subir el teclado de iOS la ventana
   no cambia de alto (vh es el viewport GRANDE) y el panel quedaba por debajo
   del teclado, con la caja de escribir fuera de la pantalla.
   Solucion: alto en dvh (viewport DINAMICO, el que si encoge con el teclado)
   y el panel anclado al borde inferior real. */
@media (max-width: 599.98px){
  .chat{
    inset-block-end: max(var(--sp-4), env(safe-area-inset-bottom));
    inset-inline: var(--sp-3);
  }
  .chat__panel{
    inline-size: 100%;
    block-size: min(72vh, 520px);
  }
}
@supports (height: 100dvh){
  @media (max-width: 599.98px){
    .chat__panel{
      /* 100dvh menos el sitio del boton y los margenes. Con el teclado
         abierto, dvh encoge y el panel encoge con el. */
      block-size: min(calc(100dvh - 9rem), 520px);
      max-block-size: calc(100dvh - 8rem);
    }
  }
}
/* El hilo es lo unico que se encoge: cabecera y caja de escribir se quedan. */
.chat__head, .chat__form{ flex: 0 0 auto; }
.chat__thread{ flex: 1 1 auto; min-block-size: 0; }


/* ---------------- 24.2 FORMULARIO: cristal, compacto, elegante ---------------- */

.contact{
  padding: clamp(var(--sp-4), 2.6vw, var(--sp-6));
  border-radius: 16px;
  background: var(--glass-bg);
  border: var(--bw) solid var(--glass-line);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  backdrop-filter: blur(var(--glass-blur)) saturate(140%);
  position: relative;
  overflow: hidden;
}
.contact::before{
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 1px;
  background: linear-gradient(90deg, transparent, var(--glass-shine) 25%, var(--glass-shine) 75%, transparent);
  pointer-events: none;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){
  .contact{ background: var(--ink-3); }
}

.contact__form{ gap: var(--sp-3); }
.contact__row{ gap: var(--sp-3); }
.contact__field{ gap: var(--sp-1); }

.contact__input,
.contact__select,
.contact__textarea{
  padding: var(--sp-2) var(--sp-3);
  border-radius: 10px;
  background: color-mix(in srgb, var(--ink) 48%, transparent);
  border: var(--bw) solid var(--field-border);
  font-size: 16px;              /* evita el zoom de iOS al enfocar */
}
@supports not (color: color-mix(in srgb, red, blue)){
  .contact__input, .contact__select, .contact__textarea{ background: var(--ink-4); }
}
.contact__textarea{ min-block-size: 5.5rem; }
.contact__label{ font-size: 0.6875rem; }
.contact__hint{ font-size: 0.8125rem; }
.contact__actions{ margin-block-start: var(--sp-1); }

@media (prefers-reduced-motion: reduce){
  .glass, .chat__panel, .contact{ -webkit-backdrop-filter: none; backdrop-filter: none; }
  .chat__panel{ background: var(--ink-2); }
  .contact{ background: var(--ink-3); }
}

/* ==================================================================
   25. PIE EN CUATRO COLUMNAS
   A 1440px el pie de dos columnas dejaba un hueco enorme a la derecha y el
   logo perdido a la izquierda. Ahora: marca · verticales · empresa · estudio.
   ================================================================== */
.footer__inner{ grid-template-columns: minmax(0, 1fr); }

@media (min-width: 700px){
  .footer__inner{ grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px){
  .footer__inner{
    grid-template-columns: minmax(0, 1.3fr) repeat(3, minmax(0, 1fr));
    gap: var(--gap-lg) var(--gap);
  }
  /* Se anula el alineado a la derecha que tenia la version de dos columnas. */
  .footer__inner > :last-child{ justify-self: start; text-align: start; }
}

.footer__col{ display: grid; gap: var(--sp-4); align-content: start; }

.footer__tag{
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: var(--fw-med);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--accent);
}

.footer__nav{ display: grid; gap: 0; list-style: none; margin: 0; padding: 0; }

.footer__addr{
  font-style: normal;
  font-size: var(--fs-small);
  line-height: 1.75;
  letter-spacing: 0;
  text-transform: none;
  color: var(--fg-dim);
}

.footer__map{
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-label);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--accent);
  text-decoration: none;
  padding-block: var(--sp-2);
  transition: color var(--d-fast) var(--ease);
}
.footer__map:hover,
.footer__map:focus-visible{ color: var(--accent-hi); }

.footer__bottom{
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--gap);
  justify-content: space-between;
}

/* 24.3 El boton iba ARRIBA del panel: en el DOM va primero (correcto para el
   foco) pero visualmente debe quedar debajo, que es donde lo busca el pulgar.
   column-reverse arregla lo visual sin tocar el orden de tabulacion. */
.chat{ flex-direction: column-reverse; }

/* El punto de estado se alineaba con el centro del bloque de dos lineas.
   Va a la altura del nombre. */
.chat__head{ align-items: flex-start; }
.chat__dot{ margin-block-start: 0.42em; }

/* Con el panel abierto en movil el boton estorba: el panel ya tiene su X. */
@media (max-width: 599.98px){
  .chat.is-open .chat__fab{ display: none; }
}

/* 26. ESCRITORIO: el logo tambien iba descentrado (29px medidos).
   Causa: `--notch` se calcula a partir de `--brand-w`, pero en escritorio la
   marca usa `--brand-w-d`, que es mas ancha. La muesca quedaba calculada para
   otra caja. Se recalcula con el ancho real y se centra igual que en movil. */
@media (min-width: 900px){
  .nav{ --notch-d: calc(var(--brand-w-d) * 0.5 * var(--cut-tan)); }
  .nav__brand{
    display: grid;
    place-items: center;
    height: calc(var(--nav-h) + var(--notch-d));
    padding-block-end: var(--notch-d);
    clip-path: polygon(
      0 0,
      100% 0,
      100% calc(100% - var(--notch-d)),
      50% 100%,
      0 calc(100% - var(--notch-d))
    );
  }
  .nav.is-stuck .nav__brand{ height: calc(var(--nav-h-stuck) + var(--notch-d)); }
}

/* 26.1 CAUSA REAL del descentrado en escritorio (medida, no supuesta):
   `.nav__brand` mide 141px dentro de una barra de 96 y `.nav__inner` es un
   flex con align-items:center, asi que lo centraba y lo colocaba en top:-23px.
   La marca tiene que colgar del BORDE SUPERIOR y sobresalir solo por abajo. */
@media (min-width: 900px){
  .nav__brand{ align-self: flex-start; }
}

/* ==================================================================
   27. CHAT — mas luz
   El cristal quedaba casi negro: el tinte partia de --ink-3 sobre una pagina
   ya negra, asi que no habia contraste que ver. Se sube la base y se aclaran
   las burbujas del bot.
   ================================================================== */
.chat__panel{
  background: color-mix(in srgb, var(--ink-4) 78%, transparent);
  border-color: color-mix(in srgb, var(--paper) 22%, transparent);
}
.chat__head{
  background: color-mix(in srgb, var(--paper) 7%, transparent);
  border-bottom-color: color-mix(in srgb, var(--paper) 12%, transparent);
}
.chat__msg--bot{
  background: color-mix(in srgb, var(--paper) 12%, transparent);
  color: var(--paper);
}
.chat__form{ background: color-mix(in srgb, var(--paper) 5%, transparent); }
.chat__in{
  background: color-mix(in srgb, var(--ink) 42%, transparent);
  border-color: color-mix(in srgb, var(--paper) 26%, transparent);
  color: var(--paper);
}
@supports not (color: color-mix(in srgb, red, blue)){
  .chat__panel{ background: var(--ink-4); }
  .chat__msg--bot{ background: var(--ink-3); }
}

/* 27.1 TECLADO EN MOVIL — el panel se ajusta al hueco REAL
   `chat.js` escribe --vv-alto (lo que queda visible) y --vv-desplazado
   (cuanto ha subido la pagina iOS). Sin esto la caja de escribir se va
   por debajo del teclado. */
@media (max-width: 599.98px){
  .chat.is-keyboard{
    /* Se ancla al hueco visible, no al viewport teorico. */
    inset-block-end: calc(var(--vv-desplazado, 0px) + var(--sp-2));
  }
  .chat.is-keyboard .chat__panel{
    block-size: calc(var(--vv-alto, 100dvh) - 5rem);
    max-block-size: calc(var(--vv-alto, 100dvh) - 4rem);
  }
  /* Con el teclado abierto el hilo es lo unico que cede. */
  .chat.is-keyboard .chat__thread{ min-block-size: 4rem; }
}

/* 23.2 LA MUESCA DEL BLOQUE Y LA DE LA LINEA TIENEN QUE SER LA MISMA.
   Medido: el clip-path de `.nav__brand` heredaba `--notch` (24,1px, calculado
   sobre `--brand-w`) mientras la linea trazaba su V con `--notch-m` (31px,
   sobre `--brand-w-m`). Resultado: 7px de negro asomando por debajo de la
   linea. Aqui el bloque pasa a usar la MISMA profundidad que la linea, asi
   que la V teal queda pegada al borde del negro. */
@media (max-width: 899.98px){
  .nav__brand{
    clip-path: polygon(
      0 0,
      100% 0,
      100% calc(100% - var(--notch-m)),
      50% 100%,
      0 calc(100% - var(--notch-m))
    );
  }
}

/* ==================================================================
   28. FUERA LA ETIQUETA FLOTANTE ("eyebrow")
   El patron etiqueta-pequena-en-mayusculas encima de cada titular es una de
   las firmas mas reconocibles de las webs hechas con IA. Se elimina de todas
   las cabeceras de seccion y en los heroes se sustituye por un MARCADOR DE
   INDICE, que es informacion real (en que vertical estas de cuantas) y usa
   el mismo sistema de numeracion que ya tienen la banda y la lista.
   ================================================================== */
.hero__idx{
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  font-family: var(--ff-display);
  font-size: clamp(0.875rem, 1.1vw, 1.0625rem);
  font-weight: var(--fw-bold);
  letter-spacing: 0.12em;
  font-variant-numeric: tabular-nums;
}
.hero__idx-n{ color: var(--accent); }
.hero__idx-t{ color: var(--fg-mute); }
.hero__idx-rule{
  inline-size: clamp(40px, 6vw, 78px);
  block-size: var(--bw);
  background: linear-gradient(90deg, var(--accent), var(--fg-mute));
}

/* Las cabeceras de seccion pierden la etiqueta: el titular sube y respira. */
.section-head{ gap: var(--sp-3); }

/* ==================================================================
   29. HEADER PLANO EN ESCRITORIO Y TABLET
   La muesca se queda SOLO en movil, donde la marca va centrada y el gesto
   se lee. De 900px para arriba la barra es recta: sin punta, sin sobresalir.
   ================================================================== */
@media (min-width: 900px){
  .nav__brand{
    clip-path: none;
    height: 100%;
    padding-block-end: 0;
    align-self: stretch;
    background: transparent;   /* sin bloque negro sobre la foto */
  }
  .nav.is-stuck .nav__brand{ height: 100%; background: transparent; }
  /* Sin muesca, el logo se centra en la barra sin mas. */
  .nav__logo{ height: clamp(44px, 3.6vw, 60px); }
  .nav.is-stuck .nav__logo{ height: clamp(34px, 2.6vw, 44px); }
}

/* ==================================================================
   30. SLIDER DE LA TARJETA + TARJETA ENTERA CLICABLE
   Tres tratamientos por servicio (duotono / azul / color contenido) que se
   funden entre si. La tarjeta completa es un enlace de verdad.
   ================================================================== */

/* --- las tres imagenes apiladas ---
   El cambio NO es un fundido plano: la entrante se descubre por la diagonal
   de 19 grados de la marca. Se nota que cambia, que es lo que se pedia, y
   ademas es el gesto del sitio. */
[data-slider]{ position: absolute; inset: 0; }
[data-slider] picture{
  position: absolute;
  inset: 0;
  display: block;
}
[data-slider] picture img{
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  display: block;
}

/* Sin JS se ve la primera y ya: nada del slider es requisito para ver. */
[data-slider] picture{ opacity: 0; }
[data-slider] picture:first-child{ opacity: 1; }

.js-anim [data-slider] picture{
  opacity: 0;
  clip-path: polygon(0 0, 0 0, -34% 100%, -34% 100%);
  transition: clip-path var(--slider-t, 760ms) var(--ease-cut),
              opacity calc(var(--slider-t, 760ms) * 0.45) linear;
  will-change: clip-path;
}
.js-anim [data-slider] picture.is-active{
  opacity: 1;
  clip-path: polygon(0 0, 134% 0, 100% 100%, 0 100%);
}
/* La saliente se queda quieta y visible debajo mientras entra la otra: sin
   esto se ve el fondo negro entre imagen e imagen. */
.js-anim [data-slider] picture.is-leaving{
  opacity: 1;
  clip-path: polygon(0 0, 134% 0, 100% 100%, 0 100%);
  transition: none;
  z-index: 0;
}
.js-anim [data-slider] picture.is-active{ z-index: 1; }

/* En movil el cambio va mas rapido y mas seco: en una pantalla pequena una
   transicion de 760ms se percibe lenta. */
@media (max-width: 599.98px){
  .js-anim [data-slider] picture{ --slider-t: 480ms; }
}

@media (prefers-reduced-motion: reduce){
  .js-anim [data-slider] picture{
    transition: none;
    clip-path: none;
  }
}

/* --- enlace que cubre toda la tarjeta --- */
.band__panel-link{
  position: absolute;
  inset: 0;
  z-index: var(--z-content);
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  padding: var(--sp-5);
  text-decoration: none;
}
.band__panel-go{
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: var(--fw-med);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--accent);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--d-fast) var(--ease), transform var(--d-fast) var(--ease);
}
.band__panel:hover .band__panel-go,
.band__panel-link:focus-visible .band__panel-go{ opacity: 1; transform: none; }
.band__panel-link:focus-visible{
  outline: var(--bw-thick) solid var(--accent);
  outline-offset: -4px;
}
/* El titulo deja de ser enlace: ahora lo es la tarjeta entera. */
.band__panel-title{ pointer-events: none; }

@media (prefers-reduced-motion: reduce){
  [data-slider] img{ transition: none; }
  .band__panel-go{ opacity: 1; transform: none; transition: none; }
}

/* ==================================================================
   31. PIE CLARO — la seccion que rompe el negro
   Medido: la pagina iba de 17 a 28-38 de luminancia media frente a los 66
   del sitio anterior de SPACE. Lo que faltaba no eran fotos mas claras:
   era que el original TENIA superficies claras y este no tenia ninguna.
   El pie es el mejor sitio para la primera: cierra la pagina, no compite
   con el contenido y da el respiro que faltaba.
   ================================================================== */
.footer{
  background: var(--paper);
  border-top: none;
  /* Se remapean los alias: los componentes de dentro se invierten solos. */
  --bg: var(--paper);
  --bg-2: var(--paper-2);
  --surface: var(--paper-3);
  --fg: var(--ink);
  --fg-dim: var(--ink-text);
  --fg-mute: var(--ink-mute);
  --fg-soft: var(--teal-700);
  --accent: var(--teal-700);
  --accent-hi: var(--teal-600);
  --hairline: var(--line-light);
  color: var(--fg-dim);
}

/* El logo blanco no se ve sobre blanco: se cambia al de color. */
/* Sobre el pie blanco, el lockup metalico medía 203 de luminancia: invisible.
   No hay variante negra en el material de marca, asi que se derivo de la
   blanca recoloreando el trazo. */
.footer__logo{ content: url("../logo/space-black-600.png"); }

.footer__title{ color: var(--teal-700); }
.footer__legal,
.footer__addr{ color: var(--fg-mute); }
.footer__link{ color: var(--fg-dim); }
.footer__link:hover,
.footer__link:focus-visible{ color: var(--teal-700); }
.footer__map{ color: var(--teal-700); }
.footer__map:hover{ color: var(--teal-600); }
.footer__bottom{
  border-top: var(--bw) solid var(--hairline);
  color: var(--fg-mute);
}
.footer__nav li + li{ border-top-color: var(--hairline); }

/* El corte de marca hace de transicion entre el negro y el blanco, en vez
   de un borde plano: es el mismo gesto de 19 grados del resto del sitio. */
.footer::before{
  content: "";
  display: block;
  block-size: clamp(48px, 7vw, 110px);
  background: var(--ink);
  clip-path: polygon(0 0, 100% 0, 100% 0, 0 100%);
  margin-block-start: calc(-1 * clamp(48px, 7vw, 110px));
}

/* 30.1 El enlace de tarjeta salia en `position: relative` y medía 493x67 en
   vez de cubrir el panel. Causa: `.band__panel > :not(.band__panel-media)`
   tiene especificidad (0,2,0) y gana a `.band__panel-link` (0,1,0) sea cual
   sea el orden. Se iguala la especificidad. Es la tercera vez que una regla
   `> *` de este bloque pisa un posicionamiento: comprobar SIEMPRE el
   position calculado, no darlo por hecho. */
.band__panel > .band__panel-link{
  position: absolute;
  inset: 0;
  z-index: var(--z-content);
}

/* ==================================================================
   32. MOVIL: EL BLOQUE DEL LOGO, DEL MISMO TONO QUE EL HEADER
   El bloque de marca usaba --ink-2 (#12161A) mientras la barra es
   transparente arriba y --ink-2 al compactarse: se veia como un panel mas
   claro pegado encima del hero. Ahora coincide EXACTO en los dos estados.
   ================================================================== */
@media (max-width: 899.98px){
  /* UN solo negro para toda la barra y para el bloque de la marca, en los
     dos estados. Antes: barra transparente sobre el hero + marca en --ink-2
     al compactarse = tres tonos alrededor del logo. Ahora todo es --ink,
     que es ademas el fondo de la pagina: el header deja de verse como una
     pieza distinta. */
  .nav,
  .nav.is-stuck{ background: var(--ink); border-bottom-color: transparent; }
  .nav__brand,
  .nav.is-stuck .nav__brand{ background: var(--ink); }
}

/* ==================================================================
   33. LENGUAJE DE MARCADOR DEPORTIVO
   Idea de Robmar: acercar la interfaz al mundo del deporte. En vez de
   disfrazar la web de estadio —que caeria en cursi— se toma UNA convencion
   concreta del marcador y se aplica donde ya hay numeros:

     · digitos tabulares, siempre a dos cifras
     · panel hundido con marco fino, como una caja de tanteo
     · un punto teal que marca "en directo"

   No se toca ni la tipografia ni la paleta: es el MISMO sistema, leido en
   clave deportiva.
   ================================================================== */

.marcador{
  display: inline-flex;
  align-items: stretch;
  gap: var(--bw);
  background: var(--line);
  border: var(--bw) solid var(--line-2);
  border-radius: var(--r-1);
  overflow: hidden;
  font-variant-numeric: tabular-nums;
}
.marcador__celda{
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  background: var(--ink);
  font-family: var(--ff-display);
  font-weight: var(--fw-bold);
  letter-spacing: 0.08em;
  line-height: 1;
}
.marcador__n{ color: var(--accent); font-size: 1.05em; }
.marcador__t{ color: var(--fg-mute); font-size: 1.05em; }
.marcador__etq{
  font-family: var(--ff-body);
  font-size: var(--fs-label);
  font-weight: var(--fw-med);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--fg-mute);
}

/* --- El marcador de indice del hero pasa a caja de tanteo --- */
.hero__idx{
  display: inline-flex;
  align-items: stretch;
  gap: var(--bw);
  background: var(--line);
  border: var(--bw) solid var(--line-2);
  border-radius: var(--r-1);
  overflow: hidden;
  padding: 0;
}
.hero__idx-n,
.hero__idx-t{
  display: flex;
  align-items: center;
  padding: var(--sp-2) var(--sp-4);
  background: var(--ink);
  line-height: 1;
}
.hero__idx-n{ color: var(--accent); }
.hero__idx-t{ color: var(--fg-mute); }
/* La regla intermedia se convierte en el separador del marcador. */
.hero__idx-rule{
  inline-size: auto;
  block-size: auto;
  display: flex;
  align-items: center;
  padding-inline: var(--sp-2);
  background: var(--ink);
}
.hero__idx-rule::before{
  content: ":";
  color: var(--fg-mute);
  font-family: var(--ff-display);
  font-weight: var(--fw-bold);
}

/* Los botones del hero NO llevan tratamiento especial: se pidio volver a
   como estaban antes de la peticion de "asociar los botones a deportes".
   Usan directamente `.btn` / `.btn--solid` / `.btn--arrow` de components.css,
   igual que en el resto del sitio (pilares, cierre, formulario). */

/* --- Las cifras del sitio, en digitos de marcador --- */
.stat__num,
.band__panel-index,
.pillars__num,
.crosslinks__num,
.timeline__step{
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}
/* (capsula del indice de tarjeta retirada a peticion: tapaba la foto) */

/* ==================================================================
   34. VELO DEL HEADER EN ESCRITORIO
   En escritorio la barra es transparente y se apoya directamente sobre la
   fotografia del hero, asi que los enlaces caian sobre el cielo o la pista
   y no se leian. Movil no: ahi la barra ya es --ink solido (seccion 32).

   MEDIDO, no estimado. Requisito AA (4.5:1) para el texto de 12px:
     - enlace normal  #C9D3D6 -> el fondo debe quedar en L <= 0.1030
     - enlace ACTIVO  #22A9C6 -> el fondo debe quedar en L <= 0.0340  <- manda
   Luminancia real de la banda que queda bajo la barra, por foto de hero:
     corporate 0.4156 de media   motorsport 0.3640 de media
     ticketing/hospitality/motorsport llegan a 0.88-0.99 en el percentil 95
   Es decir: se incumplia por un orden de magnitud, y el que manda es el
   enlace teal de la pagina actual, no los grises.

   El velo se calcula para el peor caso posible (foto blanca, L=1.0). A la
   altura del texto la opacidad es ~0.90, que compuesta sobre blanco deja el
   fondo en L=0.019: 5.5:1 el enlace activo y 10.0:1 los normales. Se apaga
   al compactarse la barra, que ya trae fondo solido propio.
   ================================================================== */
@media (min-width: 900px){
  .nav::before{
    content: "";
    position: absolute;
    inset-block-start: 0;
    inset-inline: 0;
    z-index: -1;
    /* Mas alto que la barra: el degradado tiene que morir POR DEBAJO de
       ella, si no se corta en seco y se ve el borde de una caja. */
    block-size: calc(var(--nav-h) * 1.9);
    background: linear-gradient(
      to bottom,
      color-mix(in srgb, var(--ink) 94%, transparent) 0%,
      color-mix(in srgb, var(--ink) 90%, transparent) 40%,
      color-mix(in srgb, var(--ink) 66%, transparent) 62%,
      transparent 100%
    );
    pointer-events: none;
    transition: opacity var(--d-mid) var(--ease);
  }

  /* Compactada ya tiene fondo solido: el velo sobraria y asomaria por
     debajo de la barra como una sombra. */
  .nav.is-stuck::before{ opacity: 0; }
}

/* Sin color-mix el degradado no se puede expresar: se cae a barra solida,
   que es el resultado legible. Nunca a medio velo ilegible. */
@media (min-width: 900px){
  @supports not (color: color-mix(in srgb, red, blue)){
    .nav::before{ display: none; }
    .nav{ background: var(--ink); }
  }
}
