/* EL PANEL: LA CAPA DE DISEÑO.
   ==========================================================================
   Va la última de todas a propósito: manda sobre `admin.css` y `panel.css`, que
   siguen guardando la estructura de cada pantalla. Aquí se decide cómo se ve.

   EL DIAGNÓSTICO, que es una sola cosa y explica casi todo lo demás:

     EL PANEL USABA LA LETRA DE PÍXEL COMO VOZ DE LA INTERFAZ. Los titulares,
     los botones del menú, las cifras, las etiquetas, el precio de la tienda —
     todo en Silkscreen. Y el propio sistema de diseño de este proyecto dice, por
     escrito y por haberlo aprendido a base de rehacerlo, que el pixel art es del
     JUEGO y no de la interfaz: «si aparece la tentación de poner Silkscreen en
     un botón, la respuesta es no».

     Una letra de píxel a 44 px en un titular no se lee, se descifra. No tiene
     minúsculas de verdad, no tiene pesos, no distingue el 0 del 8 en una cifra,
     y a cualquier tamaño que no sea múltiplo exacto de su rejilla sale sucia.
     Eso es lo que hacía que un panel bien construido pareciera un juguete.

   ASÍ QUE: UNA SOLA FAMILIA, Rubik, para todo el panel. La letra de píxel se
   queda donde le toca — dentro del lienzo del juego— y aquí no aparece ni una
   vez. Con eso solo, esto ya se parece a una herramienta.

   Y detrás, lo que pide una pantalla de gestión:
     · DENSIDAD. Se viene a comparar. Media pantalla de aire entre dos datos es
       media pantalla de datos que no se ven.
     · JERARQUÍA POR TAMAÑO Y PESO, no por decoración. Escala corta, de 1,2.
     · CONSISTENCIA. El mismo botón, la misma tarjeta, la misma etiqueta en las
       siete secciones.
   ========================================================================== */

/* -----------------------------------------------------------------------------
   1. LA VOZ: una familia, una escala
-------------------------------------------------------------------------------- */
.adm-shell,
.adm-shell button,
.adm-shell input,
.adm-shell select,
.adm-shell textarea,
.uf-fondo,
.uf-fondo button,
.uf-fondo input,
.uf-fondo select {
  font-family: Rubik, system-ui, sans-serif;
}

/* LA REGLA QUE LO ARREGLA TODO. Barre la letra de píxel de las siete secciones
   de una vez, sin tener que cazarla en las cuarenta y cinco reglas donde estaba
   puesta. El logotipo se salva porque es una imagen, no texto.
   
   EL NOMBRE DE LA CLASE VA REPETIDO A PROPÓSITO. Escrito una sola vez, esta
   regla pierde contra cosas como `.usr-cifra strong` —que llevan una clase y un
   elemento— y quedaban cuatrocientos trozos de letra de píxel sueltos por el
   panel. Repitiéndolo gana por especificidad sin tener que recurrir a
   `!important`, que es la manera de ganar discusiones a gritos. */
.adm-shell.adm-shell *,
.uf-fondo.uf-fondo * { font-family: Rubik, system-ui, sans-serif; }

/* Las cifras, con dígitos de ancho fijo: sin esto, un contador que pasa de 199
   a 200 mueve de sitio la etiqueta de al lado. */
.adm-shell :where(.dash-euros, .dash-n, .usr-cifra strong, .uf-cifra strong,
  .stats-cifra-n, .prd-precio, .casa-dato strong, .dash-origen strong) {
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}

/* --- Titulares ------------------------------------------------------------- */
/* EL TÍTULO DE SECCIÓN NO ES UN CARTEL. Iba a 44 px en mayúsculas de píxel,
   ocupando el ancho de la pantalla para decir «Las casas». En una herramienta,
   el título dice dónde estás y se aparta; lo que se mira son los datos. */
.adm-h1 {
  margin: 0 0 4px;
  font-size: 26px;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -.015em;
  text-transform: none;
  color: var(--ink);
}
.adm-lead {
  margin: 0 0 20px;
  max-width: 68ch;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-faint);
}
.adm-head { align-items: flex-start; gap: 14px 20px; margin-bottom: 20px; }
.adm-head .adm-lead { margin: 0; }

.stats-h2, .dash-h2 {
  margin: 0 0 3px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.stats-h3 { font-size: 15px; font-weight: 600; }
.stats-bloque { margin-bottom: 30px; }

/* -----------------------------------------------------------------------------
   2. EL ARMAZÓN, más apretado
-------------------------------------------------------------------------------- */
.adm-shell { grid-template-columns: 216px 1fr; }
.adm-side { gap: 16px; padding: 18px 12px; }
.adm-logo { padding: 2px 6px 12px; }

.adm-nav {
  padding: 9px 12px;
  border-radius: 8px;
  font-size: 14.5px;
  font-weight: 500;
  letter-spacing: 0;
}
.adm-nav-icono { width: 16px; font-size: 14px; }
/* La sección activa: fondo teñido y letra encendida. Sin la barra de tres
   píxeles a la izquierda, que es el adorno con el que se marca «lo activo»
   cuando no se ha decidido cómo marcarlo. */
.adm-nav.on {
  background: rgba(168, 244, 37, .13);
  box-shadow: none;
  color: var(--lime);
  font-weight: 600;
}
.adm-foot { font-size: 12px; }
.adm-back { font-size: 13px; }

.adm-main { padding: 28px 30px 56px; }

/* El desplegable solo existe en estrecho: en escritorio manda la lista lateral,
   que se ve entera y no cuesta un clic. */
.adm-selector { display: none; }

/* -----------------------------------------------------------------------------
   3. RED DE SEGURIDAD
   Nada, en ninguna pantalla, es más ancho que su sitio.
-------------------------------------------------------------------------------- */
.adm-main img,
.adm-main canvas,
.adm-main video,
.adm-main table { max-width: 100%; }
.adm-shell > *,
.adm-main > * { min-width: 0; }

/* -----------------------------------------------------------------------------
   4. LAS PARTES QUE NO DIBUJAMOS
-------------------------------------------------------------------------------- */
.adm-shell ::selection { background: rgba(168, 244, 37, .28); color: #fff; }

.adm-main, .adm-menu, .uf-cuerpo, .stats-carril, .tal-rejilla {
  scrollbar-width: thin;
  scrollbar-color: rgba(157, 107, 255, .45) transparent;
}
.adm-main::-webkit-scrollbar,
.uf-cuerpo::-webkit-scrollbar,
.stats-carril::-webkit-scrollbar { width: 10px; height: 10px; }
.adm-main::-webkit-scrollbar-thumb,
.uf-cuerpo::-webkit-scrollbar-thumb,
.stats-carril::-webkit-scrollbar-thumb {
  border: 3px solid transparent;
  border-radius: 99px;
  background: rgba(157, 107, 255, .45) content-box;
}
.adm-main::-webkit-scrollbar-thumb:hover { background: rgba(157, 107, 255, .75) content-box; }

.adm-shell :focus-visible,
.uf-fondo :focus-visible {
  outline: 2px solid var(--lime, #a8f425);
  outline-offset: 2px;
  border-radius: 6px;
}

/* -----------------------------------------------------------------------------
   5. TABLAS ANCHAS
   Ocho columnas no caben en un móvil. Se deslizan dentro de su caja en vez de
   llevarse la página por delante: apilarlas destruiría lo único que sirve una
   tabla, que es comparar una columna entre filas.
-------------------------------------------------------------------------------- */
.stats-carril {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  /* Sombra en los cantos mientras quede tabla por ver: sin eso, en un móvil no
     hay manera de saber que se puede deslizar. */
  background:
    linear-gradient(to right, var(--panel-2, #171326) 30%, transparent),
    linear-gradient(to left, var(--panel-2, #171326) 30%, transparent) 100% 0,
    radial-gradient(farthest-side at 0 50%, rgba(0, 0, 0, .5), transparent),
    radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, .5), transparent) 100% 0;
  background-repeat: no-repeat;
  background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
  background-attachment: local, local, scroll, scroll;
}
.stats-carril .stats-tabla { min-width: 680px; }
.stats-tabla th {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* -----------------------------------------------------------------------------
   6. EL PERSONAL, COMO LISTADO
   Eran seis tarjetas gigantes por pantalla con cinco botones cada una. Para
   comparar cuentas hace falta verlas juntas, no desfilando. Ahora es un listado
   de filas de una línea, con lo que de verdad se mira —quién, si pagó, cuándo
   entró por última vez— y los botones detrás de la ficha, que es donde se
   trabaja de verdad.
-------------------------------------------------------------------------------- */
.usr-lista { display: grid; gap: 3px; }

.usr-ficha {
  grid-template-columns: 34px minmax(160px, 1.6fr) minmax(150px, 1fr) auto auto;
  gap: 14px;
  padding: 8px 12px;
  border-radius: 8px;
  background: transparent;
  box-shadow: none;
  border-bottom: 1px solid rgba(157, 107, 255, .1);
}
.usr-ficha:hover { background: rgba(157, 107, 255, .07); }
.usr-ficha.apagada { opacity: .45; }

.usr-cara { width: 30px; height: 30px; font-size: 13px; border-radius: 8px; }
.usr-nombre { font-size: 14.5px; font-weight: 600; }
.usr-quien .dash-sub { font-size: 11.5px; }
.usr-chapa {
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .06em;
}

/* LA FILA. Cinco columnas de ancho conocido y ninguna elástica de más: es lo
   que impide que los botones se coman las cifras, que es lo que pasaba. */
.usr-ficha {
  grid-template-columns: 34px minmax(0, 1fr) auto 32px;
  gap: 14px;
  padding: 10px 14px;
  align-items: center;
}

/* EL BOTÓN DE LOS TRES PUNTOS. Apagado hasta que se pasa por encima: en una
   lista de cuarenta cuentas, cuarenta botones encendidos son ruido. */
.usr-mas {
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--ink-faint, #8b83a6);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.usr-ficha:hover .usr-mas, .usr-mas:focus-visible { background: rgba(157, 107, 255, .16); color: #fff; }

.usr-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  display: grid;
  min-width: 210px;
  padding: 5px;
  border-radius: 10px;
  background: #150f28;
  box-shadow:
    inset 0 0 0 1px rgba(157, 107, 255, .3),
    0 16px 40px rgba(0, 0, 0, .6);
}
.usr-menu-op {
  padding: 8px 10px;
  border: 0;
  border-radius: 7px;
  background: none;
  color: rgba(226, 220, 250, .82);
  font: 500 13px/1.2 var(--face-ui), system-ui, sans-serif;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
}
.usr-menu-op:hover { background: rgba(157, 107, 255, .18); color: #fff; }
/* Las que están puestas se marcan: así se ve de un vistazo si esta cuenta ya
   tiene el pase sin abrir su ficha. */
.usr-menu-op.on { color: var(--lime, #a8f425); }
.usr-menu-op--peligro { color: var(--danger, #ff5566); }
.usr-menu-op--peligro:hover { background: rgba(255, 85, 102, .16); }
.usr-menu-raya { height: 1px; margin: 4px 6px; background: rgba(157, 107, 255, .16); }

.usr-aviso {
  grid-column: 2 / -1;
  margin: 6px 0 0;
  font: 500 12px/1.4 var(--face-ui), system-ui, sans-serif;
  color: var(--lime, #a8f425);
}
.usr-aviso--mal { color: var(--danger, #ff5566); }

/* LAS CIFRAS, EN COLUMNAS DE ANCHO FIJO. Iban en una fila elástica, así que el
   «nivel» de una cuenta caía a la altura del «dinero» de la de abajo según lo
   que midiera cada número. Un listado sirve para leer una columna de arriba
   abajo: si la columna serpentea, no sirve para nada. */
.usr-cifras { display: grid; grid-template-columns: repeat(4, 58px); gap: 8px; }
.usr-cifra { text-align: right; }
.usr-cifra strong { font-size: 14px; font-weight: 600; }
.usr-cifra small { font-size: 10px; letter-spacing: .04em; text-transform: uppercase; }

/* UN SOLO BOTÓN POR FILA, y de ahí sale todo.
   Los seis que había no cabían: la columna que los llevaba se desbordaba y se
   montaba encima de las cifras. Y aunque cupieran, seis botones por cuarenta
   cuentas son doscientos cuarenta botones para usar siempre el mismo. */
.usr-mandos { gap: 4px; flex-wrap: nowrap; position: relative; }
.usr-btn {
  padding: 5px 9px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
}
.usr-embudo { padding: 6px 12px; font-size: 12.5px; }

/* -----------------------------------------------------------------------------
   7. LAS CASAS, TODAS IGUALES
   Los botones se cortaban porque la cabecera los apretaba contra el nombre. El
   nombre se corta con puntos suspensivos —siempre cabe— y los botones no se
   encogen nunca, que es la regla al revés de la que había.
-------------------------------------------------------------------------------- */
.casas {
  grid-template-columns: repeat(auto-fill, minmax(272px, 1fr));
  gap: 14px;
  align-items: stretch;
}
.casa { height: 100%; }
.casa-cab { flex-wrap: nowrap; gap: 8px; }
.casa-nombre {
  min-width: 0;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* NUNCA SE ENCOGEN. Un botón medio cortado no es un botón: no se sabe qué hace
   y da miedo pulsarlo. Antes se apretaban para dejarle sitio al nombre. */
.casa-mandos { flex: 0 0 auto; }
.casa-icono { width: 26px; height: 26px; font-size: 14px; }
.casa-cuerpo { display: flex; flex-direction: column; flex: 1; gap: 8px; }
.casa-estado { margin-top: auto; font-size: 12px; }
.casa-dato { font-size: 12.5px; }
.casa-dato strong { font-size: 14px; font-weight: 600; }

/* -----------------------------------------------------------------------------
   8. EL CONSTRUCTOR: que la imagen quepa
   Los sprites se salían de su recuadro y tapaban los botones de debajo. La caja
   tenía alto fijo y la imagen un tope en porcentaje, que es de las cosas que
   parecen que funcionan y no siempre lo hacen. Con `object-fit` sí, siempre.
-------------------------------------------------------------------------------- */
.tal-rejilla { grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); gap: 12px; }
.tal-spr { height: 100%; }
.tal-spr-img {
  height: 108px;
  overflow: hidden;
}
.tal-spr-img img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  max-width: none;
  max-height: none;
}
.tal-spr-n {
  font-size: 13.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tal-spr-tam { font-size: 11.5px; }
/* El pie, siempre abajo: con nombres de una y de dos líneas, los botones
   quedaban a distinta altura en cada tarjeta de la misma fila. */
.tal-spr-pie { margin-top: auto; }

/* -----------------------------------------------------------------------------
   9. LA TIENDA
-------------------------------------------------------------------------------- */
.prd-rejilla { grid-template-columns: repeat(auto-fill, minmax(206px, 1fr)); }
.prd-ficha { display: flex; flex-direction: column; gap: 8px; height: 100%; }
.prd-pista {
  flex: 1;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 0 !important;
}
.prd-linea { margin-top: auto; }
.prd-precio { font-size: 20px; font-weight: 700; }
.prd-icono { height: 74px; }

/* -----------------------------------------------------------------------------
   10. EL CUARTEL GENERAL
-------------------------------------------------------------------------------- */
.dash-euros { font-size: clamp(38px, 5vw, 52px); font-weight: 700; line-height: 1; }
.dash-k {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.dash-sub { font-size: 12.5px; }

/* -----------------------------------------------------------------------------
   11. PANTALLAS ESTRECHAS
-------------------------------------------------------------------------------- */
@media (max-width: 1000px) {
  .adm-shell { grid-template-columns: 1fr; }

  /* La barra lateral pasa a ser una cabecera pegada arriba. Se queda a la vista
     al desplazar: en un panel se cambia de sección constantemente, y tener que
     subir del todo cada vez es el peaje que hace que no se use en el móvil. */
  .adm-side {
    position: sticky;
    top: 0;
    z-index: 30;
    height: auto;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    padding: 8px 12px;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  .adm-logo { border: 0; padding: 0; }
  .marca--panel { width: 112px; }

  /* FUERA LA LISTA, DENTRO EL MENÚ DEL JUEGO.
     Estuvo como una tira que se deslizaba y salió mal: la última palabra queda
     partida por el canto de la pantalla, y eso NO se lee como «hay más a la
     derecha» — se lee como que la página está rota. Luego fue un desplegable del
     sistema, que resolvía eso pero metía la única pieza de la casa que no
     parecía de la casa. Ahora es un menú de pausa: ver `mando` más abajo. */
  .adm-menu { display: none; }
  .adm-selector { display: block; width: 100%; }
  .adm-foot { display: none; }
  .adm-main { padding: 20px 16px 44px; }
  .adm-h1 { font-size: 22px; }
  .adm-lead { font-size: 13px; margin-bottom: 16px; }

  .casas, .prd-rejilla { grid-template-columns: 1fr; }
  .dash-caja { grid-template-columns: 1fr; }
  .tal-rejilla { grid-template-columns: repeat(auto-fill, minmax(136px, 1fr)); }

  /* El listado se apila: nombre y correo arriba, cifras y botones debajo. Una
     fila de cinco columnas en 390 píxeles no es una fila, son cinco recortes. */
  .usr-ficha {
    grid-template-columns: 30px 1fr;
    align-items: start;
    gap: 8px 10px;
    padding: 10px 8px;
  }
  .usr-cifras, .usr-mandos { grid-column: 2 / -1; justify-content: flex-start; }
  .usr-mandos { flex-wrap: wrap; }
  .usr-cifra { text-align: left; }
}

@media (max-width: 430px) {
  /* Sin los símbolos del menú caben dos secciones más por pantallazo. Ayudan
     cuando sobra sitio; cuando no, estorban. */
  .adm-nav-icono { display: none; }
  .adm-nav { padding: 8px 10px; }
}

/* =============================================================================
   EL CUARTEL GENERAL: un tablero, no un informe
   ==========================================================================
   Ocupaba casi dos pantallas, y no por tener demasiados datos: por el
   envoltorio. Cuatro secciones apiladas con su titular y su frase, y tarjetas
   de tres líneas para enseñar un número. El contenido cabía de sobra; lo que no
   cabían eran los rótulos.

   Ahora es UNA rejilla con sitios fijos. Cada tarjeta se presenta con una
   etiqueta pequeña y ya está: en un panel de mando, el número ES el titular.
============================================================================= */
.cg {
  display: grid;
  gap: 12px;
  grid-template-columns: minmax(230px, .85fr) minmax(180px, .6fr) minmax(340px, 1.5fr);
  /* LA GRÁFICA OCUPA LAS DOS PRIMERAS FILAS, al lado del dinero y de los
     marcadores. Se probaron las tres maneras y esta es la única que cabe en una
     pantalla: darle fila propia añade una fila entera, y dejar que la gráfica se
     estire para llenar su hueco arrastra el alto de las de al lado. Aquí la
     gráfica mide lo que mide y el hueco que sobra se lo queda la leyenda,
     empujada al fondo de la tarjeta. */
  grid-template-areas:
    'caja   conv      serie'
    'vivo   vivo      serie'
    'dentro dentro    ranking'
    'altas  licencias ranking';
  align-items: stretch;
}

.cg-caja {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  padding: 14px 16px;
  border-radius: 12px;
  /* EL DEGRADADO ES DE UN PUNTO Y MEDIO, y esa es toda la gracia: con el fondo
     plano las nueve tarjetas eran nueve rectángulos idénticos y el tablero se
     leía como un mantel. Con una pizca de luz arriba cada una tiene canto y
     suelo, y el ojo las separa sin tener que ponerles bordes gordos. */
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .028), transparent 42%),
    var(--glass, rgba(20, 15, 42, .55));
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .18);
  transition: box-shadow 160ms ease;
}
.cg-caja:hover { box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .34); }

/* LA ETIQUETA DE CADA TARJETA, CON SU MARCA. Un guion corto delante del rótulo:
   es lo que da al tablero un compás: nueve tarjetas que empiezan igual se leen
   como una sola cosa con nueve partes, en vez de nueve cosas apiladas. */
.cg .dash-k { display: flex; align-items: center; gap: 7px; }
.cg .dash-k::before {
  content: '';
  flex: none;
  width: 10px;
  height: 2px;
  border-radius: 2px;
  background: rgba(157, 107, 255, .55);
}
.cg-caja[style*='caja'] .dash-k::before { background: var(--lime, #a8f425); }

/* La caja del dinero, con su propio filo: es la que hay que mirar primero y
   tiene que distinguirse sin leerla. */
.cg-caja[style*='caja'] { box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .3); }

.cg .dash-euros { margin: 2px 0 0; font-size: clamp(34px, 3.4vw, 46px); }
/* El anillo de conversión, centrado en su hueco. Pegado arriba dejaba un palmo
   de tarjeta vacía debajo del pie, que es de lo que más canta en un tablero. */
.cg-caja[style*='conv'] { justify-content: center; align-items: center; text-align: center; }
.cg-caja[style*='conv'] .dash-k { align-self: flex-start; }
.cg .dash-k { margin-bottom: 2px; }

/* --- Ahora mismo: ocho casillas, no ocho tarjetas --------------------------
   Y con una raya en medio, que es lo que separa lo que está pasando AHORA de lo
   que dice cuánta gente vuelve. Sin ella, «3 en sala» y «180 este mes» parecen
   la misma clase de dato. La raya mide un píxel y hace todo el trabajo. */
.dash-vivo {
  display: grid;
  /* SIN NÚMERO DE COLUMNAS FIJO. Contarlas ata la rejilla al número de
     marcadores, y el día que se añade uno la tira se parte con una casilla
     suelta debajo — que es exactamente lo que pasó al meter «en espera». */
  grid-template-columns: repeat(auto-fit, minmax(74px, 1fr));
  gap: 8px;
  margin-top: 2px;
}
/* La pausa entre «lo que pasa ahora» y «cuánta gente vuelve». Es un filo a la
   izquierda de la primera casilla de la segunda tanda, no una casilla aparte, y
   por eso no cuenta para la rejilla. Se desvanece por los cantos: una raya a
   tope de arriba abajo corta la tira en dos tarjetas, y lo que hace falta es una
   pausa, no un tabique. */
.dash-marca.corte { position: relative; }
.dash-marca.corte::before {
  content: '';
  position: absolute;
  left: -5px;
  top: 3px;
  bottom: 3px;
  width: 1px;
  background: linear-gradient(180deg, transparent, rgba(157, 107, 255, .55) 30%,
    rgba(157, 107, 255, .55) 70%, transparent);
}
/* Cuando la tira se dobla en varias filas, la raya ya no separa nada: separa una
   casilla de la de arriba. Fuera. */
@media (max-width: 1240px) {
  .dash-marca.corte::before { display: none; }
}
.dash-marca {
  display: grid;
  gap: 1px;
  padding: 10px 8px;
  border-radius: 9px;
  background: rgba(255, 255, 255, .04);
  text-align: center;
}
.dash-marca strong {
  font-size: 21px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.dash-marca small {
  font-size: 10.5px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
/* Encendida solo cuando hay algo: seis casillas en verde son seis casillas
   iguales, y entonces el color deja de significar nada. */
.dash-marca.on { background: rgba(168, 244, 37, .12); }
.dash-marca.on strong { color: var(--lime); }
/* El número incómodo —los que se registraron y no volvieron— en ámbar. Ni verde
   (no es un logro) ni rojo (no es una avería): es algo que mirar. */
.dash-marca.ojo { background: rgba(255, 196, 71, .1); }
.dash-marca.ojo strong { color: var(--amber, #ffc447); }

/* --- La gráfica de las tres series ------------------------------------------ */
.gr--multi { position: relative; display: flex; flex-direction: column; }
/* Y NO SE ESTIRA. Se probó a que la curva llenara su tarjeta y salió al revés
   de lo esperado: la gráfica es la tarjeta más alta de la fila, así que al
   dejarla crecer arrastró el alto de las otras tres y el tablero se llenó de
   huecos. Mide lo que mide; el sobrante se lo queda la leyenda, al fondo. */
.gr--multi .gr-svg { flex: 1; min-height: 0; }
/* La leyenda al fondo de la tarjeta: es lo que cierra el hueco que queda debajo
   de la gráfica sin añadir un solo píxel de alto. */
.cg-caja .dash-leyenda { margin-top: auto; padding-top: 10px; }
.gr-area--multi { opacity: .1; }
.gr-dias {
  display: flex;
  justify-content: space-between;
  margin-top: 4px;
  font-size: 10.5px;
  letter-spacing: .04em;
  color: var(--ink-faint);
}
.dash-leyenda { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 6px; }
.dash-ley { display: flex; align-items: baseline; gap: 5px; }
.dash-ley i { width: 8px; height: 8px; border-radius: 50%; align-self: center; }
.dash-ley strong { font-size: 15px; font-weight: 700; color: var(--ink); }
.dash-ley small { font-size: 11.5px; color: var(--ink-faint); }

/* --- El pulso: ¿hay alguien AHORA? ------------------------------------------
   Va cosido encima de la gráfica de treinta días, en la misma tarjeta. Esa
   tarjeta tenía un hueco muerto arriba —la curva mide lo que mide— y las dos
   preguntas se hacen seguidas: si hay alguien ahora y cómo ha ido el mes.

   LA QUIETUD ES EL DATO. Sin nadie dentro no se mueve NADA: línea plana, tinta
   apagada y ni una animación. Basta un vistazo de reojo para saberlo, que es
   justo lo que un número solo no consigue. */
.pulso {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 14px;
  padding-bottom: 10px;
  margin-bottom: 4px;
  border-bottom: 1px solid rgba(157, 107, 255, .14);
}
.pulso:focus-visible { outline: 2px solid var(--lime); outline-offset: 4px; border-radius: 6px; }

.pulso-cifras { display: grid; gap: 1px; }
.pulso-n {
  font-size: 30px;
  font-weight: 700;
  line-height: 1;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  transition: color .5s ease;
}
.pulso-sub {
  font-size: 11.5px;
  letter-spacing: .04em;
  color: var(--ink-dim);
  white-space: nowrap;
}
.pulso--vivo .pulso-n {
  color: var(--lime);
  /* El resplandor es el del neón del juego, no una sombra de tarjeta. */
  text-shadow: 0 0 18px rgba(168, 244, 37, .45);
}

/* El hueco de la derecha es para el punto de la punta: sin él, el punto se sale
   de la tarjeta y parece que la gráfica está rota. */
.pulso-monitor { position: relative; height: 46px; min-width: 0; padding-right: 9px; }
.pulso-svg { width: 100%; height: 100%; }
.pulso-suelo { stroke: rgba(157, 107, 255, .18); stroke-width: 1; vector-effect: non-scaling-stroke; }
.pulso-area { fill: var(--ink-faint); opacity: .07; transition: fill .5s ease; }
.pulso-linea {
  fill: none;
  stroke: var(--ink-faint);
  stroke-width: 2;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  transition: stroke .5s ease;
}
/* La punta de la línea. Va fuera del SVG —que se estira sin guardar la
   proporción y deformaría el círculo— colocada por altura en tantos por ciento. */
.pulso-punto {
  position: absolute;
  right: 3px;
  width: 7px;
  height: 7px;
  margin-top: -3.5px;
  border-radius: 50%;
  background: var(--ink-faint);
  transition: background .5s ease, top .6s cubic-bezier(.2, .8, .3, 1);
}
.pulso--vivo .pulso-area { fill: var(--lime); opacity: .12; }
.pulso--vivo .pulso-linea { stroke: var(--lime); }
.pulso--vivo .pulso-punto {
  background: var(--lime);
  box-shadow: 0 0 12px rgba(168, 244, 37, .6);
  animation: pulso-latido 1.6s ease-out infinite;
}

/* La chispa que recorre la línea. Solo se dibuja cuando hay alguien dentro
   (el JS ni la monta si no), así que su presencia ya es información. */
.pulso-chispa {
  fill: none;
  stroke: var(--lime-soft);
  stroke-width: 2.5;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 7 93;
  animation: pulso-recorrido 3.4s linear infinite;
}

@keyframes pulso-latido {
  0%   { transform: scale(1);   opacity: 1; }
  55%  { transform: scale(1.9); opacity: .35; }
  100% { transform: scale(1);   opacity: 1; }
}
@keyframes pulso-recorrido {
  from { stroke-dashoffset: 100; }
  to   { stroke-dashoffset: 0; }
}

/* De dónde se conectan: al pasar el ratón o al llegar con el teclado. */
.pulso-globo {
  position: absolute;
  z-index: 5;
  top: calc(100% + 6px);
  right: 0;
  min-width: 190px;
  display: grid;
  gap: 3px;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--glass-2);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .28), 0 14px 30px rgba(0, 0, 0, .5);
  opacity: 0;
  transform: translateY(-4px);
  pointer-events: none;
  transition: opacity .18s ease, transform .18s cubic-bezier(.2, .8, .3, 1);
}
.pulso:hover .pulso-globo,
.pulso:focus-visible .pulso-globo { opacity: 1; transform: translateY(0); }

.pulso-globo-k {
  font-size: 10px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 2px;
}
.pulso-globo-vacio { margin: 0; font-size: 12.5px; color: var(--ink-dim); }
.pulso-sitio {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: 8px;
  align-items: baseline;
  font-size: 12.5px;
  color: var(--ink);
}
.pulso-sitio strong { color: var(--lime); font-variant-numeric: tabular-nums; }
.pulso-sitio span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (prefers-reduced-motion: reduce) {
  .pulso--vivo .pulso-punto,
  .pulso-chispa { animation: none; }
  /* Sin movimiento, el «hay alguien» lo tiene que decir el color entero. */
  .pulso-chispa { opacity: .5; stroke-dasharray: none; }
}

/* --- Las tres listas --------------------------------------------------------- */
.cg .dash-filas { display: grid; gap: 1px; margin-top: 2px; }
.cg .dash-fila {
  display: grid;
  /* EL NOMBRE MANDA. Con las tres columnas a partes iguales, el nombre salía
     cortado con puntos suspensivos para dejarle sitio a una fecha — y el nombre
     es lo único de esta lista que hay que poder leer. */
  grid-template-columns: minmax(0, 1.6fr) auto auto;
  gap: 8px;
  align-items: baseline;
  padding: 5px 0;
  border-bottom: 1px solid rgba(157, 107, 255, .08);
  font-size: 13px;
}
.cg .dash-fila:last-child { border-bottom: 0; }
.cg .dash-fila strong {
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cg .dash-fila .dash-sub { font-size: 11.5px; white-space: nowrap; }

.dash-aviso { margin-bottom: 14px; }

@media (max-width: 1240px) {
  /* A dos columnas: la gráfica se pone ancha debajo del dinero, que es como se
     mira cuando no cabe al lado. */
  .cg {
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      'caja  conv'
      'serie serie'
      'vivo  vivo'
      'dentro dentro'
      'altas licencias'
      'ranking ranking';
  }
  /* Ocho casillas en dos filas de cuatro: en 1200 píxeles, ocho en fila salen a
     ochenta cada una y el número deja de caber sin partirse. La raya no pinta
     nada partiendo una fila por la mitad, así que se va. */
  .dash-vivo { grid-template-columns: repeat(4, 1fr); }
}

@media (max-width: 1000px) {
  .cg {
    grid-template-columns: 1fr;
    grid-template-areas: 'caja' 'conv' 'vivo' 'dentro' 'serie' 'altas' 'licencias' 'ranking';
  }
  .dash-vivo { grid-template-columns: repeat(3, 1fr); }
}

/* =============================================================================
   LOS CATORCE
   Una rejilla de fichas: la cara a la izquierda —la lámina subida, o el dibujo
   de siempre— y quién es a la derecha. El que ya tiene lámina se distingue sin
   leer nada, que es lo que hace falta cuando se van subiendo de una en una.
============================================================================= */
.fnt-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
  gap: 12px;
}

.fnt {
  display: grid;
  grid-template-columns: 108px minmax(0, 1fr);
  gap: 14px;
  padding: 13px;
  border-radius: 12px;
  background: var(--glass, rgba(20, 15, 42, .55));
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .18);
  transition: box-shadow 140ms ease, opacity 140ms ease;
}
/* Con lámina propia, filo verde. Es la única manera de ver de un vistazo
   cuáles quedan por hacer. */
.fnt--conarte { box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .32); }
.fnt--subiendo { opacity: .5; pointer-events: none; }

.fnt-cara {
  display: grid;
  place-items: center;
  gap: 4px;
  align-content: center;
  height: 118px;
  border-radius: 10px;
  /* El tablero de ajedrez: sin él no hay manera de saber qué es transparente y
     qué es un color parecido al fondo del panel. */
  background:
    conic-gradient(#241f36 0 25%, #1b1728 0 50%, #241f36 0 75%, #1b1728 0) 0 0 / 14px 14px;
  overflow: hidden;
}
.fnt-cara img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.fnt-cara svg { display: block; }
.fnt-sinarte {
  font-size: 9.5px;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.fnt-texto { display: grid; gap: 6px; align-content: start; min-width: 0; }
.fnt-n { margin: 0; font-size: 17px; font-weight: 700; color: var(--ink); }
.fnt-c {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink-dim);
  /* Dos líneas: los caracteres son de una frase y el que se pase no puede
     desalinear a los otros trece. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.fnt-pruebas { display: flex; flex-wrap: wrap; gap: 4px; }
.fnt-chapa {
  padding: 2px 7px;
  border-radius: 5px;
  background: rgba(255, 255, 255, .06);
  font-size: 11px;
  color: var(--ink-dim);
  white-space: nowrap;
}
.fnt-mandos { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
/* El botón de subir es una etiqueta con el campo de fichero escondido dentro:
   el campo de fichero de fábrica no se puede estilar y canta muchísimo. */
.fnt-mandos label { cursor: pointer; }
.fnt-aviso { margin: 2px 0 0; font-size: 12px; }

@media (max-width: 1000px) {
  .fnt-rejilla { grid-template-columns: 1fr; }
}

/* --- Casas: el alta y el botón de borrar ------------------------------------- */
.casa-alta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  width: 100%;
  margin-top: 4px;
}
.casa-alta .zona-nombre { flex: 1 1 220px; min-width: 0; }
.casa-alta .adm-error { flex-basis: 100%; margin: 0; font-size: 12.5px; }

/* El de borrar, en rojo y el último de la fila: es el único de esos iconos que
   no se puede deshacer, y tiene que verse distinto antes de pulsarlo. */
.casa-icono--peligro { color: rgba(255, 93, 120, .75); }
.casa-icono--peligro:hover { background: rgba(255, 93, 120, .2); color: var(--danger, #ff5d78); }

/* El botón de casa nueva, a la derecha del titular. */
.adm-head .ed-btn--go { margin-left: auto; align-self: flex-start; }


/* =============================================================================
   EL DIÁLOGO DE CONFIRMAR
   Sale antes de lo que se nota fuera: regalar el juego y dar el pase. Y lleva la
   casilla de avisar por correo, apagada — un correo no se deshace.
============================================================================= */
.cnf {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(6, 4, 14, .72);
  backdrop-filter: blur(4px);
}
.cnf-caja {
  width: min(430px, 100%);
  padding: 22px;
  border-radius: 14px;
  background: #150f28;
  box-shadow:
    inset 0 0 0 1px rgba(157, 107, 255, .3),
    0 24px 70px rgba(0, 0, 0, .65);
}
.cnf-t {
  margin: 0 0 8px;
  font: 700 17px/1.3 var(--face-ui), system-ui, sans-serif;
  color: #fff;
}
.cnf-p {
  margin: 0;
  font: 400 13.5px/1.55 var(--face-ui), system-ui, sans-serif;
  color: rgba(226, 220, 250, .68);
}

.cnf-aviso {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin: 16px 0 0;
  padding: 11px 12px;
  border-radius: 10px;
  background: rgba(157, 107, 255, .1);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .22);
  cursor: pointer;
}
.cnf-aviso input { margin: 2px 0 0; accent-color: var(--lime, #a8f425); }
.cnf-aviso-txt { display: grid; gap: 2px; }
.cnf-aviso-txt strong {
  font: 600 13px/1.2 var(--face-ui), system-ui, sans-serif;
  color: rgba(226, 220, 250, .92);
}
.cnf-aviso-txt small {
  font: 400 11.5px/1.4 var(--face-ui), system-ui, sans-serif;
  color: rgba(198, 188, 236, .5);
}

.cnf-pie {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin: 18px 0 0;
}


/* El aviso de las casas de fábrica borradas, con su botón de recuperarlas. Solo
   sale cuando hay alguna: un cartel permanente de algo que no ha pasado es
   ruido, y a la tercera vez ya no lo lee nadie. */
.casas-borradas {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin: 0 0 16px;
  padding: 12px 14px;
  border-radius: 10px;
  background: rgba(255, 180, 61, .08);
  box-shadow: inset 0 0 0 1px rgba(255, 180, 61, .3);
}
.casas-borradas-t {
  font: 600 13px/1.3 var(--face-ui), system-ui, sans-serif;
  color: #ffb43d;
}
.casas-borradas small {
  flex: 1 1 100%;
  font: 400 11.5px/1.4 var(--face-ui), system-ui, sans-serif;
  color: rgba(198, 188, 236, .5);
}


/* =============================================================================
   LAS COPIAS DE SEGURIDAD
   Lo primero que se lee no es la lista: es cuánto hace que no te bajas una. Las
   copias viven en el mismo disco que la base, así que la única que salva del día
   malo es la que está en otro sitio.
============================================================================= */
.cop { display: grid; gap: 16px; }

.cop-aviso {
  padding: 14px 16px;
  border-radius: 10px;
  background: rgba(168, 244, 37, .08);
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .28);
}
.cop-aviso--mal {
  background: rgba(255, 85, 102, .09);
  box-shadow: inset 0 0 0 1px rgba(255, 85, 102, .34);
}
.cop-aviso strong {
  display: block;
  font: 700 15px/1.3 var(--face-ui), system-ui, sans-serif;
  color: var(--lime, #a8f425);
}
.cop-aviso--mal strong { color: #ff8a97; }
.cop-aviso p {
  margin: 6px 0 0;
  font: 400 13px/1.55 var(--face-ui), system-ui, sans-serif;
  color: rgba(226, 220, 250, .62);
}

.cop-mandos { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.cop-dicho {
  font: 500 12.5px/1.3 var(--face-ui), system-ui, sans-serif;
  color: var(--lime, #a8f425);
}
.cop-dicho--mal { color: #ff5566; }

.cop-lista { display: grid; gap: 2px; }
.cop-fila {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 12px;
  align-items: center;
  padding: 10px 14px;
  border-radius: 8px;
  border-bottom: 1px solid rgba(157, 107, 255, .1);
}
.cop-fila:hover { background: rgba(157, 107, 255, .07); }
.cop-fila--nueva { background: rgba(157, 107, 255, .06); }
.cop-quien { display: grid; gap: 2px; min-width: 0; }
.cop-quien strong { font: 600 14px/1.2 var(--face-ui), system-ui, sans-serif; }
.cop-acciones { display: flex; gap: 6px; }
.cop-acciones .usr-btn { text-decoration: none; }
.cop-pie { margin: 4px 0 0; opacity: .7; }

/* =============================================================================
   LOS CÓDIGOS DE REGALO
   Aquí se viene a HACER un código, no a mirar los que hay: la máquina de
   generarlos va arriba y en grande, y la lista debajo como consecuencia. Lo
   recién hecho sale a tamaño de poder leerlo en voz alta, que es lo que se hace
   con un código.
============================================================================= */
.cod { display: grid; gap: 22px; }

.cod-forja {
  padding: 18px 20px;
  border-radius: 12px;
  background: rgba(157, 107, 255, .07);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .22);
}
.cod-t {
  margin: 0 0 14px;
  font: 700 15px/1 var(--face-ui), system-ui, sans-serif;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--lime, #a8f425);
}
.cod-campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
  margin-bottom: 16px;
}
.cod-campo { display: grid; gap: 5px; align-content: start; }
.cod-campo--ancho { grid-column: 1 / -1; }
.cod-lab {
  font: 600 12px/1.2 var(--face-ui), system-ui, sans-serif;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: rgba(226, 220, 250, .72);
}
.cod-campo input {
  padding: 9px 11px;
  border: 0;
  border-radius: 8px;
  background: rgba(10, 7, 20, .55);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .28);
  color: var(--ink, #e2dcfa);
  font: 500 14px/1.2 var(--face-ui), system-ui, sans-serif;
}
.cod-campo input:focus { outline: 2px solid var(--lime, #a8f425); outline-offset: 1px; }
.cod-pista {
  font: 400 11.5px/1.45 var(--face-ui), system-ui, sans-serif;
  color: rgba(226, 220, 250, .5);
}
.cod-check {
  /* De lado a lado: en una columna estrecha, «Que además pueda entrar hoy» se
     partía en tres líneas y parecía un párrafo, no una casilla. */
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 4px 9px;
  align-content: center;
}
.cod-check input { width: 17px; height: 17px; accent-color: var(--lime, #a8f425); }
.cod-check span { font: 500 13.5px/1.3 var(--face-ui), system-ui, sans-serif; }
.cod-check .cod-pista { grid-column: 2; }

/* Lo recién hecho: grande, para leerlo o dictarlo sin equivocarse. */
.cod-nuevos {
  margin-top: 16px;
  padding: 14px 16px;
  border-radius: 10px;
  background: rgba(168, 244, 37, .08);
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .3);
}
.cod-nuevos-t {
  margin: 0 0 10px;
  font: 700 14px/1.2 var(--face-ui), system-ui, sans-serif;
  color: var(--lime, #a8f425);
}
.cod-nuevos-caja { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.cod-grande {
  padding: 7px 12px;
  border-radius: 8px;
  background: rgba(10, 7, 20, .6);
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .35);
  font: 700 19px/1 var(--face-pixel), monospace;
  letter-spacing: .1em;
  color: #fff;
  user-select: all;
}

.cod-tabla { width: 100%; border-collapse: collapse; }
.cod-tabla th {
  padding: 8px 10px;
  text-align: left;
  font: 600 11px/1.2 var(--face-ui), system-ui, sans-serif;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(226, 220, 250, .5);
  border-bottom: 1px solid rgba(157, 107, 255, .18);
}
.cod-tabla td {
  padding: 10px;
  vertical-align: top;
  border-bottom: 1px solid rgba(157, 107, 255, .1);
  font: 400 13px/1.45 var(--face-ui), system-ui, sans-serif;
}
.cod-tabla tr:hover td { background: rgba(157, 107, 255, .06); }
.cod-fila--off td { opacity: .45; }
.cod-chapa {
  font: 700 14px/1 var(--face-pixel), monospace;
  letter-spacing: .08em;
  color: #fff;
  user-select: all;
}
.cod-etiqueta {
  display: inline-block;
  margin-left: 7px;
  padding: 2px 6px;
  border-radius: 5px;
  background: rgba(255, 191, 64, .16);
  font: 700 10px/1.3 var(--face-ui), system-ui, sans-serif;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #ffbf40;
}
.cod-nota { color: rgba(226, 220, 250, .7); max-width: 26ch; }
.cod-usos { font-variant-numeric: tabular-nums; }
.cod-usos--fin { color: #ff8a97; }
.cod-quienes { display: grid; gap: 2px; }
.cod-quien { font-size: 12px; color: rgba(226, 220, 250, .8); }
.cod-nadie { font-size: 12px; color: rgba(226, 220, 250, .4); }
.cod-acciones { display: flex; gap: 6px; }

/* =============================================================================
   EL MENÚ DE PAUSA (pantallas estrechas)

   Sustituye al `<select>` del sistema. Mismo trabajo —elegir una de once
   secciones— contado como lo cuenta un videojuego: el botón enseña dónde estás,
   se pulsa, el panel de debajo se apaga y las secciones entran escalonadas con
   su cursor parpadeando en la que estás.

   DE DÓNDE SALE LO DE «VIDEOJUEGO», Y DE DÓNDE NO. Sale de la FORMA y del
   MOVIMIENTO: el panel que sube desde abajo, el cursor ▸, la entrada
   escalonada, la vuelta por los extremos, las teclas escritas en el pie. NO
   sale de la letra: este fichero empieza explicando por qué la de píxel no entra
   en el panel —a 23 px no se lee, se descifra— y un menú no es la excepción que
   hunde la regla. Un menú de juego bien hecho no necesita fuente de juego.

   TODO ES CSS Y NADA ES UN MOTOR. Esto se abre cincuenta veces al día: la
   entrada son dos propiedades compuestas (opacidad y desplazamiento) y ni una
   sombra animada, que es lo que hace que en un móvil de hace cinco años siga
   yendo a sesenta.

   Vive fuera de la media query porque el panel se cuelga del `<body>` —tiene que
   tapar la página entera— y por eso también repite la familia: ahí fuera no le
   llega la regla del armazón.
============================================================================= */
.mando-btn {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 11px 13px;
  border: 0;
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(168, 244, 37, .16), rgba(168, 244, 37, .07));
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .34);
  color: var(--lime, #a8f425);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-align: left;
  cursor: pointer;
}
.mando-btn:active { transform: translateY(1px); }
.mando-btn-icono { font-size: 15px; opacity: .85; }
.mando-btn-nombre {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mando-btn-flecha { font-size: 11px; opacity: .7; }

/* --- El panel --------------------------------------------------------------- */
.mando {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: flex-end;
  font-family: Rubik, system-ui, sans-serif;
}
.mando[hidden] { display: none; }

.mando-fondo {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 80% at 50% 100%, rgba(157, 107, 255, .22), transparent 70%),
    rgba(5, 4, 12, .82);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 180ms ease;
}
.mando--on .mando-fondo { opacity: 1; }

.mando-caja {
  position: relative;
  width: 100%;
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  padding: 14px 14px calc(14px + env(safe-area-inset-bottom, 0px));
  border-radius: 18px 18px 0 0;
  background: linear-gradient(180deg, #17102c, #0b0818);
  /* El filo verde de arriba es el canto del panel, y es lo que hace que esto se
     lea como una pieza que ENTRA y no como una página que ha cambiado. */
  box-shadow:
    inset 0 1px 0 rgba(168, 244, 37, .28),
    0 -22px 60px rgba(0, 0, 0, .6);
  transform: translateY(14px);
  opacity: 0;
  transition: transform 200ms cubic-bezier(.2, .9, .3, 1), opacity 160ms ease;
}
.mando--on .mando-caja { transform: none; opacity: 1; }

/* EL RAYADO DE PANTALLA. Una línea de nada cada tres píxeles, al cuatro por
   ciento: no se ve mirándolo, se nota. Es lo que hace que el panel parezca
   encendido y no impreso, y cuesta un degradado que no se repinta nunca.
   Va en un `::before` porque el fondo de la caja ya está ocupado. */
.mando-caja::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: repeating-linear-gradient(180deg,
    rgba(255, 255, 255, .04) 0 1px, transparent 1px 3px);
}

.mando-cab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 4px 10px;
  border-bottom: 1px solid rgba(157, 107, 255, .2);
}
.mando-k {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-faint, #6e678c);
}
.mando-cerrar {
  border: 0;
  background: transparent;
  color: var(--ink-dim, #a79fc8);
  font-size: 16px;
  line-height: 1;
  padding: 8px 10px;
  cursor: pointer;
}
.mando-cerrar:hover { color: var(--lime, #a8f425); }

.mando-lista {
  display: grid;
  gap: 2px;
  padding: 8px 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Los montones, aquí como rótulos y sin plegar: este menú se abre a pantalla
   completa y solo para elegir una sección e irse, así que plegar sería pedir
   dos toques donde antes había uno — en la pantalla donde más caro sale. Los
   nombres son los MISMOS que en la barra ancha, para no tener que aprenderse
   dos mapas del mismo panel. */
.mando-rotulo {
  margin: 14px 0 2px;
  padding: 0 12px;
  font-family: Rubik, system-ui, sans-serif;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-faint, rgba(154, 146, 184, .6));
}
.mando-rotulo:first-child { margin-top: 2px; }

.mando-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  /* 48 de alto de verdad: es un menú que se usa con el pulgar. */
  min-height: 48px;
  padding: 0 10px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--ink-dim, #a79fc8);
  font-size: 15px;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  /* La entrada escalonada: cada fila espera su turno. */
  opacity: 0;
  transform: translateX(-10px);
}
.mando--on .mando-item {
  animation: mando-entra 220ms cubic-bezier(.2, .9, .3, 1) forwards;
  animation-delay: calc(var(--turno, 0) * 26ms);
}
@keyframes mando-entra {
  to { opacity: 1; transform: none; }
}

/* El cursor. Solo se ve en la sección donde estás: un triángulo en cada línea no
   señala nada. */
.mando-cursor {
  width: 11px;
  font-size: 13px;
  color: var(--lime, #a8f425);
  opacity: 0;
}
/* EL ICONO EN SU RANURA. Suelto es un carácter perdido en el hueco; metido en
   una casilla con su filo se lee como una ficha de menú de juego, que es
   exactamente lo que se pedía — y lo consigue con un borde, no con una fuente
   de píxel a la que este panel ya dijo que no. */
.mando-item-icono {
  display: grid;
  place-items: center;
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 7px;
  background: rgba(255, 255, 255, .035);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .22);
  font-size: 14px;
  opacity: .75;
}
.mando-item.on .mando-item-icono {
  background: rgba(168, 244, 37, .14);
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .45);
}
.mando-item-nombre {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mando-item-ir { font-size: 16px; opacity: .28; }

.mando-item:hover { background: rgba(157, 107, 255, .14); color: var(--ink, #f4f2ff); }
.mando-item:focus-visible { background: rgba(157, 107, 255, .18); color: var(--ink, #f4f2ff); }
.mando-item.on {
  background: linear-gradient(90deg, rgba(168, 244, 37, .16), rgba(168, 244, 37, .04));
  box-shadow: inset 3px 0 0 var(--lime, #a8f425);
  color: var(--lime-soft, #c9ff6b);
  font-weight: 600;
}
.mando-item.on .mando-cursor { opacity: 1; animation: mando-cursor 1.1s steps(2) infinite; }
.mando-item.on .mando-item-icono { opacity: 1; }
@keyframes mando-cursor {
  50% { opacity: .25; }
}

.mando-pie {
  display: flex;
  gap: 16px;
  justify-content: center;
  padding-top: 10px;
  border-top: 1px solid rgba(157, 107, 255, .16);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-faint, #6e678c);
}
/* Las teclas no las tiene quien va con el dedo: se dicen solo donde hay teclado.
   Enseñar «esc salir» en un móvil es ruido. */
@media (hover: none) and (pointer: coarse) {
  .mando-pie { display: none; }
}

/* Con el menú abierto, la página de debajo no se mueve. */
body.con-mando { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .mando-fondo,
  .mando-caja { transition: none; }
  .mando-caja { transform: none; }
  .mando--on .mando-item { animation: none; opacity: 1; transform: none; }
  .mando-item.on .mando-cursor { animation: none; }
}

/* =============================================================================
   LA LISTA DE ESPERA
   Tres cuentas arriba —cuántos, en qué idioma, cómo crece— y debajo la lista.
============================================================================= */
.avi-resumen {
  display: grid;
  gap: 12px;
  grid-template-columns: minmax(160px, .7fr) minmax(180px, .9fr) minmax(280px, 1.6fr);
  margin-bottom: 18px;
}
.avi-caja {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  padding: 14px 16px;
  border-radius: 12px;
  background: var(--glass, rgba(20, 15, 42, .55));
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .18);
}
.avi-caja--gordo { box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .3); }
.avi-n {
  margin: 2px 0 0;
  font-size: clamp(34px, 3.4vw, 46px);
  font-weight: 700;
  line-height: 1;
  color: var(--lime, #a8f425);
  font-variant-numeric: tabular-nums;
}

.avi-lenguas { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.avi-lengua {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 9px;
  border-radius: 8px;
  background: rgba(255, 255, 255, .05);
}
.avi-lengua i {
  font-style: normal;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .08em;
  color: var(--violet, #9d6bff);
}
.avi-lengua strong { font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; }
.avi-lengua small { font-size: 11px; color: var(--ink-faint, #6e678c); }

/* --- La lista --------------------------------------------------------------- */
.avi-lista {
  border-radius: 12px;
  background: var(--glass, rgba(20, 15, 42, .55));
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .18);
  overflow: hidden;
}
.avi-lista-cab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  border-bottom: 1px solid rgba(157, 107, 255, .16);
}
.avi-lista-cab .dash-h2 { margin: 0; }

.avi-filas { display: grid; }
.avi-fila {
  display: grid;
  grid-template-columns: 22px 1fr auto 30px;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  border-bottom: 1px solid rgba(157, 107, 255, .08);
}
.avi-fila:last-child { border-bottom: 0; }
.avi-fila:hover { background: rgba(157, 107, 255, .07); }
.avi-lengua-mini {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-align: center;
  color: var(--ink-faint, #6e678c);
}
.avi-correo {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 14px;
  font-weight: 500;
  /* Se selecciona entero de una pasada: es lo que se hace con un correo. */
  user-select: all;
}
.avi-cuando { font-size: 12px; color: var(--ink-faint, #6e678c); white-space: nowrap; }
.avi-fuera {
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--ink-faint, #6e678c);
  font-size: 15px;
  line-height: 1;
  padding: 5px 7px;
  cursor: pointer;
}
.avi-fuera:hover { background: rgba(255, 85, 102, .16); color: #ff8a97; }

.avi-vacio {
  display: grid;
  gap: 6px;
  padding: 34px 24px;
  border-radius: 12px;
  border: 1px dashed rgba(157, 107, 255, .28);
  text-align: center;
}
.avi-vacio strong { font-size: 15px; font-weight: 600; }
.avi-vacio p { margin: 0; font-size: 13px; color: var(--ink-faint, #6e678c); }

@media (max-width: 900px) {
  .avi-resumen { grid-template-columns: 1fr 1fr; }
  .avi-caja--curva { grid-column: 1 / -1; }
  /* La fecha se va: en 390 píxeles, el correo entero vale más que saber si se
     apuntó a las siete o a las ocho. */
  .avi-fila { grid-template-columns: 20px 1fr 30px; }
  .avi-cuando { display: none; }
}

/* =============================================================================
   QUIÉN ESTÁ DENTRO
   La lista viva del cuartel general. Se reescribe cada diez segundos, así que
   nada de aquí puede depender de una animación larga: lo que esté a medias
   cuando llegue la lectura siguiente se corta.
============================================================================= */
.dtr { min-height: 62px; }
.dtr-filas { display: grid; gap: 1px; margin-top: 2px; }

.dtr-fila {
  display: grid;
  grid-template-columns: 9px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 7px 2px;
  border-bottom: 1px solid rgba(157, 107, 255, .08);
}
.dtr-fila:last-child { border-bottom: 0; }

/* El punto de estado. Verde y latiendo si está jugando, morado si espera en una
   sala, apagado si anda por el menú. Es lo que se lee sin leer. */
.dtr-luz {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(226, 220, 250, .28);
}
.dtr-fila--sala .dtr-luz { background: var(--violet, #9d6bff); }
.dtr-fila--jugando .dtr-luz {
  background: var(--lime, #a8f425);
  box-shadow: 0 0 0 0 rgba(168, 244, 37, .5);
  animation: dtr-late 2s ease-out infinite;
}
@keyframes dtr-late {
  70% { box-shadow: 0 0 0 6px rgba(168, 244, 37, 0); }
  100% { box-shadow: 0 0 0 0 rgba(168, 244, 37, 0); }
}

.dtr-quien { display: flex; align-items: baseline; gap: 7px; min-width: 0; }
.dtr-quien strong {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 14px;
  font-weight: 600;
}
.dtr-lugar {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 11.5px;
  color: var(--ink-faint, #6e678c);
}
.dtr-jefe {
  flex: none;
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(157, 107, 255, .2);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--violet, #9d6bff);
}

.dtr-que { display: grid; justify-items: end; gap: 1px; }
.dtr-donde {
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-dim, #a79fc8);
  max-width: 22ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dtr-fila--jugando .dtr-donde { color: var(--lime, #a8f425); }
.dtr-rato { font-size: 11px; color: var(--ink-faint, #6e678c); white-space: nowrap; }

.dtr-vacio {
  margin: 6px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-faint, #6e678c);
}
.dtr-vacio strong { color: var(--ink-dim, #a79fc8); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .dtr-fila--jugando .dtr-luz { animation: none; }
}

/* =============================================================================
   ALTURA DE LOS MUEBLES (editor)
   Cuatro botones y un aviso, debajo del panel de luces. Es lo que decide cuánto
   tira la sombra de cada mueble.
============================================================================= */
.ed-h3 {
  margin: 18px 12px 4px;
  padding-top: 14px;
  border-top: 1px solid rgba(157, 107, 255, .18);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-faint, #6e678c);
}
.ed-h3 + .msg-lead { margin: 0 12px; }

.alt-fila {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
  margin: 10px 12px;
}
.alt-btn {
  padding: 7px 4px;
  border: 0;
  border-radius: 8px;
  background: rgba(255, 255, 255, .05);
  box-shadow: inset 0 0 0 1px rgba(157, 107, 255, .2);
  color: var(--ink-dim, #a79fc8);
  font-size: 11.5px;
  font-weight: 500;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease;
}
.alt-btn:hover { background: rgba(157, 107, 255, .16); color: var(--ink, #f4f2ff); }
.alt-btn.on {
  background: rgba(168, 244, 37, .14);
  box-shadow: inset 0 0 0 1px rgba(168, 244, 37, .45);
  color: var(--lime, #a8f425);
  font-weight: 600;
}
.alt-fila + .msg-lead { margin: 0 12px 14px; }

/* El botón de adivinar alturas, debajo de la fila de las cuatro. */
.alt-todas { margin: 0 12px 10px; width: calc(100% - 24px); }
