/* =============================================================================
   La partida: el lienzo a pantalla completa y el HUD montado encima.
   Solo asoma lo imprescindible: la casa a oscuras es lo que importa.
============================================================================= */

.game {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: #05040c;
}
.game[hidden] { display: none; }

#game-canvas { position: absolute; inset: 0; display: grid; place-items: center; }
#game-canvas canvas { display: block; image-rendering: pixelated; }

.hud {
  position: absolute;
  inset: 0;
  pointer-events: none;
  padding: 20px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--gap);
  font-family: var(--face-ui);
}

/* En pantallas grandes, el HUD entero crece con ellas. Un panel de 330 px se
   lee de sobra en un portátil y se queda en un sello en un monitor de 27, y no
   hay ganas de mantener dos juegos de medidas: `zoom` estira lo que ya está
   medido, tipografías y sombras incluidas. */
@media (min-width: 1700px) { .hud { zoom: 1.2; } }
@media (min-width: 2300px) { .hud { zoom: 1.45; } }

/* Arriba: objetivos a la izquierda, cacharros en medio, cordura a la derecha.
   Con tres columnas la barra de cacharros queda centrada de verdad y no se
   mueve de sitio porque a alguien se le alargue el nombre.

   Y CADA UNO EN SU COLUMNA, ESCRITA. Iban por orden, con el último pegado a la
   derecha, y eso se rompe en cuanto uno de los tres no está: el navegador le
   pone `display: none` a lo que lleva `hidden` —eso no lo tumba una regla que
   solo toca `visibility`— así que la columna desaparecía y los otros dos se
   corrían. Se veía en la noche de prácticas, que es la única vez que se
   esconden los objetivos con la cordura puesta: la cordura se plantaba en el
   centro de la pantalla. */
.hud-top {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  gap: var(--gap);
}
.obj { grid-column: 1; }
.hb { grid-column: 2; }
.cor { grid-column: 3; justify-self: end; }

.hud-bottom {
  display: grid;
  grid-template-columns: 1fr minmax(0, 2fr) 1fr;
  align-items: end;
  gap: var(--gap);
}
.hud-centro { display: grid; gap: 12px; justify-self: center; width: min(760px, 100%); }
.hud-hueco { min-height: 1px; }
.hud-net { display: flex; align-items: center; gap: 8px; }

/* =============================================================================
   LA BARRA DE CACHARROS (arriba, en medio)
   Tres huecos con su número. El que llevas en la mano se enciende, y su
   pantalla sale abajo a la derecha.
============================================================================= */
/* `hidden` tiene que ganarle al `display` de la clase: si no, esconder la
   barra en el cuartel no la esconde. */
.hb[hidden] { display: none; }
.hb { display: flex; gap: 12px; pointer-events: auto; }
.hb-hueco {
  position: relative;
  width: 100px;
  height: 100px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  background: rgba(5, 4, 12, .72);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .14);
  transition: box-shadow 140ms ease, background 140ms ease, transform 140ms var(--ease-pop);
}
.hb-hueco.vacio { background: rgba(5, 4, 12, .45); }
.hb-hueco.on {
  background: rgba(168, 244, 37, .16);
  box-shadow: inset 0 0 0 2px var(--lime), 0 0 20px rgba(168, 244, 37, .3);
  transform: translateY(2px);
}
.hb-tecla {
  position: absolute;
  top: 5px;
  left: 10px;
  font-family: var(--face-pixel);
  font-size: 20px;
  color: rgba(255, 255, 255, .45);
}
.hb-hueco.on .hb-tecla { color: var(--lime); }

/* El piloto de lo que llevas encendido y la cuenta de lo que se gasta. */
.hb-on {
  position: absolute;
  top: 7px;
  right: 7px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #46d34a;
  box-shadow: 0 0 10px rgba(70, 211, 74, .9);
  animation: hb-latido 1.2s ease-in-out infinite;
}
@keyframes hb-latido { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }
.hb-cargas {
  position: absolute;
  right: 6px;
  bottom: 4px;
  font-family: var(--face-pixel);
  font-size: 17px;
  color: rgba(255, 255, 255, .8);
  text-shadow: 0 2px 0 rgba(0, 0, 0, .8);
}

.icono-obj {
  display: block;
  background-repeat: no-repeat;
  /* SIN `pixelated`. Lo llevaba cuando los cacharros estaban dibujados píxel a
     píxel y encajaba; la lámina pintada a mano viene al doble de tamaño y se
     enseña reducida, así que a lo que obliga `pixelated` es a tirar píxeles de
     en medio: los cantos salen dentados y el dibujo, sucio. */
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, .5));
}

/* =============================================================================
   LOS OBJETIVOS (arriba, izquierda)
============================================================================= */
.obj {
  justify-self: start;
  min-width: 330px;
  max-width: 430px;
  padding: 15px 20px 17px;
  border-radius: 16px;
  background: rgba(5, 4, 12, .72);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .12);
}
/* Escondidos, pero SIN quitarlos de la rejilla: si desaparecen del todo, sus
   vecinos se van al hueco que dejan. Hace falta devolverles el `display` a mano:
   `hidden` lo pone a `none` por su cuenta y una regla que solo toca la
   visibilidad no lo tumba. Con las columnas escritas arriba esto ya no puede
   descolocar a nadie, pero sigue haciendo falta para que el hueco se guarde. */
.obj[hidden], .cor[hidden] { visibility: hidden; display: block; }
.ap[hidden] { display: none; }
.obj-titulo, .cor-titulo {
  margin: 0 0 11px;
  font-family: var(--face-pixel);
  font-size: 23px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--lime);
}
.obj-lista { margin: 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.obj-item {
  display: flex;
  gap: 10px;
  font-size: 17px;
  line-height: 1.3;
  color: rgba(255, 255, 255, .8);
}
.obj-marca { color: rgba(255, 255, 255, .4); }
.obj-item.hecho { color: rgba(255, 255, 255, .42); text-decoration: line-through; }
.obj-item.hecho .obj-marca { color: var(--lime); text-decoration: none; }


/* =============================================================================
   LA CINTA DE LA NOCHE DE PRACTICAS (arriba, izquierda)
   Ocupa el sitio de los objetivos: esa noche los objetivos son estos pasos.
   Una linea cada vez, y la barra de arriba lleva la cuenta.

   ES EL CARTEL MAS ALTO DE LA PANTALLA a proposito. Los objetivos son ambiente
   -estan ahi por si los miras-; esto es lo unico que te esta hablando, y en una
   casa a oscuras con cacharros pitando hay que ganarle la vista a todo lo demas.
============================================================================= */
.prac {
  /* FIJA Y POR ENCIMA DEL CAMION Y DE LA LIBRETA (60 y 62), pero por debajo de
     la demo de los cacharros (500), que es la que se pega al cursor. Colgada del
     HUD desaparecia justo en los dos pasos que hay que leer con un panel
     delante. Las medidas son las de la esquina del HUD: mismo hueco al borde. */
  position: fixed;
  left: 20px;
  top: 20px;
  z-index: 400;
  pointer-events: none;
  width: min(468px, calc(100vw - 40px));
  padding: 17px 22px 20px;
  border-radius: 18px;
  /* CASI OPACA, y no traslucida como los objetivos. Aquellos viven sobre la casa
     a oscuras y ahi un velo basta; esta se pone encima del camion y de la
     libreta, que son paneles claros, y con un velo se leian las dos cosas a la
     vez. Lo unico que tapa mientras hay un panel delante es el boton de volver
     al cuartel, que es justo el que no se viene a pulsar durante el tutorial. */
  background: linear-gradient(180deg, rgba(19, 13, 38, .97), rgba(9, 7, 20, .97));
  backdrop-filter: blur(6px);
  /* El marco es de la marca y grueso: es lo que lo separa de un panel mas. Y
     despega del fondo con sombra de verdad -desplazada y difuminada- mas un halo
     bajo, que a oscuras es lo que hace que parezca encendido y no pegado. */
  box-shadow:
    inset 0 0 0 2px rgba(168, 244, 37, .55),
    0 18px 44px rgba(0, 0, 0, .6),
    0 0 26px rgba(168, 244, 37, .12);
  transition: box-shadow 320ms var(--ease-out);
}
.prac[hidden] { display: none; }

/* El HUD entero crece en pantallas grandes y esto va por fuera, asi que se le
   aplica el mismo estiron para que no se quede pequeno al lado de sus vecinos. */
@media (min-width: 1700px) { .prac { zoom: 1.2; } }
@media (min-width: 2300px) { .prac { zoom: 1.45; } }

/* LOS DOS MOMENTOS DE LA CINTA.
   `nuevo` cuando hay paso nuevo: el marco se enciende y el cartel da un salto
   corto hacia delante. `no` cuando te topas con un candado: se sacude y se pone
   en rojo. Son las dos unicas veces que esta cosa se mueve. */
.prac[data-golpe="nuevo"] { animation: prac-nuevo 620ms var(--ease-out); }
@keyframes prac-nuevo {
  0% {
    transform: scale(.97);
    box-shadow:
      inset 0 0 0 2px var(--lime-soft),
      0 18px 44px rgba(0, 0, 0, .6),
      0 0 60px rgba(168, 244, 37, .55);
  }
  100% {
    transform: none;
    box-shadow:
      inset 0 0 0 2px rgba(168, 244, 37, .55),
      0 18px 44px rgba(0, 0, 0, .6),
      0 0 26px rgba(168, 244, 37, .12);
  }
}
.prac[data-golpe="no"] {
  animation: prac-no 520ms var(--ease-out);
  box-shadow:
    inset 0 0 0 2px var(--danger),
    0 18px 44px rgba(0, 0, 0, .6),
    0 0 34px rgba(255, 85, 102, .4);
}
@keyframes prac-no {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-9px); }
  32% { transform: translateX(7px); }
  50% { transform: translateX(-5px); }
  68% { transform: translateX(3px); }
  84% { transform: translateX(-2px); }
}

.prac-titulo {
  margin: 0 0 11px;
  font-family: var(--face-pixel);
  font-size: 25px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--lime);
}

/* --- La barra: un tramo por paso -------------------------------------------- */
.prac-tramos { display: flex; gap: 5px; margin-bottom: 15px; }
.prac-tramo {
  flex: 1;
  height: 6px;
  border-radius: 99px;
  background: rgba(255, 255, 255, .13);
  transition: background 320ms var(--ease-out);
}
.prac-tramo[data-on="si"] { background: var(--lime); }
/* EL DE AHORA LATE. En una barra de siete apagados hay que poder ver de un
   vistazo por donde vas sin ponerse a contar los encendidos. */
.prac-tramo[data-aqui="si"][data-on="no"] {
  background: rgba(168, 244, 37, .3);
  animation: prac-late 1900ms ease-in-out infinite;
}
/* Y LATE FLOJO, muy por debajo del lima de los hechos. En la primera versión
   subía hasta casi el color de un tramo cumplido y el que estabas haciendo
   parecía hecho: la barra decía uno más de la cuenta. */
@keyframes prac-late {
  0%, 100% { background: rgba(168, 244, 37, .22); }
  50% { background: rgba(168, 244, 37, .5); }
}
/* El que se acaba de encender da un golpe de luz y se apaga a su color. Es la
   unica recompensa que hay por haber hecho una cosa bien, asi que se ve. */
.prac-tramo[data-paso="prende"] { animation: prac-prende 520ms var(--ease-out); }
@keyframes prac-prende {
  0% { background: #fff; box-shadow: 0 0 14px rgba(168, 244, 37, .95); }
  100% { background: var(--lime); box-shadow: 0 0 0 rgba(168, 244, 37, 0); }
}

/* --- La linea de esta vez -------------------------------------------------- */
/* ALTURA MINIMA Y NO FIJA: mientras una linea sale y la otra entra hay un
   instante con las dos dentro, y sin esto el cartel pegaba un salto de alto
   justo cuando le estas mirando. */
.prac-hueco { min-height: 76px; }

.prac-linea { animation: prac-entra 380ms var(--ease-out) both; }
@keyframes prac-entra {
  from { opacity: 0; transform: translateY(14px); filter: blur(3px); }
  to { opacity: 1; transform: none; filter: blur(0); }
}

.prac-que {
  position: relative;
  margin: 0;
  font-size: 22px;
  font-weight: 600;
  line-height: 1.28;
  color: #fff;
}
.prac-pista {
  margin: 7px 0 0;
  font-size: 15px;
  line-height: 1.4;
  color: var(--ink-dim);
  transition: color 200ms linear;
}
/* Y cuando lo que dice es por que no te deja, lo dice en rojo y con mas peso: es
   la respuesta a algo que acabas de intentar, no una nota al pie. */
.prac-pista[data-mal] { color: #ff8a99; font-weight: 500; }

/* EL TACHON. La raya crece de izquierda a derecha sobre lo que acabas de hacer
   y despues la linea entera se va hacia arriba. Es el momento del cartel: sin
   el, los pasos se sustituyen sin mas y no se entera nadie de que ha acertado. */
.prac-linea[data-paso="hecho"] { animation: prac-sale 460ms var(--ease-out) forwards; }
.prac-linea[data-paso="hecho"] .prac-que::after {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 100%;
  height: 3px;
  border-radius: 3px;
  background: var(--lime);
  /* Crece con `scaleX` y no con `width`: es lo mismo de ver y no le pide al
     navegador que recalcule nada mientras corre. */
  transform-origin: left center;
  animation: prac-tacha 220ms var(--ease-out) forwards;
}
@keyframes prac-tacha { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes prac-sale {
  0%, 48% { opacity: 1; transform: none; }
  100% { opacity: 0; transform: translateY(-12px); }
}
.prac-linea[data-paso="hecho"] .prac-pista { opacity: 0; transition: opacity 180ms linear; }

/* =============================================================================
   EL FANTASMA DE LOS CONSEJOS (abajo, saliendo por la izquierda)
   Entra flotando, dice lo suyo y se va por donde vino. Vive fuera del HUD
   -colgado del `body`- porque tiene que verse tambien con el camion y la
   libreta delante, que tapan la pantalla entera.
============================================================================= */
.csj {
  position: fixed;
  /* A LA DERECHA DEL MINIMAPA, que manda en esa esquina: son 300 px y su hueco.
     Asi el fantasma parece que sale de detras de el. */
  left: 336px;
  /* POR ENCIMA DE LA FILA DE ABAJO DEL CAMIÓN. Puesto más abajo se sentaba
     encima de los huecos de «seleccionados», que es justo lo que estás mirando
     cuando el consejo habla de coger cacharros. */
  bottom: 170px;
  z-index: 400;
  display: flex;
  align-items: flex-end;
  gap: 4px;
  pointer-events: none;    /* se lee; no se toca */
  max-width: min(560px, calc(100vw - 380px));
}
.csj[hidden] { display: none; }

@media (min-width: 1700px) { .csj { zoom: 1.2; } }
@media (min-width: 2300px) { .csj { zoom: 1.45; } }

/* --- El fantasma ------------------------------------------------------------ */
.csj-caja {
  flex: none;
  /* La entrada y la salida van AQUI, y el flotar va en la imagen: si las dos
     cosas fueran al mismo nodo, la que entra pisaria a la que flota y el
     fantasma llegaria dando tirones. */
  transform: translateX(-190%);
  opacity: 0;
}
.csj[data-paso="entra"] .csj-caja {
  animation: csj-llega 520ms cubic-bezier(.22, 1, .36, 1) forwards;
}
.csj[data-paso="sale"] .csj-caja {
  animation: csj-marcha 460ms cubic-bezier(.5, 0, .75, 0) forwards;
}
@keyframes csj-llega {
  from { transform: translateX(-190%); opacity: 0; }
  to { transform: translateX(0); opacity: 1; }
}
@keyframes csj-marcha {
  from { transform: translateX(0); opacity: 1; }
  to { transform: translateX(-190%); opacity: 0; }
}

.csj-fant {
  display: block;
  width: 132px;
  height: auto;
  /* LA LAMINA MIRA A LA IZQUIERDA y aqui tiene que mirar a su bocadillo, que
     esta a la derecha. Se le da la vuelta y ya. */
  transform: scaleX(-1);
  animation: csj-flota 2600ms ease-in-out infinite;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .55));
}
/* El giro va en CADA paso: un `transform` sustituye al anterior, asi que un
   fotograma sin el `scaleX` deja al fantasma mirando al reves medio segundo. */
@keyframes csj-flota {
  0%, 100% { transform: scaleX(-1) translateY(0) rotate(0deg); }
  50% { transform: scaleX(-1) translateY(-9px) rotate(-2.5deg); }
}

/* --- El bocadillo ----------------------------------------------------------- */
/* De tebeo: blanco de papel, borde de tinta y la punta mirando al fantasma. Un
   panel oscuro mas seria otro cartel del juego; esto es alguien hablando. */
.csj-globo {
  position: relative;
  margin-bottom: 34px;
  padding: 11px 15px 12px;
  border-radius: 12px;
  background: rgba(253, 251, 242, .93);
  box-shadow:
    inset 0 0 0 2.5px #140d24,
    0 10px 26px rgba(0, 0, 0, .45);
  transform-origin: 0 80%;
  transform: scale(.7);
  opacity: 0;
  transition: transform 240ms cubic-bezier(.2, 1.4, .4, 1), opacity 200ms ease;
}
.csj-globo[data-on="si"] { transform: scale(1); opacity: 1; }

/* LA PUNTA. Dos triangulos, uno de tinta y otro de papel encima: es la manera
   de tener un pico con borde sin dibujar un SVG para tres pixeles. */
.csj-globo::before,
.csj-globo::after {
  content: "";
  position: absolute;
  left: -13px;
  bottom: 13px;
  width: 0;
  height: 0;
  border: 8px solid transparent;
}
.csj-globo::before { border-right-color: #140d24; }
.csj-globo::after {
  left: -8px;
  border-right-color: rgba(253, 251, 242, .93);
}

.csj-texto {
  margin: 0;
  font: 500 13px/1.4 Rubik, system-ui, sans-serif;
  color: #15102a;
}

@media (prefers-reduced-motion: reduce) {
  .csj-caja, .csj-fant { animation: none; }
  .csj[data-paso="entra"] .csj-caja { transform: none; opacity: 1; }
  .csj-globo { transition: none; }
}

/* =============================================================================
   EL FOCO: el aro que rodea el sitio exacto donde hay que pinchar.
   Vive fuera de todo -se cuelga del `body`- porque senala cosas que estan
   dentro del camion y de la libreta, y esos tapan la pantalla entera.
============================================================================= */
.foco {
  position: fixed;
  z-index: 401;          /* justo por encima de la cinta, que es quien lo manda */
  pointer-events: none;  /* el aro senala; lo que se pulsa es lo de debajo */
  border-radius: 12px;
  /* NO OSCURECE EL RESTO. La tentacion es el foco de teatro -apagar la pantalla
     menos el boton- y eso convierte cada paso en un pasillo. El aro dice
     «aqui»; lo demas se sigue viendo. */
  box-shadow:
    inset 0 0 0 3px var(--lime),
    0 0 0 3px rgba(168, 244, 37, .3),
    0 0 26px rgba(168, 244, 37, .45);
  animation: foco-late 1500ms ease-in-out infinite;
}
.foco[hidden] { display: none; }

/* LO QUE NO TOCA, APAGADO. Mientras el foco está señalando algo de la libreta,
   sus hermanos —las otras seis pruebas, las otras trece fichas— se quedan a
   media luz. Que no se puedan pulsar ya lo decide el candado; esto es para que
   además SE VEA, porque un botón que se ve igual que los demás y no reacciona
   se lee como una avería.

   Y se apagan solo los HERMANOS, no la pantalla: el resto de la libreta se lee
   entero. El foco de teatro convierte cada paso en un pasillo. */
body[data-guiando] .ex-prueba:not([data-foco]),
body[data-guiando] .ex-sospechoso:not([data-foco]),
body[data-guiando] .cam-card:not([data-foco]),
body[data-guiando] .cam-hueco:not([data-foco]) {
  opacity: .34;
  filter: saturate(.4);
  transition: opacity 220ms var(--ease-out), filter 220ms var(--ease-out);
}
@keyframes foco-late {
  0%, 100% {
    box-shadow:
      inset 0 0 0 3px var(--lime),
      0 0 0 3px rgba(168, 244, 37, .3),
      0 0 26px rgba(168, 244, 37, .45);
  }
  50% {
    box-shadow:
      inset 0 0 0 3px var(--lime-soft),
      0 0 0 7px rgba(168, 244, 37, .12),
      0 0 40px rgba(168, 244, 37, .7);
  }
}

/* --- Las teclas, dibujadas dentro de la frase ------------------------------ */
.prac-tecla {
  display: inline-grid;
  place-items: center;
  min-width: 1.8em;
  padding: 2px 7px 3px;
  margin: 0 1px;
  border-radius: 7px;
  font-family: var(--face-ui);
  font-size: .8em;
  font-weight: 700;
  letter-spacing: .04em;
  color: #0b0a12;
  background: var(--lime);
  /* Un teclado tiene canto: la sombra dura de abajo es la tecla vista de lado,
     no un adorno. */
  box-shadow: 0 3px 0 var(--lime-deep);
  vertical-align: baseline;
  white-space: nowrap;
}
/* El «o» entre la tecla y el clic: pequeno y apagado, porque es gramatica y no
   instruccion. Lo que hay que leer son las dos teclas. */
.prac-o {
  margin: 0 5px;
  font-size: .72em;
  font-weight: 400;
  color: var(--ink-faint);
}

/* --- Y el final ------------------------------------------------------------ */
.prac-linea--fin .prac-que {
  font-family: var(--face-pixel);
  font-size: 30px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--lime);
}

/* =============================================================================
   LA CORDURA DEL EQUIPO (arriba, derecha)
============================================================================= */
.cor {
  min-width: 340px;
  padding: 15px 20px 17px;
  border-radius: 16px;
  background: rgba(5, 4, 12, .72);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .12);
}
.cor-prom {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  padding-bottom: 10px;
  margin-bottom: 10px;
  border-bottom: 1px solid rgba(255, 255, 255, .1);
  font-size: 15px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .55);
}
.cor-lista { margin: 0; padding: 0; list-style: none; display: grid; gap: 7px; }
.cor-fila { display: flex; justify-content: space-between; gap: 14px; align-items: baseline; }
.cor-nombre {
  font-family: var(--face-pixel);
  font-size: 23px;
  letter-spacing: .04em;
  color: rgba(255, 255, 255, .82);
}
.cor-nombre.yo { color: #fff; }
.cor-num { font-family: var(--face-pixel); font-size: 23px; }
.cor-num.bien { color: var(--lime); }
.cor-num.regular { color: #ffd166; }
.cor-num.mal { color: #ff5d5d; }

/* =============================================================================
   EL APARATO EN LA MANO (abajo, derecha)
   Cada cacharro enseña lo suyo: el EMF sus luces, el termómetro sus grados.
============================================================================= */
.ap {
  justify-self: end;
  width: 330px;
  padding: 15px 18px 17px;
  border-radius: 16px;
  background: rgba(5, 4, 12, .78);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .14);
}
.ap-cabeza { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.ap-nombre {
  font-family: var(--face-pixel);
  font-size: 23px;
  line-height: 1.1;
  letter-spacing: .04em;
  color: #fff;
}
.ap-pantalla {
  display: grid;
  gap: 10px;
  justify-items: center;
  padding: 14px 12px;
  border-radius: 12px;
  background: rgba(0, 0, 0, .45);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08);
}
.ap-lectura { margin: 0; font-size: 16px; color: rgba(255, 255, 255, .62); text-align: center; }
.ap-pista { margin: 0; font-size: 16px; line-height: 1.35; color: rgba(255, 255, 255, .78); text-align: center; }
.ap-numero {
  margin: 0;
  font-family: var(--face-pixel);
  font-size: 54px;
  line-height: 1;
  color: var(--lime);
  transition: color .25s ease;
}
/* El termómetro se pone azul al enfriarse: el número solo, sin adornos, ya
   avisa por el rabillo del ojo de que has entrado donde no debías. */
/* Lo que ha contestado la spirit box: entrecomillado y en grande, porque es
   una palabra suelta y tiene que leerse de un vistazo desde lejos. */
.ap-voz {
  margin: 0;
  font-family: var(--face-pixel);
  font-size: 26px;
  line-height: 1.2;
  color: #fff;
  text-align: center;
  text-shadow: 0 0 14px rgba(168, 244, 37, .45);
}

.ap-numero.fresco { color: #7fd4ff; }
.ap-numero.frio {
  color: #4fe0ff;
  text-shadow: 0 0 18px rgba(79, 224, 255, .55);
}
/* Y el pie se enciende cuando lo que marca VALE COMO PRUEBA, que es el momento
   que hay que cazar: nivel cinco, o bajo cero. */
.ap-lectura.prueba {
  color: var(--lime);
  font-weight: 700;
  letter-spacing: .04em;
}
/* =============================================================================
   EL VISOR DE LAS CÁMARAS
   El hueco va TRANSPARENTE: por ahí se ve el lienzo del juego, donde una
   segunda cámara dibuja el mundo más de cerca y con su filtro. Aquí solo está
   el marco, el rótulo y las rayas de tubo.
============================================================================= */
.ap-visor {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: 6px;
  /* LA VIÑETA, MUY BAJADA. Estaba en 40px de negro al 80 %, y en una pantallita
     de trescientos píxeles eso no es una viñeta: es una tapa. La imagen de la
     cámara salía casi negra y para compensarlo se le subía el brillo a la
     escena, con lo que la parte alumbrada se quemaba. Se ve MEJOR quitando la
     tapa que subiendo la luz. */
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .22), inset 0 0 12px rgba(0, 0, 0, .4);
  overflow: hidden;
}
.ap-visor-rec {
  position: absolute;
  top: 7px;
  left: 9px;
  z-index: 2;
  font-family: var(--face-pixel);
  font-size: 15px;
  letter-spacing: .08em;
  color: #ff5d5d;
  text-shadow: 0 0 8px rgba(255, 93, 93, .8);
  animation: ap-rec 1.6s steps(1) infinite;
}
@keyframes ap-rec { 0%, 60% { opacity: 1; } 61%, 100% { opacity: .25; } }
.ap-visor-dato {
  position: absolute;
  right: 9px;
  bottom: 7px;
  z-index: 2;
  font-family: var(--face-pixel);
  font-size: 14px;
  color: rgba(255, 255, 255, .75);
  text-shadow: 0 2px 0 rgba(0, 0, 0, .8);
}
/* Las rayas de tubo y las esquinas quemadas, que es lo que hace que parezca
   una pantallita y no un recorte del juego. */
.ap-visor-rayas {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(120% 120% at 50% 50%, transparent 72%, rgba(0, 0, 0, .32)),
    repeating-linear-gradient(
      to bottom,
      rgba(255, 255, 255, .04) 0 1px,
      transparent 1px 4px);
}
/* ==========================================================================
   EL PANEL DE UNA CÁMARA NO TIENE FONDO. NINGUNO.

   Esto era el fallo de la imagen «apagada» del visor, y costó dar con él: la
   pantallita no es un dibujo, es una SEGUNDA CÁMARA de Phaser pintando en el
   lienzo, que está DEBAJO de todo el HTML. El panel del aparato llevaba un
   fondo negro al 78 % y la caja de la pantalla otro al 45 %: entre los dos se
   quedaban con tres cuartas partes de la imagen antes de que llegara al ojo.
   Para compensarlo se le subía el brillo a la escena, y de ahí venía lo de
   «demasiada luz»: lo poco que se veía salía quemado y el resto seguía negro.

   Así que cuando el aparato es una cámara, el panel se queda sin fondo y cada
   trozo de texto se pone el suyo. Se ve la imagen tal cual, y el filtro puede
   ser suave, que es cuando el blanco y negro se ve bien.
   ========================================================================== */
.ap-pantalla:has(.ap-visor) { background: none; box-shadow: none; padding: 0; }
.ap:has(.ap-visor) { background: none; box-shadow: none; padding: 0; }
.ap:has(.ap-visor) .ap-cabeza,
.ap:has(.ap-visor) .ap-pie,
.ap:has(.ap-visor) .ap-pista,
.ap:has(.ap-visor) .ap-lectura {
  margin: 0;
  padding: 8px 12px;
  border-radius: 10px;
  background: rgba(5, 4, 12, .82);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .1);
}
.ap:has(.ap-visor) .ap-cabeza { margin-bottom: 8px; }
.ap:has(.ap-visor) .ap-pantalla { gap: 8px; }

/* Los usos que le quedan a la sal o a las pastillas, como balas. */
.ap-cargas { display: flex; gap: 5px; }
.ap-carga {
  width: 12px;
  height: 22px;
  border-radius: 3px;
  background: rgba(255, 255, 255, .1);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .16);
}
.ap-carga.on { background: var(--lime); box-shadow: 0 0 8px rgba(168, 244, 37, .6); }

.ap-aviso {
  margin: 4px 0 0;
  min-height: 1em;
  text-align: center;
  font-size: 12.5px;
  color: #ffd166;
}
.ap-aviso.parpadeo { animation: inv-parpadeo 520ms ease; }

.ap-pie {
  margin: 11px 0 0;
  font-size: 15px;
  letter-spacing: .06em;
  text-transform: uppercase;
  text-align: center;
  color: rgba(255, 255, 255, .45);
}

/* Las cinco luces del EMF. */
.ap-leds { display: flex; gap: 6px; }
.ap-led {
  width: 22px;
  height: 42px;
  border-radius: 5px;
  background: rgba(255, 255, 255, .09);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12);
}
.ap-led--verde.on { background: #46d34a; box-shadow: 0 0 10px rgba(70, 211, 74, .8); }
.ap-led--ambar.on { background: #ffd166; box-shadow: 0 0 10px rgba(255, 209, 102, .8); }
.ap-led--rojo.on { background: #ff4d4d; box-shadow: 0 0 12px rgba(255, 77, 77, .85); }

/* La estática del spirit box. */
.ap-onda { display: flex; align-items: flex-end; gap: 5px; height: 48px; }
.ap-onda i {
  width: 6px;
  border-radius: 3px;
  background: rgba(168, 244, 37, .75);
  animation: ap-onda 900ms ease-in-out infinite alternate;
}
@keyframes ap-onda {
  from { transform: scaleY(.5); opacity: .5; }
  to { transform: scaleY(1); opacity: 1; }
}

/* La muestra de color de los cacharros que dan luz. */
.ap-luz {
  width: 100%;
  height: 42px;
  border-radius: 9px;
  background: rgba(255, 255, 255, .07);
  transition: background 200ms ease, box-shadow 200ms ease;
}
.ap-luz--blanca.on { background: rgba(255, 246, 214, .85); box-shadow: 0 0 16px rgba(255, 246, 214, .6); }
.ap-luz--uv.on { background: rgba(154, 77, 255, .85); box-shadow: 0 0 18px rgba(154, 77, 255, .7); }
.ap-luz--dots.on { background: rgba(53, 255, 150, .8); box-shadow: 0 0 18px rgba(53, 255, 150, .6); }
.ap-luz--fuego.on { background: rgba(255, 177, 77, .85); box-shadow: 0 0 18px rgba(255, 177, 77, .6); }

/* El chat, abajo en medio: se ve siempre, tenue, y se despierta al escribir. */
.hud-chat { pointer-events: auto; width: 100%; opacity: .72; transition: opacity 160ms ease; }
.hud-chat:hover, .hud-chat.on { opacity: 1; }
.hud-chat .dev-slot { height: 68px; gap: 14px; padding: 0 20px; border-radius: 14px; }
.hud-chat input { cursor: text; font-size: 21px; }
.hud-chat .marker { font-size: 22px; }

.hud-log {
  width: 100%;
  max-height: 200px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 2px;
  font-family: var(--face-ui);
  font-size: 21px;
  line-height: 1.3;
  color: var(--ink);
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.85);
}
.hud-log .from { color: var(--slime); margin-right: 6px; }
/* Las líneas se van solas. Antes se quedaban las seis últimas clavadas para
   siempre y al volver al cuartel seguían ahí los susurros de la partida
   anterior; ahora cada una tiene su reloj y se desvanece sin dar el cante. */
.hud-log > div {
  transition: opacity 900ms ease, transform 900ms ease;
}
.hud-log > div.yendose {
  opacity: 0;
  transform: translateY(-6px);
  pointer-events: none;
}
/* La voz del fantasma: en cursiva y con el nombre en rojo. Que no se confunda
   con un compañero hablando, o alguien acabará contestándole. */
.hud-log .fantasma { font-style: italic; color: #ffd9e6; text-shadow: 0 0 12px rgba(255, 60, 120, .45); }

/* LO QUE DICEN LOS MUERTOS. En azul frío y algo apagado: hablan entre ellos y
   los vivos no les leen, así que quien ve esto es porque ya está del otro lado.
   Que se distinga del chat normal de un vistazo es lo que impide contestarle a
   alguien que ya no puede oírte. */
.hud-log .muerto { color: #9fd4ff; opacity: .82; }
.hud-log .muerto .from { color: #6fb6e8; }
.hud-log .fantasma .from { color: #ff5d8f; }
.hud-log .sys { color: var(--ink-faint); }

/* Si se cae el enlace ya no hay juego: se tapa y se dice. */
.hud-lost {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(5, 4, 12, 0.9);
  pointer-events: auto;
}
.hud-lost[hidden] { display: none; }
.hud-lost p {
  font-family: var(--face-ui);
  font-size: var(--t-small);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--danger);
  text-align: center;
}

/* =============================================================================
   AVISO DE PANTALLA COMPLETA
   El navegador solo concede pantalla completa si viene de un gesto reciente del
   usuario, y ese permiso caduca en segundos. Si al entrar ya ha caducado, se
   pide con este botón, que sí cuenta como gesto.
============================================================================= */
.fs-nudge {
  position: absolute;
  inset: 0;
  z-index: 30;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 20px;
  padding: 24px;
  background: rgba(5, 4, 12, 0.92);
  backdrop-filter: blur(6px);
  pointer-events: auto;
  text-align: center;
}
.fs-nudge[hidden] { display: none; }
.fs-nudge p {
  margin: 0;
  font-family: var(--face-pixel);
  font-size: clamp(18px, 2vw, 26px);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
}

/* =============================================================================
   MENÚ DE PAUSA
   Cajas, cinta y botones del Basic GUI Bundle. Ojo: ese pack NO es pixel art,
   son PNG vectoriales de 1500 px, así que aquí NO se pone `image-rendering:
   pixelated` (dejaría los bordes dentados) y el 9-slice se corta por donde acaba
   la esquina redondeada del original: 200 px en la caja, 175 px en los botones.

   POSICIÓN FIJA, no absoluta: el menú aparece justo cuando el navegador SALE de
   pantalla completa, y en ese instante el lienzo del juego todavía tiene el
   tamaño de antes. Colgado del lienzo, el menú salía descentrado; anclado a la
   ventana, cae siempre en el medio.
============================================================================= */
.pause {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: 24px;
  background: radial-gradient(120% 90% at 50% 45%, rgba(24, 10, 44, .72), rgba(4, 3, 10, .92));
  backdrop-filter: blur(6px);
  pointer-events: auto;
  animation: pause-in 200ms var(--ease-out);
}
.pause[hidden] { display: none; }
@keyframes pause-in { from { opacity: 0; } to { opacity: 1; } }

.pause-box {
  display: grid;
  justify-items: stretch;
  width: min(392px, 90vw);
  padding: 0 20px 18px;
  border: 32px solid transparent;
  border-image: url('../assets/gui/Box_Rounded.png') 200 fill stretch;
  animation: pause-box 300ms var(--ease-pop);
}
@keyframes pause-box {
  from { transform: scale(.9) translateY(10px); }
  to { transform: none; }
}

/* La cinta sube por encima del borde de la caja. Su proporción es la del PNG
   (1139x456 = 2,5) para que la curva no se deforme. */
.pause-banner {
  justify-self: center;
  width: 296px;
  max-width: 100%;
  aspect-ratio: 2.5;
  margin: -62px 0 6px; /* la curva baja en el centro: sin este aire roza el botón */
  display: grid;
  place-items: center;
  background: url('../assets/gui/Banner_Grey.png') center / 100% 100% no-repeat;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .55));
}

/* CENTRAR DE VERDAD, no matemáticamente. Jersey 25 reserva mucho hueco encima y
   debajo de la letra, así que una caja centrada deja el texto visualmente alto;
   se baja un pelo a mano. La cinta además es cóncava, y su hueco útil está algo
   por encima de su centro geométrico: de ahí que el ajuste sea pequeño. */
.pause-title {
  margin: 0;
  transform: translateY(3px);
  font-family: var(--face-pixel);
  font-size: 42px;
  line-height: 1;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 3px 0 rgba(0, 0, 0, .5);
}

.pause-acts { display: grid; gap: 12px; }

/* El botón es un 9-slice: su alto lo pone el borde (24 px arriba y abajo) más
   la caja de contenido. La palabra se centra en esa caja y se baja 2 px por lo
   mismo que el rótulo: la fuente reserva más aire arriba que abajo. */
.pause-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 26px;
  height: 26px;
  border: 24px solid transparent;
  border-image: url('../assets/gui/ButtonText_Large_GreyOutline_Round.png') 175 fill stretch;
  background: none;
  color: #fff;
  font-family: var(--face-pixel);
  font-size: 22px;
  line-height: 1;
  letter-spacing: .05em;
  text-transform: uppercase;
  white-space: nowrap;
  text-shadow: 0 2px 0 rgba(0, 0, 0, .45);
  cursor: pointer;
  transition: transform 140ms var(--ease-pop), filter 140ms ease;
}
/* `display: flex` gana a `[hidden]`, así que hay que decirlo a mano o el botón
   de dejar la sala se ve siempre, incluso jugando en solitario. */
.pause-btn[hidden] { display: none; }
.pause-btn:hover { transform: translateY(-2px); filter: brightness(1.14); }
.pause-btn:active { transform: translateY(1px); }
.pause-btn--go { border-image-source: url('../assets/gui/ButtonText_Large_Green_Round.png'); }

.pause-hint {
  margin: 12px 6px 0;
  text-align: center;
  font-family: var(--face-ui);
  font-size: 12.5px;
  line-height: 1.4;
  color: rgba(255, 255, 255, .58);
}

/* =============================================================================
   EL CÓDIGO DE LA SALA
   Arriba a la izquierda y discreto: se lee cuando hace falta y no molesta el
   resto del rato. Se pincha para copiar.
============================================================================= */
.sala {
  position: absolute;
  top: 16px;
  left: 16px;
  z-index: 30;
  display: flex;
  align-items: baseline;
  gap: 9px;
  padding: 9px 15px 8px;
  border: 0;
  border-radius: 12px;
  background: rgba(9, 7, 18, 0.82);
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, 0.35), 0 6px 20px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(6px);
  color: var(--ink);
  cursor: pointer;
  pointer-events: auto;
  transition: transform 150ms var(--ease-pop), box-shadow 150ms ease;
}
.sala[hidden] { display: none; }
.sala:hover { transform: translateY(-1px); box-shadow: inset 0 0 0 1px var(--lime), 0 8px 24px rgba(0, 0, 0, .55); }

.sala-lab {
  font-family: var(--face-ui);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.sala-code {
  font-family: var(--face-pixel);
  font-size: 26px;
  line-height: 1;
  letter-spacing: 0.16em;
  color: var(--lime);
}
.sala-gente { font-family: var(--face-ui); font-size: 11px; color: var(--ink-dim); }

/* =============================================================================
   EL TERMINAL DE PARTIDAS (la tecla E)

   FUERA LAS CAJAS GRISES DEL PACK. Eran las mismas del menú de pausa y en una
   pantalla de este tamaño se veían por lo que son: plástico gris de kit de
   interfaz, con botones de pastilla, en un juego que va de una casa a oscuras.
   Y encima obligaban a una caja estrecha, así que elegir casa vivía escondida
   detrás de un botón que llevaba a otra pantalla.

   Ahora es un panel ANCHO y oscuro, de dos columnas, pintado con CSS: madera
   quemada, un filo cálido y el rótulo grabado. Sin una sola imagen de más.
============================================================================= */
.term {
  position: fixed;
  inset: 0;
  z-index: 55;
  display: grid;
  place-items: center;
  padding: 24px;
  background: radial-gradient(120% 90% at 50% 45%, rgba(24, 10, 44, .72), rgba(3, 2, 8, .95));
  backdrop-filter: blur(7px);
  pointer-events: auto;
  animation: pause-in 200ms var(--ease-out);
}
.term[hidden] { display: none; }

.term-box {
  position: relative;
  width: min(1040px, 94vw);
  max-height: 88vh;
  overflow: auto;
  padding: 30px 26px 26px;
  border-radius: 16px;
  /* Tres capas: el filo cálido de fuera, el fondo de madera quemada y una
     lumbre floja arriba, que es lo que hace que el panel parezca alumbrado por
     algo y no recortado y pegado encima. */
  border: 1px solid rgba(255, 190, 120, .16);
  background:
    radial-gradient(120% 70% at 50% -10%, rgba(255, 176, 92, .1), transparent 60%),
    linear-gradient(180deg, #1b1526 0%, #14101d 55%, #0f0c16 100%);
  box-shadow:
    0 30px 80px rgba(0, 0, 0, .7),
    inset 0 1px 0 rgba(255, 255, 255, .06),
    inset 0 -40px 90px rgba(0, 0, 0, .45);
  animation: pause-box 300ms var(--ease-pop);
}

/* El rótulo: grabado en la propia madera, no una chapa pegada. */
.term-banner {
  display: grid;
  place-items: center;
  margin: 0 0 18px;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(255, 190, 120, .12);
}
.term-title {
  margin: 0;
  font-family: var(--face-pixel);
  font-size: 30px;
  line-height: 1;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #f3e6cf;
  text-shadow: 0 2px 0 rgba(0, 0, 0, .6), 0 0 22px rgba(255, 176, 92, .25);
}

.term-body { display: grid; gap: 14px; }

/* Dos columnas: a dónde vais y quién viene. En pantalla estrecha, una encima
   de otra — y la de la casa primero, que es la que hay que decidir. */
.term-cols {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 20px;
  align-items: start;
}
@media (max-width: 860px) { .term-cols { grid-template-columns: 1fr; } }

.term-col {
  display: grid;
  gap: 12px;
  align-content: start;
  padding: 14px;
  border-radius: 12px;
  background: rgba(255, 255, 255, .022);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .05);
}

.term-rotulo {
  margin: 0;
  font-family: var(--face-pixel);
  font-size: 14px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 210, 150, .72);
}

.term-lead {
  margin: 0 2px 2px;
  text-align: center;
  font-family: var(--face-ui);
  font-size: 13px;
  line-height: 1.45;
  color: rgba(255, 255, 255, .72);
}
.term-acts { display: grid; gap: 9px; margin-top: 2px; }

/* Los botones: chapa oscura con filo, no pastilla gris. */
.term-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 13px 18px;
  border: 0;
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(255, 255, 255, .07), rgba(255, 255, 255, .02));
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, .1),
    inset 0 1px 0 rgba(255, 255, 255, .09),
    0 6px 16px rgba(0, 0, 0, .35);
  color: #ece3d4;
  font-family: var(--face-pixel);
  font-size: 17px;
  line-height: 1;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-align: center;
  text-shadow: 0 2px 0 rgba(0, 0, 0, .45);
  cursor: pointer;
  transition: transform 130ms var(--ease-pop), box-shadow 130ms ease, background 130ms ease;
}
.term-btn:hover {
  transform: translateY(-1px);
  background: linear-gradient(180deg, rgba(255, 210, 150, .16), rgba(255, 176, 92, .06));
  box-shadow:
    inset 0 0 0 1px rgba(255, 210, 150, .34),
    0 10px 22px rgba(0, 0, 0, .45);
}
.term-btn:active { transform: translateY(1px); }
.term-btn:disabled {
  /* Apagado de verdad: un botón que no se puede pulsar no puede seguir
     pareciendo el botón bueno. El verde apagado seguía cantando «púlsame». */
  filter: grayscale(1) brightness(.5) contrast(.9);
  opacity: .75;
  cursor: not-allowed;
  transform: none;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .06);
}
/* El de salir es el único verde: es el que termina la conversación. */
.term-btn--go {
  color: #0c1206;
  background: linear-gradient(180deg, #bdf94a, #8fd21f);
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, .22), 0 8px 20px rgba(140, 210, 40, .22);
  text-shadow: 0 1px 0 rgba(255, 255, 255, .35);
}
.term-btn--go:hover {
  background: linear-gradient(180deg, #cffb63, #9ee026);
  box-shadow: inset 0 -3px 0 rgba(0, 0, 0, .22), 0 12px 26px rgba(140, 210, 40, .3);
}
.term-btn--ghost {
  font-size: 15px;
  color: rgba(236, 227, 212, .74);
  background: rgba(255, 255, 255, .03);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .07);
}

.term-form { display: grid; gap: 11px; }
.term-code {
  width: 100%;
  padding: 14px 16px;
  border: 0;
  border-radius: 10px;
  background: rgba(5, 4, 12, .55);
  box-shadow: inset 0 0 0 2px rgba(168, 244, 37, .45);
  color: var(--lime);
  font-family: var(--face-pixel);
  font-size: 38px;
  line-height: 1;
  letter-spacing: 0.28em;
  text-align: center;
  text-transform: uppercase;
}
.term-code:focus { outline: none; box-shadow: inset 0 0 0 2px var(--lime), 0 0 22px rgba(168, 244, 37, .3); }
.term-code::placeholder { color: rgba(168, 244, 37, .3); }

.term-aviso {
  margin: 0;
  min-height: 16px;
  text-align: center;
  font-family: var(--face-ui);
  font-size: 12px;
  color: var(--amber);
}

/* =============================================================================
   LA PANTALLA DE CARGA
   Tapa el juego entero mientras se monta un mapa: logotipo, barra de verdad
   —la mueve la carga, no un temporizador— y una frase que va cambiando. Un
   cartel quieto hace que diez segundos parezcan treinta.
============================================================================= */
.carga {
  position: absolute;
  inset: 0;
  z-index: 70;   /* por encima de pausa, inventario y personajes */
  display: grid;
  place-items: center;
  align-content: center;
  gap: 18px;
  padding: 24px;
  text-align: center;
  background: radial-gradient(120% 90% at 50% 40%, #180a2c, #030208);
  pointer-events: auto;
  transition: opacity 380ms ease;
}
.carga[hidden] { display: none; }
.carga[data-yendo='true'] { opacity: 0; }

.carga-logo {
  height: auto;
  width: min(360px, 66vw);
  filter: drop-shadow(0 10px 24px rgba(0, 0, 0, .6));
  animation: carga-flota 4s ease-in-out infinite;
}
@keyframes carga-flota {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

.carga-texto {
  margin: 0;
  font-family: var(--face-pixel);
  font-size: 26px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #fff;
}
.carga-texto span,
.carga-puntos i {
  display: inline-block;
  animation: carga-latido 1.4s ease-in-out infinite;
}
.carga-puntos i { font-style: normal; }
@keyframes carga-latido {
  0%, 60%, 100% { opacity: .45; transform: none; }
  30% { opacity: 1; transform: translateY(-3px); }
}

.carga-barra {
  width: min(420px, 74vw);
  height: 12px;
  padding: 2px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .08);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .12);
}
.carga-barra i {
  display: block;
  width: 5%;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--lime), #d9ff7a);
  box-shadow: 0 0 16px rgba(168, 244, 37, .5);
  transition: width 260ms ease;
}

.carga-frase {
  margin: 0;
  min-height: 1.4em;
  max-width: min(560px, 88vw);
  font-family: var(--face-ui);
  font-size: 14px;
  line-height: 1.45;
  color: rgba(255, 255, 255, .66);
}
.carga-frase.entra { animation: carga-frase-in 420ms var(--ease-out); }
@keyframes carga-frase-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

/* =============================================================================
   LA SALA EN EL TERMINAL
   La tripulación con su lucecita: verde el que ya está listo. Se lee de un
   vistazo quién falta, que es lo único que importa antes de salir.
============================================================================= */
.sala-crew {
  display: grid;
  gap: 6px;
  margin: 0 0 2px;
  padding: 0;
  list-style: none;
}
.sala-fila {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(5, 4, 12, .42);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .09);
}
.sala-luz {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .18);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .25);
}
.sala-luz.on {
  background: var(--lime);
  box-shadow: 0 0 10px rgba(168, 244, 37, .8);
}
.sala-nombre {
  flex: 1;
  font-family: var(--face-pixel);
  font-size: 18px;
  letter-spacing: .04em;
  color: #fff;
}
.sala-tag {
  font-family: var(--face-ui);
  font-size: 10.5px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .5);
}
.sala-tag--jefe { color: var(--lime); }

/* =============================================================================
   EL BOCADILLO DE TEXTO
   Abajo y centrado, con la caja del Basic GUI Bundle. Ancho generoso pero con
   tope: un párrafo que cruza una pantalla de 4K no hay quien lo lea.
============================================================================= */
.boca {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 42;
  display: grid;
  justify-items: center;
  padding: 0 24px 34px;
  pointer-events: auto;
  animation: boca-sube 220ms var(--ease-out);
}
.boca[hidden] { display: none; }
@keyframes boca-sube {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

.boca-caja {
  width: min(880px, 94vw);
  padding: 6px 26px 16px;
  border: 30px solid transparent;
  border-image: url('../assets/gui/Box_Rounded.png') 200 fill stretch;
}

.boca-texto {
  margin: 0;
  min-height: 2.6em;
  font-family: var(--face-pixel);
  /* Bien grande: es un mensaje que hay que poder leer de un vistazo desde el
     sofá, no un pie de foto. */
  font-size: clamp(30px, 3.1vw, 44px);
  line-height: 1.35;
  letter-spacing: 0.02em;
  color: #fff;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.45);
  /* El texto se escribe letra a letra: sin esto, la caja pega saltos cada vez
     que una palabra cambia de línea. */
  overflow-wrap: break-word;
}

.boca-pie {
  margin: 8px 0 0;
  text-align: right;
  font-family: var(--face-ui);
  font-size: 12.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}

/* =============================================================================
   ELEGIR PERSONAJE
   Las caras se recortan de la misma lámina que usa el juego, así que la
   miniatura y el muñeco no pueden dejar de parecerse.
============================================================================= */
.pjs {
  position: fixed;
  inset: 0;
  z-index: 58;
  display: grid;
  place-items: center;
  padding: 24px;
  background: radial-gradient(120% 90% at 50% 45%, rgba(24, 10, 44, .7), rgba(4, 3, 10, .92));
  backdrop-filter: blur(6px);
  pointer-events: auto;
  animation: pause-in 200ms var(--ease-out);
}
.pjs[hidden] { display: none; }

.pjs-box {
  display: grid;
  gap: 14px;
  justify-items: stretch;
  width: min(660px, 94vw);
  padding: 0 22px 20px;
  border: 32px solid transparent;
  border-image: url('../assets/gui/Box_Rounded.png') 200 fill stretch;
  animation: pause-box 300ms var(--ease-pop);
}
.pjs-banner {
  justify-self: center;
  width: 296px;
  max-width: 100%;
  aspect-ratio: 2.5;
  margin: -62px 0 2px;
  display: grid;
  place-items: center;
  background: url('../assets/gui/Banner_Grey.png') center / 100% 100% no-repeat;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .55));
}
.pjs-title {
  margin: 0;
  transform: translateY(3px);
  font-family: var(--face-pixel);
  font-size: 34px;
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 3px 0 rgba(0, 0, 0, .5);
}

.pjs-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
}

.pjs-card {
  display: grid;
  justify-items: center;
  gap: 4px;
  padding: 12px 10px 14px;
  border: 0;
  border-radius: 14px;
  background: rgba(5, 4, 12, 0.4);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.14);
  color: #fff;
  cursor: pointer;
  transition: transform 150ms var(--ease-pop), box-shadow 150ms ease, background 150ms ease;
}
.pjs-card:hover { transform: translateY(-3px); background: rgba(5, 4, 12, .55); }
.pjs-card.on {
  background: rgba(168, 244, 37, .16);
  box-shadow: inset 0 0 0 2px var(--lime), 0 0 24px rgba(168, 244, 37, .25);
}

.pjs-cara {
  display: block;
  background-repeat: no-repeat;
  image-rendering: pixelated;
  filter: drop-shadow(0 4px 6px rgba(0, 0, 0, .45));
}
.pjs-nombre {
  font-family: var(--face-pixel);
  font-size: 22px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.pjs-desc {
  font-family: var(--face-ui);
  font-size: 11.5px;
  line-height: 1.35;
  text-align: center;
  color: rgba(255, 255, 255, 0.6);
}

/* --- LOS QUE TODAVÍA NO SON TUYOS -------------------------------------------
   EN SILUETA, no borrados. Un personaje es lo que ve el resto del equipo cuando
   entras por la puerta, así que la única manera de que apetezca llegar al nivel
   12 es haber visto antes quién hay ahí. Se le quita el color al muñeco —queda
   su forma, que es lo que da curiosidad— y el nombre se lee entero: enseñar una
   silueta anónima sería un misterio, no una meta. */
.pjs-card[data-cerrado='true'] {
  cursor: default;
  background: rgba(5, 4, 12, .28);
  box-shadow: inset 0 0 0 2px rgba(157, 107, 255, .22);
}
.pjs-card[data-cerrado='true']:hover { transform: none; background: rgba(5, 4, 12, .34); }
.pjs-card[data-cerrado='true'] .pjs-cara { filter: grayscale(1) brightness(.42) contrast(1.15); }
.pjs-card[data-cerrado='true'] .pjs-nombre { color: rgba(255, 255, 255, .45); }
.pjs-card[data-cerrado='true'] .pjs-desc {
  color: var(--violet-soft, #c3a4ff);
  font-family: var(--face-pixel);
  font-size: 14px;
  letter-spacing: .04em;
}

/* =============================================================================
   EL INVENTARIO DEL CAMIÓN
   Mismo armazón que el terminal y el elige-personaje —caja, cinta y botón—
   porque son el mismo mueble: un menú del juego. Lo suyo es la estantería, que
   se dibuja recortando la lámina de objetos y no con un fichero por icono.
============================================================================= */
.inv {
  position: fixed;
  inset: 0;
  z-index: 57;
  display: grid;
  place-items: center;
  padding: 20px;
  background: radial-gradient(120% 90% at 50% 45%, rgba(24, 10, 44, .7), rgba(4, 3, 10, .93));
  backdrop-filter: blur(6px);
  pointer-events: auto;
  animation: pause-in 200ms var(--ease-out);
}
.inv[hidden] { display: none; }

.inv-box {
  display: grid;
  gap: 12px;
  justify-items: stretch;
  width: min(860px, 95vw);
  max-height: 92vh;
  padding: 0 22px 18px;
  border: 32px solid transparent;
  border-image: url('../assets/gui/Box_Rounded.png') 200 fill stretch;
  animation: pause-box 300ms var(--ease-pop);
}
.inv-banner {
  justify-self: center;
  width: 296px;
  max-width: 100%;
  aspect-ratio: 2.5;
  margin: -62px 0 -2px;
  display: grid;
  place-items: center;
  background: url('../assets/gui/Banner_Grey.png') center / 100% 100% no-repeat;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, .55));
}
.inv-title {
  margin: 0;
  transform: translateY(3px);
  font-family: var(--face-pixel);
  font-size: 34px;
  line-height: 1;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 3px 0 rgba(0, 0, 0, .5);
}
.inv-lead {
  margin: 0;
  text-align: center;
  font-family: var(--face-ui);
  font-size: 13px;
  color: rgba(255, 255, 255, .72);
}

/* Las tres manos. Se ven siempre, llenas o vacías: así se entiende de un
   vistazo que el tope es tres y cuánto queda. */
.inv-manos {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.inv-mano {
  display: grid;
  justify-items: center;
  gap: 2px;
  padding: 8px 6px 10px;
  border: 0;
  border-radius: 14px;
  background: rgba(168, 244, 37, .14);
  box-shadow: inset 0 0 0 2px var(--lime);
  color: #fff;
  cursor: pointer;
  transition: transform 150ms var(--ease-pop), filter 150ms ease;
}
.inv-mano:hover { transform: translateY(-2px); filter: brightness(1.12); }
.inv-mano.vacia {
  background: rgba(5, 4, 12, .38);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .12);
  cursor: default;
}
.inv-vacia {
  display: grid;
  place-items: center;
  height: 72px;
  font-family: var(--face-pixel);
  font-size: 30px;
  color: rgba(255, 255, 255, .18);
}
.inv-mano-nombre {
  font-family: var(--face-pixel);
  font-size: 15px;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: center;
}

/* La estantería. Con scroll propio: son veintisiete y van a ser muchos más. */
.inv-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
  gap: 8px;
  overflow-y: auto;
  max-height: 46vh;
  padding: 4px 6px 4px 2px;
}
.inv-card {
  display: grid;
  justify-items: center;
  gap: 3px;
  padding: 8px 5px 9px;
  border: 0;
  border-radius: 12px;
  background: rgba(5, 4, 12, .4);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .1);
  color: #fff;
  cursor: pointer;
  transition: transform 150ms var(--ease-pop), box-shadow 150ms ease, background 150ms ease;
}
.inv-card:hover { transform: translateY(-3px); background: rgba(5, 4, 12, .6); }
.inv-card.on {
  background: rgba(168, 244, 37, .16);
  box-shadow: inset 0 0 0 2px var(--lime), 0 0 20px rgba(168, 244, 37, .22);
}
.inv-nombre {
  font-family: var(--face-ui);
  font-size: 11px;
  line-height: 1.25;
  text-align: center;
  color: rgba(255, 255, 255, .78);
}
.inv-icono {
  display: block;
  background-repeat: no-repeat;
  image-rendering: pixelated;
  filter: drop-shadow(0 4px 6px rgba(0, 0, 0, .5));
}
.inv-pie {
  margin: 0;
  text-align: center;
  font-family: var(--face-ui);
  font-size: 12px;
  color: rgba(255, 255, 255, .58);
}
.inv-pie.parpadeo { animation: inv-parpadeo 520ms ease; color: #ffd166; }
@keyframes inv-parpadeo {
  0%, 100% { transform: none; }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

/* --- El disparo de la cámara de fotos ---------------------------------------
   Dos cosas a la vez, que es lo que se ve de verdad al disparar: el fogonazo
   blanco del flash y el obturador cerrando y abriendo. Dura un cuarto de
   segundo: más y estorba, menos y no se ve. */
.ap-visor.disparo::before,
.ap-visor.disparo::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
}
/* El fogonazo. */
.ap-visor.disparo::before {
  background: #fff;
  animation: ap-flash 260ms ease-out forwards;
}
@keyframes ap-flash {
  0% { opacity: .95; }
  25% { opacity: .55; }
  100% { opacity: 0; }
}
/* Y el obturador: dos hojas negras que se juntan y se abren. */
.ap-visor.disparo::after {
  background: linear-gradient(to bottom, #05040c 50%, #05040c 50%);
  animation: ap-obturador 260ms ease-in-out forwards;
}
@keyframes ap-obturador {
  0% { clip-path: inset(0 0 100% 0); }
  40% { clip-path: inset(0 0 0 0); }
  100% { clip-path: inset(100% 0 0 0); }
}

@media (prefers-reduced-motion: reduce) {
  .ap-visor.disparo::before,
  .ap-visor.disparo::after { display: none; }

  /* La cinta de prácticas se queda quieta: el paso cambia y ya está. Lo que NO
     se quita es el tachón —es la única señal de que has hecho lo que se pedía—,
     solo que aparece entero en vez de crecer; ni el rojo del candado, que es
     una respuesta y no un adorno. La sacudida sí se va: eso es puro movimiento. */
  .prac-linea,
  .prac-linea[data-paso="hecho"],
  .prac[data-golpe="nuevo"],
  .prac[data-golpe="no"],
  .prac-tramo[data-aqui="si"][data-on="no"],
  .prac-tramo[data-paso="prende"],
  .foco { animation: none; }
  .prac-linea[data-paso="hecho"] { opacity: .35; }
  .prac-linea[data-paso="hecho"] .prac-que::after { width: 100%; animation: none; }
}

/* --- Los objetivos de propina -----------------------------------------------
   Van debajo de los tres de siempre, con su letra más pequeña y el porcentaje
   que pagan a la derecha. El porcentaje no es adorno: es lo que hace que uno
   se plantee quedarse cinco minutos más en una casa de la que ya se podía ir. */
.obj-titulo--extra {
  margin-top: 12px;
  font-size: 17px;
  color: rgba(255, 255, 255, .55);
}
.obj-lista--extra .obj-item { font-size: 15px; color: rgba(255, 255, 255, .8); }
.obj-pago {
  margin-left: auto;
  padding-left: 8px;
  color: var(--lime);
  font-family: var(--face-pixel);
  font-size: 13px;
}

/* ==========================================================================
   EL ORÁCULO
   Lo que contesta la ouija o el espejo. Es la respuesta más cara del juego
   —quince o veinte de cordura, y la cordura ya no se recupera sola— así que
   sale en el centro y hay que darle para cerrarla: lo que acabas de pagar
   merece que lo leas entero.
   ========================================================================== */
.orc {
  position: fixed;
  inset: 0;
  z-index: 58;
  display: grid;
  place-items: center;
  background: rgba(4, 3, 10, .72);
  cursor: pointer;
}
.orc[hidden] { display: none; }

.orc-caja {
  position: relative;
  width: min(560px, 86vw);
  padding: 30px 34px 26px;
  border: 1px solid rgba(180, 150, 255, .4);
  border-radius: 18px;
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(150, 110, 255, .16), transparent 70%),
    #100b22;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .6), inset 0 0 0 1px rgba(255, 255, 255, .05);
  text-align: center;
  animation: orc-entra 280ms cubic-bezier(.2, 1.3, .4, 1);
}
.orc-caja--espejo { border-color: rgba(140, 200, 255, .45); }
.orc-caja--roto { border-color: rgba(255, 85, 102, .55); }

@keyframes orc-entra {
  0% { transform: scale(.9) translateY(14px); opacity: 0; }
  100% { transform: none; opacity: 1; }
}

.orc-marca {
  display: block;
  margin-bottom: 6px;
  font-size: 30px;
  color: rgba(190, 160, 255, .8);
  animation: orc-late 2.4s ease-in-out infinite;
}
@keyframes orc-late { 0%, 100% { opacity: .8; } 50% { opacity: .35; } }

.orc-titulo {
  margin: 0 0 14px;
  font-family: var(--face-pixel);
  font-size: 17px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .6);
}
/* La frase es lo que se ha pagado: es lo más gordo de la caja. */
.orc-texto {
  margin: 0 0 12px;
  font-size: 26px;
  line-height: 1.35;
  color: #fff;
  text-shadow: 0 0 22px rgba(160, 120, 255, .45);
}
.orc-pie { margin: 0; font-size: 15px; color: rgba(255, 255, 255, .5); }
.orc-precio {
  display: inline-block;
  margin-top: 14px;
  padding: 5px 12px;
  border-radius: 999px;
  background: rgba(255, 85, 102, .14);
  color: #ff8d99;
  font-family: var(--face-pixel);
  font-size: 13px;
}
.orc-cerrar {
  display: block;
  margin-top: 16px;
  font-size: 13px;
  color: rgba(255, 255, 255, .35);
}

/* ==========================================================================
   LA CAZA Y LA MUERTE
   Esto FALTABA ENTERO. El fichero de la caza pintaba su capa y sus rótulos
   desde el primer día, pero nunca hubo estilos para ellos: la capa existía,
   invisible, y la partida seguía igual de tranquila con el bicho detrás. De
   ahí que morirse no se notara — no es que no pasara nada, es que no se veía.
   ========================================================================== */
.cz {
  position: fixed;
  inset: 0;
  z-index: 45;
  pointer-events: none;
  display: grid;
  place-items: center;
}
.cz[hidden] { display: none; }

.cz-centro {
  display: grid;
  gap: 8px;
  justify-items: center;
  text-align: center;
  transform: translateY(-14vh);
}
.cz-rotulo {
  font-family: var(--face-pixel);
  font-size: clamp(26px, 4.4vw, 56px);
  letter-spacing: .06em;
  color: #fff;
  text-shadow: 0 0 24px rgba(0, 0, 0, .9), 0 4px 0 rgba(0, 0, 0, .6);
}
.cz-reloj {
  font-family: var(--face-pixel);
  font-size: clamp(13px, 1.5vw, 20px);
  letter-spacing: .08em;
  color: rgba(255, 255, 255, .78);
  text-shadow: 0 2px 8px rgba(0, 0, 0, .9);
}

/* --- EL AVISO: se ha ido la luz y todavía no se mueve ---------------------
   Oscuro y quieto. Son los dos peores segundos de la partida justamente
   porque no pasa nada: la viñeta se cierra despacio y el rótulo respira. */
.cz--aviso {
  background: radial-gradient(ellipse at center, transparent 25%, rgba(4, 3, 10, .85) 92%);
  animation: cz-cierra 700ms ease-out;
}
.cz--aviso .cz-rotulo { animation: cz-respira 1.5s ease-in-out infinite; }
@keyframes cz-cierra {
  0% { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes cz-respira {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .55; transform: scale(.985); }
}

/* --- LA CAZA: ya viene --------------------------------------------------- */
.cz--caza {
  background: radial-gradient(ellipse at center, transparent 18%, rgba(120, 8, 16, .5) 78%, rgba(60, 2, 8, .82) 100%);
  animation: cz-late 820ms ease-in-out infinite;
}
.cz--caza .cz-rotulo { color: #ff6a6a; }
@keyframes cz-late {
  0%, 100% { opacity: .78; }
  50% { opacity: 1; }
}

/* --- MUERTO: se acabó ----------------------------------------------------
   El mundo se queda en gris. No es un adorno: es la única manera de saber, de
   un vistazo y sin leer nada, que lo que ves ya no va contigo. */
.cz--muerto {
  background: radial-gradient(ellipse at center, transparent 30%, rgba(0, 0, 0, .72) 95%);
}
.cz--muerto .cz-rotulo {
  color: #d8d8d8;
  animation: cz-muere 1.1s ease-out;
}
@keyframes cz-muere {
  0% { transform: scale(1.5); opacity: 0; letter-spacing: .3em; }
  100% { transform: none; opacity: 1; letter-spacing: .06em; }
}

/* EL LIENZO EN GRIS. Va por una clase en el cuerpo y no dentro de Phaser
   porque es un filtro de imagen y el navegador lo hace gratis; hacerlo en el
   motor costaría una pasada de pantalla entera cada fotograma. */
body.esta-muerto canvas {
  filter: grayscale(1) brightness(.72) contrast(1.05);
  transition: filter 900ms ease-out;
}

/* --- EL ZARPAZO: el instante en que te pilla ----------------------------- */
.cz-zarpazo {
  position: fixed;
  inset: 0;
  z-index: 46;
  pointer-events: none;
  background: radial-gradient(ellipse at center, rgba(255, 40, 40, .55), rgba(90, 0, 6, .95));
  animation: cz-zarpa 900ms ease-out forwards;
}
@keyframes cz-zarpa {
  0% { opacity: 0; }
  12% { opacity: 1; }
  100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .cz--aviso, .cz--caza, .cz--aviso .cz-rotulo, .cz--muerto .cz-rotulo, .cz-zarpazo { animation: none; }
}

/* El cartel de muerto se aparta a los tres segundos: arriba, pequeño y sin
   tapar nada. Estar muerto es quedarse de espectador un buen rato, y ese rato
   hay que poder verlo. */
.cz--muerto.cz--arriba { background: none; }
.cz--muerto.cz--arriba .cz-centro {
  transform: translateY(calc(-50vh + 46px));
  padding: 7px 16px;
  border-radius: 999px;
  background: rgba(4, 3, 10, .72);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12);
  transition: transform 600ms ease, padding 600ms ease;
}
.cz--muerto.cz--arriba .cz-rotulo { font-size: 18px; animation: none; }
.cz--muerto.cz--arriba .cz-reloj { font-size: 11px; }


/* ==========================================================================
   DE DÓNDE VINO EL RUIDO
   Un arco en el borde, en la dirección de lo que has oído. Ni flecha ni punto:
   un oído no sabe distancias, así que esto tampoco.
   ========================================================================== */
.rd {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity .45s ease;
  z-index: 6;
}
.rd.on { opacity: 1; transition: opacity .12s ease; }

.rd-arco {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(96vmin, 1100px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%) rotate(var(--a, 0deg));
  border-radius: 50%;
  /* El gajo: opaco donde suena y desvanecido hacia los lados, para que se lea
     como «por ahí» y no como «justo ahí». */
  background: conic-gradient(
    from calc(var(--ancho, 34deg) / -2),
    rgba(255, 240, 210, var(--fuerza, .2)),
    rgba(255, 240, 210, 0) var(--ancho, 34deg)
  );
  /* Y solo el borde: el centro se recorta, que si no se tiñe media pantalla. */
  -webkit-mask: radial-gradient(closest-side, transparent 76%, #000 92%);
  mask: radial-gradient(closest-side, transparent 76%, #000 92%);
}


/* =============================================================================
   EL MANDO DEL FANTASMA
   Abajo del todo y sin adornos: quien lleva al bicho no tiene mochila que
   mirar, tiene tres botones y una correa.
============================================================================= */
.mando {
  position: absolute;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  z-index: 8;
  display: grid;
  gap: 8px;
  justify-items: center;
  padding: 12px 16px;
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(28, 12, 40, .82), rgba(10, 6, 18, .9));
  box-shadow: inset 0 0 0 1px rgba(200, 120, 255, .22), 0 16px 40px rgba(0, 0, 0, .6);
  pointer-events: auto;
}
.mando[hidden] { display: none; }

.mando-cinta { display: flex; align-items: center; gap: 10px; }
.mando-quien {
  font-family: var(--face-pixel);
  font-size: 13px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(220, 180, 255, .8);
}
.mando-caza, .mando-libre {
  font-family: var(--face-pixel);
  font-size: 12px;
  padding: 3px 8px;
  border-radius: 999px;
}
.mando-caza { background: rgba(255, 60, 80, .22); color: #ff8a9a; }
.mando-libre { background: rgba(120, 200, 255, .18); color: #9fd8ff; }

.mando-botones { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.mando-btn {
  display: grid;
  gap: 3px;
  justify-items: center;
  min-width: 116px;
  padding: 9px 14px;
  border: 0;
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(255, 255, 255, .08), rgba(255, 255, 255, .02));
  box-shadow: inset 0 0 0 1px rgba(200, 120, 255, .25);
  color: #f0e6ff;
  cursor: pointer;
  transition: transform 120ms var(--ease-pop), box-shadow 120ms ease;
}
.mando-btn:hover:not(:disabled) {
  transform: translateY(-1px);
  box-shadow: inset 0 0 0 1px rgba(220, 160, 255, .55);
}
.mando-btn:disabled { filter: grayscale(.7) brightness(.65); cursor: not-allowed; }
.mando-btn-t { font-family: var(--face-pixel); font-size: 15px; }
.mando-btn-k {
  font-family: var(--face-ui);
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .45);
}
.mando-btn-c { font-family: var(--face-pixel); font-size: 12px; color: #ffb14d; }

.mando-pie {
  margin: 0;
  font-family: var(--face-ui);
  font-size: 11px;
  color: rgba(255, 255, 255, .5);
  text-align: center;
}

/* =============================================================================
   EL SUSURRO
   =============================================================================
   Lo que se oye decir cuando no llevas la caja en la mano. Una línea baja, en
   cursiva y sin nombre: se lee y se va. NO es chat —el chat va arriba, con el
   nombre de quien habla— y esa diferencia es justo lo que hay que ver de un
   vistazo, porque al chat se le contesta y a esto no.
============================================================================= */
.susurro {
  position: fixed;
  left: 50%;
  bottom: 16%;
  translate: -50% 0;
  z-index: 60;
  max-width: min(46ch, 84vw);
  text-align: center;
  font-family: var(--face-ui);
  font-style: italic;
  font-size: clamp(15px, 1.5vw, 19px);
  line-height: 1.5;
  color: rgba(226, 214, 255, .92);
  text-shadow: 0 2px 10px #000, 0 0 26px rgba(0, 0, 0, .9);
  pointer-events: none;
  opacity: 0;
  transition: opacity 900ms ease;
}
.susurro[data-on='true'] { opacity: 1; transition: opacity 260ms ease; }

/* =============================================================================
   EL MINIMAPA DEL MODO FÁCIL
   Abajo a la izquierda y acercado, como el mapa de cualquier juego. Con el
   tabulador se abre entero por encima de todo: acercado para andar, entero para
   decidir.
============================================================================= */
.mm {
  position: absolute;
  left: 18px;
  bottom: 18px;
  z-index: 14;
  /* MÁS GRANDE QUE ANTES. Con 246 se veía la habitación en la que estabas y
     poco más; el sitio de una esquina da para esto sin comerse la partida. */
  width: 300px;
  height: 300px;
  border-radius: 14px;
  /* Verde y no morado: es una pantalla de visión nocturna, no un panel del
     juego. El marco doble —una línea verde por dentro y el negro por fuera—
     es lo que le da el aire de aparato en vez de recuadro pegado. */
  background: #050c07;
  box-shadow:
    inset 0 0 0 1px rgba(127, 230, 160, .28),
    inset 0 0 30px rgba(90, 220, 140, .07),
    0 0 0 1px rgba(0, 0, 0, .6),
    0 14px 38px rgba(0, 0, 0, .6);
  pointer-events: none;
  overflow: hidden;
  /* Se aparta cuando no se mira: en una casa a oscuras, una caja encendida en
     una esquina se lleva la vista. Al pasar el ratón por encima se enciende. */
  opacity: .82;
  transition: opacity 200ms ease, width 220ms ease, height 220ms ease,
              left 220ms ease, bottom 220ms ease, border-radius 220ms ease;
}
.mm:hover { opacity: 1; }

.mm-lienzo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* EL VELO DE LA CÁMARA: las rayas horizontales y el oscurecido de los cantos.
   Va aquí y no dibujado en el lienzo porque no cambia nunca — repintarlo
   sesenta veces por segundo sería tirar el trabajo. Y es lo que convierte un
   dibujo verde en una pantalla: sin las rayas parece un mapa de colores raros;
   con ellas se entiende de qué va sin explicarlo. */
.mm-velo {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0) 0 2px,
      rgba(0, 0, 0, .22) 2px 3px),
    radial-gradient(
      120% 120% at 50% 50%,
      rgba(0, 0, 0, 0) 52%,
      rgba(0, 0, 0, .55) 100%);
}

/* El recordatorio del atajo. Muy apagado: hace falta la primera noche y estorba
   todas las demás. */
.mm-pie {
  position: absolute;
  right: 10px;
  bottom: 8px;
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--face-ui);
  font-size: 10px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: rgba(150, 215, 175, .45);
  pointer-events: none;
}
.mm-tecla {
  padding: 2px 6px;
  border-radius: 5px;
  background: rgba(127, 230, 160, .12);
  box-shadow: inset 0 0 0 1px rgba(127, 230, 160, .25);
  color: rgba(200, 250, 220, .85);
  font-weight: 700;
}

/* --- ENTERO, con el tabulador ------------------------------------------------
   Se queda en el mismo elemento y solo crece: así la transición lleva de uno a
   otro sin cortes, y no hay dos mapas que mantener sincronizados. */
.mm--grande {
  left: 50%;
  bottom: 50%;
  width: min(78vmin, 760px);
  height: min(78vmin, 760px);
  transform: translate(-50%, 50%);
  border-radius: 16px;
  opacity: 1;
  background: #050c07;
  box-shadow:
    inset 0 0 0 1px rgba(127, 230, 160, .4),
    inset 0 0 60px rgba(90, 220, 140, .06),
    0 0 0 1px rgba(0, 0, 0, .7),
    0 30px 90px rgba(0, 0, 0, .75);
}
.mm--grande .mm-pie { font-size: 11.5px; right: 16px; bottom: 13px; }

/* Con el mapa abierto, el resto del HUD se aparta: es una pausa para mirar el
   plano, no una capa más encima de la partida. */
body.mm-grande .hud > *:not(.mm) { opacity: .25; transition: opacity 200ms ease; }

/* En pantallas bajas se encoge: el minimapa no puede comerse el sitio del
   material, que es lo que se usa de verdad. */
@media (max-height: 760px), (max-width: 900px) {
  .mm { width: 220px; height: 220px; left: 12px; bottom: 12px; }
  .mm-pie { display: none; }
  .mm--grande { width: min(86vmin, 620px); height: min(86vmin, 620px); }
}

@media (prefers-reduced-motion: reduce) {
  .mm { transition: none; }
}

/* =============================================================================
   EL CURSOR DE LA PARTIDA
   Una imagen: la dibuja el sistema operativo, va a la velocidad del ratón y no
   cuesta un fotograma. El dibujo está en `--cursor-mira` (client/css/tokens.css)
   y cuando se ve, en client/js/ui/puntero.js.

   `body.jugando` = el mando lo tiene el juego. Con la libreta o la estantería
   del camión delante esa clase se va y vuelve la flecha del sistema, que es con
   la que se pulsa en ellas.
============================================================================= */

body.jugando #game { cursor: var(--cursor-mira); }

/* Salvo encima de algo que se pulsa: el aro se abre y se enciende. Es el mismo
   gesto que hacía el cursor animado, ahora sin costar nada. */
body.jugando #game a,
body.jugando #game label,
body.jugando #game [role='button'],
body.jugando #game button:not([disabled]) { cursor: var(--cursor-pulsable); }

/* Y donde se escribe manda la barrita del sistema: dice donde va a caer la
   letra, y eso un punto no lo dice. */
body.jugando #game input:not([type='range']),
body.jugando #game textarea,
body.jugando #game [contenteditable='true'] { cursor: text; }

/* Aquí vivía la barra del ALIENTO, debajo del personaje: se enseñaba sola al
   correr y se iba sola al recuperarse. Correr ya no se acaba, así que no hay
   barra ni nada que colocar bajo el muñeco (shared/movement.js). */

/* =============================================================================
   EL DEMO QUE SIGUE AL RATÓN
   Un cuadro pequeño con el vídeo de cómo se usa el cacharro sobre el que estás.
   Ver client/js/ui/demo.js para cuándo aparece.

   VA PEGADO AL CURSOR y por encima de todo lo demás, así que lo primero que hace
   es no comerse ningún clic: `pointer-events: none`. Está justo encima del sitio
   al que vas a pulsar.
============================================================================= */
.demo {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 500;
  width: 232px;
  padding: 8px;
  border-radius: 12px;
  background: linear-gradient(180deg, rgba(23, 16, 44, .97), rgba(11, 8, 24, .97));
  box-shadow:
    inset 0 0 0 1px rgba(168, 244, 37, .28),
    0 14px 34px rgba(0, 0, 0, .55);
  pointer-events: none;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 130ms ease, transform 130ms ease;
  font-family: Rubik, system-ui, sans-serif;
}
.demo--on { opacity: 1; transform: none; }

/* El marco de la animación. La proporción es la del lienzo que la dibuja
   (client/js/ui/demoanim.js): 232 por 130. */
.demo-marco {
  position: relative;
  aspect-ratio: 232 / 130;
  border-radius: 8px;
  overflow: hidden;
  background: #08060f;
  display: grid;
  place-items: center;
}
.demo-lienzo {
  width: 100%;
  height: 100%;
  display: block;
}
.demo-marco {
  background:
    radial-gradient(70% 70% at 50% 78%, rgba(157, 107, 255, .16), transparent 70%),
    #08060f;
}

.demo-nombre {
  display: block;
  margin: 7px 2px 1px;
  font-size: 13px;
  font-weight: 600;
  color: var(--lime, #a8f425);
}
.demo-pista {
  display: block;
  margin: 0 2px 2px;
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--ink-dim, #a79fc8);
}

/* Con el dedo no hay ratón al que seguir, y el cuadro taparía media pantalla. */
@media (hover: none) and (pointer: coarse) {
  .demo { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .demo { transition: opacity 130ms ease; transform: none; }
}
