/* =============================================================================
   DropDigitals — Hero sobre carbón, estilo "Ari" (réplica adaptada)
   Composición a TODA la anchura: izquierda la bienvenida (la marca en marfil
   con el acento en cobre), centro el producto protagonista en 3D con la
   constelación del catálogo, derecha las cifras apiladas con divisores + CTA,
   y abajo-izquierda la pista "Desliza · Descubre el catálogo".
   Progresivo: sin WebGL queda la misma retícula con el panel de activación al
   centro. hero3d.js añade .hero--live (pista alta + sticky) y .hero--on (canvas).
   Capas dentro de .hero__sticky: bg(0) < canvas(1) < shade(2) < contenido(3+).
   ============================================================================= */

.hero--3d {
  display: block;
  padding: 0;
  overflow: visible;
  background: none;
}

.hero--3d::after {
  content: none;
}

.hero--3d .hero__sticky {
  position: relative;
  display: flex;
  align-items: center;
  /* Pantalla COMPLETA desde el píxel cero: en la portada la cabecera flota por
     encima sin ocupar sitio (chrome.css), así que aquí ya no hay que restarle
     su alto. Los bultos entran por el borde de arriba, no por debajo de una
     barra. El padding solo evita que el titular se meta bajo el logo en
     pantallas bajas; como el contenido va centrado, casi nunca se nota. */
  min-height: 100vh;
  min-height: 100svh;
  padding-top: var(--headerH, 4.5rem);
  overflow: hidden;
  isolation: isolate;
  background: var(--bg);
}

.hero--3d .hero__sticky>.container {
  position: relative;
  z-index: 3;
}

.hero--3d .hero__bg {
  display: none;
}

.hero--3d .hero__watermark {
  display: none;
}

/* --- Retícula Ari: bienvenida | producto | cifras ----------------------------- */
.hero__ari {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  gap: clamp(1.25rem, 2.5vw, 2.5rem);
}

.hero__ari > * {
  min-width: 0;
}

@media (min-width: 961px) {
  /* Dos columnas desde el 18-ago-2026: bienvenida y cifras. La columna del
     medio era del 3D y del panel de muestra, los dos retirados. */
  .hero--3d .hero__sticky>.container.hero__ari {
    display: grid;
    grid-template-columns: minmax(0, 1.25fr) minmax(230px, 1fr);
  }

  .hero__ari .hero__content {
    grid-column: 1;
    grid-row: 1;
  }

  .hero__ari .hero__stats {
    grid-column: 2;
    grid-row: 1;
  }
}

/* Izquierda: eyebrow con línea + marca apilada */
.hero--3d .hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 0;
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brand);
}

.he-line {
  width: 2.2rem;
  height: 1px;
  background: currentColor;
  opacity: 0.7;
  flex: none;
}

/* Scopeado a .hero--3d para ganarle al titular de home.css (.hero h1 → #fff).
   Va con var(--ink) y no con una tinta clavada: cuando el hero nacía sobre
   blanco llevaba un casi negro fijo, y al pasar la web a carbón el titular
   desaparecía contra el fondo. */
.hero--3d .hero__brand {
  margin-top: 1rem;
  font-family: var(--font-display);
  font-weight: 620;
  line-height: 0.98;
  letter-spacing: -0.03em;
  /* El tamaño lo manda la palabra más larga del nombre, no el gusto: aquí el
     titular vive en la columna izquierda de una retícula de tres, así que un
     nombre de una sola palabra no tiene por dónde partirse y se salía del
     ancho. Con dos palabras cortas se puede subir; si vuelves a tocarlo,
     compruébalo a 1440 px y a 320 px, que son los dos extremos. */
  font-size: clamp(2rem, 0.9rem + 2.6vw, 3.2rem);
  color: var(--ink);
  text-shadow: none;
  /* Red de seguridad: antes que cortarse, que parta. */
  overflow-wrap: anywhere;
}

.hero--3d .hero__brand span,
.hero--3d .hero__brand em {
  display: block;
}

.hero--3d .hero__brand em {
  font-style: normal;
  color: var(--brand);
}

/* Sin la línea animada del hero anterior bajo el <em> */
.hero--3d .hero__brand em::after {
  content: none;
}

.hero--3d .hero__content {
  color: var(--ink-body);
  padding-block: 0;
}

.hero--3d .hero__lede {
  margin-top: 1.2rem;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink-body);
  max-width: 30ch;
}

/* --- Menú principal con aire de consola de videojuego -----------------------
   Barras apiladas con el canto derecho en diagonal, la activa encendida en
   cobre y un rombo al final. Sustituye a la navegación del header EN LA
   PORTADA (chrome.css la esconde ahí para no repetir los mismos cuatro
   destinos en la primera pantalla).

   Es pintura, no un invento de navegación: por dentro sigue siendo un <nav>
   con enlaces normales, así que el teclado y los lectores de pantalla lo
   recorren como siempre. Por eso el estado activo se cuelga de
   [aria-current="page"] y no de una clase suelta: el dato ya está ahí.

   El corte diagonal va con clip-path y no con un pseudo-elemento girado: aquel
   tapaba el borde y en pantallas de mucha densidad dejaba un diente visible. */
.gmenu {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 1.5rem;
  max-width: 22rem;
}

.gmenu__i {
  --gm-cut: 16px;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.9rem;
  padding: 0.7rem 1.55rem 0.7rem 1rem;
  text-decoration: none;
  color: var(--ink-strong);
  background: linear-gradient(90deg, rgb(255 255 255 / 0.07), rgb(255 255 255 / 0.015));
  border: 1px solid rgb(255 255 255 / 0.08);
  clip-path: polygon(0 0, 100% 0, calc(100% - var(--gm-cut)) 100%, 0 100%);
  transition: background var(--t) var(--ease-out), color var(--t),
    border-color var(--t), transform var(--t) var(--ease-out);
}

/* Filo de la izquierda: apagado en reposo, encendido en la activa. */
.gmenu__i::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--brand);
  opacity: 0.3;
  transition: width var(--t) var(--ease-out), opacity var(--t);
}

.gmenu__t {
  display: flex;
  flex-direction: column;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  line-height: 1.15;
}

/* El subtítulo solo asoma en la activa o al pasar por encima, como en el menú
   del juego. Se anima max-height y no height: con `height:auto` no hay
   transición posible y el texto aparecía de golpe. */
.gmenu__t em {
  font-style: normal;
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  color: var(--ink-faint);
  text-transform: uppercase;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height var(--t) var(--ease-out), opacity var(--t), margin-top var(--t);
}

.gmenu__d {
  width: 0.5rem;
  height: 0.5rem;
  flex: none;
  transform: rotate(45deg);
  background: rgb(255 255 255 / 0.2);
  transition: background var(--t), box-shadow var(--t), transform var(--t) var(--ease-out);
}

.gmenu__i:hover,
.gmenu__i:focus-visible,
.gmenu__i[aria-current="page"] {
  color: #fff;
  border-color: color-mix(in oklch, var(--brand) 45%, transparent);
  background: linear-gradient(90deg,
      color-mix(in oklch, var(--brand) 58%, transparent),
      color-mix(in oklch, var(--brand) 10%, transparent) 62%,
      transparent);
  transform: translateX(4px);
}

.gmenu__i:hover::before,
.gmenu__i:focus-visible::before,
.gmenu__i[aria-current="page"]::before {
  width: 4px;
  opacity: 1;
}

.gmenu__i:hover .gmenu__t em,
.gmenu__i:focus-visible .gmenu__t em,
.gmenu__i[aria-current="page"] .gmenu__t em {
  max-height: 1.4rem;
  opacity: 1;
  margin-top: 0.2rem;
}

.gmenu__i:hover .gmenu__d,
.gmenu__i:focus-visible .gmenu__d,
.gmenu__i[aria-current="page"] .gmenu__d {
  background: var(--brand);
  box-shadow: 0 0 10px color-mix(in oklch, var(--brand) 75%, transparent);
  transform: rotate(45deg) scale(1.15);
}

.gmenu__i:focus-visible {
  outline: none;
  box-shadow: var(--ring);
}

/* Sin desplazamiento lateral para quien pidió menos movimiento: el color y el
   rombo ya dicen cuál está seleccionada. */
@media (prefers-reduced-motion: reduce) {
  .gmenu__i {
    transition: background var(--t), color var(--t), border-color var(--t);
  }

  .gmenu__i:hover,
  .gmenu__i:focus-visible,
  .gmenu__i[aria-current="page"] {
    transform: none;
  }
}

/* En el celular el menú va a todo el ancho de su columna: con 22rem tope
   quedaba una franja rara a la derecha en pantallas de 360 px. */
@media (max-width: 960px) {
  .gmenu {
    max-width: none;
    margin-top: 1.25rem;
  }
}

/* Derecha: cifras apiladas con divisores (números grandes, leyenda pequeña) */
.hero__stats {
  display: flex;
  flex-direction: column;
}

@media (min-width: 961px) {
  .hero__stats {
    justify-self: end;
    text-align: right;
    min-width: 250px;
  }
}

.hstat {
  padding: 1.05rem 0;
  border-top: 1px solid var(--border);
}

.hstat:first-child {
  border-top: 0;
}

.hstat b {
  display: block;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  font-size: clamp(2.1rem, 1.5rem + 1.7vw, 3.3rem);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.hstat b i {
  font-style: normal;
  font-size: 0.42em;
  font-weight: 700;
  color: var(--brand);
  vertical-align: super;
  margin-left: 0.15em;
}

/* OJO: hijo DIRECTO (>): dentro del <b> ahora viven los spans del tambor de
   cifras y no deben heredar el estilo de la leyenda. */
.hstat > span {
  display: block;
  margin-top: 0.45rem;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/* --- Tambor de cifras (slot machine, home.js statOdometer) -------------------
   Cada dígito es una ventanita de 1em con una columna 0-9 que gira (transform)
   y cae en su valor. Los signos (+, –, espacio) van en la misma caja de 1em
   para que toda la cifra alinee pareja. */
.odo {
  display: inline-block;
  overflow: hidden;
  height: 1em;
  line-height: 1;
  white-space: pre;
}

.odo__reel {
  display: block;
  transition: transform 1s cubic-bezier(0.16, 0.9, 0.24, 1);
  will-change: transform;
}

.odo__reel > span {
  display: block;
  height: 1em;
  line-height: 1;
}

/* Giro terminado (la clase la pone odoRoll en home.js): en la ventanilla solo
   queda el dígito final. Así no puede asomar el borde del dígito de al lado —
   el alto de cada casilla se redondea a píxeles del aparato y en pantallas de
   mucha densidad se colaba un hilo del número vecino por encima. De paso suelta
   la capa de composición (will-change) que ya no hace falta. */
.odo.is-set .odo__reel {
  will-change: auto;
}

.odo.is-set .odo__reel > span {
  visibility: hidden;
}

.odo.is-set .odo__reel > span:last-child {
  visibility: visible;
}

@media (prefers-reduced-motion: reduce) {
  .odo__reel {
    transition: none;
  }
}

/* Aquí estaban .hero__cta y .hero__ghostpill: los tres botones de la columna
   derecha del hero. Se retiraron con su marcado — el menú de la izquierda hace
   ahora de navegación principal y aquellos repetían los mismos destinos. */

/* ---------------------------------------------------------- Puerta a la 3D
   Segunda entrada a la MISMA tienda (28-jul-2026). Usa el botón verde de la
   casa TAL CUAL (.btn--primary), sin nada propio: el degradado que llevaba
   antes partía el botón en dos tonos y se veía como un error de pintado.
   Vive junto a "Ver productos": el catálogo clásico sigue siendo el camino
   principal de compra y el que indexa Google. */

/* Velos de carbón: legibilidad en los márgenes laterales + fusión arriba/abajo.
   Son el mismo #0F1113 del fondo con transparencia, así que en vez de tapar,
   funden la escena 3D con la página. Antes eran blancos —la portada nacía sobre
   fondo claro— y sobre el carbón se veían como un marco lechoso alrededor del
   hero. Si alguna vez se vuelve a un fondo claro, hay que girarlos de nuevo. */
.hero__shade {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(90deg, rgba(0, 0, 0, 0.96) 0%, rgba(0, 0, 0, 0.74) 17%, rgba(0, 0, 0, 0) 33%),
    linear-gradient(270deg, rgba(0, 0, 0, 0.96) 0%, rgba(0, 0, 0, 0.7) 15%, rgba(0, 0, 0, 0) 30%),
    linear-gradient(180deg, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0) 14%),
    linear-gradient(0deg, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0) 16%);
}

@media (max-width: 960px) {
  /* AQUÍ ESTABA EL BUG DEL VÍDEO EN CELULAR (19-ago-2026).
     Este velo es del hero 3D: tapaba el lienzo WebGL para que el texto blanco
     que iba ENCIMA se pudiera leer. Pero se aplicaba siempre, corriera el 3D o
     no, y desde que la portada enseña el vídeo el resultado era que el vídeo se
     veía a través de una cortina negra al 95 %: gris, apagado y sin color.
     Y solo pasaba por debajo de 960 px — de ahí el "en la computadora se ve
     bien y en el celular no".
     Ahora el velo es SOLO del 3D (.hero--on, regla de abajo). Sin 3D no hay
     nada que tapar: en el celular el texto va DEBAJO del vídeo, no encima, y
     entre 861 y 960 px lo que sostiene la lectura es la sombra radial de
     .hero__content / .hero__stats más el text-shadow, igual que en escritorio.
     Si algún día vuelve el lienzo WebGL, el velo vuelve solo con .hero--on. */
  .hero--3d:not(.hero--on) .hero__shade {
    background: none;
  }

  .hero__shade {
    background:
      linear-gradient(180deg, rgba(0, 0, 0, 0.95) 0%, rgba(0, 0, 0, 0.82) 55%, rgba(0, 0, 0, 0.96) 100%);
  }

  /* Con el 3D activo el velo deja LIBRE la banda de arriba —ahí caen los
     paracaídas— y tapa del todo la de abajo, donde vive el texto.

     El corte es más brusco de lo que parece razonable a propósito: con el
     degradado suave de antes, una caja clara (Creative Cloud, que es un arcoíris
     a pantalla completa) seguía leyéndose por debajo del titular aunque el velo
     ya iba al 78 %. Sobre negro puro hace falta llegar al 100 % justo donde
     empieza el texto, y ese punto es el mismo padding-top que se reserva más
     abajo — si tocas uno, mueve el otro. */
  .hero--on .hero__shade {
    background:
      linear-gradient(180deg,
        rgba(0, 0, 0, 0.1) 0%,
        rgba(0, 0, 0, 0.04) 16%,
        rgba(0, 0, 0, 0.16) 28%,
        rgba(0, 0, 0, 0.9) 40%,
        rgba(0, 0, 0, 1) 50%,
        rgba(0, 0, 0, 1) 100%);
  }
}

/* Lienzo WebGL: entra con fundido cuando las texturas están listas.
   pointer-events none es OBLIGATORIO: en modo tour el lienzo es fijo a pantalla
   completa y sin esto se tragaba los clics del footer (los clics sobre las
   cajas 3D se resuelven por raycast en document, no en el canvas). */
.hero__gl {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity 1s var(--ease-out);
  pointer-events: none;
}

.hero--on .hero__gl.is-on {
  opacity: 1;
}

/* --- Continuidad hero → catálogo (html.hd-fija, la pone hero-drop.js) ---------
   El lienzo deja de vivir DENTRO del hero y pasa a estar fijo a la pantalla,
   por detrás de todo. Así la caída no se corta cuando el hero sale: al bajar,
   las cajas frenan, se ponen en fila y la vitrina llega justo encima, de modo
   que el salto de un apartado a otro no se nota.

   El apilado es explícito porque aquí importa el orden exacto:
     1  el lienzo (fijo, detrás de todo)
     2  el hero y la vitrina, con sus fondos
     3  el texto y los controles dentro de ellos

   Y el fondo del hero se vuelve transparente: si no, su negro opaco taparía el
   lienzo que acaba de pasar por detrás. El negro del <body> sigue debajo, así
   que no se ve ningún hueco. La opacidad del lienzo la maneja el guion (se
   apaga al terminar la transición), por eso aquí se le quita la transición CSS:
   con las dos cosas a la vez, el fundido iba siempre un segundo por detrás del
   scroll y se sentía pegajoso. */
html.hd-fija .hero__gl {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  opacity: 0;
  transition: none;
  pointer-events: none;
}

html.hd-fija .hero--3d,
html.hd-fija .s-productos {
  position: relative;
  z-index: 2;
}

html.hd-fija .hero--3d .hero__sticky {
  background: transparent;
}

html.hd-fija .hero--3d .hero__sticky > .container {
  z-index: 3;
}

/* Los fondos de las secciones se destapan: el lienzo va por DETRÁS de ellas, y
   con sus fondos opacos la caída se acababa en el hero — que es justo lo que
   había que evitar. Quien mantiene el texto legible ya no es un panel opaco,
   sino la maquetación del recorrido (html.h3d-tour, más abajo): el contenido se
   va a un lado y la caída al otro, así que nunca se pisan.

   El pie SÍ conserva su fondo y sube por encima: ahí termina el recorrido. */
html.hd-fija .s-productos {
  background: none;
}

html.hd-fija .section--alt {
  background: none;
}

html.hd-fija .site-footer {
  position: relative;
  z-index: 2;
}

/* Relevo del hero: la constelación NO se oculta por umbral de scroll (eso
   dejaba un tramo VACÍO al subir del catálogo al hero, en celular y en
   escritorio: el lienzo seguía escondido hasta retroceder media pista). En su
   lugar, la vitrina llega con fondo propio y borde superior en degradado
   (regla .s-productos más abajo): al bajar CUBRE al hero y al subir lo
   DESCUBRE al instante, sin huecos en ninguna dirección. */
.s-productos {
  background: var(--bg);
  background: linear-gradient(180deg, color-mix(in srgb, var(--bg) 0%, transparent), var(--bg) clamp(90px, 16vh, 150px));
}

/* --- Modo vivo (solo escritorio): hero de un viewport --------------------------
   Sin acto 2: al bajar, la constelación viaja en tornado al lado libre de cada
   sección (modo tour, ver bloque html.h3d-tour abajo). En ≥1101px se suma una
   pista corta de relevo (bloque siguiente) que fija el hero y lo disuelve. */
@media (min-width: 961px) {

  /* La altura de "modo vivo" se aplica SIEMPRE (no solo con .hero--live): el
     3D arranca diferido tras la carga y, si el hero creciera recién entonces,
     toda la página daba un salto de layout al refrescar (el "parpadeo"). */
  .hero--3d .hero__sticky {
    min-height: 100vh;
    min-height: 100svh;
  }

  .hero--live .hero__content,
  .hero--live .hero__stats {
    will-change: transform, opacity;
  }

  /* El texto deja pasar el puntero al lienzo; botones y enlaces siguen vivos */
  .hero--live .hero__content,
  .hero--live .hero__stats {
    pointer-events: none;
  }

  .hero--live :is(.hero__content, .hero__stats) :is(a, button) {
    pointer-events: auto;
  }

  /* Relevo suave: el panel de respaldo se funde mientras el lienzo 3D entra
     (antes era display:none y el cambio se veía como un destello). */
  .hero__visual {
    transition: opacity 0.6s var(--ease-out);
  }

  .hero--on .hero__visual {
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.6s var(--ease-out), visibility 0s 0.6s;
  }

  /* Y si la sonda de index.html ya sabe que el 3D viene (html.h3d-wait), el
     panel de respaldo NO se pinta nunca: el centro queda limpio y la
     constelación aparece directa con su fundido. Si el 3D falla, la clase se
     quita y el panel entra fundiéndose (transición de arriba). */
  html.h3d-wait .hero__visual {
    opacity: 0;
  }
}

/* --- Relevo del hero (tour ≥1101px, con movimiento permitido) ------------------
   El hero se queda QUIETO (sticky) mientras una pista corta de scroll extra lo
   disuelve en su propio sitio; recién cuando terminó de fundirse, el catálogo
   sube y toma su lugar. Sin esto, el home se escapaba hacia arriba a velocidad
   de scroll y el apartado siguiente "se posicionaba arriba de inmediato" (el
   salto agresivo). La pista existe desde la primera pintura (no depende de
   .hero--live) para no dar saltos de layout cuando el 3D arranca diferido; el
   fundido lo hace hero3d.js (updateDom) o, sin WebGL, cinematic.js. Con
   movimiento reducido no hay pista: hero clásico de un viewport. */
@media (min-width: 1101px) and (prefers-reduced-motion: no-preference) {
  /* SIN pista de relevo (20-jul-2026, tras varias vueltas con el dueño): el
     hero fijado siempre dejaba una cola fea — iconos sobrepuestos al catálogo
     al bajar, o un tramo vacío al subir. Ahora el hero FLUYE con el scroll
     como cualquier sección (la constelación sube con él, siempre visible) y
     la vitrina llega enseguida, fundiendo la unión con su degradado. */
  .hero--3d {
    min-height: 100vh;
  }

  /* Solape corto: la vitrina muerde apenas el borde inferior del hero para
     que el degradado cosa la unión (sin tapar el contenido). */
  .s-productos {
    position: relative;
    z-index: 2;
    margin-top: -5vh;
  }
}

/* --- Relevo del hero en móvil y tablet (con movimiento permitido) --------------
   Misma sensación que en escritorio: un espaciador tras el sticky (::after,
   neutralizando la capa decorativa absoluta de home.css) da una pista corta en
   la que el hero queda QUIETO disolviéndose en su sitio; el fundido lo hace
   updateDom() de hero3d.js (o cinematic.js sin WebGL) leyendo la pista real. */
@media (max-width: 1100px) and (prefers-reduced-motion: no-preference) {
  /* Sin espaciador de relevo (misma razón que en escritorio): el ::after solo
     queda para NEUTRALIZAR la capa decorativa absoluta de home.css. El hero
     fluye con el scroll y la vitrina llega justo detrás, cosida por su
     degradado con un mordisco mínimo. */
  .hero--3d::after {
    content: "";
    position: static;
    inset: auto;
    display: block;
    height: 0;
    background: none;
    z-index: auto;
  }

  .s-productos {
    position: relative;
    z-index: 2;
    margin-top: -2vh;
  }
}

/* --- Tour 3D por toda la página (hero3d.js pone html.h3d-tour en ≥1101px) ------
   El lienzo pasa a ser FIJO a pantalla completa (z 1). Los contenedores de las
   secciones suben a z 2 (el 3D pasa por detrás del contenido y por delante de
   los fondos). Cada sección [data-h3d] deja libre la mitad donde vive el 3D. */
html.h3d-tour .hero__gl {
  position: fixed;
  inset: 0;
  z-index: 1;
}

html.h3d-tour main .container {
  position: relative;
  z-index: 2;
}

/* Ya no existe crossfade por scroll: no reservamos capas grandes de composición
   permanentemente, reduciendo memoria gráfica y repintados. */
@media (min-width: 1101px) {

  /* Cada apartado ocupa ~58vw pegado a su lado (el 3D vive en el otro) y se
     extiende hacia el CENTRO para aprovechar el vacío (petición del dueño:
     "así como está en nuestros productos, en todos los apartados"). */
  html.h3d-tour [data-h3d="left"]>.container {
    width: min(58vw, 1400px);
    margin-inline: auto clamp(1.5rem, 4vw, 4.5rem);
  }

  html.h3d-tour [data-h3d="right"]>.container {
    width: min(58vw, 1400px);
    margin-inline: clamp(1.5rem, 4vw, 4.5rem) auto;
  }

  /* Capítulos con la constelación disuelta (data-h3d-hide): no hay 3D al
     costado que respetar, así que el contenido vuelve a centrarse a lo
     ancho (la vitrina de productos vive aquí desde el 20-jul-2026). */
  html.h3d-tour [data-h3d][data-h3d-hide]>.container {
    width: 100%;
    margin-inline: auto;
  }

  /* Cabecera editorial en TODAS las secciones: titular grande a la izquierda
     y su párrafo al lado derecho (aplica también al sub-título de la demo). */
  html.h3d-tour [data-h3d] .sec-head {
    align-items: center;
  }

  html.h3d-tour [data-h3d] .sec-head__t {
    display: grid;
    grid-template-columns: auto minmax(22ch, 34ch);
    gap: 0.4rem clamp(2rem, 4vw, 4.5rem);
    align-items: center;
  }

  html.h3d-tour [data-h3d] .sec-head__t .sec-eyebrow {
    grid-column: 1 / -1;
  }

  html.h3d-tour [data-h3d] .sec-head__t p {
    margin-top: 0;
  }

  /* Si el enlace baja de línea (anchos medios), que siga pegado a la derecha */
  html.h3d-tour [data-h3d] .sec-head>.btn-link {
    margin-left: auto;
  }

  html.h3d-tour .s-productos .product-grid {
    grid-template-columns: repeat(2, minmax(0, 340px));
  }

  /* Cómo funciona: los 5 pasos en 3 columnas (3 + 2), sin la línea punteada */
  html.h3d-tour .flow {
    grid-template-columns: repeat(3, 1fr);
    gap: 1.5rem 2.25rem;
  }

  html.h3d-tour .flow::before {
    display: none;
  }

  /* Demo: la lista Eliges→Activas va HORIZONTAL sobre la pantalla simulada */
  html.h3d-tour .demo {
    grid-template-columns: 1fr;
  }

  html.h3d-tour .demo__steps {
    position: static;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.25rem 1.75rem;
  }

  html.h3d-tour .demo-step:not(:last-child)::after {
    display: none;
  }

  /* Soporte y FAQ conservan sus DOS columnas de siempre (texto+chat /
     aside+lista): con el bloque a 58vw vuelven a caber con holgura. */
}

/* En pantallas muy anchas, rejilla 3×2 centrada (6 destacados parejos) */
@media (min-width: 2000px) {
  html.h3d-tour .s-productos .product-grid {
    grid-template-columns: repeat(3, minmax(0, 340px));
  }
}

/* --- Ficha del producto bajo el cursor (hover sobre una caja) ----------------- */
.hero__tip {
  position: fixed;
  z-index: 320;
  left: 0;
  top: 0;
  pointer-events: none;
  padding: 0.55rem 0.8rem;
  border-radius: var(--r);
  background: var(--surface-2);
  border: 1px solid var(--border);
  box-shadow: 0 14px 34px oklch(0.35 0.06 51 / 0.18);
  color: var(--ink);
  font-size: 0.82rem;
}

.hero__tip b {
  display: block;
  font-family: var(--font-display);
  font-size: 0.92rem;
  letter-spacing: -0.01em;
}

.hero__tip span {
  color: var(--brand);
  font-weight: 700;
}

.hero__tip small {
  display: block;
  color: var(--ink-faint);
  margin-top: 2px;
  font-size: 0.72rem;
}

/* --- Pista de scroll abajo-izquierda (línea + texto, como Ari) ----------------- */
.hero__cue {
  position: absolute;
  left: clamp(1.25rem, 4vw, 3rem);
  bottom: 1.5rem;
  z-index: 4;
  display: none;
  align-items: center;
  gap: 0.85rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  white-space: nowrap;
}

@media (min-width: 961px) {
  .hero--on .hero__cue {
    display: inline-flex;
  }
}

.cue__line {
  width: 1px;
  height: 2.4rem;
  background: oklch(0.82 0.006 250);
  flex: none;
}

/* --- Móvil: escenario 3D arriba (a plena vista) + contenido compacto debajo ---- */
@media (max-width: 960px) {
  .hero--on .hero__gl.is-on {
    opacity: 1;
  }

  .hero__act2,
  .hero__cue,
  .hero__tip {
    display: none !important;
  }

  /* Sin 3D en el celular (three.js pesaba varios segundos de carga ahí), la
     tarjeta compacta de activación vuelve a ser el visual del hero: es DOM +
     CSS puro, no cuesta nada y mantiene el hero con vida. home.css la oculta
     en angosto por defecto; aquí se re-activa solo para el hero 3D. */
  .hero--3d .hero__visual {
    display: block;
    width: min(400px, 100%);
    /* margen superior corto: en el celular el hero debe sentirse compacto */
    margin: 1.25rem auto 0.4rem;
  }

  /* Con el 3D en camino (sonda h3d-wait) la tarjeta no parpadea: invisible
     pero guardando su sitio. Con el 3D ya VIVO (hero--live) se retira del
     todo — en el celular el visual del hero es la constelación (20-jul-2026);
     la banda superior --h3dStage toma su lugar con transición. Si el 3D
     falla, las clases se quitan y la tarjeta vuelve sola. */
  html.h3d-wait .hero--3d .hero__visual {
    opacity: 0;
  }

  /* Se retira en cuanto el lienzo está vivo. Antes esto colgaba SOLO de
     .hero--live, que era la marca de la constelación; la entrega en paracaídas
     usa .hero--on y ocupa todo el hero, sin banda aparte, así que sin esta
     segunda condición el celular mostraba la tarjeta y el 3D a la vez, uno
     encima del otro. Si el 3D falla, ninguna clase llega y la tarjeta se
     queda, que es justo lo que tiene que pasar. */
  .hero--live .hero__visual,
  .hero--on .hero__visual {
    display: none;
  }

  .hero--3d .hero__beam {
    display: none;
  }

  /* hero3d.js fija --h3dStage (alto de la banda del 3D) y centra ahí la
     constelación; sin WebGL la variable no existe y no se reserva nada.
     La banda se reserva desde .hero--live (apenas hay 3D seguro) y con
     transición: el contenido baja suave una sola vez, no de golpe. */
  .hero__ari {
    transition: padding-top 0.5s var(--ease-out);
  }

  .hero--live .hero__ari {
    padding-top: var(--h3dStage, 0px);
  }

  /* Entrega en paracaídas: en el celular el hero es UNA columna, así que los
     bultos necesitan banda propia arriba. Cayendo por detrás del texto no se
     leía ni una cosa ni la otra. No hace falta recortar el lienzo: el velo de
     más arriba ya oscurece de la mitad para abajo, o sea que basta con empujar
     el contenido hasta ahí y los paracaídas se disuelven solos en negro
     mientras bajan, sin un corte duro que delate el truco. */
  .hero--on .hero__ari {
    padding-top: min(38vh, 290px);
  }

  .hero--live .hero__sticky {
    padding-block: 1.25rem 1.75rem;
  }

  .hero__brand {
    font-size: clamp(2.6rem, 14vw, 3.4rem);
  }

  .hero--3d .hero__lede {
    margin-top: 0.9rem;
  }

  .hero__stats {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.9rem 1.1rem;
    margin-top: 0.4rem;
  }

  /* Dos cifras por fila; `flex-grow` hace que la última se estire sola si queda
     impar. SIN divisor vertical (30-jul-2026): el divisor se ponía con
     `nth-child(odd)`, y eso se rompió al añadir cifras que NACEN OCULTAS
     ("Productos vendidos" y "Precios desde" solo salen si hay dato): la
     posición en el HTML dejó de decir en qué columna cae cada una y las rayas
     aparecían del lado equivocado. El espaciado ya separa de sobra. */
  .hstat {
    flex: 1 1 40%;
    min-width: 0;
    border-top: 0;
    border-left: 0;
    padding: 0.2rem 0;
  }

  .hstat b {
    font-size: 1.5rem;
  }

  /* 0.58rem eran 9,3 px: el bloque de confianza del hero ("PRODUCTOS VENDIDOS",
     "GARANTÍA DE ACTIVACIÓN") es lo primero que ve quien llega de un anuncio y
     en el celular quedaba MÁS chico que en escritorio (0.66rem). Se sube al
     mismo tamaño y se recorta el tracking, que es lo que hacía falta espacio.
     (29-jul-2026) */
  .hstat > span {
    font-size: 0.66rem;
    letter-spacing: 0.08em;
  }

  .hero__stats {
    flex-wrap: wrap;
  }
}

/* Con movimiento reducido, hero3d.js no arranca; por si acaso, el lienzo fuera. */
@media (prefers-reduced-motion: reduce) {
  .hero__gl {
    display: none;
  }
}

/* --- Formato VERTICAL ancho (monitor rotado, ventana alta, ≥961px) -------------
   La constelación SÍ corre, pero con composición propia: vive en la mitad
   superior del hero y el contenido baja en dos columnas (marca | cifras). El
   tour queda apagado (hero3d.js): en vertical las secciones no tienen costado
   libre. Sin pista de relevo: min-height 100svh más 40–60vh de pista, pensados
   para paisaje, dejaban un vacío enorme en un viewport tan alto. Van al final
   del archivo a propósito: ganan por orden a las reglas de arriba. */
@media (min-width: 961px) and (max-aspect-ratio: 9/10) {
  .hero--3d {
    min-height: 0;
  }

  .hero--3d::after {
    content: none;
  }

  .hero--3d .hero__sticky {
    position: relative;
    top: auto;
    min-height: min(calc(100svh - var(--headerH, 4.5rem)), 720px);
  }

  .s-productos {
    margin-top: 0;
  }

  /* Con el 3D vivo (o en camino: h3d-wait), el hero crece a media pantalla
     alta y el contenido se alinea ABAJO; la banda superior es del 3D. Si el
     3D falla, h3d-wait se quita y vuelve el hero compacto con su panel. */
  .hero--live .hero__sticky,
  html.h3d-wait .hero__sticky {
    min-height: min(calc(88svh - var(--headerH, 4.5rem)), 1460px);
    align-items: flex-end;
  }

  .hero--live .hero__ari,
  html.h3d-wait .hero__ari {
    padding-bottom: clamp(1.5rem, 4svh, 4rem);
  }

  /* Dos columnas: la marca a la izquierda, las cifras a la derecha. El panel
     de respaldo no se pinta (el centro es del lienzo). */
  .hero--on .hero__sticky>.container.hero__ari,
  html.h3d-wait .hero__sticky>.container.hero__ari {
    grid-template-columns: minmax(0, 1.5fr) minmax(230px, 1fr);
  }

  .hero--on .hero__ari .hero__visual,
  html.h3d-wait .hero__ari .hero__visual {
    display: none;
  }

  .hero--on .hero__ari .hero__stats,
  html.h3d-wait .hero__ari .hero__stats {
    grid-column: 2;
  }
}

/* --- Portada con el vídeo en el centro (19-ago-2026, pedido del dueño) --------
   Antes la retícula eran dos columnas dentro del .container de 1520 px: en un
   monitor ancho las dos caían encima del dibujo del vídeo, que vive en el
   medio. Ahora la retícula se sale del contenedor y usa TODO el ancho, con una
   tercera columna vacía en medio: la bienvenida se pega al canto izquierdo, las
   cifras al derecho, y el centro queda libre para la pieza.

   Los anchos van en minmax(0, …) y no en fr: lo que manda aquí es que el hueco
   del medio no se coma nunca a los costados ni al revés. El tope de 26rem sale
   del ancho del menú (22rem) más su aire; el de 18rem, del mínimo de las cifras
   (250 px) más el suyo.

   Va al FINAL del archivo a propósito: gana por orden a las retículas de arriba
   sin tener que inflar el selector.
   Este archivo es el último que carga index.html, así que también gana a
   home.css. */
@media (min-width: 961px) {
  .hero--3d .hero__sticky>.container.hero__ari {
    max-width: none;
    padding-inline: clamp(1.25rem, 3vw, 3.25rem);
    grid-template-columns: minmax(0, 26rem) minmax(0, 1fr) minmax(0, 18rem);
    gap: clamp(1rem, 2.5vw, 2.5rem);
  }

  .hero__ari .hero__content {
    grid-column: 1;
    grid-row: 1;
  }

  .hero__ari .hero__stats {
    grid-column: 3;
    grid-row: 1;
  }
}
