/*
  IDBox · Caja de Datos (Nix Business) — ESTILOS
  Pareja de idbox_nix_v1.html (archivo canónico, LEY #2: se edita, no se regenera).
  Extraído del monolito en block-02. Contenido idéntico, solo cambió de archivo.
  Paleta y tipografía: webapp_nix.md §1b.
*/

/* ===== ESTILOS GLOBALES =====

   ⚠️ LAS VARIABLES YA NO VIVEN AQUI. Se mudaron a
   apps/idbox/shared/tokens.css el 2026-08-03, que la pagina carga ANTES
   que esta hoja. Los valores son EXACTAMENTE los mismos: la mudanza no
   cambio un pixel, y si algo se viera distinto seria un error y no una
   mejora.

   POR QUE SE MUDARON: vivian repartidas en TRES bloques :root —este y dos
   en cabin.css— duplicadas a mano. Y `--filo` / `--borde`, que
   webapp_nix.md §1b-2 declara parte del lenguaje comun, existian SOLO en
   la cabina: el filo de luz no existia en esta mitad de la casa.

   NO volver a declarar un color aqui. Si falta una ficha, se agrega en
   tokens.css, que es el unico sitio.                                    */

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/*
  ⚠️ ESCONDER LE GANA A TODO. REGLA DE CASA, NO SE QUITA.
  El atributo `hidden` del HTML vale `display:none`, pero lo pone el
  NAVEGADOR — y CUALQUIER regla nuestra le gana, incluido un `display:flex`
  puesto por otra razon. El resultado no es un elemento medio escondido: es
  un elemento COMPLETAMENTE VISIBLE que el codigo cree apagado, y el fallo
  es mudo (nada da error).
  TRES VECES EN ESTA CASA, la ultima noche entera:
  1. block-13f-2c-fix — la ficha del contacto se pintaba DEBAJO de una lista
     que nunca se iba (`#dentro.vista` le ganaba a `.oculto`).
  2. block-PAN1 (2026-08-05) — `.paneles{display:flex}` le gano al `hidden`
     y la vitrina VACIA quedo fija sobre la Caja desde que cargaba la
     pagina. Lo cazo el fundador con una captura, en produccion.
  3. Ese mismo dia, minutos despues — `.cta-cards-btn{display:flex}` iba a
     hacer exactamente lo mismo con el boton que se esconde cuando una Caja
     no tiene paneles. Cazado ANTES de desplegar, leyendo la hoja.
  Una sola linea aqui arriba mata la familia entera, presente y futura, en
  vez de tres parches que hay que acordarse de escribir.
  COMO SE ESCAPO DOS VECES: se comprueba que la pantalla ABRA y no que este
  CERRADA — se lee el atributo, no los pixeles. Toda pantalla que nace
  escondida se mide en reposo primero.
*/
[hidden] { display: none !important; }

html, body {
  height: 100%;
}

/*
  ⚠️ SIN ESTA LINEA, EL `overflow-y: auto` DEL BODY ES MENTIRA. Es la regla
  de propagacion del desbordamiento de CSS: cuando el html esta en `visible`
  (su valor de fabrica), el overflow del body NO se queda en el body — SE LO
  LLEVA EL VIEWPORT, y el body queda sin poder deslizar por dentro. El
  viewport, a su vez, no tiene nada que deslizar: el documento mide justo la
  ventana porque la barra de Nix es fija y esta fuera del flujo.
  ASI SE VEIA EL DEFECTO (fundador, con captura, 2026-08-04): con la barra
  de Nix abierta la pantalla de arriba "se bloquea a partir de dos
  preguntas". Con la barra chica el contenido CABIA en el cuarto y no habia
  nada que deslizar; al crecer la barra el cuarto encoge, el contenido deja
  de caber, y se descubre que el scroll nunca tuvo dueño.
  MEDIDO EN VIVO (2026-08-05, valeria con sesion y dos preguntas de verdad):
  606 px de contenido en 339 visibles, scrollTop clavado en 0 se pidiera lo
  que se pidiera. Con esta linea puesta por consola: el cuarto se desliza
  hasta el fondo exacto (287 de 287). La prueba vale mas que la prediccion.
*/
html {
  overflow: hidden;
}

body {
  /* Las tres luces por encima del negro. Van tambien aqui y no solo en el
     velo, porque el velo solo existe con la camara encendida: sin permiso
     de camara la Caja quedaba en negro plano y el vidrio no se veia. */
  background: var(--fondo-luz), var(--void);
  background-attachment: fixed;   /* la luz no se desplaza con el contenido */
  color: var(--snow);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  /*
    ⚠️ SE LE RESTA LA BARRA DE NIX. Lo reporto el fundador: "cuando abrimos el
    comunicador con Nix desde cabina, la parte de arriba de cabina se queda
    pegada".
    LA CAUSA, MEDIDA: la Caja se centra en la pantalla entera y la pagina NO
    se desplaza (no hay de donde: mide justo lo que la ventana). Al subir la
    barra —142 px— le tapaba 29 px por abajo y no habia forma de bajar a
    verlos. Lo de "arriba pegado" era el sintoma: no estaba pegado nada, es
    que no habia hacia donde mover la Caja.
    LA CURA es la que la cabina ya usaba y a esta hoja nunca llego: la ficha
    `--nix-barra`, que escribe la propia barra al medirse. Cerrada vale 0 y
    esto es 100dvh de siempre. Al abrirse, la Caja se recentra en el hueco
    que queda arriba, que es justo lo que se espera al hablarle.
    ⚠️ VA EN `height` Y NO EN `min-height`, y lo se porque lo intente al
    reves y NO SIRVIO: el body ya media la pantalla entera, asi que bajarle
    el minimo no lo encoge (812 sigue siendo mayor que 671). Medido: con
    min-height la Caja no se movia ni un pixel; con height sube de 119 a 44 y
    la barra empieza en 662. Es ademas lo que la cabina ya usa, con la misma
    frase escrita: "height, nunca min-height".
    ⚠️ SIN TRANSICION, por la advertencia que ya esta escrita en la cabina:
    con una, esta medida se queda pegada y la Caja no vuelve a su sitio al
    cerrar a Nix.
  */
  height: calc(100dvh - var(--nix-barra, 0px));
  display: flex;
  /*
    ⚠️ `safe center` Y NO `center` A SECAS. Lo reporto el fundador con una
    captura: "cuando hay charla con Nix la pantalla de arriba se pega, la
    necesitamos suelta" — y en la imagen SU PROPIO NOMBRE estaba fuera de la
    pantalla, sin forma de subir a verlo.
    LA CAUSA, y es un clasico de flexbox: con `center`, cuando el contenido es
    MAS ALTO que su cuarto, el sobrante se reparte arriba Y abajo — y lo que
    se sale por arriba NO SE PUEDE ALCANZAR NUNCA, porque el desplazamiento
    solo llega hasta el borde de arriba del contenedor, no mas alla.
    Al subir la barra de Nix el cuarto encoge 158 px y la Caja deja de caber,
    asi que ese reparto empieza a comerse la cabecera: la foto y el nombre.
    `safe center` dice exactamente lo que hace falta: centra MIENTRAS quepa, y
    en cuanto no quepa se apoya arriba en vez de cortar.
  */
  align-items: safe center;
  justify-content: center;
  padding: 26px 20px calc(20px + env(safe-area-inset-bottom));
  overflow-x: hidden;
  /*
    Y ADEMAS TIENE QUE PODER DESPLAZARSE. `safe center` evita que la cabecera
    quede inalcanzable, pero sin esto lo que sobra por abajo sigue sin verse:
    el body tiene altura fija, asi que el documento no crece y no hay scroll
    que hacer. Con `auto` el cuarto se desplaza por dentro y la barra de Nix,
    que va fija al pie, no se mueve con el.
    La barra gris se esconde como en toda la casa: ese blanco lo pinta el
    sistema y no lo elegimos nosotros (2026-07-30).
  */
  overflow-y: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
body::-webkit-scrollbar { display: none; }

/* CÁMARA TRASERA & OVERLAY STARK VISOR */
#cameraFeed {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  display: none;
  pointer-events: none;
}

/* ⚠️ LA UNICA SUPERFICIE DE LA CASA QUE NO LLEVA LA RECETA DE VIDRIO, y el
   motivo esta en el sistema grafico §3: esto NO es vidrio, es EL VELO de la
   camara —la capa obligatoria que garantiza un piso de contraste cuando el
   lente apunta a una pared blanca—. Dos razones para dejarlo en 6 px:
   subir un desenfoque a pantalla completa SOBRE VIDEO EN VIVO se recalcula en
   cada fotograma, que es exactamente el costo que §5 prohibe en Android de
   gama media; y debajo de un negro al 82% no se veria de todos modos. */
#visorOverlay {
  position: fixed;
  inset: 0;
  /* El velo, MAS las tres luces de color encima. Sin ellas, apuntar la
     camara a un rincon oscuro deja un negro plano detras del vidrio y no
     hay nada que refractar (§2). Con ellas, el vidrio tiene de que vivir
     mire la camara lo que mire. */
  background: var(--fondo-luz), var(--velo);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  z-index: 0;
  display: none;
  pointer-events: none;
}

/* CANVAS DE VUELO LIBRE DE NIX EN ACTO 2 */
#flyCanvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 50;
  pointer-events: none;
}

.stage {
  width: 100%;
  max-width: 380px;
  position: relative;
  z-index: 1;
  min-height: 580px;
  display: flex;
  flex-direction: column;
}

/* (La cura del pie que se caia de la pantalla vive al FINAL de esta hoja,
   y esta escrito alli por que: puesta aqui no hacia nada.) */

/* ===== ACTO 0: ARRANQUE ===== */
#s0 {
  position: fixed;
  inset: 0;
  z-index: 20;
  background: var(--void);
  cursor: pointer;
  overflow: hidden;
}

#dust {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 1;
}

#arr {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 26px;
  padding: 24px;
  transition: opacity 0.35s;
}

#markWrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: floatY 6.5s ease-in-out infinite;
}

/*
  LA LUZ DETRAS DE LA IDBOX. Pedido del fundador (2026-09-22): *"la luz que
  esta detras de las IDBox puedes subirla un 33% mas incandescente, que se vea
  mas"*. Se le subio un 33%, y despues la miro en la maqueta `/luz` contra un
  44% y un 66% —en las dos tarjetas, la de la casa y la impresa de ABB— y
  cerro: **"vamos con la opcion 2 - 44%"**.

  SE SUBE UNA SOLA PERILLA: las dos opacidades del degradado, x1,44 sobre lo
  que habia antes de ese dia.
    0,34 -> 0,490   ·   0,10 -> 0,144
  Sobre un fondo casi negro la mezcla es lineal en la opacidad de la capa de
  arriba, asi que multiplicarla por 1,44 es exactamente 44% mas luz en CADA
  punto del degradado. No se toca el desenfoque (22 px), ni el tamaño, ni la
  respiracion: subir la opacidad de la animacion habria topado en 1 y le
  habria aplanado el latido, que es otra cosa y no la que pidio.

  ⚠️ ESTOS DOS NUMEROS LOS ESCOGIO EL DE OJO, comparando. No se mueven por
  gusto propio ni por "redondear": se cambian volviendo a la maqueta.
*/
#halo {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 205%;
  height: 220%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.490), rgba(214, 240, 255, 0.144) 48%, transparent 76%);
  filter: blur(22px);
  animation: haloBreathe 4.8s ease-in-out infinite;
  pointer-events: none;
}

/* ⚠️ ESTA MEDIDA SE TOCO POR ERROR EL 2026-08-03 Y SE DEVOLVIO. El fundador
   pedia achicar OTRO simbolo —la marca ")B" de la pantalla negra de carga—
   y yo achique la tarjeta ilustrada del arranque. Queda escrito para que
   nadie la vuelva a mover buscando aquello: son dos cosas distintas. */
#idboxMark {
  position: relative;
  width: 4.2cm;
  max-width: 62vw;
  line-height: 0;
  animation: cardBreathe 4.8s ease-in-out infinite;
}

#idboxMark svg {
  width: 100%;
  height: auto;
  display: block;
}

#idboxMark svg rect:not(.cls-1) {
  fill: #0a0a0f;
  stroke: rgba(255, 255, 255, 0.22);
  stroke-width: 5;
}

#idboxMark svg .cls-1 {
  fill: rgba(255, 255, 255, 0.95);
}

@keyframes haloBreathe {
  0%, 100% { opacity: 0.55; transform: translate(-50%, -50%) scale(1); }
  50% { opacity: 0.85; transform: translate(-50%, -50%) scale(1.06); }
}

@keyframes cardBreathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.014); }
}

@keyframes floatY {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-5px); }
}

#brandLine {
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--ash);
}

#brandLine b {
  font-weight: 600;
  color: var(--snow);
}

.cta-wrapper {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.s0-cta {
  background: var(--toque);
  border: 1px solid rgba(255, 255, 255, 0.18);
  backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  -webkit-backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  border-radius: var(--r-pildora);
  color: var(--snow);
  font-family: inherit;
  /* 15, era 14 (§5, la Ley · 2026-08-11). */
  font-size: var(--tam-secundario);
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 12px 28px;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 0.25s, background 0.25s, transform 0.2s;
  animation: ctaPulse 2.8s ease-in-out infinite;
  will-change: transform;
}

.s0-cta:hover {
  border-color: rgba(0, 240, 255, 0.4);
  background: rgba(0, 240, 255, 0.08);
}

@keyframes ctaPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
  50% { box-shadow: 0 0 0 6px rgba(0, 240, 255, 0.06); }
}

/* ===== ACTO 1: ESCANEO BIOMÉTRICO HUD ===== */
#s1 {
  position: fixed;
  inset: 0;
  z-index: 15;
  background: var(--void);
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.4s ease;
  background-image: 
    radial-gradient(circle at 50% 45%, rgba(0, 240, 255, 0.16) 0%, transparent 65%),
    linear-gradient(rgba(0, 240, 255, 0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 240, 255, 0.04) 1px, transparent 1px);
  background-size: 100% 100%, 24px 24px, 24px 24px;
  background-position: center center;
}

.hud-frame {
  width: 220px;
  height: 220px;
  position: relative;
  border: 1px solid rgba(0, 240, 255, 0.35);
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--panel);
  backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  -webkit-backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  box-shadow: 0 0 35px rgba(0, 240, 255, 0.15);
}

.hud-frame::before, .hud-frame::after {
  content: '';
  position: absolute;
  width: 20px;
  height: 20px;
  border-color: var(--nix-cyan);
  border-style: solid;
}

.hud-frame::before { top: -2px; left: -2px; border-width: 2px 0 0 2px; }
.hud-frame::after { bottom: -2px; right: -2px; border-width: 0 2px 2px 0; }

/* SOLO LA IDBOX, SIN CUADRADO DETRAS (correccion del fundador, 2026-09-21,
   _pendientes.md #95). Desde el #94 aqui solo se escanea la tarjeta: el
   fondo oscuro y el borde de 180x180 que sostenian la foto del rostro se
   veian como una caja dentro del marco. Se apaga al salir ACCESS GRANTED
   (app.js, runScanSequence): el letrero no se mezcla con el logo. */
.avatar-target {
  width: 180px;
  height: 180px;
  border-radius: var(--r-tarjeta);
  background: transparent;
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  transition: opacity 0.25s ease;
}

.avatar-target img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(60%) contrast(115%);
}

.laser-sweep {
  position: absolute;
  width: 100%;
  height: 3px;
  background: var(--nix-cyan);
  box-shadow: 0 0 15px var(--nix-cyan), 0 0 25px var(--accent-green);
  top: 0;
  animation: sweep 1.8s ease-in-out infinite alternate;
}

@keyframes sweep {
  0% { top: 0%; }
  100% { top: 98%; }
}

.telemetry-text {
  font-family: var(--font-mono);
  /* 13, era 10 — el tamaño mas chico que tenia la casa entera (§5, la Ley). */
  font-size: var(--tam-terciario);
  color: var(--ash);
  margin-top: 25px;
  letter-spacing: 1px;
  text-align: center;
  line-height: 1.6;
}

/* ⚠️ EL NEGRO DE AQUI SE QUEDA FIJO, Y NO ES UN OLVIDO. Este texto va SOBRE
   el verde de estado, que tampoco cambia entre modos —un estado que cambia de
   tono segun la piel deja de reconocerse—. Sobre ese verde brillante, negro es
   correcto en Obsidiana y en Cristal Perlado. Convertirlo en ficha lo haria
   claro en el modo claro, y ahi el texto desapareceria. */
.access-granted {
  position: absolute;
  background: var(--accent-green);
  color: #000;
  font-family: var(--font-mono);
  /* 600, era 800 — §5 da tres pesos y ni uno mas: 600 titulos, 500 botones,
     400 texto. En una monoespaciada en versalitas el 800 casi no se distingue
     del 600, asi que no se pierde el golpe. */
  font-weight: 600;
  /* 13, era 11 (§5, la Ley · 2026-08-11). */
  font-size: var(--tam-terciario);
  letter-spacing: 2px;
  padding: 8px 16px;
  border-radius: var(--r-chico);
  display: none;
  box-shadow: 0 0 25px var(--accent-green);
  animation: popIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

@keyframes popIn {
  0% { transform: scale(0.6); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}

/* ===== ACTO 2: LA CAJA DE DATOS ===== */
/*
  🔴 SIN FUNDIDO DE ENTRADA — Y ESO QUITA EL SEGUNDO SALTO DEL ARRANQUE.
  El fundador lo reporto el 2026-08-10: "cabina tiene dos saltos, cuando
  entramos desde la barra y desde el escaneo inicial salta dos veces".

  ERAN DOS MOVIMIENTOS ENCADENADOS, uno dentro del otro:
    1. esta caja entera fundiendose de transparente a opaca en 0,5 s
    2. y DENTRO, las tarjetas entrando una a una con su propio fundido
       y desplazamiento (`.tile.in`, 0,4 s escalonadas cada 75 ms)

  ⚠️ Y EL DE FUERA ERA ADEMAS EL CARO: las tarjetas llevan `backdrop-filter`,
  asi que fundir su contenedor obliga al telefono a recomponer todos esos
  desenfoques en cada fotograma. Es EXACTAMENTE el mismo defecto que costo
  tres rondas en el panel de Empresa ese mismo dia — aqui llevaba desde el
  principio, tapado por el segundo movimiento.

  ⚠️ NO SE PIERDE EL SHOW: el que se ve es el de dentro. Nix escribe su
  saludo letra a letra y las tarjetas entran en cascada — eso sigue igual.
  Lo que se va es un velo por encima que solo servia para cobrar medio
  segundo y un destello.

  El diseño de la vitrina esta cerrado desde el 2026-08-09 y esto NO lo
  reabre: no cambia una forma, un color ni un tamaño. Quita un defecto de
  arranque, con la orden expresa del fundador ("¿entro ahí?" — "Sí").
*/
#caja {
  opacity: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  position: relative;
}

#caja.show {
  opacity: 1;
}

/* NIX EN CASA (PALABRA NIX RESPIRANDO SIN CIRCUNFERENCIA) */
.nix-btn-container {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 25;
}

.nix-home-btn {
  background: transparent;
  border: none;
  padding: 4px 8px;
  cursor: pointer;
  display: flex;
  align-items: center;
  outline: none;
}

.nix-word {
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  color: var(--texto);
  letter-spacing: 0.8px;
  display: inline-flex;
  align-items: center;
  gap: 7px;

  /* ⚠️ NIX NUNCA SE SELECCIONA COMO TEXTO (2026-08-03).
     Reportado por el fundador: mantener el dedo en Nix sacaba el menu del
     navegador — "Copiar", "Buscar"— en vez de abrir el chat.
     LA CAUSA DE FONDO ERA OTRA (no habia sesion en esa Caja, y el gesto de
     sostener vive dentro del chat, que solo se monta para el dueno), pero
     ESTO hay que arreglarlo igual y va aparte: sin sesion, el gesto no
     existe y el navegador hace lo suyo. Nix es un personaje, no un parrafo:
     un menu de "copiar" encima de el se lee como que la pagina esta rota, y
     lo puede ver tambien un visitante en una feria.
     La regla vivia en `.nix-agarre`, que nix-chat.js pone al montarse — o
     sea SOLO cuando hay sesion. Aqui vale siempre. */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  /* mismo ADN que el orbe del arranque: núcleo blanco, halo cian */
  text-shadow: 0 0 8px rgba(255, 255, 255, 0.35), 0 0 18px rgba(0, 240, 255, 0.45);
  transition: opacity 0.25s ease, text-shadow 0.3s ease, font-size 0.3s ease, letter-spacing 0.3s ease;
}

/* ⚠️ EL NUCLEO DE NIX TAMBIEN SE QUEDA BLANCO, y es su ADN: graphic_system.md
   §6 lo describe como "nucleo blanco con halo", igual en toda la casa. El halo
   cian lo sostiene sobre cualquier fondo, asi que no desaparece en el modo
   claro — pero es lo primero que hay que mirar cuando el panel blanco exista
   de verdad. Si ahi se pierde, se corrige VIENDOLO, no aqui a ojo. */
.nix-word::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #ffffff;
  flex: none;
  transition: opacity 0.2s ease;
  animation: nixOrbBreathe 3.6s ease-in-out infinite;
}

@keyframes nixOrbBreathe {
  0%, 100% {
    opacity: 0.88;
    box-shadow: 0 0 7px 1px rgba(0, 240, 255, 0.75), 0 0 16px 3px rgba(0, 240, 255, 0.38);
  }
  50% {
    opacity: 1;
    box-shadow: 0 0 11px 2px rgba(0, 240, 255, 1), 0 0 24px 5px rgba(0, 240, 255, 0.58);
  }
}

/* Solo MIENTRAS Nix viaja: su casa no queda vacía — queda la palabra,
   dos puntos más grande y con luz. El ojo vuelve y encuentra la marca. */
.nix-word.out-of-home {
  opacity: 1;
  font-size: 16px;
  letter-spacing: 1.4px;
  text-shadow: 0 0 10px rgba(255, 255, 255, 0.55), 0 0 24px rgba(0, 240, 255, 0.5);
}

.nix-word.out-of-home::before {
  opacity: 0;
  animation: none;
  box-shadow: none;
}

.nix-menu {
  position: absolute;
  top: 32px;
  right: 0;
  background: var(--panel);
  border: 1px solid var(--nix-cyan);
  border-radius: var(--r-panel);
  width: 210px;
  /*
    🔴 10 Y NO 6 — LA LEY CONCENTRICA (graphic_system.md §7i):
        radio de dentro = radio de fuera − el relleno
    Con el padre en 18 y las filas en 8, la pareja exacta es 10. Con 6, la ley
    pedia filas de 12 y estaban en 8: cuatro de desfase, y §7i ya lo decia con
    estas palabras — *"el mismo 8 que se veia duro a 6 px de una curva de 18, a
    10 px y concentrico se lee suave"*.
    Lo caza el fundador el 2026-08-12b señalando el menu de Empresa, que era el
    unico de los tres que ya iba en 10.
    ⚠️ Solo las esquinas: el vidrio, la tapa, el borde, la sombra y lo de
    dentro se quedan como estaban.
  */
  padding: 10px;
  display: none;
  flex-direction: column;
  gap: 4px;
  box-shadow: 0 15px 35px rgba(0, 0, 0, 0.8), 0 0 15px rgba(0, 240, 255, 0.15);
  backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  -webkit-backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  z-index: 30;
}

.nix-menu.active {
  display: flex;
}

.nix-item {
  background: rgba(255, 255, 255, 0.03);
  border: none;
  color: var(--snow);
  /*
    🔴 11 y 9, CALCADOS DE LA CABINA (fundador, 2026-08-12b: *"debe ser tal
    cual el de la cabina, mismo desenfoque, mejor dicho calcado"*). Estaban en
    9 y 8 — dos pixeles de relleno y uno de hueco.

    ⚠️ Y LA INTENCION YA ESTABA ESCRITA AQUI DEBAJO desde el 2026-08-11: *"es
    el MISMO menu de Nix que en la cabina... un menu que mide distinto segun la
    pantalla deja de ser el mismo menu"*. Aquel dia se igualo la LETRA y se
    quedaron sin igualar el relleno y el hueco. *Una regla escrita a medias no
    se lee como media regla: se lee como cumplida.*

    🔴 LO DEMAS YA ERA IDENTICO, comprobado midiendo las dos en vivo antes de
    tocar nada: tapa `rgba(20,23,34,.30)`, `blur(14) saturate(1.6)`, borde cian
    de 0,8, radio 18, relleno 6, hueco 4, la misma sombra doble y 210 px de
    ancho. El desenfoque que el pedia igualar YA lo era.
  */
  padding: 11px 12px;
  border-radius: var(--r-chico);
  /* 15, era 11 (§5, la Ley · 2026-08-11). Es el MISMO menu de Nix que en la
     cabina, y alli tambien queda en 15: un menu que mide distinto segun la
     pantalla deja de ser el mismo menu. */
  font-size: var(--tam-secundario);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 9px;
  transition: background 0.2s;
}

/* Selector de idioma: control segmentado, las tres opciones a la vista.
   Un boton que cicla esconderia el portugues, y esconderlo mata la razon
   de ser: que el extranjero encuentre su idioma sin buscarlo. */
.lang-seg {
  display: flex;
  gap: 2px;
  background: rgba(255, 255, 255, 0.03);
  border-radius: var(--r-chico);
  padding: 2px;
}

.lang-opt {
  flex: 1;
  background: transparent;
  border: none;
  color: var(--ash);
  font-family: inherit;
  /* 13, era 11 (§5, la Ley · 2026-08-11). */
  font-size: var(--tam-terciario);
  font-weight: 500;
  letter-spacing: 0.04em;
  padding: 7px 0;
  /* Anidado dentro de .lang-seg: un hijo con el MISMO radio que su padre se
     ve mal pegado a la esquina. Se le resta el relleno, que es el patron que
     la maqueta ya usa para el KITT. */
  border-radius: calc(var(--r-chico) - 2px);
  cursor: pointer;
  transition: color 0.2s, background 0.2s;
}

.lang-opt:hover {
  color: var(--snow);
}

/* El activo: un solo acento de color, el cian del frente Business (§1b). */
.lang-opt.activo {
  color: var(--nix-cyan);
  background: rgba(0, 240, 255, 0.1);
}

/* Los iconos del menú: heredan el color del texto, así que son blancos.
   14 px y sin encogerse — un icono que se aplasta cuando el texto es largo
   deja de leerse como icono. */
.nix-item svg {
  width: 14px;
  height: 14px;
  flex: none;
}

.nix-item:hover {
  background: rgba(0, 240, 255, 0.15);
}

/*
  ⚠️ 28 Y NO 16 (fundador, 2026-08-13): *"vamos a abrir más aire entre la línea
  del «Buenas tardes y Nix» con la foto y el nombre de Valeria"*.

  Y NO SE HACE ALTA LA CAJA POR ESO: los 12 px que se abren aquí se le quitan
  al hueco entre "Ver paneles" y "Tus datos, en corto", que es lo que él pidió
  con todas las letras — *"bajemos todo el cuerpo desde la foto y el nombre
  hasta el CTA, para acercar todo ese cuerpo al link"*. El bloque BAJA; no
  crece. En una pantalla que ya va justa de alto, abrir aire sin cerrarlo en
  otro sitio es empujar el pie fuera de la vista.

  Medido antes: 16 px arriba y 32 abajo. Después: 28 y 20.
*/
.greet {
  font-size: 13px;
  color: var(--ash);
  margin-bottom: 28px;
  padding-right: 80px;
}

.owner {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 22px;
}

.avatar {
  width: 62px;
  height: 62px;
  border-radius: 50%;
  flex: none;
  position: relative;
  background: var(--void-2);
  display: flex;
  align-items: center;
  justify-content: center;
  /* 20, era 19 (§5, la Ley). Son las iniciales dentro del circulo de 62 px:
     "subtitulo" es el escalon que le corresponde. */
  font-size: var(--tam-subtitulo);
  font-weight: 500;
  color: var(--snow);
  box-shadow: 0 0 20px 2px rgba(255, 255, 255, 0.13), 0 6px 18px rgba(0, 0, 0, 0.55);
}

.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}

.avatar::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
  pointer-events: none;
}

.owner h1 {
  /* ⚠️ 24, era 19 — Y ES EL CAMBIO MAS GRANDE DE TODA LA LEY. §5 nombra esta
     pieza por su nombre en la tabla: "Titulo (el nombre del dueño) = 24". Es
     lo primero que lee un visitante y es de quien es la Caja; iba cinco
     puntos por debajo de lo que el propio documento le asigna.
     Y el peso baja a 600: §5 da tres pesos y el 700 no es uno de ellos. */
  font-size: var(--tam-titulo);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
  color: var(--snow);
}

.owner p {
  font-size: 13px;
  color: var(--snow-dim);
  font-weight: 400;
  margin-top: 3px;
  letter-spacing: 0.3px;
}

/* Nix Row Conversacional */
/*
  ⚠️ 14 Y NO 24 (fundador, 2026-08-13): *"sube desde las 4 tarjetas hasta el
  CTA «Ver paneles» 8 píxeles"*, y después *"subir otros 2"* — escogidos
  mirando, en dos pasadas. Es el mismo movimiento que el de arriba en el otro
  sentido: el bloque de las tarjetas SUBE, y los 10 px que deja de gastar aquí
  se los queda el aire de debajo del CTA. La Caja no encoge ni crece — el pie
  sigue acabando donde acababa.
*/
.nixrow {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin-bottom: 14px;
  /* Sostener el simbolo abre Soporte: el renglon no se selecciona ni saca el menu de copiar (2026-10-13). */
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}

/*
  EL SIMBOLO DE NIX. Antes era una "N" dibujada con la tipografia sobre un
  degradado blanco-cian hecho en CSS; desde el 2026-08-04 es la marca que
  entrego el fundador, reconstruida como vector cian
  (`assets/simbol_nix_cian.svg` — graphic_system.md §7d). Esta linea decia
  `simbol_nix.svg`, que existe pero no es el que el HTML carga: un papel
  que mandaba a buscar donde no es. Lo cazo Temis en su primera pesada.
  ⚠️ EL HALO SE QUEDA, y no es decoracion: el punto con halo es el ADN de Nix
  en toda la casa (graphic_system.md §7b, «cambia de luz, no de forma»). Lo que
  cambio es el dibujo de dentro, no lo que lo rodea.
  Si algun dia se quiere sin halo, es esta linea y solo esta.
*/
.nixdot {
  min-width: 20px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: block;
  /* El SVG ya trae su propio disco: se deja verlo entero sin recortarlo. */
  object-fit: contain;
  margin-top: 2px;
  box-shadow: 0 0 12px var(--nix-glow);
}

.nixrow p {
  /* Lo que Nix le dice al visitante ES el contenido principal de la
     Caja, no un pie de foto. Va en el tamano principal. */
  font-size: var(--tam-principal);
  line-height: 1.5;
  color: var(--texto);
}

.caret {
  color: var(--nix-cyan);
}

/* 4 Tarjetas en Retícula */
.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 11px;
  margin-bottom: 18px;
}

.tile {
  background: var(--panel);
  backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  -webkit-backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  border: 1px solid var(--line-2);
  border-radius: var(--r-tarjeta);
  padding: 20px 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 11px;
  font-family: inherit;
  /* 15, era 14 (§5, la Ley · 2026-08-11). Las cuatro tarjetas son ACCIONES, y
     en esta casa todo lo que se toca mide 15: `.accion` y `.control` de la
     cabina, `.nix-item` de los dos menus, y estas. */
  font-size: var(--tam-secundario);
  color: var(--texto);
  cursor: pointer;
  text-decoration: none;
  /* Esta receta es la DEL TOQUE y no se toca: 0,15 s es lo que hace que
     hundirse bajo el dedo se sienta inmediato. */
  transition: transform 0.15s, border-color 0.25s, box-shadow 0.25s;
  /*
    🔴 `visibility` Y NO `opacity`, POR §7g. Cada tarjeta lleva su propio
    `backdrop-filter`, asi que fundirla obliga al telefono a recomponer ese
    desenfoque en cada fotograma — el mismo defecto que ya se quito del
    contenedor, una capa mas adentro. `visibility` no se interpola: cambia y
    ya, sin nada que recomponer.
  */
  visibility: hidden;
  transform: translateY(8px);
}

/*
  🔴 LA ENTRADA VA POR `animation` Y NO POR `transition`, Y ESE ERA EL OTRO
  MEDIO SALTO. Antes, `.tile.in` cambiaba los VALORES y la RECETA en el mismo
  instante: la tarjeta pasaba de "muevete en 0,15 s" (lo que necesita al
  tocarla) a "muevete en 0,4 s" justo cuando empezaba a moverse. Cambiar el
  cuanto y el como a la vez deja el resultado a merced de cada navegador, y
  se ve como un movimiento partido en dos.
  Con `animation` la entrada viaja por su propio canal: el `transition` del
  toque se queda como estaba y nadie pisa a nadie.
  §7g — y una entrada es un EVENTO, no un estado.
*/
.tile.in {
  visibility: visible;
  transform: translateY(0);
  animation: tileEntra .4s cubic-bezier(.16, .9, .3, 1) backwards;
}

@keyframes tileEntra {
  from { transform: translateY(8px); }
  to   { transform: none; }
}

.tile:hover {
  border-color: rgba(0, 240, 255, 0.4);
}

.tile:active {
  transform: scale(0.97);
}

.tile svg {
  width: 22px;
  height: 22px;
  color: var(--nix-cyan);
}

/* La receta vive en tokens.css y la comparte con la cabina: los seis numeros
   estaban escritos a mano en los dos archivos. */
.access-granted-card {
  border-color: var(--accent-green) !important;
  box-shadow: var(--destello-verde) !important;
  transform: scale(1.02) !important;
}

/* LÍNEA DE TERMINAL CON LOGS EN BLANCO PURO */
.terminal-line {
  font-family: var(--font-mono);
  /* 13, era 11 (§5, la Ley · 2026-08-11). */
  font-size: var(--tam-terciario);
  color: var(--snow);
  text-align: left;
  padding: 8px 0;
  background: transparent;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  min-height: 30px;
}

#termText {
  letter-spacing: 0.5px;
  color: var(--snow);
}

.cursor {
  display: inline-block;
  width: 7px;
  height: 14px;
  background-color: var(--nix-cyan);
  vertical-align: middle;
  margin-left: 4px;
  animation: blink 0.8s infinite;
}

@keyframes blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}

/* BOTÓN CTA PRO "VER TARJETAS" (DESCANSO VISUAL MONOCROMÁTICO APPLE) */
.cta-cards-btn {
  width: 100%;
  background: var(--toque);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--r-tarjeta);
  padding: 14px 20px;
  color: var(--snow);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.5px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  -webkit-backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  transition: all 0.3s ease;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
  margin-bottom: 18px;
}

.cta-cards-btn:hover {
  border-color: rgba(255, 255, 255, 0.28);
  background: rgba(255, 255, 255, 0.07);
  box-shadow: 0 0 15px rgba(255, 255, 255, 0.06);
}

.cta-cards-btn:active {
  transform: scale(0.98);
}

.cta-cards-btn svg {
  width: 18px;
  height: 18px;
  color: var(--ash);
  transition: color 0.3s ease;
}

.cta-cards-btn:hover svg {
  color: var(--snow);
}

/* Formulario Handshake Inline */
.lead {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.45s ease;
}

/* OJO AL TOCAR EL FORMULARIO: este tope es lo que permite animar el
   despliegue, pero recorta en seco lo que no quepa — y con overflow:hidden no
   avisa: el boton simplemente deja de verse. Paso con el campo de la nota, que
   sumo ~90 px sobre los 240 que habia.
   ⚠️ LA HOLGURA YA SE GASTO A MEDIAS (2026-08-05): la casilla de autorizacion
   sumo 48 px y el contenido pasa de 383 a 431 medidos. Quedan 89 px, que dan
   para UNA fila mas y no para dos. El proximo campo sube este numero. */
.lead.open {
  max-height: 520px;
}

.lead-inner {
  padding-top: 11px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 15px;
}

.lead input {
  font-family: inherit;
  /* ⚠️ 17 px Y NO 14, Y NO ES SOLO LA ESCALA: en iPhone, un campo con
     letra por debajo de 16 px hace que Safari HAGA ZOOM al tocarlo. La
     pagina salta y el visitante pierde el sitio, justo en el momento mas
     caro del producto — dejar sus datos en una feria. Nunca bajar de 16. */
  font-size: var(--tam-principal);
  color: var(--snow);
  /*
    ⚠️ HUNDIDO Y NO OPACO. Lo corrigio el fundador viendolo en el celular:
    "esos cuadros del formulario se salen de la linea grafica y gritan".
    LA CAUSA, medida en la ficha: usaban `--card`, que es #0e0e13 SOLIDO — las
    unicas superficies opacas de una pantalla donde todo lo demas es vidrio
    sobre la camara. No desentonaban por el color: desentonaban por ser lo
    unico que no deja pasar nada detras.
    LA CURA NO INVENTA NADA: `--hundido` es la ficha que esta casa ya tiene
    para «esto esta metido en la pantalla», la misma de la pista del
    interruptor AR — la pinta que el fundador aprobo con "el fondo donde esta
    puesto esta muy bien". Y es CONCEPTUALMENTE lo correcto: un campo donde se
    escribe es una superficie hundida, no una que flota.
  */
  background: var(--hundido);
  box-shadow: var(--hundido-sombra);
  border: 1px solid var(--linea);
  border-radius: var(--r-chico);
  padding: 13px 14px;
}

/* La nota comparte por completo el aspecto de los campos: solo cambia que
   crece hacia abajo y que no se puede estirar a mano (en celular el tirador
   es un estorbo). Se lista junto a input para que nunca se separen. */
.lead textarea {
  font-family: inherit;
  font-size: var(--tam-principal);   /* mismo motivo que el input: el zoom */
  color: var(--snow);
  /* Mismo hundido que los campos de arriba — ver el porque alli. Si uno
     cambia, cambian los cuatro: son la misma superficie. */
  background: var(--hundido);
  box-shadow: var(--hundido-sombra);
  border: 1px solid var(--linea);
  border-radius: var(--r-chico);
  padding: 13px 14px;
  resize: none;
  line-height: 1.45;
}

/* La etiqueta de la nota. Es el unico campo que la lleva: los otros tres se
   entienden con solo el texto fantasma, este hay que invitarlo. Va en el mismo
   registro que las etiquetas del correo — mayusculas diminutas y grises — para
   que las dos superficies se sientan la misma casa (§1b-2). */
.lead-et {
  /* 13, era 11,5 (§5, la Ley · 2026-08-11). */
  font-size: var(--tam-terciario);
  font-weight: 600;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--ash);
  margin: 6px 0 -2px 2px;
}

.lead input::placeholder,
.lead textarea::placeholder {
  color: var(--ash-dim);
}

.lead input:focus,
.lead textarea:focus {
  outline: none;
  border-color: var(--nix-cyan);
}

/* Chrome pinta de blanco los campos que autocompleta y no acepta que se le
   cambie el fondo. El truco es una sombra interior gigante del color de la
   tarjeta, que lo tapa, mas -webkit-text-fill-color para el texto. Sin esto,
   correo y telefono aparecen en blanco sobre una Caja negra. */
.lead input:-webkit-autofill,
.lead input:-webkit-autofill:hover,
.lead input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--snow);
  -webkit-box-shadow: 0 0 0 1000px var(--card) inset;
  caret-color: var(--snow);
  transition: background-color 9999s ease-in-out 0s;
}

/*
  ⚠️ ESTE DEGRADADO SE QUEDA, Y ES UNA EXCEPCION DECIDIDA POR EL FUNDADOR.
  El sistema grafico §7 saca de la casa los degradados de varios colores por
  delatar "hecho con IA", y este boton cae de lleno en esa regla. Aun asi:
  "Ese boton lo dejamos asi, no hay que tocarlo, me gusta y me permito romper
  la regla solo con ese boton" (2026-08-03).
  NO lo cambies por un color plano "para cumplir el sistema". Es UN boton,
  nombrado, y la excepcion esta escrita tambien en graphic_system.md §7.
*/
.lead .send {
  font-family: inherit;
  font-size: var(--tam-principal);
  font-weight: 600;
  color: var(--void);
  background: var(--grad);
  border: none;
  border-radius: var(--r-chico);
  padding: 14px;
  cursor: pointer;
}

.lead .send:active {
  transform: scale(0.985);
}

.lead-ok {
  font-size: 13px;
  color: transparent;
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  display: none;
  text-align: center;
  padding: 8px;
}

/* Campo con error. El aviso flotante puede quedar tapado por el teclado del
   celular; el borde del campo no. Rojo = estado, igual que el verde del
   semaforo (webapp_nix.md §1b): aparece y se va, nunca decora. */
.lead input.invalido {
  border-color: var(--error);
  box-shadow: 0 0 0 1px rgba(255, 77, 77, 0.35);
}

/* LA CASILLA DE AUTORIZACION (Ley 1581 art. 9).
   ⚠️ TODA LA FILA ES TOCABLE, no solo el cuadrito de 18 px: es un <label>,
   asi que el dedo acierta cayendo en cualquier parte del texto. Un objetivo
   de 18 px en un celular es una trampa, y esta es la casilla que decide si
   el contacto se guarda o se pierde. */
.lead-permiso {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 2px 0 4px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
/* La casilla de verdad se esconde pero SIGUE EXISTIENDO para el teclado y
   para los lectores de pantalla: `display:none` la sacaria del formulario.
   Lo que se ve es el cuadrito dibujado de al lado. */
.lead-permiso input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}
.lead-marca {
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  /* 8, era 5 (§6, la Ley · 2026-08-11). La casa tiene cuatro radios y cada uno
     dice de que tamaño es la cosa: 8 es "lo pequeño que se toca", que es
     exactamente esto. El 5 no era ninguno. */
  border-radius: var(--r-chico);
  border: 1px solid var(--linea);
  background: var(--hundido);
  box-shadow: var(--hundido-sombra);
  display: grid;
  place-items: center;
  color: var(--void);
  transition: background .16s ease, border-color .16s ease;
}
.lead-marca svg { width: 12px; height: 12px; opacity: 0; transition: opacity .12s ease; }
/* Marcada: se llena de cian y el chulo aparece. El cian aqui es legal — §1b-2
   lo reserva para "donde Nix habla" y para el estado, y esto es estado. */
.lead-permiso input:checked + .lead-marca {
  background: var(--nix-texto);
  border-color: var(--nix-texto);
}
.lead-permiso input:checked + .lead-marca svg { opacity: 1; }
/* El foco del teclado tiene que verse: sin esto, quien navega con tabulador
   no sabe donde esta parado. */
.lead-permiso input:focus-visible + .lead-marca {
  outline: 2px solid var(--nix-texto);
  outline-offset: 2px;
}
.lead-permiso-txt {
  /* 13, era 11,5 (§5, la Ley). Es el texto de la autorizacion de la Ley 1581:
     un permiso que no se lee no es un permiso informado. */
  font-size: var(--tam-terciario);
  line-height: 1.45;
  color: var(--texto-2);
}
/* Sin marcar al enviar: el mismo naranja del resto del formulario. El error
   es NARANJA y no rojo (decision del fundador), y se quita al marcarla. */
.lead-permiso.invalido .lead-marca {
  border-color: var(--error);
  box-shadow: 0 0 0 1px rgba(255, 77, 77, .35);
}
.lead-permiso.invalido .lead-permiso-txt { color: var(--error); }

/* AQUI VIVIA `.lead-nota`, retirada por el fundador el 2026-08-05. El porque
   completo esta escrito en el HTML, donde estaba la frase. En corto: de los
   tres textos que hablaban de datos era el unico que no era obligatorio ni era
   puerta, y quedaba DEBAJO del boton — tranquilizar despues de la decision
   llega tarde. Su promesa la dice mejor la ventana de privacidad. */

/*
  EL ENLACE DEL AVISO DE PRIVACIDAD. Cosido entre el boton de tarjetas y la
  fila de interruptores (fundador, 2026-08-05): "visible pero que no ensucie
  el diseno". Por eso NO es un boton: no lleva fondo, ni borde, ni pildora —
  una cuarta superficie ahi competiria con el boton de tarjetas, que es la
  accion de verdad. Es texto, subrayado suave, del tercer nivel de tinta.
  ⚠️ SUBRAYADO Y NO SOLO COLOR: sin el, sobre esta pantalla se lee como una
  nota al pie y nadie descubre que se toca. El subrayado es lo que dice
  "esto abre algo" sin gritar.
*/
.privacidad-link {
  display: block;
  /*
    ⚠️ ESTE MARGEN ES EL CONTRAPESO DE LOS DOS MOVIMIENTOS DEL 2026-08-13, y
    por eso lleva dos cuentas encima. Los dos encargos del fundador fueron de
    MUDANZA, no de crecer: un bloque baja o sube, y el aire que gana por un
    lado lo paga por el otro.

      14  de siempre
      −12 "bajemos el cuerpo desde la foto hasta el CTA para acercarlo al
          link" → el aire bajo el botón pasó de 32 a 20
      +8  "sube desde las 4 tarjetas hasta el CTA 8 píxeles" → y vuelve a 28
      +2  "subir otros 2" → 30
      ───
      12

    ⚠️ SE TOCA ESTE MARGEN Y NO EL DEL BOTÓN, y no da igual: entre los dos vive
    el formulario de "Dejar mis datos", que crece al abrirse. Quitándoselo al
    botón, el formulario abierto se pegaría a lo que tiene ENCIMA; tocándolo
    aquí, el aire que se mueve es el de abajo, que es el que él señaló.
    Comprobado con el formulario abierto: sigue separado de su botón Enviar.
  */
  margin: 12px auto 0;
  background: none;
  border: 0;
  padding: 6px 10px;      /* el area del pulgar; el dibujo sigue siendo el texto */
  color: var(--texto-3);
  font-family: inherit;
  /* 13, era 11,5 (§5, la Ley · 2026-08-11). */
  font-size: var(--tam-terciario);
  letter-spacing: .2px;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(var(--toque-rgb), .28);
  -webkit-tap-highlight-color: transparent;
}
.privacidad-link:hover { color: var(--texto-2); }

.foot {
  margin-top: auto;
  /*
    ⚠️ 26 Y NO 16: el enlace de privacidad se metio justo encima y con 16 la
    fila de interruptores quedaba apretada contra el (fundador: "bajar un poco
    los botones, que no se vea apretado"). El aire de esta fila ahora tiene
    que separarla de un vecino nuevo, no del boton de tarjetas.
  */
  padding-top: 26px;
  display: flex;
  align-items: center;
  gap: 14px;
}

/*
  ⚠️ LA MARCA YA NO VIVE EN ESTA FILA. Decision del fundador (2026-08-04) al
  pedir el interruptor TURBO: "colocarlo donde ahora dice powered Ermine y ese
  texto pasarlo abajo centrado". Y es lo correcto por una razon que se ve al
  hacerlo: el pie es la fila de los INTERRUPTORES —ahi ya vivia el AR— y una
  firma no compite con un control por el mismo sitio.
*/

/*
  ⚠️ «CENTRADO» AQUI SIGNIFICA EQUIDISTANTE DE SUS VECINOS, NO DEL CONTENEDOR.
  Lo explico el fundador el 2026-08-04 despues de dos intentos mios que no
  eran lo que pedia: *"el espacio entre el boton AR y la «T» de turbo debe ser
  el mismo que el fin del boton de turbo y el ambientador"*.
  MIS DOS INTENTOS FALLIDOS, Y POR QUE: primero centre el TURBO en el
  CONTENEDOR (grid 1fr auto 1fr) — 0 px de desvio y huecos de 41 y 85, o sea
  matematicamente centrado y visualmente torcido. Luego le sume una correccion
  a ojo de 7 px, que era tapar el sintoma con un numero a mano.
  LO QUE PEDIA ERA MAS SIMPLE Y MEJOR: repartir el sobrante en dos huecos
  IGUALES. El AR se apoya en el borde izquierdo y el ambientador en el derecho
  —los dos alineados con la rejilla de tarjetas, que es la referencia de toda
  la Caja— y el TURBO cae solo donde tiene que caer.
  Sin numeros a mano y sin compensaciones: la regla lo dice todo, y sigue
  valiendo el dia que el AR desaparezca en un telefono sin camara.
*/
.foot {
  display: flex;
  align-items: center;
  /* 14 es el aire de siempre de esta fila: el que ya separaba al AR del
     repetir antes de que existiera ninguno de los otros dos. */
  gap: 14px;
}
.foot > * { min-width: 0; }

/*
  ⚠️ EL TURBO VA PEGADO AL AR Y EL AMBIENTADOR SE VA SOLO AL BORDE.
  Tercer reparto de esta fila en una tarde, y lo cerro el fundador viendolo:
  "pega turbo a AR, no me convence como se ve, obviamente dejando el aire
  correspondiente".
  LOS DOS ANTERIORES, Y POR QUE NO ERAN:
  1. TURBO centrado en el CONTENEDOR — 0 px de desvio matematico y huecos de
     41 y 85. Centrado en el papel, torcido a la vista.
  2. Huecos IGUALES con space-between — 63 y 63. Correcto, y aun asi no era
     lo que el queria ver.
  LO QUE SI ES: los dos interruptores del dueño JUNTOS, como lo que son —dos
  cosas de la misma familia, que se tocan— y el ambientador solo en su
  esquina. **El agrupamiento dice mas que el reparto: lo que va junto se lee
  junto.** Ninguna cuenta de centrado iba a dar con eso, porque el problema
  nunca fue la distancia: era de que lado pertenecia cada cosa.
  ⚠️ `margin-left:auto` y no un ancho a mano: el ambientador se empuja al
  borde con lo que sobre, sea cual sea la pantalla y exista o no el AR.
*/
.foot #btnPiel { margin-left: auto; }

/*
  LOS TRES PIXELES DEL OJO DEL FUNDADOR: "corre a AR y Turbo tres lineas a la
  derecha". Los dos interruptores se mueven JUNTOS, que es lo que los mantiene
  siendo un grupo: separarlos aqui desharia el agrupamiento que se acaba de
  decidir arriba.
  ⚠️ En `transform` y no en `margin`, por lo mismo de siempre: mueve el dibujo
  sin tocar el reparto. Los 14 px de aire siguen siendo 14 para el navegador,
  el repetir y el ambientador no se enteran, y el dia que se quite esta linea
  todo vuelve solo a su sitio.
*/
.foot #btnAR,
.foot #btnTurbo { transform: translateX(3px); }

/*
  LA SEGUNDA FILA — el repetir bajo el AR y la firma a la derecha, como pidio
  el fundador. Arriba solo los tres interruptores; aqui una accion ocasional y
  una firma, que no compiten con ellos por la mirada.
*/
/* La segunda fila se quedo con la firma sola cuando el repetir subio arriba.
   A la derecha, que es donde estaba antes de todo esto. */
/*
  EL PIE DE LA VITRINA, CON LA DISTRIBUCION DE LA CABINA (fundador,
  2026-08-07: *"mismos botones con la misma distribucion y espaciado de
  cabina"*). La cabina reparte con `space-between`, `gap: 12px` y
  `padding: 17px 0 0` (cabin.css `.pie`); la Caja los tenia pegados a la
  izquierda con 14 de hueco y 26 de aire arriba.
  ⚠️ SOLO EN MODO VITRINA, y no es timidez: los 26 px de la Caja los pidio
  el mismo fundador el 2026-08-04 —*"bajar un poco los botones, que no se
  vea apretado"*— porque ahi arriba vive el enlace de privacidad. En la
  vitrina ese vecino no existe. Cambiar los dos habria deshecho una
  decision suya para cumplir otra.
*/
body.en-paneles #caja > .foot {
  justify-content: space-between;
  gap: 12px;
  padding-top: 17px;
}

/*
  NIX SUBE A LA FILA DE LA CABECERA, SOLO EN VITRINA (fundador, 2026-08-07:
  *"Nix en su lugar, derecha arriba"*). Su esquina sigue siendo suya; lo
  que cambia es la altura.
  ⚠️ POR QUE HACIA FALTA: Nix vive en la Caja y su `top: 0` es el de #caja,
  que arranca 127 px mas abajo que la cabecera de la vitrina — medido. Asi
  que "arriba a la derecha" era cierto en la Caja y falso aqui, y los tres
  no quedaban en una linea.
  `fixed` y no `absolute`: en vitrina la Caja esta apagada debajo y su caja
  de referencia no es la que se ve. Es el mismo reparo ya anotado el
  2026-08-06 — *"Nix baja cuando la pantalla crece"*—, curado de raiz.
*/
body.en-paneles #caja > .nix-btn-container {
  position: fixed;
  /* 37, tras siete pasadas de su ojo entre el 2026-08-07 y el 08-08:
     20 → 26 → 32 → 33 → 34 → 35 → 36 → 37. Dos saltos de 6 para hallar la zona
     y cinco de 1 para rematarla. *Un remate no se calcula: se tantea, y por
     eso los ultimos cinco valen un pixel cada uno.*
     ⚠️ SE BAJA AQUI Y NO EN `.nix-btn-container`, que es la regla general:
     el rincon de Nix es el mismo en toda la casa por regla suya —*"eso no
     cambia en ningun panel ni en ninguna parte"*— y tocar la general lo
     habria movido tambien en la Caja, que el no esta mirando. Esta regla ya
     existia solo para la vitrina; el pixel entra donde ya habia un desvio
     declarado. */
  top: calc(37px + env(safe-area-inset-top));
  right: 16px;
}

.foot-2 {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-top: 10px;
}
/* Cuatro pixeles a la derecha, buscados a ojo por el fundador en tres pasos
   (dos, tres mas, uno menos). Mismo criterio que los de arriba: `transform`
   mueve el dibujo y no el reparto, asi que la firma sigue apoyada en el borde
   para el navegador.
   ⚠️ Queda 4 px PASADA del borde de las tarjetas, o sea fuera de la columna en
   la que se alinea todo lo demas de la Caja. Es a proposito: una firma pequeña
   y gris no se lee como parte de la retícula, y sacarla un pelo la separa de
   los controles en vez de dejarla colgando de ellos. */
.foot-2 .brand { transform: translateX(4px); }

/*
  ⚠️ LA FIRMA VOLVIO A LA DERECHA (2026-08-04), donde estaba antes de que el
  TURBO le quitara el sitio. Estuvo unas horas centrada bajo los controles y el
  fundador la devolvio: "powered by Ermine a la derecha como estaba antes".
  Ya no necesita reglas propias — se coloca sola con el `space-between` de
  `.foot-2`, que es lo que debia ser desde el principio.
*/

/* =====================================================================
   EL INTERRUPTOR DE AR — bloque G

   Forma pedida por el fundador: pildora con una capsula al final, no un
   boton redondo. La referencia que trajo eran botones blancos con
   degradados de colores; se toma LA FORMA y nada mas — esos degradados y
   ese blanco plano son, rasgo por rasgo, lo que §7 saca de la casa por
   delatar "hecho con IA".

   ⚠️ EL ESTADO NO SE DICE CON COLOR, Y ES A PROPOSITO. §4 reparte los
   cuatro halos —blanco por defecto, cian solo Nix, verde salio bien,
   naranja algo fallo— y "encendido" no es ninguno de los cuatro. Un cian
   permanente aqui le robaria a Nix su unico color.
   Se dice con RELLENO: encendida la capsula es solida y el icono va en
   negativo; apagada esta hueca y el icono en gris. Es como lo marca iOS,
   no gasta un color, y se entiende sin leer.
   ===================================================================== */

.ar {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 4px 0;
  background: none;
  border: 0;
  color: var(--ash);
  font-family: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* El navegador no sabe encender la camara: el boton no existe. Un
   interruptor que no interrumpe nada es peor que no tenerlo. */
.ar.oculto-ar { display: none; }

.ar-txt {
  font-size: var(--tam-terciario);
  font-weight: 500;
  letter-spacing: .12em;          /* dos letras sueltas necesitan aire */
  transition: color .22s ease;
}

/*
  LA PISTA VA HUNDIDA — pedido del fundador, "algo que se sienta metido en la
  pantalla". Es el filo de luz LEIDO AL REVES, y por eso pertenece a la casa
  en vez de ser un injerto: en todo lo demas la luz va en el borde SUPERIOR
  para decir "esto flota"; aqui la sombra va arriba y la luz abajo, que es
  como se lee "esto esta hundido".
  ⚠️ ESTA PARTE ESTA APROBADA Y NO SE TOCA: "el fondo donde esta puesto esta
  muy bien". Lo que se corrigio fue la perilla, no la pista — se aplanaron las
  dos por leerlo mal, y el fundador lo aclaro en una linea.
*/
.ar-pista {
  position: relative;
  width: 44px;
  height: 26px;
  flex: none;
  border-radius: var(--r-pildora);
  background: var(--hundido);
  box-shadow: var(--hundido-sombra);
}

/*
  LA PERILLA: UN PUNTO BLANCO LIMPIO, Y NADA MAS.
  Decision del fundador (2026-08-03): "deberia verse 2D y limpio sin nada
  encima". Es la tercera version de esta pieza y las dos anteriores fallaron
  por lo mismo — el tamaño.
  (La historia vivia en un comentario dentro del HTML. Se trajo aqui porque
  EL HTML VIAJA AL TELEFONO DE CADA VISITANTE en cada carga, y porque alli
  ademas ya mentia: seguia describiendo una capsula con un icono que habia
  dejado de existir dos versiones antes.)
  Las tres versiones y por que fallaron:
    · las cuatro esquinas del visor: a 13 px son cuatro trazos que no se
      tocan, y un trazo que no cierra se lee como algo roto;
    · la lente: cerraba bien, pero seguia siendo un dibujo dentro de 18 px;
    · el degradado y la sombra proyectada: a ese tamaño no se leen como
      volumen, se leen como suciedad.
  A 18 px lo unico que sobrevive es la SILUETA. Un circulo liso.
*/
.ar-perilla {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: var(--r-pildora);
  background: var(--ash);
  /* La misma curva de desaceleracion que usa toda la casa: el ADN de
     movimiento no cambia por componente. */
  transition: transform .26s cubic-bezier(.16, .9, .3, 1),
              background .22s ease;
}

/*
  ENCENDIDO: la perilla se corre y se pone blanca. Y nada mas.
  ⚠️ EL ESTADO NO SE DICE CON COLOR, Y ES A PROPOSITO. §4 reparte los cuatro
  halos —blanco por defecto, cian SOLO Nix, verde salio bien, naranja algo
  fallo— y "encendido" no es ninguno de los cuatro. Un cian aqui le robaria a
  Nix su unico color. Se dice con posicion y con blanco, que se entiende sin
  leer y no gasta un color.
*/
.ar[aria-pressed="true"] .ar-perilla {
  transform: translateX(18px);
  background: var(--snow);
}

.ar[aria-pressed="true"] .ar-txt { color: var(--snow); }

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

/* =====================================================================
   EL BOTON DE LA PIEL — Auto · Claro · Oscuro (§3)

   ⚠️ REDONDO Y NO PILDORA, Y NO ES CAPRICHO: el AR y el TURBO son
   interruptores —encendido o apagado— y una pildora dice exactamente eso.
   Esto tiene TRES estados y ninguno es "apagado": una pildora tendria que
   mentir para representarlo. §3 ya lo pedia redondo.

   ⚠️ Y NACE PORQUE LA LUZ SOLA NO BASTA. El fundador lo pidio el 2026-08-04
   probando el camaleon: "se salta continuamente, muy sensible… se deja
   estatico cuando uno quiera o lo cambia cuando uno quiera". Los dos frenos
   del promedio calman el salto; esto le da el mando.
   ===================================================================== */
.piel {
  flex: none;
  width: 30px;
  height: 30px;
  padding: 0;
  border-radius: var(--r-pildora);
  background: var(--hundido);
  box-shadow: var(--hundido-sombra);
  border: 1px solid var(--linea);
  color: var(--ash);
  cursor: pointer;
  display: grid;
  place-items: center;
  -webkit-tap-highlight-color: transparent;
  transition: color .22s ease;
}

/* El blanco del pulgar, cuarta vez en esta casa: el dibujo mide 30 y un dedo
   cubre 44. Un rectangulo invisible por encima crece el area, no el boton —
   el mismo truco del microfono y del altavoz. */
.piel { position: relative; }
.piel::after { content: ""; position: absolute; inset: -7px; }

.piel-icono { display: grid; place-items: center; width: 16px; height: 16px; }
.piel-icono svg { grid-area: 1 / 1; width: 16px; height: 16px; display: none; }

/* Solo se ve el icono del estado en el que esta. Los tres viven en el mismo
   sitio del grid, asi que el boton no cambia de tamaño al cambiar de piel. */
.piel[data-modo="auto"]   .piel-auto,
.piel[data-modo="claro"]  .piel-claro,
.piel[data-modo="oscuro"] .piel-oscuro { display: block; }

/*
  ⚠️ EL CIAN AQUI ES LEGAL, y es el unico sitio de este pie donde lo es. §4 lo
  reserva para "donde Nix habla", y §3 dice literalmente que el punto cian de
  Auto significa «lo esta decidiendo la luz, no tu» — o sea, es la Caja
  actuando sola. Fijada por el dueño, el icono se apaga a gris: ya no decide
  nadie mas que el.

  ⚠️ EL COLOR VA EN CADA ICONO Y NO EN EL ESTADO DEL BOTON, y es a proposito.
  Primero se escribio como `.piel[data-modo="auto"] { color: … }`, o sea el
  boton cambiando de color segun su estado; medido en el navegador, el color
  computado se quedaba en cian con el atributo ya cambiado a "oscuro" y el
  selector sin coincidir. En vez de perseguir por que, se le da la vuelta:
  cada icono trae SU color y solo uno se ve a la vez, asi que el resultado es
  el mismo y no depende de que nada se recalcule.
  Y ademas se lee mejor: el punto de Auto es cian SIEMPRE que se vea; el sol y
  la luna son grises siempre. El color es del dibujo, no del estado.
*/
.piel .piel-auto   { color: var(--nix-cyan); }
.piel .piel-claro,
.piel .piel-oscuro { color: var(--ash); }

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

.replay {
  background: none;
  border: none;
  font-family: inherit;
  /* 13, era 12 (§5, la Ley · 2026-08-11). */
  font-size: var(--tam-terciario);
  color: var(--ash-dim);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
}

.replay:hover {
  color: var(--ash);
}

.replay svg {
  width: 13px;
  height: 13px;
}

.brand {
  /* 13, era 11 (§5, la Ley · 2026-08-11). */
  font-size: var(--tam-terciario);
  color: var(--ash-dim);
}

.brand b {
  font-weight: 500;
  color: var(--texto-2);
}

#toast {
  position: fixed;
  left: 20px;
  right: 20px;
  bottom: 20px;
  max-width: 338px;
  margin: 0 auto;
  background: var(--panel-solido);
  border: 1px solid var(--line-2);
  border-radius: var(--r-tarjeta);
  padding: 12px 15px;
  font-size: 13px;
  color: var(--texto);
  opacity: 0;
  transform: translateY(10px);
  transition: 0.3s;
  pointer-events: none;
  text-align: center;
  /* 45 y no 9 (2026-08-06): con 9, el "Proximamente" de una tarjeta apagada
     salia DEBAJO del velo de la vitrina (30) — un aviso que nadie ve es un
     boton mudo. Encima de todo lo tocable, debajo del vuelo de Nix (50). */
  z-index: 45;
}

#toast.show {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
  #s0, #s1 { display: none; }
  #caja { opacity: 1; }
  /* `visibility` desde que las tarjetas dejaron de fundirse (§7g). */
  .tile { visibility: visible; transform: none; }
  .caret { display: none; }
}

/* ============================================================
   LA VENTANA DE PRIVACIDAD
   ============================================================
   Tres lineas y el resto detras de "ver mas" (fundador, 2026-08-05).
   `<dialog>` nativo: Escape y el fondo la cierran sin codigo nuestro.
*/
.priv {
  border: 0;
  padding: 0;
  background: none;
  max-width: 400px;
  width: calc(100% - 32px);
  /* La ventana no puede pasar de la pantalla: con "ver mas" abierto crece, y
     lo que sobra se desplaza POR DENTRO de la caja, no en la pagina. */
  max-height: 82dvh;
  color: var(--texto);
}
.priv::backdrop {
  background: rgba(3, 5, 9, .62);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

/* El vidrio de la casa. Va en la caja de adentro y no en el <dialog>, porque
   el desenfoque y el scroll en la misma superficie se pelean en Safari. */
.priv-caja {
  background: var(--panel);
  border: 1px solid var(--linea);
  border-top-color: var(--filo);
  border-radius: var(--r-tarjeta);
  backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  -webkit-backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  padding: 22px 20px 18px;
  max-height: 82dvh;
  overflow-y: auto;
  scrollbar-width: none;
}
.priv-caja::-webkit-scrollbar { display: none; }

.priv h2 {
  margin: 0 0 10px;
  font-size: var(--tam-principal);
  font-weight: 600;
  letter-spacing: -.2px;
}
/* Las tres lineas que hacen el trabajo. Van en el tamano principal: son EL
   mensaje, no un pie de pagina. */
.priv-corto {
  margin: 0;
  /* 15, era 13,5 (§5, la Ley). El comentario de arriba ya lo decia —"es un
     mensaje, no un pie de pagina"— y el tamaño decia lo contrario. */
  font-size: var(--tam-secundario);
  line-height: 1.55;
  color: var(--texto-2);
}

/*
  EL CAMPO DE SOPORTE (2026-08-13). Vive dentro del mismo `<dialog>` que el
  aviso de privacidad y hereda su caja, su fondo y su botón de abajo: lo único
  que hace falta escribir es el campo, porque un cuadro para escribir no
  existía todavía en esta pantalla.

  ⚠️ 17 Y NO MENOS, y no es de §5: **por debajo de 16 px, iOS hace zoom solo al
  tocar un campo** y la Caja se descoloca entera. Es la misma cifra y el mismo
  motivo que el cuadro de diálogo de Nix en la cabina (graphic_system §7i).
  ⚠️ `resize: none`: la manija de estirar la pinta el navegador con SU aspecto
  —gris, cuadrada, ajena— justo en la esquina de un cuadro con radio 18.
  ⚠️ Y radio 8, no 18: es lo pequeño que se toca dentro de un panel (§6), y la
  ley concéntrica pide que lo de dentro sea menor que lo de fuera.
*/
/* ⚠️ 14 Y NO 18 DESDE EL 2026-08-13b: las etiquetas se mudaron encima del campo
   por orden del fundador, así que los dos márgenes se INTERCAMBIARON — el 18
   que separaba de la bajada se fue con quien ahora toca la bajada, y aquí
   queda el 14 que separa de las etiquetas. La suma no cambió: el cuadro mide
   lo mismo y el pie no se movió. (La ley de la mudanza: se revisa lo que va
   pegado al SITIO, no lo que va dentro de la pieza.) */
/*
  🔴 EL CAMPO PASA A SER UN RECUADRO DE DOS FILAS (fundador, 2026-08-13b):
  *"que esté dentro del cuadro junto al micrófono de enviar audio; tal cual como
  está en el cuadro de diálogo de Nix"*. Es la receta de `.nix-campo` PORTADA,
  con las fichas de esta pantalla — no una versión parecida.
  El borde y el fondo se mudan del `<textarea>` a su padre: el que dibuja la
  caja es ahora el contenedor, y el texto de dentro va desnudo.
*/
.sop-campo {
  display: grid;
  gap: 8px;
  min-width: 0;
  box-sizing: border-box;
  margin-top: 14px;
  padding: 10px 10px 8px;
  background: var(--toque);
  border: 1px solid var(--linea);
  border-radius: var(--r-chico, 8px);
}

/* El anillo del navegador es azul y no es de nadie de esta casa: se cambia por
   el cian de Nix, que es quien está preguntando.
   ⚠️ Y AHORA CUELGA DE `:focus-within` Y NO DE `:focus`: el que se enciende es
   la caja, y el foco lo recibe un hijo. Con `:focus` se habría quedado apagada
   para siempre — la caja no toma foco nunca. */
.sop-campo:focus-within {
  border-color: var(--nix-cyan);
  box-shadow: 0 0 0 3px rgba(var(--nix-halo-rgb), .18);
}

.sop-campo textarea {
  width: 100%;
  min-width: 0;
  display: block;
  background: none;
  border: 0;
  padding: 2px 3px;
  color: var(--texto);
  font-family: inherit;
  /* ⚠️ 17 Y NO MENOS, y no es de §5: por debajo de 16 px iOS hace zoom solo al
     tocar un campo y la Caja se descoloca entera. Cualquier "arreglo" que lo
     baje de 16 rompe la escritura. */
  font-size: 17px;
  line-height: 1.5;
  resize: none;
  overflow-y: auto;
  scrollbar-width: none;
  -webkit-tap-highlight-color: transparent;
}
.sop-campo textarea::-webkit-scrollbar { display: none; }
.sop-campo textarea:focus { outline: none; }
.sop-campo textarea::placeholder { color: var(--texto-3); }

/*
  LA LÍNEA ACOMPAÑANTE. Los botones son hijos DIRECTOS de la fila, sin un div
  que los agrupe: metidos en uno se encogen a su mínimo aunque sobre sitio (el
  `fit-content` de un contenedor con hijos encogibles usa el mínimo de los
  hijos). Costó una medida entera en la maqueta de la barra de Nix.
*/
.sop-acompana {
  display: flex;
  align-items: center;
  /* A LA DERECHA, por orden del fundador (2026-08-13b). En la barra de Nix
     quedan ahí porque la cápsula de «Guardar» los empuja con `margin-right:auto`
     desde la izquierda; aquí no hay cápsula que empuje, así que lo hace la
     propia fila. Mismo sitio, y por eso el dedo los encuentra donde ya sabe. */
  justify-content: flex-end;
  gap: 0;
  min-width: 0;
}
.sop-acompana[hidden] { display: none !important; }

/*
  LOS DOS ICONOS DE LA LÍNEA — el clip y el micrófono (fundador, 2026-08-13b).
  Misma pinta que `.nix-mic` y `.nix-adjuntar` de la barra de Nix: 44 de alto,
  `flex:0 1 44` con suelo de 36, y el dibujo en 17.

  ⚠️ 44 DE ALTO DE VERDAD, no un icono de 17 con un halo invisible. El truco del
  `::after` que agranda existe donde NO CABE el botón entero; aquí cabe. Y §7i
  ya tiene medido su defecto: dos halos vecinos se solapan y gana el de la
  derecha, así que el de la izquierda se queda en 39.
  *El blanco del pulgar se mide, no se envuelve.*

  ⚠️ Y `gap:0` en la fila, no por apretarlos: con hueco, los blancos de dos
  vecinos se pisan. Sin hueco y anchos de verdad, cada uno da sus 44.
*/
.sop-icono {
  position: relative;
  flex: 0 1 44px;
  min-width: 36px;
  height: 44px;
  display: grid;
  place-items: center;
  background: none;
  border: 0;
  padding: 0;
  border-radius: var(--r-chico, 8px);
  /* `--texto-2` y no `--texto`: son herramientas al lado del campo, no la
     acción del cuadro. Al usarse se encienden. */
  color: var(--texto-2);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color .18s ease;
}
.sop-icono svg { width: 17px; height: 17px; }
/* Con algo puesto el icono se queda encendido: dice "esto lleva algo" sin
   añadir un renglón que lo explique. */
.sop-icono.puesto { color: var(--texto); }

/*
  GRABANDO. El cian es de Nix (§4) y aquí lo lleva con motivo: es Nix quien
  está oyendo, igual que en la barra. Y el latido dice que sigue vivo — un
  micrófono que se queda quieto mientras graba no distingue "te escucho" de
  "se colgó".
*/
.sop-icono.grabando {
  color: var(--nix-cyan);
  animation: sopOye 1.4s ease-in-out infinite;
}
@keyframes sopOye {
  0%, 100% { opacity: 1; }
  50%      { opacity: .45; }
}
/* Quien apaga el movimiento no pide que las cosas tarden lo mismo sin moverse:
   pide que no se muevan. El cian solo ya dice que está grabando. */
@media (prefers-reduced-motion: reduce) {
  .sop-icono.grabando { animation: none; }
}

/*
  LA FOTO ELEGIDA. Es la misma tira que la barra de Nix —miniatura, lo que pesa
  y la equis—, con las fichas de esta pantalla. Va DEBAJO y no dentro del campo:
  encima le robaría al texto las líneas que §7i le devolvió.
*/
.sop-foto {
  display: flex;
  align-items: center;
  gap: 10px;
  /* 14 desde que subió encima del campo: es el margen que separa de las
     etiquetas, el mismo que lleva el campo cuando ella no está. La ley de la
     mudanza — el margen es del SITIO, no de la pieza. */
  margin-top: 14px;
  padding: 8px 10px;
  background: var(--toque);
  border: 1px solid var(--linea);
  border-radius: var(--r-chico, 8px);
}
.sop-foto img {
  width: 44px;
  height: 44px;
  object-fit: cover;
  border-radius: var(--r-chico, 8px);
  flex: none;
  display: block;
}
/* Si la miniatura no carga se esconde: un icono de imagen rota dice "algo se
   estropeó" sobre una foto que está perfecta y lista para irse (defecto que el
   fundador reportó el 2026-08-03 en la barra de Nix). */
.sop-foto img[hidden] { display: none !important; }
.sop-foto .que {
  flex: 1;
  min-width: 0;
  font-size: var(--tam-terciario);
  color: var(--texto-2);
}
.sop-quitar {
  width: 44px;
  height: 44px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  color: var(--texto-2);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.sop-quitar svg { width: 17px; height: 17px; }
/* ⚠️ `hidden` con `!important`, la lección del 2026-08-05: el `display:none`
   del atributo lo pone el navegador y CUALQUIER regla nuestra le gana — aquí,
   el `display:flex` de tres líneas más arriba. Sin esto, la tira vacía se
   queda puesta desde que carga la página. Se probó que ABRIERA y nunca que
   estuviera CERRADO. */
.sop-foto[hidden] { display: none !important; }

/* Lo adjunto que NO es una foto —un PDF— no tiene miniatura que enseñar, así
   que en su sitio va el propio clip. Un cuadrado gris vacío diría "la vista
   previa se rompió" sobre un archivo que está perfecto. */
.sop-foto .sop-marca {
  width: 44px;
  height: 44px;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: var(--r-chico, 8px);
  background: rgba(var(--toque-rgb), .10);
  color: var(--texto-2);
}
.sop-foto .sop-marca svg { width: 19px; height: 19px; }
.sop-foto .sop-marca[hidden] { display: none !important; }

/*
  LOS DOS BOTONES DEL CUADRO. Misma forma, mismo tamaño, mismo radio — es lo
  que pidió el fundador el 2026-08-13.

  🔴 SON EL BOTÓN DE LA CABINA, Y LO DECIDIÓ UN MOTIVO FUNCIONAL SUYO
  (2026-08-13b): *"cambiemos los 2 CTAs por el mismo que tenemos en cabina; la
  razón es que en blanco no se ve el efecto KITT ni la activación en verde"*.

  **Estuvieron blancos con letra oscura menos de una hora**, por orden suya
  también, copiando la pareja invertida de `.panel-accion` (la vitrina). Y el
  blanco era correcto de color y equivocado de OFICIO: el anillo cian de §6 se
  pinta sobre el borde del propio botón, y sobre una plancha casi blanca no le
  queda contraste que gastar. *Un fondo no se escoge solo por cómo se ve
  quieto: también por lo que tiene que dejar ver encima.*

  Así que la receta es la de `.accion` de la ficha de contacto —vidrio de la
  casa, borde con el filo de luz arriba, letra `--snow`—, que es donde el KITT
  lleva viviendo desde el 2026-08-07.

  ⚠️ SIN `backdrop-filter`, Y ESA LÍNEA FALTA A PROPÓSITO. `.accion` lo lleva
  porque cuelga del cuarto; aquí el padre —`.priv-caja`— YA es vidrio, y §7c es
  ley: *un vidrio dentro de otro se queda sin suelo*. Copiarlo entero habría
  puesto un desenfoque que no desenfoca nada y cuesta en cada fotograma. Es la
  trampa que costó una tarde el 2026-08-12c, evitada antes de morder.

  ⚠️ Y SE MUEVE EL COLOR, NO LA FORMA. El radio de píldora, los 42 px de alto y
  la letra de 13 son los que él aprobó ayer y no los tocó nadie: lo que rompía
  el KITT era el fondo. *Una corrección señala una pieza, no el componente
  entero.*

  ⚠️ El que descarta se sigue leyendo después, y ahora por PESO y no por tinta
  (`--texto-2` sobre este vidrio queda corto): 500 el que actúa, 400 el que
  descarta. La tinta blanca la necesitan los dos para que el anillo no gane.
*/
#soporte .priv-cerrar {
  margin-top: 10px;
  background: var(--panel);
  border-color: var(--borde);
  border-top-color: var(--filo);
  color: var(--snow);
}
#soporte .sop-si { font-weight: 500; }
#soporte .sop-no { font-weight: 400; }

/*
  LAS CUATRO ETIQUETAS. Píldoras (radio 999, §6) porque son etiquetas y no
  acciones — la forma dice qué clase de cosa es antes de leer la palabra.

  🔴 DOS POR DOS, Y NO UNA FILA QUE SE PARTE SOLA. Empezó con `flex-wrap` y
  MEDIDO salía 3+1: las cuatro suman 324 px de contenido en 286 disponibles,
  así que PQR bajaba sola a una segunda fila, descolgada. Y lo peor no era eso
  — era que **el reparto cambia con el idioma**: "Solicitação" y "Felicitação"
  son más largas que las castellanas, así que en portugués habría salido 2+2 y
  en inglés ("Support · Request · Kudos · PQR") las cuatro en una. Tres
  aspectos distintos de la misma pantalla, ninguno escogido por nadie.
  Con la rejilla son SIEMPRE dos por dos, digan lo que digan las palabras.
  *Una fila que se acomoda sola acomoda también lo que nadie miró.*

  ⚠️ 34 px de alto y no 44, y es la excepción con motivo: 44 es el blanco del
  PULGAR para lo que ACCIONA, y estas no accionan nada — marcan. Van separadas
  8 px, así que ningún halo pisa al vecino (el defecto del 2026-08-12b con los
  iconos del campo de Nix). Y el que sí acciona, el Enviar, mide sus 42.
*/
.sop-etiquetas {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  /* 18, era 14: se mudaron encima del campo (fundador, 2026-08-13b) y con el
     sitio heredaron el margen del sitio — este 18 es el que separaba de la
     bajada. Los dos márgenes se intercambiaron, así que el cuadro mide igual. */
  margin-top: 18px;
}

.sop-eti {
  min-height: 34px;
  padding: 7px 14px;
  /* La palabra al centro: en una rejilla la píldora es más ancha que su texto,
     y alineada a la izquierda se leería como una fila de lista, no como algo
     que se toca. */
  text-align: center;
  background: var(--toque);
  border: 1px solid var(--linea);
  border-radius: var(--r-pildora);
  color: var(--texto-2);
  font-family: inherit;
  font-size: var(--tam-terciario);
  font-weight: 500;
  letter-spacing: .2px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color .2s ease, border-color .2s ease, background-color .2s ease;
}

/*
  PUESTA. Se distingue por TINTA Y BORDE, no por color de marca: §4 tiene el
  cian reservado para Nix, y gastarlo aquí lo dejaría sin decir nada el día que
  Nix hable de verdad. Es la misma decisión que en los dos botones de abajo.

  🔴 Y DESDE EL 2026-08-13b SE LLENA DE BLANCO, por orden del fundador: *"cuando
  se seleccione una etiqueta debe quedar el botón blanco (que muestre
  activado)"*. Es la MISMA pareja invertida de los dos botones y de
  `.panel-accion` —`--texto` de fondo, `--fondo` de tinta—, así que la casa
  tiene un solo "encendido" y no dos parecidos.
  ⚠️ Antes se llenaba apenas un 16% y el cambio se leía de reojo como un
  sombreado; lleno no hay duda de cuál está puesta, que es lo que él pidió.
  ⚠️ El borde va transparente y NO se quita: la píldora tiene que seguir
  midiendo lo mismo puesta que sin poner, o al tocarla la rejilla salta.
*/
.sop-eti[aria-pressed="true"] {
  color: var(--fondo);
  border-color: transparent;
  background: var(--texto);
}

/* VER MAS. Su flecha gira al abrirse — es el mismo gesto de toda la casa:
   la forma dice el estado, no hace falta cambiar la palabra. */
.priv-mas {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 14px 0 0;
  padding: 6px 0;
  background: none;
  border: 0;
  color: var(--nix-texto);
  font-family: inherit;
  /* 13, era 12,5 (§5, la Ley · 2026-08-11). */
  font-size: var(--tam-terciario);
  letter-spacing: .3px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.priv-mas svg {
  width: 14px;
  height: 14px;
  transition: transform .22s cubic-bezier(.16,.9,.3,1);
}
.priv-mas[aria-expanded="true"] svg { transform: rotate(180deg); }

.priv-todo { margin-top: 4px; }
.priv-todo h3 {
  margin: 16px 0 5px;
  /* 17, era 12 (§5, la Ley). Son los titulos de la politica; con el cuerpo
     en 15 hacia falta el escalon de arriba para que se lean como titulos. */
  font-size: var(--tam-principal);
  font-weight: 600;
  letter-spacing: .3px;
  color: var(--texto);
}
.priv-todo p {
  margin: 0;
  /* 15, era 12,5 (§5, la Ley). Es la prosa de la politica de tratamiento:
     un documento legal en 12,5 no lo lee nadie de mas de cuarenta. */
  font-size: var(--tam-secundario);
  line-height: 1.55;
  color: var(--texto-2);
}
.priv-todo a { color: var(--nix-texto); }
.priv-ley {
  margin-top: 16px !important;
  padding-top: 12px;
  border-top: 1px solid var(--linea);
  /* 13, era 11,5 (§5, la Ley). El !important se queda: lo puso el diseño
     del dialogo, no la escala. */
  font-size: var(--tam-terciario) !important;
  color: var(--texto-3) !important;
}

/* Cerrar. Es la unica accion de la ventana, asi que lleva el peso de un
   boton de verdad — el mismo vidrio del boton de tarjetas. */
.priv-cerrar {
  width: 100%;
  margin-top: 20px;
  background: var(--toque);
  border: 1px solid var(--linea);
  border-radius: var(--r-pildora);
  padding: 12px;
  color: var(--texto);
  font-family: inherit;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .4px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* ============================================================
   PANELES — la vitrina del dueño (carrusel)
   ============================================================
   El patron de menus de la casa desde el 2026-08-05: la tarjeta del frente
   entera, las vecinas asomadas, encaje con click. Movimiento estilo Apple:
   el scroll nativo pone la fisica (inercia y rebote del sistema, que ningun
   JS imita bien) y el JS solo pinta escala, giro y luz segun la distancia
   al centro. Sobre la camara corre barato: transform y opacity, nada mas —
   y el giro 3D (la atmosfera cilindrica del 2026-08-06) tambien es
   transform, asi que la ley no se movio.
*/
/*
  ⚠️ ESCONDER LE GANA A TODO, Y ESTA LINEA NO ES OPCIONAL. El `hidden` del
  HTML vale `display:none`, pero lo pone el NAVEGADOR y cualquier regla
  nuestra le gana — incluido el `display:flex` de aqui abajo. Sin esto la
  vitrina VACIA se queda fija sobre la Caja desde que carga la pagina, y lo
  unico que se ve es su cabecera flotando sobre un fondo borroso.
  ASI SALIO A PRODUCCION el 2026-08-05 y lo cazo el fundador con una captura.
  ES EL MISMO DEFECTO DEL block-13f-2c-fix, dos meses despues y en otra
  pantalla: alli `.oculto` perdia contra `#dentro.vista` y la ficha se pintaba
  debajo de una lista que nunca se iba.
  COMO SE ME PASO, que importa mas que el arreglo: probe que ABRIERA y nunca
  probe que estuviera CERRADO — lei el atributo, no los pixeles. Desde aqui,
  toda pantalla que nace escondida se mide en su estado de reposo primero.
*/
.paneles[hidden] { display: none !important; }

.paneles {
  /*
    ⚠️⚠️ EL TAMAÑO DE LA TARJETA VIVE AQUI Y EN NINGUN OTRO SITIO, y esto
    nacio de un defecto: estaba escrito a mano en DIEZ reglas —el haz, la
    linea de luz de la base, el reflejo, el vuelo de Nix, el recorte del
    tambor—, asi que cambiarlo en la tarjeta dejaba las otras nueve
    apuntando al tamaño viejo. Se cazo midiendo: la tarjeta decia 245 y
    seguia saliendo 220 porque la regla de verdad estaba mas abajo.
    245 x 385 son los numeros de la maqueta del fundador. El `min` es el
    seguro para un telefono angosto; a 360 px de pantalla ya da los 245.
    Si cambia la proporcion, se cambia AQUI y todo lo demas sigue solo.
  */
  /*
     ⚠️ TRES TOPES, Y EL TERCERO NACIO MIDIENDO. El ancho lo mandan el
     numero de la maqueta (245) y el de la pantalla (68vw), pero faltaba el
     ALTO: con 245 la tarjeta mide 385 y en una pantalla de 620 no cabe con
     el rotulo, los dos HUD, Guardar y el pie — pisaba el HUD de abajo, y
     callada. El tercer tope reserva ~250 px para todo eso y le da el resto
     a la tarjeta, dividido por su proporcion.
     En un telefono normal (800+ de alto) el que manda sigue siendo el 245
     de la maqueta: los otros dos solo aparecen cuando la pantalla obliga.
   */
  --panel-ancho: min(245px, 68vw, calc((100vh - 250px) / 1.5714));
  /*
    EL CUERPO SUBE 25 px (fundador, 2026-08-07). El "cuerpo" es todo lo que
    va centrado: la pildora, el tambor y Guardar contacto.
    ⚠️ SE SUBE RESERVANDO SITIO ABAJO, NO EMPUJANDO ARRIBA. Esta seccion
    reparte con `justify-content: center`, asi que 50 px de relleno abajo
    suben el centro 25 — la mitad, porque el centrado se los reparte entre
    los dos lados. Un `transform` sobre esta capa habria sido lo obvio y lo
    peligroso: es la ABUELA de la escena 3D, y tocarle el transform es de la
    familia de cosas que aplanan el tambor sin dar error.
  */
  padding-bottom: 50px;
  --panel-alto: calc(var(--panel-ancho) * 1.5714);   /* 385 / 245 */
  position: fixed;
  inset: 0;
  z-index: 30;              /* sobre la Caja (1), bajo el vuelo de Nix (50) */
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: rgba(3, 5, 9, .38);   /* aparta la Caja sin apagar la camara */
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}

/*
  MODO VITRINA — el fondo se calla (fundador, 2026-08-06: "siento que hay
  ruido"). El velo de arriba difuminaba la Caja pero la dejaba VIVA detras
  del vidrio: dos pantallas peleando. Ahora, con los Paneles abiertos, la
  pantalla de la Caja se apaga y quedan solo la camara con su velo (el AR
  es el terreno del vidrio, no el ruido), el rincon de Nix y el pie.

  COMO: .stage sube por encima del cuarto (40 > 30) pero deja pasar los
  toques (pointer-events: none); dentro, todo hijo de #caja se apaga salvo
  los tres que el fundador pidio conservar — Nix (su esquina es suya en
  toda la casa), el pie con sus botones, y la firma. Esos tres recuperan
  el toque. El carrusel se toca porque .stage no captura nada.

  ⚠️ LA TRANSICION VIVE SOLO EN ESTE MODO, a proposito: la ida se funde
  suave y la vuelta es instantanea, igual que el resto del cierre. Ponerla
  permanente sobre los hijos de #caja tocaria el show del arranque.
  ⚠️ La barra del chat de Nix NO se apaga: se monta en el body, no en
  #caja (nix-chat.js:743) — el dueño puede hablarle a Nix sobre la vitrina.
*/
body.en-paneles .stage { z-index: 40; pointer-events: none; }
body.en-paneles #caja > * {
  opacity: 0;
  transition: opacity .25s ease;
  pointer-events: none;
}
body.en-paneles #caja > .nix-btn-container,
body.en-paneles #caja > .foot,
body.en-paneles #caja > .foot-2 {
  opacity: 1;
  pointer-events: auto;
}
/*
  LA CABECERA ES UNA SOLA FILA (fundador, 2026-08-07): Volver a la
  izquierda · PANELES centrada · Nix arriba a la derecha. Su maqueta la
  tiene asi y la vitrina la tenia en columna —el rotulo arriba y Volver
  debajo—, que es lo que el vio distinto.

  ⚠️ EL ROTULO SE CENTRA CONTRA LA PANTALLA, NO CONTRA SU FILA, y por eso va
  absoluto. Nix no vive aqui: vive en la Caja (`.nix-btn-container`) y solo
  SOBREVIVE en modo vitrina, asi que esta fila no lo contiene y un
  `space-between` de tres dejaria el rotulo descentrado por el ancho del
  boton de Nix. Centrado contra la pantalla, los tres quedan como en la
  maqueta sin que uno tenga que saber donde vive el otro.
*/
.paneles-top {
  position: absolute;
  top: 0; left: 0; right: 0;
  display: flex;
  align-items: center;
  padding: calc(14px + env(safe-area-inset-top)) 16px 0;
  /* El contenedor no debe comerse los toques del tambor: solo el boton los
     recibe. Sin esto, una franja invisible de ancho completo se quedaria
     con el dedo en la parte de arriba de la vitrina. */
  pointer-events: none;
  /* Alto reservado para que el rotulo absoluto no se salga de la fila. */
  min-height: 34px;
}

/*
  GUARDAR CONTACTO EN LA VITRINA (fundador, 2026-08-06: *"un boton debajo
  de la palabra paneles"*). En modo vitrina la Caja se apaga entera, asi
  que la accion que este producto existe para provocar —que el visitante se
  lleve el contacto— quedaba detras de un "Volver".
  Pildora de vidrio, no boton macizo: es una accion disponible, no la
  protagonista. La protagonista es el tambor.
*/
.paneles-guardar {
  /* ABAJO DEL TAMBOR, CENTRADO — el sitio que dejo la flecha (fundador,
     2026-08-06). Es la zona del pulgar, y aqui va la accion que este
     producto existe para provocar.
     ⚠️ En el flujo y sin `bottom` a mano: la leccion de la flecha, que se
     montaba encima de TURBO porque el pie no tiene altura fija. */
  align-self: center;
  margin-top: 22px;
  display: inline-flex;
  align-items: center;
  /* 🔴 Aqui iba `gap: 8px`. Separaba el icono del texto y con una sola pieza
     adentro no separa nada: se fue con el icono (misma lapida). */
  /* 🔴 Aqui iban `position: relative` y `overflow: hidden`, puestos para
     recortar el barrido que me invente. Se van con el: sin banda que
     recortar no recortan nada, y un `overflow` de mas es justo la clase de
     regla que un dia aplana el 3D de algo que todavia no existe. */
  /* CRISTAL VOLUMETRICO — la especificacion la trajo el fundador el
     2026-08-07 con su maqueta y su imagen. Sus numeros van PORTADOS, no
     reteclados ni "interpretados": 8/20 de relleno, 14 px de letra, blur
     24, borde al 14%, y las tres sombras exactas. */
  padding: 8px 20px;
  border-radius: var(--r-pildora, 999px);
  border: 1px solid rgba(255, 255, 255, .14);
  background: linear-gradient(135deg,
    rgba(255, 255, 255, .12) 0%,
    rgba(255, 255, 255, .03) 100%);
  /*
    ⚠️ SU BLUR ES 24 Y SE RESPETA; EL `saturate()` LO PONE LA CASA.
    §2 es ley: *"`saturate()` es lo que hace que sea vidrio y no papel"*, y
    cuesta lo mismo que el desenfoque solo. Su maqueta corre sobre un fondo
    plano, donde no se nota; esta pildora corre sobre la CAMARA VIVA, que es
    justo donde ese color de atras tiene algo que revivir.
  */
  backdrop-filter: blur(24px) saturate(var(--sat));
  -webkit-backdrop-filter: blur(24px) saturate(var(--sat));
  /*
    LAS TRES SOMBRAS SON EL VOLUMEN, y cada una hace una cosa distinta:
    el reflejo especular de arriba dice que la pieza tiene canto; la
    profundidad de abajo la hunde; la proyectada la despega del fondo.
    Quitar una deja una pastilla plana con sombra.
  */
  box-shadow:
    inset 0 1px 1px 0 rgba(255, 255, 255, .45),
    inset 0 -2px 4px 0 rgba(0, 0, 0, .5),
    0 12px 28px rgba(0, 0, 0, .6);
  color: var(--texto);
  font-family: inherit;
  /* 15 px = el paso de BOTON de §5. Venia en 14 (`text-sm` de su maqueta),
     que no esta en la escala — el 14 y el 12 de esta pantalla salieron de
     clases de Tailwind copiadas del mockup, no del sistema. */
  font-size: 15px;          /* boton · §5 */
  font-weight: 500;         /* botones · §5 */
  letter-spacing: .35px;                 /* `tracking-wide` */
  cursor: pointer;
  transition: background .3s ease, border-color .3s ease, transform .3s ease;
}
/*
  LA JERARQUIA DE LAS DOS PALABRAS: la accion en negrita, el objeto en fina.
  Las palabras NO se escriben aqui ni en el CSS — se parten en `app.js` por
  el primer espacio, porque la Caja habla tres idiomas y los tres son verbo
  + objeto ("Guardar contacto", "Save contact", "Salvar contato").
*/
.paneles-guardar .guardar-fuerte { font-weight: 700; color: var(--texto); }
.paneles-guardar .guardar-fina {
  margin-left: 6px;                      /* `ml-1.5` */
  font-weight: 300;
  /* `text-slate-300` de su maqueta. Se anota como lo que es: un color de
     fuera del sistema, igual que el ambar del 4.9★ — va porque es su
     diseño. En Cristal Perlado no puede ir: ahi manda la ficha (abajo). */
  color: #cbd5e1;
}
/* Un dedo no hace hover (§6), asi que esto es solo para el escritorio.
   Lo que SI siente el dedo es la presion, y esa va abajo. */
@media (hover: hover) {
  .paneles-guardar:hover {
    background: linear-gradient(135deg,
      rgba(255, 255, 255, .18) 0%,
      rgba(255, 255, 255, .06) 100%);
    border-color: rgba(255, 255, 255, .28);
  }
}
/* 🔴 Aqui vivia `.paneles-guardar svg`, la pinta del icono cian. Se fue con
   el icono el 2026-08-07 (`ArmiñoD1NA` nombrando su blanco); su regla queda
   en la misma lapida, `backups/2026-08-07/borrado-icono-guardar.md`. */
/*
  ⚠️ MEDIA VUELTA, Y SOLO EN ESTE BOTON (fundador, 2026-08-07). El numero lo
  bajo el mismo dia, probandolo con el dedo, en tres pasadas: **1,5 → 1 →
  0,5** (*"en las pruebas se siente mucho"*, y despues *"bajemoslo a media
  vuelta"*). **Se midio con el dedo, que es el unico medidor que sirve para
  esto** — ninguna de las tres se podia decidir leyendo codigo.
  Media vuelta son 1,2 s: el anillo sale por un lado, cruza y entrega el
  turno sin llegar a volver por donde empezo.

  §6 dice DOS vueltas y la cabina se queda en dos: alli el KITT es un momento
  que se basta solo, y quien lo mira ya esta adentro. Aqui dejo de estar
  solo — es el PRIMER TIEMPO de una secuencia de tres y tiene que acabarse
  para que entre el segundo, con un visitante de pie esperando su contacto.
  *Un efecto que en un sitio dura bien, en otro estorba: lo que cambia no es
  el efecto, es cuanto puede esperar quien lo ve.*
  Con esto el toque baja de 4,5 s a ~2,1 s.

  ⚠️ Y EL REMIENDO SE CAYO SOLO. Mientras la media vuelta era solo de este
  boton, aqui habia una regla que sobreescribia las vueltas. El 2026-08-07 el
  fundador cerro el movimiento y pidio el MISMO en los cuatro botones de la
  ficha, asi que la media vuelta subio a `tokens.css` y esta linea se quedo
  repitiendo lo que la receta ya dice.
  **Una excepcion que se vuelve la regla deja de ser excepcion, y quedarse
  seria la primera de las dos copias.**
*/

/* EL EFECTO DE PRESION (`active:scale-95` de su maqueta). Es `transform`, o
   sea de lo barato, y va en ESTE boton y no en una tarjeta del tambor: un
   `scale` sobre una tarjeta la arrancaria del cilindro (§1b-3). Medido
   despues de ponerlo: el vidrio de la pildora sigue vivo — un `transform`
   sobre el MISMO elemento que lleva `backdrop-filter` no forma Backdrop
   Root; los que lo forman son los ancestros. */
.paneles-guardar:active { transform: scale(.95); }

/*
  🔴 AQUI VIVIO UN BARRIDO CIAN QUE ME INVENTE, Y LA LECCION VALE MAS QUE EL
  CODIGO QUE SE FUE (2026-08-07). El fundador pidio *"el efecto KITT"* y yo
  escribi uno nuevo —banda, keyframes y clase— en vez de buscar el que la
  casa ya tiene. Su correccion, textual: *"si te nombro un efecto o algo con
  nombre propio es porque EXISTE, no inventes cosas, perdemos tiempo"*.

  **EL EFECTO ES `access-granted-card`** (arriba en esta misma hoja): borde
  verde, `--destello-verde` y `scale(1.02)`, la que reciben los cuatro CTA
  de la Caja al activarse. La pone `flyNixToElement` cuando Nix ATERRIZA, y
  este boton ya la llamaba desde el primer dia — o sea que el efecto ya
  estaba corriendo aqui y mi barrido, que salia antes y duraba mas, se lo
  estaba tapando.

  *Un nombre propio es un puntero, no una descripcion.* Es la hermana de la
  lampara del mismo dia: alli construi lo que el creia que ya existia; aqui
  construi lo que de verdad existia.
*/

/*
  ⚠️⚠️ EL CRISTAL VOLUMETRICO ES DE OBSIDIANA, Y EN PERLADO SE DA VUELTA.
  Su especificacion esta escrita en blancos —fondo blanco al 12%, texto
  blanco, borde blanco— y eso sobre el modo claro es un fantasma: blanco
  sobre casi blanco no tiene donde apoyarse, y el texto desaparece. Es
  exactamente el caso de §1 (`--panel-solido` valiendo `#FFFFFF` en Perlado
  y poniendo las tarjetas del fondo mas brillantes que la del frente) y de
  `--tope-rgb` (*"alumbrar no existe en el modo claro, y es fisica"*).

  LO QUE SE CONSERVA ES LA ESTRUCTURA, NO LOS NUMEROS: canto de luz arriba,
  hundido abajo, sombra proyectada que la despega. Eso es lo que hace que la
  pieza se lea volumetrica, y funciona en los dos terrenos. Lo que cambia es
  de que color es cada capa — y en el claro la que trabaja es la SOMBRA,
  nunca la opacidad (la cura que ya enseño §1 dos veces).
*/
[data-modo="perlado"] .paneles-guardar {
  border: 1px solid var(--linea);
  border-top-color: var(--filo);
  background: linear-gradient(135deg,
    rgba(255, 255, 255, .55) 0%,
    rgba(255, 255, 255, .28) 100%);
  box-shadow:
    inset 0 1px 1px 0 rgba(255, 255, 255, .9),
    inset 0 -2px 4px 0 rgba(9, 10, 15, .10),
    0 10px 24px rgba(9, 10, 15, .18);
  color: var(--texto);
}
[data-modo="perlado"] .paneles-guardar .guardar-fina { color: var(--texto-2); }
@media (hover: hover) {
  [data-modo="perlado"] .paneles-guardar:hover {
    background: linear-gradient(135deg,
      rgba(255, 255, 255, .72) 0%,
      rgba(255, 255, 255, .4) 100%);
    border-color: var(--filo);
  }
}
/*
  LA FLECHA ARRIBA, ENFRENTE DE NIX (fundador, 2026-08-06 — segunda vuelta
  del mismo dia; por la mañana la bajo a la zona del pulgar).
  **El cambio no contradice aquella razon: la reemplaza por una mejor.** El
  sitio del pulgar lo necesita "Guardar contacto", que es la accion que da
  plata. Una salida se busca cuando uno quiere salir; una accion de venta
  tiene que caer donde el dedo ya esta.

  ⚠️ SIGUE SIN LLEVAR UN `bottom` A MANO, y esa leccion no caduca: el pie de
  la Caja no tiene altura fija —la decide su contenido—, asi que cualquier
  numero elegido a mano choca con TURBO en algun telefono. Aqui va dentro
  de la cabecera, que es absoluta y se mide sola.
*/
.paneles-volver {
  pointer-events: auto;   /* la cabecera no recibe toques; este boton si */
  align-self: flex-start;
  /*
    ⚠️ OTROS 3 PX, Y ESTOS YA NO CABEN EN EL RELLENO (fundador, 2026-08-07,
    quinta vuelta). Al de abajo le quedaban 2,5 px y el aviso estaba escrito
    desde la vuelta anterior: sumarle 3 arriba lo habria dejado en -0,5, que
    no existe — el navegador lo recorta a 0 y **el ajuste saldria de 2,5 px
    en vez de 3**, sin dar ningun error.
    Asi que a partir de aqui baja la CAJA ENTERA con un margen, no lo de
    adentro con el relleno. Lo que se pierde: el borde del boton tambien
    baja. Lo que NO se pierde, que era el motivo de usar relleno: el area
    tocable sigue midiendo 44 px, porque la caja se mueve sin encogerse.
    El recorrido completo del desnivel: 3+2+2+4+0,5+1 en relleno, +3 aqui.
  */
  margin-top: 3px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 0;
  color: var(--ash);
  font-family: inherit;
  font-size: 13px;          /* terciario · §5 (era 12, fuera de la escala) */
  font-weight: 500;         /* botones · §5 */
  /* Simetrico desde que la cabecera pasa a una fila (2026-08-07), y con
     2 px de desnivel a peticion suya ese mismo dia: la flecha y la palabra
     bajan juntas porque son un solo boton. El area tocable no se encoge —
     sigue en 44 px, que es el minimo que se toca comodo.
     ⚠️ OTROS 4 PX ABAJO (fundador, 2026-08-07). Se le SUMAN al relleno de
     arriba y se le RESTAN al de abajo —12/8 pasa a 16/4—, asi que los dos
     siguen sumando 20 y el boton NO CRECE NI SE MUEVE: lo que baja es lo
     que se ve adentro. Bajarlo con `margin` o con `top` habria arrastrado
     el borde del boton hacia el tambor. Es la misma cura de los 2 px del
     3+2+2: el area tocable sigue en 44 px.
     ⚠️ Y MEDIO PIXEL MAS (fundador, 2026-08-07, tercera vuelta del mismo
     dia), Y OTRO PIXEL DESPUES (cuarta): 16/4 → 16,5/3,5 → 17,5/2,5. El
     recorrido entero del desnivel es 3+2+2+4+0,5+1.
     ⚠️ EL DE ABAJO SE ESTA ACABANDO: quedan 2,5 px. El siguiente ajuste ya
     no cabe en el reparto y hay que subir el alto del boton o mover la
     cabecera entera — se dice ahora para que ese dia no se descubra
     restando y dejando el relleno en negativo. */
  padding: 17.5px 9px 2.5px 0;
  min-height: 44px;
  border-radius: var(--r-chico);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.paneles-volver svg { width: 14px; height: 14px; }

/*
  EL ITEM "Volver" DEL MENU DE NIX solo existe con la vitrina abierta — es
  la segunda de las tres salidas (la doctrina de la ficha del contacto,
  traida a la Caja publica el 2026-08-06). Fuera de la vitrina no aparece:
  un "Volver" sin nada de que volver es un boton que miente.
*/
.nix-item-volver { display: none; }
/* El Modo seguro: solo en el celular del dueño (app.js le quita el `hidden`). */
.nix-item[hidden] { display: none; }
body.en-paneles .nix-item-volver { display: flex; }
.paneles-titulo {
  /* Clavado al centro de la PANTALLA. `translateX` y no `margin: auto`
     porque su vecino de la derecha (Nix) esta en otra capa y no cuenta
     para este flex. */
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  /* 15,84 = OTRO 20% sobre los 13,2 (fundador, 2026-08-07, segunda vez ese
     dia). El recorrido entero: 11 → 13,2 → 15,84, o sea un 44% sobre el
     original. Se anota la cadena y no solo el numero, porque un "20% mas"
     pedido sobre una pantalla se mide contra LO QUE SE ESTA VIENDO, no
     contra el valor de fabrica — y sin la cadena escrita, el tercero se
     calcularia otra vez desde 11 y saldria mas chico que el actual.
     ⚠️ El `letter-spacing` NO se toca: creceria la palabra por dentro y lo
     que se pidio es la letra.

     🔴 2026-08-09 · BAJA A 15, QUE ES EL PASO DE LA ESCALA. Orden del
     fundador: *"si o si nos regimos al documento"*, y 15,84 no existe en
     §5 (13 · 15 · 17 · 20 · 24 · 32). Se deja escrita la cadena entera de
     arriba a proposito: **este numero lo subio EL, dos veces el mismo dia**,
     y bajarlo sin dejar rastro seria borrarle una decision. Son 0,84 px —
     por debajo de lo que un ojo distingue— y contra el original de 11 sigue
     siendo un 36% mas grande, que era lo que buscaba.
     Si lo quiere de vuelta arriba, el paso siguiente de la escala es 17. */
  font-size: 15px;          /* secundario · §5 */
  font-weight: 500;         /* etiquetas · §5 */
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--ash-dim);
  white-space: nowrap;
}

/* ================================================================
   EL TAMBOR — dos capas, medidas y no supuestas (2026-08-06)

   Pedido del fundador: *"que corran de atras a delante, como un mostrador
   de lentes de sol antiguo, como el tambor de un revolver"*.

   ⚠️ POR QUE DOS CAPAS Y NO UNA: un contenedor con `overflow` APLANA el 3D
   de sus hijos. Comprobado por geometria — dentro de un scroller, un objeto
   a 300 px de profundidad se dibuja con el MISMO ancho que uno al frente;
   fuera, se dibuja al 67%. Y `getComputedStyle` sigue afirmando
   "preserve-3d": MIENTE, igual que miente con el transform de un SVG.
   Consecuencia dura: el que scrollea no puede ser el que dibuja en
   profundidad. Uno recibe el dedo, el otro pinta.
   ================================================================ */
.paneles-tambor {
  position: relative;
  /*
    ⚠️ ALTO FIJO, Y ESTE NUMERO SE DERIVA DE LA TARJETA. La escena es
    absoluta y no puede medirse sola, asi que el sitio hay que RESERVARLO.
    Los 78vw de antes eran los 4/3 viejos, y al alargar la tarjeta el
    2026-08-07 se quedaron cortos: **medido, la tarjeta terminaba en 454 y
    el HUD de abajo empezaba en 449 — cinco pixeles de pisada**, y nada
    daba error. Hoy sale de `--panel-alto` y no puede volver a pasar.
    Es la misma leccion del pie del block-PAN18: cuando dos piezas viven en
    capas distintas, se RESERVA el sitio, no se ajusta el margen a ojo.
    Si vuelve a cambiar la proporcion de la tarjeta, este numero cambia con
    ella o la pisada vuelve callada.
  */
  /* Se DERIVA de la tarjeta, no se escribe: su alto mas un poco de aire
     para que la del frente no roce los bordes. Antes era un numero a mano
     y por eso al alargar la tarjeta empezo a pisar el HUD de abajo en
     silencio (5 px, medidos).
     ⚠️ Y `flex: none`, que era la otra mitad del defecto: el tambor es
     hijo de un flex en columna, asi que se ENCOGIA por debajo de su propio
     alto —342 en vez de 393— y la tarjeta se salia por abajo. Un alto
     declarado no vale nada si el padre puede apretarlo. */
  flex: none;
  height: calc(var(--panel-alto) + 8px);
}

/*
  LA ESCENA: solo dibuja.

  ⚠️⚠️ AQUI NO VA `transform-style: preserve-3d`, Y NO ES UN OLVIDO.
  Un contexto 3D compartido con `backdrop-filter` adentro ESTA ROTO EN
  CHROMIUM (bug 323735424, abierto desde feb-2024): el desenfoque se aplica
  pero el fondo SIN desenfocar se transparenta encima, y sale una imagen
  doble y sucia. Firefox directamente no aplica el filtro. Solo Safari lo
  arreglo. O sea que el navegador donde el efecto cuesta mas caro es ademas
  el unico donde se ve MAL — y es Chrome de Android, que es el telefono del
  cliente. La especificacion no define este cruce, asi que no hay a quien
  reclamarle ni fecha de arreglo.
  LA CURA NO SACRIFICA EL EFECTO: la vuelta del cilindro —donde cae cada
  panel y de que tamaño se ve— la calcula el JS y la entrega ya resuelta en
  `translateX` y `scale`. El `perspective()` individual solo se encarga del
  escorzo del giro. Mismo mostrador de lentes, sobre terreno definido.
*/
.paneles-escena {
  position: absolute;
  inset: 0;
  pointer-events: none;   /* el gesto es del riel, que va encima */
}

/*
  ================================================================
  EL HALO — la lampara detras del panel del frente (2026-08-06)
  ================================================================
  Adaptado de una maqueta que el fundador trajo (*"tiene ese toque que
  necesitamos"*). Lo que hacia viva esa maqueta no era el neon: era que el
  del frente parecia ENCENDIDO y los de al lado apagados. Eso si se puede
  traer entero.

  ⚠️ SU RECETA ERA UN `blur(130px)`, Y AQUI ES UN DEGRADADO RADIAL. Se ve
  igual y cuesta una decima parte: un desenfoque de ese radio sobre la
  camara viva es justo lo que §5 prohibe, y encima habria que recalcularlo
  contra un video que cambia 30 veces por segundo. Un degradado se pinta una
  vez y no vuelve a costar nada. **Cuando lo unico que se quiere es una
  mancha de luz suave, el desenfoque es la forma cara de dibujarla.**

  ⚠️ Y NO LLEVA UN COLOR POR CATEGORIA (su maqueta daba verde a WhatsApp,
  azul a LinkedIn...). En esta casa el verde es ESTADO —"salio bien", 250 ms
  y se va (§4)— y el cian es de Nix: repartirlos por categoria deja al verde
  sin significado en toda la Caja. La luz es una sola, la de la casa, y por
  eso usa `--nix-halo-rgb`, que ya trae su valor en cada modo.

  VA EN LA ESCENA Y NO EN LA TARJETA, por dos razones: es UNA sola capa para
  todo el tambor en vez de una por panel, y como el del frente siempre esta
  en el centro, el halo siempre le queda detras sin que nadie lo mueva.
  Ademas cae DETRAS del vidrio, asi que el propio panel lo desenfoca junto
  con la camara — que es lo que hace una lampara real detras de un cristal.
*/
/*
  🔴 AQUI VIVIA EL HAZ DE NIX — el abanico de luz que nacia en el CENTRO del
  panel (se mudo ahi desde la base el 2026-08-06: *"se siente huerfano
  saliendo de la base inferior"*) y caia detras del vidrio para que la
  propia pieza lo desenfocara, como una lampara real detras de un cristal.
  BORRADO el 2026-08-07 con la palabra del fundador nombrando su blanco.
  Con el se fue su `halo-tiron`, que no animaba otra cosa.
  §6 sigue siendo cierto —una proyeccion se lee como proyeccion cuando se
  sabe de donde sale—; lo que cambio es que esta vitrina ya no quiere
  leerse como proyeccion. Lapida en backups/2026-08-07/.
*/

/*
  ================================================================
  EL HAZ — de donde SALE la proyeccion (2026-08-06)
  ================================================================
  Fundador: *"¿como podemos hacer que el panel parezca proyeccion o
  revelacion tipo Jarvis?"*.

  LA RESPUESTA NO ES UN EFECTO, ES UNA HISTORIA: una proyeccion se lee como
  proyeccion cuando se sabe DE DONDE SALE. En el cine nunca hay un holograma
  huerfano — siempre hay un emisor y un haz. El tambor estaba ahi, sin
  origen, y por eso se leia como una tarjeta pegada por muy bien iluminada
  que estuviera.
  **Y el emisor de esta casa ya existe y tiene nombre: Nix.** Por eso el haz
  no lleva un color decorativo: lleva `--nix-halo-rgb`, la misma luz con la
  que Nix vuela y habla. Con eso, cuatro efectos sueltos pasan a ser una
  sola idea — *la vitrina es algo que Nix esta proyectando*.

  ES UN TRAPECIO: angosto abajo (el emisor) y abierto arriba, con la luz
  fuerte cerca de la base y disipandose al subir, que es como se comporta un
  haz de verdad. Y va DETRAS de las tarjetas, en la escena, asi que el
  vidrio del frente lo desenfoca junto con la camara.

  ⚠️ `clip-path` AQUI ES SEGURO Y UN PISO MAS ARRIBA NO. Forma Backdrop Root
  para SUS descendientes, y este pseudo no tiene ninguno: las tarjetas son
  sus HERMANAS, no sus hijas. Puesto en la escena, apagaria el vidrio de las
  ocho sin dar un solo error.
  ⚠️ ES EL UNICO EFECTO PERMANENTE DE LOS CUATRO, asi que nace TIMIDO a
  proposito: un punto de mas y esto deja de ser Jarvis y es una discoteca.
  Esa frontera la decide el ojo del fundador, no un numero mio.
*/
/*
  🔴🔴 ESTE ERA EL HAZ DE VERDAD, Y ME COSTO CINCO RONDAS. Borrado el
  2026-08-07 con la palabra que el fundador ya habia dado —*"ArmiñoD1NA
  para «IDBOX.LAT», el haz de Nix y los corchetes cian"*—: el blanco que
  nombro era el haz, y yo lo ejecute sobre la capa equivocada.

  ⚠️⚠️ LA LECCION, Y ES DE METODO: **la escena tenia DOS pseudos con luz
  cian.** Quite el `::before` —el halo redondo— di el haz por muerto y no
  volvi a mirar. El `::after` es el que dibuja los DOS ABANICOS OPUESTOS
  (`conic-gradient` desde -22°), o sea el huso que el veia entre los
  paneles, y siguio ahi cuatro despliegues.
  *Un elemento no se da por borrado porque su hermano lo este.*

  ⚠️ Y LO QUE ME TUVO CIEGO: llevaba cinco rondas leyendo `getComputedStyle`
  de las capas que YO sospechaba, en un navegador que no pinta fotogramas y
  donde no puedo mirar la pantalla. Lo que lo caza en un intento fue dejar
  de sospechar y BARRER la pagina entera —cada elemento y sus dos pseudos—
  preguntando cual pinta cian sobre el punto exacto de su captura.
  *Cuando no se puede ver, no se adivina: se enumera.*

  Su CSS completo, tal cual corria, en backups/2026-08-07/.
*/
/*
  🔴 AQUI VIVIA LA LINEA DE LUZ DE LA BASE — `.paneles-tambor::after`, 2 px
  de alto y cian, el suelo donde apoyaba el haz. BORRADA el 2026-08-07 con
  la palabra del fundador nombrando su blanco: *"ArmiñoD1NA para after 2px"*.

  Nacio en el block-PAN14 con el haz —*"sin ella el haz es una mancha; con
  ella la tarjeta esta parada sobre algo"*— y se quedo sin oficio ese mismo
  dia, cuando el emisor se mudo de la base al CENTRO por correccion suya.
  Desde entonces era el suelo de un haz que ya no nacia ahi. El haz entero
  salio el 2026-08-07, y esto se quedo alumbrando solo debajo de una tarjeta
  que ya no proyecta nada.

  ⚠️ NO CONFUNDIR CON EL `::before` DEL MISMO TAMBOR, que es el BARRIDO y
  sigue vivo — incluida su linea en el `prefers-reduced-motion` de mas
  abajo.
  Lo que la tarjeta esta parada sobre algo lo cuenta ahora su sombra
  (`0 22px 52px`), que es la de la maqueta. CSS completo en
  backups/2026-08-07/borrado-linea-luz-base.md.
*/

/*
  ⚠️⚠️ DOS COSAS QUE NO SE LE PUEDEN PONER A LA ESCENA, Y NINGUNA DA ERROR:

  1. `overflow` (ni `hidden` "para que no se desborde"). Un contenedor con
     overflow es "grouping property" y APLANA el 3D de sus hijos: las
     tarjetas perderian la profundidad y volverian a verse como fotos
     giradas. Es el defecto que este archivo vino a curar, y se reintroduce
     con una sola palabra. Si algo se desborda, lo recorta el cuarto.

  2. `filter`, `opacity` menor que 1, `mask`, `clip-path`, `mix-blend-mode`,
     `isolation` o un `will-change` de cualquiera de esos. Cualquiera forma
     un "Backdrop Root", y entonces el vidrio de las tarjetas desenfoca
     TRANSPARENCIA en vez de lo que hay detras. El vidrio no falla a gritos:
     simplemente deja de verse, y se pierde una tarde buscandolo.
     La tentacion tipica es un fundido de entrada con `opacity` puesto aqui.
     ✅ `transform`, `perspective` y `transform-style` NO forman Backdrop
     Root — la especificacion lo dice explicito. El 3D es seguro.
*/

/* EL RIEL: el que scrollea. El encaje lo garantiza el navegador, no un
   calculo nuestro — misma doctrina del reloj contra el rAF. Invisible a
   proposito: lo que se ve es la escena; esto es por donde corre el dedo. */
.paneles-pista {
  position: absolute;
  inset: 0;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -webkit-tap-highlight-color: transparent;
}
.paneles-pista::-webkit-scrollbar { display: none; }

/* Cada hueco es el sitio de una tarjeta en el riel, y es un BOTON de
   verdad: es lo que enfoca el teclado y lo que anuncia el lector de
   pantalla. Invisible, pero no inexistente — la escena va `aria-hidden`
   justamente porque quien manda aqui es este. */
.riel-hueco {
  flex: none;
  height: 100%;
  scroll-snap-align: center;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/*
  ⚠️ EL ANCHO ES LO QUE HACE QUE LA VECINA EXISTA (2026-08-06). Con 72vw la
  vecina asomaba **-2 px** en un celular de 375: o sea que NO SE VEIA, y por
  eso hacia falta un letrero que dijera "desliza". La cuenta, medida en el
  producto: el hueco de cada lado eran 39 px y el 3D se comia 22 por lado
  —escala, giro y perspectiva del hundimiento, TRES encogimientos que se
  multiplican—. 58vw abre el hueco a ~67 px y deja la vecina a la vista.
  ⚠️ NO SUBIR ESTE NUMERO SIN MEDIR EL ASOMO OTRA VEZ: es la unica pieza que
  hace que el carrusel se explique solo.
  ⚠️ NI BAJARLO DE ~50vw sin medir fotogramas en un telefono de gama media:
  cada tarjeta lleva su vidrio, y estrechar mete MAS vidrios a la vez sobre
  la camara. La ley de §5 no es de bytes aqui, es de fluidez.

  DESDE EL TAMBOR (2026-08-06) LA TARJETA YA NO ESTA EN UNA FILA: cuelga del
  cilindro. Vive absoluta dentro de la escena y el JS la coloca en su angulo.
  El ancho no cambio — el fundador cerro el tamaño: *"el panel como tal el
  tamaño esta bien"*.
*/
.panel-tarjeta {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--panel-ancho);
  /* 245 x 385, la proporcion de la maqueta del fundador (2026-08-07). Era
     3/4 cuando la tarjeta solo llevaba una captura; con tres piezas dentro
     —cabecera, cuadro y boton— esa forma queda cuadrada y el cuadro no
     alcanza a leerse como una pantalla. */
  aspect-ratio: 245 / 385;
  /* El JS solo escribe `transform`; el centrado va aqui para no tener que
     recalcularlo en cada fotograma. ⚠️ ESTE NUMERO ES LA MITAD DEL ALTO Y
     SE DERIVA DE LA PROPORCION: 385/245/2 = 0.7857. Si cambia una, cambia
     el otro — y si se olvida, la tarjeta deja de estar centrada en el
     tambor sin dar un solo error. */
  margin-left: calc(var(--panel-ancho) / -2);
  margin-top: calc(var(--panel-alto) / -2);
  /* Al pasar de 90 grados la tarjeta muestra su reverso: sin esto se ve el
     contenido en espejo, que delata el truco de una. */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* 14 y no 18: §6 da un radio por tamaño de cosa —"14 las tarjetas, 18 los
     paneles"— y esto es una tarjeta. Ademas `--r-grande` NO EXISTE en la
     casa: se estaba dibujando con el 18 del respaldo, o sea con un numero
     que ningun archivo declara. Una ficha inventada es una segunda verdad
     esperando a que alguien cambie el sistema y esto no se entere. */
  /* 32 px, el radio de la maqueta del fundador (`rounded-[32px]`).
     🟡 ES UN QUINTO RADIO: §6 tiene cuatro —8 lo pequeño, 14 las tarjetas,
     18 los paneles, 999 las pildoras— y este no es ninguno. Va porque es
     su diseño y porque a esta escala el 14 se leia como una ficha de
     tramite. Anotado para que §6 lo recoja o lo corrija. */
  border-radius: 32px;
  /*
    ⚠️ BLANCO AL 7%, MEDIDO DE SU MAQUETA (`bg-white/[0.07]`), y no
    `--panel`, que vale `rgba(20,23,34,.30)` — un gris oscuro. Esa era la
    diferencia grande: un tinte CLARO sobre el fondo hace que la tarjeta se
    lea como vidrio con luz dentro; un tinte oscuro la hunde y la deja
    lavada. Se vio comparando las dos a maquina, no de memoria.
    ⚠️ Y el borde es BLANCO AL 20% (`border-white/20`), no el filo cian de
    §6. Su tarjeta se sostiene sola con un contorno claro; la luz de Nix
    sigue contada por el resplandor de la esquina y por el halo de la
    medalla, que son de la misma familia y no compiten con el contenido.
  */
  background: rgba(255, 255, 255, .07);
  border: 1px solid rgba(255, 255, 255, .20);
  /* La sombra de la maqueta (`0 30px 70px rgba(0,0,0,.8)`): es lo que
     despega la tarjeta del fondo y la hace flotar sobre las vecinas. */
  box-shadow: 0 22px 52px rgba(0, 0, 0, .62);
  /*
    ⚠️⚠️ `overflow: hidden` AQUI, Y SOLO AQUI. Lo pide la respiracion: la
    proyeccion se acerca un 7% y sin recorte se saldria por los bordes.
    ES SEGURO EN ESTA TARJETA Y NO LO SERIA UN PISO MAS ARRIBA. La regla
    escrita con sangre —un contenedor con `overflow` APLANA el 3D de sus
    hijos, y `getComputedStyle` lo niega— habla de los HIJOS: aqui los
    unicos hijos son `::before` y `::after`, que no tienen 3D ninguno. El
    cilindro lo dibuja la ESCENA, que es la abuela y no se toca.
    Puesto en la escena o en el riel, esto mata el tambor entero.
    Medido despues de ponerlo: profundidad 30% y asomo 139 px — identicos
    a antes, o sea que el 3D sigue vivo.
    Y no estorba al vidrio: `backdrop-filter` mira lo que hay DETRAS del
    elemento, y el recorte solo afecta a lo que hay dentro.
  */
  overflow: hidden;
  /*
    ⚠️ 64 px Y NO LOS 14 DE LA CASA, Y ES LA EXCEPCION MAS CARA QUE TIENE
    ESTE ARCHIVO (fundador, 2026-08-07: *"la tarjeta se ve mas hacia blanco,
    mas esmerilado, mas vidrio; intenta llegar a lo mismo"*).
    Su maqueta usa `backdrop-blur-3xl`, que son 64. §2 dice *"14 px, no 64"*
    y esa decision fue SUYA — pero era sobre los seis cajones de la Caja,
    seis superficies a la vez sobre camara viva. **Aqui hay UNA SOLA**: las
    vecinas llevan `backdrop-filter: none` desde el primer dia, justo porque
    anidar desenfoques en un cilindro es el caso roto de los tres motores.
    Un vidrio caro contra seis es otra cuenta que un vidrio caro contra uno.
    🟡 Si en un Android de gama media se siente pesado, esta es la primera
    linea que baja — y se baja midiendo, no de ojo.
  */
  backdrop-filter: blur(64px) saturate(var(--sat));
  -webkit-backdrop-filter: blur(64px) saturate(var(--sat));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  /* ⚠️ NO HAY NADA QUE ALINEAR AQUI DENTRO, y no es un descuido: la tarjeta
     se quedo sin hijos el 2026-08-06 (se fue la cinta; el icono, el nombre
     y el destino ya vivian en el HUD). El relleno de arriba —48, que era el
     sitio de la cinta— vuelve al de los otros lados.
     El flex y el relleno se conservan a proposito: la proyeccion es un
     `::before` con `inset: 0`, que se mide contra la caja de RELLENO y por
     eso NO se mueve con esto — comprobado antes de tocarlo. */
  padding: 22px 18px;
  color: var(--snow);
  font-family: inherit;
  /* No recibe toques: el dedo es del riel. El cursor tampoco miente. */
  pointer-events: none;
  /* La escala la pone el JS por distancia al centro; esto solo suaviza. */
  transition: opacity .18s ease;
  /* ⚠️ SIN `will-change`, y se quito a proposito (2026-08-06): declararlo en
     TODAS las tarjetas multiplica las capas de composicion, cada una con su
     textura en la memoria de video del telefono que menos tiene. Ademas fija
     la resolucion de rasterizado: una tarjeta dibujada a su tamaño lejano y
     luego traida al frente se ve pixelada. Y `backdrop-filter` ya promueve a
     capa por su cuenta, asi que encima era gasto sin beneficio. */
}
/*
  ================================================================
  EL EFECTO GATO — la proyeccion esmerilada (2026-08-06)
  ================================================================
  Fundador: *"que se vea que es WhatsApp pero que no se entienda. La
  curiosidad es irresistible, si o si uno entra"*.

  ⚠️ EL DESENFOQUE VIENE HORNEADO EN EL ARCHIVO. Aqui NO hay `filter:
  blur()` y no puede haberlo: un blur de CSS deja viajar la imagen ORIGINAL
  al celular del visitante, y se recupera quitando el filtro. Los archivos
  de `assets/paneles/` miden 44x59 px — un nombre de 30 px quedo en 0,9 —
  asi que no hay informacion que recuperar. El desenfoque es destructivo o
  no es privacidad.
  ⚠️ Y NO SE AMPLIAN CON `image-rendering: pixelated`: lo que las vuelve
  vidrio esmerilado es justamente que el navegador las estire suave.
*/
/*
  🔴 EL HUSO DE LUZ ENTRE LOS PANELES ERA ESTO, Y ERA MIO (fundador,
  2026-08-07: *"esa linea sigue apareciendo... ahi esta"*). No era la linea
  de la base que acababamos de borrar: era LA LAMPARA, pintandose en LAS
  NUEVE TARJETAS en vez de solo en la del frente.
  Medido: en una vecina girada casi de perfil —18 px de ancho en pantalla—
  ese ovalo de 141 px se comprime en un huso vertical brillante, y como cae
  en el hueco entre dos paneles se lee como una linea suelta.

  ⚠️ EL `:not(.lejos)` NO ES COSMETICA: es lo unico que separa "una lampara
  encendida" de "una raya en el aire". Y la regla que apaga el contenido de
  las vecinas (`.panel-tarjeta.lejos > *`) no podia salvarlo, porque un
  PSEUDOELEMENTO no es un hijo — `> *` no lo alcanza nunca. Esa es la
  trampa: apagar los hijos deja vivos el `::before` y el `::after`.
  Y ademas es lo correcto por significado: la lampara dice *este esta
  encendido*; encendidas las nueve, no dice nada.
*/
/*
  🔴 AQUI VIVIA LA LAMPARA DEL CENTRO. Borrada el 2026-08-07 con la palabra
  del fundador nombrando su blanco: *"ArmiñoD1NA para la lampara. Borrarlo
  del todo"*.

  ⚠️⚠️ Y NACIO DE UN MALENTENDIDO MIO QUE VALE LA PENA GUARDAR. El señalo con
  un circulo una luz en la mitad de la tarjeta —*"desde ahi es que te digo
  que debe salir el barrido"*— y estaba señalando **el vertice del HAZ**: el
  conico de dos abanicos convergia exactamente ahi. Yo lo lei como "existe
  una lampara en el medio" y **construi la lampara que el creia que ya
  existia**. Despues el haz se fue con su palabra y esta quedo sola
  alumbrando: el halo que siguio viendo.
  *Un pedido que describe algo que YA ESTA no es un pedido de construirlo.*

  Lo que se pierde: nada de lo que dependa otra cosa. El barrido recorre la
  tarjeta entera por su cuenta desde el borde de arriba.
  ⚠️ Con ella se va su `@keyframes faro-lampara`, que no animaba nada mas.
  CSS completo en backups/2026-08-07/borrado-lampara-centro.md.
*/

/*
  LA LLUVIA DE ESCARCHA — la maqueta del fundador, traducida (2026-08-07:
  *"en la maqueta hay una lluvia de puntos blancos, es hora de agregarlo"*).

  ⚠️ ESTO ES LO QUE NO SE HIZO EL 2026-08-06 Y HOY SÍ. Aquel dia el propuso
  una lluvia de codigo y se argumento en contra con §7 —*lo que delata la IA
  es el racimo, y la lluvia de Matrix es su cliche numero uno*— y el escogio
  la respiracion. **Esto es otra cosa y por eso entra:** no son caracteres
  cayendo, son PUNTOS. No dice "sistema informatico"; dice aire, polvo,
  profundidad. Lo primero es un cliche; lo segundo es atmosfera.

  ⚠️ CADA UNO CON SU CARRIL, SU TAMAÑO Y SU RITMO, y no es adorno del
  adorno: dieciseis puntos con la misma duracion se leen como una FILA
  cayendo — el racimo que §7 saca. Las cifras salen de su maqueta tal cual.
  ⚠️ SOLO `transform` Y `opacity`, lo unico barato sobre la camara (§5).
  ⚠️ BLANCOS EN LOS DOS MODOS. En Cristal Perlado casi no se ven, y esta
  bien: escarcha oscura cayendo sobre un fondo claro no se lee como polvo de
  luz, se lee como suciedad — es el mismo motivo por el que §2 pone el filo
  en blanco en el modo claro.
*/
.paneles-escarcha {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  /* Detras de todo lo de la vitrina. El tambor no declara z-index, asi que
     con 0 basta para quedar por debajo sin pelear con nadie. */
  z-index: 0;
  /*
    ⚠️ LA ESCARCHA SE APAGA AL PASAR POR DETRAS DE LA TARJETA (fundador,
    2026-08-07: *"no deberia verse igual pasando por la tarjeta,
    perderiamos la intencion de profundidad"*).
    Tiene razon y es una mejora SOBRE SU PROPIA MAQUETA: alli la lluvia
    cruza por delante del panel a plena luz, y eso aplana las dos capas en
    una. Si el polvo se ve igual delante y detras, no hay detras.

    COMO: una mascara que baja la banda donde vive la tarjeta al 15% — nacio
    en 30 y el fundador pidio *"un 50% menos"* el mismo dia, o sea la mitad
    de lo que se veia. Es
    vertical y no un recorte de su rectangulo porque un punto que cruza a
    esa altura por los lados esta pasando por detras de una VECINA, que
    tambien es una tarjeta — asi que apagarlo ahi tambien es correcto.
    El centro va en `50% - 25px` y no en `50%`: el cuerpo de la vitrina sube
    esos 25 (ver `padding-bottom` arriba), y una mascara escrita contra el
    centro de la pantalla se habria quedado 25 px mas abajo que su tarjeta.

    ⚠️ `mask` ES UNA DE LAS SEIS QUE FORMAN BACKDROP ROOT, y por eso vive
    AQUI: sus unicos descendientes son los dieciseis puntos. Las tarjetas
    son sus HERMANAS. Puesta un piso mas arriba apagaria el vidrio de las
    nueve sin dar un solo error — se mide despues de ponerla.
  */
  -webkit-mask-image: linear-gradient(to bottom,
    #000 0,
    #000 calc(50% - 25px - var(--panel-alto) / 2),
    rgba(0, 0, 0, .15) calc(50% - 25px - var(--panel-alto) / 2 + 26px),
    rgba(0, 0, 0, .15) calc(50% - 25px + var(--panel-alto) / 2 - 26px),
    #000 calc(50% - 25px + var(--panel-alto) / 2),
    #000 100%);
  mask-image: linear-gradient(to bottom,
    #000 0,
    #000 calc(50% - 25px - var(--panel-alto) / 2),
    rgba(0, 0, 0, .15) calc(50% - 25px - var(--panel-alto) / 2 + 26px),
    rgba(0, 0, 0, .15) calc(50% - 25px + var(--panel-alto) / 2 - 26px),
    #000 calc(50% - 25px + var(--panel-alto) / 2),
    #000 100%);
}
.paneles-escarcha i {
  position: absolute;
  left: var(--x);
  top: 0;
  width: var(--p, 1.5px);
  height: var(--p, 1.5px);
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 3px rgba(255, 255, 255, .9);
  opacity: 0;
  animation: escarcha-sube var(--t) linear var(--d) infinite;
}
/*
  ⚠️ SUBE, NO CAE (fundador, 2026-08-07): *"invertir la direccion de la
  lluvia, que vaya de abajo hacia arriba"*. Se intercambian las dos puntas
  del recorrido y nada mas — el ritmo, los carriles, los tamaños y el
  desvio lateral no se tocan.
  **El nombre se cambio con el recorrido**, de `escarcha-cae` a
  `escarcha-sube`: un keyframe que dice "cae" y sube es la clase de papel
  que manda a buscar donde no es. Solo lo nombra su propia regla, dos
  lineas arriba, asi que el renombrado no alcanza a nada mas.
  Y de paso deja de ser lluvia y pasa a ser lo que de verdad hace un polvo
  de luz alrededor de algo proyectado: **flotar hacia arriba**, como una
  brasa. La escena ya decia que la vitrina es algo que Nix proyecta (§6);
  esto la acompaña en vez de contradecirla.

  Se va un poco de lado, como algo que flota en vez de algo que se deja
  caer. Nace y muere fuera de cuadro: nunca se ve aparecer.

  🔴 `vh` Y NO `%`, Y ESTE FUE UN DEFECTO MIO QUE NO DABA NINGUNA SEÑAL. Su
  maqueta usa `translateY(-10vh)` → `translateY(105vh)` y yo los "traduje" a
  porcentajes dando por hecho que eran lo mismo. **No lo son: el % de
  `translateY` se mide contra EL PROPIO ELEMENTO, no contra su contenedor.**
  Un punto mide 1,5 px, asi que el 105% eran 1,6 px de recorrido: los
  dieciseis temblaban en el borde de arriba y no se veia ninguno. Todo
  "funcionaba" —existian, estaban animados, la consola muda— y no habia
  lluvia. Cazado midiendo cuanto recorria uno de verdad.
*/
@keyframes escarcha-sube {
  0%   { transform: translateY(105vh) translateX(0);     opacity: 0; }
  15%  { opacity: .8; }
  85%  { opacity: .8; }
  100% { transform: translateY(-10vh) translateX(25px);  opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .paneles-escarcha { display: none; }
}

/*
  EL RESPLANDOR DE LA ESQUINA — VUELVE A SU SITIO (fundador, 2026-08-07:
  *"tiene un halo justo debajo del simbolo... parece que alumbrara todo el
  panel, lo hace ver muy Apple, muy premium"*).
  Es la pieza de su maqueta que yo mismo perdi por el camino: nacio aqui
  (`-top-16 -left-16 w-40 h-40 bg-white/10 blur-xl`), la RECICLE para hacer
  la lampara del centro moviendola al medio, y la lampara acabamos de
  borrarla — asi que se llevo por delante algo que el si queria.
  *Reciclar una capa para otro oficio es borrar el primero sin decirlo.*

  Es luz que entra desde fuera del cuadro y se derrama por la esquina de
  arriba a la izquierda — justo debajo del simbolo. Eso es lo que hace que
  la tarjeta parezca alumbrada y no pintada.

  ⚠️ BLANCO EN LOS DOS MODOS, y no es descuido: §2 lo tiene escrito para el
  filo de luz — *"en el claro la luz es BLANCA... sobre un fondo claro un
  filo oscuro se lee como suciedad y no como brillo"*. Un reflejo es blanco
  siempre; lo que cambia entre modos es cuanto se nota, no de que color es.
  ⚠️ Y ES UN DEGRADADO, NO UN `blur()`: se ve igual y cuesta la decima parte
  (block-PAN13). Cuando lo unico que se quiere es una mancha de luz, el
  desenfoque es la forma cara de dibujarla.
*/
.panel-tarjeta:not(.lejos)::before {
  content: "";
  position: absolute;
  top: -16%;
  left: -16%;
  width: 62%;
  height: 42%;
  border-radius: 50%;
  background: radial-gradient(closest-side,
    rgba(255, 255, 255, .11) 0%,
    rgba(255, 255, 255, .04) 55%,
    rgba(255, 255, 255, 0) 100%);
  pointer-events: none;
}



/*
  ================================================================
  LA RESPIRACION — el panel del frente esta VIVO (2026-08-06)
  ================================================================
  Fundador, viendo la vitrina desplegada: *"los paneles se sienten muy
  aburridos, casi muertos... debe ser el desenfoque"*.

  ⚠️ NO ERA EL DESENFOQUE, Y ESO SE VIO EN SU PROPIA CAPTURA: la tarjeta
  del frente era la MENOS desenfocada de las tres —se le veia la cara a la
  persona— y era la que mas muerta se veia. Si la culpa fuera del
  desenfoque, esa habria sido la viva. Lo que faltaba es que **nada se
  movia**: tres fotos fijas detras de un vidrio. Una pantalla de verdad
  respira, y quitar el desenfoque solo habria dado fotos fijas mas nitidas
  —y publicado los datos que §7e protege—.

  LA CURA ES UN PASEO LENTISIMO de la captura ya horneada: 16 segundos de
  ida y 16 de vuelta, 7% de acercamiento. No se nota moverse; se nota que
  esta encendida. Y no agrega ni un elemento ni toca la privacidad: es la
  MISMA imagen horneada, paseando.

  ⚠️ SOLO EL DEL FRENTE, Y NO ES TACAÑERIA: es §5. Animar los ocho serian
  ocho capas componiendose sobre la camara viva en el Android de gama
  media. Los de atras van girados y encogidos —su respiracion no se
  percibe y costaria igual—, asi que ademas de barato dice algo: el del
  frente esta ENCENDIDO y los otros esperan. `:not(.lejos)` es el que ya
  marca el JS, asi que esto no le pide ni una linea nueva.
*/
@keyframes panel-respira {
  from { transform: scale(1) translate(0, 0); }
  to   { transform: scale(1.10) translate(-1.6%, -2.2%); }
}
/*
  ⚠️ ESTAS DOS CIFRAS SON EL DIAL DEL DEDO DEL FUNDADOR, y la primera
  version se quedo corta: a 1,07 en 16 s la imagen recorria 13 px, o sea
  0,8 px por segundo — se habria notado tanto como nada, y el reporte
  habria sido "sigue muerto". A 1,10 en 13 s recorre 19 px (1,4 px/s):
  se lee al mirar la tarjeta tres segundos y sigue sin leerse como una
  animacion. Mas rapido empieza a marear en algo que se mira de cerca.
  Y ampliar no le quita calidad a la proyeccion: esta desenfocada a
  proposito, asi que estirarla la vuelve MAS esmerilada (§7e).
*/
/*
  🔴 EL TEMBLOR RARO ERA ESTO, Y ERA MIO (fundador, 2026-08-07: *"hay un
  temblor raro, ese no va"*). La respiracion animaba EL CUADRO entero, y un
  cuadro con BORDE y esquinas redondeadas que se agranda un 10% no respira:
  se bambolea. El borde se mueve, la retícula se estira, y el ojo lo lee
  como un defecto — que es exactamente lo que es.
  Cuando esto se escribio (§6, 2026-08-06) animaba una FOTO DESENFOCADA sin
  bordes, y ahi el mismo 10% se leia como "encendido". **La regla no cambia;
  cambio a quien se le aplica.**
  LA CURA: respira la capa de ADENTRO —la retícula—, que el cuadro recorta
  con su `overflow: hidden`. Los puntos se pasean lentísimo y el marco no se
  mueve ni un pixel. Sigue diciendo "esta pantalla esta encendida" sin
  temblar.
*/
.panel-tarjeta:not(.lejos) .panel-cuadro::before {
  animation: panel-respira 13s ease-in-out infinite alternate;
}
/* Quien pide menos movimiento no recibe ninguno: la vitrina se entiende
   igual, que es la misma doctrina del giro plano en pintarFisica. */
@media (prefers-reduced-motion: reduce) {
  .panel-tarjeta:not(.lejos) .panel-cuadro::before { animation: none; }
}

/*
  ================================================================
  LA REVELACION — el panel que llega NO ESTA: SE ARMA (2026-08-06)
  ================================================================
  La segunda mitad de la pregunta del fundador (*"proyeccion o revelacion
  tipo Jarvis"*). El haz dice de donde sale la luz; esto dice que la imagen
  **se enciende**, que es la otra mitad de por que un holograma de cine se
  lee como holograma: nunca aparece entero, se engancha.

  MEDIO SEGUNDO Y SE ACABO, y ocurre solo al cambiar de panel — o sea que
  es ocasional por naturaleza y no cae en el "estilo permanente" que §7
  saca. Dos gestos a la vez:
  · EL CRISTAL SE DIBUJA: los corchetes entran desde un pelin mas afuera.
  · LA IMAGEN SE ESTABILIZA: sube, titubea una vez y se asienta. **El
    titubeo es el truco entero** — una señal que se engancha no sube
    derecho; si sube derecho se lee como un fundido de plantilla.

  ⚠️ LAS DOS ANIMACIONES DEL `::before` VAN DECLARADAS JUNTAS, y no es
  estilo: `animation` es una sola propiedad, asi que nombrar aqui solo la
  revelacion BORRARIA la respiracion del panel — el efecto de ayer se
  apagaria justo en el panel que se esta mirando, y encima solo a veces.
*/
@keyframes panel-estabiliza {
  0%   { opacity: 0; }
  38%  { opacity: .30; }
  56%  { opacity: .14; }   /* el titubeo: la señal enganchando */
  100% { opacity: .50; }
}
@keyframes panel-dibuja {
  0%   { opacity: 0; transform: scale(1.10); }
  60%  { opacity: 1; }
  100% { opacity: 1; transform: scale(1); }
}
/*
  ⚠️⚠️ LA RESPIRACION ES DE ESTAR AL FRENTE; EL TITUBEO ES DE ACABAR DE
  LLEGAR. ESTABAN JUNTAS Y ESO CAUSABA UN PARPADEO EN LA VUELTA DE LA RONDA
  (fundador, 2026-08-07: *"el sonido se quito, pero quedo el parpadeo"*).

  Las dos colgaban de `.revelando`, que solo la tiene una tarjeta que YA
  estuvo al frente. Al dar la vuelta, el tambor cambia de la COPIA del final
  —que la tiene y esta respirando— al panel REAL equivalente, que nunca la
  tuvo: la imagen pasaba de respirar a quedarse **quieta de golpe**. Ese
  salto es el parpadeo, y aparecio al curar el doble tic — antes lo tapaba
  `revelar()`, que le ponia la clase de refilon en cada vuelta.

  Separadas: **respira cualquiera que este al frente** (por eso la primera
  regla no pide `.revelando`), y **el titubeo de llegada solo cuando de
  verdad llega una nueva**. Una tarjeta que solo cambia de elemento sin
  cambiar de panel ya no tiene por que titubear — ni por que dejar de
  respirar.
  *Dos animaciones con dos causas distintas no pueden colgar de la misma
  condicion: el dia que una de las dos causas cambie, la otra se rompe.*
*/
.panel-tarjeta:not(.lejos) .panel-cuadro::before {
  animation: panel-respira 13s ease-in-out infinite alternate;
}
.panel-tarjeta.revelando:not(.lejos) .panel-cuadro::before {
  animation: panel-respira 13s ease-in-out infinite alternate,
             panel-estabiliza .52s ease-out;
}
/* El `::after` de la tarjeta —el cristal con sus corchetes— se fue el
   2026-08-07 con la palabra, asi que `panel-dibuja` se quedo sin cuerpo.
   La revelacion la cuenta el titubeo de la señal, que es lo que quedo. */

/*
  ================================================================
  EL GOLPE — elegir panel se siente como elegir personaje
  ================================================================
  Pedido del fundador: *"al dar click, Nix baja, lo toca y lo activa; el
  panel hace algo como cuando elegimos un personaje en un videojuego"*.
  El momento ya existia y era timido: un borde verde y un destello. Lo que
  lo vuelve un GOLPE son dos cosas que pasan a la vez —el HUD fijando el
  objetivo y la luz dando un tiron—, encima del acorde que ya suena.

  · LOS CORCHETES SE CIERRAN sobre el panel desde mas afuera. Con el
    recorte de la tarjeta, empiezan fuera de vista y entran: se lee como
    una mira que se cierra, no como algo que crece.
  · EL HALO DA UN TIRON: la lampara sube de golpe y vuelve. Es el unico
    momento en que la luz de la casa se permite subir asi.

  🔴 EL GOLPE SE QUEDO SIN CUERPO EL 2026-08-07. Sus dos piezas eran los
  CORCHETES —que se cerraban como una mira— y el HALO —que daba un tiron—,
  y las dos se fueron con la palabra del fundador nombrando su blanco.
  El momento sigue existiendo —Nix aterriza y enciende el panel— y lo
  cuenta lo que quedo: el borde de la tarjeta se pone cian con
  `.panel-encendido`, que ahora SI distingue algo, porque antes lo llevaba
  siempre y por eso no distinguia nada.
  Los dos juegos de keyframes y sus reglas, en backups/2026-08-07/.
*/

/*
  ================================================================
  EL BARRIDO — la linea de escaneo que recorre el panel del frente
  ================================================================
  El clich del holograma, pero es el bueno: §6 lo tiene escrito como el
  momento KITT, **con su freno** — *"un chiste muy bueno, a la tercera y
  quinta vez ya no da risa"* (fundador). Por eso el ciclo dura 9 segundos y
  el barrido ocupa solo el ultimo quinto: pasa, y se deja extrañar.

  ⚠️ SE MUEVE LA LINEA CON `transform`, NO EL DEGRADADO CON
  `background-position`. Las dos se ven igual; la segunda repinta en cada
  fotograma y la primera no toca al pintor — §5, lo unico barato sobre la
  camara. Y no hace falta recortar nada: la linea mide lo que mide el panel
  y su recorrido termina donde termina el panel.
  ⚠️ VA EN EL TAMBOR Y NO EN LA ESCENA. En la escena tendria que ir detras
  del vidrio, y un barrido que se ve DESENFOCADO no se lee como barrido. La
  luz que recorre un cristal va por encima del cristal.
*/
/*
  ⚠️ EL BARRIDO ARRANCA DE UNA Y VUELVE CADA 3 SEGUNDOS (fundador,
  2026-08-06: *"tiene que salir apenas aparezca el panel con una
  intermitencia de 3 segundos"*).
  Antes esperaba el 74% de un ciclo de nueve, o sea que un visitante podia
  abrir la vitrina, mirar seis segundos y no ver nunca la pasada — el
  efecto existia y no se enteraba nadie. Ahora cruza en el primer segundo
  y descansa los otros dos.
  El freno de §6 sigue en pie: pasa y se va. Lo que cambio es cada cuanto.
*/
/*
  ⚠️ EL BARRIDO VUELVE A SER LA BANDA DE ARRIBA ABAJO (fundador,
  2026-08-07: *"el barrido cambio, mantengamos el que tenia, de arriba
  hacia abajo"*). Yo lo habia convertido en una cuña giratoria para
  acoplarlo a la lampara. **El acople era lo que el pedia; cambiarle el
  movimiento no.**
  LA LAMPARA SE QUEDA EN EL CENTRO Y EL ACOPLE SE HACE CON EL RELOJ, NO CON
  LA FORMA: la lampara sube justo cuando la banda le pasa por encima. Se ve
  que la luz sale de ahi sin tener que cambiar por donde pasa el barrido.
  *Acoplar era sincronizar, no reformar.*

  ⚠️ SE MUEVE LA BANDA CON `transform`, NO EL DEGRADADO CON
  `background-position`: las dos se ven igual y la segunda repinta en cada
  fotograma (§5, lo unico barato sobre la camara).
  ⚠️ VA EN EL TAMBOR Y NO EN LA ESCENA: en la escena iria detras del vidrio,
  y un barrido desenfocado no se lee como barrido. La luz que recorre un
  cristal va por encima del cristal.
  ⚠️ Y CONSERVA SU FRENO (§6, el momento KITT): cruza en el primer segundo
  y descansa los otros cinco. Pasa, y se deja extrañar.
*/
/*
  ⚠️⚠️ EL BARRIDO NACE EN LA LAMPARA (fundador, 2026-08-07, señalando la luz
  del centro con un circulo: *"hay una luz en la mitad de la tarjeta, desde
  ahi... utilizando esa es que te digo que debe salir el barrido"*).
  Entraba por el BORDE DE ARRIBA, y por eso el acople no se leia: una banda
  que aparece en el canto no sale de ninguna parte, por muy sincronizada que
  este con la luz. Ahora la banda **aparece encima de la lampara y baja**:
  se ve nacer donde esta la luz.
  Baja y no sube porque eso fue lo que el pidio mantener el mismo dia — *"de
  arriba hacia abajo"*—: lo que cambia es DONDE empieza, no hacia donde va.
  Y se apaga mientras baja, como la luz que se aleja de su fuente.
*/
/*
  ⚠️ RECORRE LA TARJETA ENTERA (fundador, 2026-08-07: *"el barrido debe ser
  de toda la tarjeta"*). Lo habia hecho nacer en la lampara y bajar solo la
  mitad de abajo; el nacimiento se leia, pero media tarjeta se quedaba sin
  barrer. Ahora cruza de borde a borde otra vez.
  ⚠️ Y SE VE UN 30% MENOS, tambien suyo: la punta baja de .95 a .66. Lo que
  cambia es CUANTO SE VE, no cuanto dura ni por donde pasa — son perillas
  distintas y se giran de a una.
*/
/* Los porcentajes se reparten el ciclo entero porque ya no hay descanso que
   repartir: sale, cruza, y se apaga al llegar abajo. */
@keyframes panel-barrido {
  0%   { transform: translateY(0);                              opacity: 0; }
  10%  { transform: translateY(0);                              opacity: .66; }
  85%  { transform: translateY(calc(var(--panel-alto) - 34px)); opacity: .66; }
  100% { transform: translateY(calc(var(--panel-alto) - 34px)); opacity: 0; }
}
.paneles-tambor::before {
  content: "";
  position: absolute;
  left: 50%;
  /* Desde el borde de arriba de la tarjeta. */
  top: calc(50% - var(--panel-alto) / 2);
  width: calc(var(--panel-ancho) - 2px);
  height: 34px;
  /* El centrado va por margen y NO por transform: el transform es de la
     animacion, y escribirlo dos veces deja ganar a uno de los dos. */
  margin-left: calc(var(--panel-ancho) / -2);
  background: linear-gradient(to bottom,
    rgba(var(--nix-halo-rgb), 0) 0%,
    rgba(var(--nix-halo-rgb), .22) 44%,
    rgba(var(--nix-halo-rgb), .35) 50%,
    rgba(var(--nix-halo-rgb), .22) 56%,
    rgba(var(--nix-halo-rgb), 0) 100%);
  opacity: 0;
  /*
    ⚠️ `screen` ES LO QUE HACE QUE ALUMBRE EN VEZ DE TAPAR (fundador,
    2026-08-06: *"el barrido debe alumbrar y revelar el panel"*). Una banda
    normal se pinta ENCIMA: aclara la zona pero esconde lo que hay debajo,
    que es lo contrario de revelar.
    ⚠️⚠️ `mix-blend-mode` es una de las seis que forman Backdrop Root, y un
    Backdrop Root sobre el tambor apagaria el vidrio de las nueve tarjetas
    SIN DAR NINGUN ERROR. Va en un pseudo del tambor —hermano de la escena,
    no su ancestro— y se comprueba despues de ponerlo.
  */
  mix-blend-mode: screen;
  pointer-events: none;
}
/*
  ⚠️⚠️ EL BARRIDO DEJA DE SER AMBIENTAL Y PASA A SER LA RESPUESTA A LA
  ACTIVACION (fundador, 2026-08-07): *"que aparezca después de que Nix
  active: alguien toca el panel, Nix baja al CTA y activa, inmediatamente se
  activa el barrido, y ese tiempo lo podemos utilizar como tiempo de carga
  del destino"*.
  Antes cruzaba solo cada 6 segundos, mirara alguien o no. Ahora **no se
  mueve hasta que Nix aterriza**, y eso lo cambia de adorno a MENSAJE: el
  barrido es la maquina leyendo el panel, y su medio segundo es el tiempo
  que el destino tarda en abrir. Un compas de espera que dice algo vale mas
  que un compas de espera en blanco.
  El ciclo baja de 6 s a .9: ya no tiene que descansar entre pasadas porque
  no hay pasadas que no haya pedido alguien.
*/
.paneles-tambor.barriendo::before {
  animation: panel-barrido .9s ease-in-out;
}
@media (prefers-reduced-motion: reduce) {
  .paneles-tambor.barriendo::before { animation: none; }
}


/* Todo lo de arriba se apaga para quien pide menos movimiento. La vitrina
   sigue diciendo lo mismo: cual esta al frente y a donde lleva. */
@media (prefers-reduced-motion: reduce) {
  .panel-tarjeta.revelando:not(.lejos)::before,
  .panel-tarjeta.revelando:not(.lejos)::after,
  .panel-tarjeta.panel-encendido:not(.lejos)::after,
  .paneles-escena.golpe::before { animation: none; }
  .paneles-tambor::before { display: none; }
}

/*
  🔴 AQUI VIVIA EL CRISTAL DEL FRENTE — los corchetes tacticos, el reflejo y
  las lineas de escaneo, las tres en una sola capa (`::after`) porque no se
  animaban. BORRADO el 2026-08-07 con la palabra del fundador nombrando su
  blanco: *"ArmiñoD1NA para «IDBOX.LAT», el haz de Nix y los corchetes
  cian"*, y con el aviso dado antes: con los corchetes se iban el reflejo y
  el escaneo, que compartian la capa.
  POR QUE: su maqueta nueva cuenta otra historia — la tarjeta se sostiene
  sola— y las tres eran §6, *"la vitrina es algo que Nix proyecta"*. Dos
  lenguajes encima de la misma tarjeta, y por eso no se veia como su imagen.
  El CSS entero, tal cual corria, en backups/2026-08-07/.
*/

/* =====================================================================
   LA FICHA DE LA TARJETA — la maqueta del fundador (2026-08-07), traducida
   a las fichas de la casa. El original tal cual quedo en
   `_originales/2026-08-07-maqueta-paneles-fundador.html`.

   ⚠️ TRADUCIDA Y NO PEGADA, y es un hecho y no un gusto: su codigo esta
   escrito en Tailwind y la casa no lo tiene —dos dependencias, cero
   framework de CSS, cero paso de compilacion—, asi que pegado literal
   saldria una pagina blanca con texto apilado.

   ⚠️ NINGUN CAMPO VACIO RESERVA SU HUECO. El JS solo crea el nodo que
   tiene contenido, asi que la tarjeta se ve digna con uno solo lleno. Hoy
   TODOS estan vacios —la 022 no se ha corrido y la cabina no existe—, y lo
   que sale es simbolo, nombre, la pantalla apagada y el boton. Correcto,
   no a medio hacer.
   ===================================================================== */
.panel-tarjeta {
  /* Reparte en tres: cabecera arriba, cuadro estirandose, boton abajo.
     Antes era `center` porque no habia hijos que repartir. */
  justify-content: space-between;
  align-items: stretch;
  gap: 12px;
  /* `p-5` de la maqueta. */
  padding: 20px;
}

.panel-cabecera {
  display: flex;
  align-items: center;
  gap: 10px;            /* `gap-2.5` */
  position: relative;   /* por encima del resplandor del ::before */
  z-index: 1;
  min-height: 30px;
}
/* El simbolo en su medalla: el aro es la luz de Nix, no un color nuevo. */
.panel-simbolo {
  /*
    🔴 42 px = LOS 32 DE LA MAQUETA MAS UN 30% (fundador, 2026-08-09:
    *"agranda el aro un 30% manteniendo el tamaño del icono, se siente super
    apretado"*). **El icono NO crece**: sus tamaños viven en `--ico`, medidos
    uno por uno por area de tinta, y no se tocan. Lo que crece es el AIRE
    entre el dibujo y el borde — que era lo apretado.
    Efecto secundario buscado: la luz que cruza la medalla tenia 32 px de
    recorrido y ahora tiene 42. Un destello sobre una moneda no se ve.
  */
  width: 42px;
  height: 42px;
  flex: none;
  border-radius: var(--r-pildora, 999px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(var(--nix-halo-rgb), .20);
  border: 1px solid rgba(var(--nix-halo-rgb), .40);
  /* El halo de la medalla (`shadow-[0_0_12px_rgba(0,242,254,0.3)]`), con
     el cian de la casa y no con el de la maqueta — el suyo es #00f2fe y
     §4 nombra ese exacto como el que NO es nuestro. */
  box-shadow: 0 0 12px rgba(var(--nix-halo-rgb), .30);
  /* Cian BRILLANTE, la regla del block-PAN30: un simbolo se lee por el
     tono, y este es el mismo de los cuatro CTA de la Caja. */
  color: var(--nix-cyan);
}
.panel-simbolo svg { width: 16px; height: 16px; }   /* `w-4 h-4` */

/*
  ── LA MEDALLA SE APAGA, Y NIX LA ENCIENDE (2026-08-09) ──────────────────

  Propuesta del fundador y su decision, escogida viendo `/iconos` en el
  celular: **aro blanco, color al icono, y un tono para cada uno.**

  🔴 LO QUE ESTO ARREGLA NO ES ESTETICO: hasta hoy la medalla nacia cian y
  se quedaba cian, **incluida la que Nix acababa de tocar**. O sea que el
  color de la casa estaba puesto en las nueve todo el tiempo y no distinguia
  nada. Ahora el cian llega SOLO cuando Nix aterriza — y ahi empieza a
  significar algo: *"esta ya es de la casa"*.
  Es la misma ley del verde de §4 (verde = SOLO estado): un color que esta
  siempre no informa; informa el que aparece.

  ⚠️ NIX YA ATERRIZA AQUI y no hubo que construirlo: `volarNixAlPanel` apunta
  a `.panel-simbolo` desde el 2026-08-07 (*"Nix tiene que llegar a un destino
  siempre, no quedar en el aire"*). Lo unico que faltaba era que la medalla
  tuviera dos caras. `.panel-encendido` la pone y la quita `alActuar`.

  🔴 Y LOS TIEMPOS SON UN DEFECTO YA MEDIDO, no una preferencia. El destello
  dura **250 ms** (`alActuar`, nix-motion.js:153). Con la transicion de .45 s
  que puse primero, **a los 248 ms el cambio iba por el 85%** y ahi Nix ya se
  habia ido: no se completaba nunca y lo que se veia era un parpadeo sucio a
  medio camino — que en una pantalla congelada se veia perfecto.
  La IDA son .16 s (llega entera a los 174 ms, comprobado) y la VUELTA .38 s,
  porque ahi ya no corre nadie y una vuelta lenta se lee como que el color
  regresa. *Existir no es ocurrir, y empezar no es llegar.*

  ⚠️ AQUI NO HAY NINGUN LOGO DE MARCA, Y NO ES UN OLVIDO. WhatsApp y Google
  exigen que sus marcas se usen **sin modificar**, asi que un dibujo mio
  parecido es justo lo que sus guias prohiben — y esto es un producto que se
  le cobra a un cliente. Los seis logos oficiales entran el dia que el
  fundador baje los paquetes; ese dia se cambia el archivo del icono y
  **nada de lo de abajo se toca**. Por eso el tono va aparte del dibujo.
*/
/*
  ── LA MEDALLA PLATEADA (2026-08-09) ────────────────────────────────────
  El "plateado" no es un gris: es un DEGRADADO que finge una superficie
  curva —claro arriba, apagado en medio, un respiro abajo— mas un filo de luz
  en el borde. Un gris plano se lee como plastico; lo que lee METAL es que el
  tono CAMBIE a lo largo de la pieza, porque eso es lo que hace la luz sobre
  una curva.
  Nace de que el fundador cazo el problema de fondo usandolo: *"la mezcla de
  lo que si, lo que no y lo que no se sabe embarra todo nuestro esfuerzo por
  ser premium"*. La medalla es lo que unifica la fila entera.
*/
.panel-simbolo {
  position: relative;
  overflow: hidden;
  background:
    linear-gradient(160deg, rgba(var(--toque-rgb), .16) 0%,
                            rgba(var(--toque-rgb), .05) 46%,
                            rgba(var(--toque-rgb), .10) 100%);
  border-color: rgba(var(--toque-rgb), .14);
  box-shadow:
    inset 0 1px 0 rgba(var(--toque-rgb), .30),
    inset 0 -1px 0 rgba(var(--toque-rgb), .06);
  color: rgba(var(--toque-rgb), .78);
  transition: color .38s ease, background .38s ease,
              border-color .38s ease, box-shadow .38s ease;
}

/*
  LA LUZ QUE CRUZA LA MEDALLA. Va en su propia capa y NO animando el fondo:
  animar el fondo repinta la pieza entera en cada fotograma, y esto tiene que
  correr en un Android de gama media (§5). Una capa con `transform` la mueve
  la tarjeta grafica sola.
  ⚠️ SOLO CORRE CUANDO SE LE PIDE (`.destella`), JAMAS EN BUCLE. El fundador
  pidio *"un efecto de movimiento... pero tiene que ser muy bien aplicado
  para que no nos mate premium"*, y se lo discuti a medias: permanente es
  exactamente lo que lo mata. Es su propia ley del momento KITT —*"un chiste
  muy bueno, a la tercera y quinta vez ya no da risa"*— y §7, que prohibe los
  bordes giratorios permanentes.
*/
.panel-simbolo::after {
  content: "";
  position: absolute;
  inset: -40%;
  /*
    🔴 LA BANDA ES MAS ANCHA Y MAS FUERTE QUE LA PRIMERA VERSION, y no es
    gusto: el fundador reporto *"el efecto de la luz por el icono no esta
    saliendo"*. **Y sí estaba saliendo** —medido en produccion: hasta 13
    medallas con la clase puesta, en cascada, y la animacion corriendo—.
    No se veia por dos cosas que se sumaban: la medalla media 32 px, y una
    banda del 8% de ancho cruzando eso es un parpadeo de nada.
    Ahora la banda ocupa el 22% (38→60 en vez de 42→58) y sube a .75.
    *Que una animacion exista y corra no prueba que se VEA* — es la misma
    familia de la que estaba declarada y quieta en produccion, un escalon
    mas arriba: esta si se movia, y aun asi no ocurria para nadie.
  */
  background: linear-gradient(105deg, transparent 38%,
                              rgba(var(--toque-rgb), .75) 50%, transparent 60%);
  transform: translateX(-130%);
  opacity: 0;
  pointer-events: none;
}
.panel-simbolo.destella::after { animation: medalla-luz 1100ms cubic-bezier(.32,.72,.28,1); }
@keyframes medalla-luz {
  0%   { transform: translateX(-130%); opacity: 0; }
  18%  { opacity: 1; }
  82%  { opacity: 1; }
  100% { transform: translateX(130%);  opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .panel-simbolo.destella::after { animation: none; }
}

/*
  LAS DOS CARAS, UNA ENCIMA DE OTRA Y EN EL MISMO CIRCULO — la condicion que
  puso el fundador: *"lo importante es que queden dentro de la misma
  circunferencia para que cuando Nix los prenda queden los que tenemos"*.
  Por eso las dos van `absolute` y centradas: al cruzarse, nada salta.
*/
.panel-marca, .panel-linea {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  transition: opacity .38s ease, transform .38s ease;
}
/*
  ── CADA ICONO SU TAMAÑO, PARA QUE TODOS SE VEAN IGUAL (2026-08-09) ──────

  Pedido del fundador cerrando el diseño de la vitrina: *"Gmail tiene un
  tamaño, WhatsApp otro, YouTube otro"*. Y no era percepcion suya: **cada
  archivo trae distinto aire alrededor del dibujo**, asi que la misma caja da
  dibujos de tamaños distintos.

  MEDIDO CON SONDA, no a ojo: se dibujo cada icono en un lienzo de 200 px y
  se recorrio el alfa para hallar el rectangulo que de verdad pinta.
     whatsapp / instagram  200x200   ← LLENAN la caja entera
     linkedin              200x186
     youtube               200x140   ← ancho y bajo
     web / agendar         164x164
     resenas               172x163
     maps                  132x164
     gmail / correo        164x130   ← el que menos pinta
  WhatsApp pintaba **37% mas tinta que Maps** con la misma caja. Y encima las
  marcas iban en caja de 18 px y los de linea en 16: doble castigo.

  ⚠️ SE IGUALA POR AREA DE TINTA, NO POR LADO. En un conjunto con un circulo,
  un cuadrado y un rectangulo ancho, "el mismo lado" NO se ve del mismo
  tamaño: el ojo pesa la cantidad de tinta, no la anchura. Por eso YouTube
  —bajito— recibe mas caja que WhatsApp, y aun asi los dos se leen iguales.
  ⚠️ Y los de linea reciben MAS caja que las marcas a proposito: un trazo
  hueco pesa menos que una silueta llena del mismo tamaño.
  ⚠️ `correo` y `otro` no se midieron: comparten dibujo exacto con `gmail` y
  con `web`. Copiar su medida es correcto; suponerla no lo seria.
*/
.panel-simbolo { --ico: 20.5px; }
[data-tipo="whatsapp"]  .panel-simbolo { --ico: 17px; }
[data-tipo="instagram"] .panel-simbolo { --ico: 17px; }
[data-tipo="linkedin"]  .panel-simbolo { --ico: 17.5px; }
[data-tipo="youtube"]   .panel-simbolo { --ico: 20.5px; }
[data-tipo="maps"]      .panel-simbolo { --ico: 23px; }
[data-tipo="gmail"]     .panel-simbolo { --ico: 23.5px; }
[data-tipo="correo"]    .panel-simbolo { --ico: 23.5px; }

.panel-marca { width: var(--ico); height: var(--ico); margin: auto; object-fit: contain; }
.panel-simbolo svg { width: var(--ico); height: var(--ico); }

/* ⚠️ EL ICONO DE LINEA SOLO SE ESCONDE SI HAY UNA MARCA QUE MOSTRAR. Los
   tipos sin monocromo oficial —maps, gmail, web, correo, agendar, otro— no
   traen `<img>`, asi que su icono se queda visible en blanco. Sin este `+`
   nacerian invisibles, y ese es el defecto que la sonda vino a cazar. */
.panel-marca + .panel-linea { opacity: 0; transform: scale(.72); }

/* NIX ATERRIZA: la marca se va, entra el icono de la casa — Y SE QUEDA.
   Misma razon que arriba: el estado es `panel-abierto`, no el destello. */
.panel-abierto .panel-marca { opacity: 0; transform: scale(1.25); }
.panel-abierto .panel-marca + .panel-linea { opacity: 1; transform: scale(1); }
.panel-abierto .panel-marca,
.panel-abierto .panel-marca + .panel-linea { transition-duration: .16s; }

/*
  🔴 UN SOLO COLOR EN REPOSO: BLANCO. NINGUNO MAS.
  *"No mas colores, no rojo, ni morado, ni ningun otro"* (fundador,
  2026-08-09, al aprobar la medalla plateada). Aqui vivian cuatro tonos para
  los tipos sin marca —naranja, morado, blanco, magenta— y se fueron con esa
  frase, junto con el chispazo de color de marca que yo habia propuesto.

  **El unico color de la vitrina es el cian, y solo lo pone Nix.** Un color
  que esta siempre no informa; informa el que aparece — la misma ley del
  verde de §4. Con dos o tres colores compitiendo en la fila, el cian dejaba
  de ser una señal y pasaba a ser uno mas.
*/

/*
  NIX ATERRIZA Y LA MEDALLA SE QUEDA EN EL CIAN DE LA CASA.

  🔴 CUELGA DE `.panel-abierto` Y NO DE `.panel-encendido`, y la diferencia
  es el defecto que costo un despliegue el 2026-08-09. Son dos cosas:
    · `panel-encendido` — el DESTELLO. Dura 250 ms y `alActuar` la retira a
      proposito, porque sin retirarla el segundo aterrizaje no destellaria.
    · `panel-abierto`  — el ESTADO. No se quita.
  Colgado del destello, la marca volvia sola a los 250 ms: *"Nix lo toca,
  pasa a cian y automaticamente queda otra vez como al principio"* (fundador).
  El gesto no contaba nada — encender algo que se apaga solo no dice "abierto",
  dice "parpadeo".
  ⚠️ Y por eso ya no hay transicion de vuelta que cuadrar: la ida sigue en
  .16 s para que entre dentro del aterrizaje, y no hay regreso.
*/
.panel-abierto .panel-simbolo {
  background: rgba(var(--nix-halo-rgb), .20);
  border-color: rgba(var(--nix-halo-rgb), .40);
  box-shadow: 0 0 12px rgba(var(--nix-halo-rgb), .30);
  color: var(--nix-cyan);
  transition-duration: .16s;
}

@media (prefers-reduced-motion: reduce) {
  .panel-simbolo, .panel-abierto .panel-simbolo,
  .panel-marca, .panel-linea { transition: none; }
}

/*
  ══ LA TIPOGRAFIA DE LA VITRINA, SEGUN EL DOCUMENTO (2026-08-09) ═════════

  Orden del fundador al cerrar el diseño: *"Cabina ya esta cerrada y tenemos
  un Design System muy claro, si o si nos regimos al documento. No nos
  podemos permitir diferentes tipografias ni diferentes pesos ni tamaños,
  para eso tenemos el manual."*

  🔴 LA VITRINA ESTABA ENTERA POR DEBAJO DE LA ESCALA. `graphic_system.md` §5
  declara SEIS pasos —13 · 15 · 17 · 20 · 24 · 32— y **13 es el piso**. Esta
  pantalla vivia en 12 y 10: **ni un solo tamaño estaba en la escala.**
  Y el porque estaba confesado en los propios comentarios: al lado de cada
  cifra decia `text-xs` y `text-[10px]` — **clases de Tailwind copiadas de la
  maqueta original**. La vitrina heredo los tamaños del mockup en vez de los
  del sistema, y nadie los volvio a mirar. *Se mide el producto, no la
  maqueta del producto* — la misma leccion que §5 ya llevaba escrita.

  🔴 Y LOS PESOS TAMBIEN: §5 admite TRES y ni uno mas —600 titulos · 500
  botones y etiquetas · 400 texto corrido—. Aqui habia 700 por todas partes,
  que no existe en el sistema.

  🔴 MAS DOS INFRACCIONES DE LA LETRA MONOESPACIADA, que nadie habia mirado:
  `.panel-etiqueta` y `.paneles-hud` iban en `--font-mono` para escribir
  PROSA ("Sede Principal", "YouTube"). §5 es literal: *"La monoespaciada es
  solo para numeros que son datos. **Jamas para prosa ni para etiquetas.**"*
  Se lee "Sede Principal" en mono como si fuera una lectura de telemetria, y
  eso es exactamente el contraste tipografico decorativo que la regla prohibe.

  EL MAPA, ROL POR ROL:
    nombre del panel  → principal   17 / 600
    subtitulo         → secundario  15 / 400
    etiqueta          → terciario   13 / 500  · Inter, ya no mono
    dato              → terciario   13 / 500
    cuerpo            → secundario  15 / 400
    nota              → terciario   13 / 400
    boton de accion   → boton       15 / 500
*/
.panel-rotulos { min-width: 0; }   /* deja que el nombre pueda recortarse */
.panel-nombre {
  font-size: 17px;              /* principal · §5 */
  font-weight: 600;             /* titulos · §5 */
  color: var(--texto);
  letter-spacing: -.3px;    /* `tracking-tight` */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.panel-subtitulo {
  font-size: 15px;              /* secundario · §5 */
  font-weight: 400;             /* texto corrido · §5 */
  color: var(--texto-2);
  margin-top: 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/*
  EL CUADRO — la pantalla de esa herramienta.
  ⚠️ Se oscurece con TINTA y no bajando la opacidad. Es la leccion de §1 del
  2026-08-06: apagar con `opacity` vuelve una cosa TRANSPARENTE, no oscura,
  y sobre un fondo claro la aclara todavia mas. Una capa de tinta a baja
  alfa se lee como "pantalla apagada" en los dos modos, que es lo que hace
  un mostrador de verdad.
*/
.panel-cuadro {
  /*
    `h-[180px]` de la maqueta, en PORCENTAJE para que aguante cualquier
    pantalla. ⚠️ EL PORCENTAJE SE MIDE CONTRA LA CAJA DE CONTENIDO, NO
    CONTRA LA TARJETA: 385 de alto menos los 20+20 del relleno son 345, asi
    que el 180 es el **52%** y no el 47 que puse primero — medido, con 47
    el cuadro salia en 143 px en vez de 180.
    Antes era `flex: 1`, o sea "todo lo que sobre": por eso en su captura el
    cuadro se comia la tarjeta entera.
  */
  flex: none;
  height: 52.2%;   /* 180 sobre los 345 de caja de contenido */
  position: relative;
  z-index: 1;
  /* `rounded-2xl` = 16. */
  border-radius: 16px;
  /* Tinta de verdad, como en la maqueta (`bg-black/40`): el cuadro tiene
     que LEERSE como una pantalla apagada dentro del vidrio, no como una
     zona un poco mas oscura. Con .26 no se distinguia del resto. */
  background: rgba(0, 0, 0, .40);          /* `bg-black/40` */
  border: 1px solid rgba(255, 255, 255, .10);   /* `border-white/10` */
  padding: 14px;   /* `p-3.5` */
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 6px;
  overflow: hidden;
}

/*
  LA RETICULA, EN SU PROPIA CAPA DENTRO DEL CUADRO.
  🔴 Y ESTAR AQUI Y NO EN EL FONDO DEL CUADRO ES LA CURA DEL TEMBLOR: **es
  esta capa la que respira**, y el cuadro tiene borde y esquinas redondeadas.
  Animando el cuadro, el marco se bamboleaba — eso era el "temblor raro".
  Aqui la recorta el `overflow: hidden` del cuadro, asi que los puntos se
  pasean y el marco no se mueve ni un pixel.

  Sobre su fuerza: la maqueta la tiene a `#ffffff12` — o sea **7%**, no el
  85 con el que yo la puse la primera vez sobre toda la tarjeta.
  `--toque-rgb` y no un blanco fijo: 255,255,255 en Obsidiana y 9,10,15 en
  Cristal Perlado, asi que los puntos se leen en los dos terrenos.
  ⚠️ `inset: -8%` y no `0`: al acercarse un 10% tiene que SOBRAR reticula por
  los cuatro lados, o al respirar se le veria el canto entrando.
*/
.panel-cuadro::before {
  content: "";
  position: absolute;
  inset: -8%;
  background-image: radial-gradient(rgba(var(--toque-rgb), .09) 1px, transparent 1px);
  background-size: 12px 12px;
  pointer-events: none;
}

/*
  ── UN PATRON POR TIPO DE PANEL (2026-08-09) ────────────────────────────

  Decision del fundador escogiendo en `/patrones`: *"que cada patron
  pertenezca a un panel y ya, solo queremos romper la simetria de todo se ve
  igual"*.

  ⚠️ VA POR TIPO Y NO POR POSICION, y no es un detalle: por posicion, arrastrar
  una tarjeta le cambiaria la textura, y dos clientes con los mismos paneles
  en distinto orden se verian distinto. Por tipo, WhatsApp es WhatsApp donde
  sea. El tipo lo pone `app.js` en `data-tipo` con la MISMA regla de reserva
  que el simbolo (`|| otro`), para que icono y textura nunca se separen.

  ⚠️ UN TIPO SIN REGLA AQUI NO SE ROMPE: se queda con el punteado de arriba,
  que es el que lleva la vitrina desde el 2026-08-07. La lista de abajo puede
  quedarse corta sin que nadie lo pague.

  ⚠️ Y LOS DIBUJOS VAN COMO MASCARA, NO COMO IMAGEN. La propuesta original
  traia el color quemado dentro del SVG (`rgba(255,255,255,.28)`), y un color
  quemado NO PUEDE CAMBIAR DE MODO: en Cristal Perlado el blanco sobre fondo
  claro desaparece. Como `mask-image`, el dibujo solo recorta y el color lo
  pone `--toque-rgb` — 255,255,255 en Obsidiana y 9,10,15 en Perlado.
  Comprobado mirando los dos modos, no leyendo el CSS.

  ⚠️ LA FUERZA ES .09 Y NO SE SUBE. El fundador comparo el 9% contra el 24%
  en la maqueta y escogio *"suave, como hoy"*. Al 24% los puntos empiezan a
  pasarle por encima al texto del widget — se ve en "Casos de exito".

  🔴 REGLA QUE SALIO DE SU ELECCION, Y VALE PARA LO QUE VENGA: **la textura
  de la vitrina es de PUNTOS Y FORMAS CERRADAS, nunca de lineas sueltas.**
  De once patrones boto exactamente dos —diagonales y guiones— y eran los
  unicos dos hechos de lineas. No lo dijo asi; lo dijo escogiendo.
  (La cuadricula de `maps` es la excepcion que confirma el resto: ahi la
  linea DIBUJA UN MAPA, no adorna.)

  ⚠️ La escala del `::before` (`panel-respira`, 1.10) mueve tambien la
  mascara, que es lo correcto: respira la capa entera. Por eso el `inset:-8%`
  sigue siendo necesario — sin el, al respirar se le veria el canto.
*/
.panel-cuadro::before { background-color: transparent; }

/* Los de gradiente: el color entra directo en la variable. */

/*
  ⚠️ `otro` LLEVA LA MATRIZ SIMPLE Y NO ES CASUALIDAD: es el tipo de reserva
  —el que recibe cualquier panel que no reconozcamos—, asi que le toca la
  textura mas neutra de todas. La tenia `youtube` hasta que el fundador
  cazo, mirando la vitrina, que **`youtube` y `resenas` se veian casi
  iguales**: eran los dos unicos de puntos redondos planos, separados solo
  por 2 px de espaciado. Un patron por tipo no sirve de nada si dos tipos
  caen en el mismo sitio del ojo.
*/
[data-tipo="otro"] .panel-cuadro::before {
  background-image: radial-gradient(rgba(var(--toque-rgb), .09) 1.2px, transparent 1.2px);
  background-size: 14px 14px;
}
[data-tipo="whatsapp"] .panel-cuadro::before {
  background-image: radial-gradient(rgba(var(--toque-rgb), .09) 1px, transparent 1px),
                    radial-gradient(rgba(var(--toque-rgb), .09) 1px, transparent 1px);
  background-size: 16px 16px;
  background-position: 0 0, 8px 8px;
}
/* La cuadricula va mas floja a proposito: una linea continua pesa mucho mas
   en el ojo que un punto del mismo color, y al .09 plano se leia como reja. */
[data-tipo="maps"] .panel-cuadro::before {
  background-image: linear-gradient(to right,  rgba(var(--toque-rgb), .04) 1px, transparent 1px),
                    linear-gradient(to bottom, rgba(var(--toque-rgb), .04) 1px, transparent 1px);
  background-size: 14px 14px;
}
[data-tipo="linkedin"] .panel-cuadro::before {
  background-image: radial-gradient(rgba(var(--toque-rgb), .09) .8px, transparent .8px);
  background-size: 6px 6px;
}
[data-tipo="resenas"] .panel-cuadro::before {
  background-image: radial-gradient(rgba(var(--toque-rgb), .11) 1.2px, transparent 1.2px);
  background-size: 12px 12px;
  -webkit-mask-image: radial-gradient(circle at center, #000 30%, transparent 95%);
          mask-image: radial-gradient(circle at center, #000 30%, transparent 95%);
}

/* Los de dibujo: la imagen se apaga y el color pasa a ser el FONDO, que la
   mascara recorta. Sin `background-image: none` quedaria el punteado base
   asomando por debajo del recorte. */
[data-tipo="agendar"]   .panel-cuadro::before,
[data-tipo="web"]       .panel-cuadro::before,
[data-tipo="correo"]    .panel-cuadro::before,
[data-tipo="instagram"] .panel-cuadro::before,
[data-tipo="gmail"]     .panel-cuadro::before,
[data-tipo="youtube"]   .panel-cuadro::before {
  background-image: none;
  background-color: rgba(var(--toque-rgb), .09);
  -webkit-mask-repeat: repeat; mask-repeat: repeat;
}
[data-tipo="agendar"] .panel-cuadro::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14'%3E%3Cpath d='M7 4v6M4 7h6' stroke='%23000' stroke-width='1.2' stroke-linecap='round'/%3E%3C/svg%3E"), radial-gradient(circle at center, #000 30%, transparent 95%);
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14'%3E%3Cpath d='M7 4v6M4 7h6' stroke='%23000' stroke-width='1.2' stroke-linecap='round'/%3E%3C/svg%3E"), radial-gradient(circle at center, #000 30%, transparent 95%);
  -webkit-mask-size: 14px 14px, 100% 100%; mask-size: 14px 14px, 100% 100%;
  -webkit-mask-composite: source-in;       mask-composite: intersect;
}
[data-tipo="web"] .panel-cuadro::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='2' fill='none' stroke='%23000' stroke-width='1'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='2' fill='none' stroke='%23000' stroke-width='1'/%3E%3C/svg%3E");
  -webkit-mask-size: 16px 16px; mask-size: 16px 16px;
}
[data-tipo="correo"] .panel-cuadro::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14'%3E%3Crect x='6' y='6' width='2' height='2' fill='%23000'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14'%3E%3Crect x='6' y='6' width='2' height='2' fill='%23000'/%3E%3C/svg%3E");
  -webkit-mask-size: 14px 14px; mask-size: 14px 14px;
}
/* Instagram = triangulos micro (candidato C) · Gmail = anillo con punto (B).
   Escogidos por el fundador el 2026-08-09 viendolos en el celular. */
[data-tipo="instagram"] .panel-cuadro::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14'%3E%3Cpath d='M7 5l2.2 3.8H4.8z' fill='%23000'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14'%3E%3Cpath d='M7 5l2.2 3.8H4.8z' fill='%23000'/%3E%3C/svg%3E");
  -webkit-mask-size: 14px 14px; mask-size: 14px 14px;
}
[data-tipo="gmail"] .panel-cuadro::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='2.6' fill='none' stroke='%23000' stroke-width='.9'/%3E%3Ccircle cx='8' cy='8' r='.9' fill='%23000'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='2.6' fill='none' stroke='%23000' stroke-width='.9'/%3E%3Ccircle cx='8' cy='8' r='.9' fill='%23000'/%3E%3C/svg%3E");
  -webkit-mask-size: 16px 16px; mask-size: 16px 16px;
}
/*
  ⚠️ LOS PUNTOS EN PAREJA PASARON DE `otro` A `youtube` EL 2026-08-09, por
  orden del fundador mirando la vitrina: *"Reseñas de Google y YouTube se ven
  muy similares a ojo"*. Y tenia razon medida — eran los dos unicos patrones
  de puntos redondos planos. La pareja rompe el parecido porque **cambia el
  ritmo, no el tamaño**: dos puntos juntos y un hueco no se confunden con una
  cuadricula regular por mucho que se afine el espaciado.
  *(Es la misma leccion del `%` que no era `vh`: mover el numero no arregla
  lo que esta mal de forma.)*
*/
[data-tipo="youtube"] .panel-cuadro::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15'%3E%3Ccircle cx='5' cy='5' r='1.1' fill='%23000'/%3E%3Ccircle cx='10' cy='10' r='1.1' fill='%23000'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15'%3E%3Ccircle cx='5' cy='5' r='1.1' fill='%23000'/%3E%3Ccircle cx='10' cy='10' r='1.1' fill='%23000'/%3E%3C/svg%3E");
  -webkit-mask-size: 15px 15px; mask-size: 15px 15px;
}
.panel-cuadro-arriba {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 6px;
}
.panel-etiqueta {
  /*
    🔴 YA NO VA EN MONOESPACIADA. §5 es literal: *"la monoespaciada es solo
    para numeros que son datos. Jamas para prosa ni para etiquetas."* Esto
    escribe "Sede Principal" — prosa, y ademas una etiqueta: las dos mitades
    de la prohibicion a la vez. En mono se leia como una lectura de
    telemetria, que es justo el contraste decorativo que la regla prohibe.
  */
  font-size: 13px;              /* terciario · §5 */
  font-weight: 500;             /* etiquetas · §5 */
  letter-spacing: .2px;
  /*
    ⚠️ PILDORA RELLENA Y OSCURA, no un lavado de cian. La maqueta usa
    `bg-cyan-950/80` —un teal casi negro— con `text-cyan-300`, que es un
    cian SUAVE. Yo tenia el fondo en cian al 13% y la letra en el cian
    pleno: se leia como una etiqueta encendida en vez de un rotulo grabado.
    Medido a maquina contra su maqueta.
  */
  color: rgb(103, 232, 249);                    /* `text-cyan-300` */
  background: rgba(8, 51, 68, .80);             /* `bg-cyan-950/80` */
  border: 1px solid rgba(var(--nix-halo-rgb), .30);
  line-height: 1.5;
  border-radius: var(--r-pildora, 999px);
  padding: 2px 8px;                         /* `px-2 py-0.5` */
  white-space: nowrap;
}
/* El destacado va en `--texto` y no en un ambar: §4 tiene cuatro halos con
   significado y ninguno quiere decir "mira este numero". Un color nuevo por
   un dato seria inventar semantica. */
.panel-dato {
  font-size: 13px;              /* terciario · §5 */
  font-weight: 500;             /* etiquetas · §5 */
  /*
    EL AMBAR DE LA MAQUETA (`text-amber-300`). Se lo discuti —§4 tiene
    cuatro halos con significado y ninguno quiere decir "mira este numero",
    y un 4.9 tecleado a mano envejece— y el lo conservo en su render. Es su
    decision y va.
    🟡 Queda anotado como el QUINTO color de la casa, para que §4 lo recoja
    o lo corrija: hoy no lo nombra ningun documento.
  */
  color: #fcd34d;
  white-space: nowrap;
}
.panel-cuerpo {
  font-size: 15px;              /* secundario · §5 */
  font-weight: 500;             /* etiquetas · §5 — es el rotulo del cuadro */
  color: var(--texto);
  line-height: 1.25;
}
.panel-nota {
  font-size: 13px;              /* terciario · §5 */
  font-weight: 400;             /* texto corrido · §5 */
  color: var(--texto-2);
  margin-top: 2px;
  line-height: 1.3;
}

/*
  EL BOTON DE ACCION — blanco sobre oscuro en la maqueta.
  ⚠️ NO SE ESCRIBE BLANCO: se escribe `--texto` de fondo y `--fondo` de
  tinta, o sea la pareja INVERTIDA. Asi en Obsidiana sale casi blanco con
  letra oscura (la maqueta) y en Cristal Perlado sale casi negro con letra
  clara — que es lo mismo dicho por el otro lado. Un `#fff` fijo seria
  invisible en el modo claro, que es justo donde el fundador revisa.
*/
.panel-accion {
  position: relative;
  z-index: 1;
  flex: none;
  text-align: center;
  border-radius: 16px;      /* `rounded-2xl` */
  padding: 10px 12px;       /* `py-2.5` */
  font-size: 15px;          /* boton · §5 */
  font-weight: 500;         /* botones · §5 */
  background: var(--texto);
  color: var(--fondo);
  /*
    EL BRILLO BAJO EL BOTON (`shadow-[0_10px_25px_rgba(255,255,255,0.2)]` de
    su maqueta, fundador 2026-08-07: *"también noto uno en el CTA... hacen
    resaltar el panel de fondo negro con elegancia"*). No es una sombra: es
    la luz que el propio boton derrama hacia abajo, y es lo que lo despega
    del vidrio en vez de dejarlo pegado como una pegatina.
    ⚠️ EL TONO SALE DE `--toque-rgb` Y NO DE UN BLANCO FIJO, y por una razon
    exacta: el boton es la pareja INVERTIDA (`--texto` de fondo), asi que en
    Obsidiana es casi blanco y en Cristal Perlado casi negro. `--toque-rgb`
    vale 255,255,255 en uno y 9,10,15 en el otro — o sea que el brillo
    siempre es del color del boton que lo tira. Un `#fff` fijo dejaria un
    halo blanco debajo de un boton negro.
  */
  /* .26 = los .20 de la maqueta un 30% mas (fundador, 2026-08-07). Sube la
     LUZ y no el tamaño: el alcance de la mancha (10/25) no se toca, porque
     lo que el pidio fue mas halo, no un halo mas grande — son dos perillas
     distintas y se giran de a una. */
  box-shadow: 0 10px 25px rgba(var(--toque-rgb), .26);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/*
  ⚠️ EL BOTON VA BLANCO EN LOS NUEVE, TENGAN DESTINO O NO (fundador,
  2026-08-07: *"ponle el botón blanco a todos los CTAs"*).
  Antes, sin url se volvia un contorno apagado, y el motivo escrito era la
  doctrina de la tercera tarjeta: *un boton lleno que no lleva a ninguna
  parte es una promesa rota*. **Sigue siendo cierto y el lo decidio con eso
  a la vista** — gana la uniformidad de la vitrina, que es lo que la hace
  ver de una pieza.
  🟡 Lo que queda por cuidar: el rotulo tiene que seguir diciendo
  "Proximamente" con todas sus letras, porque ahora es lo UNICO que avisa
  que ese panel todavia no lleva a ningun sitio. Si algun dia alguien lo
  acorta, el boton pasa a mentir.
*/

/*
  LAS VECINAS VAN VACIAS — son fantasmas, no tarjetas a medio leer.
  En la maqueta del fundador los dos lados son cajas vacias al 20%: lo que
  hacen es DECIR QUE HAY MAS, no ofrecer contenido. Yo las deje con toda su
  ficha adentro y en su captura se ve el resultado — dos tarjetas
  compitiendo con la del frente y la reticula pintada tres veces.
  *El asomo explica el gesto; el contenido de la vecina no lo explica
  mejor, lo estorba.*
  ⚠️ Se apaga el CONTENIDO, no la tarjeta: el vidrio, el borde y el asomo
  se quedan, que son las tres cosas que hacen que se lea como un tambor.
  Y no se quita del DOM: al llegar al frente tiene que estar entera, y
  construirla en ese momento costaria un recalculo en mitad del giro.
*/
.panel-tarjeta.lejos > * {
  opacity: 0;
  transition: opacity .2s ease;
}

/*
  EL BORDE QUE DEJA DE SER LINEA (2026-08-06).
  Un objeto solido tiene contorno; **una proyeccion no tiene contorno, tiene
  luz que se le escapa por los cantos**. El panel del frente llevaba el mismo
  borde gris de 1 px que cualquier caja de la Caja, y eso era lo que mas lo
  delataba como tarjeta pegada.

  ⚠️ ESTO NO ES EL NEON QUE §7 SACA, y la diferencia esta escrita alli: lo
  prohibido es *"neon y resplandores COMO ESTILO PERMANENTE"* — una pieza
  que brilla para llamar la atencion. Esto es el **filo de luz de §2**, la
  firma del vidrio, extendido un punto: sigue siendo 1 px, sigue siendo la
  luz de la casa, y solo lo lleva el del frente. Si se sube hasta que se lea
  como resplandor, cruzo la linea y hay que bajarlo.

  ⚠️⚠️ `:not(.panel-encendido)` NO ES ADORNO: SIN ESO SE ROMPE EL DESTELLO DE
  NIX. `.panel-encendido` (0,1,0) pierde por especificidad contra
  `.panel-tarjeta:not(.lejos)` (0,2,0), asi que este `box-shadow` le ganaria
  al destello verde justo en el momento en que Nix aterriza — el unico
  momento que esta vitrina tiene que contar bien. Su `border-color` se salva
  solo porque lleva `!important`; su sombra no.
*/
/*
  ================================================================
  LA FALLA DE TV — dos segundos despues de aparecer, y una sola vez
  ================================================================
  Fundador, 2026-08-06: *"colocarle un efecto al panel que se muestra tipo
  falla tv a los dos segundos de aparecer y ya, no repetir"*.

  Y el "y ya" es la mitad del efecto, no un detalle: una interferencia que
  vuelve cada tanto deja de ser una falla y pasa a ser un adorno que
  parpadea — §7 y su propio argumento del chiste que a la tercera ya no da
  risa. Aparece una vez, cuando el ojo ya se acomodo al panel, y no vuelve
  hasta que llegue otro.

  ⚠️⚠️ VA EN LA IMAGEN, NO EN EL MARCO — y la primera version lo tuvo al
  reves. La puse en la capa del cristal (corchetes, reflejo, lineas de
  escaneo) porque era la comoda: no tenia animacion permanente que pisar.
  El fundador lo corrigio con el argumento bueno: *"debe sentirse que lo
  que falla es la proyeccion (la imagen), no el sistema"*.
  **El marco ES el sistema** —los corchetes son el HUD, el aparato que
  mira—; verlo temblar dice "el aparato esta malo", que es justo lo
  contrario de lo que este efecto viene a contar. Lo que falla es la señal
  que llega, y la señal es la imagen.

  ⚠️ POR ESO USA `translate` Y NO `transform`: la proyeccion ya esta
  respirando con un `transform`, y dos animaciones sobre la misma propiedad
  se pisan —la ultima gana y la respiracion se apagaria medio segundo—.
  `translate` es una propiedad aparte que se COMPONE con el transform, asi
  que la imagen sigue paseando mientras salta. Es la unica forma de tener
  las dos a la vez sin que ninguna ceda.
  ⚠️ Ni una gota de transform sobre la TARJETA: el suyo la sostiene en el
  cilindro. Lo que salta es la capa de adentro, y el recorte la mantiene
  dentro del panel.
*/
/* ⚠️ UN 40% MENOS QUE LA PRIMERA VERSION (fundador, 2026-08-06: *"se
   siente muy animacion de TikTok de hace 6 años"*). Cada cifra bajo a su
   60%: el salto de 9 px queda en 5,4 y el parpadeo, que llegaba a caer al
   34%, ahora no baja del 40. La forma del glitch es la misma; lo que
   cambia es cuanto grita.
   El diagnostico es exacto: un desgarro grande se lee como filtro de
   aplicacion, y esta casa vende lo contrario (§7 — la sobriedad es lo
   caro). Una falla de señal de verdad es breve y pequeña. */
@keyframes panel-falla {
  0%   { translate: 0 0;      opacity: .50; filter: none; }
  9%   { translate: -5.4px 0; opacity: .644; filter: saturate(1.48); }
  18%  { translate: 4.2px 0;  opacity: .428; filter: none; }
  27%  { translate: -2.4px .6px; opacity: .596; filter: saturate(1.3); }
  38%  { translate: 3.6px 0;  opacity: .404; filter: none; }
  49%  { translate: -1.2px 0; opacity: .56;  filter: none; }
  61%  { translate: 1.8px 0;  opacity: .464; filter: saturate(1.18); }
  74%  { translate: -.6px 0;  opacity: .524; filter: none; }
  100% { translate: 0 0;      opacity: .50; filter: none; }
}
/* Se repite `panel-respira` porque `animation` es UNA propiedad: nombrar
   aqui solo la falla apagaria el paseo de la imagen. La revelacion no hace
   falta — dura medio segundo y esto llega a los dos. */
.panel-tarjeta.panel-falla:not(.lejos) .panel-cuadro::before {
  animation: panel-respira 13s ease-in-out infinite alternate,
             panel-falla .46s linear;
}
@media (prefers-reduced-motion: reduce) {
  .panel-tarjeta.panel-falla:not(.lejos) .panel-cuadro::before {
    animation: panel-respira 13s ease-in-out infinite alternate;
  }
}

/*
  EL FINAL DE LA RONDA — el halo blanco (fundador, 2026-08-06).
  Un tope que no se anuncia no se lee como "se acabo": se lee como que la
  pantalla se trabo. Aqui el panel del frente da un resplandor y vuelve.

  ⚠️ BLANCO Y NO CIAN NI VERDE, y es §4: el cian es de Nix y el verde
  significa "salio bien". Ninguno de los dos puede querer decir "hasta
  aqui". El blanco es el halo por defecto, el que no promete nada.
  ⚠️ Tres sombras y ninguna es una nube (§4): filo pegado, halo corto,
  irradiacion que muere. Y dura 620 ms — es ESTADO, no decoracion, que es
  lo unico que lo salva de §7.
*/
/*
  EL AVISO DEL TOPE SE MUDO AL BORDE DE LA PANTALLA (fundador, 2026-08-06:
  *"la advertencia de limite no deberia ir en el panel, deberia ir en el
  borde de la pantalla y debe alumbrar y sentirse la advertencia cada vez
  que uno desee pasar"*).

  Era un halo alrededor de la tarjeta del frente, y decia lo que no es: la
  tarjeta no tiene la culpa de que la ronda se acabe. **El limite es de la
  pantalla, asi que se anuncia donde esta el limite** — misma familia que
  la falla de TV del block-PAN26: el efecto va donde vive su causa.
  (El aviso no se fue del producto: cambio de sitio. Con el se fueron sus
  keyframes y el `:not(.panel-tope)` que existia solo para dejarlo ganar.)

  ⚠️ SIN `mix-blend-mode`, Y NO POR MIEDO: es que no sirve. "Alumbrar" es
  SUMAR luz, y en Cristal Perlado no hay margen para sumar —blanco sobre
  #EDEFF4 da 1,15 de contraste, o sea nada—. Por eso el tono sale de
  `--tope-rgb`, la unica ficha de la casa que cambia de signo: luz en el
  oscuro (20,02), sombra en el claro (17,19). De regalo, sin blend no hay
  Backdrop Root que vigilar.
*/
.paneles-borde {
  position: absolute;
  inset: 0;
  /* Sobre todo lo de la vitrina. No puede pasarle por encima al vuelo de
     Nix aunque el numero sea mayor: vive DENTRO de `.paneles` (z-index 30),
     y un hijo nunca se sale del apilamiento de su padre. */
  z-index: 60;
  pointer-events: none;     /* el dedo es del riel, siempre */
}
.paneles-borde::before,
.paneles-borde::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 42px;
  opacity: 0;
}
/* Pegadas a su canto y muriendo hacia adentro: una luz que toca el borde,
   no una barra dibujada sobre el. */
.paneles-borde::before {
  left: 0;
  background: linear-gradient(to right,
    rgba(var(--tope-rgb), .55) 0%,
    rgba(var(--tope-rgb), .16) 45%,
    rgba(var(--tope-rgb), 0) 100%);
}
.paneles-borde::after {
  right: 0;
  background: linear-gradient(to left,
    rgba(var(--tope-rgb), .55) 0%,
    rgba(var(--tope-rgb), .16) 45%,
    rgba(var(--tope-rgb), 0) 100%);
}
/* Entra de golpe y se va despacio: un aviso llega, no aparece. */
@keyframes tope-borde {
  0%   { opacity: 0; }
  12%  { opacity: 1; }
  100% { opacity: 0; }
}
.paneles-borde.avisa-izq::before,
.paneles-borde.avisa-der::after {
  animation: tope-borde .62s ease-out;
}
@media (prefers-reduced-motion: reduce) {
  .paneles-borde.avisa-izq::before,
  .paneles-borde.avisa-der::after { animation: none; }
}

/*
  ⚠️ EL BORDE DEL FRENTE ES BLANCO, NO CIAN (fundador, 2026-08-07). Su
  maqueta lo tiene en `border-white/20` y esta regla se lo estaba pisando
  por especificidad —`:not():not()` le gana a `.panel-tarjeta` a secas—,
  asi que el fondo salia bien y el contorno no. Cazado a maquina.

  EL CIAN NO SE PIERDE: SE GANA UN SIGNIFICADO. Antes lo llevaba SIEMPRE el
  panel del frente, o sea que no distinguia nada. Ahora aparece cuando Nix
  aterriza y lo enciende (`.panel-encendido`), que es el unico momento en
  que esta vitrina tiene algo que decir con luz. §6 pedia que el borde
  fuera luz y no linea; sigue siendolo, solo que cuando toca.
  La luz de Nix en reposo la cuentan el resplandor de la esquina y el halo
  de la medalla, que son de la misma familia y no compiten con el texto.
*/
.panel-tarjeta:not(.lejos):not(.panel-encendido) {
  border-color: rgba(255, 255, 255, .20);
  /* Una sola sombra, la de la maqueta (`0 30px 70px rgba(0,0,0,.8)`), que
     es lo que despega la tarjeta de sus vecinas. */
  box-shadow: 0 22px 52px rgba(0, 0, 0, .62);
}


/*
  AQUI VIVIA LA CINTA — la barra de arriba que nombraba la plataforma.
  Borrada el 2026-08-06 con la palabra del fundador nombrando su blanco:
  *"quitar la barra del borde superior de los paneles, se siente
  redundante"*. Y lo era, medido: en 6 de los 9 paneles repetia el nombre
  que el HUD ya da arriba. Lo que la reemplaza no hubo que construirlo —
  arriba el icono y el nombre, abajo el destino: eso es el HUD del PAN8.
  Lapida con el CSS entero, por si vuelve:
  backups/2026-08-06/borrado-cinta-plataforma.md
*/

/*
  ================================================================
  EL HUD DEL TAMBOR — los textos fuera de la tarjeta (2026-08-06)
  ================================================================
  Fundador: *"dejemos los textos fuera de la tarjeta y coloquemos todo
  arriba y abajo, con tipografia como la del escaneo, eso nos da mas
  Jarvis"*. Nacio de un diagnostico suyo que es correcto: *"tanta cosa
  junta mata premium"*.
  Nada se borro — el icono, el nombre y el destino se MUDARON. El visitante
  los sigue viendo; cambiaron de sitio, no de existencia.

  ⚠️ EXCEPCION NOMBRADA A §5, y se anota porque una regla sin su excepcion
  escrita se aplica sola. §5 dice: *"la monoespaciada es solo para numeros
  que son datos... jamas para prosa ni para etiquetas"*. Aqui la lleva
  tambien el NOMBRE del panel, que es una etiqueta.
  El porque: es la voz del HUD del escaneo (`.telemetry-text`), y el
  fundador la pidio por eso mismo — para que el tambor se sienta
  instrumental, no decorativo. El destino si es un dato y no necesita
  excepcion; el nombre la usa prestada para que los dos suenen igual.
  Alcance: SOLO estos dos renglones de la vitrina. No abre la puerta a
  ninguna otra etiqueta monoespaciada de la casa.
*/
.paneles-hud {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  /* Copiado del escaneo, no "inspirado" en el: `.telemetry-text` va en
     mono a 10 px con 1 px de espaciado. La primera version le puso 1,4 y
     colores apagados, y sobre el modo claro desaparecia — el fundador dijo
     con razon que me habia ido por otro lado. */
  /*
    🔴 SALIO DE LA MONOESPACIADA (2026-08-09). Aqui se escribe el NOMBRE DE
    LA HERRAMIENTA —"YouTube", "WhatsApp"—, o sea prosa, y §5 lo prohibe
    expresamente: *"jamas para prosa ni para etiquetas"*. El comentario de
    arriba explica de donde salio (copiado del escaneo, `.telemetry-text`) y
    ese origen es justo el problema: la telemetria SI son datos; el nombre de
    una herramienta no.
    El espaciado de 1 px se queda: eso no es de la mono, es del rotulo.
  */
  font-size: 13px;              /* terciario · §5 */
  font-weight: 500;             /* etiquetas · §5 */
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--texto-2);
  /* Alto reservado SIEMPRE, con texto o sin el: si creciera y encogiera al
     girar, el tambor entero daria un brinco en cada panel. */
  min-height: 20px;
  padding: 0 16px;
  text-align: center;
}
/*
  EL HUD DE ARRIBA SE VISTE COMO LA PILDORA DE LA MAQUETA (fundador,
  2026-08-07). Su diseño tiene ahi una pastilla de vidrio con el icono en
  cian y el nombre en minuscula, no un rotulo de telemetria en mayuscula
  monoespaciada. No se quita nada: dice lo mismo, vestido como el lo dibujo.
  `inline-flex` + `margin auto` porque una pildora se ajusta a su texto; el
  contenedor de antes ocupaba el ancho entero y por eso no se leia como
  pastilla sino como titulo de seccion.
*/
/*
  LA PILDORA SUBE 10 PX Y SE AMARRA AL PANEL (fundador, 2026-08-07).
  Dos pedidos suyos en una frase: *"subir el boton que nombra el panel 10
  pixeles"* y *"que ese boton se amarre al panel, que cuando se deslice se
  corran las dos cosas"*.

  ⚠️ SUBE CON `top`, NO CON `margin-top`, Y ESA ES LA DIFERENCIA ENTERA.
  Un `margin-top: -10px` sube la pildora Y ARRASTRA EL TAMBOR CON ELLA: la
  caja de maquetacion se encoge y todo lo de abajo la sigue. `position:
  relative` deja la caja donde esta —el tambor no se entera— y solo mueve lo
  que se pinta. Medido antes: la barra de «Volver» termina en 58 y la
  pildora empezaba en 137, o sea 79 px de aire; con los 10 quedan 69. No
  choca con nada.

  ⚠️ Y EL VERTICAL VIVE AQUI PORQUE EL HORIZONTAL LO ESCRIBE app.js.
  El amarre al panel se hace con `transform: translateX()` en cada
  fotograma; si los 10 px fueran parte de ese transform, la primera vez que
  el JS escribiera uno los borraria sin decir nada. La hoja manda en el eje
  vertical, el JS en el horizontal, y no se pisan.
*/
.paneles-hud.arriba {
  position: relative;
  top: -10px;
  margin: 0 auto 14px;
  width: fit-content;
  max-width: 86%;
  gap: 8px;                                  /* `gap-2` */
  padding: 5px 14px;                         /* `px-3.5 py-1` */
  border-radius: var(--r-pildora, 999px);    /* `rounded-full` */
  background: rgba(255, 255, 255, .10);      /* `bg-white/10` */
  border: 1px solid rgba(255, 255, 255, .15);/* `border-white/15` */
  backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  -webkit-backdrop-filter: blur(var(--vidrio)) saturate(var(--sat));
  box-shadow: 0 8px 22px rgba(0, 0, 0, .38); /* `shadow-lg` */
  /* Minuscula y sin espaciado de telemetria: es un nombre, no un codigo. */
  font-family: inherit;
  /* 13, era 12 (§5, la Ley · 2026-08-11). */
  font-size: var(--tam-terciario);                           /* `text-xs` */
  font-weight: 500;                          /* `font-medium` */
  letter-spacing: .2px;                      /* `tracking-wide` */
  text-transform: none;
  color: var(--texto);                       /* `text-white` */
}
.paneles-hud.arriba .hud-icono { width: 14px; height: 14px; }  /* `w-3.5` */
.paneles-hud.arriba .hud-icono svg { width: 100%; height: 100%; }
.paneles-hud.abajo  { margin-top: 14px; }

.hud-icono {
  width: 17px;
  height: 17px;
  flex: none;
  /*
    CIAN BRILLANTE, EL MISMO DE LOS CUATRO CTA DE LA CAJA (fundador,
    2026-08-06: *"la intensidad en el ambiente blanco deberia ser la misma
    en todo el ecosistema: si aparece el cian que sea muy brillante"*).
    Lo cazo con dos capturas suyas, y era cierto: los iconos de la Caja
    nunca bajaron el tono y los de la vitrina si, asi que en la misma
    pantalla habia DOS cianes.

    ⚠️ AQUI EL BRILLANTE GANA AUNQUE EL CONTRASTE DIGA LO CONTRARIO, y por
    eso el numero no manda solo: #00F0FF sobre el claro mide 1,22 de
    luminancia —"ilegible" para un medidor— y sin embargo se ve, porque un
    trazo de 1,6 sobre 17 px se lee por el TONO y no por el brillo. Es lo
    que llevan haciendo los cuatro CTA desde el primer dia sin que nadie se
    quejara. La medicion dice donde mirar; no reemplaza mirar.
    ⚠️ Y NO SE PUEDE GENERALIZAR A TODO LO CIAN. Un icono tiene cuerpo; un
    corchete de 1 px y un resplandor difuso no, y ahi el brillante SI
    desaparece (medido: 1,03-1,15 en las cuatro alfas del haz). El texto
    tampoco: `--hud-destino` se queda bajado. La regla completa, en
    graphic_system.md §1.
  */
  color: var(--nix-cyan);
  display: inline-flex;
}
.hud-icono svg { width: 100%; height: 100%; }
.hud-icono:empty { display: none; }

/* El nombre lo escribe el dueño: es lo unico suyo en toda la pantalla.
   Va en `--texto` pleno, no en un gris: en el escaneo la primera linea se
   LEE, y sobre el modo claro un gris apagado se borra. */
.hud-titulo {
  color: var(--texto);
  font-weight: 500;
  /* Un nombre largo no puede empujar al icono fuera ni partir la linea. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/*
  EL DESTINO VA EN CIAN, COMO LA SEGUNDA LINEA DEL ESCANEO.
  El HUD del arranque tiene dos renglones y esa es toda su gracia:
  "READING IDBOX SIGNATURE..." en gris y **"ID VERIFIED // LINK SECURE" en
  cian**. Es la voz del sistema confirmando. Aqui pasa lo mismo — arriba lo
  que es, abajo a donde lleva y comprobado.
  ⚠️ §1b dice "el cian solo donde Nix habla". Esto ES el sistema hablando,
  la misma voz del escaneo, no decoracion: se apaga con el panel y solo
  existe mientras la vitrina esta abierta. `--nix-texto` y no `--nix-cyan`
  porque la ficha ya trae su version bajada para el modo claro (§1).
  El destino es ademas un DATO, asi que la monoespaciada es su sitio por §5
  sin necesitar la excepcion que si usa el nombre.
*/
.hud-destino {
  color: var(--nix-texto);
  letter-spacing: 1px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}

/* (Aqui vivian `.panel-icono`, el `h3` y `.panel-destino` de la tarjeta.
   El 2026-08-06 su contenido se mudo al HUD de arriba y abajo, asi que
   estas reglas se quedaron sin elemento: limpiar detras. La pinta que
   heredaron —el cian del icono, la escala de §5 en el destino— vive ahora
   en `.hud-icono` y `.hud-destino`.) */
/*
  LOS DEL FONDO PIERDEN EL VIDRIO — la ley de §5 hecha regla (2026-08-06).
  El tambor pone hasta cinco paneles en pantalla contra los dos de la fila
  plana, y cada `backdrop-filter` se recalcula contra el video de la camara
  EN CADA FOTOGRAMA. Los de atras miden 36-50 px y van girados mas de medio
  angulo recto: a ese tamaño un desenfoque y un fondo liso se ven igual.
  Se paga vidrio solo donde se lee — el frente y sus dos vecinas.
  El color sale de la misma ficha, asi que no hay dos verdades: cambia
  `--panel` y cambian los dos.
*/
.panel-tarjeta.lejos {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  /*
    ⚠️ `--panel` Y NO `--panel-solido`, Y ESE ERROR SE VIO EN EL PRODUCTO.
    `--panel-solido` vale casi negro en Obsidiana pero BLANCO PURO en
    Cristal Perlado, asi que en modo claro los paneles del fondo salian mas
    brillantes que el del frente: el efecto entero al reves, reportado por
    el fundador con dos capturas. La leccion es de §0 —un componente nombra
    una ficha, no un color— con una vuelta mas: **una ficha tambien puede
    significar lo contrario en el otro modo**. Antes de usar una, mirar
    cuanto vale en los DOS.
  */
  background: var(--panel);
  /* Sin filo de luz: el filo es la firma del vidrio (§2) y estos ya no lo
     llevan. Un borde parejo los deja atras sin fingir lo que no son. */
  border-top-color: var(--linea);
}

/*
  LO QUE ESTA AL FONDO ESTA EN SOMBRA — y por eso el del frente es el unico
  con luz (fundador, 2026-08-06: *"el panel con luz debe ser el que esta de
  frente y los vecinos apagados"*).

  ⚠️ NO SE HACE CON `opacity`, y ese fue el intento fallido: bajar la
  opacidad vuelve la tarjeta TRANSPARENTE, no oscura, asi que sobre un
  fondo claro se aclara todavia mas. Una sombra de verdad apaga igual en
  los dos modos, que es lo que hace un mostrador real: lo del fondo esta
  mas oscuro, haya la luz que haya en el salon.
  Va en una capa aparte y no en el fondo para que tambien apague el icono y
  el texto: la tarjeta entera entra en sombra, no solo su superficie.
*/
.panel-tarjeta.lejos::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: rgba(3, 5, 9, .34);
  pointer-events: none;
}

/*
  EL REFLEJO — el que cuelga delante del primero y detras del ultimo para
  que el tambor no enseñe un diente vacio. Se apaga un escalon mas que un
  panel del fondo: tiene que leerse como la continuacion del cilindro, no
  como una tarjeta a la que se puede llegar. Nunca recibe el toque ni el
  tic; el dedo topa donde topaba.
*/
.panel-tarjeta.reflejo::after { background: rgba(3, 5, 9, .52); }

/* Apagada: existe pero aun no lleva a ningun sitio. El mismo trato que la
   tercera tarjeta sin url — se ve, avisa, y jamas un enlace muerto. */
.panel-tarjeta.pronto { opacity: .55; }
/* Un panel sin destino se atenua entero, pero SU SIMBOLO SE QUEDA CIAN
   (fundador, 2026-08-06: *"los simbolos todos cian"*). El icono es la
   identidad del panel y no cambia porque el enlace todavia no exista; quien
   dice que falta es el renglon de abajo, con todas sus letras. */
.paneles-hud.pronto { opacity: .62; }

/*
  EL PANEL ENCENDIDO — el destello de cuando Nix aterriza en el.
  ⚠️ NI UNA GOTA DE `transform` AQUI. El transform de estas tarjetas es lo
  que las sostiene en el cilindro: el `scale(1.02)` del destello de la Caja
  las arrancaria de su sitio a mitad del vuelo. Borde y sombra bastan — y el
  verde es estado (§4), 250 ms y se va.
*/
.panel-encendido {
  border-color: var(--accent-green) !important;
  box-shadow: var(--destello-verde);
}

/* (Aqui vivia .paneles-pie, la pinta del letrero "Desliza y toca para
   abrir". Se fue con su nodo el 2026-08-06 — una regla sin elemento es
   limpiar detras. Respaldo completo con su CSS en
   backups/2026-08-06/borrado-hint-paneles.md.) */

/*
  LA VITRINA SE PRESENCIA, NO APARECE (2026-08-06). §5 lo pide desde el
  primer dia para el arranque —"no carga, se presencia"— y esta pantalla
  entraba de golpe. Materializarse hace dos cosas a la vez: da el momento
  Jarvis que pidio el fundador, y ENSEÑA que las tarjetas son objetos que
  se mueven, que es lo que el letrero venia a decir con palabras.

  ⚠️ SE ANIMA EL CUARTO, NO LAS TARJETAS, y es a proposito: el JS reescribe
  el `transform` de cada tarjeta en cada fotograma de scroll (la escala y el
  giro), asi que cualquier animacion sobre ellas se la come el primer
  repintado. El padre no lo toca nadie, y su transform se compone con el de
  los hijos gratis.
  ⚠️ SIN `forwards`: si la animacion no corriera —navegador viejo, motor
  ocupado— el estado natural del cuarto ya es el bueno. Se degrada a
  aparecer de golpe, que es lo que hacia ayer.

  ⚠️ Y SOLO OPACIDAD: NADA DE `scale` AQUI. Este cuarto es el ANCESTRO de
  la pista que encaja, y WebKit cachea los puntos de encaje: escalar al
  padre mientras el hijo calcula donde encajar es pedirle al iPhone que se
  desalinee justo en el primer deslizar. La escala se la queda la cabecera,
  que no tiene scroll debajo. Cuando el radio de daño es la pantalla que un
  cliente le muestra a un prospecto, gana la respuesta aburrida.
*/
@keyframes panelesEntra {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes panelesEntraAlto {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.paneles:not([hidden]) {
  animation: panelesEntra .34s ease-out;
}
.paneles:not([hidden]) .paneles-top {
  animation: panelesEntraAlto .5s cubic-bezier(.16, .9, .3, 1);
}

@media (prefers-reduced-motion: reduce) {
  .panel-tarjeta { transition: none; }
  /* Quien pide menos movimiento no recibe la materializacion: el cuarto
     aparece y ya. La informacion no estaba en el movimiento — la vecina
     asomada sigue diciendo lo mismo, quieta. */
  .paneles:not([hidden]),
  .paneles:not([hidden]) .paneles-top { animation: none; }
}

/*
  ================================================================
  ⚠️ EL PIE SE CAIA DE LA PANTALLA — y no habia scroll para buscarlo
  ================================================================
  Reportado por el fundador el 2026-08-06 desde su celular: *"se nos
  borraron los botones de la parte de abajo, no aparecen"*.

  **NO LO CAUSO LA VITRINA, y eso se midio ANTES de tocar nada:** pasaba
  igual con Paneles cerrado, en la Caja de siempre. Llevaba ahi.

  LA CUENTA, medida en produccion: la Caja pide **638 px** de alto y arranca
  26 px mas abajo, asi que **por debajo de 664 px de pantalla util el pie
  sale del borde**. Y `scrollHeight` mide lo mismo que la ventana — o sea
  que **no hay scroll que lo alcance: no esta escondido, esta fuera**.
  Un iPhone SE tiene 667: queda a TRES pixeles. Y en Android la barra del
  navegador se come entre 50 y 60 px en cuanto aparece, asi que un telefono
  de 700 cae a 640 y pierde el pie a media feria. **Eso es AR y TURBO
  desapareciendo delante de un prospecto.**

  LA CURA VA DONDE ESTA EL PROBLEMA Y EN NINGUN SITIO MAS: las piezas de la
  Caja llevan 128 px de aire entre ellas, y en una pantalla baja ese aire
  vale menos que los botones. Aqui se aprieta a 54 y se recuperan **74 px**.
  Por encima de 700 px no cambia ni un pixel: lo que el fundador aprobo
  sigue igual donde ya cabia.
  *Un margen es negociable; un boton que no se ve, no.*

  ⚠️⚠️ Y VA AL FINAL DE LA HOJA A PROPOSITO. La primera version quedo junto
  a `.stage`, arriba, Y NO HIZO ABSOLUTAMENTE NADA: **una media query no
  suma especificidad**, asi que sus reglas empataban con los margenes
  originales —que viven mas abajo— y ganaba el que viene despues. No dio
  error ninguno: simplemente el defecto seguia igual. Lo caza medir el alto
  de la Caja despues de tocar, no leer el CSS y darlo por hecho.
*/
@media (max-height: 700px) {
  /* ⚠️ Y ESTE ES EL QUE DE VERDAD MANDA. Apretar los margenes recuperaba
     58 px y la firma seguia saliendose por 6: el `min-height: 580px` del
     escenario es un SUELO, asi que la Caja no podia encoger mas por mucho
     aire que se le quitara. Medido — sin esta linea el apreton extra no
     movia ni un pixel. Ese 580 tiene sentido en una pantalla normal (evita
     que la Caja se vea raquitica); en una de 600 es justamente lo que tira
     el pie fuera. */
  .stage { min-height: 0; }
  /*
    ⚠️ Y LA VITRINA LE RESERVA SU SITIO AL PIE. Este es el mismo defecto
    que tuvo la flecha con TURBO, y ahora se entiende de raiz: **la vitrina
    y el pie viven en CAPAS DISTINTAS** —Paneles flota sobre la Caja—, asi
    que "estar en el flujo" no impide que se pisen; solo impide que se
    pisen dentro del MISMO flujo. La vitrina se centraba en la pantalla
    entera como si abajo no hubiera nada, y abajo hay 83 px de pie.
    Apretar el margen no alcanzaba: de 22 a 6 gano 16 px y seguia montada
    4. Reservar el sitio lo arregla de una vez y sin numeros a mano en el
    boton.
    Solo en pantallas bajas: por encima de 700 sobran 32 px medidos y el
    tambor se queda exactamente donde el fundador lo aprobo.
  */
  .paneles { padding-bottom: 92px; padding-top: 76px; }
  .paneles-guardar { margin-top: 10px; }
  .greet { margin-bottom: 4px; }
  .owner { margin-bottom: 8px; }
  .nixrow { margin-bottom: 8px; }
  .grid { margin-bottom: 6px; }
  .terminal-line { margin-bottom: 4px; }
  .cta-cards-btn { margin-bottom: 6px; }
  .privacidad-link { margin-top: 4px; }
}

/* =====================================================================
   LA CORTINA — idea del fundador (2026-08-10)

   "Es preferible ver llenarse una barra un segundo anunciando que va a
   cargar algo, que ver un fallo que grita «esto está mal construido»."

   ⚠️ UNA CORTINA NO ES UNA SALIDA ANIMADA. Una salida despide la pantalla y
   deja el hueco a la vista —se intento tres veces y las tres se vio—. Una
   cortina TAPA: el cambio ocurre detras y lo que el ojo sigue es la cortina.

   ⚠️ SE RETIRA CON `transform`, JAMAS CON `opacity` (§7g): debajo hay cuatro
   tarjetas de vidrio, y fundir algo por encima de ellas obliga a recomponer
   sus desenfoques en cada fotograma. Eso destella — y seria absurdo que la
   pieza que viene a quitar un defecto trajera otro.
   ===================================================================== */
#cortina { display: none; }

html.con-cortina #cortina {
  display: flex;
  position: fixed;
  inset: 0;
  z-index: 90;                 /* por encima de todo, incluso del lienzo (50) */
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  background: var(--fondo-luz), var(--fondo);
  transition: transform .34s cubic-bezier(.16, .9, .3, 1);
}
/* Se va hacia arriba: la Caja queda debajo, ya montada y quieta. */
html.con-cortina #cortina.abierta { transform: translateY(-100%); }

.cortina-marca {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--sans);
  font-size: var(--tam-secundario);
  font-weight: 500;
  color: var(--texto-suave);
  letter-spacing: .01em;
}
/* El nucleo de Nix, el mismo de toda la casa: quien te lleva es el. */
.cortina-nucleo {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--nix-nucleo);
  box-shadow: 0 0 9px 2px rgba(var(--nix-halo-rgb), .7);
  animation: cortinaLate 1.1s ease-in-out infinite;
}
@keyframes cortinaLate {
  0%, 100% { opacity: .75; }
  50%      { opacity: 1; }
}

/* La barra. Se llena con `transform`, que es lo barato: animar el ancho
   obligaria a recalcular la maqueta en cada fotograma. */
.cortina-barra {
  width: 132px; height: 2px;
  border-radius: var(--r-pildora);
  background: rgba(var(--toque-rgb), .14);
  overflow: hidden;
}
.cortina-barra i {
  display: block; height: 100%; width: 100%;
  border-radius: inherit;
  background: var(--nix-cyan);
  transform-origin: left center;
  transform: scaleX(0);
  animation: cortinaLlena .62s cubic-bezier(.3, .7, .4, 1) forwards;
}
@keyframes cortinaLlena {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

@media (prefers-reduced-motion: reduce) {
  html.con-cortina #cortina { transition: none; }
  .cortina-nucleo, .cortina-barra i { animation: none; }
  .cortina-barra i { transform: scaleX(1); }
}

/*
  ═══ EL POZO DE ERMINE, EN TODAS LAS CAJAS (fundador, 2026-10-13) ═══════════
  El suelo de la Caja pasa al #131313 de ERMINE (graphic_system §10.10) y las
  tres luces siguen encima: solo cambia el color de debajo, por eso va
  `background-color` y no `background`. La cortina que llega desde la Cabina
  va con el, porque abre sobre este mismo suelo.
  🔴 EL ESCANEO CONSERVA SU NEGRO (*"Conserva el negro del escaneo"*): #s0 y #s1
  siguen en `--void` y no se nombran aqui a proposito.
*/
/* 🔴 SOLO EN LA PIEL OSCURA (arreglo, 2026-10-13, el fundador con su captura: «se desconfiguro la caja»). La piel
   automatica pasa la Caja a Perlado (clara) cuando hay luz, y este suelo no lo sabia: quedaba oscuro con la tinta
   oscura de Perlado encima, y el nombre no se veia. En Perlado el suelo vuelve a ser el claro de siempre, como las
   fichas del tono en tokens.css, que ya llevaban este mismo `:not`. */
html[data-pozo="ermine"]:not([data-modo="perlado"]) body { background-color: #131313; }
/* La cortina «Tu IDBox», en cambio, va en las DOS pieles (fundador, 2026-10-18: «la cortina de la animación también»):
   lleva .obsidiana, su tinta es la clara en cualquier piel, y su suelo es el de la casa, igual al de la cortina de IDBox. */
html[data-pozo="ermine"].con-cortina #cortina { background-color: #131313; }
/* Y su tinta: .obsidiana les cambia las fichas, pero el `color` que heredan ya viene resuelto del cuerpo (oscuro en
   Perlado). Lo que no traiga su propio color toma el claro de su ficha, como en la piel oscura. */
#s0.obsidiana, #s1.obsidiana, #cortina.obsidiana { color: var(--texto); }

/* EL RECORRIDO DE BIENVENIDA (2026-10-13): sus estilos viven dentro de recorrido.js, que tambien los usa la Cabina. */
