/* ============================================================
   King of Redactors — sistema móvil (rediseño 2026-09)
   Móvil primero, un solo breakpoint (720px).
   Pantalla = cabecera fija · cuerpo con scroll · pie fijo.
   Color: cian = acción, dorado = logro/rareza.
   Es el único CSS de la aplicación: el viejo juego.css (y layouts/game.blade.php con su
   juego.js) era código muerto y se borró al montar la PWA (2026-09-17).
   ============================================================ */

:root {
  --bg: #100a1e;
  --bg-2: #180f2e;
  --surface: #1e1338;
  --panel: #261847;
  --line: #392764;
  --line-soft: #2b1d4f;
  --ink: #e9ddbe;
  --ink-dim: #a99cd0;
  --ink-faint: #968aa8;   /* el gris morado de las etiquetas. Antes #7c7099, que sobre
                             --panel/--wood bajaba a 3,5:1 y no llegaba al 4,5:1 que
                             pide WCAG AA para texto pequeño (etiquetas de ficha,
                             subtítulos de marcador, notas). Este sube a 4,72:1 en el
                             peor fondo (--wood) y sigue claramente debajo de --ink-dim. */
  --candle: #4ee8ff;
  --candle-dim: #2bb8d9;
  --blood: #ff3d5c;
  --gold: #ffd23f;
  --green: #59d98a;
  /* Colores tipo energía Pokémon: agua / rayo / planta / fuego. */
  --stat-fue: #2ea3d8;
  --stat-tra: #f7ca3f;
  --stat-red: #5cbb52;
  --stat-gam: #ef4136;
  --wood: #2c1a52;
  --wood-2: #170c30;

  --f-body: "Fira Sans", "Helvetica Neue", system-ui, sans-serif;
  --f-display: "Bungee", "Fira Sans", system-ui, sans-serif;
  --f-pixel: "Press Start 2P", "Fira Sans", monospace;

  --pad: 16px;
  --tap: 46px;
  /* Antes 30rem (480px), un ancho suelto que no coincidía con ninguna otra medida
     de la app. La pantalla de combate ya tenía su propia columna angosta a
     propósito (--stage-w = carta + rail, ver play.blade.php) para que "la carta
     mande" y nada crezca de más en escritorio — el resto de pantallas (mapa,
     logros, elegir redactor...) se estiraba más ancho que eso, descoordinado.
     Ahora --col sigue la MISMA regla en toda la app: el tope de carta
     (--card-w-max, definido más abajo) más un margen fijo, así todas las
     pantallas comparten columna en escritorio — no solo combate. */
  --col: calc(var(--card-w-max) + 100px);

  /* ── REGLA FIJA DE CARTAS ──────────────────────────────────────
     La carta de redactor (.card) mide SIEMPRE lo mismo, en todas las pantallas: el
     tamaño que imprime en combate. Y el combate se ajusta para que los botones del
     rail —cuadrados, uno por pieza— llenen exactamente su alto:

         carta + hueco + rail = ancho disponible
         rail = (alto_carta - (n-1) · separación) / n
         alto_carta = carta × 4.25/3

     Despejando sale el --card-w de abajo. En escritorio sobra sitio y manda el tope
     --card-w-max (287 px). En el móvil no caben 287 px de carta + los botones, así
     que la carta encoge lo justo: en 390 px de ancho salen 261 px de carta y 87 de
     botones (antes 287 + 61, con los botones sin llenar el alto).
     No poner tamaños de carta sueltos en ninguna pantalla: todo se deriva de
     --card-w / --card-aspect.                                          */
  --card-aspect: 3 / 4.25;
  --card-w-max: 287px;    /* el tamaño de carta más grande que se usa */
  --card-gap: 10px;       /* carta ↔ rail de botones, solo en combate */
  --rail-gap: 8px;        /* separación entre los botones del rail */
  --rail-n-ref: 4;        /* botones de REFERENCIA con los que se mide el ancho de
                             carta (rival + maletines + consola + overclock) */
  --card-w: min(var(--card-w-max), calc(
    3 * ((100vw - 2 * var(--pad) - var(--card-gap)) * var(--rail-n-ref)
         + var(--rail-gap) * (var(--rail-n-ref) - 1))
    / (3 * var(--rail-n-ref) + 4.25)
  ));
  --card-h: calc(var(--card-w) * 4.25 / 3); /* 407 px en escritorio, 370 en móvil */
  --rail-n: 4;            /* botones REALES del rail de combate: la vista de combate
                             lo reescribe inline y de ahí salen --stage-rail y
                             --stage-w — ver play.blade.php. (OJO: --card-w usa
                             --rail-n-ref, no este, para que la carta mida lo mismo en
                             todas las pantallas aunque una Fase tenga 5 botones.) */
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background:
    radial-gradient(circle at 12% -5%, rgba(78, 232, 255, .10), transparent 42%),
    radial-gradient(circle at 92% 105%, rgba(255, 61, 214, .09), transparent 46%),
    var(--bg);
  color: var(--ink);
  font-family: var(--f-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: var(--candle); }
[hidden] { display: none !important; }

/* ---------- pantalla ----------
   App shell: alto exacto de viewport, cabecera y pie fijos, el cuerpo
   es lo único que hace scroll. min-height:0 en el cuerpo es lo que evita
   que el contenido lo estire y empuje el pie fuera de pantalla. */
html, body { height: 100%; }
body { overflow: hidden; }
.screen {
  height: 100svh;
  height: 100dvh;
  /* --app-h lo pone app.js SOLO en la app instalada, donde algunos navegadores Android
     mienten con dvh y el pie se quedaba fuera de la pantalla. En el navegador no existe
     y manda dvh, que se ajusta solo al mostrar y ocultar las barras. */
  height: var(--app-h, 100dvh);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background:
    radial-gradient(circle at 15% 0%, rgba(78, 232, 255, .06), transparent 45%),
    linear-gradient(180deg, var(--bg-2), var(--bg));
}
.screen__top {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  /* El FONDO se queda a todo lo ancho (barra de verdad, de borde a borde); lo que se
     limita a la columna (--col, 30rem) como .screen__body es solo el padding
     horizontal, que crece en escritorio hasta dejar el mismo hueco de contenido
     centrado en medio — un max-width en .screen__top habría encogido también la
     propia barra, dejando fondo y borde flotando en el centro. Sin efecto en móvil
     (var(--pad) ya gana el max(), porque ahí sobra menos que --col). */
  padding-inline: max(var(--pad), calc((100% - var(--col)) / 2));
  /* Arriba se suma el área segura del sistema (notch, barra de estado): en la app instalada
     a pantalla completa, sin esto la cabecera se mete debajo. Abajo ya se hacía en el pie. */
  padding-block: calc(12px + env(safe-area-inset-top, 0px)) 12px;
  border-bottom: 1px solid var(--line-soft);
  background: rgba(12, 7, 24, .7);
  backdrop-filter: blur(6px);
}
/* min-height igual al icon-btn (--tap): sin él, el eyebrow+título (~30px) es más
   bajo que el botón (46px) y la barra entera encoge en las pantallas que no
   llevan botón — se ve más estrecha verticalmente que el resto. Con esto mide
   lo mismo haya o no botón, y el texto queda centrado dentro con align-items. */
.screen__top-main { flex: 1; min-width: 0; min-height: var(--tap); display: flex; flex-direction: column; justify-content: center; }
.screen__eyebrow {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.screen__title { font-weight: 800; font-size: 1rem; line-height: 1.15; }
/* Progreso de la edición (x-game.edition-pips): las 7 etapas, en la cabecera de todas
   las pantallas de la partida. */
.pips { display: flex; gap: 4px; margin-top: 6px; }
.pip { width: 8px; height: 8px; border-radius: 1px; background: #2c2450; border: 1px solid #120e1f; }
.pip--done { background: #2f7d4f; }
.pip--current { background: var(--candle); box-shadow: 0 0 0 3px rgba(78,232,255,.2); }
/* Varios botones a la derecha de la cabecera (mapa: tu build + portada). */
.screen__top > .icon-btn + .icon-btn { margin-left: -2px; }
.screen__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 20px var(--pad);
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.screen__body > * { width: 100%; max-width: var(--col); margin-inline: auto; }
.screen__body::-webkit-scrollbar { width: 5px; }
.screen__body::-webkit-scrollbar-thumb { background: var(--line); border-radius: 3px; }
.screen__body--center { justify-content: center; }
.screen__foot {
  flex: 0 0 auto;
  /* Mismo truco que .screen__top: el FONDO ocupa toda la barra, y es el padding
     horizontal el que crece en escritorio hasta dejar la misma columna de
     contenido centrada (--col) que .screen__body. Esto además arregla solo un
     pie con <form> (la mayoría): el form pone display:contents (ver más abajo), así
     que sus hijos reales no son hijos DIRECTOS de .screen__foot y un max-width en
     ellos (o en ".screen__foot > *") no les llegaba — con el límite en el propio
     padding del contenedor, da igual cuántos niveles de display:contents haya en
     medio. */
  padding-inline: max(var(--pad), calc((100% - var(--col)) / 2));
  padding-block: 12px calc(12px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--line-soft);
  background: rgba(12, 7, 24, .8);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.screen__foot form { display: contents; }

/* En la app instalada a pantalla completa, el área segura del sistema puede no reportarse
   (según el móvil): este mínimo garantiza que el pie nunca quede pegado al borde de la
   pantalla ni debajo del indicador de inicio. Si el sistema sí la reporta, se sigue usando
   la de arriba (es más generosa). */
@media (display-mode: standalone) {
  .screen__foot { padding-bottom: max(28px, calc(12px + env(safe-area-inset-bottom, 0px))); }
}

/* Red de seguridad para pantallas muy bajas: móvil en horizontal, o navegadores dentro de
   otras apps (WhatsApp, Instagram...), donde la altura real no siempre es la que cree
   `dvh`. Ahí, en vez de recortar la pantalla —que dejaba el botón de la acción fuera—, se
   deja hacer scroll y el pie se queda pegado abajo, siempre a mano. */
@media (max-height: 560px) {
  .screen { height: auto; min-height: 100dvh; overflow: visible; }
  .screen__body { overflow: visible; }
  .screen__foot { position: sticky; bottom: 0; }
}
.foot-row { display: flex; gap: 10px; }

/* ---------- botones de juego ----------
   UN solo sistema para todos los botones de la app. Decisión de diseño: botón moderno de
   videojuego, no retro. La letra pixel (Press Start) se queda para los rótulos cortos del
   HUD; en un botón, que es lo que más se lee y se pulsa, se lee mal en el móvil. Así que:
   - letra Bungee (la del título del juego), en mayúsculas: gruesa, de recreativa y legible;
   - canto 3D debajo (--btn-edge) que se hunde al pulsar, como un botón físico;
   - variantes que solo cambian colores: principal (cian), --ghost (secundario oscuro),
     --danger (rojo), .is-loaded (dorado, moneda cargada).
   No poner fuentes ni sombras sueltas a botones en las vistas: se cambia aquí. */
.btn {
  --btn-edge: #0b5d70;
  --btn-glow: rgba(78, 232, 255, .45);
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--tap);
  font-family: var(--f-display);
  font-weight: 400;
  font-size: 1rem;
  line-height: 1.1;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  color: #052733;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .35);
  background: linear-gradient(180deg, #8ff4ff 0%, var(--candle) 45%, var(--candle-dim) 100%);
  border: 2px solid #0a3f4d;
  border-radius: 10px;
  padding: 10px 20px;
  cursor: pointer;
  box-shadow: 0 4px 0 var(--btn-edge), inset 0 2px 0 rgba(255, 255, 255, .45), 0 8px 20px -8px var(--btn-glow);
  transition: transform .1s cubic-bezier(.3, 1.6, .5, 1), box-shadow .1s ease, filter .12s ease;
}
.btn:not(:disabled):active {
  transform: translateY(3px);
  box-shadow: 0 1px 0 var(--btn-edge), inset 0 2px 0 rgba(255, 255, 255, .3);
  filter: brightness(1.08);
}
.btn:disabled { opacity: .45; filter: grayscale(.6); box-shadow: 0 4px 0 rgba(0, 0, 0, .35); cursor: not-allowed; }
.btn:focus-visible { outline: 2px solid var(--candle); outline-offset: 3px; }
.btn--ghost {
  --btn-edge: #0b0716;
  --btn-glow: transparent;
  flex: 0 0 auto;
  color: var(--ink);
  text-shadow: none;
  background: linear-gradient(180deg, #2c1d52, #1e1338);
  border-color: var(--line);
  box-shadow: 0 4px 0 var(--btn-edge), inset 0 1px 0 rgba(255, 255, 255, .08);
}
.btn--danger {
  --btn-edge: #6a0014;
  --btn-glow: rgba(255, 61, 92, .4);
  color: #2a0006;
  background: linear-gradient(180deg, #ff8a9a 0%, var(--blood) 50%, #c81e3a 100%);
  border-color: #3d0011;
}
.btn--wide { flex: 1 1 100%; }

/* Botón cuadrado de icono (salir, sonido, registro…): mismo canto, más bajito. */
.icon-btn {
  flex: 0 0 auto;
  width: var(--tap);
  height: var(--tap);
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, #2c1d52, #1e1338);
  border: 2px solid var(--line);
  border-radius: 10px;
  color: var(--ink-dim);
  cursor: pointer;
  box-shadow: 0 3px 0 #0b0716, inset 0 1px 0 rgba(255, 255, 255, .08);
}
.icon-btn svg { width: 20px; height: 20px; }
.icon-btn:focus-visible { outline: 2px solid var(--candle); outline-offset: 3px; }

/* ---------- campo de formulario ---------- */
.field { display: flex; flex-direction: column; gap: 5px; }
.field > span { font-size: .8rem; font-weight: 600; color: var(--ink-dim); letter-spacing: .02em; }
.field input {
  min-height: var(--tap);
  width: 100%;
  padding: 10px 13px;
  font: inherit;
  font-size: 1rem;
  color: var(--ink);
  background: rgba(0, 0, 0, .32);
  border: 1px solid var(--line);
  border-radius: 4px;
}
.field input:focus-visible { outline: 2px solid var(--candle); outline-offset: 1px; border-color: var(--candle); }

/* Red de seguridad del foco: los botones del rail, los chips de habilidad, las fichas de
   los modales y el botón de cerrar del registro no tienen regla propia, y por teclado hay
   que ver dónde estás. Los de arriba (.btn, .icon-btn, campos) conservan su estilo, que es
   más específico. */
:where(a, button, summary, input, select, textarea):focus-visible {
  outline: 3px solid var(--candle);
  outline-offset: 2px;
}

.panel { background: var(--surface); border: 1px solid var(--line); border-radius: 10px; padding: 18px; }
.notice { font-size: .88rem; color: var(--ink-dim); text-align: center; margin: 0 0 16px; }
.error {
  font-size: .88rem;
  color: #ffb3bd;
  background: rgba(255, 61, 92, .12);
  border: 1px solid rgba(255, 61, 92, .35);
  border-radius: 4px;
  padding: 8px 12px;
  text-align: center;
  margin: 0 0 14px;
}

/* ---------- marca / masthead ---------- */
.masthead { text-align: center; display: flex; flex-direction: column; gap: 12px; align-items: center; }
.brand {
  display: inline-block;
  font-family: var(--f-body);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: #1a0f00;
  background: linear-gradient(100deg, var(--gold), #ffb020);
  padding: 3px 14px;
  border-radius: 2px;
  transform: skewX(-8deg);
  box-shadow: 0 3px 0 rgba(0, 0, 0, .4), 0 6px 14px -6px rgba(0, 0, 0, .6);
}
.masthead__title {
  font-family: var(--f-display);
  font-weight: 400;
  font-size: clamp(1.5rem, 8vw, 2.1rem);
  line-height: 1.05;
  color: var(--ink);
  text-shadow: 0 0 18px rgba(78, 232, 255, .25), 3px 3px 0 rgba(0, 0, 0, .35);
  margin: 0;
  text-wrap: balance;
}
.foot-note { text-align: center; font-size: .74rem; color: var(--ink-faint); }

/* ---------- barra de usuario ---------- */
.userbar { display: flex; align-items: center; gap: 10px; width: 100%; }
.avatar {
  width: 36px;
  height: 36px;
  border-radius: 9px;
  object-fit: cover;
  flex: 0 0 auto;
  background: rgba(78, 232, 255, .14);
  border: 2px solid rgba(78, 232, 255, .3);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  color: var(--candle);
}
.userbar__name {
  font-weight: 700;
  font-size: .98rem;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.userbar form { display: contents; }

/* ---------- home ---------- */
.tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.tile {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 6px;
  text-align: center;
}
.tile b {
  display: block;
  font-size: 1.15rem;
  font-weight: 900;
  color: var(--ink);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.tile > span {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.tile--fire b { color: var(--blood); }

.resume {
  display: flex;
  align-items: center;
  gap: 12px;
  background: rgba(78, 232, 255, .08);
  border: 1px solid rgba(78, 232, 255, .3);
  border-radius: 10px;
  padding: 12px 14px;
}
.resume__body { flex: 1; min-width: 0; }
.resume__title { font-weight: 800; font-size: .95rem; }
.resume__meta { font-size: .8rem; color: var(--ink-dim); }
.resume .btn { flex: 0 0 auto; min-height: 38px; padding: 8px 16px; font-size: .85rem; }

.rank {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 14px 16px;
}
.rank__head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.rank__label {
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0;
}
.rank__mine { font-size: .78rem; color: var(--ink-dim); }
.rank__mine b { color: var(--candle); font-weight: 800; font-variant-numeric: tabular-nums; }
.rank__list { display: flex; flex-direction: column; }
.rank__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 4px;
  margin: 0 -6px;
  border-radius: 7px;
  border-bottom: 1px solid var(--line-soft);
}
.rank__row:last-child { border-bottom: none; }
.rank__row--you {
  background: rgba(78, 232, 255, .09);
  box-shadow: inset 3px 0 0 var(--candle);
  border-bottom-color: transparent;
}
.rank__pos {
  width: 1.6em;
  text-align: center;
  font-weight: 800;
  color: var(--ink-dim);
  flex: 0 0 auto;
  font-size: .95rem;
}
.rank__av {
  width: 28px;
  height: 28px;
  border-radius: 7px;
  flex: 0 0 auto;
  background: rgba(168, 155, 207, .16);
  border: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: .82rem;
  color: var(--ink-dim);
  object-fit: cover;
}
.rank__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
  font-size: .95rem;
}
.rank__row--you .rank__name { font-weight: 800; }
.rank__ventas {
  flex: 0 0 auto;
  font-weight: 800;
  color: var(--candle);
  font-variant-numeric: tabular-nums;
  font-size: .95rem;
}
.rank__chase { font-size: .72rem; color: var(--gold); font-weight: 700; text-align: right; margin: 6px 4px 0; }
.rank__all {
  display: block;
  margin-top: 10px;
  text-align: center;
  font-size: .85rem;
  font-weight: 600;
  color: var(--candle);
  text-decoration: none;
}
.rank__empty { font-size: .88rem; color: var(--ink-dim); text-align: center; padding: 8px 0; }

.home-tut { text-align: center; font-size: .82rem; font-weight: 600; color: var(--ink-dim); text-decoration: none; }

.dev-login {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed var(--line);
  text-align: center;
}
.dev-login button {
  font: inherit;
  font-size: .82rem;
  font-weight: 700;
  color: var(--gold);
  background: rgba(255, 210, 63, .1);
  border: 1px dashed rgba(255, 210, 63, .4);
  border-radius: 6px;
  padding: 8px 14px;
  cursor: pointer;
}

/* ---------- desktop: un poco más de aire ---------- */
@media (min-width: 720px) {
  :root { --pad: 24px; }
  .screen__body { padding-top: 32px; padding-bottom: 32px; }
}

/* ---------- ordenador: pantallas anchas ----------
   En el móvil todo es una columna. En el ordenador las pantallas con .screen--wide
   ensanchan su columna de contenido y reparten el contenido en dos (cada vista dice
   cómo, con su propio grid); los botones del pie se quedan del ancho del móvil, que es
   como se leen y se pulsan mejor. .desk-only: solo se ve en el ordenador. */
@media (max-width: 1023.98px) { .desk-only { display: none !important; } }
.home-a, .home-b { display: contents; }
/* Sus hijos se comportan como hijos directos del cuerpo (misma columna centrada). */
.home-a > *, .home-b > * { width: 100%; max-width: var(--col); margin-inline: auto; }
@media (min-width: 1024px) {
  .screen--wide { --col: 64rem; }
  .screen--wide .screen__foot { padding-inline: max(var(--pad), calc((100% - 30rem) / 2)); }
  .desk-grid {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 18px 32px; align-content: start;
    padding-inline: max(var(--pad), calc((100% - var(--col)) / 2));
  }
  .desk-grid > * { max-width: none; margin-inline: 0; }

  /* Portada: rótulo arriba, menú a la izquierda, ranking a la derecha. */
  .home-body {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 18px 32px;
    grid-template-areas: "title title" "a rank" "b rank"; grid-template-rows: auto auto 1fr; align-content: start;
    padding-inline: max(var(--pad), calc((100% - var(--col)) / 2));
  }
  .home-body > * { max-width: none; margin-inline: 0; }
  .home-body .menu-title { grid-area: title; }
  .home-a, .home-b { display: flex; flex-direction: column; gap: 18px; }
  .home-a { grid-area: a; }
  .home-b { grid-area: b; }
  .home-body .rank { grid-area: rank; align-self: start; }

  /* Pantallas de elegir (starter kit, sobre, consola): las opciones lado a lado, para
     compararlas de un vistazo; el resto (rótulos, resumen) en la misma columna. */
  .screen--pick { --col: 46rem; }
  .screen--pick .screen__foot { padding-inline: max(var(--pad), calc((100% - 30rem) / 2)); }
  .screen--pick .ficha-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; }
  .screen--pick .ficha-list > .ficha { height: 100%; }

  /* Logros: la lista en dos columnas. */
  .screen--wide .logro-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

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

/* ============================================================
   LA CARTA — componente contenedor (container-type: inline-size).
   Dos modos: normal (juego) y .is-full (ficha, se abre grande).
   Tipos con suelo en px vía clamp(): escalan sin volverse ilegibles.
   ============================================================ */
.card {
  container-type: inline-size;
  width: 100%;
  aspect-ratio: var(--card-aspect);
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  isolation: isolate;
  /* El marco PROPIO de la carta va en px fijos, NO en cqw: un elemento con
     container-type no puede consultarse a sí mismo, así que sus cqw se resolvían
     contra el ancestro contenedor (o el viewport) y en combate/desktop la carta
     salía con 32px de padding y un radio gigante. Las cqw de dentro (.card__*)
     sí son válidas: esos hijos SÍ consultan a .card. */
  border-radius: 12px;
  border: 2px solid #140a22;
  padding: 8px;
  color: var(--ink);
  background:
    radial-gradient(circle at 22% 12%, rgba(78, 232, 255, .14), transparent 46%),
    radial-gradient(circle at 82% 88%, rgba(255, 61, 214, .12), transparent 52%),
    linear-gradient(160deg, var(--wood), var(--wood-2));
  box-shadow: 0 0 0 1px rgba(78, 232, 255, .4), 0 0 16px 3px rgba(78, 232, 255, .2), 0 12px 22px -12px rgba(0, 0, 0, .85);
  /* La carta NO se inclina: quitada la rotación 3D que seguía al puntero/dedo.
     Lo único que se mueve al pasar el dedo/ratón o inclinar el móvil es el
     brillo holo de las raras (--tilt-x/--tilt-y, ver public/js/app.js), y el
     único movimiento de la carta entera es el volteo a la cara mayor, que lo
     hace su envoltorio (.pick-flip__inner / .giro-flip), no .card. */
  transition: box-shadow .4s ease;
}
@media (prefers-reduced-motion: reduce) {
  .card { transition: none; }
}
.card--rara { border-color: var(--gold); }
/* Carta impresa tal cual (image_carta_path, prueba con la PX12): la imagen ocupa la carta
   entera, sin marco ni relleno del diseño dibujado. Misma proporción (3 / 4,25) que la
   carta física, así que no se deforma. */
.card:has(> .card__print) { padding: 0; }
.card:not(.card--rara):has(> .card__print) { background: #0b0716; }
.card__print { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 10px; }
/* Jefe final (CardShaper::bossify) con carta impresa: el marco holo de las raras, más fino
   para no comerse la carta, el brillo prismático encima y una chapa con el bonus de stats
   (las cifras impresas son las de la carta normal). */
.card--rara:has(> .card__print),
.card--rara.is-full:has(> .card__print) { border-width: 6px; }
.card--rara:has(> .card__print) .card__print { border-radius: 7px; }
.card--rara:has(> .card__print) .card__holo { opacity: .45; }
/* Efectos animados de las cartas impresas (cards.efectos): cada capa lleva solo la pieza que se
   anima, en su sitio exacto sobre la carta. */
.card__fx { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 10px; pointer-events: none; z-index: 4; }
.card--rara:has(> .card__print) .card__fx { border-radius: 7px; }
/* Sable de luz: la hoja se enciende de blanco, vibra con el zumbido (parpadeo rápido e
   irregular) y el halo cian late despacio, como en Star Wars. */
.card__fx--sable-luz {
  mix-blend-mode: screen;
  filter: brightness(1.35) drop-shadow(0 0 2px #e8fdff) drop-shadow(0 0 7px #2fd8ff) drop-shadow(0 0 16px #00a8ff);
  animation: fx-sable-zumbido .19s steps(2, jump-none) infinite, fx-sable-halo 2.6s ease-in-out infinite;
}
@keyframes fx-sable-zumbido {
  0% { opacity: 1; }
  100% { opacity: .82; }
}
@keyframes fx-sable-halo {
  0%, 100% { filter: brightness(1.25) drop-shadow(0 0 2px #e8fdff) drop-shadow(0 0 6px #2fd8ff) drop-shadow(0 0 12px #00a8ff); }
  50% { filter: brightness(1.6) drop-shadow(0 0 3px #ffffff) drop-shadow(0 0 10px #4ae2ff) drop-shadow(0 0 24px #00a8ff); }
}
/* LEDs (robot de la PX18 mayor): la capa lleva solo los LED rojos; laten despacio con un
   halo rojo y, de vez en cuando, dan un parpadeo de fallo eléctrico. */
.card__fx--leds {
  mix-blend-mode: screen;
  animation: fx-leds-latido 2.2s ease-in-out infinite, fx-leds-fallo 7s steps(1, end) infinite;
}
@keyframes fx-leds-latido {
  0%, 100% { filter: brightness(1) drop-shadow(0 0 1px #ff3030) drop-shadow(0 0 3px #ff1a1a); }
  50% { filter: brightness(1.9) drop-shadow(0 0 2px #ff6060) drop-shadow(0 0 8px #ff1010) drop-shadow(0 0 14px #c00000); }
}
@keyframes fx-leds-fallo {
  0%, 81%, 84%, 86%, 100% { opacity: 1; }
  82%, 85% { opacity: .15; }
}
/* Destello (espada de la PX18 joven): la capa es la hoja en blanco y una franja de luz la
   recorre de la punta a la empuñadura cada pocos segundos. La máscara mide 3 cartas de ancho:
   en mask-position 100% la franja queda fuera por la izquierda y en 40%, a un 70% del ancho de la
   carta (pasada la espada, que está a la izquierda). */
.card__fx--destello {
  opacity: .95;
  -webkit-mask-image: linear-gradient(120deg, transparent 45%, #000 50%, transparent 55%);
  mask-image: linear-gradient(120deg, transparent 45%, #000 50%, transparent 55%);
  -webkit-mask-size: 300% 100%; mask-size: 300% 100%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: 100% 0; mask-position: 100% 0;
  filter: drop-shadow(0 0 3px #fff);
  animation: fx-destello 3.6s ease-in-out infinite;
}
@keyframes fx-destello {
  0% { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  35%, 100% { -webkit-mask-position: 40% 0; mask-position: 40% 0; }
}
/* Agua (mar de la PX18): la capa es el mar, aclarada y casi sin color (la luz del sol sobre el
   agua es blanca, no azul). Dos rejillas de manchas suaves y alargadas se desplazan despacio en
   sentidos contrarios y solo se ve donde coinciden: reflejos difusos que aparecen y se apagan
   poco a poco. Cada rejilla avanza un número entero de baldosas por vuelta (10 % de ancho → 9
   baldosas; 1/7 → 6), así que el bucle no salta. agua-sangre (mar rojo de la mayor) es lo
   mismo, con un rojo claro y más tenue. */
.card__fx--agua, .card__fx--agua-sangre {
  mix-blend-mode: screen;
  filter: saturate(.25) brightness(2.6);
  opacity: .85;
  -webkit-mask-image:
    radial-gradient(ellipse 55% 45% at 50% 50%, #000 30%, transparent),
    radial-gradient(ellipse 55% 50% at 50% 50%, #000 30%, transparent);
  mask-image:
    radial-gradient(ellipse 55% 45% at 50% 50%, #000 30%, transparent),
    radial-gradient(ellipse 55% 50% at 50% 50%, #000 30%, transparent);
  -webkit-mask-size: 10% 3%, 14.2857% 4.5%; mask-size: 10% 3%, 14.2857% 4.5%;
  -webkit-mask-repeat: repeat; mask-repeat: repeat;
  -webkit-mask-composite: source-in; mask-composite: intersect;
  animation: fx-agua 30s linear infinite;
}
.card__fx--agua-sangre { filter: saturate(.6) brightness(2.2); opacity: .7; }
@keyframes fx-agua {
  from { -webkit-mask-position: 0 0, 100% 0; mask-position: 0 0, 100% 0; }
  to { -webkit-mask-position: 100% 0, 0 0; mask-position: 100% 0, 0 0; }
}
/* Escena por capas (PX2): la carta se monta con capas apiladas (cielo, nubes o estrellas,
   colinas, personaje y el diseño de la carta encima), así cada pieza se anima por separado sin
   tocar las demás. Las capas quietas son tipo "capa". Las nubes son una tira de dos cartas de
   ancho que se repite cada carta: al avanzar media tira el bucle no salta. El personaje flota. */
.card__fx--nubes {
  /* alto automático: la tira conserva su proporción y las nubes nunca se deforman, aunque la
     carta no tenga exactamente su proporción (layouts que la encogen en alto o en ancho) */
  right: auto; bottom: auto; width: 200%; height: auto; object-fit: initial; border-radius: 0;
  animation: fx-nubes 80s linear infinite;
}
/* Lluvia (nube de lluvia de la PX2 joven): la capa son solo las gotas; caen y se apagan. Dos
   capas desfasadas media vuelta para que la lluvia no se corte. */
.card__fx--lluvia, .card__fx--lluvia-2 {
  animation: fx-lluvia 1.1s linear infinite;
}
.card__fx--lluvia-2 { animation-delay: -.55s; }
@keyframes fx-lluvia {
  0% { transform: translateY(-3cqw); opacity: 0; }
  25% { opacity: 1; }
  100% { transform: translateY(9cqw); opacity: 0; }
}
@keyframes fx-nubes {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
.card__fx--flotar {
  animation: fx-flotar 3.4s ease-in-out infinite alternate;
}
@keyframes fx-flotar {
  from { transform: translateY(0); }
  to { transform: translateY(-2.2cqw); }
}
/* Luna (PX1): la capa es un resplandor ancho y difuminado alrededor de la luna (frío, en la luna de
   la joven y en la Estrella de la Muerte de la mayor). Brilla siempre: solo respira un poco, muy despacio, para
   que se note vivo sin parecer un foco que se enciende y se apaga. */
.card__fx--luna-halo {
  mix-blend-mode: screen;
  opacity: .7;
  animation: fx-luna-halo 9s ease-in-out infinite;
}
@keyframes fx-luna-halo {
  0%, 100% { opacity: .6; }
  50% { opacity: .8; }
}
/* Estrellas (cielo de la PX1): tres capas con las estrellas repartidas al azar; cada una se
   enciende y se apaga con su propio ritmo, así nunca titilan todas a la vez. */
.card__fx--estrellas, .card__fx--estrellas-2, .card__fx--estrellas-3 {
  mix-blend-mode: screen;
  animation: fx-estrellas 3.1s ease-in-out infinite;
}
.card__fx--estrellas-2 { animation-duration: 4.3s; animation-delay: -1.7s; }
.card__fx--estrellas-3 { animation-duration: 2.6s; animation-delay: -.9s; }
@keyframes fx-estrellas {
  0%, 100% { opacity: .1; filter: none; }
  50% { opacity: 1; filter: brightness(1.4) drop-shadow(0 0 2px #fff) drop-shadow(0 0 5px #bcd4ff); }
}
/* Estrellas intensas (PX1): las mismas tres capas con su ritmo, algo más marcadas que las
   normales: se apagan más y al encenderse brillan con un halo blanco azulado. */
.card__fx--estrellas-intensas, .card__fx--estrellas-intensas-2, .card__fx--estrellas-intensas-3 {
  mix-blend-mode: screen;
  animation: fx-estrellas-intensas 2.8s ease-in-out infinite;
}
.card__fx--estrellas-intensas-2 { animation-duration: 3.7s; animation-delay: -1.5s; }
.card__fx--estrellas-intensas-3 { animation-duration: 2.2s; animation-delay: -.8s; }
@keyframes fx-estrellas-intensas {
  0%, 100% { opacity: .15; filter: none; }
  50% { opacity: 1; filter: brightness(1.5) drop-shadow(0 0 2px #fff) drop-shadow(0 0 6px #9cc2ff); }
}
/* Estrella fugaz (cielos de noche de la PX1 y la PX2 mayor): la capa es una sola estrella con su
   estela, al principio de su recorrido (cada cielo tiene el suyo, por una zona despejada). Cruza el cielo en diagonal (25°, como la estela) en menos de
   un segundo, se apaga y no vuelve a pasar hasta unos segundos después. */
.card__fx--estrella-fugaz {
  opacity: 0;
  animation: fx-estrella-fugaz 9s linear infinite;
  animation-delay: 1.5s;
}
@keyframes fx-estrella-fugaz {
  0% { transform: translate(0, 0); opacity: 0; animation-timing-function: ease-in; }
  1.5% { opacity: 1; }
  7% { opacity: 1; }
  10% { transform: translate(60cqw, 28cqw); opacity: 0; }
  100% { transform: translate(60cqw, 28cqw); opacity: 0; }
}
/* Rayos (nube de lluvia de la PX2 joven): dos rayos de formas distintas, cada uno con su
   ritmo (7,3 s y 11,9 s), así que caen a destiempo y el patrón no se repite hasta pasado minuto
   y medio: parece aleatorio. Cada caída es un fogonazo con un parpadeo, como un rayo de verdad. */
.card__fx--rayo, .card__fx--rayo-2 {
  opacity: 0;
  animation: fx-rayo 7.3s linear infinite;
}
.card__fx--rayo-2 { animation-duration: 11.9s; animation-delay: -6s; }
@keyframes fx-rayo {
  0%, 88% { opacity: 0; }
  88.6% { opacity: 1; }
  89.6% { opacity: .15; }
  90.2% { opacity: 1; }
  92.5% { opacity: 0; }
  100% { opacity: 0; }
}
/* Iridiscente (puntos de los monstruos de la PX4): la capa lleva solo los puntos, ya pintados
   con un arcoíris pastel en diagonal (cada punto de un tono). El giro de tono los hace pasar por
   todos los colores, como una pompa de jabón, y laten con un halo suave. */
.card__fx--iridiscente {
  animation: fx-iridiscente 9s linear infinite;
}
@keyframes fx-iridiscente {
  0% { filter: hue-rotate(0deg) brightness(1) drop-shadow(0 0 2px rgba(255, 255, 255, .5)); }
  25% { filter: hue-rotate(90deg) brightness(1.15) drop-shadow(0 0 5px rgba(255, 255, 255, .7)); }
  50% { filter: hue-rotate(180deg) brightness(1) drop-shadow(0 0 2px rgba(255, 255, 255, .5)); }
  75% { filter: hue-rotate(270deg) brightness(1.15) drop-shadow(0 0 5px rgba(255, 255, 255, .7)); }
  100% { filter: hue-rotate(360deg) brightness(1) drop-shadow(0 0 2px rgba(255, 255, 255, .5)); }
}
/* Humo (arma de la PX4 mayor): la capa son unas hebras de humo que salen de la boca del arma
   (67.6 % 48.7 % de la carta). Lo que se ve lo marca un óvalo de máscara de borde muy suave que
   sube por la carta (mide 2 cartas de alto: con mask-position y = p su centro queda a y = 100 % − p
   de la carta): sale del cañón, lleva el humo hacia arriba y lo deja deshacerse por arriba en
   curva, nunca con un corte recto. Va semitransparente para que el humo sea un velo, no un trazo.
   humo-2 es otra forma de hebras, desfasada media vuelta. */
.card__fx--humo, .card__fx--humo-2 {
  transform-origin: 67.6% 48.7%;
  -webkit-mask-image: radial-gradient(ellipse 20% 11% at 71% 50%, #000 15%, rgba(0, 0, 0, .5) 55%, transparent 100%);
  mask-image: radial-gradient(ellipse 20% 11% at 71% 50%, #000 15%, rgba(0, 0, 0, .5) 55%, transparent 100%);
  -webkit-mask-size: 100% 200%; mask-size: 100% 200%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: 0 45%; mask-position: 0 45%;
  opacity: 0;
  animation: fx-humo 5.6s linear infinite;
}
.card__fx--humo-2 { animation-delay: -2.8s; }
@keyframes fx-humo {
  0% { -webkit-mask-position: 0 46%; mask-position: 0 46%; transform: scale(.85); filter: blur(0); opacity: 0; }
  15% { opacity: .6; }
  60% { opacity: .5; }
  100% { -webkit-mask-position: 0 92%; mask-position: 0 92%; transform: translateY(-6%) scale(1.25) rotate(4deg); filter: blur(4px); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .card__fx--humo { -webkit-mask-image: none; mask-image: none; opacity: .45; }
  .card__fx--humo-2 { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .card__fx { animation: none !important; }
  .card__fx--estrella-fugaz, .card__fx--rayo, .card__fx--rayo-2 { display: none; }
}
.card--rara .card__name { color: var(--gold); }
.card--infrecuente { border-color: rgba(120, 180, 255, .55); }
.card--rival { border-color: rgba(255, 61, 92, .55); }
.card--rival .card__art-inner { border-color: rgba(255, 61, 92, .5); }
.card--rival .card__year { background: var(--blood); color: #fff; }
.card--rival .card__art-initial { color: rgba(255, 61, 92, .22); }

.card__head { display: flex; align-items: center; justify-content: space-between; gap: 2cqw; padding: 1cqw 1.5cqw 1.5cqw; position: relative; z-index: 6; }
.card__name { font-weight: 700; font-size: clamp(12.5px, 6cqw, 22px); line-height: 1.08; }
.card__year { flex: 0 0 auto; font-size: clamp(9px, 3.8cqw, 14px); font-weight: 700; color: #0b0718; background: var(--candle); padding: .3cqw 1.8cqw; border-radius: 1.4cqw; }

.card__art {
  position: relative; flex: 1 1 auto; margin: 0 1.5cqw 5cqw; z-index: 2;
}
.card__art-inner {
  position: absolute; inset: 0; overflow: hidden;
  border-radius: 1.5cqw; border: max(1px, .5cqw) solid rgba(78, 232, 255, .5);
  background: repeating-linear-gradient(115deg, rgba(78, 232, 255, .06) 0 2px, transparent 2px 6px), linear-gradient(160deg, #241344, #150a28);
  display: flex; align-items: center; justify-content: center;
}
.card__art-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* El recorte del personaje va CONTENIDO dentro del marco, con 5px de margen en los
   cuatro lados (antes se desbordaba arriba/abajo a propósito; con recortes de aspecto
   muy variado -PX8 salió casi cuadrado y se veía enorme frente al resto- contenerlo es
   lo que garantiza el mismo tamaño de "hueco" para cualquier personaje, sea cual sea su
   proporción). object-fit:contain hace el trabajo: encaja el ancho O el alto (el que
   toque según su forma) sin recortar nada del personaje. object-position "bottom" lo
   ancla abajo, como ya hacía el desbordamiento anterior. width/height explícitos son
   necesarios porque <img> es un elemento reemplazado: con solo left/right/top/bottom
   (o inset) no se estira solo a ese hueco. La cabecera (nombre) y el medallón de PF
   van por encima (z-index). */
.card__pj {
  position: absolute; left: 5px; top: 5px; right: 5px; bottom: 5px;
  width: calc(100% - 10px); height: calc(100% - 10px);
  object-fit: contain; object-position: center bottom;
  z-index: 3; pointer-events: none;
  filter: drop-shadow(0 2cqw 1.6cqw rgba(0, 0, 0, .55));
}
.card__art-initial { font-weight: 900; font-size: 46cqw; color: rgba(78, 232, 255, .2); line-height: 1; }
.card__mag {
  position: absolute; top: 0; left: 0; max-width: 68%;
  background: rgba(11, 7, 24, .82); border-bottom-right-radius: 1.4cqw; padding: 1cqw 1.6cqw;
  font-size: clamp(7px, 2.9cqw, 11px); font-weight: 700; letter-spacing: .02em; line-height: 1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; z-index: 3;
}
.card__mag--img { background: none; padding: 1.4cqw; max-width: 34%; height: auto; }
.card__vida {
  /* Centrada y a caballo del borde inferior de .card__art: la mitad de arriba
     queda dentro de la imagen, la mitad de abajo sobresale hacia el hueco
     antes de .card__stats. .card__art tiene overflow visible (solo
     .card__art-inner lo recorta), así que el desbordamiento no se corta. */
  position: absolute; left: 50%; bottom: 0; transform: translate(-50%, 50%);
  display: inline-flex; align-items: baseline; gap: 1.6cqw;
  background: rgba(11, 7, 24, .85); border: max(1px, .5cqw) solid var(--blood); border-radius: 999px;
  padding: 1cqw 2.4cqw; line-height: 1; color: #fff; z-index: 5; white-space: nowrap;
}
.card__vida-k {
  font-size: clamp(10px, 5.1cqw, 19px); font-weight: 700; text-transform: uppercase;
  letter-spacing: .01em; color: rgba(255, 255, 255, .82);
}
.card__vida-n { flex: 0 0 auto; font-weight: 900; font-size: clamp(10px, 5.1cqw, 19px); }

.card__stats { display: flex; align-items: flex-start; justify-content: space-around; gap: 1cqw; padding: 3cqw .5cqw 1.5cqw; z-index: 2; }
.pstat { display: flex; flex-direction: column; align-items: center; gap: .8cqw; flex: 1 1 0; min-width: 0; }
/* Las 4 gemas de stat usan la receta "ficha de cristal" (probada primero en
   Gamer, ahora en las 4): círculo con degradado radial CENTRADO, claro en el
   centro y oscuro justo al filo visible (circle farthest-side — con el
   farthest-corner por defecto el tono oscuro cae fuera del recorte redondo y
   nunca se ve oscuro de verdad en el borde); número negro puro con un filo
   fino cálido para despegarlo del color; una "lente" de brillo (::before,
   elipse blanca al 25%, recortada al círculo con overflow:hidden) que pinta
   sola detrás del número porque .pstat__n es flex (los flex items se tratan
   como z-index:auto y pintan en orden de árbol, después del ::before). */
.pstat__n {
  position: relative;
  overflow: hidden;
  width: clamp(21px, 15cqw, 43px); height: clamp(21px, 15cqw, 43px); border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: max(1.75px, 1cqw) solid rgba(255, 255, 255, .92); /* línea blanca exterior */
  box-shadow:
    inset 0 -2cqw 2.6cqw rgba(0, 0, 0, .38),
    inset 0 1.4cqw 1.8cqw rgba(255, 255, 255, .4);
  font-weight: 900; font-size: clamp(12px, 9.3cqw, 26px); line-height: 1;
  color: #000;
  text-shadow: 0 1px 1px rgba(255, 255, 255, .35);
  -webkit-text-stroke: max(.3px, .15cqw) rgba(255, 214, 163, .55); paint-order: stroke fill;
}
.pstat__n::before {
  content: "";
  position: absolute; top: -12%; left: 14%;
  width: 72%; height: 46%;
  background: #fff; opacity: .25; border-radius: 50%;
  transform: rotate(-6deg);
  pointer-events: none;
}
.pstat--fue .pstat__n { background: radial-gradient(circle farthest-side at 50% 50%, #5bc8f5 0%, #0d4a66 100%); }
.pstat--tra .pstat__n { background: radial-gradient(circle farthest-side at 50% 50%, #fff44f 0%, #d98c00 100%); }
.pstat--red .pstat__n { background: radial-gradient(circle farthest-side at 50% 50%, #9be88a 0%, #1f5c1a 100%); }
.pstat--gam .pstat__n { background: radial-gradient(circle farthest-side at 50% 50%, #ff3b30 0%, #990000 100%); }
.pstat--pick .pstat__n { outline: 3px solid var(--candle); outline-offset: 2px; }
.pstat__k { font-size: clamp(8px, 2.9cqw, 12px); font-weight: 700; text-transform: uppercase; color: rgba(230, 217, 184, .9); white-space: nowrap; letter-spacing: -.01em; }

.card__fine { margin: 1.5cqw -8px -8px; padding: 4px 8px; background: rgba(10, 6, 24, .5); text-align: center; font-size: clamp(6px, 2.6cqw, 9px); color: rgba(230, 217, 184, .55); line-height: 1.1; z-index: 2; }

.card__sheen { display: none; }
.card.is-full { border-width: 3px; }
.card__illustrator {
  text-align: right; padding: 1cqw 1.5cqw 0; line-height: 1.15;
  font-size: clamp(7px, 2.5cqw, 10px); font-style: italic; color: rgba(230, 217, 184, .68); z-index: 2;
}
/* La rareza NO lleva chapa de texto: se lee sola por el color del marco
   (.card--rara oro, .card--infrecuente azul) y, en ficha completa, por el
   brillo holo — que solo se enciende si la carta es especial. */
.card--infrecuente.is-full .card__sheen {
  display: block; position: absolute; inset: 0; z-index: 4; pointer-events: none;
  background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, .12) 48%, rgba(120, 220, 255, .1) 54%, transparent 66%);
  mix-blend-mode: overlay;
}

/* ============================================================
   CARTA RARA (holo) — canto iridiscente, fondo holográfico prismático
   que se mueve SOLO al inclinar la carta (--tilt-x/--tilt-y, public/js/app.js).
   Personaje centrado resaltado; nombre + año + stats en la posición normal.
   ============================================================ */
.card--rara {
  justify-content: space-between;
  /* Marco ANCHO tipo carta Pokémon. Los dos intentos anteriores (::before
     enmascarado, luego border-image) o dejaban asomar un anillo gris debajo
     (la máscara no recorta igual en todos los navegadores) o perdían las
     esquinas redondeadas (border-image no respeta border-radius).
     Solución robusta: el arcoíris es el FONDO propio de la carta, pintado
     hasta el borde (background-clip: border-box) con el borde en transparente.
     .card__bleed (el arte, hijo, opaco) tapa todo MENOS el aro del borde, que
     es donde se ve este fondo. Sin capas extra, sin máscaras: no puede haber
     nada "debajo" asomando, y el redondeado es el normal de cualquier fondo. */
  border: 11px solid transparent;
  border-radius: 13px;
  /* .card.is-full pone border-width: 3px (para las cartas normales, cuyo
     borde es fino); esa regla tiene más especificidad (dos clases) que este
     border de aquí y se lo comía en la ficha grande, dejando el marco ancho
     reducido a un filo de 3px. Se restaura el ancho aquí, en una regla con
     la misma especificidad (.card--rara.is-full) que sí gana por ir después
     en el CSS. */
  padding: 6px 5px;
  background-origin: border-box; background-clip: border-box;
  background-repeat: repeat;
  background-size: 300% 300%;
  background-position: calc(50% + var(--tilt-x, 0) * 45%) calc(50% + var(--tilt-y, 0) * 45%);
  background-image:
    repeating-linear-gradient(115deg,
      #dde1e8 0%, #b8bdc7 8%, #ced3da 16%,
      #949aa6 24%, #dde1e8 32%, #7a808f 40%, #dde1e8 56%);
  transition: background-position .12s ease-out;
  box-shadow:
    inset 0 0 0 1px rgba(24, 18, 40, .55),   /* filo oscuro donde el marco toca el arte */
    0 0 15px rgba(180, 185, 195, .28),
    0 12px 22px -12px rgba(0, 0, 0, .85);
}
.card--rara.is-full { border-width: 11px; }

/* Arte a sangre + arcoíris prismático mezclado en la MISMA capa (background-blend-mode,
   no mix-blend-mode: así no rompe la inclinación 3D de la carta). Las bandas se
   desplazan con --tilt-x/--tilt-y (0 en reposo), que fija app.js al mover la carta. */
.card--rara .card__bleed {
  /* Una sola dirección de bandas (115deg) — con dos capas a ángulos distintos
     (antes 58deg + 115deg) se formaba un enrejado/rombos: "se cruzan". */
  position: absolute; inset: 0; border-radius: 4px; z-index: 0;
  background-color: #10131f;
  background-image:
    repeating-linear-gradient(115deg,
      rgba(255, 0, 128, .45) 0%, rgba(255, 170, 0, .45) 3.5%,
      rgba(60, 255, 140, .45) 7%, rgba(0, 180, 255, .45) 10.5%,
      rgba(180, 70, 255, .45) 14%, rgba(255, 0, 128, .45) 17.5%),
    var(--bleed, none);
  background-repeat: repeat, no-repeat;
  background-size: 260% 260%, cover;
  background-position:
    calc(50% + var(--tilt-x, 0) * 72%) calc(50% + var(--tilt-y, 0) * 72%),
    center;
  background-blend-mode: soft-light, normal;
  transition: background-position .12s ease-out;
}

/* Capa reflectante sobre TODA la ilustración, personaje incluido (z-index 3,
   por encima de él): las mismas franjas diagonales de arcoíris que
   .card__bleed (mismo ángulo 115deg, misma escala 260%/72% de tilt), pero
   en su propia capa translúcida, para que el "sheen" cruce la carta entera
   de una sola vez -como en una carta Pokémon holo real- en lugar de manchas
   de color sueltas (el efecto "aurora" anterior parecía un degradado con
   blobs, no un holograma). background-blend-mode "normal" (sin sumar luz)
   evita que las franjas se disparen a blanco al solaparse; mix-blend-mode
   NO se usa aquí porque rompe la inclinación 3D de la carta (mezcla con lo
   que hay detrás en la pila). */
.card--rara .card__holo {
  position: absolute; inset: -10%; z-index: 3; pointer-events: none; border-radius: 4px;
  opacity: .3; transition: background-position .12s ease-out, opacity .2s;
  background-repeat: repeat;
  background-size: 260% 260%;
  background-position: calc(50% + var(--tilt-x, 0) * 72%) calc(50% + var(--tilt-y, 0) * 72%);
  background-image:
    repeating-linear-gradient(115deg,
      rgba(255, 0, 128, .4) 0%, rgba(255, 170, 0, .4) 3.5%,
      rgba(60, 255, 140, .4) 7%, rgba(0, 180, 255, .4) 10.5%,
      rgba(180, 70, 255, .4) 14%, rgba(255, 0, 128, .4) 17.5%);
  background-blend-mode: normal;
  /* difumina del todo el borde entre bandas de color: sin esto se veían
     "líneas" marcadas y poco realistas entre un color y el siguiente.
     inset: -10% + el blur en los bordes lo recorta .card (overflow: hidden). */
  filter: blur(10px);
}
.card--rara:hover .card__holo,
.card--rara:active .card__holo { opacity: .45; }

/* Columna izquierda de la cabecera: nombre y, colgando de él, el logo de la
   revista. El gap es el MISMO valor que el de .card__corner (PF/año), que es lo
   que se pidió: márgenes iguales. Al vivir el logo dentro de esta columna, su
   separación depende solo del nombre — no de lo alta que sea la columna de
   chips de la derecha. */
.card--rara .card__head-left {
  display: flex; flex-direction: column; align-items: flex-start; gap: .6cqw;
  min-width: 0;
}
.card--rara .card__mag-rara {
  /* max-width en cqw, no en %: cqw se resuelve contra .card (que es el
     container-type) y no contra la columna que lo envuelve, así que el tamaño
     del logo no cambia por estar anidado. position:relative + z-index:5 (por
     encima del personaje, z-index:2) para que el personaje no lo tape. */
  display: block; position: relative; z-index: 5;
  max-width: 26cqw; height: auto;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .65));
}
.card--rara .card__pj--rare {
  /* A sangre pero SIN pasarse: 104%/108% (intento anterior) desbordaba tanto que
     tapaba el logo de la revista pese al z-index — con margen real de vuelta. */
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  height: 92%; width: auto; max-width: 96%;
  z-index: 2; pointer-events: none;
  /* sombra proyectada hacia abajo (no ambiental/centrada) para que el
     personaje parezca elevado sobre la carta, no pegado al fondo. */
  filter:
    drop-shadow(0 0 4px rgba(255, 255, 255, .6))
    drop-shadow(0 0 13px rgba(130, 205, 255, .5))
    drop-shadow(0 8px 8px rgba(0, 0, 0, .5))
    drop-shadow(0 16px 14px rgba(0, 0, 0, .35));
}
.card--rara .card__head {
  /* Sin sombreado de fondo: sobre el patrón cuadriculado del holo se notaba
     mucho el corte recto del degradado. La legibilidad la da el text-shadow.
     align-items:flex-start (en vez del center heredado): con dos chips
     apilados en la esquina, centrarlos contra la única línea del nombre lo
     desplazaría hacia abajo — así el de arriba queda a la altura del nombre. */
  position: relative; z-index: 4; align-items: flex-start;
}
.card--rara .card__name { color: #fff; text-shadow: 0 1px 5px rgba(0, 0, 0, .9), 0 0 2px rgba(0, 0, 0, .8); }
/* Esquina superior derecha de la cabecera: PF arriba, año debajo — sustituye al
   .card__vida flotante de antes (se solapaba con las stats y con la habilidad;
   aquí, en la cabecera, no compite por espacio con nada). */
.card--rara .card__corner {
  display: flex; flex-direction: column; align-items: flex-end; gap: .6cqw;
}
.card__pf-chip {
  /* Mismo tamaño/padding/radio que .card__year (justo debajo, en la misma
     esquina) — solo cambia el color de fondo para distinguirla a golpe de vista. */
  flex: 0 0 auto; font-size: clamp(9px, 3.8cqw, 14px); font-weight: 700;
  color: #0b0718; background: var(--blood); padding: .3cqw 1.8cqw; border-radius: 1.4cqw;
  white-space: nowrap;
}
/* El bloque de stats se empuja al fondo de la carta. */
.card--rara .card__bottom {
  position: relative; z-index: 4;
  margin-top: auto;
}
.card--rara .card__stats {
  margin: 0 -5px 0; padding: 1.5cqw 2px 1.5cqw; gap: .5cqw;
}

.card--rara .pstat__k { color: #fff; text-shadow: 0 1px 3px rgba(0, 0, 0, .95); }

/* La iridiscencia ya va integrada en el gradiente del marco (::before, arriba) —
   un solo elemento de marco, sin capas extra que puedan desalinearse. */


/* ---------- pantallas de "te toca esto" (starter kit, sobre) ---------- */
.reveal-cards { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; }
.explain {
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px; padding: 14px 16px;
  font-size: .88rem; color: var(--ink-dim); line-height: 1.55;
}
.explain b, .explain strong { color: var(--ink); }

/* línea informativa que se despliega al pulsarla (nativo <details>) */
.info-drop { border: 1px solid var(--line); border-radius: 10px; background: var(--surface); overflow: hidden; }
.info-drop > summary {
  list-style: none; cursor: pointer; padding: 12px 14px;
  display: flex; align-items: center; gap: 8px;
  font-size: .84rem; font-weight: 600; color: var(--ink-dim);
}
.info-drop > summary::-webkit-details-marker { display: none; }
.info-drop > summary svg { width: 17px; height: 17px; flex: 0 0 auto; color: var(--candle); }
.info-drop > summary b { color: var(--candle); }
.info-drop > summary::after { content: "▾"; margin-left: auto; color: var(--ink-faint); }
.info-drop[open] > summary { border-bottom: 1px solid var(--line-soft); }
.info-drop[open] > summary::after { content: "▴"; }
.info-drop__body {
  padding: 12px 14px; font-size: .85rem; color: var(--ink-dim); line-height: 1.55;
}
.info-drop__body strong { color: var(--ink); }
.pick-caption { font-size: .78rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-faint); text-align: center; }

/* etiqueta junto a la carta (consola-swap, starter kit) */
.opt { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.opt > span, .opt__tag {
  font-size: .74rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-dim);
}
.opt__tag { display: block; margin-bottom: 8px; text-align: center; }

/* ---------- ficha horizontal (starter kit, sobre) — sustituye al carrusel swipe ---------- */
.ficha-list { display: flex; flex-direction: column; gap: 8px; width: 100%; }
.ficha {
  display: grid; grid-template-columns: 80px 1fr; align-items: center; gap: 12px;
  width: 100%; padding: 11px 13px; text-align: left; color: var(--ink);
  background: linear-gradient(160deg, var(--wood), var(--wood-2));
  border: 2px solid var(--line); border-radius: 12px;
  transition: border-color .12s, box-shadow .12s, opacity .12s;
}
button.ficha { font: inherit; cursor: pointer; }
.ficha--pickable { grid-template-columns: 80px 1fr auto; }
.ficha--dropped { opacity: .4; }
/* Ranura sin nada (build): la fila se ve, pero apagada y con el borde punteado. */
.ficha--vacia { opacity: .4; border-style: dashed; }
.ficha--vacia .ficha__art { background: none; border-style: dashed; font-size: 1.4rem; color: var(--ink-faint); }
.ficha--picked { border-color: var(--candle); box-shadow: 0 0 0 1px var(--candle), 0 0 14px -4px rgba(78, 232, 255, .5); }
.ficha--consola { border-color: rgba(78, 232, 255, .4); }
.ficha__art {
  width: 80px; height: 80px; border-radius: 9px; overflow: hidden; font-size: 1.6rem;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255, 210, 63, .12); border: 1px solid rgba(255, 210, 63, .3);
}
.ficha--consola .ficha__art {
  background: rgba(78, 232, 255, .1); border-color: rgba(78, 232, 255, .3);
}
.ficha__art img { width: 100%; height: 100%; object-fit: contain; }
.ficha__body { min-width: 0; }
.ficha__label { display: block; font-size: .62rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 2px; }
.ficha__name { display: block; font-weight: 800; font-size: .92rem; line-height: 1.2; }
.ficha__tag {
  display: inline-block; margin-left: 6px; vertical-align: middle; padding: 1px 7px; border-radius: 999px;
  font-size: .6rem; font-weight: 800; letter-spacing: .06em; color: #052733; background: var(--candle);
}
.ficha__desc { display: block; margin-top: 3px; font-size: .76rem; color: var(--ink-dim); line-height: 1.4; }
.ficha__eff {
  display: inline-block; margin-top: 5px; padding: 2px 10px; border-radius: 999px;
  font-size: .74rem; font-weight: 800; color: #1a0f00; background: var(--gold); border: 1px solid #140a22;
}
.ficha--consola .ficha__eff { background: var(--candle); color: #052733; }
.ficha__check {
  width: 24px; height: 24px; border-radius: 999px; display: flex; align-items: center; justify-content: center;
  font-size: .8rem; font-weight: 900; border: 2px solid var(--ink-faint); color: transparent;
}
.ficha--picked .ficha__check { border-color: var(--candle); background: var(--candle); color: #052733; }

/* resumen de stats sumadas (sobre: combinación de 3 elegida) */
.fx-sum {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; width: 100%;
  padding-top: 8px; border-top: 1px solid var(--line); margin-top: 4px;
}
.fx-sum__pill {
  display: inline-flex; align-items: baseline; gap: 4px; padding: 4px 10px; border-radius: 999px;
  font-size: .72rem; font-weight: 700; background: var(--surface); border: 1px solid var(--line); color: var(--ink-dim);
}
.fx-sum__pill b { font-size: .82rem; font-weight: 900; color: var(--ink); font-variant-numeric: tabular-nums; }
.fx-sum__pill--zero { opacity: .45; }
.fx-sum__pill--fue b { color: var(--stat-fue); }
.fx-sum__pill--tra b { color: var(--stat-tra); }
.fx-sum__pill--red b { color: var(--stat-red); }
.fx-sum__pill--gam b { color: var(--stat-gam); }
.fx-sum__pill--mult { background: rgba(78, 232, 255, .12); border-color: rgba(78, 232, 255, .4); }
.fx-sum__pill--mult b { color: var(--candle); }
.fx-sum__pill--pf { background: rgba(255, 61, 92, .12); border-color: rgba(255, 61, 92, .4); }
.fx-sum__pill--pf b { color: var(--blood); }
/* Stat que cambiaría si eliges este maletín (pantalla de abrir sobre): mismo dorado que
   usa el resto del juego para "esto es especial/va a pasar algo". */
.fx-sum__pill--changed { border-color: var(--gold); box-shadow: 0 0 0 1px var(--gold); }
.fx-sum__pill--changed b { color: var(--gold); }

/* ---------- moneda ---------- */
.coin-choices { display: flex; gap: 24px; justify-content: center; }
.coin-choice {
  background: none; border: none; padding: 0; cursor: pointer; color: var(--ink);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  font: inherit; font-weight: 800; font-size: .95rem; letter-spacing: .02em; text-transform: uppercase;
}
/* las dos monedas se ven iguales pase lo que pase con su fondo: recorte circular */
.coin-choice img, .coin-result {
  width: 104px; height: 104px; border-radius: 50%; object-fit: cover;
  background: radial-gradient(circle at 35% 30%, #5a5f66, #2b2f35);
  border: 3px solid #3a3f47;
  box-shadow: 0 6px 16px -6px rgba(0, 0, 0, .7), inset 0 0 12px rgba(0, 0, 0, .4);
}
.coin-choice:active img { transform: translateY(1px); }
.coin-result { width: 128px; height: 128px; }
.big-verdict { font-family: var(--f-display); font-size: clamp(1.3rem, 6vw, 1.7rem); }
.big-verdict--win { color: var(--green); }
.big-verdict--lose { color: var(--blood); }

/* --- Logros (pantalla de logros y aviso en el resultado) ---
   Una fila por logro, con su icono. Los que no se tienen van en gris y con el requisito a la
   vista: la pantalla se lee como una lista de cosas que hacer, no como un museo. */
.logro-list { list-style: none; margin: 0 auto; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.logro-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: 10px;
  background: var(--surface); border: 1px solid var(--line);
}
.logro-row__ico { flex: 0 0 auto; font-size: 1.4rem; line-height: 1; filter: grayscale(1) opacity(.45); }
.logro-row__txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.logro-row__name { font-weight: 800; font-size: .9rem; color: var(--ink-faint); }
.logro-row__req { font-size: .76rem; line-height: 1.35; color: var(--ink-faint); }
.logro-row--on { border-color: rgba(255, 210, 63, .45); background: linear-gradient(160deg, rgba(255, 210, 63, .10), var(--surface)); }
.logro-row--on .logro-row__ico { filter: none; }
.logro-row--on .logro-row__name { color: var(--gold); }
.logro-row--on .logro-row__req { color: var(--ink-dim); }
.logro-count { font-size: .82rem; color: var(--ink-dim); text-align: center; }
.logro-count b { color: var(--candle); }

/* ---------- tutorial ---------- */
.tut { display: flex; flex-direction: column; gap: 16px; }
.tut__item { background: var(--surface); border: 1px solid var(--line); border-radius: 10px; padding: 14px 16px; }
.tut__n { font-size: .72rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--candle); margin: 0 0 4px; }
.tut__t { font-size: .9rem; color: var(--ink-dim); line-height: 1.55; margin: 0; }
.tut__t strong { color: var(--ink); }
/* Punto de reglas con icono (x-game.rule): tutorial y manual. */
.rule { display: flex; align-items: flex-start; gap: 12px; }
.rule__ico {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: 9px; margin-top: 1px;
  display: flex; align-items: center; justify-content: center; font-size: 1.15rem;
  background: rgba(255, 210, 63, .12); border: 1px solid rgba(255, 210, 63, .3);
}
.rule__ico img { width: 100%; height: 100%; object-fit: contain; padding: 6px; }
.rule__body { min-width: 0; }
.tut__more { align-self: center; font-size: .85rem; font-weight: 700; text-align: center; }

/* ---------- ranking (pantalla completa) ---------- */
.rank-full { display: flex; flex-direction: column; }
.rank-full .rank__row { padding: 11px 4px; }

/* ============================================================
   Sensación de juego (game feel) — ver public/js/fx.js
   Todo esto es decorativo: con prefers-reduced-motion se apaga entero (al final).
   ============================================================ */

/* Transición entre pantallas: al cambiar de página el navegador funde y escala una
   pantalla sobre la otra en vez de "parpadear" a blanco. Es la View Transitions API
   entre documentos (Chrome/Edge/Safari recientes); donde no existe, se ignora y la
   navegación es la de siempre. No retrasa nada: el DOM nuevo ya está cargado. */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: kor-screen-out .16s ease-in both; }
::view-transition-new(root) { animation: kor-screen-in .28s cubic-bezier(.2, .8, .2, 1) both; }
@keyframes kor-screen-out { to { opacity: 0; transform: scale(.97); filter: brightness(1.6); } }
@keyframes kor-screen-in { from { opacity: 0; transform: scale(1.04); } }

/* Partículas: un canvas a pantalla completa, por encima de todo y transparente al dedo. */
.fx-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 9999;
}

/* Pantalla "de recreativa" (combate y portada): luz ambiental suave que cambia despacio
   (dos focos de color que se funden uno en otro) y un viñeteado, en toda la pantalla
   —cabecera y pie incluidos, que aquí van sin fondo propio— para que no parezca una web
   con barras. Solo se animan opacity y transform (los compone la GPU, no repinta). Van en
   pseudo-elementos con z-index:-1 dentro de un isolation:isolate: detrás de todo. */
.screen--arcade {
  position: relative; isolation: isolate;
  background: radial-gradient(ellipse 90% 75% at 50% 45%, #1d1238 0%, #120a24 60%, #07040f 100%);
}
.screen--arcade::before, .screen--arcade::after {
  content: ""; position: absolute; inset: -25%; z-index: -1; pointer-events: none;
}
.screen--arcade::before {
  background:
    radial-gradient(32% 26% at 22% 30%, rgba(78, 232, 255, .22), transparent 70%),
    radial-gradient(36% 30% at 80% 72%, rgba(255, 61, 214, .18), transparent 70%);
  animation: ambient-a 16s ease-in-out infinite alternate;
}
.screen--arcade::after {
  background:
    radial-gradient(34% 28% at 75% 25%, rgba(255, 170, 60, .16), transparent 70%),
    radial-gradient(30% 26% at 25% 78%, rgba(120, 90, 255, .20), transparent 70%);
  opacity: 0;
  animation: ambient-b 16s ease-in-out infinite alternate;
}
@keyframes ambient-a { from { transform: translate(-3%, -2%) scale(1); opacity: 1; } to { transform: translate(3%, 2%) scale(1.08); opacity: .35; } }
@keyframes ambient-b { from { transform: translate(2%, 2%) scale(1.06); opacity: 0; } to { transform: translate(-3%, -1%) scale(1); opacity: 1; } }
.screen--arcade .screen__top,
.screen--arcade .screen__foot { background: transparent; border: 0; backdrop-filter: none; }

/* ---------- portada como pantalla de título (game/home) ----------
   Jugador 1 arriba, el título del juego, marcadores de HUD, el reto del día como misión,
   el ranking como tabla de récords de recreativa y un menú. Todo en .screen--menu para no
   tocar el ranking completo ni el reto, que reutilizan .rank. */
.menu-player { display: flex; flex-direction: column; min-width: 0; flex: 1; line-height: 1.2; }
.screen--menu .screen__body { gap: 14px; padding-top: 10px; }
.menu-player__k { font-family: var(--f-pixel); font-size: .45rem; letter-spacing: .1em; color: var(--candle); }
.menu-player__name { font-weight: 800; font-size: .95rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.screen--menu .avatar { border-radius: 2px; box-shadow: 0 0 0 2px #000; }

.menu-title { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.menu-title .brand { font-size: .7rem; }
.menu-title__tag { margin: 2px 0 0; font-size: .72rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-faint); }
.menu-title__main {
  margin: 0; font-family: var(--f-display); font-weight: 400; text-align: center;
  font-size: clamp(1.5rem, 8vw, 2.1rem); line-height: 1; color: var(--gold);
  -webkit-text-stroke: 2px #120e1f; text-shadow: 0 4px 0 var(--blood), 0 0 26px rgba(255, 210, 63, .45);
}

.screen--menu .tiles { gap: 10px; }
.screen--menu .tile {
  border-radius: 2px; border: 2px solid #3b2d6b; background: rgba(8, 5, 18, .72);
  box-shadow: 0 0 0 2px #000; padding: 7px 4px 6px;
}
.screen--menu .tile b { font-family: var(--f-display); font-weight: 400; font-size: 1.2rem; color: var(--gold); text-shadow: 2px 2px 0 #000; }
.screen--menu .tile--fire b { color: #ff7a45; }
.screen--menu .tile > span { font-family: var(--f-pixel); font-size: .42rem; letter-spacing: .08em; color: var(--ink-dim); }

.screen--menu .resume { border-radius: 2px; border: 2px solid var(--candle); box-shadow: 0 0 0 2px #000, 0 0 18px -4px rgba(78, 232, 255, .6); background: rgba(8, 5, 18, .78); }
.screen--menu .resume__title { font-family: var(--f-pixel); font-size: .58rem; letter-spacing: .06em; color: var(--candle); line-height: 1.6; }

.screen--menu .reto-card {
  border-radius: 2px; border: 2px solid var(--gold); background: linear-gradient(120deg, rgba(255, 210, 63, .14), rgba(8, 5, 18, .8) 60%);
  box-shadow: 0 0 0 2px #000, 0 0 20px -6px rgba(255, 210, 63, .6);
}
.screen--menu .reto-card { padding: 9px 12px; }
.reto-card__tag { font-family: var(--f-pixel); font-size: .42rem; letter-spacing: .1em; color: var(--gold); margin-bottom: 3px; }

/* Ranking como tabla de récords de recreativa. */
.screen--menu .rank { padding: 10px 14px; border-radius: 2px; border: 2px solid #3b2d6b; background: rgba(8, 5, 18, .72); box-shadow: 0 0 0 2px #000; }
.screen--menu .rank__label { font-family: var(--f-pixel); font-size: .55rem; text-transform: uppercase; letter-spacing: .1em; color: var(--gold); text-shadow: 2px 2px 0 #000; }
.screen--menu .rank__row { border-radius: 0; padding: 6px 4px; }
.screen--menu .rank__pos { font-family: var(--f-pixel); font-size: .5rem; width: 2.6em; color: var(--ink-dim); }
.screen--menu .rank__row:nth-child(1) .rank__pos { color: var(--gold); }
.screen--menu .rank__row:nth-child(2) .rank__pos { color: #cfd6e6; }
.screen--menu .rank__row:nth-child(3) .rank__pos { color: #e09a5c; }
.screen--menu .rank__av { border-radius: 2px; }
.screen--menu .rank__ventas { font-family: var(--f-pixel); font-size: .6rem; color: var(--gold); text-shadow: 1px 1px 0 #000; }
.screen--menu .rank__all { margin-top: 6px; font-family: var(--f-pixel); font-size: .45rem; letter-spacing: .06em; text-transform: uppercase; }

/* Menú: dos entradas de recreativa con su cursor ▶. */
.menu-links { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.menu-link {
  display: flex; align-items: center; gap: 8px; min-height: var(--tap); padding: 8px 10px;
  border-radius: 10px; border: 2px solid var(--line); background: linear-gradient(180deg, #2c1d52, #1e1338); box-shadow: 0 4px 0 #0b0716, inset 0 1px 0 rgba(255, 255, 255, .08);
  font-family: var(--f-display); font-size: .82rem; line-height: 1.1; letter-spacing: .04em; text-transform: uppercase; color: var(--ink); text-decoration: none;
  transition: transform .12s cubic-bezier(.3, 1.6, .5, 1), border-color .15s;
}
.menu-link::before { content: "▶"; color: var(--candle); font-size: .9em; }
.menu-link:active { transform: translateY(3px); box-shadow: 0 1px 0 #0b0716; border-color: var(--candle); }


/* Destello de impacto (KorFx.flash): fogonazo del color del golpe, muy breve. */
.fx-flash { position: fixed; inset: 0; z-index: 9998; pointer-events: none; opacity: 0; mix-blend-mode: screen; }
.fx-flash.play { animation: kor-flash .14s ease-out; }
@keyframes kor-flash { 0% { opacity: .45; } 100% { opacity: 0; } }

/* Botones con "peso": se hunden al pulsar y rebotan al soltar, como un botón de
   recreativa. Sustituye al translateY(1px) de antes, que apenas se notaba. */
.icon-btn { transition: transform .1s cubic-bezier(.3, 1.6, .5, 1), box-shadow .1s ease; }
.icon-btn:active { transform: translateY(2px); box-shadow: 0 1px 0 #0b0716, inset 0 1px 0 rgba(255, 255, 255, .08); }

/* El botón principal del pie respira (brillo que barre de lado a lado cada pocos
   segundos) para que siempre se sepa cuál es "la jugada". Solo el primario y solo
   habilitado: los fantasma y los deshabilitados se quedan quietos. */
.screen__foot .btn--wide:not(.btn--ghost):not(:disabled) { position: relative; overflow: hidden; }
.screen__foot .btn--wide:not(.btn--ghost):not(:disabled)::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, .55) 50%, transparent 70%);
  transform: translateX(-120%);
  animation: kor-shine 3.2s ease-in-out 1s infinite;
  pointer-events: none;
}
@keyframes kor-shine { 0%, 70% { transform: translateX(-120%); } 100% { transform: translateX(120%); } }

/* Entrada del contenido: los bloques del cuerpo suben en cascada al llegar a la
   pantalla. Solo los 8 primeros llevan retardo; el resto entra con el último.
   OJO: fill-mode backwards (no both) a propósito. Un transform que se queda "aplicado"
   al acabar convierte al bloque en contenedor de sus hijos position:fixed, y los modales
   de combate dejarían de cubrir la pantalla. Con backwards la animación deja de existir
   en cuanto termina. */
.screen__body > * { animation: kor-rise .38s cubic-bezier(.2, .8, .2, 1) backwards; }
.screen__body > :nth-child(2) { animation-delay: .05s; }
.screen__body > :nth-child(3) { animation-delay: .1s; }
.screen__body > :nth-child(4) { animation-delay: .15s; }
.screen__body > :nth-child(5) { animation-delay: .2s; }
.screen__body > :nth-child(6) { animation-delay: .25s; }
.screen__body > :nth-child(7) { animation-delay: .3s; }
.screen__body > :nth-child(n+8) { animation-delay: .35s; }
@keyframes kor-rise { from { opacity: 0; transform: translateY(14px); } }

/* Mapa: las paradas aparecen una a una y la casilla actual late como un marcador
   de "estás aquí" de videojuego. */
.route .stop { animation: kor-pop .34s cubic-bezier(.3, 1.5, .5, 1) backwards; }
.route .stop:nth-child(1) { animation-delay: .05s; }
.route .stop:nth-child(2) { animation-delay: .1s; }
.route .stop:nth-child(3) { animation-delay: .15s; }
.route .stop:nth-child(4) { animation-delay: .2s; }
.route .stop:nth-child(5) { animation-delay: .25s; }
.route .stop:nth-child(6) { animation-delay: .3s; }
.route .stop:nth-child(n+7) { animation-delay: .35s; }
@keyframes kor-pop { from { opacity: 0; transform: translateX(-16px) scale(.96); } }
.stop--current .stop__dot, .stop--choice .stop__dot { animation: kor-beacon 1.4s ease-in-out infinite; }
@keyframes kor-beacon {
  0%, 100% { box-shadow: 0 0 0 3px rgba(78, 232, 255, .25); transform: scale(1); }
  50% { box-shadow: 0 0 0 9px rgba(78, 232, 255, 0), 0 0 18px rgba(78, 232, 255, .6); transform: scale(1.08); }
}
.choice { transition: transform .12s cubic-bezier(.3, 1.6, .5, 1), border-color .15s, background .15s; }
.choice:active { transform: scale(.97); }
.choice[aria-pressed="true"] { animation: kor-select .3s cubic-bezier(.3, 1.6, .5, 1); }
@keyframes kor-select { 50% { transform: scale(1.04); } }

/* Veredictos (moneda y resultado final): entran de golpe, como un "K.O." */
[data-fx-onload] { animation: kor-slam .5s cubic-bezier(.2, 1.6, .4, 1) .15s backwards; }
@keyframes kor-slam {
  0% { opacity: 0; transform: scale(2.4) rotate(-6deg); }
  60% { opacity: 1; transform: scale(.92) rotate(1deg); }
  100% { transform: none; }
}

/* Bloques agrupados (portada, resultado): sus hijos entran igual que los del cuerpo. */
.home-a > *, .home-b > *, .res-a > *, .res-b > * { animation: kor-rise .38s cubic-bezier(.2, .8, .2, 1) .08s backwards; }
.home-a > :nth-child(2), .home-b > :nth-child(2), .res-a > :nth-child(2), .res-b > :nth-child(2) { animation-delay: .14s; }
.home-a > :nth-child(n+3), .home-b > :nth-child(n+3), .res-a > :nth-child(n+3), .res-b > :nth-child(n+3) { animation-delay: .2s; }

/* Listas (logros, ranking, reglas, opciones): las filas entran en cascada. */
.logro-row, .rank__row, .tut__item, .ficha-list > *, .fases > * { animation: kor-rise .34s cubic-bezier(.2, .8, .2, 1) backwards; }
:is(.logro-row, .rank__row, .tut__item, .ficha-list > *, .fases > *):nth-child(1) { animation-delay: .12s; }
:is(.logro-row, .rank__row, .tut__item, .ficha-list > *, .fases > *):nth-child(2) { animation-delay: .17s; }
:is(.logro-row, .rank__row, .tut__item, .ficha-list > *, .fases > *):nth-child(3) { animation-delay: .22s; }
:is(.logro-row, .rank__row, .tut__item, .ficha-list > *, .fases > *):nth-child(4) { animation-delay: .27s; }
:is(.logro-row, .rank__row, .tut__item, .ficha-list > *, .fases > *):nth-child(5) { animation-delay: .32s; }
:is(.logro-row, .rank__row, .tut__item, .ficha-list > *, .fases > *):nth-child(6) { animation-delay: .37s; }
:is(.logro-row, .rank__row, .tut__item, .ficha-list > *, .fases > *):nth-child(n+7) { animation-delay: .42s; }

/* Mapa: avanzar se ve. El tramo que lleva a la casilla actual se dibuja de arriba abajo
   y la casilla actual "aterriza" antes de empezar a latir. */
.stop--done:has(+ .stop--current, + .stop--choice)::before {
  transform-origin: top; animation: kor-trail .5s .45s ease-out backwards;
}
@keyframes kor-trail { from { transform: scaleY(0); } }
.stop--current .stop__dot, .stop--choice .stop__dot {
  animation: kor-land .45s .85s cubic-bezier(.2, 1.6, .4, 1) backwards, kor-beacon 1.4s 1.3s ease-in-out infinite;
}
@keyframes kor-land { from { transform: scale(.3); opacity: 0; } }

/* Estado vacío (x-game.empty): un icono enmarcado que flota, una frase y qué hacer. */
.empty { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 14px 8px 6px; text-align: center; }
.empty__art {
  display: grid; place-items: center; width: 64px; height: 64px; font-size: 2rem; line-height: 1;
  background: linear-gradient(160deg, var(--wood), var(--wood-2)); border: 2px solid var(--line);
  box-shadow: 0 0 0 2px #000, 0 6px 0 rgba(0, 0, 0, .35); border-radius: 4px;
  animation: kor-float 3.2s ease-in-out infinite;
}
@keyframes kor-float { 50% { transform: translateY(-5px); } }
.empty__title { margin: 4px 0 0; font-family: var(--f-display); font-size: 1rem; color: var(--ink); }
.empty__txt { margin: 0; font-size: .84rem; color: var(--ink-dim); max-width: 32ch; text-wrap: balance; }
.empty__cta { margin-top: 4px; font-size: .85rem; font-weight: 800; color: var(--candle); text-decoration: none; }

/* Botón de sonido (portada). */
/* Botones de sonido y de música (portada): mismo par de iconos encendido/apagado. */
.icon-btn[data-fx-mute] .fx-mute__off, .icon-btn[data-music-toggle] .fx-mute__off { display: none; }
.icon-btn.is-muted .fx-mute__on { display: none; }
.icon-btn.is-muted .fx-mute__off { display: inline; }
.icon-btn.is-muted { color: var(--ink-faint); }

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
  .screen__body > *,
  .route .stop,
  .stop--current .stop__dot, .stop--choice .stop__dot,
  .stop--done::before, .empty__art,
  .home-a > *, .home-b > *, .res-a > *, .res-b > *,
  .logro-row, .rank__row, .tut__item, .ficha-list > *, .fases > *,
  .choice[aria-pressed="true"],
  [data-fx-onload],
  .screen__foot .btn--wide::after,
  .screen--arcade::before, .screen--arcade::after { animation: none !important; }
  .screen--arcade::after { opacity: .5; }
  .btn:not(:disabled):active, .icon-btn:active, .choice:active, .menu-link:active { transform: none; }
}

/* Ajustes → Movimiento reducido (ver public/js/settings.js): el mismo efecto que pedirlo
   al sistema, solo para este juego. Las animaciones acaban al instante (se ve su estado
   final) en vez de quitarlas una a una. */
html[data-motion="reduced"] *, html[data-motion="reduced"] *::before, html[data-motion="reduced"] *::after {
  animation-duration: .001ms !important; animation-iteration-count: 1 !important; animation-delay: 0s !important;
  transition-duration: .001ms !important; scroll-behavior: auto !important;
}

/* Cortina al entrar en combate (data-wipe, ver app.js): barras horizontales negras que
   se abren alternando lados, como la transición a un combate de los juegos de Pokémon. */
.wipe { position: fixed; inset: 0; z-index: 900; pointer-events: none; display: flex; flex-direction: column; }
.wipe i { flex: 1; background: #05070d; transform-origin: left; animation: wipe-open .55s cubic-bezier(.7, 0, .3, 1) forwards; }
.wipe i:nth-child(2n) { transform-origin: right; }
@keyframes wipe-open { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* Lluvia de ventas en la victoria (resultado): monedas que caen girando. */
.ventas-rain { position: fixed; inset: 0; z-index: 800; pointer-events: none; overflow: hidden; }
.ventas-rain i {
  position: absolute; top: -28px; width: 18px; height: 18px; border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #fff6b0, #ffcc33 55%, #b8860b);
  box-shadow: 0 0 0 2px #7a5200; animation: ventas-fall linear forwards;
}
.ventas-rain i::after { content: "$"; position: absolute; inset: 0; display: grid; place-items: center; font: 800 11px/1 var(--f-body); color: #7a5200; }
@keyframes ventas-fall { to { transform: translateY(112vh) rotate(720deg); } }
@media (prefers-reduced-motion: reduce) { .wipe, .ventas-rain { display: none; } }

/* ============================================================
   GALERÍA PÚBLICA DE CARTAS (/cartas, ver CartasController)
   ============================================================ */
/* Volteo joven ↔ mayor: el mismo de "Elige tu redactor", para la ficha y el iframe. */
.flip { perspective: 1000px; width: 100%; aspect-ratio: var(--card-aspect); cursor: pointer; background: none; border: 0; padding: 0; display: block; }
.flip__inner { position: relative; width: 100%; height: 100%; transition: transform .5s; transform-style: preserve-3d; }
.flip.flipped .flip__inner { transform: rotateY(180deg); }
.flip__front, .flip__back { position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.flip__back { transform: rotateY(180deg); }

/* Carta todavía sin publicar: la silueta, con la fecha si la tiene. */
.silueta {
  width: 100%; aspect-ratio: var(--card-aspect); display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 6px; text-align: center; border-radius: 10px;
  background: repeating-linear-gradient(135deg, #17112b 0 10px, #1c1534 10px 20px);
  border: 2px dashed var(--line); color: var(--ink-faint);
}
.silueta__q { font-family: var(--f-display); font-size: clamp(2rem, 32cqw, 6rem); color: #3b2d6b; line-height: 1; }
.silueta__k { font-family: var(--f-pixel); font-size: .5rem; letter-spacing: .1em; color: var(--ink-dim); }
.silueta__d { font-size: .8rem; color: var(--candle); font-weight: 700; }
.silueta { container-type: inline-size; }

.galeria { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 12px; }
.galeria__item { display: flex; flex-direction: column; gap: 6px; text-decoration: none; color: inherit; min-width: 0; }
.galeria__item:hover .card { transform: translateY(-3px); }
.galeria__item .card { transition: transform .2s; }
.galeria__pie { display: flex; justify-content: space-between; gap: 6px; font-size: .78rem; color: var(--ink-dim); }
.galeria__pie b { color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.galeria-intro { margin: 0 auto; max-width: 62ch; font-size: .9rem; color: var(--ink-dim); text-align: center; text-wrap: balance; }
@media (min-width: 720px) { .galeria { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .galeria { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 22px 18px; } }

/* Ficha de una carta. */
.ficha-carta { display: flex; flex-direction: column; gap: 16px; align-items: center; }
.ficha-carta__arte { width: min(100%, 320px); display: flex; flex-direction: column; gap: 6px; align-items: center; }
.ficha-carta__hint { font-size: .75rem; color: var(--ink-faint); }
.ficha-carta__info { width: 100%; display: flex; flex-direction: column; gap: 12px; }
.ficha-carta__n { font-family: var(--f-pixel); font-size: .5rem; letter-spacing: .1em; color: var(--candle); margin: 0; }
.ficha-carta__nombre { font-family: var(--f-display); font-size: clamp(1.5rem, 7vw, 2.1rem); line-height: 1.05; margin: 0; }
.ficha-carta__meta { margin: 0; color: var(--ink-dim); font-size: .9rem; }
.caras { display: grid; grid-template-columns: 1fr; gap: 10px; }
@media (min-width: 480px) { .caras { grid-template-columns: 1fr 1fr; } }
.cara { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; }
.cara__k { margin: 0 0 6px; font-size: .72rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-faint); }
.cara__nombre { margin: 0 0 8px; font-weight: 800; font-size: .9rem; }
.cara__stats { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 10px; font-size: .82rem; color: var(--ink-dim); margin: 0; }
.cara__stats div { display: flex; justify-content: space-between; }
.cara__stats dd { margin: 0; font-weight: 800; color: var(--ink); }
.cara__stats dt::before { content: ""; display: inline-block; width: 8px; height: 8px; margin-right: 5px; border-radius: 2px; background: var(--c, var(--ink-faint)); }
.ficha-carta__acciones { display: flex; flex-direction: column; gap: 8px; }
.ficha-carta__nav { display: flex; justify-content: space-between; font-size: .85rem; }
.ficha-carta__nav a { color: var(--candle); text-decoration: none; font-weight: 700; }
@media (min-width: 1024px) {
  .ficha-carta { flex-direction: row; align-items: flex-start; gap: 40px; justify-content: center; }
  .ficha-carta__arte { width: 340px; flex: 0 0 auto; position: sticky; top: 0; }
  .ficha-carta__info { max-width: 30rem; }
}

/* Marcos de la racha del reto diario (ver App\Services\Rachas): bronce a los 3 días
   seguidos, plata a los 7 y oro a los 30. Se ven en tu carta durante el combate y como
   etiqueta en la portada. Puramente estético: el reto sigue siendo igual para todos. */
.marco { --marco: #cd7f32; --marco-2: #f3b47a; }
.marco--plata { --marco: #b9c3cf; --marco-2: #ffffff; }
.marco--oro { --marco: #e8b400; --marco-2: #fff3a6; }
.marco .card {
  outline: 3px solid var(--marco); outline-offset: 2px;
  box-shadow: 0 0 0 6px rgba(0, 0, 0, .45), 0 0 18px 2px color-mix(in srgb, var(--marco) 60%, transparent);
}
.marco--oro .card { animation: marco-oro 2.6s ease-in-out infinite; }
@keyframes marco-oro { 50% { outline-color: var(--marco-2); } }
.marco-chip {
  flex: 0 0 auto; font-size: .64rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 999px; color: #1a1205;
  background: linear-gradient(135deg, var(--marco-2), var(--marco));
}
.marco-chip--bronce { --marco: #cd7f32; --marco-2: #f3b47a; }
.marco-chip--plata { --marco: #b9c3cf; --marco-2: #ffffff; }
.marco-chip--oro { --marco: #e8b400; --marco-2: #fff3a6; }
@media (prefers-reduced-motion: reduce) { .marco--oro .card { animation: none; } }
