/* estilo.css — paleta de marca (PALETA-WEB): negro #050505 · hueso #F2F0E9 · amarillo #FFD400.
   Mobile-first, sin dependencias ni fuentes externas (condensada del sistema como eco de
   Archivo Black/Anton hasta que la landing real lo integre con su tipografía). */
:root {
  --negro: #050505; --hueso: #F2F0E9; --amarillo: #FFD400;
  --gris: #8a877f; --linea: #26241f;
  /* escala de SUPERFICIES por elevación (rework UX lote 1): la profundidad se hace ACLARANDO,
     nunca con sombras — y nada "encima" puede ser más oscuro que el fondo (firma del dark
     barato). Base #050505 → panel #141414 → casilla activa #1E1E1E. */
  --sup-1: #141414; --sup-2: #1e1e1e;
  --radio: 10px;
  --muelle: cubic-bezier(.34, 1.56, .64, 1);
  /* 🚦 EL CÓDIGO DE COLOR DE LAS BARRAS, y no hay otro. Tres tramos que salen de `nivelDeBarra()`
     (core/necesidades.mjs) y que son los MISMOS cortes que la cara del Nomms (0,60 y 0,30), así que
     barra y cara no se pueden contradecir. Antes vivía duplicado: ámbar en «Mi Nomms» y rojo en la
     tira de la casa, o sea que la misma barra cambiaba de color según la pestaña. */
  --nivel-ok: #6ee7a8; --nivel-media: #ffd84d; --nivel-baja: #e4574c;
}
* { box-sizing: border-box; }
/* pasada 2 del bucle: foco de teclado de MARCA en TODO lo interactivo (antes solo 3 selectores lo
   tenían → el creador era casi innavegable por teclado, con el anillo azul del navegador). */
:focus-visible { outline: 2px solid var(--amarillo); outline-offset: 2px; border-radius: 3px; }
:focus:not(:focus-visible) { outline: none; }
/* P24 (política Low+): el check del boletín usaba el azul del navegador → de marca (amarillo) */
input[type="checkbox"] { accent-color: var(--amarillo); }
body {
  margin: 0; background: var(--negro); color: var(--hueso);
  font-family: "Avenir Next Condensed", "Arial Narrow", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}
main { max-width: 560px; margin: 0 auto; padding: 28px 18px 64px; }
.kicker { color: var(--gris); letter-spacing: .2em; font-size: 12px; margin: 0 0 6px; }
h1, h2 { font-weight: 900; text-transform: uppercase; letter-spacing: .01em; margin: 0 0 8px; }
h1 { font-size: clamp(34px, 9vw, 52px); line-height: .95; }
h2 { font-size: 22px; }
.acento { color: var(--amarillo); }
.cursor { color: var(--amarillo); animation: parpadeo 1.1s steps(1) infinite; }
@keyframes parpadeo { 50% { opacity: 0; } }
.sub { color: var(--gris); margin: 0 0 18px; }
.meta { color: var(--gris); font-size: 13px; }
.num { font-variant-numeric: tabular-nums; }
/* ⚠️ LA TARJETA DEL JUEGO USA EL MISMO LENGUAJE QUE LA PORTADA, y antes no.
   Medido el 27-jul: era `border-radius: 0` con fondo TRANSPARENTE —un rectángulo de borde fino sobre
   negro— mientras la portada y el panel usaban `--radio: 10px` y superficie rellena (`--sup-1`). El juego
   se veía de otra época que su propia página de inicio.
   Y el hallazgo que lo aclaró: el sistema del juego NO estaba desordenado por dentro (los titulares tenían
   2 variantes, las tarjetas 2, las etiquetas 1 — coherente). La frontera estaba ENTRE la portada y el
   producto, no dentro del producto. Un solo cambio de regla la cierra. */
.tarjeta {
  border: 1px solid var(--linea); border-radius: var(--radio);
  background: var(--sup-1);
  padding: 18px; margin: 18px 0;
}
.oculto { display: none !important; }
/* ⚠️ El `!important` es NECESARIO, no pereza. `.oculto` es una utilidad de una sola clase, así que
   CUALQUIER otra clase que fije `display` y venga después en la cascada la gana. Medido el 27-jul: 4
   elementos llevaban `oculto` puesto y seguían mostrándose, y uno se veía de verdad — `#panel-yo`
   (`.panel-yo { display: flex }` en panel.css, que carga después) pintaba un círculo gris vacío al lado
   del logo en la primerísima pantalla, leyéndose como «algo no ha cargado».
   Es el fallo más traicionero que hay: el código CREE que escondió algo y el usuario lo está viendo. */
label, .etiqueta { display: block; color: var(--gris); font-size: 12px; letter-spacing: .12em; margin: 12px 0 6px; }
input[type="text"], input[type="email"], input[type="password"], input:not([type]) {
  width: 100%; background: transparent; border: 1px solid var(--linea); color: var(--hueso);
  padding: 12px; font-size: 18px; font-family: inherit;
}
input:focus { outline: 2px solid var(--amarillo); border-color: var(--amarillo); }
/* ⚠️ La lista de tipos de arriba llevaba `text` y `email` pero NO `password`, que no existía cuando se
   escribió. Al añadir el login con contraseña el campo salía SIN `width: 100%`: estrecho, con esquinas
   raras y el botón «ver» colgando fuera de la caja. Enumerar tipos de input a mano se rompe así cada vez
   que aparece uno nuevo — si añades otro (`search`, `tel`…), acuérdate de esta línea. */
.paletas { display: grid; grid-template-columns: repeat(8, 1fr); gap: 8px; }
.paletas button {
  aspect-ratio: 1; border: 2px solid var(--linea); cursor: pointer; width: 100%;
  background: var(--c); border-radius: 4px;
}
.paletas button[aria-selected="true"] { border-color: var(--hueso); outline: 2px solid var(--amarillo); }

.btn {
  background: var(--amarillo); color: var(--negro); border: 0; cursor: pointer;
  font: 900 16px/1 inherit; letter-spacing: .06em; padding: 14px 22px; text-transform: uppercase;
}
.btn:hover { filter: brightness(1.08); }
.btn:disabled { opacity: .45; cursor: not-allowed; }
/* 🔴 21-ago-2026 · «REVISA TU CORREO» está deshabilitado a propósito, y NO es un botón roto.
   El `:disabled` genérico lo apagaría al 45% —el mismo aspecto que «no puedes pulsar esto todavía»— y
   justo aquí el mensaje es el contrario: salió bien, y lo que queda por hacer está en su bandeja. Verde
   de acierto, cursor normal (no `not-allowed`: no le has prohibido nada, ya está hecho). */
.btn.btn-enviado:disabled {
  opacity: 1; cursor: default;
  background: transparent; color: var(--nivel-ok);
  box-shadow: inset 0 0 0 2px var(--nivel-ok);
}
/* P19: el botón secundario era "borde-pegatina" hueso 2px — el anti-patrón que la marca
   prohíbe. Ahora superficie elevada + glow al hover (mismo lenguaje que piezas y swatches). */
.btn-secundario { background: var(--sup-1); color: var(--hueso); border: 1px solid var(--linea); }
.btn-secundario:hover { background: var(--sup-2); border-color: #4a463c; box-shadow: 0 0 18px rgba(255, 212, 0, .10); filter: none; }
.saldo { float: right; font-size: 15px; color: var(--amarillo); }
/* CHIP conmutador (el «vivir / editar» de la habitación).
   ⚠️ Esta clase se usaba en el HTML desde F6 y NO TENÍA NINGUNA REGLA: el navegador le ponía su botón por
   defecto y salía un rectángulo BLANCO en medio del tema oscuro. Lo encontré barriendo las clases del HTML
   contra el CSS —tres sin regla, y esta era la que se veía—, no mirando la pantalla: a plano completo el
   ojo lo lee como «un botón» y pasa. Con `aria-pressed` marca su estado encendido en amarillo. */
.chip {
  background: var(--sup-1); color: var(--hueso); border: 1px solid var(--linea);
  font: 700 12px/1 inherit; letter-spacing: .06em;
  padding: 8px 12px; border-radius: 999px; cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.chip:hover { background: var(--sup-2); border-color: #4a463c; }
.chip[aria-pressed="true"] { background: var(--amarillo); color: var(--negro); border-color: var(--amarillo); }
.enlace-suave { background: none; border: 0; color: var(--gris); cursor: pointer; font: inherit; font-size: 13px; text-decoration: underline; padding: 0; }
.enlace-suave:hover { color: var(--hueso); }
.aviso-red { background: #2b2416; color: var(--amarillo); margin: 0; padding: 8px 12px; font-size: 13px; text-align: center; }
/* P20: renombrar solapaba la línea de perfil y tapaba «vale» (peor en móvil). #compartir pasa a
   flex-wrap: el input + «vale» caen ordenados a su propia línea en vez de encimarse. */
#compartir { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.editor-nombre { background: var(--sup-1); color: var(--hueso); border: 1px solid var(--gris); font: inherit; font-size: 14px; padding: 6px 8px; margin-left: 0; max-width: 180px; border-radius: 6px; }
.check { display: flex; gap: 8px; align-items: flex-start; color: var(--hueso); font-size: 14px;
  letter-spacing: 0; text-transform: none; margin: 12px 0; }
.separador { text-align: center; margin: 14px 0 10px; }

/* rework cuerpo-v1: composición por capas (misma cámara/luz → apilar = componer) */
.nomms-capas { position: relative; display: inline-block; flex: none; }
.nomms-capas img { position: absolute; inset: 0; width: 100%; height: 100%; }
.nomms-capas img:first-child { position: relative; } /* la 1ª da tamaño al contenedor */
.nomms-capas canvas { width: 100%; height: 100%; display: block; }
.capas-preview { width: 240px; height: 240px; filter: drop-shadow(0 8px 20px rgba(0,0,0,.6)); }
/* ACABADO: misma fila que el tinte pero botones un poco MÁS grandes y redondos. Un acabado no es un color:
   es de qué está hecha la pieza, y a 24px cuadrado se leía como «otro tinte más». */
.swatches-acabado { display: flex; gap: 7px; flex-wrap: wrap; margin: 2px 0 10px; }
.swatches-acabado button { width: 30px; height: 30px; border-radius: 50%; background: var(--c);
  border: 2px solid #0006; cursor: pointer; }
.swatches-acabado button[aria-pressed="true"] { outline: 2px solid var(--acento, #FFD400); outline-offset: 2px; }
/* el rúnico tiene luz propia en el motor; aquí se marca con un halo, o a tamaño de botón se confunde con
   «un dorado más» y el jugador no ve que es el legendario */
.swatches-acabado button.acabado-brilla { box-shadow: 0 0 8px 2px #C9A22799, inset 0 0 6px #fff6; }
.swatches-tinte { display: flex; gap: 6px; flex-wrap: wrap; margin: 2px 0 10px; }
.swatches-tinte button { width: 24px; height: 24px; border-radius: 3px; background: var(--c);
  border: 2px solid var(--linea); cursor: pointer; padding: 0; }
.swatches-tinte button[aria-pressed="true"] { border-color: var(--hueso); outline: 2px solid var(--amarillo); }
.swatches-tinte .sin-tinte { background: transparent; color: var(--gris); font-size: 13px; line-height: 1; }
.capas-cmp { width: 150px; height: 150px; filter: drop-shadow(0 6px 18px rgba(0,0,0,.6)); }
.capas-ring { width: 130px; height: 130px; filter: drop-shadow(0 6px 16px rgba(0,0,0,.6)); }
.capas-mini { width: 56px; height: 56px; filter: drop-shadow(0 3px 8px rgba(0,0,0,.5)); }
.desbloqueo { border-color: var(--amarillo); box-shadow: 0 0 24px rgba(255,212,0,.12); }
.desbloqueo .btn { margin-right: 10px; margin-top: 6px; }
#cuenta .btn { margin-right: 10px; }
#cuenta-correo { margin-bottom: 12px; }
.versus { display: flex; align-items: center; justify-content: space-around; gap: 8px; }
.versus figure { margin: 0; text-align: center; }
.versus figcaption b { display: block; font-size: 15px; }
.versus figcaption span { color: var(--gris); font-size: 13px; }
.vs { color: var(--amarillo); font-weight: 900; font-size: 20px; }
#btn-lucha { margin-top: 14px; }
#btn-lucha:disabled { opacity: .35; cursor: not-allowed; }
.ring { display: flex; align-items: flex-start; justify-content: space-around; gap: 8px; }
.esquina { margin: 0; text-align: center; }
.esquina figcaption { color: var(--gris); font-size: 13px; margin-top: 4px; }
.hp { height: 8px; background: var(--linea); margin-top: 8px; border-radius: 2px; overflow: hidden; }
.hp-fill { height: 100%; width: 100%; background: var(--amarillo); transition: width .25s ease-out; }
.golpeado { animation: sacudida .3s; }
@keyframes sacudida {
  25% { transform: translateX(-6px) rotate(-3deg); }
  75% { transform: translateX(6px) rotate(3deg); }
}
/* mejora-exhaustiva: combate como espectáculo — daño flotante + flash de la barra HP + victoria */
.esquina { position: relative; }
.dano-flota {
  position: absolute; left: 50%; top: 20%; transform: translateX(-50%); z-index: 3; pointer-events: none;
  font: 900 26px/1 inherit; color: var(--hueso); text-shadow: 0 2px 6px rgba(0, 0, 0, .8);
  animation: sube-dano .85s cubic-bezier(.16, 1, .3, 1) both;
}
.dano-flota.esquiva { color: var(--gris); font-size: 18px; }
/* R09 · el CRÍTICO se anuncia como crítico. Si pega 1,8 veces y sale con la misma pinta que un golpe
 * normal, el jugador solo ve un número más grande y lo lee como suerte: no aprende que la Maña sirve
 * para algo. Va en amarillo, más grande y con su propio arranque (un golpe seco en vez de subir). */
.dano-flota.critico {
  color: var(--amarillo); font-size: 34px; letter-spacing: .02em;
  text-shadow: 0 0 14px rgba(240, 190, 60, .55), 0 2px 6px rgba(0, 0, 0, .9);
  animation-name: sube-critico;
}
@keyframes sube-dano {
  0% { opacity: 0; transform: translate(-50%, 10px) scale(.7); }
  25% { opacity: 1; transform: translate(-50%, -6px) scale(1.1); }
  100% { opacity: 0; transform: translate(-50%, -46px) scale(1); }
}
@keyframes sube-critico {
  0% { opacity: 0; transform: translate(-50%, 4px) scale(1.7); }
  18% { opacity: 1; transform: translate(-50%, -8px) scale(.92); }
  32% { transform: translate(-50%, -12px) scale(1.06); }
  100% { opacity: 0; transform: translate(-50%, -58px) scale(1); }
}
/* R09 · la variante SIN MOVIMIENTO. El número deja de flotar, no de existir: se planta sobre el
 * muñeco, se lee, y `danoFlotante` lo retira por temporizador (sin animación no hay `animationend`
 * que lo borre). Lo pone `app.mjs`, no una media query, porque quien decide es `reducidoMov()`. */
.dano-flota.quieto {
  animation: none; opacity: 1; transform: translate(-50%, -18px);
  background: #12100dcc; border-radius: 8px; padding: 2px 10px;
}
/* ── R08 · EL MARCADOR DE ARRIBA (Street Fighter) ─────────────────────────────────────────────────
 * Estructura; la ESCALA de escena la pone `pantalla.css`. Vida a la izquierda, VS en medio, vida a la
 * derecha. Las dos barras se vacían HACIA EL CENTRO: la de la izquierda ancla a la izquierda y se la
 * comen por su borde derecho, y la de la derecha al revés. Eso es lo que hace que las dos vidas se lean
 * como una sola escena en vez de como dos indicadores sueltos. */
#hud-combate { display: flex; align-items: center; gap: 14px; }
#hud-combate .hud-lado { flex: 1; min-width: 0; }
#hud-combate .hud-fila { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
#hud-combate .hud-b .hud-fila { flex-direction: row-reverse; }   /* espejo: la cifra siempre mira al centro */
#hud-combate .hud-nombre {
  font-weight: 900; font-size: 13px; color: var(--hueso); letter-spacing: .06em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#hud-combate .hud-cifra { font-size: 12px; color: var(--gris); font-variant-numeric: tabular-nums; }
#hud-combate .hp { position: relative; }
#hud-combate .hp-fill, #hud-combate .hp-fantasma { position: absolute; top: 0; bottom: 0; height: auto; }
#hud-combate .hud-a .hp-fill, #hud-combate .hud-a .hp-fantasma { left: 0; }
#hud-combate .hud-b .hp-fill, #hud-combate .hud-b .hp-fantasma { right: 0; }
/* EL RASTRO. Un golpe de 3 sobre 40 de vida mueve la barra 7 px en un cuarto de segundo: eso no se ve,
 * y «que se vea BAJAR la vida» era justo lo pedido. La barra buena cae de golpe (.12s) y el rastro la
 * persigue medio segundo después, así que el mordisco queda visible como un destello que dura.
 * El rastro va en BLANCO ROTO: se probó en rojo y por debajo de un tercio de vida la barra buena ya se
 * pone roja (`.critico`), así que el tramo perdido y el que queda eran el mismo color justo en el
 * momento del combate en el que más falta hace distinguirlos. Se vio en la captura, no en el CSS. */
#hud-combate .hp-fantasma { background: #f3e6c8; opacity: .82; transition: width .55s ease-in .18s; }
#hud-combate .hp-fill { transition: width .12s linear; z-index: 1; }

.hp.flash-hp { animation: flash-barra .28s ease-out; }
@keyframes flash-barra { 0% { box-shadow: 0 0 0 2px var(--amarillo); } 100% { box-shadow: none; } }
.lucha-final.victoria { animation: pulso-victoria .5s var(--muelle); }
@keyframes pulso-victoria { 0% { transform: scale(1); } 40% { transform: scale(1.14); } 100% { transform: scale(1); } }
.cronica { margin-top: 14px; min-height: 72px; max-height: 128px; overflow-y: auto;
  font-size: 14px; color: var(--gris); border-top: 1px solid var(--linea); padding-top: 10px; }
.cronica p { margin: 2px 0; }
.cronica .tuyo { color: var(--hueso); }
.lucha-final { font-weight: 900; font-size: 18px; text-transform: uppercase; min-height: 24px; }
.lucha-final.victoria { color: var(--amarillo); }
/* R11 · el cartel del desenlace. Tres piezas y una jerarquía deliberada: el titular grande, las CIFRAS
 * más grandes todavía (son el premio, y eran justo lo que no se veía), y el gancho pequeño y en minúscula
 * porque es una frase, no un dato. */
.lucha-final p { margin: 0; }
.cartel-titulo { font-size: 20px; line-height: 1.15; }
.cartel-cifras { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 8px !important; }
.cartel-cifras:empty { display: none; }
.cartel-ficha {
  display: inline-block; padding: 4px 11px; border-radius: 999px;
  font-size: 19px; font-weight: 900; letter-spacing: .3px;
  border: 2px solid currentColor; background: #0000004d;
}
.ficha-oro { color: var(--amarillo); }
.ficha-botin { color: #9BE07F; }
.ficha-nada { color: var(--gris); font-size: 14px; font-weight: 700; border-style: dashed; }
/* el gancho NO hereda la mayúscula del contenedor: es prosa («ya te llevas la Caja para tu casa») y en
 * caja alta se lee como otro titular, que es exactamente lo que no es. */
.cartel-gancho {
  margin-top: 8px !important; text-transform: none; font-size: 13px; font-weight: 600;
  color: var(--gris); letter-spacing: 0;
}
.cartel-gancho:empty { display: none; }
/* las fichas entran una detrás de otra: el ojo las CUENTA en vez de encontrárselas puestas */
.lucha-final.victoria .cartel-ficha { animation: entraFicha .42s var(--muelle) both; }
.lucha-final.victoria .cartel-ficha:nth-child(2) { animation-delay: .13s; }
.lucha-final.victoria .cartel-ficha:nth-child(3) { animation-delay: .26s; }
@keyframes entraFicha {
  0%   { transform: scale(.4) translateY(10px); opacity: 0; }
  100% { transform: scale(1) translateY(0); opacity: 1; }
}

/* tablón de misiones (B1) */
.misiones { list-style: none; margin: 0; padding: 0; }
.misiones li { display: flex; align-items: baseline; gap: 8px; padding: 10px 0; border-bottom: 1px solid var(--linea); }
.misiones li:last-child { border-bottom: 0; }
.misiones .marca { color: var(--gris); }
.misiones .progreso { margin-left: auto; color: var(--gris); font-size: 13px; }
.misiones .hecha .marca, .misiones .hecha .progreso { color: var(--amarillo); }
.misiones .hecha { color: var(--gris); }
.misiones .cuerpo-mision { display: flex; flex-direction: column; gap: 2px; }
.misiones .det { color: var(--gris); font-size: 12px; }

/* La Arena (B4 all-in): roster de salvajes + liga semanal */
#arena-intentos { font-size: 15px; color: var(--gris); }
.arena-rivales { list-style: none; margin: 0 0 20px; padding: 0; }
.arena-rival { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--linea); }
.arena-rival:last-child { border-bottom: 0; }
.arena-rival.luchado { opacity: .5; }
.arena-rival-info { display: flex; flex-direction: column; gap: 2px; }
.arena-rival-info .det { color: var(--gris); font-size: 12px; }
.arena-retar { margin-left: auto; padding: 8px 16px; font-size: 13px; }
.arena-liga-titulo { font-weight: 900; text-transform: uppercase; font-size: 16px; margin: 4px 0 4px; }
.arena-liga { list-style: none; margin: 8px 0 0; padding: 0; }
.liga-fila { display: flex; align-items: baseline; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--linea); }
.liga-fila:last-child { border-bottom: 0; }
.liga-pos { color: var(--gris); width: 24px; }
.liga-nom { color: var(--hueso); }
.liga-fila.salvaje .liga-nom { color: var(--gris); }
.liga-xp { margin-left: auto; color: var(--gris); font-size: 13px; }
.liga-fila.eres-tu { background: rgba(255,212,0,.08); }
.liga-fila.eres-tu .liga-nom { color: var(--amarillo); font-weight: 900; }
/* El RANGO de tu fila (desbloqueo `titulo`, Aspirante en adelante). Va en gris y no en el amarillo del
   nombre a propósito: acompaña al nombre, no compite con él, y la fila tiene que seguir leyéndose de un
   vistazo como «quién y cuánto». */
.liga-titulo { color: var(--gris); font-weight: 400; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; }
/* LIGA con avatar + barra (opcional aprobado 26-jul). La fila pasa de `baseline` a `center` porque ahora
   tiene un elemento alto (el retrato) y con baseline el avatar quedaba colgando bajo el texto. */
.liga-fila { align-items: center; }
.liga-avatar { flex: 0 0 34px; width: 34px; height: 34px; border-radius: 50%; overflow: hidden;
  background: rgba(242,240,233,.06); display: grid; place-items: center; }
.liga-avatar canvas { width: 100%; height: 100%; display: block; }
/* respaldo sin WebGL2: la inicial. Sigue distinguiendo a los rivales entre sí, que es a lo que sirve. */
.liga-avatar-letra { font-weight: 900; font-size: 15px; color: var(--gris); }
.liga-fila.eres-tu .liga-avatar { box-shadow: 0 0 0 2px var(--amarillo); }
.liga-nom-caja { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1 1 auto; }
.liga-nom-caja .liga-nom { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* la barra es RELATIVA al líder: lo que se lee de un vistazo es cuánto falta para el de arriba */
.liga-barra { height: 4px; border-radius: 3px; background: rgba(242,240,233,.10); overflow: hidden; }
.liga-barra-relleno { display: block; height: 100%; border-radius: 3px; background: var(--gris);
  transition: width .5s ease; }
.liga-fila.eres-tu .liga-barra-relleno { background: var(--amarillo); }
/* reduced-motion: la barra aparece ya en su sitio, sin animar */
@media (prefers-reduced-motion: reduce) { .liga-barra-relleno { transition: none; } }
.liga-fila.eres-tu .liga-pos { color: var(--amarillo); }

/* ═══ R06 · LOS ESCALONES DE LA LIGA ═══════════════════════════════════════════════════════════
   Dos suelos: el tuyo (izquierda, al ras) y el de arriba (derecha, LEVANTADO). El escalón es
   literal, por eso el nombre: subir de liga se ve como subir un peldaño y moverse a la derecha.
   Los actores van en posición ABSOLUTA sobre el ring y se mueven con `left`/`bottom`, no
   reordenando el DOM: mover un nodo de un contenedor a otro corta la transición en seco. */
.liga-escalones { margin: 10px 0 6px; }
/* 🔴 Los actores se plantan con `bottom` = ALTURA EXACTA de su losa, no a ojo. Primera versión: los
   cuatro a `bottom: 34px` sobre losas de 46 y 74 px, y en la captura salían FLOTANDO por encima del
   suelo, que es justo el defecto del que venía la orden (el Nomms sentado en el aire sobre la silla).
   Las dos losas van PEGADAS y con alturas distintas: así la silueta es una escalera de verdad y
   subir de liga se ve como subir un peldaño, no como cambiar de caja. */
.esc-ring {
  position: relative; max-width: 560px; height: 205px; margin: 0 auto;
  border-radius: var(--radio); background: var(--sup-1); border: 1px solid var(--linea);
  overflow: hidden; transition: opacity .4s ease;
}
.liga-escalones.mudando .esc-ring { opacity: .25; }
.esc-suelo { position: absolute; bottom: 0; border-top: 1px solid var(--linea); }
/* la losa se rellena con degradado hacia abajo y el canto de arriba se ilumina: sin eso son dos
   marcos huecos y el Nomms parece pegado a una línea, no de pie sobre un suelo */
.esc-suelo-tuyo {
  left: 0; width: 52%; height: 54px; border-top-width: 2px;
  background: linear-gradient(rgba(242,240,233,.13), rgba(242,240,233,.03));
}
.esc-suelo-arriba {
  left: 52%; width: 48%; height: 92px; border-top-width: 2px;
  background: linear-gradient(rgba(255,212,0,.09), rgba(255,212,0,.015));
  border-top-color: rgba(255,212,0,.55); border-left: 1px solid rgba(255,212,0,.22);
}
/* el rótulo vive ABAJO dentro de su losa: arriba chocaba de frente con los pies y con las chapas */
.esc-rotulo {
  position: absolute; bottom: 5px; left: 10px; font-size: 10px; letter-spacing: .09em;
  font-weight: 900; color: var(--gris); white-space: nowrap;
}
.esc-suelo-arriba .esc-rotulo { color: var(--amarillo); opacity: .85; }

.esc-nomms {
  position: absolute; bottom: 48px; width: 84px; margin-left: -42px;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  transition: left .8s var(--muelle), bottom .8s var(--muelle), opacity .5s ease;
}
.esc-nomms.en-alto { bottom: 86px; }
.esc-nomms.fuera { opacity: 0; }
/* la chapa de nivel va SOBRE la cabeza y la figura queda la última de la columna: así el borde de
   abajo de la caja son los pies, y `bottom` los apoya en la losa al milímetro */
.esc-nivel {
  font-size: 9px; font-weight: 900; letter-spacing: .08em; color: var(--gris);
  background: rgba(242,240,233,.08); border-radius: 999px; padding: 2px 7px; line-height: 1.2;
}
.esc-nomms.en-alto .esc-nivel { color: var(--negro); background: var(--amarillo); }
/* la figura mira al rival (scaleX) y el golpe embiste (translate): en dos capas porque el mismo
   `transform` no puede llevar las dos cosas sin que una pise a la otra */
.esc-figura { width: 72px; height: 72px; display: grid; place-items: center;
  transform: scaleX(var(--mira, 1)); }
.esc-pose { display: none; width: 72px; height: 72px; }
.esc-pose canvas { width: 100%; height: 100%; display: block; }
.esc-nomms[data-pose="idle"] .pose-idle,
.esc-nomms[data-pose="ataque"] .pose-ataque,
.esc-nomms[data-pose="victoria"] .pose-victoria,
.esc-nomms[data-pose="derrota"] .pose-derrota { display: block; }
/* respaldo sin WebGL2: la inicial, y siempre visible pase lo que pase con data-pose */
.esc-nomms.sin-3d .pose-idle { display: grid; place-items: center; font-weight: 900; font-size: 28px;
  color: var(--gris); }
.esc-nomms.sin-3d .esc-pose:not(.pose-idle) { display: none; }

/* 🔴 la embestida va multiplicada por `--mira`. `translate` y `transform: scaleX()` son propiedades
   distintas y el espejo NO invierte el desplazamiento: sin el calc, el que mira a la izquierda
   embestía hacia atrás y el golpeado salía despedido hacia su agresor. */
.esc-nomms.golpea .esc-figura { animation: esc-embiste .5s ease-out; }
@keyframes esc-embiste {
  0% { translate: 0 0; } 35% { translate: calc(26px * var(--mira, 1)) 0; } 100% { translate: 0 0; }
}
.esc-nomms.recibe .esc-figura { animation: esc-encaja .3s ease-out; }
@keyframes esc-encaja {
  0% { translate: 0 0; filter: brightness(2.2); }
  50% { translate: calc(-10px * var(--mira, 1)) 0; filter: brightness(1.4); }
  100% { translate: 0 0; filter: none; }
}
/* la chispa de CREAR, que es lo que de verdad asciende (y por eso es lo que brilla) */
.esc-nomms.chispea::after {
  /* por encima de la chapa de nivel, que es el primer hijo de la caja: a -20px la pisaba */
  content: '✨'; position: absolute; top: -34px; font-size: 18px;
  animation: esc-chispa 1.4s ease-out;
}
@keyframes esc-chispa {
  0% { opacity: 0; translate: 0 8px; scale: .4; }
  30% { opacity: 1; translate: 0 0; scale: 1.15; }
  100% { opacity: 0; translate: 0 -10px; scale: 1; }
}
.esc-rosa {
  /* va arriba a la IZQUIERDA, encima del que está a punto de subir: ahí no hay nadie nunca (los de
     abajo van bajos) y además señala al protagonista en vez de flotar en medio */
  position: absolute; top: 9px; left: 12px; padding: 6px 12px; border-radius: 999px; background: var(--amarillo); color: var(--negro);
  font-size: 10px; font-weight: 900; letter-spacing: .08em;
  opacity: 0; scale: .8; transition: opacity .3s ease, scale .3s var(--muelle);
}
/* 🔴 La clase de estado va PREFIJADA. Se llamó `vista` y la rosa no se veía NUNCA: `vista` es el
   vocabulario del enrutador (`panel.css`: `.vista { display: none }` para las pantallas que no
   tocan), que se carga DESPUÉS y ganaba. El síntoma es cruel — la clase se ponía y se quitaba en su
   milisegundo exacto, el módulo estaba bien y no había ni un error en consola. */
.esc-rosa.esc-puesta { opacity: 1; scale: 1; }
.esc-pie { margin: 8px auto 0; max-width: 560px; font-size: 12px; color: var(--gris); min-height: 2.6em; }

/* ═══ R07 · EL CARTELON DE ASCENSO ═════════════════════════════════════════════════════════════
   Va arriba del todo de la Arena y solo con datos reales. Dos pesos deliberados: la celebración
   (semana ya cerrada) manda con el amarillo lleno; el aviso de «vas en zona» es un borde, porque
   avisar de algo que aún no ha pasado no puede sonar igual que haberlo conseguido. */
.liga-ascenso {
  display: flex; align-items: center; gap: 12px; margin: 0 0 14px;
  padding: 12px 14px; border-radius: var(--radio);
}
.liga-ascenso.celebra { background: var(--amarillo); color: var(--negro); }
.liga-ascenso.aviso { background: var(--sup-1); border: 1px solid rgba(255,212,0,.35); color: var(--hueso); }
.liga-ascenso-marca { font-size: 26px; line-height: 1; }
.liga-ascenso.aviso .liga-ascenso-marca { color: var(--amarillo); font-weight: 900; }
.liga-ascenso-cuerpo { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.liga-ascenso-texto { font-weight: 900; letter-spacing: .04em; font-size: 15px; text-transform: uppercase; }
.liga-ascenso-det { font-size: 12px; opacity: .78; }
.liga-ascenso.entra { animation: liga-ascenso-entra .55s var(--muelle); }
@keyframes liga-ascenso-entra {
  0% { opacity: 0; translate: 0 -14px; scale: .96; }
  100% { opacity: 1; translate: 0 0; scale: 1; }
}
/* el destello solo en la celebración: es la que se ha ganado */
.liga-ascenso.celebra.entra::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, transparent 35%, rgba(255,255,255,.55) 50%, transparent 65%);
  animation: liga-ascenso-brillo 1s ease-out .2s;
}
.liga-ascenso.celebra { position: relative; overflow: hidden; }
@keyframes liga-ascenso-brillo { 0% { translate: -100% 0; } 100% { translate: 100% 0; } }

@media (prefers-reduced-motion: reduce) {
  .esc-nomms, .esc-ring, .esc-rosa { transition: none; }
  .esc-nomms.golpea .esc-figura, .esc-nomms.recibe .esc-figura,
  .esc-nomms.chispea::after, .liga-ascenso.entra,
  .liga-ascenso.celebra.entra::after { animation: none; }
}
/* pasada 2: marca de zona (▲ sube / ▼ baja) — convención sellada, cero rojo/verde en deltas */
.liga-aviso { margin: 0 0 8px; }
/* aversión a la pérdida sin romper la paleta (cero rojo): el aviso de descenso va en amarillo
   atenuado con una barra de acento, no en rojo de alarma */
.liga-aviso.peligro { color: var(--amarillo); }
.liga-zona { margin-left: 4px; font-size: 12px; }
.zona-asciende .liga-zona { color: var(--amarillo); }
.zona-desciende .liga-zona { color: var(--gris); }
.zona-asciende { box-shadow: inset 2px 0 0 var(--amarillo); }


/* ============================================================================
   REWORK DEL CREADOR — lote 1 (informe UX/UI del creador de Nomms, 19-jul-2026)
   Cura los síntomas medidos en el baseline: opciones que se leen en vez de verse,
   amarillo diluido en 7 sitios, selección tipo pegatina, todo pegado, Nomms flotando.
   ========================================================================== */

/* — ESCENARIO: el Nomms se planta en un suelo, con sombra y un único halo de foco — */
.escenario {
  position: relative;
  display: flex; align-items: flex-end; justify-content: center;
  padding: 18px 0 0;
  margin: 4px 0 18px;
  border-radius: var(--radio);
  /* el ÚNICO glow amarillo de la vista, detrás del personaje (patrón dark-premium 2025) */
  background:
    radial-gradient(ellipse 70% 55% at 50% 12%, rgba(255, 212, 0, .10), transparent 70%),
    var(--sup-1);
  overflow: hidden;
}
.escenario .capas-preview {
  width: min(260px, 64vw); height: min(260px, 64vw);
  filter: drop-shadow(0 14px 26px rgba(0, 0, 0, .75));
  /* idle: respira. Un personaje quieto se lee como pegatina (regla del módulo-personaje). */
  animation: respira 3.4s ease-in-out infinite;
  transform-origin: 50% 100%;
  position: relative; z-index: 1;
}
@keyframes respira {
  0%, 100% { transform: translateY(0) scale(1, 1); }
  50%      { transform: translateY(-4px) scale(.995, 1.008); }
}
/* suelo + sombra elíptica: lo que hace que deje de flotar */
.escenario-suelo {
  position: absolute; left: 50%; bottom: 26px; transform: translateX(-50%);
  width: 46%; height: 16px; border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, .75), transparent 72%);
  animation: sombra 3.4s ease-in-out infinite;
}
@keyframes sombra {
  0%, 100% { opacity: .85; width: 46%; }
  50%      { opacity: .68; width: 42%; }
}
/* al cambiar de pieza el Nomms hace squash&stretch (micro-feedback del lote 2, base aquí) */
.escenario.pt-cambio .capas-preview { animation: squash .34s var(--muelle); }

/* — JUICE lote 2 (web/juice.mjs): hitstop, flash, latido y partículas de la CEREMONIA — */
/* hitstop: congela el idle un instante (el cerebro lee la pausa como peso) */
.escenario.congelado .capas-preview, .escenario.congelado .escenario-suelo { animation-play-state: paused; }
/* flash del impacto: overlay 90ms que nace y muere solo (lo limpia juice.mjs en animationend) */
.escenario .flash {
  position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: radial-gradient(ellipse at 50% 40%, rgba(255, 212, 0, .30), transparent 65%);
  animation: flashea .09s ease-out both;
}
@keyframes flashea { 0% { opacity: 0; } 30% { opacity: 1; } 100% { opacity: 0; } }
/* latido: el mismo squash con el origen al CENTRO se lee como corazón, no como aterrizaje */
.escenario .capas-preview.latido { animation: late .5s var(--muelle); transform-origin: 50% 50%; }
@keyframes late {
  0% { transform: scale(1); } 30% { transform: scale(1.12); }
  55% { transform: scale(.97); } 75% { transform: scale(1.05); } 100% { transform: scale(1); }
}
/* partícula del estallido: viaja a su --dx/--dy (anillo + jitter) mientras cae y se apaga */
.escenario .particula {
  position: absolute; left: 50%; top: 44%; z-index: 2; pointer-events: none;
  width: 7px; height: 7px; border-radius: 50%; background: var(--c, var(--amarillo));
  animation: vuela .8s cubic-bezier(.16, 1, .3, 1) both;
}
@keyframes vuela {
  0%   { transform: translate(0, 0) scale(1); opacity: 1; }
  100% { transform: translate(var(--dx), calc(var(--dy) + 46px)) scale(.4); opacity: 0; }
}
/* la ruleta del dado deshabilita el botón mientras gira (estado visible, no solo lógico) */
.preset-dado[disabled] { opacity: .55; cursor: wait; }

/* con el motor 3D activo, la sombra pertenece a la ESCENA (se mueve con la órbita): la CSS sobra */
.escenario.con-3d .escenario-suelo { display: none; }
/* P6: con el motor 3D activo, el mundo entero (respiración + sombra de contacto) lo hace el
   propio motor. La animación `respira` y el `drop-shadow` CSS sobre el contenedor duplicaban
   ambas cosas (doble respiración + sombra fantasma) — regresión del fix de anatomía v2. */
.escenario.con-3d .capas-preview { animation: none !important; filter: none; }

/* — GIRO 2.5D: agarrar y girar el Nomms (direct manipulation, sin gate de reduced-motion) — */
.escenario.girable { cursor: grab; }
.escenario.girable.girando { cursor: grabbing; }
.escenario.girable:focus-visible { outline: 2px solid var(--amarillo); outline-offset: -2px; } /* foco de marca, no azul del navegador */
.escenario.girable .capas-preview { user-select: none; -webkit-user-select: none; }
.pista-giro {
  position: absolute; left: 50%; bottom: 2px; transform: translateX(-50%); z-index: 2;
  margin: 0; color: var(--gris); font-size: 12px; letter-spacing: .04em; white-space: nowrap;
  pointer-events: none; transition: opacity .4s ease;
}
.pista-giro.oculto { display: block; opacity: 0; } /* se desvanece, no salta el layout */

/* — LOTE 3: grano, photo-booth, unicidad y confirmar escénico — */
/* grano: mosaico de ruido al mínimo (runtime, juice.mjs) — textura, no suciedad */
.escenario .grano { position: absolute; inset: 0; z-index: 0; pointer-events: none; background-repeat: repeat; }
/* photo-booth: mueble discreto en la esquina del escenario (jamás compite con el CTA) */
.btn-foto {
  position: absolute; top: 10px; right: 10px; z-index: 3;
  width: 38px; height: 38px; border-radius: 10px; cursor: pointer;
  background: rgba(20, 20, 20, .72); border: 1px solid var(--linea); font-size: 16px; line-height: 1;
  opacity: .75; transition: opacity .15s ease, background .15s ease;
}
.btn-foto:hover { opacity: 1; background: var(--sup-2); }
/* unicidad: una línea serena bajo el escenario */
.unicidad { text-align: center; margin: 0 0 14px; }
/* CONFIRMAR ESCÉNICO (patrón BG3): DARLE VIDA descansa apagado y SE ENCIENDE al haber nombre —
   el único amarillo pleno de la vista aparece cuando la decisión está madura */
#crear .btn:not(.listo), .barra-crear .btn:not(.listo), .barra-look .btn:not(.listo):not(.btn-fantasma) {
  background: transparent; color: var(--gris); border: 1px solid var(--linea);
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
#crear .btn.listo, .barra-crear .btn.listo, .barra-look .btn.listo {
  box-shadow: 0 0 26px rgba(255, 212, 0, .22);
  animation: enciende .5s var(--muelle);
}
@keyframes enciende { 0% { transform: scale(1); } 40% { transform: scale(1.03); } 100% { transform: scale(1); } }
/* toggle de sonido: mueble discreto, jamás compite con el CTA */
.btn-sfx {
  flex: 0 0 auto; background: transparent; border: 1px solid var(--linea); color: var(--gris);
  border-radius: 999px; width: 34px; height: 34px; cursor: pointer; font-size: 14px; line-height: 1;
}
.btn-sfx:hover { color: var(--hueso); border-color: #4a463c; }
@keyframes squash {
  0%   { transform: scale(1, 1); }
  35%  { transform: scale(1.06, .94); }
  70%  { transform: scale(.97, 1.03); }
  100% { transform: scale(1, 1); }
}

/* — PRESETS: arranque de un toque (la mejora nº1 de choice architecture) — */
/* UNA sola fila deslizable: en la primera captura ocupaban 3 filas y empujaban la vitrina
   fuera de pantalla — el personaje y las piezas son lo que manda, los presets son el atajo */
.fila-arranque {
  display: flex; gap: 8px; align-items: center;
  /* ⚠️ ENVUELVE, no se desplaza. Antes era un carrusel horizontal con un desvanecido al borde como
     pista, y aun así la queja del 1-ago fue literalmente que «Sorpréndeme» salía cortado: medido en un
     iPhone, la fila daba 364px de ancho para 577px de contenido, o sea que DOS presetes y medio vivían
     fuera de la pantalla y el único aviso era un degradado de 42px. Un desplazamiento horizontal dentro
     de una página que ya se desplaza en vertical no lo descubre nadie. Envolviendo no se esconde nada,
     y el sitio que ocupa la segunda línea estaba vacío de todas formas. */
  flex-wrap: wrap; row-gap: 8px;
}
/* `display: contents` y no `flex`: los presets tienen que envolver EN LA MISMA rejilla que «Sorpréndeme»,
   que es su hermano de fuera. Con un flex anidado cada caja envuelve por su cuenta y salía escalonado
   (3 presetes / «Alado» solo / «Sorpréndeme» solo, tres líneas para cinco píldoras). Sin caja propia,
   las cinco reparten el mismo hueco. */
.presets { display: contents; }
.preset {
  flex: 0 0 auto; white-space: nowrap;
  background: var(--sup-1); border: 1px solid var(--linea); color: var(--hueso);
  border-radius: 999px; padding: 8px 13px; cursor: pointer;
  font: 700 12px/1 inherit; letter-spacing: .03em;
  transition: background .15s ease, border-color .15s ease, transform .15s var(--muelle);
}
.preset:hover { background: var(--sup-2); border-color: #4a463c; transform: translateY(-1px); }
.preset:active { transform: scale(.96); }

/* — PESTAÑAS por slot con icono (una categoría a la vez) — */
.pestanas {
  display: flex; gap: 4px; overflow-x: auto; scrollbar-width: none;
  margin: 20px 0 0; padding-bottom: 2px;
}
.pestanas::-webkit-scrollbar { display: none; }
.pestana {
  position: relative;
  flex: 1 0 auto;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  background: transparent; border: 0; border-bottom: 2px solid transparent;
  color: var(--gris); cursor: pointer; padding: 8px 10px 7px;
  font: 700 10px/1 inherit; letter-spacing: .1em;
  transition: color .15s ease, border-color .15s ease;
}
/* ⚠️ El `filter: grayscale(1)` que había aquí era un PARCHE para apagar un emoji: un emoji trae sus
   colores puestos y no obedece a `color`, así que la única forma de bajarlo era desaturar la imagen
   entera. Con los iconos dibujados (`web/iconos.mjs`) el trazo es `currentColor` y basta con el color del
   botón — que además ya lo tiene, heredado de `.pestana`. Menos CSS y el estado se lee de verdad. */
.pestana-icono { line-height: 0; color: inherit; }
.ico-svg { width: 22px; height: 22px; display: block; }
.pestana:hover { color: var(--hueso); }
/* la pestaña activa NO usa amarillo (está reservado a UNA cosa): se marca con hueso + peso */
.pestana[aria-selected="true"] { color: var(--hueso); border-bottom-color: var(--hueso); }
.pestana[aria-selected="true"] .pestana-icono { color: var(--hueso); }
/* punto = ese slot lleva pieza puesta (lectura de un vistazo) */
.pestana-punto {
  position: absolute; top: 6px; right: 8px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--gris);
}

/* — VITRINA: la pieza se VE (miniatura recortada), no se lee — */
#vitrina-piezas { background: var(--sup-1); border-radius: var(--radio); padding: 14px; margin-top: 2px; }
.vitrina {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
}
.pieza {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  background: transparent; border: 0; padding: 0; cursor: pointer;
  color: var(--gris); font: 600 11px/1.1 inherit;
}
.pieza-caja {
  position: relative;
  width: 100%; aspect-ratio: 1;
  display: flex; align-items: center; justify-content: center;
  background: var(--sup-2); border: 1px solid transparent; border-radius: var(--radio);
  transition: background .16s ease, box-shadow .2s ease, transform .18s var(--muelle);
}
.pieza-lienzo canvas { width: 100%; height: 100%; display: block; }
.pieza-vacia { color: #4a463c; font-size: 22px; }
.pieza:hover .pieza-caja { background: #262626; transform: translateY(-2px); }
.pieza:active .pieza-caja { transform: scale(.95); }
/* SELECCIÓN = GLOW ENVOLVENTE (no el borde-pegatina prohibido por PALETA-WEB) */
.pieza[aria-pressed="true"] .pieza-caja {
  background: #241f08;
  box-shadow: 0 0 0 1px rgba(255, 212, 0, .55), 0 0 18px 2px rgba(255, 212, 0, .22);
}
.pieza[aria-pressed="true"] { color: var(--hueso); }
.pieza:focus-visible .pieza-caja { outline: 2px solid var(--amarillo); outline-offset: 2px; }
.pieza-nombre { text-align: center; }

/* la rejilla de color hereda el mismo lenguaje (blobs, no cuadraditos sueltos) */
#vitrina-piezas .paletas { grid-template-columns: repeat(auto-fill, minmax(52px, 1fr)); gap: 10px; }
#vitrina-piezas .paletas button {
  border-radius: 42% 58% 54% 46% / 50% 44% 56% 50%;
  border: 0; box-shadow: inset 0 -6px 14px rgba(0, 0, 0, .28);
  transition: box-shadow .2s ease, transform .18s var(--muelle);
}
#vitrina-piezas .paletas button:hover { transform: translateY(-2px) scale(1.04); }
#vitrina-piezas .paletas button[aria-selected="true"] {
  outline: 0;
  box-shadow: inset 0 -6px 14px rgba(0, 0, 0, .28),
              0 0 0 2px rgba(255, 212, 0, .7), 0 0 18px 3px rgba(255, 212, 0, .25);
}
#vitrina-piezas .paletas button:disabled { opacity: .3; cursor: not-allowed; }

/* tintes: mismo criterio de selección (glow), sin bordes amarillos sueltos */
.swatches-tinte button[aria-pressed="true"] {
  border-color: transparent; outline: 0;
  box-shadow: 0 0 0 2px rgba(255, 212, 0, .7), 0 0 14px 2px rgba(255, 212, 0, .22);
}

/* — el CTA es la ÚNICA cosa amarilla plena de la vista — */
#crear .btn { width: 100%; margin-top: 6px; padding: 16px 22px; border-radius: var(--radio); font-size: 17px; }

/* respeto a quien no quiere movimiento (guardarraíl innegociable del informe) */
@media (prefers-reduced-motion: reduce) {
  .escenario .capas-preview, .escenario-suelo { animation: none; }
  .preset, .pieza-caja, #vitrina-piezas .paletas button { transition: none; }
  .escenario.pt-cambio .capas-preview { animation: none; }
  /* juice lote 2: con movimiento reducido, cero fiesta (juice.mjs ya corta antes; doble cinturón) */
  .escenario .flash, .escenario .particula { animation: none; display: none; }
  .escenario .capas-preview.latido { animation: none; }
  /* lote 3: el encendido del CTA sin animación (el cambio de color ya comunica) */
  #crear .btn.listo, .barra-crear .btn.listo, .barra-look .btn.listo { animation: none; }
  /* pasada 2 del bucle: el reduced-motion estaba a medias — el CLÍMAX (la pelea) seguía
     temblando. Se apagan la sacudida de los golpes, el parpadeo infinito del cursor del H1
     y cualquier keyframe residual. El desenlace se sigue leyendo (color + texto), sin movimiento. */
  .golpeado { animation: none; }
  .cursor { animation: none; }
  .hp.flash-hp, .lucha-final.victoria { animation: none; }
  /* R11 · las fichas del premio se QUEDAN, solo dejan de entrar volando. El atajo global de abajo
   * (`animation-duration: 0.001ms`) las dejaría visibles por accidente —su último fotograma es
   * `opacity: 1`—, pero por accidente no vale: si mañana la animación acabara en otro sitio, el premio
   * desaparecería para quien pidió menos movimiento y nadie se enteraría. */
  .lucha-final.victoria .cartel-ficha { animation: none; opacity: 1; transform: none; }
  /* 🔴 R09 · el número del daño YA NO se esconde aquí. Estaba en `display:none` con la excusa de que
   * «depende de la animación», y eso lo trataba como adorno: es el único sitio donde se ve CUÁNTO has
   * pegado, así que apagarlo dejaba jugando a ciegas a quien tiene el movimiento reducido. Lo que se
   * quita es el vuelo, no el dato — `app.mjs` le pone la clase `.quieto` y lo retira por temporizador. */
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; }
}

/* escritorio: el escenario manda y la vitrina respira (el baseline desaprovechaba 2/3) */
@media (min-width: 720px) {
  .escenario { padding-top: 26px; }
  .escenario .capas-preview { width: 340px; height: 340px; }
  .vitrina { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
}

/* ── EL HOGAR (R1 lote 4): habitación con muebles crafteados + puntuación ── */
.materiales { color: var(--hueso); letter-spacing: .3px; }
.hogar-lienzo {
  display: block; width: 100%; max-width: 264px; height: auto; margin: 10px auto;
  image-rendering: pixelated; border: 1px solid var(--linea); border-radius: var(--radio);
  background: #12100b; cursor: pointer; touch-action: manipulation;
}
.hogar-bandeja { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0 4px; }
.hogar-pieza {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px;
  background: var(--sup-1); border: 1px solid var(--linea); border-radius: var(--radio);
  color: var(--hueso); cursor: pointer; transition: transform .12s var(--muelle), border-color .12s;
}
.hogar-pieza .ico { font-size: 18px; }
.hogar-pieza.sel { border-color: var(--amarillo); box-shadow: 0 0 0 2px var(--amarillo) inset; transform: translateY(-1px); }
.hogar-pieza:disabled { opacity: .4; cursor: default; }
/* F6: el catálogo pasa a ser una PILA de bloques por tema; la rejilla de tarjetas vive DENTRO de cada
   bloque (.hogar-crafts). Antes `#hogar-catalogo` era el grid directamente, así que al meter las
   cabeceras de tema caían como una celda de 84px y la maqueta se partía en columnas raras. */
.hogar-catalogo { display: flex; flex-direction: column; gap: 2px; }
.hogar-craft {
  display: flex; flex-direction: column; align-items: center; gap: 3px; padding: 8px 6px;
  background: var(--sup-1); border: 1px solid var(--linea); border-radius: var(--radio); text-align: center;
}
.hogar-craft .ico { font-size: 22px; }
.hogar-craft .det { color: var(--gris); font-size: .8rem; }
.hogar-craft.no { opacity: .55; }
.hogar-craft .btn { padding: 4px 8px; font-size: .8rem; margin-top: 2px; }

/* ── EL ICONO DE UN MUEBLE ES SU MODELO ────────────────────────────────────────────────────────────
   `pintaIconosMueble()` (app.mjs) mete un <img> con el sprite 3D DENTRO del mismo <span class="ico"> que
   traía el emoji. El span conserva su hueco, así que la lista no da un salto cuando el sprite llega:
   se le fija el tamaño en el propio span y la imagen lo rellena.
   ⚠️ `display:block` en la imagen no es cosmético — sin él, un <img> es inline y arrastra el
   interlineado de su caja de texto, que aquí valía 22px y descuadraba la tarjeta hacia abajo. */
.hogar-pieza .ico { width: 22px; height: 22px; display: inline-grid; place-items: center; }
.hogar-craft .ico { width: 40px; height: 40px; display: grid; place-items: center; }
.hogar-pieza .ico img, .hogar-craft .ico img, .col-pieza img {
  width: 100%; height: 100%; display: block; object-fit: contain;
}
.col-pieza img { width: 100%; height: 100%; }

/* ── DESKTOP: creador a lo ancho (preview grande + panel de opciones, estilo VRoid/ARK) + tablero 2col ── */
@media (min-width: 900px) {
  main { max-width: 1040px; }
  /* la cabecera del JUEGO va CENTRADA (antes se veía "a la izquierda" por el text-align por defecto).
   * ⚠️ `body:not(.landing)` NO es decorativo. Esta hoja la carga también la portada, y allí el hero es una
   * columna de texto a la izquierda con el bicho a la derecha: centrar su `h1` y su antetítulo dentro de esa
   * columna dejaba el titular flotando en medio con el párrafo y el botón alineados a la izquierda — el
   * borde izquierdo salía dentado. Es la queja 8b de Iñaki del 1-ago («la regla que no se toca está en el
   * medio y el texto a la izquierda»), y venía de aquí: una regla escrita para una pantalla que se aplicaba
   * a otra por compartir hoja. */
  body:not(.landing) :is(.kicker, h1, .sub, #guia-ios) { text-align: center; }
  /* el CREADOR ocupa el ancho: escenario grande y pegajoso a la izquierda + opciones a la derecha */
  #crear { display: grid; grid-template-columns: 46% 1fr; column-gap: 34px; align-items: start; }
  #crear > .escenario { grid-column: 1; grid-row: 1 / span 99; position: sticky; top: 18px; margin-top: 0; }
  #crear > *:not(.escenario) { grid-column: 2; }
  #crear .escenario .capas-preview { width: min(380px, 40vw); height: min(380px, 40vw); }
  /* el resto del flujo de creación se queda centrado y legible, no estirado */
  /* ⚠️ `#tarjeta-cuidado` entra en la lista (21-ago). Es hermano de `#comparativa` dentro de la misma
   * vista y era el UNICO de los cuatro que se quedaba fuera: en ancho la comparativa se veia centrada y
   * legible y las necesidades, justo encima, estiradas a lo ancho de la pantalla. No fallaba nada, solo
   * faltaba un id en un selector. */
  #guardar, #cuenta, #comparativa, #desbloqueo, #tarjeta-cuidado { max-width: 560px; margin-inline: auto; }
  /* el tablero del juego (misiones/arena/hogar/lucha) a 2 columnas */
  .tablero { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }
  .tablero #lucha { grid-column: 1 / -1; } /* el ring de combate, a lo ancho */
}
/* las pestañas de categoría ENVUELVEN (nunca se corta la de arma ⚔️, antes quedaba fuera del scroll) */
.pestanas { flex-wrap: wrap; }

/* ── Momento de NACIMIENTO (Optional aplicado): celebración breve al dar vida ── */
.nacimiento {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: center;
  background: rgba(5, 5, 5, .88); opacity: 0; pointer-events: none; transition: opacity .33s ease;
}
.nacimiento.ver { opacity: 1; }
.nacimiento-caja { text-align: center; transform: scale(.9); transition: transform .33s var(--muelle); }
.nacimiento.ver .nacimiento-caja { transform: scale(1); }
.nacimiento-chispa { font-size: 46px; margin: 0 0 4px; }
.nacimiento-nombre {
  font-weight: 900; text-transform: uppercase; letter-spacing: .01em; line-height: .95;
  font-size: clamp(34px, 11vw, 66px); color: var(--amarillo); margin: 0;
}
.nacimiento-sub { color: var(--hueso); margin: 10px 0 0; letter-spacing: .2em; text-transform: uppercase; font-size: 13px; }
@media (prefers-reduced-motion: reduce) {
  .nacimiento, .nacimiento-caja { transition: none; }
  .nacimiento.ver .nacimiento-caja { transform: none; }
}

/* ── F1: sliders de morfo del cuerpo (pestaña CUERPO del creador) ── */
.morfos { display: flex; flex-direction: column; gap: 15px; padding: 6px 2px 2px; }
.morfo { display: block; }
.morfo-cab { display: block; color: var(--hueso); font-size: 13px; letter-spacing: .08em; text-transform: uppercase; margin-bottom: 5px; }
.morfo input[type="range"] { width: 100%; accent-color: var(--amarillo); height: 24px; cursor: pointer; }
.morfo-ext { display: flex; justify-content: space-between; color: var(--gris); font-size: 11px; letter-spacing: .03em; margin-top: 1px; text-transform: lowercase; }
.morfo-nota { text-align: center; margin-top: 8px; }

/* UNDO del creador (investigación p3: petición nº1 de power-users) */

/* UNDO del creador (investigación p3: petición nº1 de los power-users). Va junto a la cámara, sobre la
   escena: es una acción sobre el personaje, NO un "look" — meterlo en el carrusel de presets lo dejaba
   fuera del área visible y lo mezclaba con los arquetipos. */
.btn-undo-esc { position: absolute; top: 10px; right: 58px; z-index: 3;
  background: rgba(0,0,0,.45); border: 1px solid rgba(255,255,255,.18); border-radius: 10px;
  color: #fff; font-size: 15px; line-height: 1; padding: 7px 9px; cursor: pointer; }
.btn-undo-esc:disabled { opacity: .35; cursor: default; }

/* ── F9: diario de bienvenida + barras de necesidad (docs/ADR-001-barras-de-necesidades.md) ──
   Tono: el diario cuenta lo que HIZO; las barras informan sin alarmar. Nada de rojo de peligro ni
   iconos de aviso: el ADR prohíbe el marco de castigo, y el color es parte del marco. */
.diario { margin: 10px 0 6px; padding: 10px 12px; border-radius: 12px;
  background: rgba(255,255,255,.05); border-left: 3px solid var(--acento, #ffd84d); }
.diario p { margin: 0 0 4px; font-size: 13.5px; line-height: 1.45; opacity: .92; }
.diario p:last-child { margin-bottom: 0; }
/* ⚠️ 21-AGO-2026 · DE FILA APRETADA A TARJETA. Iñaki, mirando esta pantalla: «lo del hambre, higiene,
   energía, juego se ve muy pequeñito. No lo acabo de ver así, tendría que ser más grande, tendría que
   verse más visualmente». Y tenía razón medida, no de gusto: la fila era `icono + palabra + barra +
   botón` en una columna de 150 px, o sea que a la barra —lo ÚNICO que lleva el dato— le quedaban unos
   40 px de ancho y 7 de alto, sin número. El cuidado diario es el bucle central del producto (ADR-001)
   y se estaba pintando como un adorno de pie de tarjeta.
   Ahora cada necesidad es una TARJETA en rejilla 2×2: icono grande, nombre, el porcentaje en grande, la
   barra a todo el ancho y el botón como acción de verdad. Lo que NO cambia: nada de rojo de peligro ni
   iconos de aviso (el ADR prohíbe el marco de castigo, y el color es parte del marco).
   ↩︎ CORREGIDO el mismo día, mirándolo él otra vez: «las barras ni tanto ni tan poco, ahora me parece
   excesivo el tamaño». Se baja a un punto medio ENTRE las dos versiones —no se vuelve a la fila apretada,
   que era el bug original—: barra 12→9 px (antes 7), número 19→15 px, icono 22→19 px (antes 17) y menos
   aire. La tarjeta 2×2 y el número se quedan: eran lo que faltaba; lo que sobraba era la escala. */
.necesidades { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px;
  margin: 10px 0 5px; }
.nec {
  display: flex; flex-direction: column; gap: 7px;
  /* `--sup-2`, no `--sup-1`: la tarjeta que las contiene YA es `--sup-1`, así que con el mismo tono las
     cuatro cajas solo se distinguían por su borde de 1 px. La profundidad de esta casa se hace
     ACLARANDO, nunca con sombra. */
  background: var(--sup-2); border: 1px solid var(--linea); border-radius: 10px;
  padding: 9px 11px 9px;
}
.nec-cab { display: flex; align-items: center; gap: 7px; }
.nec-icono { font-size: 17px; line-height: 0; display: inline-flex; color: var(--hueso); opacity: .9; }
.nec-icono .ico-svg { width: 19px; height: 19px; }
.nec-nom { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--gris); }
/* el número a la derecha, y en la MISMA escala que un titular pequeño: es el dato, no una nota al pie */
.nec-pct { margin-left: auto; font-size: 15px; font-weight: 800; line-height: 1; color: var(--hueso); }
.nec.nivel-media .nec-pct { color: var(--nivel-media); }
.nec.nivel-baja  .nec-pct { color: var(--nivel-baja); }
.rbtn .ico-svg { width: 24px; height: 24px; }
.rail .rbtn > span, .rail .rbtn { line-height: 0; }
.rail .rbtn .ico-svg, .rail button > span > .ico-svg { width: 24px; height: 24px; margin: 0 auto; }
.nec-ico { line-height: 0; display: inline-flex; }
.nec-ico .ico-svg { width: 16px; height: 16px; }
.nec-barra { width: 100%; height: 9px; border-radius: 999px; background: rgba(255,255,255,.10);
  overflow: hidden; display: block; }   /* un <span> inline ignora width/height: se vio vacía */
.nec-relleno { display: block; height: 100%; border-radius: 999px; background: var(--nivel-ok);
  transition: width .35s ease, background .35s ease; }
.nec.nivel-media .nec-relleno { background: var(--nivel-media); }
.nec.nivel-baja  .nec-relleno { background: var(--nivel-baja); }
.nec-btn { background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.16); border-radius: 8px;
  color: inherit; font: 700 11px/1 inherit; letter-spacing: .08em; text-transform: uppercase;
  padding: 6px 9px; cursor: pointer; transition: background .15s ease, border-color .15s ease; }
.nec-btn:hover:not(:disabled) { background: rgba(255,212,0,.14); border-color: rgba(255,212,0,.4); }
/* ⚠️ El botón NO ocupa el ancho, y se vio capturando: a 100% las cuatro necesidades enseñaban un
   slab gris vacío de borde a borde con «AL DÍA» dentro, o sea que el elemento más grande de cada
   tarjeta era el que no hace nada. Ahora es una pastilla a la izquierda cuando hay algo que atender…
   */
.nec-btn { align-self: flex-start; padding: 6px 12px; }
/* …y cuando no lo hay se apaga del todo: pierde caja y borde y se lee como el pie de la barra que es.
   El `disabled` sigue ahí (no se puede pulsar) — lo que cambia es que deja de gritar. */
.nec-btn:disabled { opacity: .5; cursor: default; background: none; border-color: transparent;
  padding-left: 0; padding-right: 0; letter-spacing: .1em; }
/* el botón de vacaciones REUSA `.nec-btn` y vive fuera de la rejilla: ahí no tiene que ocupar el ancho */
#btn-vacaciones { align-self: flex-start; text-transform: none; letter-spacing: .04em; }
/* 🎨 …y el del vestidor es su HERMANO: misma pastilla, misma caja, y por eso tiene que LEERSE igual.
   Se vio capturando el render real: heredaba de `.nec-btn` el `uppercase` + `letter-spacing: .08em` que
   `#btn-vacaciones` sí anula, así que uno gritaba «CAMBIAR SU LOOK» y el otro susurraba «modo vacaciones»
   pegados el uno al otro, y parecían dos cosas de rango distinto cuando son la misma. El `margin-top`
   arregla el otro defecto de la misma captura: sin él quedaba clavado bajo `#nota-vacaciones` (que es el
   pie de vacaciones) y ese párrafo se leía como si explicara ESTE botón. */
#btn-vestidor { align-self: flex-start; text-transform: none; letter-spacing: .04em; margin-top: 14px; }
.nec-pie { grid-column: 1 / -1; font-size: 11.5px; opacity: .6; margin: 2px 0 0; }
@media (max-width: 360px) { .necesidades { grid-template-columns: 1fr; } }

/* F10.8 — MIS LOOKS y copiar color. Mismo lenguaje visual que los presets de arranque: son la misma
   idea (un look de un toque), solo que estos los hizo el jugador. */
.presets-mios { margin-bottom: .35rem; }
.preset-caja { position: relative; display: inline-flex; }
.preset-mio { padding-right: 1.55rem; }
.preset-x {
  position: absolute; right: .18rem; top: 50%; transform: translateY(-50%);
  width: 1.15rem; height: 1.15rem; line-height: 1; padding: 0; border: 0; border-radius: 50%;
  background: rgba(0,0,0,.28); color: #fff; font-size: .72rem; cursor: pointer; opacity: .55;
}
.preset-x:hover, .preset-x:focus-visible { opacity: 1; background: rgba(190,40,60,.85); }
.preset-guardar { border-style: dashed; }
.copia-color { margin: .35rem 0 .1rem; }
.copia-color .mini {
  font: inherit; font-size: .78rem; padding: .28rem .55rem; border-radius: .5rem; cursor: pointer;
  border: 1px solid rgba(255,255,255,.16); background: rgba(255,255,255,.06); color: inherit;
}
.copia-color .mini:hover, .copia-color .mini:focus-visible { background: rgba(255,255,255,.12); }

/* F6 — catálogo del Hogar por TEMAS. La cabecera lleva el color del tema como pista visual (así el
   jugador ve de un vistazo qué muebles pegan entre sí, que es justo lo que premia la puntuación). */
.hogar-tema { border-left: 3px solid var(--c, #888); padding-left: .45rem; margin: .7rem 0 .3rem; }
.hogar-crafts { display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); gap: 8px; }
.hogar-craft .hogar-tienes { opacity: .75; font-variant-numeric: tabular-nums; }

/* F9.6 — COLECCIÓN. La pieza que no tienes NO lleva candado ni tachado: es una silueta apagada. La
   diferencia importa — un candado dice «no puedes», una silueta dice «todavía no» (ADR-001). */
.hogar-coleccion { display: flex; flex-direction: column; gap: 4px; margin: .5rem 0 .7rem; }
.col-tema { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; }
.col-tema-et {
  font-size: .74rem; color: var(--gris); border-left: 3px solid var(--c, #888);
  padding-left: .35rem; min-width: 6.6rem; font-variant-numeric: tabular-nums;
}
.col-pieza {
  width: 1.55rem; height: 1.55rem; display: grid; place-items: center; border-radius: .4rem;
  font-size: .95rem; background: var(--sup-1); border: 1px solid var(--linea);
  filter: grayscale(1) brightness(.55); opacity: .8; cursor: help;
}
.col-pieza.col-tengo { filter: none; opacity: 1; border-color: var(--c, var(--linea)); background: color-mix(in srgb, var(--c) 16%, var(--sup-1)); }
.col-siguiente { margin-top: .2rem; }

/* la fecha de nacimiento en la tarjeta de guardar: presencia sin robar el foco al campo de correo */
.nacimiento-fecha:empty { display: none; }
.nacimiento-fecha { color: var(--amarillo); font-weight: 700; margin: 2px 0 6px; }

/* F7: qué está haciendo el rival ahora mismo. En cursiva y apagado: es color, no dato de combate — el nivel
   sigue siendo lo que decide si le retas, y esto no debe competir con él por la atención. */
.arena-rutina { font-style: italic; opacity: .78; }

/* Una misión que espera a que vincules tu canal NO es una misión rota. En gris se leía como «esto no
   está hecho»; en ámbar se lee como «te falta un paso», que es la verdad. Y es la fila más importante
   del tablón: las dos que llevan esta marca son las únicas que dan XP. */
.progreso-pendiente {
  color: var(--amarillo); font-size: 11px; letter-spacing: .08em; font-weight: 700;
  border: 1px solid #4a3d15; border-radius: 999px; padding: 3px 9px; white-space: nowrap;
}

/* LIGA A CERO: lo que se enseña cuando nadie ha puntuado todavía. Ocupa el sitio que ocupaban 20 filas
   idénticas de «0 XP» — que no informaban de nada y se leían como una pantalla rota — y dice lo único
   que importa en ese momento: qué hay que hacer para entrar en la tabla. */
.liga-vacia {
  background: var(--sup-1); border: 1px solid var(--linea); border-radius: var(--radio);
  padding: 16px 18px; margin: 10px 0 4px;
}
.liga-vacia-titulo { color: var(--hueso); font-size: 17px; font-weight: 700; margin: 0 0 6px; }
.liga-vacia .meta { margin: 0 0 10px; line-height: 1.5; }

/* ═══ BARRA DE SALIDA DEL CREADOR ═══════════════════════════════════════════════════════════════════
   Fija abajo, siempre visible. Antes el nombre y «DARLE VIDA» estaban al final de la página y quien
   entraba nuevo no tenía forma de saber cuál era el paso final: la pantalla no enseñaba su salida.
   Va por encima del contenido pero por debajo de los avisos, y respeta el área segura del iPhone. */
/* ⚠️ La barra fija TAPA lo último del contenido si no se le reserva su alto. Medido: los nombres de las
   piezas de la vitrina («púas», «flequillo», «antena») salían cortados por la mitad, así que elegir una
   categoría dejaba las opciones a medio ver. El `scroll-padding-bottom` además hace que cualquier
   desplazamiento automático deje la pieza por encima de la barra, no debajo. */
#crear { padding-bottom: 96px; }
.landing, html { scroll-padding-bottom: 110px; }
/* 🎨 La barra del VESTIDOR comparte TODA la geometría con la de bautismo: es la misma barra de salida
   pegada abajo, y se turnan. Va en el mismo bloque y no en una copia con sus propios números porque una
   copia se desincroniza en el primer ajuste de `padding` y nadie mira las dos a la vez para notarlo. */
.barra-crear, .barra-look {
  position: sticky; bottom: 0; z-index: 25;
  margin: 18px -18px 0; padding: 12px 18px calc(12px + env(safe-area-inset-bottom));
  background: rgba(5, 5, 5, .93);
  backdrop-filter: blur(10px);
  border-top: 1px solid var(--linea);
}
.barra-crear-dentro { display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: center; }
.etiqueta-crear {
  grid-column: 1 / -1; margin: 0 0 2px; color: var(--gris);
  font-size: 11px; letter-spacing: .14em;
}
.barra-crear input { margin: 0; }
.barra-look .barra-crear-dentro { grid-template-columns: 1fr auto; }
/* El estado («sin cambios» / «3 cambios sin guardar») ocupa la columna del nombre. Va en gris y
   pequeño: informa, no grita, y el sitio de gritar es el botón de al lado. */
.look-estado { margin: 0; color: var(--gris); font-size: 12px; line-height: 1.35; }
.look-botones { display: flex; gap: 8px; align-items: center; }
.barra-look .btn { margin: 0; white-space: nowrap; padding: 14px 20px; }
.btn-fantasma {
  background: transparent; color: var(--gris); border: 1px solid var(--linea);
  padding: 13px 14px; font-size: 12px;
}
.btn-fantasma:hover { color: var(--hueso); border-color: #4a463c; box-shadow: none; filter: none; }
/* Con el vestidor abierto el botón de guardar es el ÚNICO amarillo de la pantalla: si además
   heredase el `:not(.listo)` apagado de `#crear .btn`, el jugador tocaría cinco cascos y no vería
   nunca dónde se confirma. Aquí el encendido lo decide `pintaBarraLook()` con `.listo`. */

/* ⚠️ El botón SALIÓ de #crear al mudarse a esta barra, y con eso perdió sin querer el «confirmar
   escénico» (`#crear .btn:not(.listo)`): se quedaba amarillo desde el primer segundo. El selector de esa
   regla ahora alcanza también la barra, así que el patrón sobrevive a la mudanza — y aquí gana sentido:
   el botón se VE siempre, apagado, con «PONLE NOMBRE» encima, y se enciende al escribir. Antes ese
   encendido ocurría al final de una página que nadie había recorrido, o sea que no lo veía nadie. */
.barra-crear .btn { margin: 0; white-space: nowrap; padding: 14px 20px; }

/* Las CATEGORÍAS del creador en rejilla regular. Con `flex-wrap` quedaban 5+4 en escritorio y 4+4+1 en
   móvil, con «ARMA» sola en su fila: se leía como un desajuste, no como una decisión. */
#pestanas-slot { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px 4px; }
@media (min-width: 620px) { #pestanas-slot { grid-template-columns: repeat(5, 1fr); } }

/* La cifra de looks, ahora pegada a «empieza con un look» */
.unicidad { color: var(--gris); font-size: 11px; letter-spacing: 0; text-transform: none; margin-left: 6px; }


/* ═══ REDES: donde publicas ══════════════════════════════════════════════════════════════════════════
   Antes eran dos `<a class="btn">` amarillos apilados. Tres cosas iban mal y se ven en cualquier captura:
   el SUBRAYADO del enlace se colaba dentro del botón, cada uno tenía un ancho distinto según su texto, y
   DOS amarillos a la vez se anulan — el amarillo es el color de acción única de la marca.
   Ahora cada red es una FILA con su estado, y el botón es secundario: la jerarquía la pone el estado
   («sin conectar» / «conectado»), no dos manchas amarillas. */
.redes { list-style: none; padding: 0; margin: 16px 0 6px; display: grid; gap: 8px; }
.red {
  display: grid; grid-template-columns: 34px 1fr auto; gap: 12px; align-items: center;
  background: var(--sup-2); border: 1px solid var(--linea); border-radius: 10px; padding: 12px 14px;
}
.red-icono {
  width: 34px; height: 34px; display: grid; place-items: center;
  background: var(--negro); border: 1px solid var(--linea); border-radius: 8px;
  color: var(--gris); font-size: 15px;
}
.red-datos { min-width: 0; display: grid; gap: 2px; }
.red-nombre { color: var(--hueso); font-size: 15px; }
.red-estado { color: var(--gris); font-size: 12px; }
.red-estado-ok { color: var(--amarillo); }
/* Los números que leemos de esa red. Van con cifras TABULARES: son datos, y sin eso los dígitos bailan de
   ancho y la línea parece un texto más en vez de un recuento. */
.red-cifras {
  display: flex; flex-wrap: wrap; gap: 0 6px; margin-top: 3px; font-size: 12px; color: var(--gris);
  font-variant-numeric: tabular-nums; letter-spacing: .02em;
}
/* cada dato entero o a la línea siguiente — nunca «2570 ⏎ suscriptores».
   ⚠️ El separador «·» va en el DOM, NO en un `::before`: el contenido generado por CSS no llega igual a
   todos los lectores de pantalla, y sin él la línea se oye «14 vídeos128.430 visualizaciones». */
.red-cifras .cifra { white-space: nowrap; }
.red.vinculada .red-cifras { color: #cfc7ad; }
.red.vinculada .red-icono { color: var(--amarillo); border-color: #4a3d15; }
.red-acciones { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
/* ── LA SEGUNDA PUERTA (26-ago-2026): las redes, capadas aparte del juego ──────────────────────────
   Orden de Iñaki: «yo deshabilitaría esos botones por ahora hasta que más adelante lo desarrollemos».
   No se pulsan porque NO FUNCIONAN: Google sigue en «usuarios de prueba» y TikTok en sandbox, así que
   quien los pulse choca con una pantalla de error de Google, no con Nommeros.
   ⚠️ Se apagan por CSS y no borrando nodos desde JS, igual que la veda: el pintado de la cuenta rehace
   esta fila cada vez que llega `/api/yo`, y un `oculto` puesto a mano volvería a caerse solo. Y el que
   MANDA es el servidor (core/veda.mjs · REDES_ABIERTAS): esto solo evita que se vea roto. */
#redes-capadas-nota { display: none; }
body.redes-capadas #redes-capadas-nota { display: block; }
body.redes-capadas .red-acciones { display: none; }
/* ⚠️ EN ESTRECHO, LOS BOTONES BAJAN. Con las tres columnas fijas y dos botones al lado, en un móvil de
   480px la columna de texto se quedaba en ~130px: «conectado · sincroniza para traer lo nuevo» salía en
   tres líneas y los números en otras tres, y la fila se convertía en un párrafo. Se ve en la captura, no
   en el código. Aquí el texto ocupa el ancho entero y los botones se van debajo, alineados a la derecha. */
@media (max-width: 560px) {
  .red { grid-template-columns: 34px 1fr; row-gap: 10px; }
  .red-acciones { grid-column: 1 / -1; justify-content: flex-start; }
}
/* ⚠️ `text-decoration: none` explícito: estos botones son `<a>`, y sin esto el subrayado del enlace se
   dibuja DENTRO del botón. Se veía en la pantalla de cuenta desde el primer día. */
.btn-red { padding: 9px 13px; font-size: 12px; text-decoration: none; white-space: nowrap; }

/* Una etiqueta de sección que además lleva un control: el control va al lado, no dentro de la frase. Con
   el guion largo («TU HABITACIÓN — [vivir]») el botón se leía como parte del texto y no como algo pulsable. */
.fila-etiqueta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ⚠️ EL SALDO VIVE EN LA BARRA, no en el titular del tablón. `#saldo` sigue siendo la FUENTE (la barra del
   panel lo espeja con un MutationObserver, y `display:none` no afecta a `textContent`), pero pintarlo en
   los dos sitios enseñaba las monedas dos veces en la misma pantalla — y la del titular era la que menos
   se veía, arrinconada a la derecha de «TABLÓN DE MISIONES».
   No se borra del DOM a propósito: si desapareciera, la barra se quedaría sin de dónde copiar. */
#saldo { display: none; }

/* ═══ CATEGORÍAS DEL CREADOR EN MÓVIL: una sola fila ════════════════════════════════════════════════
   Medido en un móvil de 430×932: las 9 categorías ocupaban 156 px en 3 filas de 50, y la página pedía 227
   px de desplazamiento para verse entera. Con el icono solo —y el nombre únicamente en la ACTIVA— caben en
   una fila desplazable de ~50 px: 106 px recuperados, casi la mitad del déficit.
   Es EXACTAMENTE el patrón que ya usa la barra de pestañas del panel en este mismo ancho, así que el
   creador deja de resolver el mismo problema de otra manera. Los iconos son reconocibles (paleta, cara,
   músculo, pelo, casco, camiseta, bota, mochila, espadas) y la activa siempre dice su nombre. */
@media (max-width: 520px) {
  #pestanas-slot {
    /* ⚠️ `flex-wrap: nowrap` EXPLÍCITO: `#pestanas-slot` lleva la clase `.pestanas`, que ya trae
       `flex-wrap: wrap` de la hoja base. Sin anularlo la fila se PARTÍA en dos en vez de desplazarse, así
       que el bloque seguía ocupando 88 px y el arreglo no servía para nada — se veía en la captura. */
    display: flex; flex-wrap: nowrap; gap: 4px;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
    /* el desvanecido del final avisa de que hay más a la derecha, igual que en la fila de presets */
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 34px), transparent 100%);
    mask-image: linear-gradient(to right, #000 calc(100% - 34px), transparent 100%);
  }
  #pestanas-slot::-webkit-scrollbar { display: none; }
  #pestanas-slot .pestana { flex: 0 0 auto; }
  #pestanas-slot .pestana .pestana-txt { display: none; }
  #pestanas-slot .pestana[aria-selected="true"] .pestana-txt { display: inline; }
}

/* Aviso suave: una explicación, no un error. Se usa cuando el juego tiene que decir «esto todavía no» —
   por ejemplo al volver de pulsar «Vincular» con una red que aún no está abierta. Deliberadamente NO usa
   el rojo de error ni el amarillo de acción: no ha fallado nada y no hay nada que pulsar. */
.aviso-suave {
  margin: 14px 0 0;
  padding: 12px 14px;
  border-radius: 12px;
  border-left: 3px solid var(--amarillo);
  background: rgba(255, 255, 255, 0.04);
  color: var(--tenue, #b9b6ad);
  font-size: 0.95rem;
  line-height: 1.45;
}

/* «De dónde sale la XP», bajo el nivel del jugador. Existe porque el juego enseñaba «NIVEL 1 · 0/20 XP» y
   NADA decía cómo se sube: quien no ha vinculado su canal no puede ganar un solo punto, y eso no estaba
   escrito en ninguna parte. Es una explicación, no una alarma — de ahí el tamaño pequeño y el color tenue.
   El enlace sí lleva el amarillo de acción, porque es lo único que hay que hacer. */
.como-sube { display: block; margin: 4px 0 12px; font-size: 0.82rem; color: var(--tenue, #b9b6ad); line-height: 1.35; }
.como-sube a { color: var(--amarillo); text-decoration: underline; text-underline-offset: 3px; }

/* ── EL SELECTOR DE MODO (18-ago-2026) ────────────────────────────────────────────────────────────
   Dos tarjetas, no un <select>: lo que se elige aquí no se puede cambiar luego, así que las dos
   opciones tienen que estar VISIBLES a la vez con lo que miden escrito. Un desplegable esconde la
   alternativa detrás de un clic y hace que la irreversible parezca un ajuste menor. */
.modos {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .5rem; margin: .1rem 0 .45rem;
}
.modo-op {
  display: flex; flex-direction: column; gap: .18rem; text-align: left;
  padding: .55rem .65rem; border: 1px solid var(--linea); border-radius: 10px;
  background: var(--sup-1); color: inherit; cursor: pointer; font: inherit;
  transition: border-color .12s, background .12s, transform .12s;
}
.modo-op:hover { background: var(--sup-2); border-color: #4a463c; transform: translateY(-1px); }
.modo-op:active { transform: scale(.985); }
.modo-op[aria-checked="true"] {
  border-color: var(--amarillo); background: var(--sup-2);
  box-shadow: inset 0 0 0 1px var(--amarillo);
}
.modo-cabeza { display: flex; align-items: center; gap: .35rem; font-weight: 700; letter-spacing: .02em; }
.modo-cabeza .ico-svg { width: 18px; height: 18px; flex: none; opacity: .85; }
.modo-op[aria-checked="true"] .modo-cabeza { color: var(--amarillo); }
.modo-op[aria-checked="true"] .modo-cabeza .ico-svg { opacity: 1; }
.modo-mide { font-size: .74rem; line-height: 1.3; opacity: .72; }
.modo-nota { margin: 0 0 .55rem; opacity: .62; font-size: .72rem; }
/* En móvil, una debajo de otra: a dos columnas el texto de lo que mide cada modo cae a 3-4 palabras
   por línea y deja de leerse — y ese texto ES la decisión. */
@media (max-width: 430px) { .modos { grid-template-columns: 1fr; } }

/* ═══ 21-AGO-2026 · LA TARJETA DE «GUÁRDALO CON TU CORREO» ═══════════════════════════════════════
   Iñaki: «hay que mejorar esto de guardarlo con tu correo, se ve muy feo, hay que hacerlo más
   estético». El porqué de cada regla está en el comentario del `<section id="guardar">` de
   `web/index.html`: los cuatro defectos eran medibles, no de gusto.
   ⚠️ Este bloque va AL FINAL de la hoja a propósito. La regla que centra el hero de la portada
   (`body:not(.landing) :is(.kicker, h1, .sub, #guia-ios)`) puntúa 1-1-1 por el `#guia-ios` de dentro
   del `:is()`, así que un `#guardar .sub` (1-1-0) NO la gana por especificidad: hay que igualarla y
   ganar por orden. Si algún día mueves esto arriba, el `.sub` vuelve a salir centrado en escritorio
   dentro de una tarjeta alineada a la izquierda, que es justo el defecto (1). */
#guardar { border-color: rgba(255, 212, 0, .22); padding: 20px 20px 18px; }
#guardar .kicker { color: var(--amarillo); margin: 0 0 4px; font-weight: 700; }
/* la fecha de nacimiento deja de ser una línea suelta y pasa a PLACA: es el ancla que dice de QUIÉN
   es este formulario, y lo único de la tarjeta que habla del bicho que acabas de hacer */
#guardar .nacimiento-fecha {
  display: inline-block; margin: 8px 0 10px; padding: 6px 11px;
  background: rgba(255, 212, 0, .10); border: 1px solid rgba(255, 212, 0, .28);
  border-radius: 999px; font-size: 13px; letter-spacing: .01em;
}
/* ↓ 1-2-1: gana a la regla del hero (1-1-1) y encima viene después */
body:not(.landing) #guardar :is(.sub, .kicker) { text-align: left; }
#guardar .sub { margin: 0 0 4px; font-size: 15px; }
#guardar .etiqueta { margin-top: 14px; }
#guardar input[type="email"] { padding: 13px 12px; border-radius: 8px; }
#guardar .check { margin: 12px 0 16px; align-items: flex-start; line-height: 1.35; }
#guardar .check input { margin-top: 1px; flex: none; }
/* la acción principal ocupa la línea entera: era un botón del ancho de su texto con medio renglón
   muerto al lado, y ésa es la única cosa que esta pantalla te está pidiendo que hagas */
.btn-ancho { display: block; width: 100%; text-align: center; border-radius: 8px; }
/* 🔴 `text-decoration: none` explícito: el de Google es un `<a>`, y sin esto el subrayado del enlace
   se cuela DENTRO del botón. Ya pasó con `.btn-red`; el mismo fallo, otra pantalla. */
a.btn-ancho { text-decoration: none; }
#guardar #btn-guardar { margin-top: 2px; padding: 15px 22px; font-size: 17px; }
#guardar #aviso-guardar:empty { display: none; }
#guardar #aviso-guardar { margin: 10px 0 0; }
/* el «o» con dos hilos, en vez de un «· o ·» suelto que se leía como texto perdido */
.separador-o { display: flex; align-items: center; gap: 12px; color: var(--gris);
  font-size: 12px; letter-spacing: .18em; text-transform: uppercase; margin: 16px 0; }
.separador-o::before, .separador-o::after { content: ""; flex: 1; height: 1px; background: var(--linea); }
#guardar .guardar-riesgo { margin: 14px 0 0; font-size: 12px; opacity: .75; }

/* El puente a El Show de Last, que sale al guardar (U0072, 22-ago-2026). El `<a>` NECESITA color y
   `text-underline-offset` explícitos: sin ellos el navegador lo pinta en su AZUL de serie sobre un fondo
   negro con paleta amarillo/hueso, y se ve medido en la captura del flujo real. Es el tercer `<a>` de
   esta misma pantalla que cae en lo mismo (antes el de Google), así que aquí no se hereda de nadie: se
   reusa el patrón que ya existe en `.como-sube a`, que es el enlace-dentro-de-texto de la casa. */
#guardar-reto { margin: 10px 0 0; line-height: 1.45; }
#guardar-reto a { color: var(--amarillo); text-decoration: underline; text-underline-offset: 3px; }
