/* =============================================================================
   POLTERBYTE · el panel de dentro
   El resumen, la gente y el catálogo de casas.

   La idea: una sala de control de una empresa que se dedica a algo muy serio
   —vender licencias, mirar métricas— pero cuyo producto son fantasmas. Así que
   la retícula es de panel de control de verdad, la tipografía de rótulo es de
   píxel, y el tono de los textos es el de alguien que lleva demasiado tiempo
   en este negocio.

   Nada de librerías de gráficas: las barras y los anillos son SVG a mano, y por
   eso pintan como el resto de la casa en vez de como una hoja de cálculo.
============================================================================= */

/* --- Cabecera de sección ---------------------------------------------------- */
.dash-head { margin-bottom: 22px; }

.dash-seccion { margin: 0 0 34px; }
.dash-seccion-head {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(157, 107, 255, .18);
}
.dash-h2 {
  margin: 0;
  font-family: var(--face-pixel);
  font-size: 30px;
  letter-spacing: .05em;
  color: var(--ink);
}
.dash-k {
  font-family: var(--face-pixel);
  font-size: 17px;
  letter-spacing: .07em;
  color: var(--ink-dim);
  text-transform: uppercase;
}
.dash-sub { font-size: 13.5px; line-height: 1.45; color: var(--ink-faint); }
.dash-vacio {
  margin: 10px 0 0;
  padding: 14px;
  border: 1px dashed rgba(157, 107, 255, .28);
  border-radius: var(--r-sm);
  font-size: 14px;
  color: var(--ink-faint);
}

/* El cartel de modo pruebas. Va con rayas de obra a propósito: los ingresos de
   abajo son de mentira y eso no puede confundirse ni de reojo. */
.dash-aviso {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 26px;
  padding: 12px 16px;
  border-radius: var(--r-sm);
  background:
    repeating-linear-gradient(-45deg,
      rgba(255, 196, 71, .14) 0 12px,
      rgba(255, 196, 71, .04) 12px 24px);
  box-shadow: inset 0 0 0 1px rgba(255, 196, 71, .4);
  color: var(--ink-dim);
  font-size: 14px;
}
.dash-aviso strong {
  flex: none;
  font-family: var(--face-pixel);
  font-size: 20px;
  letter-spacing: .1em;
  color: var(--amber);
}

/* --- La caja ---------------------------------------------------------------- */
.dash-caja {
  display: grid;
  grid-template-columns: minmax(260px, 1.2fr) minmax(200px, .8fr) minmax(280px, 1.6fr);
  gap: 14px;
}

.dash-tarjeta,
.dash-gordo {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 18px;
  border-radius: var(--r);
  background: var(--glass-2);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .22);
}
.dash-tarjeta--anillo { align-items: center; text-align: center; }
.dash-tarjeta--ancha { min-width: 0; }

/* El número gordo: el dinero. Que se lea desde la puerta. */
.dash-gordo {
  justify-content: center;
  background:
    radial-gradient(120% 100% at 0% 0%, rgba(168, 244, 37, .16), transparent 60%),
    var(--glass-2);
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .38);
}
.dash-euros {
  font-family: var(--face-pixel);
  font-size: clamp(44px, 6vw, 74px);
  line-height: .95;
  color: var(--lime);
  text-shadow: 0 0 32px rgba(168, 244, 37, .35);
}

/* --- En directo ------------------------------------------------------------- */
.dash-vivo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
}
.dash-vivo-item {
  display: grid;
  gap: 4px;
  padding: 14px 16px;
  border-radius: var(--r-sm);
  background: var(--glass);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .2);
}
.dash-vivo-v {
  font-family: var(--face-pixel);
  font-size: 40px;
  line-height: 1;
  color: var(--ink);
}
/* Cuando hay alguien dentro, la tarjeta respira. Es el único sitio del panel
   con animación, y por eso se ve: si todo parpadeara no se vería ninguno. */
.dash-vivo-item.on {
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .55);
  animation: dash-latido 2.4s ease-in-out infinite;
}
.dash-vivo-item.on .dash-vivo-v { color: var(--lime); }
@keyframes dash-latido {
  0%, 100% { background: var(--glass); }
  50% { background: rgba(168, 244, 37, .08); }
}

/* --- Series y tablas -------------------------------------------------------- */
.dash-series,
.dash-tablas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 14px;
}

.dash-filas { display: grid; gap: 2px; }
.dash-fila {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 10px;
  align-items: baseline;
  padding: 7px 8px;
  border-radius: 6px;
  font-size: 14px;
}
.dash-fila:nth-child(odd) { background: rgba(157, 107, 255, .07); }
.dash-fila strong { font-family: var(--face-pixel); font-size: 19px; letter-spacing: .03em; }

/* =============================================================================
   LAS GRÁFICAS (SVG a mano)
============================================================================= */
.gr { position: relative; width: 100%; }
.gr-svg { display: block; width: 100%; height: 100%; overflow: visible; }
.gr-guia { stroke: rgba(157, 107, 255, .16); stroke-width: .4; vector-effect: non-scaling-stroke; }
.gr-barra { opacity: .82; transition: opacity 120ms ease; }
.gr-barra:hover { opacity: 1; }
.gr-area { opacity: .16; }
.gr-linea { fill: none; stroke-width: 2; vector-effect: non-scaling-stroke; }
/* El tope de la escala, arriba a la derecha: sin él «alto» no significa nada. */
.gr-tope {
  position: absolute;
  top: -4px;
  right: 0;
  font-family: var(--face-pixel);
  font-size: 15px;
  color: var(--ink-faint);
}

.gr-anillo { display: block; }
.gr-anillo-fondo { fill: none; stroke: rgba(157, 107, 255, .18); stroke-width: 4; }
.gr-anillo-trozo { fill: none; stroke-width: 4; stroke-linecap: round; }
.gr-anillo-cifra {
  fill: var(--ink);
  font-family: var(--face-pixel);
  font-size: 11px;
  text-anchor: middle;
}

/* =============================================================================
   EL PERSONAL
============================================================================= */
.usr-barra {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 14px;
}
.usr-buscar {
  flex: 1;
  max-width: 380px;
  padding: 10px 14px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--glass-2);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .28);
  color: var(--ink);
  font-family: var(--face-ui);
  font-size: 15px;
}
.usr-buscar:focus { outline: none; box-shadow: inset 0 0 0 1px var(--lime); }

.usr-lista { display: grid; gap: 8px; }
.usr-ficha {
  display: grid;
  grid-template-columns: 46px minmax(180px, 1.4fr) minmax(220px, 1fr) auto;
  gap: 16px;
  align-items: center;
  padding: 12px 16px;
  border-radius: var(--r-sm);
  background: var(--glass);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .18);
}
.usr-ficha.apagada { opacity: .45; }

/* La inicial en un cuadrado, como una chapa de empleado. Nadie tiene foto y no
   hace falta: lo que se busca en esta lista es el nombre. */
.usr-cara {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 10px;
  background: rgba(157, 107, 255, .18);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .4);
  font-family: var(--face-pixel);
  font-size: 26px;
  color: var(--violet);
}
.usr-cara.jefe {
  background: rgba(168, 244, 37, .16);
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .5);
  color: var(--lime);
}

.usr-quien { display: grid; gap: 3px; min-width: 0; }
.usr-nombre {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-family: var(--face-pixel);
  font-size: 23px;
  letter-spacing: .03em;
}
.usr-chapa {
  padding: 2px 7px;
  border-radius: 4px;
  font-family: var(--face-pixel);
  font-size: 13px;
  letter-spacing: .08em;
}
.usr-chapa--jefe { background: rgba(168, 244, 37, .18); color: var(--lime); }
.usr-chapa--pago { background: rgba(168, 244, 37, .2); color: var(--lime); }
/* REGALADA NO ES PAGADA, y se ve de lejos que son dos cosas. El verde es de la
   que trajo dinero; esta va en cian y con el nombre de su origen escrito. */
.usr-chapa--regalo { background: rgba(53, 224, 240, .16); color: var(--cyan); }
.usr-chapa--fuera { background: rgba(255, 85, 102, .18); color: var(--danger); }

/* --- Los embudos del personal ------------------------------------------------
   «Se registró y no ha comprado» es la lista más útil que hay aquí, y hasta
   ahora no había manera de sacarla. Van como pestañas y no como desplegable
   porque se cambia de una a otra constantemente. */
.usr-embudos {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 14px;
}
.usr-embudo {
  padding: 7px 13px;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, .06);
  color: var(--ink-dim);
  font-family: inherit;
  font-size: 13.5px;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.usr-embudo:hover:not(:disabled) { background: rgba(255, 255, 255, .12); color: var(--ink); }
.usr-embudo.on { background: var(--lime); color: #06210a; font-weight: 700; }
.usr-embudo:disabled { opacity: .35; cursor: default; }
.usr-embudo--copiar { margin-left: auto; }

.usr-correos {
  width: 100%;
  min-height: 70px;
  margin-bottom: 10px;
  padding: 10px;
  border: 0;
  border-radius: 8px;
  background: #0a0718;
  box-shadow: inset 0 0 0 1px var(--panel-edge);
  color: var(--ink-dim);
  font-size: 12.5px;
  resize: vertical;
}

/* La columna del nombre abre la ficha: que se note que se puede pinchar. */
.usr-quien[role='button'] { cursor: pointer; border-radius: 8px; }
.usr-quien[role='button']:hover .usr-nombre { color: var(--lime); }
.usr-quien[role='button']:focus-visible { outline: 2px solid var(--lime); outline-offset: 4px; }

.usr-cifras { display: flex; gap: 18px; flex-wrap: wrap; }
.usr-cifra { display: grid; }
.usr-cifra strong { font-family: var(--face-pixel); font-size: 21px; }
.usr-cifra small { font-size: 11.5px; color: var(--ink-faint); }

.usr-mandos { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.usr-btn {
  padding: 7px 11px;
  border: 0;
  border-radius: 6px;
  background: rgba(157, 107, 255, .14);
  color: var(--ink-dim);
  font-family: var(--face-pixel);
  font-size: 15px;
  letter-spacing: .04em;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.usr-btn:hover { background: rgba(157, 107, 255, .28); color: var(--ink); }
.usr-btn.on { background: rgba(168, 244, 37, .16); color: var(--lime); }
.usr-btn:disabled { opacity: .4; cursor: default; }

/* El de borrar va en rojo desde el principio: un botón que no se deshace no
   debería parecerse a los que sí. */
.usr-btn--peligro { color: rgba(255, 120, 130, .85); background: rgba(255, 85, 102, .12); }
.usr-btn--peligro:hover { background: rgba(255, 85, 102, .26); color: #fff; }

/* =============================================================================
   LAS CASAS

   Una ficha es un botón entero: pinchas donde sea y entras a la obra. Por eso
   el plano ocupa lo que ocupa y por eso al pasar por encima se levanta y se
   enciende — tiene que pedir el clic.

   Los tres iconos de la esquina son la excepción, y se nota: son pequeños, van
   agrupados y solo se encienden al apuntarlos.
============================================================================= */
.casas {
  display: grid;
  /* Con el plano más bajo, la ficha cabe en menos ancho: a 340 px entraban tres
     casas en una pantalla de 1440 y ahora entran cuatro. En una pantalla de
     gestión, una fila más es una comparación más. */
  grid-template-columns: repeat(auto-fill, minmax(288px, 1fr));
  gap: 16px;
}

.casa {
  display: flex;
  flex-direction: column;
  border-radius: var(--r);
  background: var(--glass-2);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .22);
  overflow: hidden;
  cursor: pointer;
  transition: transform 160ms var(--ease-pop), box-shadow 160ms ease;
}
.casa:hover,
.casa:focus-visible {
  transform: translateY(-3px);
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .55), 0 14px 34px rgba(0, 0, 0, .5);
  outline: none;
}
/* El cuartel lleva su propio filo: es el único mapa distinto de los demás. */
.casa.es-cuartel { box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .38); }
/* Cerrada al público: apagada, pero ahí. Es lo que la separa de borrarla. */
.casa.cerrada .casa-plano { filter: grayscale(.8) brightness(.6); }
.casa.cerrada .casa-nombre { color: var(--ink-faint); }

/* --- El plano --------------------------------------------------------------- */
.casa-plano {
  /* Bloque con posición, no rejilla: el plano va dentro colocado a mano de
     borde a borde. En rejilla, el `height: 100%` del lienzo se quedaba sin
     referencia y la casa salía cortada por abajo. */
  position: relative;
  /* Alto FIJO para todas. Los planos vienen de casas de 24x16 y de 38x30, y
     dejando que cada uno mandara su alto la rejilla salía como una escalera y
     ninguna ficha empezaba a la misma altura que su vecina. */
  /* MÁS BAJO QUE ANCHO, y bastante. A 16/10 el plano se comía media ficha y en
     una pantalla solo cabían tres casas: en una pantalla de gestión lo que se
     viene a hacer es comparar, y para comparar hacen falta varias a la vez. El
     plano sigue reconociéndose de sobra a esta altura — es una miniatura, no el
     editor. */
  aspect-ratio: 16 / 7;
  background:
    radial-gradient(120% 100% at 50% 0%, rgba(157, 107, 255, .08), transparent 70%),
    #06050b;
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .14);
  overflow: hidden;
}
.map-mini {
  /* Que quepa ENTERO, sea la casa apaisada o cuadrada. */
  position: absolute;
  inset: 12px;
  width: calc(100% - 24px);
  height: calc(100% - 24px);
  object-fit: contain;
  image-rendering: pixelated;
}

/* El velo de «entrar»: solo al pasar por encima, y encima del plano, que es
   donde está mirando el ojo cuando decide entrar. */
.casa-velo {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: linear-gradient(0deg, rgba(7, 6, 12, .88), rgba(7, 6, 12, .5));
  opacity: 0;
  transition: opacity 160ms ease;
}
.casa-velo span {
  padding: 9px 16px;
  border-radius: 999px;
  background: var(--lime);
  color: #0a0714;
  font-family: var(--face-pixel);
  font-size: 20px;
  letter-spacing: .04em;
  transform: translateY(6px);
  transition: transform 180ms var(--ease-pop);
}
.casa:hover .casa-velo,
.casa:focus-visible .casa-velo { opacity: 1; }
.casa:hover .casa-velo span,
.casa:focus-visible .casa-velo span { transform: none; }

.casa-chapas {
  position: absolute;
  top: 8px;
  left: 8px;
  display: flex;
  gap: 5px;
}
.casa-chapa {
  padding: 3px 8px;
  border-radius: 5px;
  font-family: var(--face-pixel);
  font-size: 14px;
  letter-spacing: .08em;
  backdrop-filter: blur(3px);
}
.casa-chapa--cuartel { background: rgba(168, 244, 37, .22); color: var(--lime); }
.casa-chapa--cerrada { background: rgba(255, 85, 102, .26); color: #ffd0d6; }

/* --- El cuerpo -------------------------------------------------------------- */
.casa-cuerpo { display: grid; gap: 8px; padding: 12px 14px 14px; }

.casa-cab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 34px;
}
.casa-nombre {
  margin: 0;
  min-width: 0;
  font-family: var(--face-pixel);
  font-size: 26px;
  letter-spacing: .03em;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* El campo de renombrar ocupa el sitio del título, con su misma letra: al
   escribir se ve exactamente cómo va a quedar. */
.casa-nombre-campo {
  flex: 1;
  min-width: 0;
  padding: 4px 8px;
  border: 0;
  border-radius: 6px;
  background: rgba(0, 0, 0, .45);
  box-shadow: inset 0 0 0 1px var(--lime);
  color: var(--ink);
  font-family: var(--face-pixel);
  font-size: 26px;
  letter-spacing: .03em;
}
.casa-nombre-campo:focus { outline: none; }

.casa-mandos { display: flex; gap: 4px; flex: none; }
.casa-icono {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border: 0;
  border-radius: 8px;
  background: rgba(157, 107, 255, .12);
  color: var(--ink-faint);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.casa-icono:hover { background: rgba(168, 244, 37, .2); color: var(--lime); }
.casa-icono:disabled { opacity: .4; cursor: default; }

/* La línea de identidad: tamaño, cuánto hay pintado y cuándo se tocó. */
.casa-ficha1 {
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex-wrap: wrap;
  margin: -4px 0 0;
  font-size: 12.5px;
  color: var(--ink-faint);
}
.casa-ficha1 b {
  font-family: var(--face-pixel);
  font-size: 15px;
  font-weight: 400;
  color: var(--ink-dim);
}

/* Los cuatro datos que se comparan entre casas, en cuatro columnas clavadas.
   El tamaño y el porcentaje pintado se han subido a la línea de la fecha: son
   dato de identidad, no de comparación, y aquí obligaban a partir las pastillas
   en renglones desiguales. */
.casa-datos {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 5px;
  padding: 8px 0 2px;
  border-top: 1px solid rgba(157, 107, 255, .16);
}
.casa-dato {
  display: flex;
  align-items: baseline;
  gap: 5px;
  min-width: 0;
  padding: 4px 8px;
  border-radius: 6px;
  background: rgba(157, 107, 255, .09);
}
.casa-dato strong {
  font-family: var(--face-pixel);
  font-size: 16px;
  color: var(--ink);
  white-space: nowrap;
}
.casa-dato small {
  font-size: 12px;
  color: var(--ink-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* El semáforo de obra.
   Iba con una barra de color de 3px a la izquierda, que es el adorno con el que
   se marca un aviso cuando no se ha decidido cómo marcarlo. Ahora el color está
   donde de verdad informa —en la palabra que dice el estado— y el bloque lleva
   un fondo teñido del mismo tono: se distingue de un vistazo entre seis fichas
   sin pintar una raya que no significa nada por sí sola. */
.casa-estado {
  margin: 2px 0 0;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink-faint);
}
.casa-estado strong {
  font-family: var(--face-pixel);
  font-size: 15px;
  letter-spacing: .05em;
}
.casa-estado.lista { background: rgba(168, 244, 37, .09); }
.casa-estado.lista strong { color: var(--lime); }
.casa-estado.obra { background: rgba(255, 196, 71, .09); }
.casa-estado.obra strong { color: var(--amber); }

@media (max-width: 900px) {
  .dash-caja { grid-template-columns: 1fr; }
  .usr-ficha { grid-template-columns: 44px 1fr; }
  .usr-cifras, .usr-mandos { grid-column: 1 / -1; justify-content: flex-start; }
}

/* =============================================================================
   EN DIRECTO
   La lista de salas abiertas. Se refresca sola, así que el punto de la
   izquierda tiene que decir de un vistazo si ahí dentro está pasando algo.
============================================================================= */
.viv-lista { display: grid; gap: 8px; max-width: 900px; }

.viv-ficha {
  display: grid;
  grid-template-columns: 14px 1fr auto auto;
  gap: 16px;
  align-items: center;
  padding: 14px 18px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--glass);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .2);
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  transition: background 140ms ease, box-shadow 140ms ease, transform 140ms var(--ease-pop);
}
.viv-ficha:hover {
  transform: translateX(2px);
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .45);
}
.viv-ficha.contrato { box-shadow: inset 0 0 0 1px rgba(255, 79, 216, .35); }

/* El punto: gris en el cuartel, latiendo en rosa si hay contrato en marcha.
   Es lo único que hay que mirar para saber dónde está pasando algo. */
.viv-punto {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: rgba(167, 159, 200, .35);
}
.viv-punto--vivo {
  background: var(--pink);
  box-shadow: 0 0 12px rgba(255, 79, 216, .8);
  animation: viv-late 1.6s ease-in-out infinite;
}
@keyframes viv-late {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .45; transform: scale(.75); }
}

.viv-quien { display: grid; gap: 2px; min-width: 0; }
.viv-nombre { font-family: var(--face-pixel); font-size: 24px; letter-spacing: .03em; }
.viv-chapas { display: flex; gap: 6px; flex-wrap: wrap; }
.viv-chapa { background: rgba(157, 107, 255, .16); color: var(--ink-dim); }
.viv-chapa--roja { background: rgba(255, 79, 216, .18); color: var(--pink); }
.viv-chapa--morada { background: rgba(157, 107, 255, .24); color: var(--violet); }
.viv-ir { font-family: var(--face-pixel); font-size: 19px; color: var(--lime); }

.viv-vacio {
  display: grid;
  gap: 6px;
  padding: 26px 24px;
  border: 1px dashed rgba(157, 107, 255, .3);
  border-radius: var(--r);
  background: var(--glass);
  color: var(--ink-faint);
  font-size: 14px;
  line-height: 1.5;
}
.viv-vacio strong {
  font-family: var(--face-pixel);
  font-size: 26px;
  letter-spacing: .05em;
  color: var(--ink-dim);
}


/* La ficha de caza en el panel de partidas: en rojo y latiendo, porque
   mientras dura no hay nada más que mirar en esa pantalla. */
.pt-caza {
  background: rgba(255, 79, 216, .1) !important;
  box-shadow: inset 0 0 0 1px rgba(255, 79, 216, .55) !important;
  animation: viv-late 1.1s ease-in-out infinite;
}
.pt-caza .pt-titulo { color: var(--pink); letter-spacing: .12em; }

/* =============================================================================
   EN DIRECTO
   La lista de salas abiertas. Se refresca sola, así que el punto de la
   izquierda tiene que decir de un vistazo si ahí dentro está pasando algo.
============================================================================= */
.viv-lista { display: grid; gap: 8px; max-width: 900px; }

.viv-ficha {
  display: grid;
  grid-template-columns: 14px 1fr auto auto;
  gap: 16px;
  align-items: center;
  padding: 14px 18px;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--glass);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .2);
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  transition: background 140ms ease, box-shadow 140ms ease, transform 140ms var(--ease-pop);
}
.viv-ficha:hover {
  transform: translateX(2px);
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .45);
}
.viv-ficha.contrato { box-shadow: inset 0 0 0 1px rgba(255, 79, 216, .35); }

/* El punto: gris en el cuartel, latiendo en rosa si hay contrato en marcha.
   Es lo único que hay que mirar para saber dónde está pasando algo. */
.viv-punto {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: rgba(167, 159, 200, .35);
}
.viv-punto--vivo {
  background: var(--pink);
  box-shadow: 0 0 12px rgba(255, 79, 216, .8);
  animation: viv-late 1.6s ease-in-out infinite;
}
@keyframes viv-late {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: .45; transform: scale(.75); }
}

.viv-quien { display: grid; gap: 2px; min-width: 0; }
.viv-nombre { font-family: var(--face-pixel); font-size: 24px; letter-spacing: .03em; }
.viv-chapas { display: flex; gap: 6px; flex-wrap: wrap; }
.viv-chapa { background: rgba(157, 107, 255, .16); color: var(--ink-dim); }
.viv-chapa--roja { background: rgba(255, 79, 216, .18); color: var(--pink); }
.viv-chapa--morada { background: rgba(157, 107, 255, .24); color: var(--violet); }
.viv-ir { font-family: var(--face-pixel); font-size: 19px; color: var(--lime); }

.viv-vacio {
  display: grid;
  gap: 6px;
  padding: 26px 24px;
  border: 1px dashed rgba(157, 107, 255, .3);
  border-radius: var(--r);
  background: var(--glass);
  color: var(--ink-faint);
  font-size: 14px;
  line-height: 1.5;
}
.viv-vacio strong {
  font-family: var(--face-pixel);
  font-size: 26px;
  letter-spacing: .05em;
  color: var(--ink-dim);
}


/* La ficha de caza en el panel de partidas: en rojo y latiendo, porque
   mientras dura no hay nada más que mirar en esa pantalla. */
.pt-caza {
  background: rgba(255, 79, 216, .1) !important;
  box-shadow: inset 0 0 0 1px rgba(255, 79, 216, .55) !important;
  animation: viv-late 1.1s ease-in-out infinite;
}
.pt-caza .pt-titulo { color: var(--pink); letter-spacing: .12em; }

/* ==========================================================================
   LA TIENDA
   Rejilla de fichas, no lista. El icono manda —es como se reconoce el cacharro
   dentro del juego— y el precio es lo más gordo, porque el precio es lo que se
   viene a tocar aquí.
   ========================================================================== */
.prd-barra {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 14px;
}
.prd-buscar {
  flex: 1;
  max-width: 320px;
  padding: 9px 12px;
  border: 1px solid var(--linea, #2a2242);
  border-radius: 9px;
  background: #0f0b1f;
  color: var(--tinta, #efeaff);
  font: 14px/1.2 Rubik, sans-serif;
}
.prd-buscar:focus { outline: none; border-color: #a8f425; }

.prd-rejilla {
  display: grid;
  /* A 190 px los nombres largos salían cortados con puntos suspensivos («Libro
     de escritura fanta…»). Veinte más y caben enteros, que es lo que se viene a
     leer. */
  grid-template-columns: repeat(auto-fill, minmax(212px, 1fr));
  gap: 12px;
}

.prd-ficha {
  position: relative;
  display: grid;
  gap: 8px;
  padding: 14px 14px 12px;
  border: 1px solid var(--linea, #2a2242);
  border-radius: 14px;
  background: linear-gradient(180deg, #1a1436, #140f2a);
  transition: border-color 140ms ease, transform 140ms ease, box-shadow 140ms ease;
}
.prd-ficha:hover {
  transform: translateY(-2px);
  border-color: #4a3d78;
  box-shadow: 0 8px 20px rgba(0, 0, 0, .35);
}
/* Retirado: se apaga, pero se sigue leyendo. Un producto fuera de la venta hay
   que poder encontrarlo para volver a meterlo. */
.prd-ficha.fuera { opacity: .5; filter: grayscale(.7); }
.prd-ficha.guardando { border-color: #ffd34d; }
.prd-ficha.hecho { border-color: #a8f425; }

.prd-icono {
  display: grid;
  place-items: center;
  height: 84px;
  border-radius: 10px;
  background: radial-gradient(circle at 50% 45%, rgba(168, 244, 37, .09), transparent 70%), #0d0920;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .05);
}
.prd-icono img,
.prd-icono canvas { image-rendering: pixelated; }

.prd-nombre {
  padding: 7px 9px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--tinta, #efeaff);
  font: 600 13px/1.2 Rubik, sans-serif;
  text-align: center;
  /* Los nombres largos se cortan con puntos suspensivos en vez de a machete.
     Al enfocar el campo se ve entero, que es cuando hace falta. */
  text-overflow: ellipsis;
}
.prd-nombre:hover { border-color: var(--linea, #2a2242); }
.prd-nombre:focus {
  outline: none;
  border-color: #a8f425;
  background: #0f0b1f;
  text-align: left;
}

.prd-pista {
  margin: 0;
  min-height: 30px;
  color: #8d83ad;
  font: 11.5px/1.35 Rubik, sans-serif;
  text-align: center;
}

/* El precio: grande, verde y en el centro. Es el dato de esta pantalla. */
.prd-linea {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 4px;
  padding: 6px 4px;
  border: 1px solid var(--linea, #2a2242);
  border-radius: 10px;
  background: #0d0920;
}
.prd-linea:focus-within { border-color: #a8f425; }
/* SIN LETRA DE PÍXEL EN UN DATO EDITABLE. Lo dice el sistema de diseño del
   propio proyecto —Silkscreen solo dentro del lienzo— y aquí además molesta:
   una cifra que se escribe se lee peor con una tipografía de píxel, y las
   cifras de tres dígitos bailaban de ancho entre tarjeta y tarjeta. */
.prd-moneda { color: #a8f425; font: 700 15px/1 Rubik, sans-serif; }
.prd-precio {
  width: 92px;
  border: 0;
  background: transparent;
  color: #a8f425;
  font: 700 21px/1 Rubik, sans-serif;
  text-align: center;
  /* Cifras de ancho fijo: sin esto, cambiar un 1 por un 8 mueve el precio de
     sitio mientras se escribe. */
  font-variant-numeric: tabular-nums;
}
.prd-precio:focus { outline: none; }
/* Sin las flechitas del navegador: aquí molestan más de lo que ayudan. */
.prd-precio::-webkit-outer-spin-button,
.prd-precio::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.prd-precio[type=number] { -moz-appearance: textfield; }

.prd-venta {
  padding: 7px 10px;
  border: 1px solid var(--linea, #2a2242);
  border-radius: 8px;
  background: #0f0b1f;
  color: #8d83ad;
  font: 600 11px/1 Rubik, sans-serif;
  letter-spacing: .09em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
}
.prd-venta:hover { color: var(--tinta, #efeaff); }
.prd-venta.on { border-color: rgba(168, 244, 37, .5); color: #a8f425; }

/* El identificador interno del cacharro. Hace falta —es lo que se busca al
   mirar el código— pero no es información de escaparate: se queda muy apagado y
   se enciende al pasar por encima de la ficha. */
.prd-nota {
  color: #4b4467;
  font: 10.5px/1 Rubik, sans-serif;
  letter-spacing: .06em;
  text-align: center;
  transition: color 140ms ease;
}
.prd-ficha:hover .prd-nota { color: #8d83ad; }

/* La foto de la casa, encima del plano: la misma que se ve en el terminal al
   elegir contrato. Aquí sale para comprobar de un vistazo cuáles la tienen. */
.casa-portada {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: .85;
}

/* ==========================================================================
   EL CATÁLOGO
   Todas las piezas de una hoja, para retirar las que no valgan. Rejilla densa
   a propósito: aquí se viene a barrer, y para barrer hay que ver mucho de una
   vez. Lo retirado no desaparece — se apaga y se le pone una cruz — porque
   volver a meterlo tiene que ser tan fácil como sacarlo.
   ========================================================================== */
.pza-barra {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 10px 0 12px;
}
.pza-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
  gap: 6px;
  align-items: end;
}
.pza {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 76px;
  /* Las piezas grandes se recortan a su casilla en vez de desbordarse encima de
     las vecinas: aquí se viene a reconocerlas de un vistazo, no a admirarlas. */
  overflow: hidden;
  padding: 6px;
  border: 1px solid var(--linea, #2a2242);
  border-radius: 9px;
  background: #0d0920;
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease;
}
.pza:hover { border-color: #6a5aa8; background: #140f2a; }
.pza-art { display: block; image-rendering: pixelated; }
.pza.fuera { opacity: .3; border-color: rgba(255, 85, 102, .4); }
.pza.fuera:hover { opacity: .55; }
.pza-marca {
  position: absolute;
  top: 3px;
  right: 5px;
  color: var(--danger, #ff5566);
  font: 12px/1 Silkscreen, monospace;
}

/* =============================================================================
   EL ENFADO DEL FANTASMA
   =============================================================================
   Una barra que se llena de rojo. Es el dato que más dice de cómo va a acabar la
   noche —de él dependen cuándo caza, cuánto le dura y las ganas que tiene de
   romper cosas— y un número suelto no se lee de un vistazo mientras pasan cosas.

   El color va del ámbar al rojo con el propio relleno, no a saltos: así se ve
   que está subiendo aunque no te sepas los tramos de memoria.
============================================================================= */
.pt-fila--ancha { display: grid; gap: 6px; }
.pt-enfado {
  position: relative;
  height: 16px;
  border-radius: 3px;
  background: rgba(0, 0, 0, .45);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .22);
  overflow: hidden;
}
.pt-enfado-lleno {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #d9a11e, #e2521f 55%, #ff2d2d);
  transition: width 400ms ease;
}
.pt-enfado-cifra {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--face-ui);
  font-size: 11px;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 1px 3px #000;
}
