  /* EL SET — ahora la vitrina NO es CSS: es el render. El marco, el vidrio, el
     panel piramidal, el piso y la sombra vienen dentro de la imagen, que es la
     única forma de que tenga profundidad real. El CSS solo hace tres cosas:
     colocar las vitrinas en el riel, apagar las de los lados y encender la del
     centro. Pieza de un mundo visual propio: todo color va explícito. */
  :root{
    --sala:#08090E; --sala2:#12141C;
    --papel:#F2F0EB; --tintaPapel:#16181D;
    --luz:#B399D2;                 /* lo reescribe el JS por personaje */
    --ease:cubic-bezier(.22,1,.36,1);
  }
  *,*::before,*::after{box-sizing:border-box}
  html,body{height:100%}
  body{
    margin:0; overflow:hidden; color:#EDEAF2;
    font-family:Inter,system-ui,-apple-system,"Segoe UI",sans-serif;
    -webkit-font-smoothing:antialiased;
    background:radial-gradient(120% 90% at 50% 6%, var(--sala2) 0%, var(--sala) 60%), var(--sala);
  }
  h1,p{margin:0}
  .anton{font-family:Anton,Impact,sans-serif; font-weight:400; text-transform:uppercase; letter-spacing:-.015em}

  .sala{position:relative; width:100%; height:100svh; min-height:400px; overflow:hidden; touch-action:none}
  html.sin-cursor, html.sin-cursor *{cursor:none !important}

  /* el resplandor de la sala toma el color del nahual encendido */
  .aura{
    position:absolute; inset:0; z-index:0; pointer-events:none;
    background:radial-gradient(58% 48% at 50% 44%,
      color-mix(in srgb, var(--luz) 34%, transparent) 0%,
      color-mix(in srgb, var(--luz) 12%, transparent) 40%,
      transparent 76%);
    transition:background 1s var(--ease);
  }
  .piso-sala{
    position:absolute; inset-inline:0; bottom:0; height:38%; z-index:1; pointer-events:none;
    background:linear-gradient(to top, rgba(0,0,0,.72), transparent);
  }

  /* ============================ RIEL ============================ */
  .riel{position:absolute; inset:0; z-index:5; perspective:1900px; perspective-origin:50% 44%}
  .vit{
    position:absolute; top:var(--anclaY,50%); left:50%;
    width:var(--cw,320px); height:calc(var(--cw,320px) / .7471);
    margin:calc(var(--cw,320px) / .7471 / -2) 0 0 calc(var(--cw,320px) / -2);
    transform-style:preserve-3d; will-change:transform,filter,opacity; cursor:pointer;
  }
  /* .caja es lo que "vive": respira, se inclina hacia el puntero. El riel mueve
     .vit; la personalidad mueve .caja. Separarlos evita que una pelee con otra. */
  /* El render trae su propio piso de estudio, un pelín más claro que la sala.
     Sin esta máscara el borde de la imagen se ve como un rectángulo pegado
     encima —el defecto de "estampita"—; así la vitrina se funde con el cuarto. */
  .caja{
    position:absolute; inset:0; transform-style:preserve-3d; will-change:transform;
    -webkit-mask-image:
      linear-gradient(to right, transparent 0, #000 8%, #000 92%, transparent 100%),
      linear-gradient(to bottom, transparent 0, #000 6%, #000 94%, transparent 100%);
    mask-image:
      linear-gradient(to right, transparent 0, #000 8%, #000 92%, transparent 100%),
      linear-gradient(to bottom, transparent 0, #000 6%, #000 94%, transparent 100%);
    -webkit-mask-composite:source-in; mask-composite:intersect;
  }
  .capa{
    position:absolute; inset:0; width:100%; height:100%;
    object-fit:contain; object-position:center center;
    display:block; user-select:none; -webkit-user-drag:none;
  }
  .capa.on{opacity:0; will-change:opacity}       /* fuego / hielo */
  .capa.vid{opacity:0}                            /* solo cuando está al frente */
  .bicho{transition:opacity .3s ease}
  /* OJO: estas dos reglas SOLO valen para la vitrina que tiene video (el
     camaleón). Sin `.conVideo` el selector alcanzaba a las tres, y al centrarse
     el Chico o el Encapuchado su imagen base se ponía en opacity:0 — quedaban
     invisibles justo cuando les tocaba el foco. Ese era el bug. */
  /* ===================== EL CRISTAL RETUMBA =====================
     Antes hacía vibrar `.caja`, que contiene la vitrina ENTERA — se movía el
     mueble, el suelo y el reflejo. Un cristal que vibra no desplaza el mueble:
     lo que se mueve son sus BRILLOS. Los cantos especulares zumban y se
     emborronan, y eso es exactamente lo que hace esta capa.

     Los cuatro montantes verticales del render están medidos (detección de
     bordes Sobel sobre el propio render): x = 0.15, 0.383, 0.675 y 0.84. Cada
     destello se coloca encima del suyo. */
  .cristal{position:absolute; inset:0; pointer-events:none; overflow:hidden; opacity:var(--vib,0)}
  .cristal i{
    position:absolute; top:12%; height:71%; width:3px; border-radius:2px;
    background:linear-gradient(to bottom,
      transparent 0%, color-mix(in srgb, var(--luz) 55%, white) 18%,
      color-mix(in srgb, var(--luz) 85%, white) 50%,
      color-mix(in srgb, var(--luz) 40%, white) 78%, transparent 100%);
    mix-blend-mode:screen; will-change:transform, filter;
  }
  .cristal i:nth-child(1){left:14.6%}
  .cristal i:nth-child(2){left:38.0%}
  .cristal i:nth-child(3){left:67.2%}
  .cristal i:nth-child(4){left:83.7%}
  /* el paño de vidrio frontal: un velo ancho que respira con el golpe */
  .cristal u{
    position:absolute; left:38%; width:29.2%; top:12%; height:71%;
    background:linear-gradient(112deg, transparent 8%,
      color-mix(in srgb, var(--luz) 22%, white) 42%, transparent 70%);
    mix-blend-mode:screen; opacity:.5; will-change:transform;
  }
  /* LA GRIETA. Solo la abre el portal, nunca el bajo. Es un trazo fijo
     dibujado a mano sobre el paño frontal; `--grieta` (0→1) va soltando el
     dash, así que la fractura CRECE en vez de aparecer de golpe. */
  .cristal .fisura{
    position:absolute; left:38%; width:29.2%; top:12%; height:71%;
    overflow:visible; mix-blend-mode:screen; pointer-events:none;
    opacity:calc(var(--grieta,0) * 1.0);
  }
  .cristal .fisura path{
    fill:none; stroke:#fff; stroke-width:.9; vector-effect:non-scaling-stroke;
    stroke-dasharray:1; stroke-dashoffset:calc(1 - var(--grieta,0));
    filter:drop-shadow(0 0 calc(2px + var(--grieta,0) * 7px) color-mix(in srgb, var(--luz) 90%, white));
  }
  .cristal .fisura path:last-child{ stroke-width:.5; opacity:.75 }
  @media (prefers-reduced-motion:reduce){ .cristal{display:none} }

  /* La animación de transformación de Kairo. Mientras corre, ella es la imagen;
     al terminar se congela y toma el relevo la foto fija, que es exactamente el
     mismo cuadro — por eso el cambio no se ve. */
  .capa.trans{opacity:0; transition:opacity .25s ease}
  /* el bucle del cabeceo releva a la foto fija en cuanto entra la música */
  .capa.bob{opacity:0; transition:opacity .3s ease}
  .vit.cabeceando .capa.bob{opacity:1}
  .vit.cabeceando .capa.on{opacity:0 !important}
  .vit.transformando .capa.trans{opacity:1}
  .vit.transformando .capa.base,
  .vit.transformando .capa.on{opacity:0 !important}

  /* la escena de la mosca se monta encima del barrido y se cruza con él */
  /* hay tres lengüetazos apilados; solo el elegido se muestra */
  .capa.lengua{opacity:0; transition:opacity .28s ease}
  .vit:not(.conVideo) .capa.lengua{display:none}
  .vit.comiendo .capa.lengua.activa{opacity:1}
  .vit.comiendo .capa.vid{opacity:0}
  .capa.vid{transition:opacity .28s ease}

  /* NUNCA se esconde la foto base hasta que el video esté REALMENTE listo.
     Este era el bug de móvil: la regla escondía la base en cuanto la vitrina
     pasaba al frente, pero los navegadores de móvil ignoran `preload` con
     frecuencia (datos móviles, ahorro de batería, iOS sin interacción previa).
     Resultado: base oculta + video sin decodificar = vitrina VACÍA, y solo se
     veía la mosca flotando. Ahora la clase `videoOk` la pone el JS cuando
     readyState >= 2, y si el video falla la foto se queda para siempre. */
  .vit.conVideo.videoOk.frente .capa.vid{opacity:1}
  .vit.conVideo.videoOk.frente .capa.base{opacity:0}
  .vit:not(.frente) .capa.vid{display:none}

  /* Halo: el aliento del poder. No sustituye al render de fuego/hielo —lo
     acompaña— porque un gradiente CSS nunca va a iluminar el interior de la
     cabina como lo hace la imagen. Solo respira encima de ella.
     El voxel respira a saltos: si lo suavizas deja de estar hecho de cubos. */
  .halo{
    position:absolute; left:0; right:0; bottom:6%; height:74%;
    pointer-events:none; mix-blend-mode:screen; opacity:calc(var(--on,0) * .55);
    background:radial-gradient(46% 42% at 50% 62%,
      color-mix(in srgb, var(--luz) 62%, white) 0%,
      color-mix(in srgb, var(--luz) 26%, transparent) 46%, transparent 74%);
    animation:aliento 2.1s ease-in-out infinite alternate;
    transition:opacity .5s ease;
  }
  /* sin transición: el voxel enciende de golpe, no se funde */
  .vit.voxel .halo{animation:aliento 1.15s steps(3) infinite alternate; transition:none}
  .vit.voxel .charco{transition:none}
  @keyframes aliento{
    from{transform:scale(.93) translateY(6px); filter:blur(6px)}
    to  {transform:scale(1.07) translateY(-5px); filter:blur(11px)}
  }
  @media (prefers-reduced-motion:reduce){ .halo{animation:none} }

  /* ===================== EL CONTRALUZ =====================
     Esto es lo que arregla que el viaje se viera PLANO. Antes, al abrirse el
     portal, la cabina seguía iluminada exactamente igual: la sala cambiaba de
     color pero el objeto del centro no se enteraba. Un portal que se abre
     detrás de algo tiene que CONTRALUZAR ese algo.

     Dos cosas a la vez, y las dos las manda `--cl` (0→1, la carga):
       · un halo de luz que crece detrás de la vitrina
       · la propia vitrina que se apaga y gana contraste — que es exactamente
         lo que le pasa a un objeto cuando le nace una luz detrás
     El resultado es una silueta, no una foto plana con un filtro verde. */
  .contraluz{
    position:absolute; left:-40%; top:-30%; width:180%; height:160%;
    pointer-events:none; opacity:var(--cl,0); mix-blend-mode:screen;
    background:radial-gradient(42% 46% at 50% 44%,
      color-mix(in srgb, var(--luz) 92%, white) 0%,
      color-mix(in srgb, var(--luz) 55%, transparent) 34%,
      color-mix(in srgb, var(--luz) 18%, transparent) 60%, transparent 78%);
    transform:scale(calc(.45 + var(--cl,0) * .75));
    will-change:transform, opacity;
  }
  /* la silueta: se oscurece y se endurece según entra la luz por detrás */
  .vit.frente .caja{
    filter:brightness(calc(1 - var(--cl,0) * .62)) contrast(calc(1 + var(--cl,0) * .45))
           saturate(calc(1 - var(--cl,0) * .3));
  }

  /* charco de luz que la vitrina encendida derrama en el piso de la sala */
  .charco{
    position:absolute; left:50%; bottom:-4%; width:150%; height:26%;
    transform:translateX(-50%); pointer-events:none; opacity:var(--on,0);
    background:radial-gradient(50% 50% at 50% 50%,
      color-mix(in srgb, var(--luz) 46%, transparent), transparent 72%);
    filter:blur(16px); mix-blend-mode:screen; transition:opacity .6s ease;
  }
  /* Barra de progreso del tema, en la base del cristal. Fina de verdad: si se
     nota como UI, deja de ser parte de la vitrina. */
  .progreso{
    position:absolute; left:9%; right:9%; bottom:11.5%; height:2px;
    background:rgba(255,255,255,.07); border-radius:2px; overflow:hidden;
    opacity:0; transition:opacity .5s ease; pointer-events:none;
  }
  .vit.sonando .progreso{opacity:1}
  .progreso i{
    display:block; height:100%; width:100%; transform:scaleX(0); transform-origin:left center;
    background:linear-gradient(90deg,
      color-mix(in srgb, var(--luz) 55%, transparent),
      color-mix(in srgb, var(--luz) 95%, white));
    box-shadow:0 0 8px color-mix(in srgb, var(--luz) 80%, transparent);
  }

  .placa{
    position:absolute; inset-inline:0; bottom:-22px; text-align:center;
    font-size:9.5px; font-weight:700; letter-spacing:.22em; text-transform:uppercase;
    color:rgba(237,234,242,.28); transition:color .5s ease; pointer-events:none;
  }
  .vit.frente .placa{color:color-mix(in srgb, var(--luz) 78%, white)}

  /* ============================ TÍTULO ============================ */
  .titulo{
    position:absolute; z-index:20; left:50%; transform:translateX(-50%);
    bottom:clamp(70px,8vh,104px); width:min(660px,90vw); text-align:center; pointer-events:none;
  }
  .titulo h1{
    font-size:clamp(38px,6.2vw,88px); line-height:.9; color:#F7F4FB;
    text-shadow:0 0 46px color-mix(in srgb, var(--luz) 50%, transparent);
    transition:text-shadow .8s var(--ease);
  }
  .titulo p{
    margin:13px auto 0; max-width:44ch;
    font-size:clamp(12.5px,1.1vw,15px); line-height:1.6; color:rgba(247,244,251,.58);
  }
  .titulo .cambio{animation:sube .55s var(--ease)}
  @keyframes sube{from{opacity:0; transform:translateY(10px)} to{opacity:1; transform:none}}

  /* ===================== PORTAL Y UNIVERSO =====================
     Tres modos: `portal` (el riel, lo de siempre), `transicion` (el hold en
     curso) y `universo` (dentro del mundo del personaje).
     `--carga` va de 0 a 1 durante el hold y es lo que mueve todo. */
  .sala{--carga:0; --dim:0}
  /* (10 sep) temblor dimensional de la sala entera: dos capas desfasadas para
     que no se lea como un parpadeo. Solo transform: lo hace el compositor. */
  .sala.cargando .riel{animation:temblorDim .09s steps(2) infinite; will-change:transform}
  @keyframes temblorDim{0%{transform:translate3d(calc(var(--dim) * -3px), calc(var(--dim) * 1px),0)}50%{transform:translate3d(calc(var(--dim) * 3px), calc(var(--dim) * -2px),0)}100%{transform:translate3d(0,calc(var(--dim) * 1.5px),0)}}
  .sala.cargando .aura{animation:pulsoDim .35s ease-in-out infinite alternate}
  @keyframes pulsoDim{from{filter:brightness(1)}to{filter:brightness(calc(1 + var(--dim) * .6))}}

  /* El portal se abre DETRÁS de la vitrina: una grieta vertical de luz que
     crece. Nunca por delante, porque el cuerpo del personaje tiene que leerse
     en todo momento. */
  #portal{
    position:absolute; inset:0; z-index:4; pointer-events:none; opacity:0;
    display:flex; align-items:center; justify-content:center;
  }
  #portal .grieta{
    width:calc(2px + var(--carga) * 46vmin);
    height:calc(18vmin + var(--carga) * 92vmin);
    border-radius:50%;
    background:radial-gradient(50% 50% at 50% 50%,
      color-mix(in srgb, var(--luz) 95%, white) 0%,
      color-mix(in srgb, var(--luz) 70%, transparent) 32%,
      color-mix(in srgb, var(--luz) 22%, transparent) 62%, transparent 78%);
    filter:blur(calc(6px + var(--carga) * 26px));
    transform:translateY(-2%);
  }
  #portal .anillo{
    position:absolute; width:calc(26vmin + var(--carga) * 30vmin);
    aspect-ratio:1; border-radius:50%;
    border:calc(1px + var(--carga) * 2px) solid color-mix(in srgb, var(--luz) 80%, white);
    opacity:calc(var(--carga) * .85);
    transform:scale(calc(1 + var(--carga) * .12));
    filter:blur(calc(var(--carga) * 1.5px));
  }
  .sala.cargando #portal, .sala.viajando #portal{opacity:1}

  /* Las partículas que se van hacia el centro, absorbidas.
     El mismo lienzo dibuja después el CORREDOR del viaje. */
  /* z-index 7bis: el corredor tiene que ir POR ENCIMA del túnel. Estaba
     debajo, y el velo oscuro del túnel se comía justo la zona de los bordes,
     que es donde viven las estelas. Por eso el viaje se veía vacío. */
  #succion{position:absolute; inset:0; width:100%; height:100%; z-index:7;
           pointer-events:none; opacity:0; will-change:opacity}
  .sala.cargando #succion, .sala.viajando #succion{opacity:1}

  /* EL TÚNEL. Es lo que hace que el mundo se doble sin mover la cabina:
     un velo que se cierra desde los bordes y deja solo el hueco del centro.
     Va POR ENCIMA del riel, así que se traga las vitrinas vecinas mientras la
     del medio se queda intacta y perfectamente legible. */
  #tunel{
    position:absolute; left:-100%; top:-100%; width:300%; height:300%;
    z-index:6; pointer-events:none;
    opacity:calc(var(--carga) * .96);
    background:radial-gradient(22% 20% at 50% 48.7%,
      transparent 0%, transparent 62%,
      color-mix(in srgb, var(--luz) 26%, #05060B) 82%, #04050A 100%);
    /* el degradado es FIJO; lo que se cierra es la escala. Cero repintados. */
    transform:scale(calc(1.62 - var(--carga) * .68));
    transform-origin:50% 48.7%;
    will-change:transform, opacity;
  }
  .sala:not(.cargando):not(.viajando) #tunel{opacity:0; transition:opacity .3s ease}

  /* LA DISTORSIÓN, SIN FILTROS.
     Antes esto era un filter() sobre `.riel` y un degradado recalculado cuadro
     a cuadro sobre `.aura`. Medido: la pieza caía de 44 a 8 fps mientras
     cargabas — el viaje se veía a trompicones justo en el momento que más
     tiene que impresionar. Filtrar `.riel` obliga al navegador a rasterizar de
     nuevo TODO el riel (cuatro renders enormes y dos vídeos) en cada cuadro.

     Ahora el color lo rompe una capa suelta que solo cambia de OPACIDAD, y el
     encuadre lo cierra el túnel con un TRANSFORM. Las dos cosas las hace el
     compositor sin volver a pintar nada. */
  #tinte{
    position:absolute; inset:0; z-index:6; pointer-events:none;
    background:radial-gradient(34% 30% at 50% 46%,
      color-mix(in srgb, var(--luz) 70%, white) 0%,
      color-mix(in srgb, var(--luz) 30%, transparent) 46%, transparent 72%);
    mix-blend-mode:screen; opacity:0; will-change:opacity;
  }
  /* Tope .32 mientras cargas. Durante el VIAJE baja a .09: ahí la luz ya no
     la pone un velo de color, la pone el contraluz de detrás de la cabina y
     las estelas. Con el tinte alto todo era una mancha verde y no se veía ni
     la silueta ni el corredor. */
  .sala.cargando #tinte{opacity:calc(var(--carga) * .32)}
  .sala.viajando #tinte{opacity:calc(var(--carga) * .09)}

  /* Durante el VIAJE la sala se APAGA. Ese cuarto se está quedando atrás y no
     puede seguir iluminando nada. Con el aura de la sala encendida, todo el
     corredor era una mancha verde clara sobre la que ni las estelas ni la
     silueta tenían contraste: por eso el cruce se veía plano. */
  .sala.viajando .aura{opacity:.10; transition:opacity .18s ease}
  .sala.viajando .piso-sala{opacity:.18; transition:opacity .18s ease}
  .sala.viajando .charco{opacity:0 !important; transition:opacity .18s ease}

  /* destello del salto */
  #salto{
    position:absolute; inset:0; z-index:50; pointer-events:none; opacity:0;
    background:radial-gradient(60% 60% at 50% 46%,
      color-mix(in srgb, var(--luz) 90%, white), color-mix(in srgb, var(--luz) 40%, transparent) 55%, transparent 80%);
    mix-blend-mode:screen;
  }
  /* El salto en dos tiempos: primero la luz se ESTRECHA (la sala se colapsa
     dentro de la grieta), y solo entonces revienta. Un fundido plano a blanco
     leía como un corte de montaje; esto lee como atravesar algo. */
  #salto.vivo{animation:absorber 1.05s cubic-bezier(.32,0,.12,1)}
  @keyframes absorber{
    0%  {opacity:0;   transform:scale(.35)}
    22% {opacity:.55; transform:scale(.16)}
    34% {opacity:1;   transform:scale(1.9)}
    62% {opacity:.5;  transform:scale(2.6)}
    100%{opacity:0;   transform:scale(3.2)}
  }
  /* el anillo de choque que sale disparado al cruzar */
  #onda{
    position:absolute; left:50%; top:46%; z-index:49; pointer-events:none;
    width:22vmin; aspect-ratio:1; margin:-11vmin 0 0 -11vmin; border-radius:50%;
    border:2px solid color-mix(in srgb, var(--luz) 70%, white);
    opacity:0; mix-blend-mode:screen;
  }
  #onda.vivo{animation:onda .8s cubic-bezier(.15,.7,.25,1)}
  @keyframes onda{
    0%{opacity:0; transform:scale(.2); border-width:5px}
    18%{opacity:.9}
    100%{opacity:0; transform:scale(7); border-width:1px}
  }

  /* ---------- el universo ---------- */
  #universo{
    position:absolute; inset:0; z-index:8; pointer-events:none;
    opacity:0; transition:opacity .5s ease;
  }
  .sala.enUniverso #universo{opacity:1; pointer-events:auto}
  /* Dentro del universo la vitrina sigue ahí un instante — es lo que ata el
     salto con la llegada — y se disuelve en cuanto empiezas a bajar, para
     dejarle la pantalla entera a la secuencia. `--vit` lo maneja el descenso. */
  .sala.enUniverso .riel{
    z-index:3; opacity:var(--vit,1); pointer-events:none;
    transition:opacity .42s ease;
  }
  /* el universo (y con el, el plano) va por encima del riel */
  .sala.enUniverso #universo{z-index:10}
  .sala.enUniverso .titulo,
  .sala.enUniverso .flecha,
  .sala.enUniverso .pista{opacity:0; pointer-events:none; transition:opacity .4s ease}

  /* el cuarto del personaje. De momento gradiente; cuando haya arte, va aquí. */
  #cuarto{
    position:absolute; inset:0;
    background:
      radial-gradient(70% 44% at 50% 96%, color-mix(in srgb, var(--luz) 30%, transparent), transparent 70%),
      radial-gradient(40% 30% at 12% 14%, color-mix(in srgb, var(--luz) 22%, transparent), transparent 70%),
      radial-gradient(46% 34% at 88% 20%, color-mix(in srgb, var(--luz) 16%, transparent), transparent 72%),
      linear-gradient(180deg, #0A0F0A 0%, #070B07 60%, #050705 100%);
  }
  #cuarto::after{  /* tiras LED de cuarto de adolescente */
    content:''; position:absolute; inset:0;
    background:
      linear-gradient(90deg, transparent 6%, color-mix(in srgb, var(--luz) 55%, transparent) 6.4%, transparent 6.8%),
      linear-gradient(90deg, transparent 93%, color-mix(in srgb, var(--luz) 45%, transparent) 93.4%, transparent 93.8%);
    filter:blur(2px); opacity:.7;
  }

  .estacion{
    position:absolute; left:50%; transform:translateX(-50%);
    bottom:clamp(70px,9vh,110px); width:min(720px,90vw); text-align:center;
    opacity:0; pointer-events:none; transition:opacity .18s ease, transform .18s var(--ease);
  }
  /* el rotulo que entra espera a que el anterior ya se haya ido: nunca dos
     superpuestos (S3) */
  .estacion.viva{opacity:1; transform:translateX(-50%) translateY(0); transition:opacity .5s ease .22s, transform .5s var(--ease) .22s}
  .estacion:not(.viva){transform:translateX(-50%) translateY(14px)}
  .estacion .num{
    font-size:9.5px; font-weight:700; letter-spacing:.3em; text-transform:uppercase;
    color:color-mix(in srgb, var(--luz) 80%, white); margin-bottom:12px;
  }
  .estacion h2{
    font-family:Anton,Impact,sans-serif; font-weight:400; text-transform:uppercase;
    letter-spacing:-.015em; margin:0;
    font-size:clamp(30px,5.2vw,68px); line-height:.94; color:#F7F4FB;
  }
  .estacion p{
    margin:14px auto 0; max-width:46ch; font-size:clamp(13px,1.15vw,15.5px);
    line-height:1.62; color:rgba(247,244,251,.66);
  }
  .estacion .vacio{
    display:inline-block; margin-top:10px; padding:6px 12px; border-radius:6px;
    border:1px dashed rgba(247,244,251,.28); font-size:11px; letter-spacing:.12em;
    text-transform:uppercase; color:rgba(247,244,251,.42);
  }

  /* barra de estaciones */
  #ruta{
    position:absolute; right:clamp(16px,3vw,44px); top:50%; transform:translateY(-50%);
    display:flex; flex-direction:column; gap:10px; z-index:12;
  }
  #ruta i{
    display:block; width:2px; height:26px; border-radius:2px;
    background:rgba(255,255,255,.16); transition:background .3s ease, height .3s ease;
  }
  #ruta i.aqui{background:color-mix(in srgb, var(--luz) 90%, white); height:38px}

  #salirUniverso{
    position:absolute; top:20px; right:clamp(16px,4vw,52px); z-index:14;
    border:1px solid rgba(237,234,242,.3); background:rgba(8,9,14,.5);
    color:rgba(237,234,242,.8); border-radius:999px; padding:8px 15px; cursor:pointer;
    font:600 9.5px/1 Inter,sans-serif; letter-spacing:.2em; text-transform:uppercase;
    backdrop-filter:blur(6px);
  }
  #salirUniverso:hover{color:#fff; border-color:rgba(237,234,242,.65)}

  /* indicador de que hay que MANTENER, no tocar */
  #cargaAro{
    position:absolute; z-index:24; width:54px; height:54px; pointer-events:none;
    opacity:0; transition:opacity .2s ease; transform:translate(-50%,-50%);
  }
  .sala.cargando #cargaAro{opacity:0}   /* (10 sep) sin aro: la distorsión es el aviso */
  #cargaAro circle{fill:none; stroke-width:3; transform:rotate(-90deg); transform-origin:50% 50%}
  #cargaAro .pista2{stroke:rgba(255,255,255,.18)}
  #cargaAro .val{stroke:color-mix(in srgb, var(--luz) 90%, white); stroke-linecap:round}

  @media (prefers-reduced-motion:reduce){
    .sala.cargando .riel{filter:none}
    #salto.vivo, #onda.vivo{animation:none}
    #tunel{display:none}
  }

  /* ============================ HUD ============================ */
  .flecha{
    position:absolute; z-index:22; top:50%; margin-top:-24px;
    width:48px; height:48px; border-radius:50%; cursor:pointer;
    border:1.5px solid rgba(237,234,242,.34); background:rgba(8,9,14,.45);
    color:#EDEAF2; display:flex; align-items:center; justify-content:center;
    backdrop-filter:blur(6px); transition:transform .18s ease, background .18s, border-color .18s;
  }
  .flecha:hover{transform:scale(1.1); background:rgba(237,234,242,.16); border-color:#fff}
  .flecha:focus-visible{outline:2px solid var(--luz); outline-offset:3px}
  #prev{left:clamp(16px,3.4vw,52px)} #next{right:clamp(16px,3.4vw,52px)}

  .marca{
    position:absolute; z-index:20; top:22px; left:clamp(18px,4vw,54px);
    display:flex; align-items:center; gap:12px;
    font-size:11px; font-weight:700; letter-spacing:.2em; color:rgba(237,234,242,.5);
  }
  /* El isotipo ⚇⚉ dibujado en SVG, no como carácter: la mayoría de sistemas no
     trae ese glifo y saldrían dos cuadraditos. Va del color del nahual
     encendido, así que la marca respira con la pieza sin gritar. */
  .iso{width:34px; height:15.3px; flex:none; color:var(--luz); transition:color 1s var(--ease)}
  .marca .n{margin-left:14px; opacity:.7; font-variant-numeric:tabular-nums}
  /* La pista vivía suelta en `bottom:24px` y el nombre la pisaba en cuanto la
     ventana era baja. Ahora va DENTRO de .titulo, en el flujo: si crece el
     nombre, empuja a la pista, y medir() reserva el bloque entero. */
  .pista{
    margin-top:14px; font-size:10px; letter-spacing:.2em; text-transform:uppercase;
    color:rgba(237,234,242,.42);
  }

  /* punteros propios de cada universo */
  #puntero{position:absolute; inset:0; z-index:40; pointer-events:none; display:none}
  html.sin-cursor #puntero{display:block}
  .bicho{position:absolute; left:0; top:0; width:30px; height:30px; will-change:transform;
         filter:drop-shadow(0 2px 4px rgba(0,0,0,.5))}

  /* Destello de cambio de escena: la atmósfera nueva inunda la sala un instante.
     Es lo que convierte "cambió la foto" en "cambiaste de mundo". */
  #destello{
    position:absolute; inset:0; z-index:32; pointer-events:none; opacity:0;
    background:radial-gradient(70% 60% at 50% 44%,
      color-mix(in srgb, var(--luz) 70%, white) 0%,
      color-mix(in srgb, var(--luz) 30%, transparent) 42%, transparent 74%);
    mix-blend-mode:screen;
  }
  #destello.vivo{animation:inunda .62s cubic-bezier(.15,.9,.3,1)}
  @keyframes inunda{
    0%{opacity:0; transform:scale(1.12)}
    12%{opacity:.85}
    28%{opacity:.32}
    38%{opacity:.6}
    100%{opacity:0; transform:scale(1)}
  }

  /* botón de sonido */
  .sonido{
    position:absolute; z-index:22; top:20px; right:clamp(18px,4vw,54px);
    display:flex; align-items:center; gap:8px; cursor:pointer;
    border:1px solid rgba(237,234,242,.28); background:rgba(8,9,14,.45);
    color:rgba(237,234,242,.72); border-radius:999px; padding:7px 13px 7px 11px;
    font:600 9.5px/1 Inter,sans-serif; letter-spacing:.18em; text-transform:uppercase;
    backdrop-filter:blur(6px); transition:color .2s, border-color .2s, background .2s;
  }
  .sonido:hover{color:#fff; border-color:rgba(237,234,242,.6)}
  .sonido .barras{display:flex; align-items:flex-end; gap:2px; height:11px}
  .sonido .barras i{width:2px; background:currentColor; height:3px; border-radius:1px}
  .sonido.on .barras i{animation:vu .9s ease-in-out infinite alternate}
  .sonido.on .barras i:nth-child(2){animation-delay:.18s}
  .sonido.on .barras i:nth-child(3){animation-delay:.36s}
  @keyframes vu{from{height:3px} to{height:11px}}
  @media (prefers-reduced-motion:reduce){
    #destello.vivo{animation:none}
    .sonido.on .barras i{animation:none; height:7px}
  }

  /* CARGA — la pieza son ~7 MB de video e imagen. Sin esto el primer pintado es
     un cuarto negro vacío y parece que está rota. */
  #carga{
    position:absolute; inset:0; z-index:60; background:var(--sala);
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:22px;
    transition:opacity .7s ease; 
  }
  #carga.ido{opacity:0; pointer-events:none}
  #carga .iso{width:62px; height:27.9px; color:#B399D2; animation:latir 2.2s ease-in-out infinite}
  @keyframes latir{0%,100%{opacity:.35}50%{opacity:1}}
  #carga .barra{width:160px; height:2px; background:rgba(255,255,255,.1); border-radius:2px; overflow:hidden}
  #carga .barra i{display:block; height:100%; width:100%; transform:scaleX(0); transform-origin:left;
    background:#B399D2; transition:transform .35s ease}
  #carga span{font-size:9.5px; letter-spacing:.24em; text-transform:uppercase; color:rgba(237,234,242,.4)}

  .grano{
    position:absolute; inset:0; z-index:31; pointer-events:none; opacity:.26;
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4'/></filter><rect width='200' height='200' filter='url(%23n)' opacity='0.07'/></svg>");
    background-size:200px 200px;
  }

  @media (max-width:900px){
    .titulo{bottom:104px; width:calc(100% - 30px)}
    .titulo h1{font-size:clamp(30px,9vw,44px)}
    .titulo p{font-size:13px; margin-top:9px; max-width:32ch}
    .flecha{top:auto; bottom:20px; margin-top:0}
    #prev{left:calc(50% - 62px)} #next{right:calc(50% - 62px)}
    .pista{margin-top:11px; font-size:9.5px}
    .placa{bottom:-13px; font-size:8px; letter-spacing:.16em}
  }
  .vit:focus-visible{outline:2px solid var(--luz); outline-offset:6px; border-radius:4px}
  @media (prefers-reduced-motion:reduce){
    .titulo .cambio{animation:none}
    #carga .iso{animation:none; opacity:.8}
    .halo{animation:none}
  }

  /* ============================================================
     GLITCH DE PANTALLA
     Nada de filter: en elementos grandes — eso fue lo que hundió los FPS.
     El glitch son tres cosas baratas: una rejilla de líneas que aparece,
     dos bandas que saltan, y un tirón de 3 cuadros en la sala.
     ============================================================ */
  #glitch{position:fixed; inset:0; z-index:60; pointer-events:none;
          opacity:0; mix-blend-mode:overlay; contain:strict;
          background:repeating-linear-gradient(0deg,
            rgba(255,255,255,.055) 0 1px, transparent 1px 3px)}
  #glitch.on{opacity:var(--gl,1)}
  #glitch i{position:absolute; left:-4%; width:108%; display:block;
            background:rgba(255,255,255,.09); mix-blend-mode:screen;
            transform:translate3d(0,0,0)}
  #glitch i.a{height:2.5%; top:22%}
  #glitch i.b{height:1.2%; top:58%; background:rgba(120,255,210,.10)}
  #glitch i.c{height:.6%;  top:77%; background:rgba(255,120,160,.10)}
  /* usa la propiedad `translate`, no `transform`: la sala ya lleva transform
     inline en el viaje y una animación sobre transform quedaría pisada */
  .sala.tiron{animation:tiron .16s steps(4,end) 1}
  @keyframes tiron{
    0%{translate:0 0} 25%{translate:-4px 1px}
    50%{translate:3px -2px} 75%{translate:-2px 0} 100%{translate:0 0}
  }
  @media (prefers-reduced-motion:reduce){
    #glitch{display:none}
    .sala.tiron{animation:none}
  }

  /* ============================================================
     LA SECUENCIA DE LA ESTACIÓN
     Ocho clips apilados dentro del universo. `avance` elige cuál se ve;
     el clip activo se reproduce solo, y si el dedo se está moviendo, el
     dedo manda y raspa el tiempo. En el móvil eso es lo que convierte el
     scroll en "yo lo estoy bajando".
     ============================================================ */
  /* El video es 9:16. Estirarlo a pantalla completa con `cover` lo recortaba
     y lo agigantaba en escritorio. Ahora vive dentro de un MARCO de proporción
     9:16 que se centra y ocupa el mismo sitio que la vitrina: en el teléfono
     llena la pantalla, en el escritorio es un panel vertical con el resto en
     negro. Nunca se deforma ni se recorta. */
  #secuencia{
    position:absolute; inset:0; display:none;
    place-items:center; background:#05070A;
  }
  /* LA ATMOSFERA. Detras del plano, a sangre. Es el sitio donde ocurre la
     escena, no un fondo negro: sin esto el video flota en la nada y se pierde
     la sensacion de que Kairo esta DENTRO de algo. Respira muy despacio para
     que el encuadre nunca se sienta congelado. */
  #secuencia .atmosfera{
    position:absolute; inset:0; z-index:0; overflow:hidden;
    background:#05070A;
  }
  /* el cuarto de gradiente viejo tapaba la atmosfera */
  #universo.conSecuencia #cuarto{opacity:0 !important}
  #secuencia .atmosfera img,
  #secuencia .atmosfera video{
    position:absolute; inset:-6%; width:112%; height:112%;
    object-fit:cover; opacity:0; transition:opacity .5s linear;
    animation:respirar 26s ease-in-out infinite;
  }
  #secuencia .atmosfera .vivo{opacity:1}
  /* EL ESPEJO: el mismo plano, agrandado y desenfocado, pintado por el JS.
     Va SOBRE las imagenes fijas, que quedan solo como primer golpe de vista
     mientras el video arranca. Al ser el propio plano, el fondo cuadra
     siempre y se mueve solo: no hay bucle que se note porque no hay bucle. */
  #secuencia .atmosfera .espejo{
    position:absolute; inset:-14%; width:128%; height:128%;
    object-fit:cover; pointer-events:none;
    filter:blur(38px) saturate(1.18) brightness(.68);
    transform:scale(1.06);
    animation:respirar 26s ease-in-out infinite;
  }
  /* ---------- PUERTO ÓNIX EN CAPAS ----------
     Del plano del pozo en adelante el espejo desenfocado se apaga y detrás
     del plano vive la calle: la fachada entera (una sola plancha, con el
     pozo vacío), las ventanas con mal contacto, dos capas de niebla que no
     vuelven a coincidir, el farol de sodio y un coche que cruza cada tanto.
     Todo es CSS sobre tres imágenes: cero video, cero créditos. La fachada
     SUBE conforme baja el descenso (--desc 0→1): la cabina está quieta y es
     el entorno el que se mueve, como manda la biblia. --mx/--my es el
     puntero, para que el fondo tenga profundidad al mover el ratón. */
  #secuencia .capas{
    position:absolute; inset:0; overflow:hidden; pointer-events:none;
    opacity:0; transition:opacity 1.1s ease;
    --desc:0; --mx:0; --my:0;
  }
  #secuencia .capas.vivo{opacity:1}
  #secuencia .capas .capa{position:absolute; inset:0; pointer-events:none}
  #secuencia .capas .cielo{
    background:
      radial-gradient(ellipse 90% 50% at 50% 100%, rgba(232,150,58,.16), transparent 70%),
      linear-gradient(180deg, #0A1220 0%, #0D1522 45%, #14171C 100%);
  }
  /* la fachada mide 130% de alto: lo que sobra es el recorrido del descenso */
  #secuencia .capas .fachada{
    top:-2%; height:134%; width:100%;
    background:url(../media/fachada.webp?v=1) center top / cover no-repeat;
    transform:translate3d(calc(var(--mx) * -14px), calc(var(--desc) * -24% + var(--my) * -6px), 0);
    filter:brightness(.72) saturate(.92);
    transition:transform .35s cubic-bezier(.22,.61,.36,1);
  }
  /* ventanas con mal contacto: cada una es un punto de luz encima de la
     ventana pintada; se apagan y encienden por código, con periodos primos */
  #secuencia .capas .ventanas{
    top:-2%; height:134%; width:100%;
    transform:translate3d(calc(var(--mx) * -14px), calc(var(--desc) * -24% + var(--my) * -6px), 0);
    transition:transform .35s cubic-bezier(.22,.61,.36,1);
    mix-blend-mode:screen;
  }
  #secuencia .capas .ventanas i{
    position:absolute; display:block; border-radius:2px;
    transform:translate(-50%,-50%);
    background:radial-gradient(ellipse at center, rgba(255,196,120,.95) 0%, rgba(255,170,80,.55) 45%, transparent 75%);
    filter:blur(1px); opacity:var(--on, .9);
    transition:opacity .08s steps(1,end);
  }
  #secuencia .capas .ventanas i.cian{
    background:radial-gradient(ellipse at center, rgba(120,255,240,.95) 0%, rgba(63,208,201,.6) 45%, transparent 75%);
  }
  #secuencia .capas .ventanas i.farol{
    border-radius:50%;
    background:radial-gradient(circle at center, rgba(255,205,130,1) 0%, rgba(232,150,58,.55) 35%, transparent 70%);
    filter:blur(6px);
  }
  /* niebla: dos capas, periodos primos (41 s y 67 s), deriva lateral y vertical */
  #secuencia .capas .niebla{
    inset:-20%; opacity:.5;
    background:url(../media/niebla1.webp?v=1) 0 0 / 900px 900px repeat;
    animation:nieblaA 41s linear infinite;
    transform:translate3d(calc(var(--mx) * 22px), calc(var(--my) * 10px), 0);
  }
  #secuencia .capas .niebla.b{
    opacity:.38; background-image:url(../media/niebla2.webp?v=1); background-size:1300px 1300px;
    animation:nieblaB 67s linear infinite;
  }
  @keyframes nieblaA{ from{background-position:0 0} to{background-position:900px 260px} }
  @keyframes nieblaB{ from{background-position:0 0} to{background-position:-1300px -180px} }
  /* la calle: banda mojada abajo con el reflejo del farol, y el coche */
  #secuencia .capas .calle{
    top:auto; bottom:0; height:22%;
    background:linear-gradient(180deg, transparent 0%, rgba(5,7,10,.55) 55%, rgba(5,7,10,.92) 100%);
  }
  #secuencia .capas .coche{
    position:absolute; left:-30%; bottom:4%; width:30%; height:7%; z-index:2;
    opacity:0; pointer-events:none;
    background:
      radial-gradient(ellipse 18% 60% at 8% 50%, rgba(255,240,210,.95), transparent 70%),
      radial-gradient(ellipse 18% 60% at 22% 50%, rgba(255,240,210,.95), transparent 70%),
      radial-gradient(ellipse 60% 100% at 40% 50%, rgba(255,220,160,.28), transparent 70%);
    filter:blur(2px);
  }
  #secuencia .capas .coche.pasa{animation:cruzar 7s cubic-bezier(.3,.1,.7,.9) 1}
  @keyframes cruzar{
    0%{left:-30%; opacity:0} 8%{opacity:.9} 92%{opacity:.9} 100%{left:110%; opacity:0}
  }
  /* el velo de las capas: más oscuro en los bordes para que el plano mande */
  #secuencia .capas .velo{
    background:radial-gradient(ellipse at 50% 50%,
      rgba(5,7,10,.05) 0%, rgba(5,7,10,.30) 50%, rgba(5,7,10,.78) 100%);
  }
  /* cuando las capas están vivas, el espejo y el humo viejo se retiran */
  #secuencia .atmosfera.enCalle .espejo,
  #secuencia .atmosfera.enCalle .parpadeo,
  #secuencia .atmosfera.enCalle .humo,
  #secuencia .atmosfera.enCalle img{opacity:0 !important}
  @media (prefers-reduced-motion:reduce){
    #secuencia .capas .niebla{animation:none}
    #secuencia .capas .coche.pasa{animation:none}
  }
  @keyframes respirar{
    0%,100%{ transform:scale(1.00) translate3d(0,0,0) }
    50%    { transform:scale(1.045) translate3d(0,-1.1%,0) }
  }

  /* ---------- LA ATMOSFERA ESTA VIVA ----------
     Tres capas encima del fondo. Los periodos son PRIMOS ENTRE SI (17 s, 23 s,
     31 s), asi que la combinacion no vuelve a repetirse hasta pasadas horas:
     el ojo nunca pilla el bucle aunque se quede mirando. */
  #secuencia .atmosfera .parpadeo,
  #secuencia .atmosfera .humo{
    position:absolute; inset:-10%; pointer-events:none;
  }
  /* las luces del edificio entrecortandose: nunca las dos a la vez */
  #secuencia .atmosfera .parpadeo{
    background:inherit; mix-blend-mode:screen; opacity:0;
    animation:titilar 17s steps(1,end) infinite;
  }
  #secuencia .atmosfera .parpadeo.b{
    animation:titilar2 23s steps(1,end) infinite;
  }
  @keyframes titilar{
    0%,  6%{opacity:.00}   7%{opacity:.16}   8%{opacity:.02}
    9%{opacity:.13}  11%{opacity:.00}  46%{opacity:.00}
    47%{opacity:.10} 48%{opacity:.00}  100%{opacity:.00}
  }
  @keyframes titilar2{
    0%, 28%{opacity:.00}  29%{opacity:.11}  30%{opacity:.01}
    31%{opacity:.08} 33%{opacity:.00}  71%{opacity:.00}
    72%{opacity:.14} 74%{opacity:.00}  100%{opacity:.00}
  }
  /* el humo del ascensor: a la deriva, muy lento, nunca vuelve al mismo sitio */
  #secuencia .atmosfera .humo{
    background:
      radial-gradient(ellipse 42% 26% at 34% 62%, rgba(226,236,244,.13), transparent 70%),
      radial-gradient(ellipse 30% 20% at 62% 48%, rgba(210,226,240,.09), transparent 72%);
    animation:derivar 31s linear infinite;
  }
  @keyframes derivar{
    0%  { transform:translate3d(-3%, 2%, 0) scale(1.05); opacity:.55 }
    35% { opacity:.85 }
    100%{ transform:translate3d( 4%,-5%, 0) scale(1.22); opacity:.30 }
  }
  /* el velo que hunde la atmosfera: tiene que leerse como profundidad, no
     competir con el plano */
  #secuencia .atmosfera::after{
    content:''; position:absolute; inset:0;
    background:radial-gradient(ellipse at 50% 46%,
      rgba(5,7,10,.04) 0%, rgba(5,7,10,.34) 46%, rgba(5,7,10,.80) 100%);
  }

  /* EL PLANO. Ya no llena la pantalla: se encaja al tamaño de la vitrina, y
     es el JS quien le fija la altura (--planoAlto) midiendo la vitrina real.
     Antes yo agrandaba la vitrina hasta el video; es al reves. */
  #secuencia .marco{
    position:relative; z-index:1; aspect-ratio:9/16;
    height:var(--planoAlto, min(100%, calc(100vw * 16 / 9)));
    width:auto; max-width:100%; max-height:100%;
    overflow:hidden; background:#05070A;
    border-radius:3px;
    box-shadow:0 0 0 1px rgba(255,255,255,.07),
               0 0 40px 6px rgba(5,7,10,.85),
               0 30px 90px rgba(0,0,0,.7);
    transition:height .45s cubic-bezier(.22,.61,.36,1);
  }
  /* cuando el universo tiene secuencia, el cuarto de gradiente y el aro de
     carga sobran: la pantalla es del video */
  /* el plano manda: por encima del riel y con el dedo para el. Sin esto la
     vitrina se queda arriba interceptando la pulsacion y nada avanza. */
  #universo.conSecuencia #secuencia{display:grid; z-index:5}
  .sala.enUniverso .riel{pointer-events:none}
  /* DURANTE EL SALTO la pantalla no recibe nada. Un viaje dimensional no se
     rebobina ni se pausa: ocurre. Lo unico que queda es el boton atras del
     navegador. */
  .sala.enSalto #universo,
  .sala.enSalto .riel{pointer-events:none !important}
  .sala.enSalto{cursor:default}
  /* Nada de menus nativos ni seleccion: el dedo es del sitio, no del navegador */
  .sala.enUniverso, .sala.enUniverso *{
    -webkit-touch-callout:none !important;
    -webkit-user-select:none !important; user-select:none !important;
    -webkit-tap-highlight-color:transparent;
  }
  .sala.enUniverso #universo{touch-action:none; overscroll-behavior:contain}
  #secuencia{touch-action:none}

  /* LA INDICACION. Sin esto nadie adivina que hay que sostener el dedo. */
  #mantener{
    position:absolute; left:50%; bottom:8%; transform:translateX(-50%);
    z-index:30; display:none; align-items:center; gap:9px;
    padding:9px 16px; border-radius:999px;
    background:rgba(8,10,16,.62); backdrop-filter:blur(6px);
    border:1px solid rgba(255,255,255,.10);
    font-size:11px; letter-spacing:.16em; text-transform:uppercase;
    color:rgba(237,234,242,.82); pointer-events:none; white-space:nowrap;
    animation:respiraPista 2.6s ease-in-out infinite;
  }
  .sala.enUniverso #mantener{display:flex}
  .sala.enUniverso.cargando #mantener,
  .sala.enSalto #mantener{animation:none; opacity:.35}
  #sello{
    position:absolute; right:8px; bottom:6px; z-index:31;
    font-size:9px; letter-spacing:.1em; color:rgba(237,234,242,.30);
    pointer-events:none; font-variant-numeric:tabular-nums;
  }
  #mantener i{
    width:11px; height:17px; border-radius:7px; flex:none;
    border:1.5px solid currentColor; position:relative;
  }
  #mantener i::after{
    content:''; position:absolute; left:50%; top:3px; width:1.5px; height:5px;
    background:currentColor; transform:translateX(-50%); border-radius:2px;
    animation:pulsaDedo 2.6s ease-in-out infinite;
  }
  @keyframes respiraPista{0%,100%{opacity:.55} 50%{opacity:.95}}
  @keyframes pulsaDedo{0%,100%{opacity:.35} 50%{opacity:1}}
  /* LA CAMARA ENTRA. Cuando el ascensor ya se acomodo a la altura del cuarto,
     el plano crece: no es un corte, es la camara acercandose. */
  #secuencia .marco{transition:height .45s cubic-bezier(.22,.61,.36,1),
                              scale .9s cubic-bezier(.33,.9,.28,1)}
  .sala.camaraDentro #secuencia .marco{scale:1.16}
  /* EL PLANO CRECE. La medida de la vitrina solo tiene sentido mientras la
     escena ocurre en la vitrina (planos 0 y 1). En cuanto el portal se abre
     en el pozo, el plano ocupa la pantalla: a sangre en el teléfono, alto
     completo en escritorio con la calle a los lados. El crecimiento cae
     dentro del retroceso de cámara, así que se lee como parte del plano. */
  .sala.planoGrande #secuencia .marco{
    height:min(92%, calc(100vw * 16 / 9)) !important;
    translate:0 0 !important;
    border-radius:0; box-shadow:0 0 60px 10px rgba(5,7,10,.7);
    transition:height 1.6s cubic-bezier(.33,.9,.28,1), translate 1.6s cubic-bezier(.33,.9,.28,1),
               scale .9s cubic-bezier(.33,.9,.28,1);
  }
  @media (max-aspect-ratio: 9/16){
    .sala.planoGrande #secuencia .marco{width:100%; height:auto !important; aspect-ratio:9/16}
  }
  /* con el plano ya a pantalla, "la cámara entra" no puede escalar 1.16 sin
     salirse por los bordes: en móvil se queda a 1.04 */
  .sala.planoGrande.camaraDentro #secuencia .marco{scale:1.08}
  @media (max-width:720px){ .sala.planoGrande.camaraDentro #secuencia .marco{scale:1.03} }
  /* la barra de descenso y los textos de estación por ENCIMA del plano: hoy
     quedaban debajo de #secuencia (z 5) y nadie los veía */
  #universo.conSecuencia #descenso{z-index:12}
  #universo.conSecuencia .estacion{z-index:12; bottom:clamp(118px,15vh,170px)}
  /* el botón Salir no puede vivir debajo de Sonido */
  #salirUniverso{right:calc(clamp(18px,4vw,54px) + 118px) !important; z-index:23 !important}
  .sala.sonando #salirUniverso{right:calc(clamp(18px,4vw,54px) + 132px) !important}
  /* en pantallas estrechas arriba no cabe: Salir baja a la esquina inferior izquierda */
  @media (max-width:720px){
    #salirUniverso{top:auto !important; bottom:18px !important; left:16px !important; right:auto !important}
  }
  #universo.conSecuencia #cuarto{opacity:0; transition:opacity .3s}
  .sala.enUniverso #cargaAro{pointer-events:none; transition:opacity .3s}
  .sala.enUniverso.cargando #cargaAro{opacity:1}
  /* con la secuencia corriendo la vitrina desaparece del todo: nada puede
     quedar flotando encima del video */
  .sala.secuenciaViva .riel,
  .sala.secuenciaViva .aura,

  #secuencia video, #secuencia .atmosfera img{
    pointer-events:none !important;
    -webkit-touch-callout:none; -webkit-user-select:none; user-select:none;
    -webkit-user-drag:none;
  }
  #secuencia video{
    position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
    /* el marco ya es 9:16 y la fuente también, así que cover no recorta nada */
    opacity:0; transition:opacity .26s linear; will-change:opacity;
    background:#05070A;
  }
  #secuencia video.vivo{opacity:1}
  /* viñeta: sin esto el texto de la estación se pierde sobre el video */
  #secuencia .marco::after{
    content:''; position:absolute; inset:0; pointer-events:none; z-index:2;
    background:linear-gradient(180deg,
      rgba(5,7,10,.62) 0%, rgba(5,7,10,.10) 22%,
      rgba(5,7,10,.10) 48%, rgba(5,7,10,.88) 100%);
  }
  /* barra fina de progreso del descenso, arriba */
  #descenso{
    position:absolute; left:0; right:0; top:0; height:2px; z-index:3;
    background:rgba(255,255,255,.07); pointer-events:none;
  }
  #descenso i{
    display:block; height:100%; width:0;
    background:linear-gradient(90deg,
      color-mix(in srgb, var(--luz) 70%, white), color-mix(in srgb, var(--luz) 95%, transparent));
    box-shadow:0 0 10px color-mix(in srgb, var(--luz) 80%, transparent);
  }
  /* el chasquido de la grieta: un latigazo blanco de tres cuadros */
  .cristal .fisura.chasquido path{
    stroke-width:2.1; filter:drop-shadow(0 0 14px #fff) drop-shadow(0 0 26px color-mix(in srgb, var(--luz) 90%, white));
  }

/* Títulos completos y resúmenes en una línea; el nombre se mide por personaje. */
.titulo h1{white-space:nowrap}
.titulo p{white-space:nowrap;max-width:none}
