/* ==========================================================================
   SUPERLIGA FRONTIER TCG — COMPONENTES
   Librería mínima viable (briefing, sección 22). Depende de tokens.css y
   base.css. Cada componente documenta sus estados donde no son obvios.
   ========================================================================== */

/* ==========================================================================
   1. BOTÓN
   Variantes: primario / ghost / peligro · Tamaños: sm / md / lg
   Objetivo táctil: 44px de alto en md y lg, 36px en sm (uso secundario).
   ========================================================================== */
.btn {
  --btn-alto: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--btn-alto);
  padding: 0 var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-family: var(--font-ui);
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--t-micro) var(--ease),
              border-color var(--t-micro) var(--ease),
              color var(--t-micro) var(--ease),
              transform var(--t-micro) var(--ease);
}
.btn:active { transform: scale(.98); }

.btn-primary {
  background: var(--amber);
  color: var(--amber-ink);
  font-weight: var(--fw-bold);
  box-shadow: var(--shadow-sm);
}
.btn-primary:hover { background: var(--amber-light); }

.btn-ghost {
  background: transparent;
  color: var(--frost);
  border-color: var(--line-strong);
}
.btn-ghost:hover { background: rgba(255, 255, 255, .05); border-color: rgba(255, 255, 255, .28); }

.btn-danger {
  background: var(--danger);
  color: #2A0603;
  font-weight: var(--fw-bold);
}
.btn-danger:hover { background: #FF6E63; }

/* texto sin caja: acciones terciarias dentro de tablas y tarjetas */
.btn-plano {
  background: transparent;
  color: var(--frost-dim);
  padding-inline: var(--space-3);
}
.btn-plano:hover { color: var(--frost); background: rgba(255, 255, 255, .04); }

.btn-sm { --btn-alto: 36px; padding-inline: var(--space-4); font-size: var(--fs-caption); }
.btn-lg { --btn-alto: 52px; padding-inline: var(--space-6); font-size: var(--fs-body); }
.btn-bloque { width: 100%; }

.btn:disabled, .btn[aria-disabled="true"] {
  opacity: .45;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none !important;
}

/* estado de carga: el botón conserva su ancho para no descuadrar el layout */
.btn.is-cargando { pointer-events: none; color: transparent !important; position: relative; }
.btn.is-cargando::after {
  content: '';
  position: absolute;
  width: 16px; height: 16px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: girar .7s linear infinite;
  color: var(--amber-ink);
}
.btn-ghost.is-cargando::after, .btn-plano.is-cargando::after { color: var(--frost); }
@keyframes girar { to { transform: rotate(360deg); } }

/* ==========================================================================
   2. CAMPO DE FORMULARIO
   Etiqueta siempre visible (nunca placeholder como etiqueta).
   ========================================================================== */
.campo { display: flex; flex-direction: column; gap: var(--space-2); }

.campo > label, .campo-label {
  font-size: var(--fs-caption-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caption);
  text-transform: uppercase;
  color: var(--frost-dim);
}

.campo input[type="text"],
.campo input[type="password"],
.campo input[type="number"],
.campo input[type="search"],
.campo input[type="file"],
.campo textarea,
.campo select {
  width: 100%;
  min-height: 44px;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--void-2);
  color: var(--frost);
  font-size: var(--fs-body-sm);
  outline: none;
  transition: border-color var(--t-micro) var(--ease), background var(--t-micro) var(--ease);
}
.campo textarea { min-height: 96px; resize: vertical; line-height: var(--lh-body); }

.campo input::placeholder, .campo textarea::placeholder { color: rgba(147, 149, 159, .7); }

.campo input:hover, .campo select:hover, .campo textarea:hover { border-color: var(--line-strong); }

.campo input:focus, .campo select:focus, .campo textarea:focus {
  border-color: var(--amber);
  background: rgba(232, 117, 42, .05);
}

/* select con caret propio */
.campo select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: var(--space-7);
  cursor: pointer;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%2393959F' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'><path d='M5 7.5l5 5 5-5'/></svg>");
  background-repeat: no-repeat;
  background-position: right var(--space-4) center;
  background-size: 16px;
}
.campo select option { background: var(--panel); color: var(--frost); }

.campo-hint { font-size: var(--fs-caption-sm); color: var(--frost-dim); }

/* error inline: siempre junto al campo, nunca solo arriba del formulario */
.campo.is-error input, .campo.is-error select, .campo.is-error textarea { border-color: var(--danger); }
.campo-error {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-caption-sm);
  color: var(--danger-text);
}

/* casilla */
/* la etiqueta entera es el objetivo táctil, no solo la casilla de 18px */
.casilla {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 36px;
  font-size: var(--fs-body-sm);
  color: var(--frost-dim);
  cursor: pointer;
}
.casilla:hover { color: var(--frost); }
.casilla input { width: 18px; height: 18px; accent-color: var(--amber); cursor: pointer; flex-shrink: 0; }

/* ==========================================================================
   3. TARJETA DE CARTA  ← el componente más importante del sistema
   --------------------------------------------------------------------------
   Regla estructural: el arte se muestra SIEMPRE completo (contain), sobre una
   placa de fondo con halo de color según rareza. El marco absorbe que el arte
   de origen no tenga proporciones ni resoluciones uniformes.

   La rareza se marca por color Y por señal no cromática (chevrones / corona /
   destello), obligatorio por accesibilidad y por equidad en los duelos.

   Estados: por defecto · hover (solo si es interactiva) · is-nopos (no
   poseída, álbum) · is-protegida (bloqueada para venta) · is-venta (en el
   mercado) · is-seleccionada (deck builder) · is-revelando (ceremonia).
   ========================================================================== */
.carta {
  --rz: var(--rz1);
  --rz-halo: var(--rz1-halo);
  --rz-ink: var(--rz1-ink);
  --rz-borde: var(--line-strong);

  position: relative;
  display: block;
  padding: 1px;                       /* el padding de 1px ES el borde */
  /* misma trampa que .cer-escena/.submenu-tipos/etc. (§8 del CLAUDE.md de
     branding): un display propio empata en especificidad con la regla
     [hidden] del navegador, y gana el autor. album.js/coleccion.js ocultan
     cartas con .hidden = true; sin esto, la carta seguía mostrándose. */
  border-radius: var(--radius-xl);
  background: var(--rz-borde);
  text-decoration: none;
  color: inherit;
  transition: transform var(--t-media) var(--ease);
}
.carta[hidden] { display: none; }

.carta-marco {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  height: 100%;
  padding: var(--space-3);
  /* red de seguridad: nada de lo que haya dentro del marco debe poder
     asomar fuera de él. Sin esto, una etiqueta de rareza larga ("Poco
     común") empujaba la insignia de cantidad literalmente fuera de la
     tarjeta —y en el selector de mazos, fuera de la pantalla en móvil—.
     Seguro: insignias, candado y el aura SRF están posicionados contra
     .carta, no contra .carta-marco, así que no los recorta. */
  overflow: hidden;
  border-radius: calc(var(--radius-xl) - 1px);
  background: linear-gradient(180deg, var(--panel), var(--void));
  transition: box-shadow var(--t-media) var(--ease);
}

.carta-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: 26px;
}

/* ---- placa de arte: la decisión estructural del sistema ---- */
.carta-placa {
  position: relative;
  aspect-ratio: 233 / 361;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background:
    radial-gradient(ellipse 75% 55% at 50% 20%, var(--rz-halo), transparent 72%),
    linear-gradient(170deg, var(--void-2), #08090C);
  display: grid;
  place-items: center;
}
/* La imagen se posiciona en absoluto contra la placa. Con `height: 100%` a
   secas el porcentaje no resuelve —la altura de la placa viene de
   aspect-ratio, no de un valor explícito— y un arte muy alto desbordaba la
   caja: se recortaba justo lo que este sistema promete no recortar nunca. */
.carta-arte {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;      /* NUNCA cover: el arte no se recorta jamás */
  object-position: center;
}
/* marca de agua cuando la carta aún no tiene arte */
.carta-placa-vacia {
  font-size: 40px;
  color: rgba(255, 255, 255, .10);
}

/* ---------------------------------------------------------------------------
   MARCO CON FOTO (Común/Poco común/Raro/Épico) — plantillas de
   assets/img/marcos/ (451×800 completas, sin recortar), una por rareza. El
   cuadrado y el rectángulo blanco de cada plantilla caen siempre en el mismo
   sitio (medido a mano), así que las dos zonas se posicionan en porcentaje
   fijo — no dependen del arte que lleve dentro.

   `background-size: contain`, no `cover`: la plantilla tiene una proporción
   más alargada que `.carta-placa` (451/800 contra 233/361), y recortarla se
   comía las estrellas y el emblema de abajo. Con `contain` se ve la plantilla
   ENTERA y sobra hueco a los lados, que se rellena con `background-color` en
   vez de dejarlo transparente — mismo criterio que ya usa el arte de
   Legendario/SRF (una banda oscura antes que recortar algo). Por eso las
   coordenadas de abajo son distintas a cuando era `cover`: con `contain` la
   imagen no ocupa el 100% del ancho de la placa, así que el cuadrado y el
   rectángulo quedan más centrados y más estrechos en proporción al hueco.
   --------------------------------------------------------------------------- */
.carta-placa--marco {
  background-image: var(--marco-img);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  background-color: var(--void-2);
}
.carta[data-rareza="1"] .carta-placa--marco { --marco-img: url('../img/marcos/comun.jpg'); }
.carta[data-rareza="2"] .carta-placa--marco { --marco-img: url('../img/marcos/poco-comun.jpg'); }
.carta[data-rareza="3"] .carta-placa--marco { --marco-img: url('../img/marcos/raro.jpg'); }
.carta[data-rareza="4"] .carta-placa--marco { --marco-img: url('../img/marcos/epico.jpg'); }

.carta-foto-hueco {
  position: absolute;
  left: 18.1%; top: 9.25%; width: 64.1%; height: 41.25%;
}
/* El nombre real (mismo <h3>, solo movido) sobre el rectángulo blanco de la
   plantilla: sigue siendo texto de verdad, no está "quemado" en la imagen —
   lo sigue leyendo un lector de pantalla y lo sigue encontrando el buscador
   del álbum (§7, WCAG 2.2, no negociable). */
.carta-nombre-marco {
  position: absolute;
  left: 17.9%; top: 53.25%; width: 64.9%; height: 6.75%;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  padding: 0 4px;
  color: #14151A;
  font-size: var(--fs-caption-sm);
  font-weight: var(--fw-semibold);
  text-align: center;
}
.carta--lg .carta-nombre-marco { font-size: var(--fs-caption); }

/* insignia de posición, esquina SUPERIOR izquierda de la placa. Antes iba
   abajo, pero ahí tapaba las estrellas de la plantilla de marco (§ arriba,
   Común/Poco común/Raro/Épico). */
.carta-pos {
  position: absolute;
  left: var(--space-2);
  top: var(--space-2);
  z-index: 3;               /* por encima del tinte y el barrido holográficos */
  padding: 3px var(--space-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: rgba(11, 12, 16, .8);
  backdrop-filter: blur(6px);
  font-size: 11px;
  font-weight: var(--fw-semibold);
  letter-spacing: .06em;
  color: var(--frost);
}

/* ---- cuerpo ---- */
.carta-cuerpo { display: flex; flex-direction: column; gap: var(--space-1); }
.carta-nombre {
  font-size: var(--fs-body);
  font-weight: var(--fw-semibold);
  line-height: 1.25;
  /* dos líneas máximo: nombres largos no descuadran la rejilla */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.carta-meta {
  display: flex;
  justify-content: space-between;
  gap: var(--space-2);
  font-size: var(--fs-caption-sm);
  color: var(--frost-dim);
}
.carta-equipo { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- rasgo de configuración (Capa 2 — Compos): Contraataque, Justicia,
   Vínculo o Brecha. La afinidad ya se ve como hexágono; este es el otro
   ingrediente de las Compos y hasta ahora no se veía en ningún sitio. ---- */
.carta-rasgo {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-caption-sm);
  color: var(--amber-light);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.carta-rasgo i { font-size: 11px; flex-shrink: 0; }

/* ---- bloque de estadísticas de combate ----
   Espacio reservado desde ya (briefing, sección 32). Se rellena cuando el
   diseño de los duelos fije las estadísticas; el marco no cambia. */
.carta-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-1);
  margin-top: var(--space-1);
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}
.carta-stat { text-align: center; }
.carta-stat b {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--frost);
}
.carta-stat span {
  font-size: 10px;
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caption);
  text-transform: uppercase;
  color: var(--frost-dim);
}

/* pie de la carta: lo que cada pantalla añade debajo (vendedor, comprar…) */
.carta-pie {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: auto;
  padding-top: var(--space-3);
  border-top: 1px solid var(--line);
}
.carta-vendedor {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-caption-sm);
  color: var(--frost-dim);
}

/* botón flotante sobre la carta (proteger / quitar protección) */
.carta-accion-flotante {
  position: absolute;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 4;
  display: grid;
  place-items: center;
  width: 32px; height: 32px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: rgba(11, 12, 16, .82);
  backdrop-filter: blur(6px);
  color: var(--frost-dim);
  font-size: 15px;
  cursor: pointer;
  transition: color var(--t-micro) var(--ease), border-color var(--t-micro) var(--ease);
}
.carta-accion-flotante:hover { color: var(--frost); border-color: var(--line-strong); }
.carta-accion-flotante.esta-activa { color: var(--amber-light); border-color: var(--amber-line); }

/* agrupa la insignia de cantidad y el hexágono en el lado derecho de la
   cabecera, para que la rareza (izquierda) y ellos (derecha) se repartan con
   el space-between de .carta-head sin que la cantidad quede suelta al centro */
.carta-head-derecha {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  /* nunca cede espacio: si algo tiene que recortarse en .carta-head es la
     etiqueta de rareza (ver .rz-texto), no la cantidad ni el hexágono */
  flex-shrink: 0;
}

/* insignia "×N" para copias repetidas en colección (ver $opts['cantidad']) */
.carta-cantidad {
  font-family: var(--font-mono);
  font-size: var(--fs-caption-sm);
  font-weight: var(--fw-semibold);
  color: var(--frost-dim);
}

/* ---- afinidad (hexágono) ---- */
.carta-afinidad {
  width: 28px; height: 28px;
  flex-shrink: 0;
  clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
  background: rgba(255, 255, 255, .06);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.carta-afinidad img { width: 100%; height: 100%; object-fit: contain; }

/* ==========================================================================
   3b. ETIQUETA DE RAREZA
   El mismo lenguaje visual en colección, mercado, álbum y sala de duelo.
   Las marcas van en .rz-marcas y son la señal NO cromática.
   ========================================================================== */
.rz {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  /* min-width:0 es lo que permite que esta etiqueta se encoja por debajo
     del ancho de su propio texto dentro de .carta-head (flex). Sin esto,
     "Poco común" en una tarjeta pequeña empujaba lo que hubiera a su lado
     fuera de la tarjeta en vez de truncarse. */
  min-width: 0;
  padding: 4px var(--space-2);
  border: 1px solid color-mix(in srgb, var(--rz) 40%, transparent);
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--rz) 14%, transparent);
  color: var(--rz-ink);
  font-size: 10px;
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caption);
  text-transform: uppercase;
}
.rz-marcas { display: inline-flex; align-items: center; gap: 2px; line-height: 0; flex-shrink: 0; }
/* el texto es lo único que se recorta con puntos suspensivos: las marcas no
   cromáticas (chevrones, corona, destello) siempre se quedan completas, son
   la señal de accesibilidad que no puede desaparecer */
.rz-texto {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
/* chevrón dibujado en CSS: sigue siendo legible aunque falle la fuente de iconos */
.rz-marca {
  width: 5px; height: 5px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
}
.rz-marcas i { font-size: 12px; }

/* ---- rarezas 1–4: color plano + n marcas ---- */
.carta[data-rareza="1"], .rz[data-rareza="1"] { --rz: var(--rz1); --rz-halo: var(--rz1-halo); --rz-ink: var(--rz1-ink); }
.carta[data-rareza="2"], .rz[data-rareza="2"] { --rz: var(--rz2); --rz-halo: var(--rz2-halo); --rz-ink: var(--rz2-ink); }
.carta[data-rareza="3"], .rz[data-rareza="3"] { --rz: var(--rz3); --rz-halo: var(--rz3-halo); --rz-ink: var(--rz3-ink); }
.carta[data-rareza="4"], .rz[data-rareza="4"] { --rz: var(--rz4); --rz-halo: var(--rz4-halo); --rz-ink: var(--rz4-ink); }
.carta[data-rareza="5"], .rz[data-rareza="5"] { --rz: var(--rz5); --rz-halo: var(--rz5-halo); --rz-ink: var(--rz5-ink); }
.carta[data-rareza="6"], .rz[data-rareza="6"] { --rz: var(--rz6); --rz-halo: var(--rz6-halo); --rz-ink: var(--rz6-ink); }

.carta[data-rareza="2"] { --rz-borde: color-mix(in srgb, var(--rz2) 34%, transparent); }
.carta[data-rareza="3"] { --rz-borde: color-mix(in srgb, var(--rz3) 38%, transparent); }
.carta[data-rareza="4"] { --rz-borde: color-mix(in srgb, var(--rz4) 42%, transparent); }

/* ---- 5. Legendario: borde metálico + etiqueta en degradado ámbar-fuego ---- */
.carta[data-rareza="5"] {
  --rz-borde: linear-gradient(140deg, #FFE0AE, #E8752A 30%, #7A3A12 52%, #F2B134 72%, #FFE0AE);
}
.rz[data-rareza="5"] {
  background: var(--rz5-grad);
  border-color: rgba(255, 224, 174, .6);
  color: var(--amber-ink);
}

/* ---- 6. SRF: la rareza cumbre.
        Es la única con animación por defecto y tiene que ganar a la legendaria
        sin discusión, así que suma tres señales que ninguna otra rareza usa:
        borde arcoíris en movimiento, aura exterior y barrido holográfico sobre
        el arte. El marco se ensancha a 2px para que el borde se lea de lejos. ---- */
.carta[data-rareza="6"] {
  padding: 2px;
  background: var(--rz6-grad);
  background-size: 300% 100%;
  animation: holoDeriva 4s linear infinite;
}
.carta[data-rareza="6"] .carta-marco { border-radius: calc(var(--radius-xl) - 2px); }
.carta--sm[data-rareza="6"] .carta-marco { border-radius: calc(var(--radius-lg) - 2px); }

/* aura exterior: se pinta por detrás de la carta y es lo que la hace destacar
   en una rejilla, antes incluso de leer la etiqueta */
.carta[data-rareza="6"]::before {
  content: '';
  position: absolute;
  inset: -7px;
  z-index: -1;
  border-radius: inherit;
  background: var(--rz6-grad);
  background-size: 300% 100%;
  filter: blur(13px);
  opacity: .5;
  animation: holoDeriva 4s linear infinite, holoAura 3.2s ease-in-out infinite;
}

/* tinte multitono sobre el arte, contenido para no competir con la
   ilustración: el arte manda, el holográfico lo acompaña */
.carta[data-rareza="6"] .carta-placa::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: var(--rz6-grad);
  background-size: 300% 100%;
  mix-blend-mode: overlay;
  opacity: .45;
  animation: holoDeriva 6s linear infinite;
}

/* barrido de luz diagonal: el destello de una carta holográfica física al
   girarla bajo la luz */
.carta[data-rareza="6"] .carta-placa::before {
  content: '';
  position: absolute;
  inset: -30%;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(110deg,
    transparent 38%,
    rgba(255, 255, 255, .16) 46%,
    rgba(255, 255, 255, .55) 50%,
    rgba(255, 255, 255, .16) 54%,
    transparent 62%);
  animation: holoBarrido 4.5s var(--ease) infinite;
}

.rz[data-rareza="6"] {
  position: relative;
  overflow: hidden;
  /* la placa oscura mantiene el texto legible cuando pasa la banda amarilla:
     sin ella el blanco cae por debajo de 2:1 */
  background-image: linear-gradient(rgba(11, 12, 16, .45), rgba(11, 12, 16, .45)), var(--rz6-grad);
  background-size: 100% 100%, 300% 100%;
  border-color: rgba(255, 255, 255, .75);
  color: #fff;
  box-shadow: 0 0 12px -2px rgba(255, 255, 255, .35);
  animation: holoDeriva 3s linear infinite;
}
/* la etiqueta recibe su propio barrido, más corto. Va por debajo del texto:
   si pasara por encima, el contraste caería durante el destello */
.rz[data-rareza="6"]::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(110deg, transparent 40%, rgba(255, 255, 255, .5) 50%, transparent 60%);
  animation: holoBarrido 3.5s var(--ease) infinite;
}
.rz[data-rareza="6"] > * { position: relative; z-index: 1; }

@keyframes holoDeriva {
  0%   { background-position: 0% 50%; }
  100% { background-position: 300% 50%; }
}
@keyframes holoAura {
  0%, 100% { opacity: .38; }
  50%      { opacity: .68; }
}
@keyframes holoBarrido {
  0%, 55%  { transform: translateX(-115%); }
  100%     { transform: translateX(115%); }
}

/* Movimiento reducido: se apagan los barridos y el aura queda fija en su
   estado medio. La carta sigue siendo inconfundiblemente SRF —borde
   arcoíris, aura y tinte— pero sin nada en movimiento. */
:root[data-motion="reduce"] .carta[data-rareza="6"] .carta-placa::before,
:root[data-motion="reduce"] .rz[data-rareza="6"]::after { display: none; }
:root[data-motion="reduce"] .carta[data-rareza="6"]::before { opacity: .5; }

/* ==========================================================================
   3c. TAMAÑOS Y ESTADOS DE LA CARTA
   ========================================================================== */
.carta--sm { border-radius: var(--radius-lg); }
.carta--sm .carta-marco { padding: var(--space-2); gap: var(--space-2); border-radius: calc(var(--radius-lg) - 1px); }
.carta--sm .carta-nombre { font-size: var(--fs-caption); }
.carta--sm .carta-meta { font-size: 11px; }
.carta--sm .carta-afinidad { width: 22px; height: 22px; }
.carta--sm .rz { font-size: 9px; padding: 3px 6px; }

.carta--lg .carta-marco { padding: var(--space-4); gap: var(--space-4); }
.carta--lg .carta-nombre { font-size: var(--fs-h3); }
.carta--lg .carta-meta { font-size: var(--fs-body-sm); }

/* interactiva: solo las cartas que llevan a algún sitio se elevan al hover */
.carta--accion { cursor: pointer; }
@media (hover: hover) {
  .carta--accion:hover { transform: translateY(-6px); }
  .carta--accion:hover .carta-marco { box-shadow: var(--shadow-lg); }
}
.carta--accion:focus-visible { outline: 2px solid var(--amber-light); outline-offset: 4px; }

/* no poseída (álbum): silueta apagada, nunca oculta del todo */
.carta.is-nopos .carta-marco { filter: grayscale(1); opacity: .45; }
.carta.is-nopos:hover .carta-marco { opacity: .65; }
.carta-candado {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  border-radius: var(--radius-xl);
  background: rgba(11, 12, 16, .45);
  font-size: var(--fs-caption-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caption);
  text-transform: uppercase;
  color: var(--frost-dim);
}
.carta-candado i { font-size: 22px; }

/* insignias flotantes sobre la carta */
.carta-insignia {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 5px var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: rgba(11, 12, 16, .82);
  backdrop-filter: blur(6px);
  font-family: var(--font-mono);
  font-size: var(--fs-caption-sm);
  font-weight: var(--fw-semibold);
  color: var(--frost);
}
.carta-insignia--precio { color: var(--amber-light); border-color: var(--amber-line); }
.carta-insignia--protegida { top: var(--space-3); left: var(--space-3); right: auto; color: var(--amber-light); }

/* seleccionada (deck builder): anillo ámbar, sin depender del arrastre */
.carta.is-seleccionada { --rz-borde: var(--amber); }
.carta.is-seleccionada .carta-marco { box-shadow: 0 0 0 2px var(--amber-soft); }

/* dorso: usado en la ceremonia de apertura antes del volteo */
.carta-dorso {
  display: grid;
  place-items: center;
  height: 100%;
  border-radius: calc(var(--radius-xl) - 1px);
  background:
    repeating-linear-gradient(135deg, rgba(255,255,255,.03) 0 8px, transparent 8px 16px),
    linear-gradient(180deg, var(--panel), var(--void));
  color: rgba(255, 255, 255, .18);
  font-size: 34px;
}

/* rejilla estándar de cartas */
.carta-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: var(--space-4);
}
@media (min-width: 480px) {
  .carta-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--space-5); }
}
.carta-grid--densa { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: var(--space-3); }

/* ==========================================================================
   4. CAJAS Y SOBRES 3D — pack3d (components/caja3d.php)
   Todo el volumen es CSS falso: perspective + transform-style:preserve-3d +
   translateZ/rotateX/rotateY sobre capas PLANAS. Nunca WebGL, nunca Three.js,
   nunca un modelo real. GSAP solo orquesta timing/easing, en sobres.js.

   REFERENCIA VISUAL: caja de cromos tipo Panini/blaster. Cerrada se ven tres
   caras con grosor real (frente + tapa + lateral); abierta, la tapa se
   levanta por su charnela trasera y los sobres están DE PIE dentro, apretados
   de delante hacia atrás y sobresaliendo por encima del borde.

   GEOMETRÍA — cada cara se CENTRA primero en el volumen con
   translate(-50%,-50%) y luego se empuja a su sitio con translateX/Y/Z +
   rotate:
     · front: translateZ(+d/2)
     · top:   translateY(-h/2) rotateX(90deg)      (tamaño w × d)
     · side:  translateX(+w/2) rotateY(90deg)      (tamaño d × h)
     · suelo: translateY(+h/2) rotateX(90deg)      (tamaño w × d)
   NO plegar las caras desde su arista con transform-origin: es lo que hacía
   la versión anterior y las dejaba casi de canto — la caja se veía como un
   rectángulo plano, sin ningún volumen.

   El volumen se orienta con rotateX(-18deg) rotateY(-32deg): con esos signos
   quedan visibles a la vez frente, tapa y lateral DERECHO (las normales de
   ambas caras acaban con z positiva, o sea mirando a cámara).

   Los sobres van en .pack3d-interior-sobres, en el MISMO árbol preserve-3d
   que la caja. Ese contenedor NO puede llevar overflow ni scroll: cualquier
   overflow≠visible crea un contexto de recorte que APLANA a todos sus
   descendientes y destruye el 3D (además de pintar barras de scroll sueltas
   flotando en la escena).
   ========================================================================== */

/* arte común: sin plantilla subida (Fase 5) este degradado es el único fondo,
   así el render nunca se rompe por falta de assets */
.pack3d-cara, .pack3d-tapa, .pack3d-interior, .pack3d-sobre-frente {
  background-color: var(--panel);
  background-image:
    radial-gradient(ellipse 75% 55% at 50% 20%, var(--amber-soft), transparent 72%),
    linear-gradient(170deg, var(--void-2), #08090C);
  background-size: cover;
  background-position: center;
}

/* ---- Fase 1: caja cerrada por expansión (vitrina) ---- */
.vitrina-cabecera {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}
.vitrina-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-8);
  padding-block: var(--space-6);
}
.vitrina-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}
.js-caja-expansion { cursor: pointer; display: block; }
.js-caja-expansion:focus-visible { outline: 2px solid var(--amber); outline-offset: 8px; border-radius: var(--radius-md); }
.vitrina-item-nombre { font-weight: var(--fw-semibold); text-align: center; }

/* el portal: en reposo no pinta caja propia (display:contents), y solo al
   abrirse pasa a overlay fijo. Abrir/cerrar es un toggle de clase, sin mover
   el nodo en el DOM ni clonar nada. */
.pack3d-portal { display: contents; }
.pack3d-portal.esta-abierta {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  padding: var(--space-6);
  background: radial-gradient(ellipse at 50% 45%, rgba(24,14,6,.96), rgba(4,5,7,.985) 70%);
}
.pack3d-portal-cerrar { display: none; position: absolute; top: var(--space-5); right: var(--space-5); z-index: 2; }
.pack3d-portal.esta-abierta .pack3d-portal-cerrar { display: inline-flex; }

/* ---- el volumen ---- */
.pack3d {
  --pack3d-w: 200px;
  --pack3d-h: 250px;
  --pack3d-d: 130px;
  --pack3d-sobre-w: 165px;
  --pack3d-sobre-h: 235px;
  --pack3d-giro-x: -18deg;
  --pack3d-giro-y: -32deg;
  position: relative;
  width: var(--pack3d-w);
  height: var(--pack3d-h);
  perspective: 1500px;
  perspective-origin: 50% 42%;
  /* La caja gira y su tapa/lateral asoman FUERA de su caja de layout, y la
     sombra de contacto cae otro medio "fondo" por debajo. Sin reservar ese
     hueco arriba y abajo, la tapa se comía lo que hubiera encima y la sombra
     oscurecía el nombre/precio de debajo. */
  margin: calc(var(--pack3d-d) * .55) auto calc(var(--pack3d-d) * .5 + var(--space-4));
}
.pack3d--pequena {
  --pack3d-w: 150px; --pack3d-h: 185px; --pack3d-d: 95px;
  --pack3d-sobre-w: 122px; --pack3d-sobre-h: 172px;
}

/* sombra de contacto: elipse aplanada bajo la caja, fuera del preserve-3d
   para que no herede la rotación del volumen */
.pack3d-sombra {
  position: absolute;
  left: 50%;
  top: calc(100% + var(--pack3d-d) * .1);
  width: calc(var(--pack3d-w) * 1.25);
  height: calc(var(--pack3d-d) * .5);
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center, rgba(0,0,0,.72), transparent 70%);
  filter: blur(7px);
  pointer-events: none;
}

/* idle (Fase 1: animación visible sin interacción). El tilt al cursor vive en
   .pack3d-tilt, una capa aparte: GSAP escribe "transform" en línea, y sobre
   esta misma capa competiría con la animación CSS por la misma propiedad. */
.pack3d-volumen {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  animation: pack3dFlota 5.2s ease-in-out infinite;
}
@keyframes pack3dFlota {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-9px); }
}
.pack3d-volumen.en-portal { animation: none; }

.pack3d-tilt {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transform: rotateX(var(--pack3d-giro-x)) rotateY(var(--pack3d-giro-y));
}

.pack3d-cara, .pack3d-interior, .pack3d-tapa {
  position: absolute;
  left: 50%;
  top: 50%;
  background-size: cover;
  background-position: center;
}

/* frente */
.pack3d-cara--front {
  width: var(--pack3d-w);
  height: var(--pack3d-h);
  transform: translate(-50%, -50%) translateZ(calc(var(--pack3d-d) / 2));
  box-shadow: inset 0 0 0 1px var(--line), inset 0 -60px 90px rgba(0,0,0,.45);
}
/* tapa superior (la cara fija; la que se abre es .pack3d-tapa) */
.pack3d-cara--top {
  width: var(--pack3d-w);
  height: var(--pack3d-d);
  transform: translate(-50%, -50%) translateY(calc(var(--pack3d-h) / -2)) rotateX(90deg);
  filter: brightness(1.22);
  box-shadow: inset 0 0 0 1px var(--line);
}
/* lateral derecho */
.pack3d-cara--side {
  width: var(--pack3d-d);
  height: var(--pack3d-h);
  transform: translate(-50%, -50%) translateX(calc(var(--pack3d-w) / 2)) rotateY(90deg);
  filter: brightness(.62);
  box-shadow: inset 0 0 0 1px var(--line);
}
/* suelo interior: solo se ve con la caja abierta */
.pack3d-interior {
  width: var(--pack3d-w);
  height: var(--pack3d-d);
  transform: translate(-50%, -50%) translateY(calc(var(--pack3d-h) / 2)) rotateX(90deg);
  filter: brightness(.4);
}

/* charnela: div de altura 0 colocado en la arista TRASERA-SUPERIOR. La tapa
   cuelga de ella con transform-origin en su propio borde superior, así que
   rotarla es literalmente abrir una bisagra:
     · rotateX(90deg)  → tumbada hacia delante, tapando la boca (cerrada)
     · rotateX(205deg) → de pie e inclinada hacia atrás (abierta) */
.pack3d-bisagra {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--pack3d-w);
  height: 0;
  transform: translateX(-50%)
             translateY(calc(var(--pack3d-h) / -2))
             translateZ(calc(var(--pack3d-d) / -2));
  transform-style: preserve-3d;
}
.pack3d-tapa {
  left: 0;
  top: 0;
  width: 100%;
  height: var(--pack3d-d);
  transform-origin: 50% 0;
  transform: rotateX(90deg);
  /* al abrirse pasa de 180°, así que se ve su reverso: sin esto desaparecería */
  backface-visibility: visible;
  filter: brightness(1.3);
  box-shadow: inset 0 0 0 1px var(--amber-line);
}

/* ---- Fase 3/4: los sobres, DE PIE dentro de la caja ----
   Sin overflow de ningún tipo (aplanaría el 3D). Cada sobre se coloca en
   profundidad con --i (su índice) y --n (cuántos hay): se reparten simétricos
   respecto al centro, ocupando ~el 88% del fondo de la caja. */
.pack3d-interior-sobres {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--pack3d-w);
  height: var(--pack3d-h);
  transform: translate(-50%, -50%);
  transform-style: preserve-3d;
  pointer-events: none;   /* solo los sobres reciben clic, no el hueco */
}
.pack3d-sobre {
  --paso: calc(var(--pack3d-d) * .88 / var(--n));
  --z: calc((var(--i) - (var(--n) - 1) / 2) * var(--paso));
  /* apoyado en el suelo: su base coincide con el fondo de la caja, así que
     asoma por arriba tanto como su alto exceda al de la caja */
  --y: calc((var(--pack3d-h) - var(--pack3d-sobre-h)) / 2);
  --alza: 0px;
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--pack3d-sobre-w);
  height: var(--pack3d-sobre-h);
  transform: translate(-50%, -50%)
             translateY(calc(var(--y) + var(--alza)))
             translateZ(var(--z));
  transform-style: preserve-3d;
  transition: transform 200ms var(--ease), filter 200ms var(--ease);
  border: 0;
  padding: 0;
  font: inherit;
  background: none;
  cursor: pointer;
  opacity: 0;               /* invisibles hasta que la caja se abre */
  pointer-events: none;
}
.pack3d--abierta .pack3d-sobre { opacity: 1; pointer-events: auto; }

.pack3d-sobre-frente {
  position: absolute;
  inset: 0;
  border-radius: 3px;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.07);
}
/* canto brillante en el borde superior: es lo que de verdad da la lectura de
   "muchos sobres apretados" al mirarlos desde arriba */
.pack3d-sobre-canto {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 4px;
  background: linear-gradient(180deg, rgba(255,255,255,.5), rgba(255,255,255,.06));
  border-radius: 3px 3px 0 0;
}

/* Fase 4: levantar SOLO el sobre bajo el cursor (o con foco de teclado) */
@media (hover: hover) {
  .pack3d--abierta .pack3d-sobre:hover { --alza: -46px; filter: brightness(1.35); }
}
.pack3d--abierta .pack3d-sobre:focus-visible {
  --alza: -46px;
  filter: brightness(1.35);
  outline: 2px solid var(--amber);
  outline-offset: 3px;
}
/* mismo efecto forzado por JS (SRF.pack3d.liftEnvelopeOnHover), para la vista
   previa del panel y para poder demostrarlo sin ratón */
.pack3d--abierta .pack3d-sobre.es-hover-forzado { --alza: -46px; filter: brightness(1.35); }
.pack3d-sobre:disabled { cursor: not-allowed; filter: grayscale(.7) brightness(.55); }

/* seleccionado: sale del todo de la caja, hacia cámara */
.pack3d-sobre.es-seleccionado {
  --alza: -150px;
  transform: translate(-50%, -50%)
             translateY(calc(var(--y) + var(--alza)))
             translateZ(calc(var(--pack3d-d) / 2 + 140px))
             rotateY(8deg);
  filter: brightness(1.5) drop-shadow(0 26px 40px rgba(0,0,0,.7));
  transition: transform 420ms var(--ease), filter 420ms var(--ease);
}
/* al elegir uno, el resto y la propia caja se apartan visualmente */
.pack3d-interior-sobres.con-seleccion .pack3d-sobre:not(.es-seleccionado) { opacity: 0; pointer-events: none; }
.pack3d-portal.con-seleccion .pack3d-cara,
.pack3d-portal.con-seleccion .pack3d-interior,
.pack3d-portal.con-seleccion .pack3d-tapa { opacity: .18; }

/* ---- Fase 3: tamaño de la caja abierta ---- */
/* DOS escalas independientes, cada una uniforme dentro de sí misma — nunca
   valores sueltos por eje, o el arte se recorta (ver más abajo):
     · caja  ×1.2 de la base 200:250:130   → 240×300×156
     · sobre ×1.4 de la base 165:235       → 231×329
   front/top/side/interior pintan un recorte FIJO de Tcg::ZONAS_CAJA
   (proporción 4:5, 1.538:1 y 1:1.923 — ver §14.1 de branding/CLAUDE.md) y el
   sobre otro de Tcg::ZONAS_SOBRE (1:1.427): cualquier forma que no respete
   esas proporciones hace que `background-size: cover` recorte trozos reales
   del arte — el bug de "la plantilla se ve cortada".
   Las DOS escalas tienen que ser distintas a propósito: el sobre (329 alto)
   es más alto que la caja (300 alto) para que asome por encima del borde
   como una caja de cromos real abierta («sobresaliendo un poco por encima»,
   ver cabecera de components/caja3d.php) — iguales, la caja tapa los sobres
   enteros y no se ve ninguno (lo que pasó al probar con una sola escala
   1.6× para las dos). Al mismo tiempo el sobre se queda MÁS ESTRECHO que la
   caja (231 < 240): si fuera más ancho asomaría también por los LADOS, el
   mismo defecto de "atraviesa el contenedor" que ya se corrigió para la
   carta de la ceremonia en escenaCarta() (ceremonia.js). */
.pack3d--abierta {
  --pack3d-w: 240px;
  --pack3d-h: 300px;
  --pack3d-d: 156px;
  --pack3d-sobre-w: 231px;
  --pack3d-sobre-h: 329px;
  margin: 0;
}

/* ---- Fase 2: submenú de tipos de sobre de una expansión ---- */
/* [hidden] tiene la MISMA especificidad que .submenu-tipos (0-1-0): sin el
   ":not([hidden])", esta regla -que llega después en la cascada- le gana al
   "display:none" del navegador y el submenú se queda visible siempre,
   superpuesto a la vitrina, aunque sobres.js ponga/quite el atributo bien. */
.submenu-tipos:not([hidden]) {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  gap: var(--space-8);
  padding-block: var(--space-6);
}
.submenu-tipos-cabecera {
  flex-basis: 100%;
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}
.submenu-tipos-cabecera h2 { margin: 0; }
.submenu-tipos-cabecera p { margin: 0; }
.submenu-tipo {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-2);
}
.js-tipo-sobre { cursor: pointer; display: block; }
.js-tipo-sobre:focus-visible { outline: 2px solid var(--amber); outline-offset: 8px; border-radius: var(--radius-md); }
.submenu-tipo-nombre { font-weight: var(--fw-semibold); text-align: center; }
.submenu-tipo-precio {
  display: flex; align-items: center; gap: var(--space-1);
  font-family: var(--font-mono); font-weight: var(--fw-semibold); color: var(--amber-light);
}

/* rótulo de la caja abierta, dentro del portal */
.pack3d-portal-titulo {
  display: none;
  text-align: center;
  margin-top: var(--space-6);
}
.pack3d-portal.esta-abierta .pack3d-portal-titulo { display: block; }

/* sin movimiento: ni flotación, ni tilt, ni levantado al hover — cada fase
   deja su estado final sin transición */
:root[data-motion="reduce"] .pack3d-volumen { animation: none; }
:root[data-motion="reduce"] .pack3d-sobre { transition: none; }
:root[data-motion="reduce"] .pack3d-sobre:hover,
:root[data-motion="reduce"] .pack3d-sobre:focus-visible,
:root[data-motion="reduce"] .pack3d-sobre.es-hover-forzado { --alza: -46px; }

@media (max-width: 760px) {
  .vitrina-grid { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: var(--space-6); }
  .pack3d { --pack3d-w: 150px; --pack3d-h: 185px; --pack3d-d: 95px; --pack3d-sobre-w: 122px; --pack3d-sobre-h: 172px; }
  /* mismas DOS escalas que la variante de escritorio (caja ×1.2, sobre ×1.4
     de sus respectivas bases), ver nota ahí: no valores sueltos, o el arte
     vuelve a recortarse y los sobres dejan de asomar por encima. */
  .pack3d--abierta {
    --pack3d-w: 180px; --pack3d-h: 222px; --pack3d-d: 114px;
    --pack3d-sobre-w: 171px; --pack3d-sobre-h: 241px;
  }
  .pack3d--abierta .pack3d-sobre:hover, .pack3d--abierta .pack3d-sobre.es-hover-forzado { --alza: -34px; }
}

/* ==========================================================================
   4b. CEREMONIA DE APERTURA
   Se reserva movimiento largo para este momento y para el duelo; el resto de
   la interfaz se mantiene sobria. La lógica de ritmo vive en assets/js/sobres.js.
   ========================================================================== */
/* La mesa tiene que caber en pantalla: el sobre se mira, no se navega.
   El número de columnas y el tamaño de la carta se calculan para que el modal
   entre completo en el viewport sin scroll. */
/* :not([hidden]) por la misma razón que .cer-escena/.cer-walkout/
   .cer-aviso-motion: ceremonia.js hace mesa.hidden = true/false y sin el
   guard esta regla de autor le ganaría siempre al [hidden] de user-agent. */
/* minmax(110px, 170px), NO 1fr: con "1fr" una mesa de una sola carta (un
   cofre que solo suelta una, el caso más común) tenía una única columna que
   se estiraba a los 780px del modal entero y, con aspect-ratio 5/7 en la
   carta, se disparaba también en alto — el "se ve ultra grande" que se vio
   al probarlo. Con un tope fijo la carta para en su tamaño natural aunque
   sea la única, y justify-content la centra en vez de pegarla a la
   izquierda cuando la fila no se llena. */
.ceremonia-mesa:not([hidden]) {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 170px));
  justify-content: center;
  gap: var(--space-3);
  perspective: 1200px;
}
.ceremonia .modal-caja {
  display: flex;
  flex-direction: column;
  max-height: 92svh;
  overflow: hidden;          /* el contenido se ajusta, no se desplaza */
}
/* La mesa es la única parte que puede crecer más de lo que cabe en pantalla
   (sobres con muchas cartas). Sin overflow-y aquí, .modal-caja (overflow:
   hidden, arriba) fuerza a la mesa a encogerse por flexbox, pero su rejilla
   de cartas —que es overflow:visible por defecto— se desborda igualmente
   por encima y se solapa con la cabecera y con los botones del pie, que
   quedan enterrados entre cartas en vez de fijos. Dándole scroll propio, la
   cabecera y el pie quedan siempre fijos alrededor y el sobre entero, del
   tamaño que sea, es alcanzable. */
.ceremonia .ceremonia-mesa { min-height: 0; overflow-y: auto; overflow-x: hidden; }

/* Resumen del cofre: monedas y bonus (camino perfecto, formación), por
   encima de las cartas si trae alguna. Un cofre solo-monedas no tiene mesa
   que enseñar, así que este es el único rastro visible del botín — tiene
   que sostenerse solo. */
.cer-cofre-bonus {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
}
.cer-cofre-bonus span {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--success) 45%, var(--line));
  background: color-mix(in srgb, var(--success) 14%, transparent);
  color: var(--frost);
  font-size: var(--fs-body-sm);
}
.cer-cofre-bonus span i { color: var(--success); }

/* ==========================================================================
   ESCENA DE APERTURA — inmersiva y a pantalla completa.

   Mientras dura la apertura, el modal deja de parecer un modal: se le quita
   caja, borde, cabecera y pie, y queda solo el fondo negro con el sobre. Es
   deliberado: los botones y el marco competían con lo único que importa mirar.
   El único control es .cer-saltar, discreto, arriba a la derecha. Al llegar al
   resumen se quita .es-inmersiva y vuelve el modal normal (título, Continuar).

   EL SOBRE está construido como uno real:
     · proporción 1 : 1.9, como un sobre de Adrenalyn / Pokémon
     · dos bandas TERMOSELLADAS (arriba y abajo) con su estriado vertical fino
     · borde dentado en el filo de cada banda (el corte "pinking")
     · reflejo de film que barre al aparecer
   La banda de arriba (.cer-sobre-tira) es la que se rasga y sale volando.
   ========================================================================== */

/* ---- el escenario ---- */
.ceremonia.es-inmersiva { background: radial-gradient(ellipse at 50% 45%, #0d0a08, #000 72%); }
.ceremonia.es-inmersiva .modal-caja {
  max-width: none;
  width: 100%;
  height: 100%;
  max-height: none;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
}
.ceremonia.es-inmersiva .modal-head,
.ceremonia.es-inmersiva .modal-pie,
.ceremonia.es-inmersiva .ceremonia-mesa,
.ceremonia.es-inmersiva .cer-aviso-motion { display: none; }

/* [hidden] tiene la MISMA especificidad que .cer-escena (0-1-0): sin el
   ":not([hidden])", esta regla -que llega después en la cascada- le gana al
   "display:none" del navegador (mismo problema que ya se documentó para
   .submenu-tipos, ver más abajo). Sin este guard, escena.hidden = true
   (terminar(), en ceremonia.js) NO ocultaba nada: la escena de apertura se
   quedaba pintada por encima del resumen, mezclando el sobre/carta a medio
   animar con la mesa de cartas reveladas — el "se queda ahí bugueado" que
   se veía tras usar "Saltar". */
.cer-escena:not([hidden]) {
  --cer-crimp: 7%;          /* alto de cada banda termosellada */
  --cer-diente: 9px;        /* paso del dentado del filo */
  position: relative;
  flex: 1;
  min-height: 0;
  display: block;
}

/* control único, discreto */
.cer-saltar {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  z-index: 9;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 10px 16px;
  min-height: 44px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(255, 255, 255, .05);
  color: var(--frost-dim);
  font: inherit;
  font-size: var(--fs-caption);
  text-transform: uppercase;
  letter-spacing: .08em;
  cursor: pointer;
  transition: color var(--t-micro) var(--ease), border-color var(--t-micro) var(--ease);
}
.cer-saltar:hover { color: var(--frost); border-color: var(--line-strong); }
.cer-saltar:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; }

/* ---- el sobre ---- */
/* Sin `transform` de centrado en CSS: lo escribe GSAP entero (xPercent /
   yPercent), igual que en .cer-carta. Si se dejara aquí un
   translate(-50%,-50%), el primer tween lo machacaría y el sobre se iría a
   la esquina. */
.cer-sobre {
  position: absolute;
  left: 50%;
  top: 50%;
  width: clamp(150px, 21vh, 215px);
  aspect-ratio: 1 / 1.9;
  transform-style: preserve-3d;
  z-index: 3;
  filter: drop-shadow(0 30px 44px rgba(0, 0, 0, .8));
}

/* plástico: la textura de la plantilla, con un sombreado lateral que le da
   el abombamiento del sobre lleno */
.cer-sobre-cuerpo {
  position: absolute;
  inset: 0;
  background-color: var(--panel);
  background-image:
    radial-gradient(ellipse 82% 58% at 50% 22%, var(--amber-soft), transparent 70%),
    linear-gradient(168deg, var(--void-2), #08090C);
  background-size: cover;
  background-position: center;
  z-index: 3;
}
/* abombamiento + brillo de film, encima de la textura */
.cer-sobre-cuerpo::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgba(0,0,0,.42) 0 4%, transparent 16% 84%, rgba(0,0,0,.42) 96% 100%),
    linear-gradient(90deg, transparent 30%, rgba(255,255,255,.09) 42% 50%, transparent 62%);
  pointer-events: none;
}

/* bandas termoselladas: estriado vertical fino, el detalle que hace que se
   lea como un sobre y no como una tarjeta */
.cer-sobre-sellado,
.cer-sobre-tira {
  position: absolute;
  left: 0;
  right: 0;
  height: var(--cer-crimp);
  background-color: color-mix(in srgb, var(--panel) 70%, #fff 30%);
  background-image:
    repeating-linear-gradient(90deg,
      rgba(0,0,0,.34) 0 1px,
      rgba(255,255,255,.16) 1px 3px);
  z-index: 4;
}
.cer-sobre-sellado { bottom: 0; }
.cer-sobre-tira    { top: 0; transform-origin: bottom center; }

/* filo dentado: triángulos del color del escenario recortando el borde.
   Se pintan encima en vez de usar mask, para que no dependa del soporte de
   mask-image en el navegador. */
.cer-sobre-sellado::after,
.cer-sobre-tira::after {
  content: '';
  position: absolute;
  left: -1px;
  right: -1px;
  height: 6px;
  background:
    repeating-linear-gradient(90deg,
      #000 0 calc(var(--cer-diente) * .22),
      transparent calc(var(--cer-diente) * .22) calc(var(--cer-diente) * .5),
      #000 calc(var(--cer-diente) * .5) var(--cer-diente));
}
.cer-sobre-sellado::after { bottom: -1px; }
.cer-sobre-tira::after    { top: -1px; }

/* boca: el hueco oscuro que aparece al arrancar la tira */
.cer-sobre-boca {
  position: absolute;
  left: 4%;
  right: 4%;
  top: 0;
  height: calc(var(--cer-crimp) + 6%);
  border-radius: 0 0 6px 6px;
  background: linear-gradient(180deg, #000 40%, rgba(0,0,0,.3));
  box-shadow: inset 0 8px 16px rgba(0,0,0,.95);
  z-index: 2;
  opacity: 0;
}

/* reflejo que barre el film al aparecer el sobre */
.cer-sobre-brillo {
  position: absolute;
  inset: 0;
  z-index: 5;
  background: linear-gradient(102deg,
    transparent 36%, rgba(255,255,255,.3) 47%, rgba(255,255,255,.06) 53%, transparent 60%);
  pointer-events: none;
  opacity: 0;
}

/* ---- el cofre (ceremonia_cofre.js) ----
   Misma lógica que el sobre: sin `transform` de centrado en CSS, lo escribe
   GSAP entero. La tapa gira sobre una bisagra trasera (transform-origin
   abajo, rotateX negativo levanta el borde de delante). */
.cer-cofre {
  position: absolute;
  left: 50%;
  top: 50%;
  width: clamp(160px, 22vh, 220px);
  aspect-ratio: 1 / .82;
  transform-style: preserve-3d;
  z-index: 3;
  filter: drop-shadow(0 30px 44px rgba(0, 0, 0, .8));
}
.cer-cofre-cuerpo {
  position: absolute;
  inset: 14% 0 0;
  border-radius: var(--radius-lg);
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--amber) 22%, var(--panel)) 0%, var(--void-2) 78%);
  border: 1px solid var(--line-strong);
  box-shadow: inset 0 -10px 18px rgba(0, 0, 0, .5);
  z-index: 2;
}
.cer-cofre-cierre {
  position: absolute;
  left: 50%;
  top: 12%;
  width: 15%;
  aspect-ratio: 1;
  transform: translateX(-50%);
  border-radius: var(--radius-sm);
  background: linear-gradient(180deg, var(--amber-light), var(--amber));
  box-shadow: 0 2px 8px rgba(0, 0, 0, .5);
  z-index: 4;
}
.cer-cofre-tapa {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 34%;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--amber) 30%, var(--panel)), var(--panel));
  border: 1px solid var(--line-strong);
  border-bottom: none;
  transform-origin: bottom center;
  z-index: 5;
}
/* el brillo del interior, revelado al abrirse la tapa. z-index por ENCIMA
   del cuerpo (2): es opaco, así que un brillo detrás de él no se vería
   nunca — mismo motivo que el z-index de .cer-sobre-boca sobre el cuerpo. */
.cer-cofre-brillo {
  position: absolute;
  left: 8%;
  right: 8%;
  top: 16%;
  height: 26%;
  border-radius: 50%;
  background: radial-gradient(ellipse, var(--amber-light), transparent 72%);
  filter: blur(6px);
  opacity: 0;
  z-index: 3;
}

/* ---- la carta que sale ---- */
/* Sin `transform` en CSS a propósito: lo escribe GSAP entero. El giro va con
   rotationY desde JS, nunca con una clase — un transform en línea de GSAP le
   gana siempre a una regla de clase y la carta se quedaría sin girar. */
.cer-carta {
  position: absolute;
  left: 50%;
  top: 50%;
  width: clamp(170px, 30vh, 260px);
  aspect-ratio: 5 / 7;
  transform-style: preserve-3d;
  border: 0;
  padding: 0;
  background: none;
  cursor: pointer;
  z-index: 2;              /* DETRÁS del sobre hasta que asoma por la boca */
  opacity: 0;
}
.cer-carta:focus-visible { outline: 2px solid var(--amber); outline-offset: 8px; border-radius: var(--radius-lg); }
.cer-carta-cara {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  display: block;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: 0 20px 40px rgba(0,0,0,.6);
}
.cer-carta-dorso .carta-dorso {
  display: grid;
  place-items: center;
  width: 100%; height: 100%;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line-strong);
  background:
    repeating-linear-gradient(135deg, rgba(255,255,255,.035) 0 9px, transparent 9px 18px),
    linear-gradient(180deg, var(--panel), var(--void));
  color: rgba(255,255,255,.2);
  font-size: 54px;
}
.cer-carta-frente { transform: rotateY(180deg); }
.cer-carta-frente .carta { width: 100%; height: 100%; }
.cer-carta-aura {
  position: absolute;
  inset: -22%;
  border-radius: 50%;
  background: radial-gradient(circle, var(--rz-aura, var(--amber)), transparent 62%);
  opacity: 0;
  pointer-events: none;
  z-index: -1;
  filter: blur(18px);
}

.cer-pista, .cer-contador {
  position: absolute;
  left: 0; right: 0;
  margin: 0;
  text-align: center;
  color: var(--frost-dim);
  font-size: var(--fs-caption);
  z-index: 7;
}
.cer-pista {
  bottom: var(--space-6);
  text-transform: uppercase;
  letter-spacing: .08em;
}
.cer-contador { top: var(--space-6); }

/* ---- walkout: solo legendaria (5) y SRF (6) ---- */
/* z-index 9: por ENCIMA de .cer-carta (máx. 6) y de .cer-pista/.cer-contador
   (7) a propósito — el walkout tiene que tapar sobre y carta mientras dura
   la tensión, y solo al desvanecerse (pedirVolteo, tramo final) deja ver la
   carta ya volteada debajo. Antes iba en z-index 5, POR DEBAJO de la carta,
   así que se veía la carta encima y la animación enterrada al fondo.
   :not([hidden]) por el mismo motivo que .cer-escena y .cer-aviso-motion:
   sin él, este display:grid (regla de autor) le gana siempre al display:none
   de [hidden] (regla de user-agent), así que walkout.hidden = true (fuera de
   una revelación legendaria/SRF) no ocultaba nada de verdad — el fondo
   oscurecido del walkout se veía DETRÁS de cada carta común también,
   mientras .cer-escena estuviera visible, no solo en las exclusivas. */
.cer-walkout:not([hidden]) {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
  z-index: 9;
  background: radial-gradient(ellipse at center, rgba(0,0,0,.35), rgba(0,0,0,.93) 66%);
}
.cer-walkout-rayos {
  position: absolute;
  width: 150vmax;
  aspect-ratio: 1;
  border-radius: 50%;
  background: conic-gradient(
    from 0deg,
    transparent 0deg 8deg, var(--rz-aura, var(--amber)) 9deg 11deg, transparent 12deg 26deg,
    transparent 26deg 34deg, var(--rz-aura, var(--amber)) 35deg 37deg, transparent 38deg 52deg);
  opacity: .45;
  mask-image: radial-gradient(circle, transparent 12%, #000 26%, #000 52%, transparent 66%);
  -webkit-mask-image: radial-gradient(circle, transparent 12%, #000 26%, #000 52%, transparent 66%);
}
.cer-walkout-texto { position: relative; text-align: center; }
.cer-walkout-rareza {
  display: block;
  font-size: clamp(34px, 9vw, 84px);
  font-weight: var(--fw-bold);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 0 30px var(--rz-aura, var(--amber)), 0 0 84px var(--rz-aura, var(--amber));
}
.cer-walkout-nombre {
  display: block;
  margin-top: var(--space-2);
  font-family: var(--font-mono);
  font-size: clamp(15px, 2.6vw, 22px);
  letter-spacing: .04em;
  color: var(--frost);
  text-shadow: 0 0 20px rgba(0, 0, 0, .8);
}

@media (max-width: 600px) {
  .cer-sobre { width: clamp(130px, 19vh, 170px); }
  .cer-cofre { width: clamp(140px, 20vh, 175px); }
  .cer-carta { width: clamp(150px, 27vh, 200px); }
  .cer-saltar { top: var(--space-3); right: var(--space-3); }
}

/* Con movimiento reducido la escena no se usa: ceremonia.js va directo al
   resumen. Se apaga también por CSS por si el modo cambia a media sesión. */
:root[data-motion="reduce"] .cer-escena { display: none; }

/* aviso de "puedes activar las animaciones solo en esta web": aparece en el
   resumen cuando la ceremonia se saltó por la preferencia del SISTEMA.
   :not([hidden]) por el mismo motivo que .cer-escena más arriba: sin él,
   este display:flex (regla de autor) le gana al display:none de [hidden]
   (regla de user-agent) pase lo que pase — así que ofrecerAnimaciones()
   podía marcar avisoMotion.hidden = true y el aviso seguía viéndose en
   cuanto .es-inmersiva dejaba de taparlo con su propio display:none. Es la
   causa de "el aviso sigue saliendo aunque ya haya activado animaciones". */
.cer-aviso-motion:not([hidden]) {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-top: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--amber-line);
  border-radius: var(--radius-md);
  background: var(--amber-soft);
}
.cer-aviso-motion p {
  margin: 0;
  flex: 1;
  min-width: 220px;
  font-size: var(--fs-body-sm);
  color: var(--frost);
}
.cer-aviso-motion p .ph { color: var(--amber-light); margin-right: var(--space-1); }
.cer-aviso-motion-botones { display: flex; gap: var(--space-2); flex-wrap: wrap; }

/* dentro de la ceremonia la carta va al grano: rareza, arte y nombre */
.ceremonia .carta-meta { display: none; }
.ceremonia .carta-nombre { -webkit-line-clamp: 1; }

@media (max-width: 600px) {
  /* tres columnas fijas: cinco cartas caben en dos filas sin encogerse tanto
     que el arte deje de leerse */
  .ceremonia-mesa { grid-template-columns: repeat(3, 1fr); gap: var(--space-2); }
  .ceremonia .modal-caja { padding: var(--space-4); }
  .ceremonia .modal-head { margin-bottom: var(--space-4); }
  .ceremonia .modal-pie { margin-top: var(--space-4); }
  .ceremonia .carta-nombre { font-size: 11px; }
  /* se quita el hexágono de afinidad para que la etiqueta de rareza conserve
     su texto: la rareza es lo que importa en este momento */
  .ceremonia .carta-afinidad { display: none; }
  .ceremonia .rz { font-size: 8.5px; padding: 3px 5px; }
}

/* pantallas bajas (móvil apaisado): la mesa se ciñe al alto disponible */
@media (max-height: 560px) {
  .ceremonia-mesa { grid-template-columns: repeat(5, 1fr); gap: var(--space-2); }
  .ceremonia .carta-cuerpo { display: none; }
}

.ranura {
  position: relative;
  transform-style: preserve-3d;
  transition: transform 560ms var(--ease);
}
.ranura-cara { backface-visibility: hidden; }
/* el frente va en el flujo: es quien define la altura de la ranura */
.ranura-frente { transform: rotateY(180deg); }
.ranura-dorso { position: absolute; inset: 0; }
.ranura.esta-volteada { transform: rotateY(180deg); }

/* fanfarria de legendario y SRF: un resplandor que acompaña al volteo */
.ranura.con-fanfarria::after {
  content: '';
  position: absolute;
  inset: -10px;
  z-index: -1;
  border-radius: var(--radius-xl);
  background: radial-gradient(circle, var(--amber-light), transparent 68%);
  animation: fanfarria 1.5s var(--ease-out) forwards;
}
.ranura[data-rareza="6"].con-fanfarria::after {
  background: radial-gradient(circle, #fff, transparent 70%);
}
@keyframes fanfarria {
  0%   { opacity: 0; transform: scale(.7); }
  35%  { opacity: .85; transform: scale(1.05); }
  100% { opacity: 0; transform: scale(1.2); }
}

/* el propio modal reacciona a la mejor carta del sobre */
.ceremonia .modal-caja.es-legendario { box-shadow: var(--shadow-lg), 0 0 60px -12px var(--amber); }
.ceremonia .modal-caja.es-srf {
  border-color: rgba(255, 255, 255, .5);
  box-shadow: var(--shadow-lg), 0 0 80px -10px rgba(255, 255, 255, .4);
  animation: pulsoSrf 2.4s ease-in-out infinite;
}
@keyframes pulsoSrf {
  0%, 100% { box-shadow: var(--shadow-lg), 0 0 70px -14px rgba(255, 255, 255, .3); }
  50%      { box-shadow: var(--shadow-lg), 0 0 100px -8px rgba(255, 255, 255, .5); }
}

/* aura anticipatoria de rareza (§14.4): se enciende justo antes del volteo,
   GSAP controla opacidad/escala; el color depende de la rareza real de la
   carta, así el jugador intuye lo que va a salir antes de verlo. */
.ranura[data-rareza="1"] { --aura-color: var(--rz1); }
.ranura[data-rareza="2"] { --aura-color: var(--rz2); }
.ranura[data-rareza="3"] { --aura-color: var(--rz3); }
.ranura[data-rareza="4"] { --aura-color: var(--rz4); }
.ranura[data-rareza="5"] { --aura-color: var(--rz5); }
.ranura[data-rareza="6"] { --aura-color: var(--rz6); }
.ranura-aura {
  position: absolute;
  inset: -18px;
  z-index: -2;
  border-radius: var(--radius-xl);
  opacity: 0;
  pointer-events: none;
  background: radial-gradient(circle, var(--aura-color, var(--rz1)), transparent 70%);
  filter: blur(2px);
}

/* secuencia FUT (§14.6): preámbulo exclusivo para legendaria y SRF, una
   carta a la vez, por encima de la mesa. Reutiliza --aura-color de la ranura. */
.ceremonia-fut {
  position: absolute;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: var(--radius-xl);
  background: rgba(4, 5, 7, .92);
  opacity: 0;
  pointer-events: none;
}
.ceremonia-fut-rayos {
  position: absolute;
  inset: -50%;
  background: conic-gradient(from 0deg,
    transparent 0 10deg, var(--aura-color, var(--amber)) 10deg 12deg, transparent 12deg 45deg);
  opacity: .35;
}
.ceremonia-fut-nombre {
  position: relative;
  text-align: center;
  padding-inline: var(--space-4);
  font-family: var(--font-mono);
  color: var(--frost);
  text-shadow: 0 0 24px var(--aura-color, var(--amber));
}
.ceremonia-fut-nombre .fut-rareza {
  display: block;
  font-size: var(--fs-h2);
  font-weight: var(--fw-bold);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--aura-color, var(--amber));
}
.ceremonia-fut-nombre .fut-nombre {
  display: block;
  font-size: var(--fs-h1);
  font-weight: var(--fw-bold);
}

/* destello de pantalla: exclusivo de la SRF */
.ceremonia-destello {
  position: fixed;
  inset: 0;
  z-index: calc(var(--z-modal) + 1);
  pointer-events: none;
  background: radial-gradient(circle at 50% 42%, rgba(255, 255, 255, .5), transparent 60%);
  animation: destello 800ms var(--ease-out) forwards;
}
@keyframes destello {
  0%   { opacity: 0; }
  16%  { opacity: 1; }
  100% { opacity: 0; }
}

/* Movimiento reducido: sin volteo, sin fanfarria, sin destello. Las cartas
   ya salen reveladas desde JavaScript, así que aquí solo se anula el 3D. */
:root[data-motion="reduce"] .ranura,
:root[data-motion="reduce"] .ranura.esta-volteada { transform: none; transition: none; }
:root[data-motion="reduce"] .ranura-frente { transform: none; }
:root[data-motion="reduce"] .ranura-dorso,
:root[data-motion="reduce"] .ranura.con-fanfarria::after,
:root[data-motion="reduce"] .ceremonia-destello { display: none; }
:root[data-motion="reduce"] .ceremonia .modal-caja.es-srf { animation: none; }
:root[data-motion="reduce"] .ranura-aura,
:root[data-motion="reduce"] .ceremonia-fut { display: none; }
/* la escena de apertura ya se apaga en su propio bloque (.cer-escena) */

/* ==========================================================================
   5. PANEL / TARJETA GENÉRICA
   ========================================================================== */
.panel {
  padding: var(--space-5);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--panel);
}
.panel-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.panel-titulo { font-size: var(--fs-h3); font-weight: var(--fw-semibold); }

/* cifra destacada de dashboard: el dato en mono, la etiqueta en caption */
.dato { display: flex; flex-direction: column; gap: var(--space-1); }
.dato b {
  font-family: var(--font-mono);
  font-size: clamp(1.5rem, 1.2rem + 1.2vw, 1.875rem);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.dato span {
  font-size: var(--fs-caption-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caption);
  text-transform: uppercase;
  color: var(--frost-dim);
}

/* ==========================================================================
   6. ALERTA
   ========================================================================== */
.alerta {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .03);
  font-size: var(--fs-body-sm);
  line-height: var(--lh-body);
  color: var(--frost-dim);
}
.alerta i { font-size: 18px; flex-shrink: 0; margin-top: 1px; }
.alerta-success { background: var(--success-bg); border-color: var(--success-line); color: var(--success-text); }
.alerta-warning { background: var(--warning-bg); border-color: var(--warning-line); color: var(--warning-text); }
.alerta-danger  { background: var(--danger-bg);  border-color: var(--danger-line);  color: var(--danger-text); }
.alerta-info    { background: var(--info-bg);    border-color: var(--info-line);    color: var(--info-text); }

/* ==========================================================================
   7. PASTILLA DE ESTADO
   Lleva punto + texto: el color nunca es la única señal.
   ========================================================================== */
.pastilla {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 4px var(--space-3);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, .04);
  font-size: var(--fs-caption-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: .04em;
  color: var(--frost-dim);
}
.pastilla::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pastilla-on   { background: var(--success-bg); border-color: var(--success-line); color: var(--success-text); }
.pastilla-warn { background: var(--warning-bg); border-color: var(--warning-line); color: var(--warning-text); }
.pastilla-off  { background: var(--danger-bg);  border-color: var(--danger-line);  color: var(--danger-text); }

/* ==========================================================================
   8. BARRA DE PROGRESO (álbum, misiones)
   ========================================================================== */
.progreso { display: flex; align-items: center; gap: var(--space-3); min-width: 180px; }
.progreso-riel {
  flex: 1;
  height: 6px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, .07);
  overflow: hidden;
}
.progreso-relleno {
  height: 100%;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--amber), var(--amber-light));
  transition: width var(--t-media) var(--ease);
}
.progreso-label {
  font-family: var(--font-mono);
  font-size: var(--fs-caption-sm);
  color: var(--frost-dim);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   9. TABLA DE DATOS
   En móvil hace scroll horizontal controlado, nunca comprime columnas.
   ========================================================================== */
.tabla-wrap {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--panel);
}
.tabla { width: 100%; border-collapse: collapse; min-width: 520px; }
.tabla thead th {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--line);
  text-align: left;
  font-size: var(--fs-caption-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caption);
  text-transform: uppercase;
  color: var(--frost-dim);
  white-space: nowrap;
}
.tabla tbody td {
  padding: var(--space-4);
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-body-sm);
}
.tabla tbody tr:last-child td { border-bottom: 0; }
.tabla tbody tr { transition: background var(--t-micro) var(--ease); }
.tabla tbody tr:hover { background: rgba(255, 255, 255, .03); }
.tabla .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; }

/* ==========================================================================
   10. CHIP DE USUARIO (avatar + monedas)
   ========================================================================== */
.chip-usuario {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 5px var(--space-4) 5px 5px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, .03);
}
.avatar {
  --avatar: 32px;
  width: var(--avatar); height: var(--avatar);
  flex-shrink: 0;
  display: grid;
  place-items: center;
  border-radius: 50%;
  overflow: hidden;
  background: var(--amber);
  color: var(--amber-ink);
  font-size: calc(var(--avatar) * .4);
  font-weight: var(--fw-bold);
  line-height: 1;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--lg { --avatar: 96px; border-radius: var(--radius-xl); }
.avatar--sm { --avatar: 24px; }

.monedas {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  color: var(--amber-light);
}

/* ==========================================================================
   11. TABS
   ========================================================================== */
.tabs {
  display: flex;
  gap: var(--space-5);
  border-bottom: 1px solid var(--line);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  position: relative;
  padding: var(--space-4) 0;
  border: 0;
  background: none;
  color: var(--frost-dim);
  font-size: var(--fs-caption);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caption);
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--t-micro) var(--ease);
}
.tab:hover { color: var(--frost); }
.tab[aria-selected="true"] { color: var(--frost); }
.tab[aria-selected="true"]::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 2px;
  background: var(--amber);
}
.tab-panel[hidden] { display: none; }

/* ==========================================================================
   12. PAGINACIÓN
   ========================================================================== */
.paginacion { display: flex; justify-content: center; gap: var(--space-2); flex-wrap: wrap; }
.pag-btn {
  min-width: 44px;
  height: 44px;
  padding: 0 var(--space-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--frost-dim);
  font-family: var(--font-mono);
  font-size: var(--fs-caption);
  cursor: pointer;
  transition: border-color var(--t-micro) var(--ease), color var(--t-micro) var(--ease);
}
.pag-btn:hover { border-color: var(--line-strong); color: var(--frost); }
.pag-btn[aria-current="page"] { background: var(--amber); border-color: var(--amber); color: var(--amber-ink); font-weight: var(--fw-bold); }

/* ==========================================================================
   13. ESTADO VACÍO
   Siempre indica la siguiente acción posible; nunca deja la pantalla en blanco.
   ========================================================================== */
.vacio {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-5);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
  text-align: center;
}
.vacio-ico {
  display: grid;
  place-items: center;
  width: 52px; height: 52px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: rgba(255, 255, 255, .03);
  font-size: 22px;
  color: var(--frost-dim);
}
.vacio h3 { font-size: var(--fs-h3); }
.vacio p { max-width: 42ch; font-size: var(--fs-body-sm); color: var(--frost-dim); }
.vacio .btn { margin-top: var(--space-2); }

/* ==========================================================================
   14. SKELETON
   ========================================================================== */
.skeleton {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, .06);
}
.skeleton::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .09), transparent);
  animation: brillo 1.6s ease-in-out infinite;
}
@keyframes brillo { 100% { transform: translateX(100%); } }
.skeleton-texto { height: 12px; }
.skeleton-carta { aspect-ratio: 233 / 361; border-radius: var(--radius-lg); }

/* ==========================================================================
   15. MODAL
   Foco atrapado y cierre con Esc los aporta assets/js/ui.js.
   ========================================================================== */
.modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
  background: rgba(6, 7, 9, .72);
  backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t-media) var(--ease), visibility 0s linear var(--t-media);
}
.modal.is-abierto { opacity: 1; visibility: visible; transition: opacity var(--t-media) var(--ease); }

.modal-caja {
  width: 100%;
  max-width: 560px;
  max-height: 88vh;
  overflow-y: auto;
  padding: var(--space-6);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-xl);
  background: var(--panel-2);
  box-shadow: var(--shadow-lg);
  transform: scale(.97) translateY(8px);
  transition: transform var(--t-media) var(--ease);
}
.modal.is-abierto .modal-caja { transform: none; }
.modal-caja--ancha { max-width: 780px; }

.modal-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}
.modal-cerrar {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  margin: calc(var(--space-2) * -1);
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--frost-dim);
  font-size: 20px;
  cursor: pointer;
  transition: color var(--t-micro) var(--ease), background var(--t-micro) var(--ease);
}
.modal-cerrar:hover { color: var(--frost); background: rgba(255, 255, 255, .05); }
.modal-pie { display: flex; justify-content: flex-end; gap: var(--space-3); margin-top: var(--space-6); flex-wrap: wrap; }

/* ==========================================================================
   15b. SELECTOR VISUAL DE CARTAS
   Para elegir una carta entre muchas: se busca y se reconoce por el arte, en
   vez de leer una lista desplegable de cientos de líneas.
   ========================================================================== */
.selector-cartas {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: var(--space-3);
  max-height: 40vh;
  padding: var(--space-1);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.selector-cartas::-webkit-scrollbar { width: 6px; }
.selector-cartas::-webkit-scrollbar-thumb {
  border-radius: var(--radius-pill);
  background: var(--line-strong);
}

/* Selector de jugadores del mazo: cartas más grandes que el resto de
   selectores (apuesta de duelo, venta en mercado) porque aquí hace falta
   leer la afinidad y las estadísticas para decidir la alineación. */
.selector-cartas--grande { grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); }

.selector-item { display: block; cursor: pointer; border-radius: var(--radius-lg); }
.selector-item[hidden] { display: none; }
.selector-item .carta-meta,
.selector-item .carta-afinidad { display: none; }
.selector-item .carta-nombre { font-size: 11px; -webkit-line-clamp: 1; }
.selector-item .rz { font-size: 8.5px; padding: 3px 5px; }

.selector-cartas--grande .carta-afinidad { display: grid; }
.selector-cartas--grande .carta-nombre { font-size: var(--fs-body-sm); -webkit-line-clamp: 2; }
.selector-cartas--grande .rz { font-size: var(--fs-caption-sm); padding: 3px var(--space-2); }

/* el foco del teclado se ve sobre la tarjeta entera, no sobre el radio oculto */
.selector-item:focus-within { outline: 2px solid var(--amber-light); outline-offset: 3px; }
/* marca de elegida: el check va dibujado en CSS, no con un glifo de la fuente
   de iconos, para que no dependa de que Phosphor haya cargado */
.selector-item.esta-elegida { position: relative; }
.selector-item.esta-elegida::before {
  content: '';
  position: absolute;
  top: -7px; right: -7px;
  z-index: 5;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--amber);
  box-shadow: 0 0 0 2px var(--panel-2);
}
.selector-item.esta-elegida::after {
  content: '';
  position: absolute;
  top: -1px; right: 1px;
  z-index: 6;
  width: 5px; height: 9px;
  border-right: 2px solid var(--amber-ink);
  border-bottom: 2px solid var(--amber-ink);
  transform: rotate(45deg);
}

.selector-vacio {
  grid-column: 1 / -1;
  padding: var(--space-6) var(--space-4);
  text-align: center;
  font-size: var(--fs-body-sm);
  color: var(--frost-dim);
}
.selector-vacio[hidden] { display: none; }

/* ==========================================================================
   16. TOAST
   Nunca tapa el foco: se ancla abajo y deja libre la zona de la nav.
   ========================================================================== */
.toast-zona {
  position: fixed;
  left: 50%;
  bottom: var(--space-5);
  z-index: var(--z-toast);
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: min(420px, calc(100vw - var(--space-8)));
  pointer-events: none;
}
.toast {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-md);
  background: var(--panel-2);
  box-shadow: var(--shadow-lg);
  font-size: var(--fs-body-sm);
  pointer-events: auto;
  animation: toastEntra var(--t-media) var(--ease);
}
@keyframes toastEntra { from { opacity: 0; transform: translateY(12px); } }
.toast i { font-size: 18px; }
.toast-success i { color: var(--success); }
.toast-danger i { color: var(--danger); }
.toast-info i { color: var(--info); }
