/* ============================================================
   Memorie Legends — mesa de juego
   Paleta de casino: fieltro verde, madera y oro sobre fondo oscuro.
   ============================================================ */

:root {
  --noche-1: #0a0a0a;
  --noche-2: #101010;
  --noche-3: #16161a;

  /* El paño dejó de ser verde.

     Era fieltro de casino y la mesa ahora es una sala de piedra: sobre
     verde, el oro de los marcos y el azul de los dorsos se pelean con el
     fondo en vez de despegarse de él. Los nombres de las variables se
     quedan —los usa media hoja— pero lo que guardan es el azul de la
     piedra pulida. */
  --fieltro-claro: #24304a;
  --fieltro: #161f33;
  --fieltro-hondo: #0a1020;

  /* Las antorchas del salón. Un solo tono cálido, en tres intensidades. */
  --antorcha: rgba(255, 168, 76, 0.5);
  --antorcha-tenue: rgba(255, 148, 60, 0.16);

  /* El verde del turno: el aro que cuenta y el filo del asiento activo. */
  --turno: #43d17f;
  --turno-hondo: rgba(67, 209, 127, 0.35);

  /* El corte de los marcos: cuánto se le come a cada esquina.
     Vive acá porque lo comparten el asiento, la botonera y las tarjetas del
     costado, y si cada uno eligiera el suyo la mesa dejaría de leerse como
     una sola pieza. */
  --corte: 13px;

  --madera-clara: #8a6432;
  --madera: #4a2f16;
  --madera-honda: #1d1108;

  --oro: #d4a843;
  --oro-claro: #f0d060;
  --oro-hondo: #8a6d2a;

  --rojo: #c0392b;
  --verde: #3d8b6b;
  --ambar: #f0d060;

  --texto: #ffffff;
  --texto-tenue: #c0c0c0;
  --vidrio: rgba(18, 18, 22, 0.86);
  --vidrio-borde: rgba(212, 168, 67, 0.18);

  /* Las cartas se miden contra la altura de la ventana, no en píxeles fijos.
     Así, en una pantalla baja el paño encoge las cartas en vez de empujar la
     botonera fuera del viewport. `dvh` y no `vh` por la barra de direcciones
     del móvil, que cambia de alto mientras se juega. */
  --carta-alto: clamp(66px, 13.4dvh, 136px);
  --carta-ancho: calc(var(--carta-alto) * 0.667);
  --carta-radio: 6px;

  --sombra-carta: 0 6px 14px rgba(0, 0, 0, 0.55), 0 2px 4px rgba(0, 0, 0, 0.4);
  --sombra-carta-alta: 0 18px 34px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(212, 168, 67, 0.3);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
  color: var(--texto);

  /* La mesa es una superficie, no una página: ocupa exactamente la ventana y
     no se desplaza nunca. Lo que sobra o falta lo absorbe el paño. */
  height: 100dvh;
  padding: 10px;
  overflow: hidden;

  /* La sala donde está la mesa.

     Cinco capas, de arriba hacia abajo: el grano de la piedra, las dos
     antorchas de los costados, el halo del techo, la penumbra del suelo y
     el degradado de la pared.

     Está hecho con degradados y un mosaico de ruido de un kilobyte, y no
     con una ilustración, por una razón práctica: una foto de sala de piedra
     que se vea bien pesa entre 300 KB y un mega, y se carga JUSTO cuando el
     jugador está esperando que se reparta. Esto pesa nada y no se descarga.

     Si algún día hay una ilustración, entra como una capa más arriba de
     todo esto y no hay que tocar ninguna otra regla: ver `--sala` abajo. */
  background:
    var(--sala, none),
    url("/img/mesa/piedra.svg") 0 0 / 320px 320px repeat,
    radial-gradient(ellipse 26% 62% at 0% 42%, var(--antorcha-tenue), transparent 70%),
    radial-gradient(ellipse 26% 62% at 100% 42%, var(--antorcha-tenue), transparent 70%),
    radial-gradient(ellipse 90% 46% at 50% 0%, rgba(212, 168, 67, 0.1), transparent 72%),
    radial-gradient(ellipse 80% 55% at 50% 100%, rgba(0, 0, 0, 0.6), transparent 70%),
    linear-gradient(178deg, #131721 0%, #0a0d15 55%, #05070c 100%);
  background-blend-mode: normal, soft-light, screen, screen, screen, normal, normal;
  background-attachment: fixed;
}

/* Viñeta general para concentrar la vista en la mesa. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  background: radial-gradient(ellipse at center, transparent 50%, rgba(0, 0, 0, 0.62) 100%);
}

/* Las dos antorchas.

   Son luz, no objetos: no se dibuja el hierro ni la llama, sólo lo que
   iluminan. Un fuego dibujado con degradados se ve como un fuego dibujado
   con degradados; su resplandor sobre una pared, en cambio, se ve como un
   resplandor.

   El parpadeo es lento y de poca amplitud —seis segundos, entre 0.72 y 1—
   porque esto está DETRÁS de una mesa donde alguien tiene que acordarse de
   una carta. Un fondo que late rápido compite con el juego.

   Y respeta `prefers-reduced-motion`: quien pidió menos movimiento ve las
   antorchas quietas y encendidas, no apagadas. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(circle 190px at 3% 26%, var(--antorcha), transparent 68%),
    radial-gradient(circle 190px at 97% 26%, var(--antorcha), transparent 68%);
  opacity: 0.5;
  animation: fuego 6s ease-in-out infinite alternate;
}

@keyframes fuego {
  0% { opacity: 0.38; }
  100% { opacity: 0.6; }
}

@media (prefers-reduced-motion: reduce) {
  body::before { animation: none; opacity: 0.48; }
}

.escena {
  position: relative;
  z-index: 2;
  max-width: 1360px;
  height: 100%;
  margin: 0 auto;
  display: grid;
  gap: 10px;
  grid-template-columns: minmax(0, 1fr) 200px;

  /* La única fila elástica es la del paño. Cabecera, pista y acciones toman lo
     que necesitan y no se mueven nunca; el `minmax(0, 1fr)` es lo que permite
     que la mesa se encoja por debajo de su contenido en vez de desbordar. */
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  grid-template-areas:
    "cabecera cabecera"
    "mesa     lateral"
    "pista    lateral"
    "acciones lateral";
}

/* ================================================== cabecera */

.cabecera {
  grid-area: cabecera;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 16px;
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(28, 38, 54, 0.85), rgba(12, 17, 25, 0.85));
  border: 1px solid var(--vidrio-borde);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

.cabecera .marca {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  object-fit: cover;
  border: 1px solid rgba(212, 168, 67, 0.4);
  box-shadow: 0 0 18px rgba(212, 168, 67, 0.2);
}

/* La marca, en serif como en el resto del sitio.

   La mesa era la única pantalla con el nombre en palo seco: todos los
   títulos del proyecto van en Playfair Display y ésta se quedó en la
   tipografía del cuerpo. No se notaba porque nadie tiene las dos pantallas
   al lado.

   Y va con la familia de respaldo, no con Playfair: `mesa.html` es la única
   página que NO enlaza Google Fonts, y no es un olvido —es la pantalla donde
   el jugador está esperando que se reparta, y una fuente que descargar antes
   de dibujar el título no vale lo que cuesta—. `Playfair respaldo` está
   declarada en `tema.css` como Georgia con las métricas corregidas para
   parecerse a Playfair, sale de la máquina y no pide nada a la red.

   Las mayúsculas se quedan: el logo del costado también las usa. */
.cabecera h1 {
  font-family: "Playfair respaldo", Georgia, "Times New Roman", serif;
  font-size: 1.14rem;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  font-weight: 700;
  background: linear-gradient(180deg, var(--oro-claro) 10%, var(--oro) 55%, var(--oro-hondo) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 2px 6px rgba(212, 168, 67, 0.25));
}

.cabecera .lema {
  font-size: 0.6rem;
  letter-spacing: 2.4px;
  text-transform: uppercase;
  color: var(--texto-tenue);
}

.cabecera .derecha {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

.chip-ronda {
  padding: 5px 13px;
  border-radius: 999px;
  font-size: 0.78rem;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--oro-claro);
  background: rgba(212, 168, 67, 0.09);
  border: 1px solid rgba(212, 168, 67, 0.32);
  white-space: nowrap;
}

.chip-ronda strong {
  font-size: 1.05rem;
  color: #fff;
}

.btn-icono {
  width: 34px;
  height: 34px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--vidrio-borde);
  background: rgba(255, 255, 255, 0.05);
  color: var(--texto);
  font-size: 1rem;
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: background 0.2s, transform 0.2s;
}

.btn-icono:hover {
  background: rgba(212, 168, 67, 0.16);
  transform: translateY(-2px);
}

/* ====================================================== mesa */

.mesa-zona {
  grid-area: mesa;
  display: flex;
  flex-direction: column;
  align-items: center;

  /* Sin esto un ítem de grid se niega a encogerse por debajo de su contenido
     y el techo de 100dvh deja de servir para nada. */
  min-height: 0;
}

.mesa {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 0;
  border-radius: 50% / 44%;

  /* Los cuatro asientos y las pilas se reparten el alto disponible: arriba el
     rival de enfrente, al medio las pilas, abajo tu mano. Los laterales van
     absolutos porque ocupan el ancho que aquéllos no usan. */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 6px 0;

  /* El borde hace de baranda de madera; el relleno, de piedra pulida.

     `--pano` es el paño COMPRADO, y va arriba de todo.

     Con la variable sin definir la capa vale `none`, no pinta nada y se ve
     el degradado de siempre. O sea que quien no compró nada ve exactamente
     la mesa de antes, sin una regla condicional de por medio.

     Va en `padding-box` como el degradado: el `border-box` es la baranda de
     madera, y un paño que la tapara dejaría la mesa sin borde. */
  border: 14px solid transparent;
  background:
    var(--pano, none) padding-box,
    radial-gradient(
        ellipse 74% 66% at 50% 44%,
        var(--fieltro-claro) 0%,
        var(--fieltro) 44%,
        #101728 74%,
        var(--fieltro-hondo) 100%
      )
      padding-box,
    linear-gradient(
        155deg,
        var(--madera-clara) 0%,
        var(--madera) 26%,
        #6d5227 48%,
        var(--madera-honda) 74%,
        #5c421f 100%
      )
      border-box;
  box-shadow:
    0 40px 90px rgba(0, 0, 0, 0.7),
    0 0 0 1px rgba(212, 168, 67, 0.5),
    inset 0 0 0 2px rgba(212, 168, 67, 0.26),
    inset 0 0 70px rgba(0, 0, 0, 0.5),
    inset 0 22px 60px rgba(0, 0, 0, 0.45);
}

/* La rosa de los vientos grabada en el paño.

   Va con `mask-image` y no con un `<img>` de fondo por una razón concreta:
   dentro de un `url()` de CSS, el `currentColor` del SVG no hereda nada —el
   archivo se resuelve contra sí mismo y sale negro—. Usándolo de máscara,
   el dibujo aporta la FORMA y el color lo pone esta regla, así que el oro
   del grabado se cambia acá y no abriendo el SVG.

   `contain` y no `cover`: la brújula tiene que entrar entera. Con `cover`,
   en una ventana ancha se le cortan el norte y el sur y queda una figura
   que no se reconoce.

   ─────────────────────────────────────────────────────────────────────────
   POR QUÉ ESTÁ GRABADA Y NO PINTADA DE ORO
   ─────────────────────────────────────────────────────────────────────────

   Era un degradado dorado, y andaba bien mientras el paño fue uno solo y
   oscuro. Con los paños comprables desapareció: sobre el roble de taberna es
   oro sobre oro y no se ve absolutamente nada.

   Ahora se dibuja como un GRABADO: una línea clara con una sombra oscura
   corrida un píxel. Eso funciona sobre cualquier superficie —claro sobre
   oscuro, sombra sobre claro— sin que el paño tenga que traer un color
   propio para la brújula, que es un dato que el catálogo no puede guardar:
   un artículo tiene una imagen, no una paleta.

   La sombra es un `drop-shadow` y no un segundo elemento porque el filtro se
   aplica DESPUÉS de la máscara: sigue el contorno de la brújula, que es lo
   que hay que sombrear, y no el rectángulo que la contiene. */
.mesa::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0.5;
  background: rgba(255, 244, 214, 0.85);
  filter: drop-shadow(0 1.5px 0 rgba(0, 0, 0, 0.55));
  -webkit-mask: url("/img/mesa/rosa-viento.svg") center 46% / contain no-repeat;
  mask: url("/img/mesa/rosa-viento.svg") center 46% / contain no-repeat;
}

/* La veta de la piedra. Ruido estirado, casi invisible: su trabajo es que la
   superficie no se lea como un degradado plano. */
.mesa::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0.16;
  mix-blend-mode: overlay;
  background: url("/img/mesa/vetas.svg") 0 0 / 600px 600px repeat;
}

/* ---- asientos alrededor del óvalo ---- */

.asiento {
  position: absolute;
  z-index: 3;
  display: flex;
  justify-content: center;

  /* Sin esto el tope de más abajo no sirve para nada.

     Un ítem de flex arranca con `min-width: auto`, que quiere decir «no
     encojas por debajo de tu contenido». El asiento tenía su `max-width`, el
     jugador de adentro se negaba a achicarse, y con siete cartas las manos
     laterales se salían del paño por los dos costados —medido: 60 píxeles
     por izquierda—.

     La cadena tiene que poder encoger ENTERA: asiento, jugador y mano. Recién
     ahí el `flex-shrink` de las cartas recibe la orden. */
  min-width: 0;
}

.asiento > .jugador { min-width: 0; }

/* Arriba y abajo participan del reparto vertical del paño. */
.asiento-arriba,
.asiento-abajo {
  position: static;
  transform: none;
}

.asiento-abajo { z-index: 5; }

/* Cuánto puede ocupar cada asiento.

   ─────────────────────────────────────────────────────────────────────────
   POR QUÉ HACE FALTA UN TOPE
   ─────────────────────────────────────────────────────────────────────────

   Los laterales tienen la mitad del paño menos las pilas del centro: unos
   410 píxeles en una pantalla ancha. Cuatro cartas entran. Seis —una mano
   con dos castigos— piden 534, y la mano se metía encima del mazo y de la
   muestra. No es un problema estético: tapa las dos pilas que hay que
   mirar para saber si se puede descartar.

   El tope va acá, en el asiento, y no en la mano: es una propiedad del
   LUGAR —cuánto paño le toca a esa silla—, no de las cartas que tenga
   encima. Arriba y abajo el tope es holgado porque ahí el ancho es el del
   paño entero.

   Lo que hace que el tope no corte nada es el `flex-shrink` de las cartas,
   más abajo: al no entrar, encogen.

   ─────────────────────────────────────────────────────────────────────────
   Y POR QUÉ VA DENTRO DE UNA CONSULTA DE MEDIOS
   ─────────────────────────────────────────────────────────────────────────

   Porque este tope describe el óvalo de escritorio, donde los laterales son
   absolutos y se reparten el paño a los costados de las pilas. De 950 para
   abajo la mesa deja de ser un óvalo y pasa a ser una grilla, y ahí el 32%
   se resuelve contra la CELDA y no contra el paño: a 768 de ancho dejaba a
   cada rival en 76 píxeles, y sus cuatro cartas encogían hasta 16.

   A 360 el resultado era peor y es lo que se veía: cartas de diez píxeles y
   los tres nombres escritos unos encima de otros. El `flex-shrink` no
   estaba fallando —hacía exactamente lo que se le pidió— sino obedeciendo a
   un tope que no correspondía a ese diseño. */
@media (min-width: 951px) {
  /* Treinta por ciento, no treinta y dos.
     Las pilas del centro pasaron a medir lo mismo que una carta de la mesa —antes
     eran más chicas— así que el centro se ensanchó y las manos laterales
     llegaron a taparlo por cinco píxeles. El tope cede lo que el centro ganó.
     Lo encontró `mesa-vestida.spec.js`, que mide cada carta contra las pilas. */
  .asiento-izq,
  .asiento-der {
    max-width: 30%;
  }

  .asiento-arriba,
  .asiento-abajo {
    max-width: 92%;
  }
}

.asiento-izq {
  left: 8px;
  top: 50%;
  transform: translateY(-50%);
}

.asiento-der {
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
}

/* =================================================== jugador */

/* El marco del asiento: esquinas cortadas y filo dorado.

   ─────────────────────────────────────────────────────────────────────────
   POR QUÉ EL FILO ES UN FONDO Y NO UN BORDE
   ─────────────────────────────────────────────────────────────────────────

   Porque clip-path corta TODO lo que hay dentro de la caja, el borde
   incluido. Con un borde de un píxel las esquinas quedaban con el bisel
   abierto: la línea dorada recorría los cuatro lados y se interrumpía justo
   en las ocho diagonales, que es donde el marco tiene que verse.

   Así que el dorado es el FONDO del elemento, el relleno oscuro es un
   ::after metido dos píxeles para adentro, y los dos se recortan con la
   misma silueta. Lo que asoma entre uno y otro son esos dos píxeles: un filo
   continuo, diagonales incluidas.

   `isolation: isolate` es lo que hace que funcione. Sin un contexto de
   apilamiento propio, el z-index negativo del relleno se va detrás del paño
   y el asiento aparece dorado y macizo.

   ─────────────────────────────────────────────────────────────────────────
   Y POR QUÉ EL RESPLANDOR DEL TURNO ES UN FILTRO
   ─────────────────────────────────────────────────────────────────────────

   Por lo mismo: clip-path también recorta las sombras. Un box-shadow verde
   alrededor del asiento en turno no se veía en absoluto. drop-shadow se
   aplica DESPUÉS del recorte y sigue la silueta biselada, que además es lo
   que uno querría dibujar a mano.

   Se fue con eso el aro que latía. No es una pérdida: ahora quien tiene el
   turno lleva un aro que cuenta hacia atrás alrededor de su retrato, que es
   movimiento con información adentro. Dos cosas latiendo por el mismo motivo
   son una de más.

   ─────────────────────────────────────────────────────────────────────────
   Y POR QUÉ EL RECORTE VIVE EN LOS DOS SEUDOELEMENTOS Y NO EN EL ASIENTO
   ─────────────────────────────────────────────────────────────────────────

   Porque recortando el asiento se recorta TAMBIÉN lo que tiene adentro, y
   adentro están las cartas. Las de los extremos del abanico van giradas y
   se asoman siete píxeles del relleno; con el recorte puesto en `.jugador`
   esos siete píxeles no se veían. Y una carta cortada no es un defecto
   estético: es una carta a la que le falta una esquina para tocar.

   Así que el marco entero —filo y relleno— es un par de capas de fondo con
   `z-index` negativo, y el recorte se aplica a esas capas. El contenido no
   se recorta nunca y el abanico vuelve a asomarse como asomaba antes.

   Lo encontró `mesa-vestida.spec.js`, que mide cada carta contra la caja de
   su asiento. A ojo no se veía: siete píxeles de una esquina girada parecen
   parte del diseño. */
.jugador {
  position: relative;
  isolation: isolate;
  padding: 4px 10px 6px;
  text-align: center;
  transition: opacity 0.3s, transform 0.3s;
}

/* El halo del asiento en turno.

   Reemplaza al marco entero. Antes cada jugador vivía dentro de una caja
   con filo dorado y relleno oscuro; con cuatro cajas sobre un paño que ya
   tiene su propia textura, la mesa era todo bordes y el ojo no sabía dónde
   pararse. Ahora el asiento es lo que de verdad importa —la cara, el nombre
   y las cartas— apoyado sobre el paño, y lo único que se dibuja es a quién
   le toca.

   Y es un resplandor difuso, no un contorno: un contorno vuelve a ser una
   caja. Con `opacity: 0` no ocupa nada ni pinta nada mientras no sea el
   turno de nadie.

   El aro que cuenta hacia atrás alrededor del retrato sigue estando, y
   sigue siendo el que dice CUÁNTO queda. Este halo dice QUIÉN. */
.jugador::before {
  content: "";
  position: absolute;
  inset: -14px -6px -10px;
  z-index: -2;
  opacity: 0;
  border-radius: 50% / 30%;
  transition: opacity 0.35s;
  background:
    radial-gradient(ellipse at 50% 34%, var(--turno-hondo) 0%, transparent 68%);
}

.jugador.en-turno { transform: translateY(-3px); }
.jugador.en-turno::before { opacity: 1; }

/* Sin caja detrás, el texto se apoya en el paño y necesita su propia
   sombra: el nombre en blanco sobre el roble claro se borraba. La sombra no
   se ve sobre los paños oscuros y salva a los claros, igual que en los
   rótulos del centro. */
.jugador .nombre,
.jugador .puntos {
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.9), 0 0 12px rgba(0, 0, 0, 0.6);
}

.jugador.eliminado {
  opacity: 0.35;
  filter: grayscale(1);
}

/* La insignia sí conserva su fondo: es una pastilla chica de texto y sin
   nada detrás se pierde entre el nombre y el paño. */
.jugador .insignia {
  backdrop-filter: blur(3px);
  text-shadow: none;
}

.jugador .cabecera-jugador {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 11px;
  margin-bottom: 8px;
}

/* ------------------------------------------------------- el retrato

   Un círculo con dos aros superpuestos: el de abajo es el marco dorado, que
   está siempre; el de arriba es la cuenta atrás, que sólo se dibuja mientras
   a ese asiento le toca.

   El de arriba es un conic-gradient cuyo ángulo escribe temporizadores.js en
   --vuelta, tick a tick, con el MISMO reloj que pinta el número del cartel.
   En reposo --aro-vivo es transparente, así que la capa existe y no se ve: no
   hay que agregar ni sacar reglas al empezar el turno, sólo cambiar una
   variable. */
.jugador .retrato {
  --retrato: 62px;
  --aro: 3px;
  --aro-vivo: transparent;
  --vuelta: 0deg;
  position: relative;
  flex-shrink: 0;
  width: var(--retrato);
  height: var(--retrato);
  border-radius: 50%;
  background:
    conic-gradient(from -90deg, var(--aro-vivo) 0deg var(--vuelta), transparent var(--vuelta) 360deg),
    linear-gradient(180deg, var(--oro-claro), var(--oro) 55%, var(--oro-hondo));
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.55), 0 4px 10px rgba(0, 0, 0, 0.5);
}

/* La ventana redonda por donde se ve la cara.

   ─────────────────────────────────────────────────────────────────────────
   POR QUÉ HAY UN ENVOLTORIO Y NO SÓLO LA IMAGEN
   ─────────────────────────────────────────────────────────────────────────

   Porque el aro dorado es el FONDO de `.retrato`, y un `overflow: hidden`
   ahí recorta contra la caja de relleno, que es la misma donde está pintado
   el aro: la cara terminaría tapándolo. Este envoltorio se mete `--aro`
   píxeles para adentro y recorta ahí, así que el aro queda por fuera del
   recorte y se ve entero.

   ─────────────────────────────────────────────────────────────────────────
   Y POR QUÉ LA IMAGEN VA AL DOBLE Y CORRIDA HACIA ARRIBA
   ─────────────────────────────────────────────────────────────────────────

   Porque los trece avatares no son caras: son MEDALLONES. Cada PNG trae la
   figura dentro de su propio aro dorado y con una cinta con el nombre
   debajo, sobre fondo transparente. Metido entero en un círculo de sesenta
   píxeles se ve un aro dentro de otro aro y una cinta ilegible, y la cara
   queda ocupando un tercio del espacio.

   Al doble y corrida, lo que queda a la vista es la ventana de 200x200
   centrada en (200, 175) del original de 400x400: la cara, sin el aro de la
   ilustración —que reemplaza el de acá— y sin la cinta, que repetiría el
   nombre que ya está escrito al lado.

   Los números salen de la plantilla que comparten los trece. Es la única
   atadura entre esta hoja y el arte, y por eso está escrita: un avatar nuevo
   con otra composición hay que componerlo igual, o cambiar esto. */
.jugador .retrato .cara {
  position: absolute;
  inset: var(--aro);
  border-radius: 50%;
  overflow: hidden;
  background: #0b0f18;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.6);
}

.jugador .retrato .cara img {
  position: absolute;
  width: 200%;
  height: 200%;
  left: -50%;
  top: -37.5%;
  object-fit: contain;
  display: block;
}

/* El aro del color del asiento, por fuera del dorado.

   Es lo que reemplaza a la miniatura del dorso que había antes al lado del
   nombre. Sin ella habría que adivinar de quién es cada mano, y eso el
   retrato solo no lo dice: dos jugadores pueden tener la misma cara en
   partidas distintas, el color del asiento no. */
.jugador .retrato::before {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1px solid var(--color-asiento, rgba(212, 168, 67, 0.5));
  box-shadow: 0 0 10px -2px var(--color-asiento, transparent);
}

.jugador .retrato.contando { --aro-vivo: var(--turno); }
.jugador .retrato.apurado { --aro-vivo: #ff5a45; }

/* Los segundos que quedan, colgados del retrato.

   Va con aria-hidden: el texto cambia ocho veces por segundo y un lector de
   pantalla que lo anunciara no dejaría oír otra cosa. Lo que sí se anuncia es
   el cambio de fase, y eso lo dice la pista.

   Vacío no ocupa lugar: sin contenido, el relleno y el fondo seguirían
   dibujando una pastilla diminuta, así que se esconde cuando no hay número. */
.jugador .cuenta-asiento {
  position: absolute;
  top: -7px;
  left: 50%;
  transform: translateX(-50%);
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 0.6rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.3px;
  color: #05210f;
  background: var(--turno);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
  white-space: nowrap;
}

.jugador .cuenta-asiento:empty { display: none; }
.jugador .retrato.apurado .cuenta-asiento { background: #ff5a45; color: #2a0803; }

/* --------------------------------------------------- nombre y puntos */

.jugador .datos {
  text-align: left;
  min-width: 0;
}

.jugador .nombre {
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.4px;
  display: flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
}

.jugador .nombre::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--color-asiento, var(--oro));
  box-shadow: 0 0 8px var(--color-asiento, var(--oro));
}

.jugador .insignia {
  font-size: 0.58rem;
  text-transform: uppercase;
  letter-spacing: 1px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(212, 168, 67, 0.14);
  border: 1px solid rgba(212, 168, 67, 0.32);
  color: var(--oro-claro);
}

/* La insignia ganada va como imagen, y sin la pastilla.

   La de arriba es texto —DIFÍCIL, MEDIO— y necesita algo detrás para no
   perderse contra el paño. Ésta trae su propio contorno y su propio color:
   encerrarla en el marco dorado le pondría un segundo borde discutiendo con
   el suyo.

   El alto va en `em` y no en píxeles a propósito. `--retrato` se reajusta en
   seis pasos de media query, y una insignia con medida fija habría necesitado
   los seis; atada al tamaño de letra del nombre —que ya baja a 0.72rem y a
   0.68rem— encoge sola. 1.6em es un poco más alto que la línea, que es lo que
   hace que se lea como una medalla al lado del nombre y no como parte de él. */
.jugador .insignia-mesa {
  height: 1.6em;
  width: auto;
  flex-shrink: 0;
  object-fit: contain;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.75));
}

/* Dos renglones y no uno.

   Ronda es lo que se anotó en la ronda anterior y Total lo acumulado en la
   partida. Puestos en la misma línea con un punto en el medio —que es como
   estaba— se leen como un solo número partido; en dos renglones alineados a
   la izquierda se leen como lo que son, dos cuentas distintas.

   tabular-nums para que al pasar de 9 a 10 el renglón de abajo no se corra. */
.jugador .puntos {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-top: 2px;
  font-size: 0.68rem;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--texto-tenue);
  white-space: nowrap;
}

.jugador .puntos b {
  font-size: 0.92rem;
  font-variant-numeric: tabular-nums;
  margin-left: 3px;
}

.jugador .puntos .parcial b { color: #7fc4ff; }
.jugador .puntos .acumulado b { color: var(--oro-claro); }

/* Tu asiento juega con cartas más grandes. */
/* Tus cartas son las que tocás bajo presión de reloj: se dimensionan aparte
   y son siempre las más grandes de la mesa. */
.jugador.propio {
  --carta-alto: clamp(100px, 20.4dvh, 210px);
  --carta-ancho: calc(var(--carta-alto) * 0.667);
  padding: 4px 14px 6px;
}

.jugador.propio .nombre { font-size: 1.05rem; }
.jugador.propio .retrato { --retrato: 74px; }
/* ====================================================== mano */

.mano {
  display: flex;
  min-width: 0;
  gap: 8px;
  justify-content: center;
  align-items: flex-end;
  flex-wrap: nowrap;
  padding-top: 6px;
  max-width: 100%;
}

/* La carta cede ancho cuando la mano no entra en su asiento.

   `--escala` la calcula `geometriaAbanico` y es el tamaño que la mano
   QUERRÍA tener; esto es lo que hace que quepa igual cuando no alcanza.
   Son dos cosas distintas y las dos hacen falta: sin la escala, ocho cartas
   entrarían encogidas hasta ser ilegibles en un asiento y enormes en otro;
   sin el `flex-shrink`, la escala tendría que conocer el ancho de cada
   silla, que es una medida del CSS y no del abanico.

   `aspect-ratio` con `height: auto` es lo que impide que encoger deforme la
   carta. Con la altura fija, ceder ancho las dejaba flacas y largas.

   Va sobre los hijos DIRECTOS de una mano y no sobre `.carta` a secas: las
   pilas del centro y las del modal también son cartas, y ahí no hay nada
   que encoger. */
.mano > .carta,
.mano > .hueco {
  flex: 0 1 auto;
  min-width: 0;
  width: calc(var(--carta-ancho) * var(--escala, 1));
  height: auto;
  aspect-ratio: 2 / 3;
}

.hueco {
  --giro: 0deg;
  --desvio: 0px;
  --solape: 0px;

  transform-origin: 50% 130%;
  transform: rotate(var(--giro)) translateY(var(--desvio));
  margin-inline: calc(var(--solape) / -2);
  width: calc(var(--carta-ancho) * var(--escala, 1));
  height: calc(var(--carta-alto) * var(--escala, 1));
  border-radius: var(--carta-radio);
  border: 1px dashed rgba(212, 168, 67, 0.22);
  background: rgba(0, 0, 0, 0.25);
  position: relative;
}

.hueco.vacio::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: repeating-linear-gradient(
    45deg,
    transparent 0 6px,
    rgba(212, 168, 67, 0.05) 6px 12px
  );
}

/* ---- carta 3D ---- */

/* `--escala` la escribe la mano, y sale de `geometriaAbanico`: con más de
   cuatro cartas la mano encoge en vez de montarlas unas sobre otras. Vale 1
   en todo lo que no está dentro de una mano —las pilas del centro, el
   modal— porque nadie se la define. */
.carta {
  --giro: 0deg;
  --desvio: 0px;
  --solape: 0px;

  width: calc(var(--carta-ancho) * var(--escala, 1));
  height: calc(var(--carta-alto) * var(--escala, 1));
  border-radius: var(--carta-radio);
  position: relative;
  perspective: 900px;
  border: none;
  padding: 0;
  background: none;
  cursor: default;
  transform-origin: 50% 130%;
  transform: rotate(var(--giro)) translateY(var(--desvio));
  margin-inline: calc(var(--solape) / -2);
  transition: transform 0.25s cubic-bezier(0.34, 1.4, 0.64, 1), filter 0.25s;
}

.carta.jugable { cursor: pointer; }

/* Mano de un rival sobre la que un poder 8 o 10 dejó conocimiento.
   Se marca la mano ENTERA, a propósito: el servidor manda a quién se puede
   atacar y jamás dónde está la carta. Señalar una posición sería regalar
   justo lo que el jugador tiene que recordar. */
.carta.atacable::before {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: calc(var(--carta-radio) + 3px);
  border: 2px dashed rgba(240, 208, 96, 0.55);
  pointer-events: none;
}

.carta.atacable:hover::before { border-color: var(--oro-claro); }

/* La carta bajo el cursor se despega del abanico sin perder su ángulo. */
.carta.jugable:hover {
  transform: rotate(var(--giro)) translateY(calc(var(--desvio) - 16px)) scale(1.06);
  z-index: 6;
}

.carta.jugable::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: calc(var(--carta-radio) + 4px);
  border: 2px solid var(--oro);
  box-shadow: 0 0 20px rgba(212, 168, 67, 0.55);
  opacity: 0;
  transition: opacity 0.22s;
  pointer-events: none;
}

/* El brillo dorado dice "esto se puede tocar AHORA".

   Antes sólo aparecía al pasar el ratón por encima, y en un teléfono no hay
   ratón: la única forma de saber si le tocaba a uno era leer la barra de
   pista. Con el aro tenue puesto de base, se ve de un vistazo — y cuando no
   es el turno del jugador, sus cartas no lo tienen y eso también se ve. */
.carta.jugable::after { opacity: 0.4; }

.carta.jugable:hover::after,
.carta.seleccionada::after { opacity: 1; }

.carta .lados {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  transition: transform 0.55s cubic-bezier(0.45, 0.05, 0.2, 1);
}

.carta.visible .lados { transform: rotateY(180deg); }

.carta .cara,
.carta .dorso {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: var(--carta-radio);
  overflow: hidden;
  background: var(--noche-3);
  box-shadow: var(--sombra-carta);
}

.carta .cara {
  transform: rotateY(180deg);
  background: #f6f1e4;
}

.carta.jugable:hover .cara,
.carta.jugable:hover .dorso { box-shadow: var(--sombra-carta-alta); }

.carta img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

/* Brillo diagonal que da sensación de barniz. */
.carta .cara::after,
.carta .dorso::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    118deg,
    rgba(255, 255, 255, 0.26) 0%,
    rgba(255, 255, 255, 0.06) 22%,
    transparent 46%,
    rgba(0, 0, 0, 0.16) 100%
  );
}

/* Dorsos de los asientos 3 y 4 si faltan los PNG propios. */
/* Sólo hay dorso azul y rojo. Los asientos 3 y 4 los repiten, así que lo que
   los identifica es este aro de color alrededor de la carta y de la ficha. */
.asiento-color-0 { --color-asiento: #4a7fb5; }
.asiento-color-1 { --color-asiento: #c0392b; }
.asiento-color-2 { --color-asiento: #35c98a; }
.asiento-color-3 { --color-asiento: #d4a843; }

.carta[class*="asiento-color-"] .dorso {
  box-shadow: var(--sombra-carta), inset 0 0 0 2px var(--color-asiento);
}

/* Los dos primeros no necesitan refuerzo: su dorso ya es único. */
.carta.asiento-color-2 .dorso,
.carta.asiento-color-3 .dorso {
  box-shadow: var(--sombra-carta), inset 0 0 0 3px var(--color-asiento),
    0 0 12px -2px var(--color-asiento);
}

.carta.recien-cambiada { animation: destello 0.65s ease-out; }

@keyframes destello {
  0%   { box-shadow: 0 0 0 0 rgba(212, 168, 67, 0.85); }
  100% { box-shadow: 0 0 0 22px rgba(212, 168, 67, 0); }
}

.posicion {
  position: absolute;
  bottom: 3px;
  left: 5px;
  z-index: 3;
  font-size: 0.6rem;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.6);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
}

/* ==================================================== centro */

.centro {
  position: static;
  transform: none;
  display: flex;
  align-items: flex-start;
  gap: 26px;
  z-index: 2;
}

.pila { text-align: center; }

/* Los rótulos del centro se esconden, pero se siguen anunciando.

   ─────────────────────────────────────────────────────────────────────────
   POR QUÉ NO ES `display: none`
   ─────────────────────────────────────────────────────────────────────────

   Mirando la mesa no hacen falta: el mazo es una pila boca abajo, la muestra
   es la única carta dada vuelta, y el hueco del medio es el de la levantada.
   Tres palabras en mayúsculas sobre el paño eran ruido, y encima se comían
   el alto que necesitan las cartas.

   Pero quien no ve la pantalla no tiene ninguna de esas pistas: para un
   lector de pantalla las tres pilas serían «Carta, boca abajo» tres veces.
   Con `display: none` el rótulo desaparece también para él.

   Así que se saca de la vista y se deja en el árbol: fuera de la pantalla,
   de un píxel y sin recorte. El truco de siempre, y el motivo por el que se
   usa éste y no `visibility: hidden` —que también lo esconde del lector— ni
   `opacity: 0` —que deja el hueco ocupado, que es justo lo que se quería
   recuperar—.

   ─────────────────────────────────────────────────────────────────────────
   EL CONTADOR VA CON EL MISMO TRATO, Y CUESTA MÁS
   ─────────────────────────────────────────────────────────────────────────

   «39 cartas» debajo del mazo era el único lugar donde se veía cuánto queda
   por levantar. Escondiéndolo, quien mira la pantalla pierde ese dato: la
   pila se dibuja como UNA carta, no como un montón, así que no hay ninguna
   otra pista de su altura.

   No es grave —cuando el mazo se acaba, `rellenarMazo` lo rehace con el
   descarte y la partida sigue— pero es información que antes estaba. Queda
   anotado acá por si algún día conviene devolverla de otra forma: el grosor
   de la pila dibujado, por ejemplo, en vez de un número.

   Para el lector de pantalla no cambia nada: sigue leyéndose. */
.pila .etiqueta,
.pila .contador {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* El mazo, la levantada y la muestra miden lo mismo que una carta de la
   mesa.

   Tenían su propio tamaño, más chico, de cuando el centro tenía que ceder
   alto para que entraran las manos. Con los rótulos fuera de la vista ese
   alto volvió, y no hay ninguna razón para que una carta en el centro se vea
   distinta de una carta en una mano: es la misma baraja.

   Se hereda `--carta-alto` de `:root` en vez de repetir el valor. Eso es lo
   que hace que sigan iguales en los ocho escalones de pantalla que tiene
   esta hoja, sin tener que acordarse de tocar tres reglas cada vez. */
.pila .carta {
  --carta-ancho: calc(var(--carta-alto) * 0.667);
}

/* El mazo se ve como una pila de varias cartas. */
#pilaMazo .carta .dorso {
  box-shadow:
    var(--sombra-carta),
    3px 3px 0 -1px rgba(255, 255, 255, 0.07),
    6px 6px 0 -2px rgba(255, 255, 255, 0.05);
}

/* La levantada tampoco: es una carta más. Antes era la más grande del centro
   para que se notara cuál estaba en juego; ahora eso lo dice su marco, que
   se enciende cuando la carta tiene poder. */
.levantada-caja .carta {
  --carta-ancho: calc(var(--carta-alto) * 0.667);
  animation: aparecer 0.4s cubic-bezier(0.2, 1.2, 0.4, 1);
}

@keyframes aparecer {
  from { transform: translateY(22px) scale(0.82) rotateZ(-6deg); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

.levantada-caja.con-poder .carta .cara {
  box-shadow: 0 0 0 2px var(--ambar), 0 0 26px rgba(255, 176, 32, 0.55);
}

.levantada-caja.con-poder .etiqueta { color: var(--ambar); }

/* ==================================================== el cartel

   Una sola pieza: qué hay que hacer, y cuánto queda para hacerlo.

   Antes eran dos —la instrucción por un lado, el reloj por el otro— y decían
   lo mismo con distintas palabras, una al lado de la otra: "Tocá tu carta"
   junto a "ELEGÍ UNA CARTA 2.4s". Dos lugares donde mirar para entender un
   solo momento del juego.

   El color hace el trabajo que hacía el rótulo repetido: oro cuando la
   jugada es tuya, rojo cuando corren los reflejos, plata cuando hay que
   decidir el corte. Se ve antes de leerlo.

   Todo el tono sale de tres variables. Cambiar de fase es cambiar `data-fase`
   en el cartel y nada más: el borde, el texto, la barra y el latido salen de
   ahí. Un color suelto escrito en cada regla es como se termina con tres
   rojos distintos que no combinan. */

.tira-pista {
  grid-area: pista;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;

  /* Por encima del paño, y sordo al tacto.
   *
   * En su fila el cartel no le estorba a nadie, pero un mensaje largo —"Se
   * cortó la conexión con la partida"— lo parte en dos renglones, y en un
   * teléfono bajo esos 16 px de más empujan la mesa hasta que las cartas se
   * meten encima. Justo el mensaje que hay que poder leer, tapado.
   *
   * Se resuelve con el orden de pintado en vez de recortando la mesa: si algo
   * se derrama, se derrama por DEBAJO. Y `pointer-events: none` es la otra
   * mitad — un cartel que se pone delante de una carta no puede además
   * comerse el toque que iba a la carta. */
  position: relative;

  /* Doce, y no tres.
   *
   * Tres alcanzaba en el teléfono y no en la computadora, por una razón que
   * sólo existe con puntero: `.carta.jugable:hover` se levanta con `z-index:
   * 6` para despegarse del abanico. En el móvil no hay hover y no pasaba
   * nunca; en la computadora el puntero vive sobre las cartas propias, así
   * que la carta se ponía delante del cartel justo mientras uno decide.
   *
   * Doce pasa por encima de eso y del 8 de los efectos de poder, y sigue por
   * debajo del cartel de poder (20), del registro (55) y del modal (60): lo
   * que tiene que taparlo, lo sigue tapando. */
  z-index: 12;
  pointer-events: none;
}

.anuncio {
  --tono: var(--oro);
  --tono-claro: var(--oro-claro);
  --tono-filo: rgba(212, 168, 67, 0.5);
  --tono-halo: rgba(212, 168, 67, 0.35);

  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 100%;
  min-width: 0;
  padding: 6px 16px;
  border-radius: 999px;

  /* Casi opaco. Cuando el cartel se pone delante de una carta —pasa con un
     mensaje largo en un teléfono bajo— un fondo translúcido deja el dorso de
     la carta asomando entre las letras. */
  background: rgba(5, 8, 14, 0.96);
  border: 1px solid var(--tono-filo);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.05);
  transition: border-color 0.3s, box-shadow 0.3s;
}

.anuncio .pista {
  min-width: 0;
  font-size: 0.86rem;
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0.4px;
  color: var(--tono-claro);
}

/* Dentro de un texto ya coloreado, la palabra importante se destaca en
   blanco: subirle más el tono al tono no destaca nada. */
.anuncio .pista b { color: #fff; }

/* --- las dos cuentas atrás, con la misma forma --- */

.anuncio .temporizador,
.anuncio .reloj-turno {
  display: none;
  flex: none;
  align-items: center;
  gap: 8px;
}

.anuncio .temporizador.activo,
.anuncio .reloj-turno { display: flex; }
.anuncio .reloj-turno[hidden] { display: none; }

/* Cinturón: si por un cruce de fases los dos quedaran encendidos a la vez, el
   cartel mostraría dos barras contando cosas distintas. Manda la grande. */
.anuncio .temporizador.activo ~ .reloj-turno { display: none; }

.anuncio .barra,
.anuncio .reloj-barra {
  /* Se encoge con la pantalla: en un teléfono de 320 px una barra fija de
     130 px empuja el texto fuera del cartel. */
  width: clamp(44px, 13vw, 120px);
  height: 7px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  overflow: hidden;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.6);
}

/* Las dos se pintan por ancho desde JavaScript, tick a tick. La transición
   corta es sólo para que el salto entre ticks no se vea escalonado; si el
   sistema pide menos movimiento se apaga sola, y la barra sigue diciendo la
   verdad porque el ancho lo pone el reloj, no la animación. */
.anuncio .relleno,
.anuncio .reloj-relleno {
  display: block;
  height: 100%;
  width: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--tono-claro), var(--tono));
  transition: width 0.12s linear;
}

.anuncio .texto,
.anuncio .reloj-numero {
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.5px;
  color: var(--tono-claro);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;

  /* Ancho reservado, y no es un capricho: el cartel está centrado, así que
     cada vez que "10.0s" pasa a "9.9s" el cartel entero se corría un pelo.
     Con el hueco fijo, el número cambia y nada más se mueve. */
  min-width: 3.1em;
  text-align: right;
}

/* --- el color de cada fase --- */

.anuncio[data-fase="descarte"] {
  --tono: var(--rojo);
  --tono-claro: #ff9d84;
  --tono-filo: rgba(233, 69, 96, 0.6);
  --tono-halo: rgba(233, 69, 96, 0.4);
  animation: latido 0.9s ease-in-out infinite;
}

.anuncio[data-fase="postLevantada"] {
  --tono: #8d96a3;
  --tono-claro: #e2e8f0;
  --tono-filo: rgba(226, 232, 240, 0.45);
  --tono-halo: rgba(226, 232, 240, 0.3);
}

/* Los últimos dos segundos del reloj del turno, en rojo y latiendo. Pisa al
   color de la fase a propósito: que se acabe el tiempo es más urgente que
   saber en qué fase estás.

   La clase la pone el reloj sobre el cartel, en vez de resolverlo acá con un
   `:has()`. Es una línea de JavaScript contra un selector que en un iPhone con
   iOS viejo no existe — y ahí el aviso de los dos segundos finales, que es
   justo el que hay que ver, no se vería. */
.anuncio.apurado {
  --tono: #a93226;
  --tono-claro: #ff7a6a;
  --tono-filo: rgba(231, 76, 60, 0.7);
  --tono-halo: rgba(231, 76, 60, 0.4);
  animation: latido 0.7s ease-in-out infinite;
}

@keyframes latido {
  0%, 100% { box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5), 0 0 0 0 var(--tono-halo); }
  50%      { box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5), 0 0 22px 3px var(--tono-halo); }
}

@media (max-width: 720px) {
  .anuncio { gap: 8px; padding: 5px 12px; }
  .anuncio .pista { font-size: 0.78rem; letter-spacing: 0.2px; }
  .anuncio .texto,
  .anuncio .reloj-numero { font-size: 0.72rem; min-width: 2.9em; }
}

/* ================================================== acciones */

/* La caja de los botones: del ancho de los botones, y centrada.

   Antes cruzaba la pantalla entera con los cuatro botones amontonados en una
   punta y medio metro de negro en la otra. Ahora es una pieza del ancho de lo
   que contiene, en el eje de la mesa.

   Que contenga SÓLO botones es lo que la hace posible: adentro estaba el
   reloj, que aparece y desaparece según la fase, y una caja centrada que
   cambia de ancho corre los cuatro botones de sitio justo cuando hay que
   decidir contra reloj. Un botón que se mueve es un botón que se falla, así
   que el reloj se fue arriba, con la pista. */
.acciones {
  grid-area: acciones;
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: center;

  /* Una sola fila, siempre. Si algo empuja los botones a una segunda línea, la
     botonera crece 58px justo en `turno`, que es la fase donde más falta
     hace. */
  flex-wrap: nowrap;
  gap: 9px;
  padding: 11px 14px;
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(28, 38, 54, 0.8), rgba(9, 13, 20, 0.88));
  border: 1px solid var(--vidrio-borde);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

button.accion {
  position: relative;
  flex: none;

  /* El dibujo arriba y la palabra abajo.

     Uno al lado del otro, los cuatro botones sumaban 88px más de ancho y la
     botonera se pasaba del 80% del paño que exige entrenamiento-ux.spec.js.
     Apilados entran en el mismo ancho de antes, y de paso el ícono queda
     más grande: es lo que se reconoce sin leer cuando quedan dos segundos. */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 8px 16px 7px;

  /* El filo dorado, que antes no estaba: es lo que emparenta estos botones con
     el marco de las cartas y con las cajas del tablero. Va con `border` y no
     con un `outline`, para que entre en la caja y no se coma un píxel de la
     fila al aparecer en `:hover`. */
  border: 1px solid rgba(212, 168, 67, 0.6);

  /* Cuarenta y cuatro píxeles es el mínimo que se toca sin apuntar. Con el
     relleno de arriba ya se llega, pero puesto explícito no depende de que
     nadie afine el `padding` más adelante. */
  min-height: 44px;
  border-radius: 11px;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 1.4px;
  text-transform: uppercase;
  cursor: pointer;
  color: #1a1206;
  overflow: hidden;
  transition: transform 0.2s, box-shadow 0.2s, filter 0.2s;
  background: linear-gradient(180deg, var(--oro-claro) 0%, var(--oro) 46%, var(--oro-hondo) 100%);
  box-shadow:
    0 6px 0 #6b530f,
    0 14px 26px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

button.accion:hover:not(:disabled) {
  transform: translateY(-3px);
  box-shadow:
    0 9px 0 #6b530f,
    0 20px 34px rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.7);
}

button.accion:active:not(:disabled) {
  transform: translateY(3px);
  box-shadow: 0 2px 0 #6b530f, 0 6px 14px rgba(0, 0, 0, 0.45);
}

button.accion:disabled {
  /* Apagado, no gris.

     `grayscale` dejaba los cuatro botones del mismo tono de plomo y no se
     distinguía cuál era cuál. Bajar la opacidad y quitarle algo de color
     conserva la identidad —el de cortar se sigue leyendo rojo— y avisa igual
     de que ahora no se puede.

     Y en vez de sobresalir, se hunde: la sombra pasa de estar debajo del
     botón a estar adentro. Un botón que se puede tocar tiene relieve; uno que
     no, es un hueco. Eso se entiende sin leer nada. */
  opacity: 0.55;
  filter: saturate(0.75);
  border-color: rgba(212, 168, 67, 0.2);
  box-shadow: inset 0 2px 7px rgba(0, 0, 0, 0.55);
  cursor: not-allowed;
}

/* El dibujo del botón.

   Hereda el color del texto —los SVG van con `currentColor`— así que no hay
   una regla de color por botón: el ícono del que corta es del color del que
   corta, y cuando el botón se apaga el dibujo se apaga con él. Ésa es toda
   la razón por la que son SVG en línea y no cuatro PNG. */
.icono-accion {
  width: 22px;
  height: 22px;
  display: block;
  flex-shrink: 0;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.35));
}

/* Barrido de brillo en los botones habilitados. */
button.accion:not(:disabled)::after {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 45%;
  height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.55), transparent);
  transform: skewX(-18deg);
  animation: barrido 4.5s ease-in-out infinite;
}

/* El brillo que barre sólo en los que se pueden tocar. El selector de arriba
   ya lo limita con `:not(:disabled)`; esto es el cinturón: un botón apagado
   que destella invita a tocarlo. */
button.accion:disabled::after {
  content: none;
}

@keyframes barrido {
  0%, 62% { left: -60%; }
  85%     { left: 130%; }
  100%    { left: 130%; }
}

/* Un color por jugada, y no cuatro botones dorados.

   ─────────────────────────────────────────────────────────────────────────
   POR QUÉ CADA UNO TIENE EL SUYO
   ─────────────────────────────────────────────────────────────────────────

   Porque estos cuatro se aprietan contra reloj. Leer cuatro etiquetas
   iguales y elegir una lleva más que reconocer un color, y en la ventana de
   reflejos eso es la diferencia entre jugar y no llegar.

   Azul para levantar (mirar, tomar), rojo para tirar (soltar, deshacerse),
   violeta para cortar (la decisión que termina la ronda) y verde para pasar
   (seguir, no hacer nada). Los cuatro con el mismo relieve y el mismo filo
   dorado: lo que cambia es el color, no la jerarquía.

   ─────────────────────────────────────────────────────────────────────────
   CORTAR ERA ROJO Y AHORA ES VIOLETA
   ─────────────────────────────────────────────────────────────────────────

   Era rojo por una razón buena —que se viera desde la otra punta de la
   mesa— y esa razón sigue valiendo. Lo que cambió es que ahora TIRAR
   también necesita un color, y el rojo le corresponde antes: tirar es la
   jugada de deshacerse de algo, y el rojo es el color de eso en cualquier
   interfaz.

   El violeta conserva lo que importaba: no se parece a ninguno de los otros
   tres, lleva halo propio para despegarse del negro de la caja, y sigue
   siendo el único que no se confunde de un vistazo.

   `.peligro` —el rojo apagado de "Abandonar", en el modal de salir— se
   queda como estaba, y ahora se distingue todavía mejor: es el único rojo
   sin brillo de la pantalla. */
button.accion.levanta {
  color: #fff;
  border-color: rgba(150, 205, 255, 0.7);
  background: linear-gradient(180deg, #6cb6f5 0%, #2a72c9 42%, #16457e 100%);
  box-shadow:
    0 6px 0 #0d2c53,
    0 14px 26px rgba(0, 0, 0, 0.45),
    0 0 26px rgba(42, 114, 201, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    inset 0 -3px 8px rgba(0, 0, 0, 0.28);
}

button.accion.tira {
  color: #fff;
  border-color: rgba(255, 180, 168, 0.7);
  background: linear-gradient(180deg, #f0705a 0%, #cc2b1c 42%, #86160c 100%);
  box-shadow:
    0 6px 0 #550c05,
    0 14px 26px rgba(0, 0, 0, 0.45),
    0 0 26px rgba(204, 43, 28, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.45),
    inset 0 -3px 8px rgba(0, 0, 0, 0.28);
}

button.accion.corte {
  color: #fff;
  border-color: rgba(216, 176, 255, 0.75);
  background: linear-gradient(180deg, #b98af0 0%, #7c3fd0 42%, #4a1e88 100%);
  box-shadow:
    0 6px 0 #2e1156,
    0 14px 26px rgba(0, 0, 0, 0.45),
    0 0 34px rgba(124, 63, 208, 0.6),
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    inset 0 -3px 8px rgba(0, 0, 0, 0.28);
}

button.accion.pasa {
  color: #fff;
  border-color: rgba(160, 240, 190, 0.7);
  background: linear-gradient(180deg, #5fd694 0%, #22a35f 42%, #106035 100%);
  box-shadow:
    0 6px 0 #093c21,
    0 14px 26px rgba(0, 0, 0, 0.45),
    0 0 26px rgba(34, 163, 95, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.45),
    inset 0 -3px 8px rgba(0, 0, 0, 0.28);
}

button.accion.corte:hover:not(:disabled) {
  box-shadow:
    0 9px 0 #2e1156,
    0 20px 34px rgba(0, 0, 0, 0.5),
    0 0 44px rgba(124, 63, 208, 0.75),
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    inset 0 -3px 8px rgba(0, 0, 0, 0.28);
}

/* El rojo se queda para lo que de verdad es grave: abandonar la partida. */
button.accion.peligro {
  color: #fff;
  border-color: rgba(255, 150, 130, 0.5);
  background: linear-gradient(180deg, #f0765e 0%, #d8402e 42%, #92210f 100%);
  box-shadow:
    0 6px 0 #5a140b,
    0 14px 26px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.45),
    inset 0 -3px 8px rgba(0, 0, 0, 0.3);
}

button.accion.peligro:hover:not(:disabled) {
  box-shadow:
    0 9px 0 #5a140b,
    0 20px 34px rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.5),
    inset 0 -3px 8px rgba(0, 0, 0, 0.3);
}

/* Acero oscuro, con un filo de oro.

   Tercer intento, y los dos anteriores enseñaron algo. La plata plana
   —`#d0d0d0` a `#a0a0a0`— parecía muerta: dos tonos sin una sola luz. El
   aluminio claro estaba vivo pero pasaba lo contrario: dos botones casi
   blancos al lado del oro y del rojo, gritando más fuerte que las jugadas que
   deciden la ronda. Tirar y pasar son de trámite y tienen que verse de
   trámite.

   Éste es oscuro y metálico: banda de luz arriba, cuerpo gris frío, pie
   hundido, y una línea de oro finita que lo emparenta con el filo de las
   cartas. Se lee como botón sin pelearse con nadie. */
button.accion.sobria {
  color: #f2f5f9;
  border-color: rgba(212, 168, 67, 0.35);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
  background: linear-gradient(180deg, #98a0aa 0%, #626a75 40%, #3b414a 100%);
  box-shadow:
    0 6px 0 #262a30,
    0 14px 26px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    inset 0 -3px 8px rgba(0, 0, 0, 0.32);
}

button.accion.sobria:hover:not(:disabled) {
  border-color: rgba(212, 168, 67, 0.6);
  background: linear-gradient(180deg, #aab2bd 0%, #727b87 40%, #464d57 100%);
  box-shadow:
    0 9px 0 #262a30,
    0 20px 34px rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.45),
    inset 0 -3px 8px rgba(0, 0, 0, 0.3);
}

/* =================================================== lateral */

.lateral {
  grid-area: lateral;
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  min-height: 0;
}

/* La misma esquina cortada que los asientos y por el mismo motivo: si el
   marcador tuviera esquinas redondas y los asientos biseladas, la pantalla
   se leería como dos interfaces pegadas.

   Acá el filo alcanza con un `border` porque el corte es más chico que el
   radio del bisel del asiento y la interrupción de la línea en la diagonal
   no se ve. Donde sí se veía —el marco del asiento, que es grande y está en
   el centro de la mirada— se resuelve con el fondo dorado. */
.tarjeta {
  --corte: 10px;
  background: var(--vidrio);
  border: 1px solid rgba(212, 168, 67, 0.28);
  padding: 12px 14px;
  backdrop-filter: blur(8px);
  clip-path: polygon(
    var(--corte) 0%, calc(100% - var(--corte)) 0%,
    100% var(--corte), 100% calc(100% - var(--corte)),
    calc(100% - var(--corte)) 100%, var(--corte) 100%,
    0% calc(100% - var(--corte)), 0% var(--corte)
  );
  filter: drop-shadow(0 12px 26px rgba(0, 0, 0, 0.45));
}

.tarjeta h2 {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 2.4px;
  color: var(--oro);
  margin-bottom: 13px;
  padding-bottom: 9px;
  border-bottom: 1px solid rgba(212, 168, 67, 0.18);
}

/* Cara, nombre y puntos. Nada de barras ni de historial: es un dato de
   consulta, no compite con el paño.

   La cara la agrega el mismo `retratoDe` que dibuja el asiento, así que la
   fila y el asiento no pueden discrepar: es una función, no dos listas.
   Sirve para lo que el nombre solo no alcanza —encontrar en la tabla al que
   uno está mirando en la mesa— sobre todo cuando dos nombres empiezan
   igual. */
.marcador-fila {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 0;
  font-size: 0.84rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.marcador-fila:last-child { border-bottom: none; }

.retrato-mini {
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  border-radius: 50%;
  object-fit: cover;
  background: #0b0f18;
  border: 1px solid var(--color-asiento, rgba(212, 168, 67, 0.45));
  box-shadow: 0 0 8px -3px var(--color-asiento, transparent);
}

.marcador-fila span {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* La tijera de quien cortó. `font-style: normal` porque va en un `<i>`, que
   es lo que corresponde a una marca sin voz propia, y en itálica un símbolo
   se ve torcido. */
.marcador-fila .tijera {
  flex-shrink: 0;
  font-style: normal;
  font-size: 0.8rem;
  color: var(--oro-claro);
}

.marcador-fila b {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  color: var(--oro-claro);
}

.marcador-fila.fuera {
  color: var(--texto-tenue);
}

/* Tachado sólo el nombre, no la fila entera.

   Con la línea encima de todo, el retrato quedaba cruzado por una raya y los
   puntos del eliminado —que siguen contando para el orden final— se leían
   como si fueran mentira. */
.marcador-fila.fuera span { text-decoration: line-through; }
.marcador-fila.fuera .retrato-mini { filter: grayscale(1); opacity: 0.5; }

/* Quién cortó, con todas las letras. */
.quien-corto {
  margin-top: 10px;
  padding-top: 9px;
  border-top: 1px solid rgba(212, 168, 67, 0.18);
  font-size: 0.72rem;
  letter-spacing: 0.3px;
  color: var(--texto-tenue);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.quien-corto[hidden] { display: none; }
.quien-corto i { font-style: normal; color: var(--oro-claro); }
.quien-corto b { color: var(--texto); font-weight: 700; }

/* Panel deslizante del registro. Cerrado no ocupa nada del paño; abierto se
   apoya encima con su propio scroll y no mueve una sola carta. */
.panel-registro {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 55;
  width: min(340px, 88vw);
  height: 100dvh;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  background: linear-gradient(200deg, #16202e 0%, #0a0f16 100%);
  border-left: 1px solid var(--vidrio-borde);
  box-shadow: -24px 0 60px rgba(0, 0, 0, 0.7);
}

/* Sin animación de entrada a propósito: si el navegador congela las
   animaciones —pestaña en segundo plano, throttling— un panel que llega
   deslizándose se queda fuera de la pantalla y el botón 📜 parece roto. La
   posición de reposo no puede depender de que una animación termine. */
.panel-registro[hidden] { display: none; }

.panel-cabecera {
  display: flex;
  align-items: center;
  gap: 10px;
}

.panel-cabecera h2 {
  flex: 1;
  font-size: 0.7rem;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--oro-claro);
}

.panel-registro .registro {
  flex: 1;
  max-height: none;
}

.registro {
  max-height: 250px;
  overflow-y: auto;
  font-size: 0.78rem;
  line-height: 1.6;
  color: var(--texto-tenue);
  scrollbar-width: thin;
  scrollbar-color: rgba(212, 168, 67, 0.3) transparent;
}

.registro::-webkit-scrollbar { width: 6px; }
.registro::-webkit-scrollbar-thumb {
  background: rgba(212, 168, 67, 0.3);
  border-radius: 999px;
}

.registro div {
  padding: 4px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}

.registro div:last-child { border-bottom: none; }

.registro .destacado {
  color: var(--oro-claro);
  font-weight: 600;
}

/* ===================================================== modal */

.velo {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 22px;
  background: rgba(3, 5, 9, 0.86);
  backdrop-filter: blur(8px);
}

.velo.abierto { display: flex; animation: entrarVelo 0.28s ease-out; }

@keyframes entrarVelo {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.modal {
  width: 100%;
  max-width: 660px;
  max-height: 88vh;
  overflow-y: auto;
  padding: 30px;
  text-align: center;
  border-radius: 22px;
  background:
    radial-gradient(ellipse at 50% 0%, rgba(212, 168, 67, 0.14), transparent 62%),
    linear-gradient(170deg, #1a2434 0%, #0b1119 100%);
  border: 1px solid rgba(212, 168, 67, 0.42);
  box-shadow: 0 34px 90px rgba(0, 0, 0, 0.75), inset 0 1px 0 rgba(255, 255, 255, 0.07);
  animation: entrarModal 0.34s cubic-bezier(0.2, 1.1, 0.4, 1);
}

@keyframes entrarModal {
  from { transform: translateY(26px) scale(0.95); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

.modal h2 {
  font-size: 1.45rem;
  letter-spacing: 1px;
  margin-bottom: 8px;
  background: linear-gradient(180deg, var(--oro-claro), var(--oro));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.modal p {
  color: var(--texto-tenue);
  font-size: 0.92rem;
  margin-bottom: 20px;
}

.modal .objetivos {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  justify-content: center;
  margin-bottom: 22px;
}

.grupo-objetivo {
  padding: 12px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.07);
}

.grupo-objetivo .titulo {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 1.4px;
  color: var(--oro);
  margin-bottom: 9px;
}

.grupo-objetivo .mano {
  --carta-ancho: 54px;
  --carta-alto: 81px;
}

/* ====================================== efectos de los poderes */

.anuncio-poder {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 18px 30px;
  border-radius: 18px;
  background: rgba(6, 9, 16, 0.93);
  border: 1px solid var(--tinte-poder, var(--oro));
  box-shadow: 0 0 50px var(--tinte-poder, var(--oro)), 0 24px 60px rgba(0, 0, 0, 0.7);
  animation: entrarAnuncio 0.4s cubic-bezier(0.2, 1.3, 0.4, 1);
  pointer-events: none;
}

.anuncio-poder.saliendo {
  animation: salirAnuncio 0.3s ease-in forwards;
}

.anuncio-poder .icono {
  font-size: 2.6rem;
  line-height: 1;
  filter: drop-shadow(0 0 14px var(--tinte-poder, var(--oro)));
  animation: girarIcono 1.4s ease-in-out;
}

.anuncio-poder .detalle {
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-align: left;
}

.anuncio-poder b {
  font-size: 1.15rem;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--tinte-poder, var(--oro));
}

.anuncio-poder i {
  font-style: normal;
  font-size: 0.9rem;
  color: var(--texto);
}

.anuncio-poder em {
  font-style: normal;
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 1.2px;
  color: var(--texto-tenue);
}

.anuncio-poder.poder-7 { --tinte-poder: #d4a843; }
.anuncio-poder.poder-8 { --tinte-poder: #46c8ff; }
.anuncio-poder.poder-9 { --tinte-poder: #b87333; }
.anuncio-poder.poder-10 { --tinte-poder: #c0392b; }

@keyframes entrarAnuncio {
  from { transform: translate(-50%, -50%) scale(0.7); opacity: 0; }
  to   { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}

@keyframes salirAnuncio {
  to { transform: translate(-50%, -90%) scale(0.9); opacity: 0; }
}

@keyframes girarIcono {
  0%   { transform: rotate(0) scale(1); }
  35%  { transform: rotate(14deg) scale(1.25); }
  70%  { transform: rotate(-10deg) scale(1.1); }
  100% { transform: rotate(0) scale(1); }
}

/* --- efectos sobre las cartas afectadas --- */

.carta.efecto-mirar .cara,
.carta.efecto-mirar .dorso {
  animation: escanear 1s ease-in-out;
}

@keyframes escanear {
  0%   { box-shadow: var(--sombra-carta); }
  35%  { box-shadow: 0 0 0 3px #d4a843, 0 0 34px 6px rgba(212, 168, 67, 0.75); }
  100% { box-shadow: var(--sombra-carta); }
}

.carta.efecto-ciego {
  animation: giroCiego 1.1s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 8;
}

@keyframes giroCiego {
  0%   { transform: rotate(var(--giro)) translateY(var(--desvio)); filter: none; }
  40%  { transform: rotate(calc(var(--giro) + 180deg)) translateY(calc(var(--desvio) - 26px)) scale(1.1);
         filter: brightness(0.45) saturate(0.3); }
  100% { transform: rotate(calc(var(--giro) + 360deg)) translateY(var(--desvio)); filter: none; }
}

.carta.efecto-vista {
  animation: giroVista 1.1s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 8;
}

@keyframes giroVista {
  0%   { transform: rotate(var(--giro)) translateY(var(--desvio)); }
  45%  { transform: rotate(var(--giro)) translateY(calc(var(--desvio) - 32px)) scale(1.14); }
  100% { transform: rotate(var(--giro)) translateY(var(--desvio)); }
}

.carta.efecto-vista .cara,
.carta.efecto-vista .dorso {
  animation: halooVista 1.1s ease-in-out;
}

@keyframes halooVista {
  0%   { box-shadow: var(--sombra-carta); }
  45%  { box-shadow: 0 0 0 3px #c0392b, 0 0 40px 8px rgba(255, 95, 141, 0.7); }
  100% { box-shadow: var(--sombra-carta); }
}

/* --- paso de decisión del poder --- */

.carta-poder {
  display: grid;
  place-items: center;
  margin-bottom: 16px;
}

.carta-poder img {
  width: 108px;
  height: 162px;
  border-radius: 8px;
  object-fit: cover;
  box-shadow: 0 0 0 2px var(--ambar), 0 18px 40px rgba(0, 0, 0, 0.65),
    0 0 40px rgba(255, 176, 32, 0.35);
  animation: entrarCartaPoder 0.45s cubic-bezier(0.2, 1.2, 0.4, 1);
}

@keyframes entrarCartaPoder {
  from { transform: translateY(18px) rotateZ(-7deg) scale(0.85); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

.modal .nombre-poder {
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--ambar);
  margin-bottom: 10px;
}

.modal .aviso-poder {
  font-size: 0.82rem;
  font-style: italic;
  color: var(--texto-tenue);
  margin-bottom: 22px;
}

.botonera-poder {
  display: flex;
  gap: 14px;
  justify-content: center;
  flex-wrap: wrap;
}

.botonera-poder .accion { min-width: 200px; }

/* ------------------------------------------- la insignia recién ganada

   Aparece entre el marcador y la revancha, y sólo si se ganó algo. Una
   partida normal no gana ninguna, así que el hueco nace `hidden` y no
   ocupa lugar: un espacio en blanco permanente debajo de la tabla se lee
   como que algo no cargó. */
.logros-ganados[hidden] {
  display: none;
}

.logros-ganados {
  display: block;
  margin-top: 14px;
}

.logro-nuevo {
  margin: 6px 0;
  padding: 10px 14px;
  border-radius: var(--corte, 10px);
  border: 1px solid rgba(212, 168, 67, 0.45);
  background: rgba(212, 168, 67, 0.12);
  font-weight: 600;
}

/* Las Leyendas, en la voz de siempre del saldo, para que se lean como
   dinero y no como parte del nombre de la insignia. */
.logro-paga {
  margin-left: 6px;
  color: var(--oro, #d4a843);
  white-space: nowrap;
}

/* ------------------------------------------------------- la revancha

   El panel que aparece debajo del resultado cuando la partida termina.
   Va separado de la tabla por una línea: lo de arriba es lo que pasó y lo
   de abajo una decisión, y sin la línea el botón se lee como parte del
   marcador. */
.revancha {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid rgba(212, 168, 67, 0.22);
}

/* El selector de apuesta.

   Los `option` se pintan aparte y con colores explícitos: en Windows los
   dibuja el sistema, y sobre un desplegable claro un texto claro queda
   ilegible. Es el mismo cuidado que ya tiene `lobby.css` con sus selects. */
.apuesta-revancha {
  min-width: 170px;
  padding: 12px 14px;
  border-radius: var(--corte, 10px);
  border: 1px solid rgba(212, 168, 67, 0.4);
  background: rgba(0, 0, 0, 0.35);
  color: var(--oro-claro, #fcf0c4);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.apuesta-revancha option {
  background: #1a2233;
  color: #fcf0c4;
}

.apuesta-revancha:focus-visible {
  outline: 2px solid var(--oro, #d4a843);
  outline-offset: 2px;
}

/* Tercera salida del reglamento, deliberadamente discreta. */
.enlace-modal {
  display: block;
  margin: 16px auto 0;
  padding: 6px 10px;
  border: none;
  background: none;
  color: var(--texto-tenue);
  font-size: 0.8rem;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  transition: color 0.2s;
}

.enlace-modal:hover { color: var(--oro-claro); }

/* El botón de tirar se vuelve el acceso al poder y llama la atención. */
button.accion.con-poder {
  color: #2a1b02;
  background: linear-gradient(180deg, #ffd98a 0%, var(--ambar) 46%, #b8730a 100%);
  box-shadow: 0 6px 0 #7c4e06, 0 14px 26px rgba(0, 0, 0, 0.45),
    inset 0 1px 0 rgba(255, 255, 255, 0.55);
  animation: pulsoPoder 1.5s ease-in-out infinite;
}

@keyframes pulsoPoder {
  0%, 100% { filter: brightness(1); box-shadow: 0 6px 0 #7c4e06, 0 14px 26px rgba(0, 0, 0, 0.45), 0 0 0 0 rgba(255, 176, 32, 0.55); }
  50%      { filter: brightness(1.12); box-shadow: 0 6px 0 #7c4e06, 0 14px 26px rgba(0, 0, 0, 0.45), 0 0 26px 6px rgba(255, 176, 32, 0.4); }
}

/* La carta levantada con poder invita a tocarla. */
.levantada-caja.con-poder .carta { cursor: pointer; }

/* El marcador del final.

   `.tabla-final` es la de entrenamiento y `.tabla-resultado` la de una
   partida por Leyendas. Comparten estas reglas porque son la misma tabla
   con distinto origen del dato: la primera la arma el motor del navegador y
   la segunda llega en la vista que publica el servidor.

   La de red no tenía NINGUNA regla —ni relleno en las celdas— así que sus
   encabezados salían pegados: «JugadorEn manoTotal». Se veía sólo al
   terminar una partida apostada, que es la pantalla que menos conviene
   tener descuidada. */
.tabla-final,
.tabla-resultado {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 22px;
  font-size: 0.9rem;
}

.tabla-final th,
.tabla-final td,
.tabla-resultado th,
.tabla-resultado td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}

.tabla-final th,
.tabla-resultado th {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 1.4px;
  color: var(--oro);
}

/* La fila de uno mismo, destacada igual que la del que cortó: en una mesa
   de cuatro, encontrarse en el marcador no puede costar una lectura. */
.tabla-resultado tr.propio td {
  color: var(--oro-claro);
  font-weight: 700;
  background: rgba(212, 168, 67, 0.07);
}

.tabla-final td.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.tabla-final tr.cortador td {
  color: var(--oro-claro);
  font-weight: 700;
  background: rgba(212, 168, 67, 0.07);
}

.tabla-final tr.fuera td { opacity: 0.45; }

/* El ajuste del corte: verde si restó, rojo si castigó. */
.tabla-final td.bueno { color: #8fd4b4; font-weight: 700; }
.tabla-final td.malo { color: #d9604f; font-weight: 700; }

.corona {
  font-size: 3.2rem;
  line-height: 1;
  margin-bottom: 10px;
  animation: flotar 2.6s ease-in-out infinite;
}

@keyframes flotar {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-9px); }
}

/* ================================================== confeti */

#confeti {
  position: fixed;
  inset: 0;
  /* El canvas es un elemento reemplazado: inset:0 no lo estira, hay que medirlo. */
  width: 100%;
  height: 100%;
  z-index: 70;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
}

#confeti.activo { opacity: 1; }

/* ============================================== adaptativo */

/* Sin ancho para la columna, el marcador se retira. No se pierde el dato: los
   puntos de la ronda ya están en la ficha de cada asiento. */
@media (max-width: 1080px) {
  .escena {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "cabecera"
      "mesa"
      "pista"
      "acciones";
  }
  .lateral { display: none; }
}

@media (max-width: 950px) {
  /* El aire de los bordes y el que separa las cuatro bandas. En un teléfono
     son 20 px de márgenes y 30 de huecos que no se ven pero se cobran: cada
     píxel que se le quita al aire se lo lleva la carta. */
  body { padding: 6px; }
  .escena { gap: 6px; }

  .cabecera { padding: 5px 10px; gap: 8px; }
  .cabecera h1 { font-size: 0.92rem; letter-spacing: 1px; }
  .cabecera .lema { display: none; }
  .cabecera .marca { width: 30px; height: 30px; }
  .btn-icono { width: 32px; height: 32px; }
  .chip-ronda { padding: 4px 10px; font-size: 0.7rem; }

  /* El óvalo deja de serlo: los tres rivales se reparten una tira arriba, las
     pilas quedan al medio y tu mano abajo. Todo sobre la misma superficie,
     que sigue siendo la única zona elástica. */
  .mesa {
    border-radius: 20px;
    border-width: 8px;
    padding: 8px;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-areas:
      "izq    arriba der"
      "centro centro centro"
      "propio propio propio";
    align-content: space-between;
    justify-items: center;
    gap: 8px;
  }

  .mesa::before { background-size: 55% auto; }

  .asiento {
    position: static;
    transform: none;
    width: 100%;
    min-width: 0;
  }

  .asiento-izq    { grid-area: izq; }
  .asiento-arriba { grid-area: arriba; }
  .asiento-der    { grid-area: der; }
  .centro         { grid-area: centro; }
  .asiento-abajo  { grid-area: propio; }

  /* Las cartas de los rivales están boca abajo casi siempre: de ellas hace
     falta cantidad y posición, no legibilidad. Las tuyas, en cambio, se tocan
     con el reloj corriendo, así que crecen respecto del diseño anterior. */
  :root {
    --carta-alto: clamp(44px, 7.4dvh, 60px);
    --carta-ancho: calc(var(--carta-alto) * 0.667);
  }

  .jugador { padding: 5px 6px 6px; }
  .jugador .nombre { font-size: 0.72rem; }
  .jugador .puntos { font-size: 0.62rem; }
  .jugador .retrato { --retrato: 38px; --aro: 2px; }
  .jugador.propio .retrato { --retrato: 44px; }
  .jugador .cuenta-asiento { top: -6px; font-size: 0.54rem; padding: 0 5px; }
  .mano { gap: 3px; padding-top: 4px; }

  /* El ancho no lo fija la mano llena sino la de cinco o seis: con pocas
     cartas el abanico casi no las monta, así que suman ancho completo más el
     hueco entre ellas. Con muchas, el solape crece más rápido que la cuenta. */
  .jugador.propio {
    --carta-alto: min(clamp(74px, 14.5dvh, 128px), 29vw);
    --carta-ancho: calc(var(--carta-alto) * 0.667);
    padding: 6px 8px 8px;
  }

  .jugador.propio .nombre { font-size: 0.86rem; }
  .jugador.propio .mano { gap: 5px; }

  /* Los castigos hacen crecer la mano. El abanico las monta unas sobre otras,
     pero llega un punto en que ni así entran en el ancho de un teléfono. A
     partir de ahí la mano se achica en escalones, que es preferible a que
     queden cartas fuera de la pantalla. */
  .jugador.propio .mano:has(> :nth-child(10)) {
    --carta-alto: clamp(64px, 11dvh, 90px);
    --carta-ancho: calc(var(--carta-alto) * 0.667);
  }

  .jugador.propio .mano:has(> :nth-child(14)) {
    --carta-alto: clamp(54px, 9.2dvh, 75px);
    --carta-ancho: calc(var(--carta-alto) * 0.667);
  }

  /* El centro tampoco tiene tamaño propio acá: las tres pilas miden lo mismo
     que una carta de la mesa, igual que en escritorio. Es la misma baraja, y
     con los rótulos fuera de la vista sobra el alto para que se vean iguales. */
  .centro { gap: 10px; justify-content: center; }

  /* En el teléfono la caja sí ocupa el ancho: apretar cuatro botones en el
     medio de la pantalla deja los dedos peleándose por 60 px cada uno. */
  .acciones { width: auto; flex-wrap: wrap; padding: 8px 10px; gap: 6px; }
  button.accion { flex: 1 1 auto; padding: 11px 12px; font-size: 0.7rem; letter-spacing: 1px; }

  .modal { padding: 20px; }
  .modal h2 { font-size: 1.15rem; }
}

/* En un teléfono los tres rivales no entran uno al lado del otro sin dejar
   las cartas por debajo del tamaño de un dedo. Se apilan, pero en filas
   compactas: ficha a la izquierda, cartas a la derecha. */
@media (max-width: 560px) {
  .mesa {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "izq"
      "arriba"
      "der"
      "centro"
      "propio";
    gap: 5px;
  }

  .asiento:not(.asiento-abajo) .jugador {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    text-align: left;
  }

  /* Cuarenta por ciento, no cuarenta y seis.

     La cuenta a 360 de ancho: adentro del paño quedan 316 píxeles. La cara y
     el nombre se llevan 126 y el hueco 8, así que a las cuatro cartas les
     quedan 182 — y con los huecos de 4, cuarenta y dos por carta, que es
     justo lo que pide `--carta-alto` a ese ancho. Con 46% la cuenta daba
     diecinueve píxeles de menos y la mano se salía. */
  .asiento:not(.asiento-abajo) .cabecera-jugador {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 40%;
    justify-content: flex-start;
    margin-bottom: 0;
  }

  /* La dificultad de la IA no se necesita durante la jugada, y su etiqueta
     empujaba las cartas por encima del nombre. */
  .asiento:not(.asiento-abajo) .insignia { display: none; }

  /* Del rival se muestra el TOTAL y no la ronda.

     Los dos no entran: en 126 píxeles, «Ronda 0 Total 0» se cortaba y lo que
     quedaba afuera era justo el número del total. Y de los dos, el que
     importa mirar de un rival es el acumulado —cuánto le falta para pasarse
     del límite y quedar eliminado—; lo que anotó en la ronda anterior se ve
     entero en el marcador del final de ronda.

     En el asiento propio siguen los dos: ahí hay ancho de sobra. */
  .asiento:not(.asiento-abajo) .puntos .parcial { display: none; }

  /* En el teléfono la mano de un rival BAJA en vez de encoger.

     En escritorio, cuando los castigos suman cartas, la mano encoge: el
     ancho es lo que sobra y el alto lo que falta. En un teléfono es al
     revés, y encogiendo se llegaba a cartas de veintidós píxeles, donde ya
     no se distingue el dorso rojo del azul —que es lo único que distingue de
     quién es cada mano—.

     Por eso acá se envuelve en dos filas y se ignora la escala: siete cartas
     son cuatro arriba y tres abajo, todas del mismo tamaño legible. El alto
     que cuesta sólo se paga cuando alguien recibió un castigo. */
  .asiento:not(.asiento-abajo) .mano {
    flex: 1 1 auto;
    min-width: 0;
    padding-top: 0;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 4px;
    --escala: 1;
  }

  /* Un piso, para que encoger no llegue nunca a hacerlas desaparecer. Si
     algo no entra, que se note: una carta de diez píxeles no se ve como un
     problema, se ve como que el rival no tiene cartas. */
  .mano > .carta,
  .mano > .hueco {
    min-width: 26px;
  }

  /* La carta del rival, medida contra el renglón en el que vive.

     Con 17.5vw daba 42 píxeles de ancho, y cuatro más sus huecos pedían 192
     donde hay 182: envolvía a dos filas con la mano LLENA, que es el caso
     normal. Tres cartas arriba y una abajo, en los cuatro asientos, y la
     mesa dejaba de entrar en la pantalla.

     Con 15.5vw entran las cuatro con aire de sobra, y las dos filas quedan
     para lo que se pensaron: la mano de alguien que recibió un castigo. */
  :root {
    --carta-alto: min(clamp(40px, 8.6dvh, 84px), 15.5vw);
    --carta-ancho: calc(var(--carta-alto) * 0.667);
  }
}

/* Pantallas BAJAS: un teléfono chico acostado, un iPhone SE, media ventana.
 *
 * El paño no entraba y se derramaba hacia abajo: la mano propia terminaba
 * dibujada encima del cartel y de la botonera. Dos cosas rotas de una vez —el
 * cartel es el único lugar donde la mesa dice qué hacer, y una carta encima de
 * un botón se come el toque que iba al botón—.
 *
 * Se recorta donde no duele: cartas más chicas, menos aire entre asientos y
 * una baranda más fina. Los rótulos de las pilas y los contadores se quedan:
 * cuántas cartas van quedando en el mazo decide cuándo cortar.
 *
 * Va por ALTO y no por ancho. El problema nunca fue que la pantalla sea
 * angosta —a 390x844 sobra sitio— sino que sea baja. */
/* El teléfono de pie necesita el escalón ANTES que los demás, y por eso éste
   sí mira el ancho: por debajo de 560 px los asientos se apilan en cinco filas
   en vez de repartirse alrededor del óvalo, y cinco filas piden más alto que
   tres. A 375x667 sobra sitio con el óvalo y falta con la pila. */
@media (max-width: 560px) and (max-height: 730px) {
  :root { --carta-alto: clamp(34px, 8.3dvh, 62px); }
  .jugador.propio { --carta-alto: clamp(52px, 14.1dvh, 105px); padding: 4px 8px 5px; }
  .jugador { padding: 3px 7px 4px; }
  .mesa { gap: 2px; padding: 1px 0 10px; border-width: 8px; }
}

/* Y el más chico de pie, que es el único que no llega con lo de arriba. */
@media (max-width: 560px) and (max-height: 600px) {
  :root { --carta-alto: clamp(26px, 6.5dvh, 44px); }
  .jugador.propio { --carta-alto: clamp(42px, 11dvh, 75px); padding: 2px 6px 3px; }
  .jugador { padding: 2px 6px 3px; }
  .mesa { gap: 1px; padding: 0 0 9px; border-width: 6px; }
}

/* ─────────────────────────────────────────────────────────────────────
   De acá para abajo, la mesa del ÓVALO: 561 px de ancho para arriba.
   Van separadas de las de la pila a propósito. Las dos reparten el mismo
   alto entre cosas distintas —cinco filas contra tres bandas— y cuando
   compartían escalón, subirle el tamaño a una se lo bajaba a la otra.
   ───────────────────────────────────────────────────────────────────── */

/* Portátiles de 768 y 800 de alto.

   No son pantallas raras: son las dos alturas más comunes de un portátil. Con
   las medidas de base, a 1366x768 el paño cerraba con dos píxeles de holgura
   —medidos, no estimados— y cualquier cosa que creciera un poco lo desbordaba.

   El alto que hace falta se lo saca al RETRATO, no a las cartas. Un retrato
   de 46 píxeles en vez de 62 sigue siendo una cara reconocible; una carta
   más chica es una carta que cuesta más recordar, y las cartas son el juego.
   Entre las dos caras y los dos retratos son unos treinta y seis píxeles,
   que es justo lo que falta a 1280x720.

   Va ANTES del escalón de 660 para que aquél lo pise donde de verdad hace
   falta apretar. */
@media (min-width: 561px) and (max-height: 820px) {
  :root { --carta-alto: clamp(62px, 12.6dvh, 122px); }
  .jugador.propio { --carta-alto: clamp(94px, 19.2dvh, 190px); }
  .jugador .retrato { --retrato: 46px; }
  .jugador.propio .retrato { --retrato: 54px; }
  .jugador .cabecera-jugador { gap: 9px; margin-bottom: 5px; }
}

/* Pantallas bajas: un portátil chico, o una ventana que no está maximizada.

   ─────────────────────────────────────────────────────────────────────────
   ESTOS NÚMEROS SUBIERON, Y NO PORQUE SÍ
   ─────────────────────────────────────────────────────────────────────────

   Estaban calibrados para el diseño anterior, el que le ponía a cada jugador
   una caja con filo, relleno y su propio relleno interior. Sacada la caja,
   cada asiento ocupa menos alto — y como los `clamp` no se tocaron, ese alto
   quedó libre sin que nadie lo usara.

   Medido a 1351x651, que es una ventana real: el paño mide 434 píxeles y las
   tres filas usaban 344. Noventa píxeles de aire, el 21% de la mesa, con las
   cartas del rival en 29 de ancho. En una pantalla baja el alto es lo único
   que falta; dejarlo sin gastar era el peor de los dos errores posibles.

   El reparto sigue el mismo criterio que en pantalla grande: la mano propia
   se lleva la mayor parte —son las cartas que se tocan contra reloj— y las
   pilas del centro, que son de consulta, ceden primero. */
@media (min-width: 561px) and (max-height: 660px) {
  :root { --carta-alto: clamp(42px, 9.4dvh, 76px); }

  .jugador.propio {
    --carta-alto: clamp(66px, 15.2dvh, 128px);
    padding: 4px 8px 5px;
  }

  .jugador { padding: 3px 7px 4px; }
  .mesa { gap: 2px; padding: 1px 0 10px; border-width: 8px; }
}

/* Un escalón más para lo más bajo que existe de pie: un iPhone SE son 568 px,
   y ahí ni con lo de arriba entra.

   Sube por lo mismo que el de arriba —la caja del jugador dejó alto libre—
   pero menos: acá el margen es de verdad estrecho y el paño tiene que seguir
   cerrando abajo. */
@media (min-width: 561px) and (max-height: 580px) {
  :root { --carta-alto: clamp(36px, 8dvh, 62px); }
  .jugador.propio { --carta-alto: clamp(58px, 13.2dvh, 108px); padding: 2px 6px 3px; }
  .jugador { padding: 2px 6px 3px; }
  .mesa { gap: 1px; padding: 0 0 9px; border-width: 6px; }
}

/* Y el caso que estaba del todo roto: el teléfono ACOSTADO.
 *
 * Ahí no sobraban 50 px, faltaban 200: la mano se dibujaba entera por debajo
 * del paño, encima del cartel y de los cuatro botones, que quedaban tapados y
 * sin recibir un solo toque. La mesa era injugable y no lo decía.
 *
 * Es cuatro personas y trece cartas en 360 px de alto, así que todo tiene que
 * ceder a la vez: cartas, nombres, la baranda y los rótulos de las pilas —los
 * contadores se quedan, que deciden cuándo cortar—. Entra, pero apretado; de
 * pie se juega mejor. */
@media (min-width: 561px) and (max-height: 500px) {
  :root { --carta-alto: clamp(20px, 4.8dvh, 34px); }
  .jugador.propio { --carta-alto: clamp(30px, 8.4dvh, 52px); padding: 1px 6px 2px; }

  .jugador { padding: 1px 5px 2px; }
  .jugador .nombre { font-size: 0.68rem; }
  .jugador .puntos { font-size: 0.56rem; }
  .jugador .retrato { --retrato: 30px; --aro: 2px; }
  .jugador.propio .retrato { --retrato: 34px; }
  .jugador .cuenta-asiento { top: -5px; font-size: 0.5rem; padding: 0 4px; }
  .mano { gap: 2px; padding-top: 2px; }
  .mesa { gap: 1px; border-width: 4px; padding-bottom: 8px; }
  .centro { gap: 8px; }

  /* El aire entre las cuatro bandas de la pantalla. Son 30 px repartidos en
     tres huecos, y acostado son 30 px que el paño no tiene. */
  .escena { gap: 4px; }
  body { padding: 5px; }

  .cabecera { padding: 3px 8px; }
  .cabecera .marca { width: 26px; height: 26px; }
  .btn-icono { width: 30px; height: 30px; }
  .anuncio { padding: 3px 12px; }
  .anuncio .pista { font-size: 0.74rem; }
  .acciones { padding: 5px 8px; gap: 6px; }
  button.accion { padding: 8px 12px; }
}

/* Cuando los cuatro botones no entran en una fila, dos y dos.
 *
 * Con `flex-grow` y a lo que salga, entraban tres arriba y "Pasar" quedaba
 * solo abajo estirado de lado a lado: un botón del ancho de la pantalla, tres
 * veces más grande que los otros tres, para la jugada más inocua de las
 * cuatro. El tamaño de un botón es una manera de decir cuánto importa, y ése
 * decía lo que no era.
 *
 * El corte va en 385 px, que es donde dejan de entrar los cuatro. Por encima
 * se quedan en una sola fila, y no es cosmética: en un teléfono alto sobran
 * 25 px hasta el borde, y una segunda fila de botones los desborda. */
/* Los cuatro en una fila, todo lo que se pueda.
 *
 * Dos filas de botones cuestan 112 px contra 62, y esos 50 px salen del paño:
 * a 375 px de ancho las cartas quedaban en 43 px por tener la botonera
 * partida. Apretando el relleno y el espaciado de las letras entran los cuatro
 * en una fila hasta bien abajo, y el alto táctil de 44 px no se toca.
 *
 * Por debajo de 355 px ni así entran, y ahí sí van dos y dos. */
/* ============================================================
   CUANDO NO SOBRA ALTO: TODO VUELVE A UNA LÍNEA
   ============================================================

   Dos adornos de este rediseño cuestan alto, y en una pantalla baja el alto
   es lo único que no hay:

     - los puntos en dos renglones (Ronda arriba, Total abajo);
     - el dibujo del botón encima de su palabra.

   Sumaban unos cincuenta píxeles en cada punta. A 320x568 eso empujaba la
   mano 102 píxeles por debajo del paño, encima del cartel y de los botones;
   con el teléfono acostado, 41. Lo encontraron dos pruebas de
   `entrenamiento-ux.spec.js` que ya estaban escritas justamente para esto.

   Acá los dos vuelven a una sola línea. No se pierde información —siguen
   los dos números y sigue el dibujo con su palabra— se pierde el respiro,
   que es lo que sobra en una pantalla grande y no existe en una chica.

   La condición es «angosto O bajo», con coma. Los dos casos son el mismo
   problema por caminos distintos: el teléfono de pie es angosto, y el
   teléfono acostado —740 de ancho, 360 de alto— no es angosto en absoluto
   pero tiene todavía menos alto. Una regla atada sólo al ancho deja el
   segundo sin arreglar, que es exactamente el error que ya se cometió una
   vez en este archivo y está contado en la prueba. */
@media (max-width: 560px), (max-height: 620px) {
  .jugador .puntos {
    flex-direction: row;
    gap: 9px;
  }

  button.accion {
    flex-direction: row;
    gap: 7px;
    padding: 9px 13px;
  }

  .icono-accion {
    width: 17px;
    height: 17px;
  }
}

/* Más abajo todavía: el dibujo se queda solo con lo que cabe. */
@media (max-height: 480px) {
  .jugador .retrato { --retrato: 30px; --aro: 2px; }
  .jugador.propio .retrato { --retrato: 34px; }
  .jugador .puntos { gap: 7px; font-size: 0.58rem; }
  .jugador .puntos b { font-size: 0.72rem; }
  button.accion { padding: 7px 11px; }
  .icono-accion { width: 15px; height: 15px; }
}

@media (max-width: 420px) {
  .acciones { padding: 8px 6px; gap: 5px; }
  button.accion { padding: 11px 7px; font-size: 0.66rem; letter-spacing: 0.4px; }
}

@media (max-width: 355px) {
  button.accion { flex: 1 1 calc(50% - 3px); font-size: 0.7rem; letter-spacing: 1px; }
}

/* Un teléfono chico de verdad: 320 px.
 *
 * A ese ancho la cabecera no entraba —logo, título, la ficha de la ronda y
 * tres botones redondos suman 328 px de contenido en 284 de hueco— y la mesa
 * entera scrolleaba de costado. En un juego que se toca, un desplazamiento
 * lateral parásito es peor que feo: se arrastra el dedo para descartar y lo
 * que se mueve es la página.
 *
 * Se achica el rótulo y la ficha de la ronda; los botones redondos NO se
 * tocan, que son los que hay que poder acertar con el pulgar. */
@media (max-width: 400px) {
  .cabecera { gap: 8px; padding: 5px 8px; }
  .cabecera h1 { font-size: 0.74rem; letter-spacing: 0.6px; }
  .cabecera .derecha { gap: 6px; }
  .chip-ronda { padding: 3px 8px; font-size: 0.62rem; letter-spacing: 0.6px; }
  .chip-ronda strong { font-size: 0.85rem; }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.05ms !important;
  }
}


/* Pantalla que se muestra al entrar a una partida de sala mientras la mesa
   en red no exista. Reemplaza el tablero entero: no se simula una partida. */
.mesa-pendiente {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 16px;
  padding: 40px 22px;
  max-width: 620px;
  margin: 0 auto;
}

.mesa-pendiente .logo-img.grande {
  width: 96px;
  height: 96px;
  border-radius: 22px;
  border: 2px solid var(--oro);
  box-shadow: 0 0 34px -8px var(--oro);
}

.mesa-pendiente h1 {
  font-family: "Playfair Display", "Playfair respaldo", Georgia, serif;
  font-size: 1.6rem;
  color: var(--oro);
}

.mesa-pendiente p { color: var(--texto); line-height: 1.7; }
.mesa-pendiente p b { color: var(--oro-claro); }

.mesa-pendiente .detalle {
  color: var(--plata);
  font-size: 0.92rem;
  border-top: 1px solid var(--borde);
  padding-top: 16px;
  margin-top: 6px;
}

.botonera-pendiente {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 10px;
}

.botonera-pendiente a { text-decoration: none; }


/* Lugares libres cuando la mesa es de dos o tres jugadores.

   El filo va gris y no dorado. El `border-style: dashed` de antes ya no
   podía funcionar: el marco del asiento dejó de ser un `border` y pasó a ser
   una capa de fondo recortada, y un estilo de borde sobre un borde de ancho
   cero no dibuja nada. Un filo apagado al 35% dice lo mismo que decía la
   línea de puntos —acá no hay nadie— sin fingir un borde que no existe. */
.jugador.vacante { opacity: 0.35; }

.jugador.vacante::before {
  background: rgba(255, 255, 255, 0.16);
  filter: none;
}

.jugador.vacante .nombre { color: var(--texto-tenue); }
.jugador.vacante .nombre::before { display: none; }

/* Y el hueco del retrato es redondo, como el retrato que reemplaza. Era
   rectangular porque en su momento reemplazaba a la miniatura de un dorso. */
.ficha-vacante {
  width: 42px;
  height: 42px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 2px dashed rgba(255, 255, 255, 0.2);
}


/* Carta que se tocó cuando no correspondía: se sacude y no se destapa. */
.carta.rechazada {
  animation: cartaRechazada 0.45s ease-in-out;
}

.carta.rechazada .dorso {
  box-shadow: var(--sombra-carta), inset 0 0 0 2px #c0392b;
}

@keyframes cartaRechazada {
  0%, 100% { transform: rotate(var(--giro)) translateY(var(--desvio)); }
  25% { transform: rotate(var(--giro)) translateY(var(--desvio)) translateX(-6px); }
  75% { transform: rotate(var(--giro)) translateY(var(--desvio)) translateX(6px); }
}

/* ----------------------------------------------------- aviso de abandono */

.detalle-abandono {
  list-style: none;
  margin: 18px 0 14px;
  padding: 0;
  display: grid;
  gap: 2px;
}

.detalle-abandono li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  /* En pantallas angostas la cifra baja a su propia línea en vez de estirar
     el modal: con `nowrap` y sin envolver, la fila no podía encogerse. */
  flex-wrap: wrap;
  gap: 4px 16px;
  padding: 10px 14px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.04);
}

.detalle-abandono li span {
  color: var(--texto-suave, #b9b9b9);
  font-size: 0.9rem;
  min-width: 0;
}

.detalle-abandono li b {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Lo que se descuenta ahora: es la cifra que importa antes de confirmar. */
.detalle-abandono li.destacada {
  margin-top: 6px;
  background: rgba(212, 168, 67, 0.12);
  border: 1px solid rgba(212, 168, 67, 0.35);
}

.detalle-abandono li.destacada span {
  color: var(--oro, #d4a843);
  font-weight: 600;
}

.detalle-abandono li.destacada b {
  color: var(--oro, #d4a843);
  font-size: 1.15rem;
}

.aviso-suave {
  margin: 12px 0 0;
  color: var(--texto-suave, #b9b9b9);
  font-size: 0.88rem;
  line-height: 1.5;
}

.error-modal {
  margin: 12px 0 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: rgba(200, 60, 60, 0.14);
  border: 1px solid rgba(200, 60, 60, 0.4);
  color: #ffb4b4;
  font-size: 0.88rem;
}

/* ------------------------------------------- elegir objetivo de un poder */

/* Lo que se puede tocar ahora mismo: aro dorado y un latido suave. */
.carta.elegible-poder {
  cursor: pointer;
  outline: 2px solid var(--oro, #d4a843);
  outline-offset: 2px;
  border-radius: 8px;
  animation: latir-elegible 1.6s ease-in-out infinite;
  z-index: 4;
}

.carta.elegible-poder:hover {
  transform: translateY(-8px) scale(1.04);
}

@keyframes latir-elegible {
  0%, 100% { box-shadow: 0 0 0 0 rgba(212, 168, 67, 0.5); }
  50% { box-shadow: 0 0 14px 4px rgba(212, 168, 67, 0.35); }
}

/* Lo que NO se puede tocar: se ve que está, pero que no es para ahora. */
.carta.apagada {
  filter: grayscale(0.7) brightness(0.55);
  cursor: not-allowed;
}

/* La carta propia ya elegida, mientras se busca con cuál cambiarla. */
.carta.elegida-poder {
  outline: 3px solid var(--plata, #c0c0c0);
  outline-offset: 2px;
  filter: none;
  animation: none;
  z-index: 5;
}

@media (prefers-reduced-motion: reduce) {
  .carta.elegible-poder { animation: none; box-shadow: 0 0 12px 3px rgba(212, 168, 67, 0.4); }
}

/* ---------------------------------------------- miradas de los poderes 7 y 8

   Un segundo exacto: lo que dura MS_MARCA_PODER en mesa.js. Dice QUE alguien
   miró una carta y de quién, nunca cuál. El resplandor va sobre la mano
   entera y no sobre una carta suelta, porque señalar la carta exacta
   convertiría el poder en un anuncio público de dónde está lo que se vio. */

/* El cartel corto: un ícono grande y una palabra.

   Va arriba y chico, no en el medio y grande como el de los poderes. Es una
   diferencia deliberada: el de poder ANUNCIA algo que está por pasar y merece
   frenar la mesa; éste CONFIRMA algo que ya pasó y tiene que poder ignorarse.
   Si los dos gritaran igual, el que importa dejaría de destacar. */

.cartel-corto {
  position: absolute;
  top: 18%;
  left: 50%;
  transform: translateX(-50%);
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 18px;
  border-radius: 999px;
  background: rgba(10, 10, 10, 0.88);
  border: 1px solid rgba(70, 200, 255, 0.5);
  color: #d8f2ff;
  white-space: nowrap;
  pointer-events: none;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.5);
  animation: mirada-entra 160ms ease-out;
}

.cartel-corto .icono {
  font-size: 1.5rem;
  line-height: 1;
}

.cartel-corto b {
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.3px;
}

/* Es tu turno: dorado, no celeste. El celeste es "alguien hizo algo"; el
   dorado, "te toca a vos". Que se distingan de un vistazo es el punto de que
   exista este cartel. */
.cartel-corto.tuyo {
  border-color: rgba(212, 168, 67, 0.75);
  color: #f6e6c0;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.5), 0 0 26px rgba(212, 168, 67, 0.35);
}

.cartel-corto.saliendo {
  opacity: 0;
  transition: opacity 240ms ease-in;
}

/* La animación sólo hace la entrada. La posición de reposo no depende de que
   termine: si el navegador congela animaciones, el cartel igual queda donde va. */
@keyframes mirada-entra {
  from { opacity: 0; transform: translate(-50%, -6px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

.mano-mirada {
  animation: mano-mirada 1000ms ease-out;
}

@keyframes mano-mirada {
  0%, 100% { filter: none; }
  35%      { filter: drop-shadow(0 0 10px rgba(70, 200, 255, 0.9)); }
}

@media (prefers-reduced-motion: reduce) {
  .cartel-corto { animation: none; }
  .mano-mirada { animation: none; outline: 2px solid rgba(70, 200, 255, 0.7); }
}

/* ------------------------------------------------ indicador de espera

   Aparece con retraso (ver spinner.js) y NO tapa la mesa: quien decide si una
   acción se puede pedir es `pedir()`, y dos cosas decidiendo lo mismo es como
   se cuelga una interfaz. Esto sólo informa. */

.cargando-global {
  position: fixed;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px;
  border-radius: 999px;
  /* Contraste comprobado: #f2e6cd sobre #12100a da 13.4:1, muy por encima del
     4.5:1 que pide WCAG AA para texto normal. */
  background: rgba(18, 16, 10, 0.94);
  border: 1px solid rgba(212, 168, 67, 0.45);
  color: #f2e6cd;
  font-size: 0.84rem;
  pointer-events: none;
}

.cargando-global[hidden] { display: none; }

.cargando-global .aro {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 2px solid rgba(212, 168, 67, 0.3);
  border-top-color: #d4a843;
  animation: cargando-gira 700ms linear infinite;
}

@keyframes cargando-gira {
  to { transform: rotate(360deg); }
}

/* Sin animación, el aro se queda quieto pero visible: el texto ya dice lo que
   está pasando, así que no se pierde información. */
@media (prefers-reduced-motion: reduce) {
  .cargando-global .aro { animation: none; }
}

/* El foco del teclado, marcado a propósito y no dejado al contorno de fábrica.

   El del navegador es un hilo fino que sobre el paño verde oscuro casi no se
   distingue, y las cartas se pintan unas sobre otras: quien navega con
   tabulador necesita saber en cuál está. Va con `:focus-visible` y no con
   `:focus`, para que no aparezca al hacer clic con el ratón. */
.carta:focus-visible,
.accion:focus-visible,
.btn-icono:focus-visible {
  outline: 3px solid #d4a843;
  outline-offset: 2px;
}

/* --------------------------------- las dos cartas del poder 10

   Se ven mientras se decide, no un instante. Se está decidiendo CON ellas: si
   desaparecen antes de la respuesta, mostrarlas no sirvió de nada, que era
   justamente el problema que tenía el 10. */

.cartas-del-diez {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  margin: 18px 0 14px;
  flex-wrap: wrap;
}

.cartas-del-diez figure {
  margin: 0;
  text-align: center;
}

.cartas-del-diez img {
  width: 92px;
  max-width: 26vw;
  border-radius: 8px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55);
}

.cartas-del-diez figcaption {
  margin-top: 7px;
  font-size: 0.76rem;
  color: var(--tenue, #a1a1aa);
}

.cartas-del-diez figcaption b {
  color: var(--oro, #d4a843);
  font-size: 0.95rem;
}

.cartas-del-diez .flecha {
  font-size: 1.6rem;
  color: var(--oro, #d4a843);
}


/* ------------------------------------------- el doble toque en iPhone

   Sin esto, en iOS el doble toque sobre una carta es el gesto de ZOOM: Safari
   se lo queda y el segundo toque no llega como clic. El descarte —que pide dos
   toques— no se disparaba nunca en iPhone, mientras que en PC y en Android
   funcionaba bien.

   `manipulation` deja el desplazamiento y el pellizco para agrandar, y sólo
   apaga el doble toque para hacer zoom. Va SOBRE LAS CARTAS y no en el body a
   propósito: apagarlo en toda la página le sacaría a alguien con poca visión
   la forma más rápida de acercar el resto del tablero.

   Y de paso quita el retraso que iOS mete antes de decidir si un toque era
   simple o doble. En una ventana de reflejos donde el servidor ordena los
   intentos con 60 ms de tolerancia, ese retraso no es una molestia: es una
   desventaja sistemática para quien juegue desde un iPhone. */
.carta[data-posicion] {
  touch-action: manipulation;
}


/* =====================================================================
   ACUSE DEL PRIMER TOQUE  ·  sólo mesa de entrenamiento
   =====================================================================

   Descartar pide dos toques y, hasta que llegaba el segundo, la mesa no
   hacía NADA visible. Con cinco segundos de ventana y la carta quieta, el
   primer toque se lee como "no me registró", y la reacción natural es tocar
   más veces o más fuerte — que es justo lo que cuesta cartas de castigo.

   Ciento cincuenta milisegundos: se ve, y termina mucho antes de que pueda
   llegar el segundo toque (los sistemas operativos dan unos 400 ms para el
   doble clic). Lo que se anima es `transform`, que el navegador resuelve en
   la capa de composición y no obliga a recalcular la página. */

@keyframes primer-toque {
  0%   { transform: rotate(var(--giro)) translateY(var(--desvio)); }
  35%  { transform: rotate(var(--giro)) translateY(calc(var(--desvio) - 2px)); }
  70%  { transform: rotate(var(--giro)) translateY(calc(var(--desvio) + 2px)); }
  100% { transform: rotate(var(--giro)) translateY(var(--desvio)); }
}

.carta.carta-primer-toque {
  animation: primer-toque 150ms ease-in-out;
  z-index: 7;
}

/* El destello va en el `::after` que ya existe para el aro dorado, en vez de
   en un `box-shadow` propio de la carta: así no compite con la sombra del
   naipe ni la pisa. */
.carta.carta-primer-toque::after {
  opacity: 1;
  border-color: var(--oro-claro, #f0d060);
  box-shadow: 0 0 26px 4px rgba(240, 208, 96, 0.85);
}

/* =====================================================================
   ENTREGAR UNA CARTA A UN RIVAL
   ===================================================================== */

/* La carta ajena ya apuntada. Queda encendida mientras el resto se apaga:
   es lo único que sigue importando hasta elegir qué se entrega. */
.carta.apuntada {
  outline: 3px solid var(--oro);
  outline-offset: 2px;
  filter: none;
  z-index: 6;
}

/* Y la mano propia, que es de donde sale la entrega. */
.carta.entregable::after {
  opacity: 1;
}

/* ---------------------------------------------------------------------
   Con movimiento reducido, el destello se queda sin sacudida.

   La sacudida es la parte que molesta a quien pide menos movimiento; el
   brillo NO se saca, porque no es decoración: es el acuse de recibo del
   primer toque, y sin él la mesa vuelve a parecer que ignora los toques. */
@media (prefers-reduced-motion: reduce) {
  .carta.carta-primer-toque {
    animation: none;
  }
}


/* =====================================================================
   PANTALLA DE CARGA  ·  sólo mesa de entrenamiento
   ===================================================================== */

.velo-carga {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  padding: 24px;
  background: var(--noche-1, #05070b);
  transition: opacity 0.45s ease;

  /* Red de seguridad.

     Si el JavaScript no llega a correr —un import roto, una red que se cae a
     la mitad— este velo se quedaría tapando la mesa para siempre. A los diez
     segundos se desvanece solo. Diez es mucho más de lo que tarda un arranque
     normal, así que en la práctica no se ve nunca; es para el día que sí. */
  animation: velo-rendirse 0.5s ease 10s forwards;
}

@keyframes velo-rendirse {
  to { opacity: 0; visibility: hidden; }
}

.velo-carga-logo {
  width: clamp(160px, 46vw, 260px);
  height: auto;
  filter: drop-shadow(0 0 26px rgba(212, 168, 67, 0.45));
}

.velo-carga-aro {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 3px solid rgba(212, 168, 67, 0.25);
  border-top-color: var(--oro, #d4a843);
  animation: velo-girar 0.9s linear infinite;
}

@keyframes velo-girar {
  to { transform: rotate(360deg); }
}

.velo-carga-texto {
  margin: 0;
  color: var(--texto-tenue, #9aa3b2);
  letter-spacing: 1.6px;
  text-transform: uppercase;
  font-size: 0.78rem;
}

/* Al irse se apaga la red de seguridad: si no, la animación de rendición
   seguiría corriendo y podría volver a pintar el velo por un instante. */
.velo-carga.se-va {
  animation: none;
  opacity: 0;
  visibility: hidden;
}

/* =====================================================================
   CUENTA REGRESIVA  ·  sólo mesa de entrenamiento
   =====================================================================

   No tapa la mesa: se pinta encima, en el centro y sin fondo, para que el
   reparto recién terminado siga a la vista. La idea es "ya va a empezar", no
   "esperá otra pantalla". */

.cuenta-atras {
  position: fixed;
  inset: 0;
  z-index: 55;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;

  /* Un oscurecido suave y redondo detrás del número.

     Sin esto el número caía justo encima de las etiquetas del centro —"MAZO",
     "LEVANTADA", "MUESTRA"— y las dos cosas se leían mal a la vez. No es un
     velo opaco a propósito: el reparto recién termina y se quiere que siga
     viéndose. La idea es "ya empieza", no "esperá otra pantalla". */
  background: radial-gradient(
    circle at 50% 50%,
    rgba(3, 5, 9, 0.82) 0%,
    rgba(3, 5, 9, 0.55) 28%,
    rgba(3, 5, 9, 0) 55%
  );
}

.cuenta-atras[hidden] {
  display: none;
}

.cuenta-atras-numero {
  /* Grande de verdad: en un teléfono de 390px son unos 120px de alto. El
     primer intento usaba 22vw y el número quedaba del tamaño de una carta,
     compitiendo con la mesa en vez de destacarse sobre ella. */
  font-size: clamp(5rem, 31vw, 11rem);
  font-weight: 800;
  letter-spacing: 2px;
  color: var(--oro, #d4a843);
  text-shadow: 0 0 40px rgba(212, 168, 67, 0.6), 0 6px 24px rgba(0, 0, 0, 0.7);
  animation: cuenta-latir 0.9s ease-out;
}

/* "Preparate…" es una palabra, no un número: con el mismo tamaño se sale de
   la pantalla en un teléfono. */
.cuenta-atras-numero.palabra {
  font-size: clamp(1.6rem, 8vw, 3.2rem);
  letter-spacing: 3px;
  text-transform: uppercase;
}

@keyframes cuenta-latir {
  0%   { transform: scale(0.55); opacity: 0; }
  25%  { transform: scale(1.08); opacity: 1; }
  70%  { transform: scale(1); opacity: 1; }
  100% { transform: scale(0.94); opacity: 0.15; }
}

/* =====================================================================
   REPARTO: LAS CARTAS VUELAN DESDE EL MAZO
   =====================================================================

   `--dx` y `--dy` los calcula `mesa.js` midiendo la distancia entre cada
   carta y el mazo del centro. Se hace con medidas reales y no con una
   dirección fija por asiento porque la mesa cambia de forma: en un teléfono
   los asientos se acomodan distinto que en una pantalla ancha, y una
   dirección escrita a mano manda las cartas a cualquier lado.

   Se anima `transform` y `opacity`, que el navegador resuelve en la capa de
   composición: veinte cartas volando no obligan a recalcular la página. */

@keyframes volar-al-asiento {
  from {
    transform: translate(var(--dx, 0px), var(--dy, 0px)) scale(0.55);
    opacity: 0;
  }
  55% { opacity: 1; }
  to {
    transform: rotate(var(--giro)) translateY(var(--desvio)) scale(1);
    opacity: 1;
  }
}

.carta.repartiendo {
  animation: volar-al-asiento 260ms cubic-bezier(0.22, 0.7, 0.3, 1) both;
  animation-delay: var(--retraso-reparto, 0ms);
}

/* ---------------------------------------------------------------------
   Con movimiento reducido no vuela nada y no hay cuenta regresiva.

   `mesa.js` mira la misma preferencia y se saltea las esperas, así que esto
   es sólo la mitad visual: sin la otra, las cartas aparecerían quietas pero
   el jugador igual esperaría los cuatro segundos de la cuenta. */
@media (prefers-reduced-motion: reduce) {
  .carta.repartiendo {
    animation: none;
  }
  .cuenta-atras-numero {
    animation: none;
  }
  .velo-carga-aro {
    animation: none;
  }
}


/* =====================================================================
   EL CURSOR Y LA SELECCIÓN DE TEXTO
   =====================================================================

   Descartar son DOS toques seguidos, y en una PC dos clics seguidos son un
   doble clic: el navegador lo entiende como "seleccionar la palabra que hay
   debajo". Las cartas llevan texto adentro —el número de posición— así que
   cada descarte dejaba el número resaltado en azul y el puntero convertido en
   la barra de escribir. Se veía como un error de la página.

   `user-select: none` lo apaga. Va sobre la mesa entera y no sólo sobre las
   cartas porque el arrastre no respeta fronteras: empezar sobre una carta y
   terminar sobre el paño seleccionaba todo lo del medio.

   NO se pone en `body`: el registro de jugadas y el marcador final son texto
   que uno querría poder copiar. */

.mesa,
.asiento,
.carta,
.pila,
.tira-pista,
.acciones {
  user-select: none;
  -webkit-user-select: none;
}

/* `-webkit-touch-callout` es lo mismo para iOS: sin esto, mantener el dedo
   sobre una carta abre el menú de "copiar / compartir imagen" en mitad de la
   ventana de reflejos. */
.carta {
  -webkit-touch-callout: none;
}

/* El puntero dice qué se puede tocar, y nada más.

   Antes cualquier hueco de la mesa heredaba el puntero de mano de algún
   contenedor, así que la mesa entera parecía tocable. Ahora la mano aparece
   sólo sobre lo que responde: una carta jugable, el mazo cuando se puede
   levantar, la levantada con poder y los botones. */
.mesa,
.asiento,
.pila,
.carta {
  cursor: default;
}

.carta.jugable,
.carta.atacable,
.carta.elegible-poder {
  cursor: pointer;
}

/* Y lo apagado se dice apagado: el puntero avisa antes del clic que ahí no
   hay nada, en vez de dejar que uno lo descubra tocando. */
.carta.apagada {
  cursor: not-allowed;
}

/* ------------------------------------------- el marco y el titulo comprados

   El MARCO va encima de la cara, en posición absoluta, y no como `border`.

   Un borde de verdad empujaría la cara hacia adentro y cambiaría el tamaño de
   la caja, así que los cuatro asientos dejarían de medir lo mismo según quién
   tenga marco puesto. Superpuesto ocupa el mismo lugar y no mueve nada.

   Sale un poco por fuera —el `inset` negativo— porque un marco dibujado justo
   al borde de la cara se lee como parte de la foto y no como un marco. */
.jugador .retrato .marco-avatar {
  position: absolute;
  inset: calc(var(--aro) * -1.5);
  width: auto;
  height: auto;
  pointer-events: none;
  /* Encima de la cara y del aro, debajo de la cuenta del asiento. */
  z-index: 2;
}

/* La cuenta del asiento tiene que seguir viéndose por encima del marco: es
   información de la partida y el marco es decoración. */
.jugador .retrato .cuenta-asiento {
  z-index: 3;
}

/* El TÍTULO, al lado del nombre.

   En voz más baja que el nombre y sin envolver: en una mesa de cuatro el
   asiento es angosto, y un título de dos líneas empuja los puntos fuera de
   la cabecera. El servidor ya lo recorta a 24 caracteres; esto es el segundo
   cinturón, visual. */
.jugador .nombre .titulo-jugador {
  display: inline-block;
  max-width: 11ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid rgba(212, 168, 67, 0.45);
  background: rgba(212, 168, 67, 0.12);
  color: var(--oro-claro, #fcf0c4);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.3px;
}
