/* =========================================================================
   Corral de Ovejas - hoja de estilos unica.
   Organizada en: variables -> base -> componentes -> pantallas -> responsive.
   Los componentes (.btn, .card, .field, .panel) se reutilizan en todas las
   pantallas para no repetir estilos.
   ========================================================================= */

:root {
  --green-900: #10241a;
  --green-800: #16362552;
  --green-700: #1b3a2b;
  --green-600: #245c3f;
  --green-500: #2f7d52;
  --green-400: #43a06a;
  --cream:     #f6f1e2;
  --cream-2:   #e9e0c9;
  --ink:       #17251d;
  --ink-soft:  #4a5b51;
  --gold:      #f2b134;
  --gold-dark: #c98a1a;
  --danger:    #d8503f;
  --danger-dark:#a93a2c;
  --info:      #3b82f6;
  --purple:    #8b5cf6;

  /* ---------------------------------------------------------------------
     Acentos.

     El juego era verde, crema y poco mas: correcto pero apagado para un
     grupo de adolescentes. Estos colores son los que le dan alegria sin
     abandonar la identidad de granja: cielo, atardecer, flores del prado.
     Cada uno tiene su pareja oscura para poder hacer degradados, que es lo
     que separa un boton plano de uno con cuerpo.
     --------------------------------------------------------------------- */
  --sky:       #38bdf8;
  --sky-dark:  #0284c7;
  --coral:     #fb7185;
  --coral-dark:#e11d48;
  --mango:     #fb923c;
  --mango-dark:#ea580c;
  --grape:     #a78bfa;
  --grape-dark:#7c3aed;
  --mint:      #34d399;
  --mint-dark: #059669;

  /* Degradados listos para usar: un solo sitio los define. */
  --grad-green: linear-gradient(135deg, #43a06a, #2f7d52);
  --grad-gold:  linear-gradient(135deg, #ffd166, #f2b134);
  --grad-sky:   linear-gradient(135deg, #7dd3fc, #0ea5e9);
  --grad-coral: linear-gradient(135deg, #fda4af, #f43f5e);
  --grad-grape: linear-gradient(135deg, #c4b5fd, #8b5cf6);
  /*
   * Acento de la marca. Empezo siendo un arcoiris de cinco colores y resultaba
   * disfraz de fiesta: se quedan solo el verde y el dorado, que son los colores
   * del juego, con un toque de miel entre medias.
   */
  --grad-fiesta: linear-gradient(90deg, #2f7d52, #6bbd7f, #f2b134, #e08b3a);

  --panel-bg: rgba(255, 253, 246, 0.97);
  --shadow-sm: 0 2px 6px rgba(0, 0, 0, .18);
  --shadow-md: 0 10px 30px rgba(0, 0, 0, .28);
  --radius: 14px;
  --radius-sm: 9px;

  /* Cristal del HUD: un solo sitio define el look de todo lo que flota
     sobre el corral (fichas, botones, chat, podio, rueda de bailes). */
  --glass-bg: rgba(14, 32, 23, .74);
  --glass-border: rgba(255, 255, 255, .14);
  --glass-blur: blur(10px) saturate(1.15);
  --font: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", sans-serif;
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  /* En horizontal el notch se come el lateral: sin esto, el joystick o los
     botones quedan medio tapados por la muesca o por la barra de gestos. */
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);

  /* Lado minimo de cualquier cosa que se toque con el dedo. */
  --touch: 46px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  font-family: var(--font);
  color: var(--ink);
  background: var(--green-700);
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
}

/*
 * `font-size: 1rem` (16 px) no es estetica: por debajo de 16 px Safari en iOS
 * hace zoom automatico al enfocar un campo y deja la pantalla descuadrada, sin
 * forma de volver porque el juego desactiva el zoom manual.
 *
 * `touch-action: manipulation` quita el retardo de ~300 ms que algunos
 * navegadores dejan por si el toque era un doble toque para hacer zoom.
 */
button, input, select, textarea { font-family: inherit; font-size: 1rem; }
button { touch-action: manipulation; }

.app { position: fixed; inset: 0; display: flex; flex-direction: column; }

/* ------------------------------------------------------------------ base */

h1, h2, h3, h4 { margin: 0 0 .5rem; line-height: 1.2; }
h1 { font-size: 1.7rem; }
h2 { font-size: 1.3rem; }
h3 { font-size: 1.05rem; }
p  { margin: 0 0 .6rem; line-height: 1.5; }
small, .muted { color: var(--ink-soft); font-size: .85rem; }
.center { text-align: center; }
.row { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
.row-tight { display: flex; gap: .35rem; align-items: center; }
.spacer { flex: 1; }
.hidden { display: none !important; }
.stack > * + * { margin-top: .8rem; }
.scroll { overflow-y: auto; -webkit-overflow-scrolling: touch; }

/* --------------------------------------------------------------- botones */

/*
 * Botones.
 *
 * Tres cosas los sacan de "plano y aburrido":
 *   1. degradado en lugar de color liso, para que tengan volumen;
 *   2. la sombra es del COLOR del boton, no gris. Un boton verde deja un halo
 *      verde, y eso es lo que hace que parezca que brilla en vez de que pesa;
 *   3. al pulsar se hunde de verdad (baja 2px y pierde la sombra), asi que se
 *      siente el clic aunque no pase nada mas.
 */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .45rem;
  padding: .68rem 1.05rem;
  border: none;
  border-radius: var(--radius-sm);
  background: var(--grad-green);
  color: #fff;
  font-weight: 700;
  letter-spacing: .01em;
  cursor: pointer;
  transition: transform .1s ease, box-shadow .16s ease, filter .16s ease;
  box-shadow: 0 3px 0 rgba(0, 0, 0, .13), 0 4px 10px -5px var(--green-500);
  line-height: 1.1;
}
.btn:hover:not(:disabled) {
  filter: brightness(1.06);
  transform: translateY(-1px);
  box-shadow: 0 4px 0 rgba(0, 0, 0, .13), 0 7px 16px -6px var(--green-500);
}
.btn:active:not(:disabled) {
  transform: translateY(2px);
  box-shadow: 0 1px 0 rgba(0, 0, 0, .13), 0 2px 6px -2px var(--green-500);
}
.btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; filter: grayscale(.4); }

.btn-gold {
  background: var(--grad-gold); color: #4a3406;
  box-shadow: 0 3px 0 rgba(0,0,0,.13), 0 4px 10px -5px var(--gold);
}
.btn-gold:hover:not(:disabled)  { box-shadow: 0 4px 0 rgba(0,0,0,.13), 0 7px 16px -6px var(--gold); }
.btn-gold:active:not(:disabled) { box-shadow: 0 1px 0 rgba(0,0,0,.13), 0 2px 6px -2px var(--gold); }

.btn-danger {
  background: linear-gradient(135deg, #f87171, #dc2626);
  box-shadow: 0 3px 0 rgba(0,0,0,.13), 0 4px 10px -5px var(--danger);
}
.btn-info {
  background: var(--grad-sky);
  box-shadow: 0 3px 0 rgba(0,0,0,.13), 0 4px 10px -5px var(--sky);
}
.btn-grape {
  background: var(--grad-grape);
  box-shadow: 0 3px 0 rgba(0,0,0,.13), 0 4px 10px -5px var(--grape);
}
.btn-coral {
  background: var(--grad-coral);
  box-shadow: 0 3px 0 rgba(0,0,0,.13), 0 4px 10px -5px var(--coral);
}
.btn-dark { background: linear-gradient(135deg, #2a5340, #16362a); box-shadow: var(--shadow-sm); }

.btn-ghost {
  background: #fffdf7; color: var(--ink);
  border: 2px solid #ddd4bc;
  box-shadow: 0 2px 0 rgba(0,0,0,.05);
  font-weight: 600;
}
.btn-ghost:hover:not(:disabled) {
  background: #fff;
  border-color: var(--green-400);
  color: var(--green-600);
  box-shadow: 0 3px 0 rgba(0,0,0,.05);
}

.btn-sm     { padding: .38rem .68rem; font-size: .85rem; }
.btn-block  { width: 100%; }
.btn-icon   { padding: .5rem .6rem; }

/* --------------------------------------------------------------- campos */

.field { display: block; margin-bottom: .75rem; }
.field > span { display: block; font-size: .82rem; font-weight: 600; margin-bottom: .28rem; color: var(--ink-soft); }
.field input, .field select, .field textarea {
  width: 100%;
  padding: .65rem .75rem;
  border: 1.5px solid #d8cfb6;
  border-radius: var(--radius-sm);
  background: #fffdf7;
  color: var(--ink);
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--green-400);
  box-shadow: 0 0 0 3px rgba(67, 160, 106, .18);
}
.field textarea { resize: vertical; min-height: 74px; }

.error-box {
  background: #fdecea;
  border: 1.5px solid #f3b7ae;
  color: #8c2418;
  padding: .6rem .75rem;
  border-radius: var(--radius-sm);
  font-size: .9rem;
  margin-bottom: .7rem;
}
.info-box {
  background: #eef7f1;
  border: 1.5px solid #b9dfc7;
  color: #1e4c33;
  padding: .6rem .75rem;
  border-radius: var(--radius-sm);
  font-size: .9rem;
}

/* --------------------------------------------------------------- tarjetas */

.card {
  position: relative;
  background: var(--panel-bg);
  border-radius: var(--radius);
  padding: 1rem;
  box-shadow: var(--shadow-sm);
  border: 1px solid rgba(0, 0, 0, .05);
  overflow: hidden;
  transition: transform .15s ease, box-shadow .15s ease;
}
/* Filete de color en el canto izquierdo: rompe el blanco sin gritar. */
.card::before {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--grad-green);
  opacity: .9;
}
.card-gold::before  { background: var(--grad-gold); }
.card-sky::before   { background: var(--grad-sky); }
.card-grape::before { background: var(--grad-grape); }
.card-coral::before { background: var(--grad-coral); }
.card + .card { margin-top: .8rem; }
.card-head { display: flex; align-items: center; gap: .5rem; margin-bottom: .6rem; }
.card-head h3 { margin: 0; flex: 1; }

.tag {
  display: inline-block;
  padding: .16rem .5rem;
  border-radius: 999px;
  font-size: .72rem;
  font-weight: 700;
  background: #e6ded0;
  color: #4c4230;
  white-space: nowrap;
}
.tag-green  { background: #d6f0e0; color: #1c5334; }
.tag-gold   { background: #fbeccb; color: #7a5406; }
.tag-red    { background: #fadcd7; color: #8c2418; }
.tag-blue   { background: #dbeafe; color: #1e40af; }
.tag-purple { background: #ede9fe; color: #5b21b6; }

.code-pill {
  font-family: "Consolas", "SF Mono", monospace;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: .06em;
  background: #23402f;
  color: #ffe9a8;
  padding: .45rem .8rem;
  border-radius: var(--radius-sm);
  display: inline-block;
  user-select: all;
}

/* -------------------------------------------------------------- arranque */

.boot-screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: var(--cream);
  gap: .8rem;
}
.boot-sheep { font-size: 4rem; animation: bounce 1.1s infinite ease-in-out; }
@keyframes bounce { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-16px); } }

/* ---------------------------------------------------------- autenticacion */

/* =========================================================================
 * PORTADA  (repintada con `criterio-humano`)
 *
 * El fondo es un CUADRO que trajo Hansel: `public/img/fondo-login.png`. Pixel
 * art de dia — prado, iglesia, ovejas y los dos carteles (ORA / LEE / CONFIA /
 * CRECE y ORAR / LEER BIBLIA / MISION DIARIA), que es el juego entero contado
 * en una imagen. Antes esto era un atardecer pintado a mano con bandas planas
 * de CSS; se hizo porque el verde liso de la version anterior era el unico
 * color de la pantalla, y ese problema el cuadro ya no lo tiene: trae cielo,
 * montana, camino y flores. La razon de aquel apano se cae sola, asi que el
 * apano tambien.
 *
 * Del atardecer sobreviven los COLORES, que son entradas EXACTAS de `PALETTE`
 * (`public/js/game/pixel.js`) y visten la tarjeta, las pestanas y los botones.
 * El naranja de fuego sobre el azul del cielo del cuadro tira mas que sobre el
 * morado, asi que el cambio le sienta bien a lo que ya habia.
 *
 * ENCIMA DEL CUADRO VA UNA CAPA, y la pidio Hansel: *"que la imagen del fondo
 * se vea como opaco o distorsionado un poco porque estas en el login"*. Son
 * dos pisos y dos mandos (`--fondo-velo` y `--fondo-desenfoque`, justo abajo).
 * Sale en las tres pantallas que usan `.auth-screen` — entrar, crear cuenta y
 * las de corral de `gateScreens.js` — porque asi lo pidio: la capa es de "estar
 * en el login", no de una pantalla concreta.
 *
 * OJO, EL DESENFOQUE CONTRADICE A `criterio-humano` a proposito: alli pone que
 * el pixel art no difumina, y es verdad. Se eligio entre cuatro intensidades
 * mirandolas, y Hansel se quedo con esta (velo 25 %, 3 px) por delante de una
 * variante que distorsionaba pixelando mas grueso sin difuminar nada. O sea que
 * no es un descuido: es lo que se pidio despues de ver las dos. No hay mas
 * `blur` en toda la interfaz, y este no debe servir de precedente.
 *
 * `image-rendering: pixelated` NO es opcional, y ahora vive en el `::before`.
 * El cuadro es cuadrado (1254 px) y en una pantalla ancha `cover` lo estira por
 * encima de su tamano; sin esto el navegador lo interpola y el fondo sale
 * lechoso ademas de desenfocado. Primero se amplia a bloques duros, luego el
 * `blur` de 3 px los ablanda: ese orden es el que conserva el pixel art.
 *
 * Pesaba 1,9 MB. Esta cuantizado a 128 colores (PNG indexado, 378 KB) porque
 * esto se sirve por el hotspot del movil y es lo PRIMERO que se descarga.
 * Indexado y no JPEG: el JPEG ensucia los bordes duros y las letras de los
 * carteles, que aqui son diminutas.
 *
 * Los overrides van colgados de `.auth-screen` a proposito: `.btn`, `.field`,
 * `.tabs` y `.divider` los comparten la tienda, el arcade, el bano y los dos
 * paneles de admin, y repintar todo eso no se ha pedido. Cuando le toque el
 * turno a la siguiente pantalla, estas reglas suben al componente.
 * ========================================================================= */

.auth-screen {
  position: relative;
  flex: 1;
  /*
   * `display: flex` + `margin: auto` en la tarjeta, y NADA de `align-items`
   * ni `justify-content`. Con esos dos la sombra dura sobresalia 8 px, abria
   * scroll horizontal y el centrado se iba: la tarjeta salia pegada al borde
   * derecho y cortada. Con `margin: auto` se centra igual pero cuando no cabe
   * se puede llegar a los dos lados.
   */
  display: flex;
  /*
   * `min-height` ademas de `flex: 1`: las pantallas de `gateScreens.js`
   * (esperando aprobacion, entrar al corral, crear corral) envuelven esto en
   * un `div` sin clase que no reparte altura, asi que el cielo se quedaba a la
   * altura del formulario y la mitad de abajo era verde liso. Con el degradado
   * viejo casi no se veia; con bandas duras canta.
   */
  min-height: 100vh;
  min-height: 100dvh;
  padding: 1rem .9rem;
  padding-top: calc(1rem + var(--safe-top));
  overflow-y: auto;
  overflow-x: hidden;

  /* Cuatro tamanos de letra para TODA la pantalla, y se reutilizan. */
  --f-title: 1.75rem;
  --f-body:  .95rem;
  --f-small: .8rem;
  --f-tiny:  .7rem;

  /*
   * Los cinco colores de la portada, sacados de PALETTE. Eran once: los seis
   * que faltan (dusk, lilac, flame, sun y los dos verdes) solo pintaban el
   * cielo, el sol y las colinas de CSS, y de eso ahora se encarga el cuadro.
   */
  --p-night: #282242;
  --p-ember: #c44a18;
  --p-wool:  #f7f2e8;
  --p-ink:   #1a1412;
  --p-gold:  #f2b134;

  /*
   * LOS DOS MANDOS DE LA CAPA. Estan aqui arriba y sueltos porque son lo unico
   * que hay que tocar para subir o bajar el efecto; el resto de la maquinaria
   * (los dos pseudoelementos) no se toca.
   *
   *   --fondo-velo        cuanto TAPA:        el alfa del tinte de tinta
   *   --fondo-desenfoque  cuanto DISTORSIONA: el radio del desenfoque
   */
  --fondo-velo: #28224240;
  --fondo-desenfoque: 3px;

  /*
   * El color liso es solo el RESPALDO: se ve el instante antes de que llegue
   * el PNG, y se queda si no llega. Es el azul medio del cielo del cuadro
   * (media de su franja de arriba), no un azul cualquiera.
   */
  background-color: #7ea6bf;
}

/*
 * LA CAPA, primer piso: el cuadro.
 *
 * El PNG se pinta AQUI y no en el fondo de `.auth-screen` por una razon: hay
 * que desenfocarlo, y `filter` en el elemento arrastraria tambien a la tarjeta
 * y al formulario, que es justo lo que no puede pasar. En un pseudoelemento el
 * desenfoque se queda en el fondo.
 */
.auth-screen::before {
  content: '';
  position: absolute;
  /*
   * Sobresale por los cuatro lados el DOBLE del desenfoque. Un `blur` mezcla
   * cada pixel con sus vecinos, y en el borde no hay vecinos: sin este margen
   * los cuatro cantos salen lavados, con una orla clara de un par de pixeles
   * que canta sobre todo abajo. El `overflow` del padre recorta el sobrante.
   */
  inset: calc(var(--fondo-desenfoque) * -2);
  background-image: url('../img/fondo-login.png');
  background-size: cover;
  /*
   * En vertical `cover` no recorta por arriba y por abajo, RECORTA POR LOS
   * LADOS: en un movil se ve poco mas de un tercio del ancho del cuadro. Por
   * eso no va centrado. Corrido al 62 % entran la iglesia y el cartel de las
   * tres tareas, que es la mitad que cuenta algo; centrado solo se veia el
   * camino, y la tarjeta lo tapa casi entero.
   */
  background-position: 62% center;
  background-repeat: no-repeat;
  image-rendering: pixelated;
  filter: blur(var(--fondo-desenfoque));
  pointer-events: none;
}

/*
 * LA CAPA, segundo piso: el velo de tinta, PLANO.
 *
 * El cuadro es de mediodia y muy luminoso, y la tarjeta es color hueso: sin
 * esto se tocan en valor y el borde tiene que hacer solo todo el trabajo de
 * despegarla. Un tinte oscuro uniforme la manda atras y deja claro que el
 * fondo es fondo. Color liso y no vineta difuminada: no se mete un degradado
 * en una pantalla que no tiene ninguno.
 *
 * Va en un segundo pseudoelemento en vez de encima del primero porque el
 * `filter` del de abajo tambien desenfocaria el velo contra sus bordes.
 */
.auth-screen::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--fondo-velo);
  pointer-events: none;
}

/*
 * La tarjeta.
 *
 * Esquinas a cero y sombra dura desplazada: la vieja tenia radio 22 y una
 * sombra de 50 px de difuminado, o sea una tarjeta de web encima de un juego
 * de pixeles. El borde de tinta es el mismo recurso que usa el sprite de la
 * oveja para despegarse del fondo.
 */
.auth-card {
  position: relative;
  z-index: 1;
  /* 8 px menos de los que caben: es el hueco que necesita la sombra dura
     para no salirse y abrir scroll horizontal. */
  width: min(410px, calc(100% - 8px));
  background: var(--p-wool);
  border: 3px solid var(--p-ink);
  border-radius: 0;
  padding: 1.5rem 1.4rem 1.4rem;
  box-shadow: 8px 8px 0 var(--p-night);
  margin: auto;
  font-size: var(--f-body);
}
/* Banda de oro en el canto de arriba: un color, no una cinta de cinco. */
.auth-card::before {
  content: '';
  position: absolute; top: 0; left: 0; right: 0; height: 6px;
  background: var(--p-gold);
}

/* Las pantallas intermedias (esperando aprobacion, entrar al corral, crear
   corral) reusan `.auth-card` con un `h1` suelto, sin `.auth-logo`. */
.auth-card h1 { font-size: var(--f-title); color: var(--p-ink); }
.auth-card p  { font-size: var(--f-body); color: #4a5b51; }
.auth-card > .center h1 { margin-top: .3rem; }

.auth-logo { text-align: center; margin-bottom: 1rem; }
.auth-logo .emoji {
  font-size: 3.2rem; display: block; line-height: 1;
  animation: logo-hop 2.6s ease-in-out infinite;
}
@keyframes logo-hop {
  0%, 62%, 100% { transform: translateY(0) rotate(0); }
  72%           { transform: translateY(-9px) rotate(-6deg); }
  84%           { transform: translateY(0) rotate(4deg); }
}
.auth-logo h1 {
  font-size: var(--f-title);
  margin: .4rem 0 .35rem;
  color: var(--p-ink);
  letter-spacing: -.01em;
}
/* Subrayado corto de oro en vez del degradado sobre el texto. */
.auth-logo h1::after {
  content: '';
  display: block;
  width: 54px; height: 4px;
  margin: .45rem auto 0;
  background: var(--p-gold);
}
.auth-logo small { font-size: var(--f-small); color: #6e645c; }

.auth-screen .tabs {
  display: flex; gap: 0;
  background: transparent; padding: 0;
  border: 2px solid var(--p-ink);
  border-radius: 0;
  margin-bottom: 1rem;
}
.auth-screen .tabs button {
  flex: 1;
  border: none;
  border-radius: 0;
  background: var(--p-wool);
  padding: .6rem;
  font-size: var(--f-small);
  font-weight: 700;
  color: #6e645c;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.auth-screen .tabs button + button { border-left: 2px solid var(--p-ink); }
/* La pestana viva se pinta de tinta: se distingue por VALOR, no por color,
   asi que sigue leyendose igual de lejos y en una pantalla al sol. */
.auth-screen .tabs button.active {
  background: var(--p-ink);
  color: var(--p-wool);
  box-shadow: none;
}

/*
 * Selector de rol.
 *
 * Cada rol tiene su color, y no es decoracion: ayuda a acordarse de cual eres
 * ("yo soy el morado") y hace que elegir sea un momento y no un formulario.
 * El elegido se HUNDE en vez de levantarse -2 px abajo y la sombra pasa de 4
 * a 2- porque el "hover levantita" no existe con el dedo, y esto si.
 */
.role-picker { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; margin-bottom: .9rem; }
.role-option {
  position: relative;
  border: 2px solid var(--p-ink);
  border-radius: 0;
  padding: .75rem .5rem;
  text-align: center;
  cursor: pointer;
  background: #fffdf8;
  box-shadow: 4px 4px 0 var(--p-ink);
  transition: transform .1s ease, box-shadow .1s ease, background .15s ease;
}
.role-option .emoji { font-size: 1.75rem; display: block; }
.role-option strong { font-size: var(--f-body); display: block; color: var(--p-ink); }
.role-option small  { font-size: var(--f-tiny); display: block; color: #6e645c; }

/* Hundirse es la respuesta AL DEDO, no la marca de "elegido": si el elegido se
   queda hundido, las dos fichas dejan de alinear por el borde y se ve
   descuadrado. El elegido se distingue por color de fondo. */
.role-option:active { transform: translate(2px, 2px); box-shadow: 2px 2px 0 var(--p-ink); }
/*
 * Oveja en verde prado, pastor en morado: los mismos dos colores que los
 * distinguen dentro del juego.
 *
 * Los dos tintes salen de PALETTE, no del ojo: son el cesped `#6bb56e` y el
 * morado `#7460a8` al 30 % sobre la lana `#f7f2e8`. Hace falta rebajarlos
 * porque a plena saturacion no se puede leer texto de tinta encima.
 */
.role-option.active              { background: #cddecd; }
.role-option:nth-child(2).active { background: #d0c6d5; }

.auth-screen .divider {
  display: flex; align-items: center; gap: .6rem;
  margin: 1.1rem 0 .8rem;
  color: #6e645c; font-size: var(--f-small);
}
.auth-screen .divider::before,
.auth-screen .divider::after { content: ""; flex: 1; height: 2px; background: #cdbfa3; }

.google-btn {
  display: flex; align-items: center; justify-content: center; gap: .6rem;
  width: 100%; padding: .7rem;
  border-radius: 0;
  border: 2px solid var(--p-ink);
  background: #fff;
  font-weight: 600; font-size: var(--f-body);
  cursor: pointer; color: #3c4043;
  box-shadow: 4px 4px 0 var(--p-ink);
  transition: transform .1s ease, box-shadow .1s ease;
}
.google-btn:active { transform: translate(2px, 2px); box-shadow: 2px 2px 0 var(--p-ink); }
.google-btn svg { width: 19px; height: 19px; }

/* ---- componentes compartidos, solo dentro de la portada ---------------- */

.auth-screen .btn {
  border-radius: 0;
  background: var(--p-ink);
  color: var(--p-wool);
  font-size: var(--f-body);
  padding: .75rem 1.05rem;
  box-shadow: 4px 4px 0 var(--p-night);
  transition: transform .1s ease, box-shadow .1s ease, background .15s ease;
}
.auth-screen .btn:hover:not(:disabled) {
  filter: none; transform: none;
  background: #3a2c22;
  box-shadow: 4px 4px 0 var(--p-night);
}
.auth-screen .btn:active:not(:disabled) {
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 var(--p-night);
}
.auth-screen .btn:disabled { opacity: .4; filter: none; box-shadow: 4px 4px 0 var(--p-night); }

/* El boton secundario es el mismo hueco en negativo: crema con borde de tinta. */
.auth-screen .btn-ghost {
  background: #fffdf8;
  color: var(--p-ink);
  border: 2px solid var(--p-ink);
  box-shadow: 4px 4px 0 var(--p-ink);
}
.auth-screen .btn-ghost:hover:not(:disabled) {
  background: #fff; border-color: var(--p-ink); color: var(--p-ink);
  box-shadow: 4px 4px 0 var(--p-ink);
}
.auth-screen .btn-ghost:active:not(:disabled) { box-shadow: 2px 2px 0 var(--p-ink); }

.auth-screen .field > span {
  font-size: var(--f-small);
  color: var(--p-ink);
  text-transform: uppercase;
  letter-spacing: .04em;
}
.auth-screen .field input {
  border-radius: 0;
  border: 2px solid #cdbfa3;
  background: #fffdf8;
  font-size: var(--f-body);
}
/* El foco marca con OTRO BORDE, no con un halo difuminado alrededor. */
.auth-screen .field input:focus {
  border-color: var(--p-ink);
  box-shadow: 3px 3px 0 var(--p-gold);
}

.auth-screen .error-box,
.auth-screen .info-box {
  border-radius: 0;
  border-width: 2px;
  font-size: var(--f-small);
}
.auth-screen .error-box { background: #fadcd7; border-color: var(--p-ember); color: #7d2410; }
.auth-screen .info-box  { background: #ede8dc; border-color: #a89578; color: #4a2c20; }

/* --------------------------------------------------------------- pantalla */

.screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}
.screen-pad {
  padding: 1rem;
  padding-top: calc(1rem + var(--safe-top));
  padding-bottom: calc(1rem + var(--safe-bottom));
  overflow-y: auto;
  background: linear-gradient(160deg, #1b3a2b, #0f2419);
  flex: 1;
}
.screen-inner { width: min(1100px, 100%); margin: 0 auto; }

.top-bar {
  display: flex; align-items: center; gap: .6rem;
  padding: .6rem .8rem;
  padding-top: calc(.6rem + var(--safe-top));
  background: var(--green-700);
  color: var(--cream);
  box-shadow: var(--shadow-sm);
  flex-wrap: wrap;
  z-index: 5;
}
.top-bar h2 { margin: 0; font-size: 1.05rem; }
.top-bar .who { font-size: .78rem; opacity: .85; }

/* ------------------------------------------------------------------ juego */

.game-screen { position: relative; flex: 1; overflow: hidden; background: #7cb87c; }
#game-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }

.hud { position: absolute; inset: 0; pointer-events: none; }
.hud > * { pointer-events: auto; }

.hud-top {
  position: absolute; top: calc(.5rem + var(--safe-top)); left: .5rem;
  display: flex; flex-direction: column; gap: .4rem; max-width: 62vw;
}
/*
 * ---------------------------------------------------------------------------
 *  EL HUD, CON EL CRITERIO DEL JUEGO (26-sep-2026)
 * ---------------------------------------------------------------------------
 * Antes era cristal: verde translucido, desenfoque, pastillas redondas y un
 * emoji en cada boton. Ahora lleva lo mismo que los carteles de accion y el
 * menu: colores planos de PALETTE, contorno de tinta, sombra DURA y botones
 * que se hunden al pulsarlos. Fuera del menu solo queda esto: la ficha, el
 * saldo, el buzon y el boton del menu (Hansel: "todo en menu, menos el buzon").
 */
.player-chip {
  display: flex; align-items: center; gap: .5rem;
  background: var(--ms-green-dk);
  color: var(--ms-paper);
  border: 2px solid var(--ms-ink);
  box-shadow: 3px 3px 0 var(--ms-ink);
  padding: .3rem .65rem .3rem .3rem;
}
/* La cara de la oveja, en pixel art (ver `paintAvatar` en menuScenes.js), sobre
   el celeste del cielo del prado. */
.player-chip .avatar {
  width: 38px; height: 38px; flex-shrink: 0;
  display: grid; place-items: center; overflow: hidden;
  background: #9fd8f2;
  border: 2px solid var(--ms-ink);
}
.player-chip .avatar canvas { display: block; image-rendering: pixelated; }
.player-chip .meta { min-width: 0; }
.player-chip .name { font-weight: 900; font-size: var(--ms-body); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.player-chip .sub { font-size: var(--ms-small); color: var(--ms-paper-2); }

.xp-bar {
  height: 8px; width: 130px; margin-top: 4px;
  background: var(--ms-ink);
  border: 1px solid var(--ms-ink);
  overflow: hidden;
}
.xp-bar i {
  display: block; height: 100%;
  background: var(--ms-gold);
  transition: width .4s ease;
}

/* ---- el lado derecho: saldo, buzon y menu, en una fila */
.hud-actions {
  position: absolute; right: calc(.5rem + var(--safe-right)); top: calc(.5rem + var(--safe-top));
  display: flex; align-items: flex-start; gap: .45rem;
}
.hud-purse { display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; justify-content: flex-end; }

/* Las fichas del saldo: tinta con el numero en el color de lo que cuentan. */
.coin-chip, .gem-chip, .streak-chip {
  display: inline-flex; align-items: center; gap: .3rem;
  height: 34px; padding: 0 .6rem 0 .3rem;
  background: var(--ms-green-dk);
  border: 2px solid var(--ms-ink);
  box-shadow: 3px 3px 0 var(--ms-ink);
  font-size: var(--ms-body); font-weight: 900; font-variant-numeric: tabular-nums;
}
.coin-chip i, .gem-chip i, .streak-chip i { display: block; line-height: 0; }
.coin-chip svg, .gem-chip svg, .streak-chip svg { width: 24px; height: 24px; display: block; }
.coin-chip { color: var(--ms-gold-lt); }
/* Agua clara de PALETTE: el color de la gema, para que se lea de un vistazo. */
.gem-chip { color: #9fd8f2; }
.streak-chip { color: #f9a825; }

/* Los dos botones: cuadrados, con su icono pixel a 24 px (2 por casilla). */
.hud-btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  min-width: 44px; height: 44px; padding: 0 .7rem 0 .55rem;
  border: 2px solid var(--ms-ink); border-radius: 0;
  box-shadow: 3px 3px 0 var(--ms-ink);
  font: inherit; font-size: var(--ms-body); font-weight: 900;
  cursor: pointer;
  /* opacity/visibility: se apartan en la vista de mapa completo (abajo). */
  transition: opacity .18s ease, visibility .18s ease;
}
.hud-btn:active { translate: 2px 2px; box-shadow: 1px 1px 0 var(--ms-ink); }
.hud-btn:focus-visible { outline: 3px solid var(--ms-gold-lt); outline-offset: 2px; }
.hud-ico { display: block; line-height: 0; }
.hud-ico svg { width: 24px; height: 24px; display: block; }
/* El menu en oro: es EL boton, el que abre todo lo demas. */
.hud-menu-btn { background: var(--ms-gold); color: var(--ms-ink); }
.hud-menu-btn .hud-ico svg { filter: none; }
/* El buzon en papel, que es de lo que esta hecha una carta. */
.hud-mail-btn { background: var(--ms-paper); color: var(--ms-ink); }

/*
 * El punto rojo de las cartas sin abrir. Sale SOLO con 1 o mas (el atributo
 * `hidden` lo quita del todo con 0). Teja clara de PALETTE, contorno de tinta y
 * el numero en blanco; entra con un saltito para que se note que acaba de llegar.
 */
.hud-badge {
  position: absolute; top: -9px; right: -9px;
  min-width: 22px; height: 22px; padding: 0 5px;
  display: grid; place-items: center;
  background: #c4503c; color: #fffdf8;
  border: 2px solid var(--ms-ink);
  font-size: var(--ms-small); font-weight: 900; line-height: 1;
  animation: badgePop .3s steps(3) both;
}
.hud-badge[hidden] { display: none; }
@keyframes badgePop { from { scale: .4; } to { scale: 1; } }

/*
 * Vista de mapa completo: el HUD se aparta.
 *
 * La vista existe para sacar una captura del corral entero (ver `setMapView` en
 * game/engine.js). Se va todo menos el boton del menu -que es por donde se
 * vuelve: la entrada Mapa vive dentro del menu- y el aviso de reconexion,
 * porque quedarse sin saber que el juego se ha caido no es una captura limpia.
 *
 * Se va con `opacity` y no con `display: none` para que se aparte y vuelva con
 * suavidad; `visibility` ademas lo saca del alcance del dedo mientras no esta.
 */
.game-screen .hud > *:not(.reconnect-banner) {
  transition: opacity .18s ease, visibility .18s ease;
}
.game-screen.map-view .hud > *:not(.hud-actions):not(.reconnect-banner),
.game-screen.map-view .hud-purse,
.game-screen.map-view .hud-btn:not(.hud-menu-btn) {
  opacity: 0; visibility: hidden;
}

/* Podio de la esquina */
.podium-box {
  position: absolute; right: .5rem; bottom: calc(.6rem + var(--safe-bottom));
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  padding: .5rem .55rem .35rem;
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow-sm);
  color: var(--cream);
  width: 168px;
}
.podium-box h4 { font-size: .72rem; text-transform: uppercase; letter-spacing: .06em; opacity: .8; margin: 0 0 .25rem; text-align: center; }
.podium-stage { display: flex; align-items: flex-end; justify-content: center; gap: 2px; }
.podium-slot { text-align: center; width: 52px; }
.podium-slot canvas { display: block; margin: 0 auto; }
.podium-slot .pname { font-size: .62rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.podium-slot .plvl { font-size: .6rem; color: var(--gold); font-weight: 700; }
.podium-base { border-radius: 4px 4px 0 0; margin-top: 2px; }
.podium-base.gold   { background: linear-gradient(#f4c95d, #c98a1a); height: 26px; }
.podium-base.silver { background: linear-gradient(#dfe3e8, #9aa5b1); height: 18px; }
.podium-base.bronze { background: linear-gradient(#e0a878, #a76b3a); height: 13px; }

/* ------------------------------------------------------- rueda de bailes */

.emote-dock {
  position: absolute;
  right: .5rem;
  top: 50%;
  transform: translate(120%, -50%);
  width: min(290px, 76vw);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius);
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow-md);
  color: var(--cream);
  padding: .6rem;
  opacity: 0;
  pointer-events: none;
  transition: transform .22s cubic-bezier(.2, .9, .3, 1.2), opacity .18s ease;
}
.emote-dock.open { transform: translate(0, -50%); opacity: 1; pointer-events: auto; }
.emote-dock-head { display: flex; align-items: center; margin-bottom: .5rem; font-size: .9rem; }
.emote-dock-head .btn-ghost { color: var(--cream); border-color: rgba(255,255,255,.25); }

.emote-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: .4rem;
  max-height: 46vh; overflow-y: auto; scrollbar-width: thin;
}
.emote-chip {
  display: flex; flex-direction: column; align-items: center; gap: .1rem;
  background: rgba(255, 253, 246, .1);
  border: 1.5px solid transparent;
  border-radius: var(--radius-sm);
  padding: .35rem .2rem;
  color: var(--cream);
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, transform .1s ease;
}
.emote-chip:hover { background: rgba(255, 253, 246, .2); }
.emote-chip:active { transform: scale(.94); }
.emote-chip.active { border-color: var(--gold); background: rgba(242, 177, 52, .22); }
.emote-chip.locked { opacity: .58; }
.emote-chip canvas { display: block; }
.emote-chip .emote-icon { font-size: 1.7rem; line-height: 52px; height: 52px; }
.emote-chip .ename { font-size: .62rem; line-height: 1.15; text-align: center; }
.emote-chip .eprice { font-size: .6rem; font-weight: 700; color: var(--gold); }
.emote-hint { font-size: .66rem; opacity: .7; margin-top: .45rem; text-align: center; line-height: 1.3; }

/* Boton de salto (solo tactil). Va por encima del podio para no taparlo. */
.jump-btn {
  position: absolute;
  right: calc(1.1rem + var(--safe-right));
  bottom: calc(8.4rem + var(--safe-bottom));
  width: 68px; height: 68px; border-radius: 50%;
  background: var(--glass-bg);
  border: 2px solid rgba(255,255,255,.28);
  color: var(--cream);
  font-size: 1.9rem; line-height: 1; cursor: pointer;
  backdrop-filter: var(--glass-blur);
  box-shadow: var(--shadow-md);
  /* `none`, no `manipulation`: el salto se dispara en pointerdown y aqui no
     queremos que el navegador se plantee gestos con este dedo. */
  touch-action: none;
  transition: transform .1s ease, background .15s ease;
}
.jump-btn:active { transform: scale(.9); background: rgba(36, 92, 63, .92); }

/*
 * Patada voladora. Solo existe para quien la ha comprado, asi que se permite
 * ocupar un sitio bueno: junto al salto, al alcance del pulgar derecho.
 *
 * Va a la IZQUIERDA del salto, no debajo. Antes ambos estaban en la misma
 * columna con alturas casi iguales y la patada, que se anade despues, tapaba
 * casi todo el circulo del salto: quien tenia la patada comprada practicamente
 * no podia saltar con el dedo.
 */
.kick-btn {
  position: absolute;
  right: calc(6rem + var(--safe-right));
  bottom: calc(8.6rem + var(--safe-bottom));
  width: 60px; height: 60px; border-radius: 50%;
  background: linear-gradient(160deg, rgba(190, 60, 50, .9), rgba(120, 30, 30, .92));
  border: 2px solid rgba(255, 190, 170, .4);
  color: var(--cream);
  font-size: 1.6rem; line-height: 1; cursor: pointer;
  box-shadow: var(--shadow-md);
  touch-action: none;
  transition: transform .1s ease, filter .15s ease;
}
.kick-btn:active { transform: scale(.88); filter: brightness(1.2); }
/* La bota dibujada (pixelIcons.js) en vez del emoji de la pierna: 36 px, tres
   pixeles por casilla. */
.kick-btn svg { width: 36px; height: 36px; display: block; margin: auto; }

/* Joystick movil: flotante, como el de Brawl Stars (ver JoystickInput).

   La ZONA es invisible y recibe el dedo: toda la parte de abajo a la izquierda.
   La BASE solo se ve: en reposo en su esquina y medio transparente, y al tocar
   salta debajo del dedo. No recibe toques (`pointer-events: none`), asi que
   pulsar encima de ella es pulsar la zona. */
.joy-zone {
  position: absolute;
  left: 0; bottom: 0;
  width: 50%; height: 72%;
  touch-action: none;
  -webkit-user-select: none; user-select: none;
}
.joystick {
  position: absolute;
  left: 1rem; bottom: calc(1rem + var(--safe-bottom));
  width: 128px; height: 128px;
  border-radius: 50%;
  background: rgba(16, 36, 26, .3);
  border: 2px solid rgba(255,255,255,.28);
  touch-action: none;
  pointer-events: none;
  opacity: .45;
  transition: opacity .15s ease;
}
.joystick.active { opacity: 1; }
/* Con el dedo encima el pomo va pegado a el, sin retraso. */
.joystick.active .knob { transition: none; }
.joystick .knob {
  position: absolute; left: 50%; top: 50%;
  width: 54px; height: 54px; margin: -27px 0 0 -27px;
  border-radius: 50%;
  background: rgba(246, 241, 226, .82);
  box-shadow: var(--shadow-sm);
  transition: transform .05s linear;
}

/*
 * Chat.
 *
 * Ya no hay cuadro de mensajes ni historial: lo que se escribe sale como
 * bocadillo encima de la oveja y se desvanece. Aqui solo queda la barra de
 * escribir, centrada abajo y estrecha, para dejar el corral despejado.
 */
.chat-box {
  position: absolute;
  left: 50%; transform: translateX(-50%);
  bottom: calc(.7rem + var(--safe-bottom));
  width: min(400px, 54vw);
  display: flex; flex-direction: column;
}
@keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

.chat-input { display: flex; gap: .3rem; }
.chat-input input {
  flex: 1; padding: .5rem .8rem; border-radius: 999px;
  border: 1px solid var(--glass-border);
  background: rgba(255, 253, 246, .92); outline: none;
  box-shadow: var(--shadow-sm);
}
.chat-input input:focus { background: #fffdf6; }
.chat-input button { border-radius: 999px; padding: .5rem .85rem; }
.chat-toggle-mobile { display: none; }
.chat-toggle-mobile svg { width: 24px; height: 24px; display: block; }

/* ------------------------------------------------------------------ modal */

.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(8, 18, 13, .62);
  backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
  padding-top: calc(1rem + var(--safe-top));
  padding-bottom: calc(1rem + var(--safe-bottom));
  z-index: 60;
  animation: fadeIn .15s ease;
}
.modal {
  background: var(--panel-bg);
  border-radius: 18px;
  width: min(760px, 100%);
  max-height: 100%;
  display: flex; flex-direction: column;
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.modal {
  animation: modalIn .22s cubic-bezier(.2, .9, .3, 1.15);
}
@keyframes modalIn {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to   { opacity: 1; transform: none; }
}
.modal-head {
  display: flex; align-items: center; gap: .6rem;
  padding: .85rem 1rem;
  background: linear-gradient(120deg, var(--green-600), var(--green-700));
  color: #fff;
  box-shadow: 0 2px 10px rgba(0,0,0,.18);
}
.modal-head h2 { margin: 0; flex: 1; font-size: 1.1rem; }
.modal-close {
  border: none; background: rgba(255,255,255,.18); color: #fff;
  width: 32px; height: 32px; border-radius: 50%; cursor: pointer; font-size: 1.1rem; line-height: 1;
}
.modal-body { padding: 1rem; overflow-y: auto; flex: 1; }
.modal-narrow .modal { width: min(460px, 100%); }

/* =========================================================================
   MISIONES

   Este bloque se rehizo entero el 25 de agosto de 2026. Hansel dijo que el
   panel "se ve muy de IA", y tenia razon: llevaba los seis delatores de
   .claude/skills/criterio-humano a la vez. Diez degradados, sombras
   difuminadas, el "hover levantita" (`translateY(-2px)` con la sombra
   creciendo), emoji del sistema usados de iconografia, y DIECISIETE tamanos de
   letra distintos en un solo panel.

   La regla que lo ordena todo ahora es una: **la interfaz tiene que parecer del
   mismo juego que el corral**. El corral es pixel art, clava cada pixel a los
   60 colores de `PALETTE` (public/js/game/pixel.js) y no difumina nada. Asi
   que aqui:

     - Colores PLANOS y sacados de esa paleta, no inventados. Los que se usan
       estan abajo con su nombre; ninguno es un tono suelto puesto a ojo.
     - Ni un degradado.
     - Las sombras son DURAS y desplazadas (`3px 3px 0`), como la que proyecta
       un sprite. Ninguna lleva blur.
     - Esquinas duras. El corral no tiene una sola curva de 14 pixeles.
     - CUATRO tamanos de letra, y se repiten. Estan en las variables de abajo.

   Y una nota sobre el movimiento: las tarjetas ya no se levantan al pasar por
   encima, se HUNDEN al pulsarlas (la sombra se acorta y la tarjeta se desplaza
   lo mismo que se acorta). Es el gesto de un boton fisico, cuesta lo mismo, y
   no es el efecto que sale por defecto en todo lo generado.
   ========================================================================= */

/*
 * Estos tokens vivian dentro de `.mission-panel`, y eso era un fallo silencioso.
 *
 * No los usa solo el panel de misiones: `.mission-note`, la bandeja de lecturas
 * del pastor (`.inbox-*`) y ahora el buzon los venian pidiendo desde fuera de
 * ese contenedor. Una variable CSS que no existe en el ambito no da error: la
 * propiedad entera se descarta y el navegador sigue tan tranquilo. El resultado
 * era que la bandeja del pastor se pintaba sin los bordes ni los tamanos de
 * letra que dice tener aqui, y nadie lo veia porque nada fallaba.
 *
 * Suben a `:root`. El bloque se queda EN ESTE SITIO, con su documentacion
 * encima, porque es donde se decidieron y donde hay que venir a cambiarlos.
 */
:root {
  /* --- los cuatro tamanos de letra, y no hay mas ------------------------- */
  --ms-display: 1.75rem;  /* el numero del marcador y el reloj */
  --ms-lead:    1.05rem;  /* versiculo y titulos de mision */
  --ms-body:    .875rem;  /* el texto normal */
  --ms-small:   .75rem;   /* metadatos, etiquetas y recompensas */

  /* --- colores, todos entradas exactas de PALETTE ------------------------ */
  --ms-ink:      #1a1412;  /* tinta                      */
  --ms-ink-soft: #48403a;  /* topo oscuro                */
  --ms-line:     #a89578;  /* crema oscuro: los bordes   */
  --ms-paper:    #f7f2e8;  /* crema: el fondo normal     */
  --ms-paper-2:  #e8dfc9;  /* crema hundido              */
  --ms-green:    #3d7a4f;  /* cesped                     */
  --ms-green-lt: #6bb56e;  /* cesped claro               */
  --ms-green-dk: #223e2c;  /* cesped oscuro              */
  --ms-gold:     #f2b134;  /* oro                        */
  --ms-gold-lt:  #ffd977;  /* oro claro                  */
  --ms-night:    #282242;  /* noche: solo el versiculo   */
  --ms-fire:     #c44a18;  /* fuego: solo los avisos     */
}

/* La sombra dura del panel. Un solo sitio la define para que todas las piezas
   proyecten igual — sombras desiguales es lo que hace que una pantalla parezca
   pegada de trozos. */
.mission-panel .card,
.daily-header,
.verse-card,
.pen-goal,
.pastor-note {
  border-radius: 0;
  box-shadow: 3px 3px 0 var(--ms-ink);
}

/* -------------------------------------------------------------------------
   Los componentes compartidos, puestos a tono DENTRO del panel.

   Esto hizo falta al ver la primera captura: con las tarjetas ya cuadradas y
   con sombra dura, los botones, las pestañas y las etiquetas -que vienen de
   `.btn`, `.tabs` y `.tag`, compartidos con toda la aplicacion- se quedaron
   como estaban, con degradado y esquinas de 9 pixeles. El panel se veia PEOR
   que antes de empezar: media pantalla de un estilo y media de otro.

   Se corrigen aqui y **solo bajo `.mission-panel`**, a proposito. Lo suyo
   seria arreglar los componentes en su sitio, pero eso repinta la tienda, el
   ranking, el arcade, el bano y los dos paneles de administracion de una
   tacada, y no es lo que se pidio. Cuando le toque el turno a otra pantalla,
   estas reglas se suben al componente y este bloque se queda vacio.
   ------------------------------------------------------------------------- */

.mission-panel .btn {
  border-radius: 0;
  background: var(--ms-green);
  border: 2px solid var(--ms-ink);
  color: var(--ms-paper);
  box-shadow: 3px 3px 0 var(--ms-ink);
  transition: box-shadow .12s steps(2), transform .12s steps(2);
}
.mission-panel .btn-gold { background: var(--ms-gold); color: var(--ms-ink); }
/* Se hunde, como las tarjetas. Un solo gesto para todo lo que se pulsa. */
.mission-panel .btn:active:not(:disabled) {
  transform: translate(2px, 2px);
  box-shadow: 1px 1px 0 var(--ms-ink);
}
.mission-panel .btn:disabled { box-shadow: 3px 3px 0 var(--ms-line); }

.mission-panel .tabs {
  background: transparent; padding: 0; gap: 0;
  border-bottom: 2px solid var(--ms-ink);
  border-radius: 0;
}
/*
 * Pestañas de carpeta: la elegida se pega al contenido y las demas se quedan
 * detras. Es como se han dibujado las pestañas desde antes de que existiera el
 * navegador, y dice cual esta abierta sin necesidad de encenderla de verde.
 */
.mission-panel .tabs button {
  border-radius: 0;
  border: 2px solid transparent;
  border-bottom: none;
  color: var(--ms-ink-soft);
  transition: none;
}
.mission-panel .tabs button.active {
  background: var(--ms-paper);
  border-color: var(--ms-ink);
  color: var(--ms-ink);
  box-shadow: none;
  /* Tapa la linea de abajo justo debajo de la pestaña abierta. */
  margin-bottom: -2px; padding-bottom: calc(.55rem + 2px);
}

.mission-panel .tag {
  border-radius: 0;
  border: 1px solid var(--ms-ink);
  font-size: var(--ms-small);
  background: var(--ms-paper-2); color: var(--ms-ink);
}
.mission-panel .tag-green { background: var(--ms-green-lt); color: var(--ms-ink); }
.mission-panel .tag-gold  { background: var(--ms-gold-lt); color: var(--ms-ink); }
.mission-panel .tag-red   { background: var(--ms-fire); color: var(--ms-paper); }

/* ------------------------------------------------ cabecera: cuantas van hoy */
.daily-header {
  display: flex; align-items: center; gap: .8rem;
  background: var(--ms-green-dk);
  color: var(--ms-paper);
  border: 2px solid var(--ms-ink);
  padding: .7rem .9rem;
  margin-bottom: .8rem;
}
/* Cuadrado y no un circulo: es un marcador, y los marcadores de este juego
   -el podio, la barra del corral- son todos rectos. */
.daily-count {
  display: grid; place-items: center;
  width: 52px; height: 52px; flex-shrink: 0;
  background: var(--ms-green-dk);
  border: 2px solid var(--ms-gold);
  line-height: 1;
}
.daily-count b { font-size: var(--ms-display); color: var(--ms-gold); font-variant-numeric: tabular-nums; }
.daily-count span { font-size: var(--ms-small); color: var(--ms-gold-lt); }
.daily-meta strong { display: block; font-size: var(--ms-lead); }
.daily-meta small { color: var(--ms-paper-2); font-size: var(--ms-small); }

/* ------------------------------------------------------ tarjeta de mision */
.mission-card {
  border: 2px solid var(--ms-ink);
  border-left-width: 6px;
  border-left-color: var(--ms-green);
  background: var(--ms-paper);
  transition: box-shadow .12s steps(2), transform .12s steps(2);
}
/*
 * Al pulsar, la tarjeta se HUNDE: se desplaza exactamente lo que se acorta la
 * sombra, asi que la esquina de abajo a la derecha no se mueve ni un pixel y el
 * movimiento se lee como "esto se aplasta contra la mesa". Es la alternativa
 * honesta al hover levantita, y ademas funciona con el dedo — un `:hover` en un
 * movil no existe.
 */
.mission-card:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ms-ink); }
.mission-card.done { border-left-color: var(--ms-gold); background: var(--ms-paper-2); }
.mission-card.expired { opacity: .55; }
.bonus-card { border-left-color: var(--ms-gold); background: #fff6dd; }

/*
 * El icono de la mision viene del catalogo, o sea que es CONTENIDO y se queda
 * (la regla de los emoji es contra los decorativos, no contra estos). Lo que se
 * le quita es la caja de color con esquinas redondeadas: sin ella el icono se
 * lee igual y deja de parecer el boton de una app.
 */
.mission-icon { font-size: 1.5rem; line-height: 1; flex-shrink: 0; width: 1.6em; text-align: center; }
.mission-card.done .mission-icon { opacity: .55; }

.mission-note {
  font-size: var(--ms-body); color: var(--ms-ink-soft);
  background: var(--ms-paper-2); border-left: 3px solid var(--ms-line);
  padding: .45rem .6rem; margin: .5rem 0;
}

/* La recompensa: etiquetas rectas, no pastillas. */
.reward-line {
  display: flex; gap: .4rem; flex-wrap: wrap;
  font-size: var(--ms-small); font-weight: 700; color: var(--ms-ink);
}
.reward-line > span:not(.tag) {
  background: var(--ms-gold-lt);
  border: 1px solid var(--ms-ink);
  padding: .1rem .45rem;
}

/* ------------------------------------------------- el pastor te contesto

   La tarjeta que le sale a la OVEJA cuando su pastor leyo lo que escribio.

   Es verde y no dorada aunque venga con premio, y es deliberado: el dorado del
   juego significa "has cobrado algo", y lo que aqui importa no es el cobro sino
   que alguien al otro lado te leyo. El premio va en la linea pequena de abajo.
   Si esto fuera dorado, seria una notificacion de pago mas. */
.pastor-note {
  display: flex; gap: .6rem; align-items: flex-start;
  background: #eaf3e6;
  border: 2px solid var(--ms-green);
  padding: .6rem .7rem; margin: .55rem 0;
}
/* Cuando ademas trajo premio, el canto se pone dorado. Es un canto y no el
   fondo entero a proposito: lo que importa de esta tarjeta es que alguien te
   leyo, no lo que te dieron (ver el comentario de arriba). */
.pastor-note.rewarded { border-left: 6px solid var(--ms-gold); }
/* Y cuando la respuesta no valio y le retiraron lo cobrado: la misma tarjeta,
   en el mismo sitio, con el fondo y el canto del aviso. Sigue siendo "tu pastor
   te contesto" -ver el comentario de `shepherdCard`- solo que esta vez la
   respuesta fue que no. Una tarjeta distinta en otro sitio la convertiria en un
   castigo anonimo. */
.pastor-note.taken { background: #f7e4da; border-color: var(--ms-fire); border-left: 6px solid var(--ms-fire); }
.pastor-note.taken strong { color: var(--ms-fire); }
.pastor-note strong { display: block; font-size: var(--ms-body); color: var(--ms-green-dk); }
.pastor-note small { font-size: var(--ms-small); color: var(--ms-ink-soft); }
.pn-icon { font-size: 1.25rem; line-height: 1.1; flex-shrink: 0; }
.pn-text {
  margin: .25rem 0; font-size: var(--ms-body);
  color: var(--ms-ink); line-height: 1.45; white-space: pre-wrap;
}

/* El aviso de plazo de una tarea del pastor. Solo sale cuando quedan menos de
   dos dias, asi que puede permitirse ser llamativo: cuando aparece, importa. */
.due-note {
  font-size: var(--ms-small); font-weight: 800;
  color: var(--ms-paper); background: var(--ms-fire);
  border: 1px solid var(--ms-ink);
  padding: .25rem .5rem; margin-top: .45rem; display: inline-block;
}
.due-note.closed { background: var(--ms-ink-soft); }

/* El reloj de las misiones de tiempo. El numero es la pieza mas grande del
   panel porque es lo unico que hay que mirar mientras corre. */
.timer-ring { display: flex; align-items: center; justify-content: center; gap: .8rem; margin: .6rem 0; }
.timer-value {
  font-size: var(--ms-display); font-weight: 800;
  font-variant-numeric: tabular-nums; color: var(--ms-green-dk);
}
.timer-track {
  height: 10px; flex: 1; overflow: hidden;
  background: var(--ms-paper-2); border: 1px solid var(--ms-ink);
}
/*
 * `steps(N)` y no un avance continuo: una barra que se desliza suave es de otro
 * juego. Esta avanza a saltos, como una barra de carga de 16 bits, y ademas es
 * mas honesta — el progreso se cuenta en segundos enteros.
 */
.timer-track i { display: block; height: 100%; background: var(--ms-green-lt); transition: width 1s steps(8); }

/* Las casillas del dia: una por mision, se encienden al cobrarlas. */
.progress-strip { display: flex; gap: .25rem; margin-bottom: .8rem; }
.progress-strip i {
  flex: 1; height: 8px;
  background: var(--ms-paper-2); border: 1px solid var(--ms-ink);
}
.progress-strip i.on { background: var(--ms-gold); }

/* ------------------------------------------------ versiculo del dia

   Es la unica tarjeta del juego que no pide nada: solo se lee. Por eso es la
   unica con fondo oscuro. En un panel entero de tarjetas color crema, invertir
   el contraste es lo que hace que la vista vaya AHI primero, sin necesidad de
   ponerla mas grande ni de gritar con un borde de colores.

   El azul noche no es decoracion: es el color que en el resto del juego solo
   sale de noche, y da la sensacion de calma que corresponde a un momento de
   lectura. Encima, el degradado dorado del borde superior lo ata al oro de las
   recompensas: se lee como "esto tambien vale". */
.verse-card {
  position: relative;
  background: var(--ms-night);
  color: var(--ms-paper);
  border: 2px solid var(--ms-ink);
  padding: 1rem 1.05rem;
  margin-bottom: .9rem;
}
/*
 * La banda dorada de arriba. Era un degradado de tres colores y ahora es una
 * franja plana: a lo que sirve es a atar esta tarjeta al oro de las
 * recompensas, y para eso el color tiene que ser EL oro, no una transicion que
 * pasa cerca de el.
 */
.verse-card::before {
  content: '';
  position: absolute; inset: 0 0 auto 0; height: 4px;
  background: var(--ms-gold);
}
.verse-head { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .55rem; }
.verse-tag {
  font-size: var(--ms-small); font-weight: 800;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--ms-gold-lt);
}
.verse-theme {
  margin-left: auto;
  font-size: var(--ms-small); font-weight: 700;
  padding: .1rem .45rem;
  background: var(--ms-gold-lt); color: var(--ms-ink);
}
.verse-text {
  margin: 0 0 .45rem; padding: 0;
  font-size: var(--ms-lead); line-height: 1.55; font-weight: 500;
}
.verse-ref {
  display: block; font-style: normal; font-weight: 800;
  font-size: var(--ms-body); color: var(--ms-gold-lt); margin-bottom: .8rem;
}
/*
 * El reto del dia, dentro de la tarjeta oscura. El canto dorado a la izquierda
 * hace todo el trabajo de separarlo del versiculo: no hace falta ni caja ni
 * fondo distinto, que es lo que antes lo dejaba flotando en un gris a medias.
 */
.verse-challenge {
  border-left: 4px solid var(--ms-gold);
  padding: .1rem 0 .1rem .7rem;
}
.verse-challenge strong {
  display: block; font-size: var(--ms-small); letter-spacing: .06em;
  text-transform: uppercase; color: var(--ms-gold-lt); margin-bottom: .15rem;
}
.verse-challenge span { font-size: var(--ms-body); line-height: 1.45; }

/* El versiculo repetido dentro de su mision, mientras se escribe la respuesta. */
.mission-verse {
  background: var(--ms-paper-2); border-left: 4px solid var(--ms-green);
  padding: .5rem .65rem; margin: .5rem 0;
  font-size: var(--ms-body); line-height: 1.45; color: var(--ms-ink);
}
.mission-verse cite {
  display: block; margin-top: .25rem;
  font-style: normal; font-weight: 800; font-size: var(--ms-small); color: var(--ms-green-dk);
}

/* ------------------------------------------------------ meta del corral

   Una sola barra para todo el grupo. Se pinta verde mientras se sube y dorada
   al completarse, que es el mismo idioma de color que usan las recompensas en
   el resto del juego: verde = en marcha, oro = cobrado. */
/* -------------------------------------------------------------------------
   LA MISION DEL CORRAL: 20 libros de la Biblia

   Es la unica tarjeta del panel que no es de una persona, y por eso es la
   unica que se sale del molde: canto grueso a la izquierda en vez de arriba,
   y una barra de VEINTE CASILLAS en lugar de una linea que se rellena.

   Las casillas no son un capricho retro. Una barra lisa al 65 % no se puede
   repetir en voz alta; trece casillas de veinte se cuentan de un vistazo y se
   dicen solas — "nos faltan siete" —, que es exactamente lo que tiene que
   pasar para que una meta de grupo funcione.
   ------------------------------------------------------------------------- */

.bible-goal {
  background: #eaf3e6;
  border: 2px solid var(--ms-ink);
  border-left: 6px solid var(--ms-green);
  box-shadow: 3px 3px 0 var(--ms-ink);
  padding: .8rem .85rem;
  margin-bottom: .9rem;
}
/* Mismo idioma de color que la meta semanal: verde en marcha, oro conseguido. */
.bible-goal.ready { border-left-color: var(--ms-gold); background: #fff6dd; }
.bible-goal.done { border-left-color: var(--ms-gold); }

.bg-head { display: flex; align-items: baseline; gap: .55rem; margin-bottom: .6rem; }
/* Color explicito y no heredado: `.mission-panel` solo define variables, asi
   que el texto lo pinta quien envuelva al panel. Dentro del modal se hereda
   bien, pero en cuanto la tarjeta se saca a otro sitio -una captura, por
   ejemplo- sale crema sobre crema y no se ve. Lo mismo que ya paso con el
   `small` global en la Biblia: si el color importa, se dice. */
.bg-head strong { display: block; font-size: var(--ms-lead); color: var(--ms-ink); }
.bg-head small { color: var(--ms-ink-soft); font-size: var(--ms-small); }
.bg-count {
  margin-left: auto; font-weight: 800; font-variant-numeric: tabular-nums;
  color: var(--ms-green-dk); font-size: var(--ms-lead); white-space: nowrap;
}
.bible-goal.ready .bg-count, .bible-goal.done .bg-count { color: var(--ms-ink); }

/*
 * Las veinte casillas.
 *
 * `grid` con `1fr` por casilla y no `flex`, para que las veinte midan
 * exactamente lo mismo y la fila acabe donde acaba la tarjeta: con anchos
 * calculados a mano, en un movil estrecho la ultima se sale o queda coja.
 */
.bg-notches {
  display: grid;
  grid-template-columns: repeat(20, 1fr);
  gap: 2px;
  height: 18px;
  padding: 2px;
  background: var(--ms-paper-2, #e8dfc9);
  border: 2px solid var(--ms-ink);
}
.bg-notches i {
  background: rgba(0, 0, 0, .07);
  /* Se ENCIENDE a saltos, no con un fundido: una casilla esta puesta o no
     esta, y un fundido la dejaria un rato a medias diciendo una mentira. */
  transition: background .12s steps(2);
}
.bg-notches i.on { background: var(--ms-green); }
.bible-goal.ready .bg-notches i.on,
.bible-goal.done .bg-notches i.on { background: var(--ms-gold); }

/* Color explicito: si no, gana el "small, .muted" global y se apaga. */
.bg-prize { margin: .55rem 0 0; font-size: var(--ms-small); color: var(--ms-ink); }
.bible-goal.ready .bg-prize { font-weight: 700; }

@media (max-width: 420px) {
  /* En un movil estrecho, veinte casillas de dos pixeles no se distinguen:
     se parten en dos filas de diez, que ademas se cuentan mejor. */
  .bg-notches { grid-template-columns: repeat(10, 1fr); height: 34px; }
}

.pen-goal {
  background: #eaf3e6;
  border: 2px solid var(--ms-ink);
  border-top: 6px solid var(--ms-green);
  padding: .8rem .85rem; margin-bottom: .9rem;
}
/* Al completarse, lo que cambia es el canto: verde = en marcha, oro = cobrado.
   Es el mismo idioma de color que el resto del juego, dicho con una franja en
   vez de con un fondo entero de otro color. */
.pen-goal.ready { border-top-color: var(--ms-gold); background: #fff6dd; }
.pen-goal.done { border-top-color: var(--ms-gold); opacity: .8; }
.pg-head { display: flex; align-items: baseline; gap: .55rem; margin-bottom: .55rem; }
.pg-head strong { display: block; font-size: var(--ms-lead); }
.pg-head small { color: var(--ms-ink-soft); font-size: var(--ms-small); }
.pg-count {
  margin-left: auto; font-weight: 800; font-variant-numeric: tabular-nums;
  color: var(--ms-green-dk); font-size: var(--ms-lead); white-space: nowrap;
}
.pg-bar {
  height: 12px; overflow: hidden;
  background: var(--ms-paper-2); border: 1px solid var(--ms-ink);
}
/*
 * Sube a saltos, como el reloj. Y con `steps` el movimiento sigue siendo suave
 * de ver -tarda casi medio segundo- sin ser el deslizamiento con curva de
 * aceleracion que lleva cualquier barra de progreso generada.
 */
.pg-bar i {
  display: block; height: 100%;
  background: var(--ms-green-lt);
  transition: width .45s steps(6);
}
.pen-goal.ready .pg-bar i, .pen-goal.done .pg-bar i { background: var(--ms-gold); }
.pg-top { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .55rem; }
.pg-person {
  font-size: var(--ms-small); font-weight: 700; color: var(--ms-ink);
  background: var(--ms-paper); border: 1px solid var(--ms-line);
  padding: .1rem .45rem;
}

/* ------------------------------------------------------------- insignias

   Las bloqueadas se ven en gris y con su barra: una insignia escondida no
   motiva, y una que dice "22 de 25" casi obliga a terminarla. Por eso el gris
   no las esconde del todo, solo las apaga. */
.badge-summary {
  display: flex; align-items: center; gap: .8rem;
  background: var(--grad-green); color: #fff;
  border-radius: var(--radius); padding: .75rem .9rem; margin-bottom: .9rem;
}
.bs-count {
  min-width: 62px; text-align: center;
  background: rgba(0, 0, 0, .18); border-radius: 12px; padding: .35rem .5rem;
}
.bs-count b { font-size: 1.5rem; color: var(--gold); }
.bs-count span { font-size: .68rem; opacity: .8; }
.bs-meta { flex: 1; min-width: 0; }
.bs-meta strong { display: block; font-size: 1rem; }
.bs-meta small { color: rgba(246, 241, 226, .78); font-size: .78rem; }
.bs-bar {
  height: 8px; border-radius: 99px; background: rgba(0, 0, 0, .25);
  overflow: hidden; margin: .35rem 0 .3rem;
}
.bs-bar i { display: block; height: 100%; background: var(--grad-gold); border-radius: 99px; }

.badge-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(146px, 1fr)); gap: .6rem; }
.badge-card {
  background: linear-gradient(170deg, #fffdf7, #f4efe1);
  border: 2px solid #e2d9c1; border-radius: var(--radius);
  padding: .65rem .55rem; text-align: center;
  display: flex; flex-direction: column; gap: .28rem;
  transition: transform .15s ease, box-shadow .15s ease;
}
.badge-card:hover { transform: translateY(-3px); box-shadow: 0 8px 20px rgba(0,0,0,.12); }
.badge-medal {
  width: 54px; height: 54px; margin: 0 auto .15rem;
  display: grid; place-items: center; border-radius: 50%;
  font-size: 1.7rem;
  background: #ece7d8; border: 2px dashed #cfc5a9;
  filter: grayscale(1); opacity: .5;
}
.badge-card.earned {
  border-color: var(--gold);
  background: linear-gradient(170deg, #fffaef, #fdf0d2);
  box-shadow: 0 4px 14px -6px rgba(242, 177, 52, .8);
}
.badge-card.earned .badge-medal {
  filter: none; opacity: 1;
  border: 2px solid rgba(255, 255, 255, .8);
  background: var(--grad-gold);
  box-shadow: 0 3px 12px -3px var(--gold-dark), inset 0 -3px 6px rgba(0,0,0,.12);
}
.badge-name { font-weight: 800; font-size: .84rem; line-height: 1.2; }
.badge-desc { font-size: .72rem; color: var(--ink-soft); line-height: 1.32; flex: 1; }
.badge-done { font-size: .74rem; font-weight: 800; color: var(--green-500); }
.badge-progress small { font-size: .68rem; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.bp-bar { height: 6px; border-radius: 99px; background: #ddd4bc; overflow: hidden; margin-bottom: .15rem; }
.bp-bar i { display: block; height: 100%; background: var(--green-400); border-radius: 99px; }
.badge-reward { font-size: .72rem; font-weight: 800; color: var(--gold-dark); }

/* ------------------------------------------------------- ayudas (tienda)

   Se pintan en fila y sin oveja de muestra, al reves que la ropa: son lo unico
   que se GASTA, y confundirlas con una prenda seria la peor compra posible
   para quien ahorro dos semanas. */
.boost-list { display: flex; flex-direction: column; gap: .55rem; }
.boost-card {
  display: flex; align-items: center; gap: .75rem;
  background: #fffdf8;
  border: 2px solid #a89578; border-radius: 0;
  box-shadow: 3px 3px 0 rgba(58, 44, 34, .18);
  padding: .7rem .8rem;
}
.boost-card.full { border-color: #3d7a4f; background: #f7f2e8; }
.boost-card.locked { opacity: .55; }
/*
 * El icono del objeto va enmarcado en su hueco.
 *
 * Estos emoji SI se quedan: son la cara del objeto en el catalogo, no adorno de
 * la interfaz. Pero sueltos sobre el fondo parecian pegados; dentro de un marco
 * de la paleta se leen como la ilustracion de la ficha, que es lo que son.
 */
.boost-icon {
  font-size: 1.5rem; line-height: 1;
  width: 44px; height: 44px; flex-shrink: 0;
  display: grid; place-items: center;
  background: #e8dfc9; border: 2px solid #a89578;
}
.boost-body { flex: 1; min-width: 0; }
.boost-name { display: flex; align-items: center; gap: .4rem; }
.boost-name strong { font-size: .95rem; }
.boost-have {
  font-size: .72rem; font-weight: 800; color: #2f5aa8;
  background: rgba(59, 130, 246, .14); border-radius: 999px; padding: .05rem .45rem;
}
.boost-body p { margin: .2rem 0 .15rem; font-size: .84rem; line-height: 1.4; }
.boost-body small { color: var(--ink-soft); font-size: .74rem; }
.boost-action { flex-shrink: 0; }
@media (max-width: 520px) {
  .boost-card { flex-wrap: wrap; }
  .boost-action { width: 100%; }
  .boost-action .btn { width: 100%; }
}

/* ------------------------------------------------- panel del pastor

   LOS ESCALONES DE RECOMPENSA

   Tres botones y no un desplegable, y esa es toda la decision de diseno de este
   bloque: el pastor esta eligiendo CUANTO vale una tarea, asi que las tres
   opciones tienen que estar delante con su precio puesto para poder compararlas
   de un vistazo. Un desplegable esconde dos de las tres y convierte una
   comparacion en dos clics.

   No hay ninguna caja donde escribir un numero, ni la habra: la lista sale del
   servidor (ver server/domain/missionRewards.js). */
.tier-picker { display: flex; gap: .45rem; margin: .35rem 0 .2rem; }
.tier-btn {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: center; gap: .12rem;
  padding: .5rem .3rem; border-radius: var(--radius);
  background: #fffdf7; border: 2px solid #e2d9c1;
  font-family: inherit; color: var(--ink); cursor: pointer;
  transition: transform .12s ease, border-color .12s ease, background .12s ease;
}
.tier-btn:hover { transform: translateY(-1px); border-color: #cdbf9c; }
.tier-btn strong { font-size: .82rem; }
.tier-icon { font-size: 1.25rem; line-height: 1; }
.tier-pay {
  font-size: .7rem; font-weight: 800; color: var(--gold-dark);
  white-space: nowrap;
}
/* El elegido se ve elegido desde la otra punta de la mesa: en un movil, un
   borde un poco mas oscuro no lo distingue nadie. */
.tier-btn.on {
  background: linear-gradient(150deg, #fff6de, #fbeccb);
  border-color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold);
}

/* LA BANDEJA DE LECTURAS

   El texto de la oveja va grande y entero; los botones, debajo y pequenos.
   Ver el comentario de `dailyView` en shepherdPanel.js: esta pantalla es para
   LEER, y si se pareciera a una bandeja de correo se convertiria en una lista
   de cosas que despachar. */
.inbox-head { margin-bottom: .6rem; }
.inbox-head strong { display: block; font-size: 1rem; color: var(--green-600); }
.inbox-head small { font-size: .76rem; color: var(--ink-soft); }
.inbox-divider {
  margin: 1.1rem 0 .5rem; font-size: .82rem; color: var(--ink-soft);
  text-transform: uppercase; letter-spacing: .06em;
}
.inbox-card.done { opacity: .72; }
.inbox-answers { margin: .55rem 0 .2rem; display: flex; flex-direction: column; gap: .5rem; }
.inbox-answer {
  background: #fbf8ee; border-left: 3px solid var(--green-400);
  border-radius: 0 10px 10px 0; padding: .45rem .65rem;
}
.ia-label {
  display: block; font-size: .7rem; font-weight: 800;
  text-transform: uppercase; letter-spacing: .05em; color: var(--ink-soft);
}
.inbox-answer p { margin: .2rem 0 0; font-size: .92rem; line-height: 1.5; }
.inbox-actions { margin-top: .6rem; display: flex; flex-direction: column; gap: .45rem; }
.inbox-note {
  width: 100%; padding: .55rem .7rem; font-family: inherit; font-size: .86rem;
  border: 1.5px solid #d8cfb6; border-radius: 9px; background: #fffdf7;
}
@media (max-width: 460px) {
  .tier-picker { flex-wrap: wrap; }
  .tier-btn { flex: 1 1 30%; }
}

/* ---------------------------------------------- retirar una recompensa

   El pie de cada entrega de la bandeja.

   No es un boton, y eso es lo importante: es texto subrayado, sin fondo, sin
   borde y separado por una linea del resto de la tarjeta. Quitarle progreso a
   alguien es la unica accion del juego que RESTA, y no puede tener el mismo
   peso visual que "aceptar y recompensar". Solo se pone rojo al pasar por
   encima, cuando ya has decidido ir a por el. */
.inbox-revoke {
  margin-top: .6rem; padding-top: .5rem;
  border-top: 1px solid var(--ms-line);
  text-align: right;
}
.link-danger {
  background: none; border: 0; padding: 0;
  font: inherit; font-size: var(--ms-small); font-weight: 700;
  color: var(--ink-soft); text-decoration: underline; text-underline-offset: 3px;
  cursor: pointer;
}
.link-danger:hover { color: var(--danger-dark); }

/* La entrega ya revocada. El canto rojo a la izquierda dice lo que paso sin
   tener que repintar la tarjeta entera de un color de alarma: lo que hay
   dentro sigue siendo un texto que una adolescente escribio. */
.inbox-card.revoked { border-left: 6px solid var(--ms-fire); opacity: 1; }
.inbox-reason {
  font-size: var(--ms-body); color: var(--ms-ink);
  background: #f7e4da; border-left: 3px solid var(--ms-fire);
  padding: .45rem .6rem; margin: .5rem 0;
}

/* El nombre de un admin, que abre su ficha. Un nombre que se pulsa se subraya:
   es lo unico que ya sabe leer todo el mundo sin que se lo expliquen. */
.link-open {
  background: none; border: 0; padding: 0;
  font: inherit; font-weight: 800; color: var(--green-600);
  text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}
.link-open:hover { color: var(--green-500); }

/* --------------------------------------------- la ficha de un administrador

   Un arbol: el admin arriba, cada pastor debajo, y dentro de cada pastor sus
   corrales con sus ovejas. La jerarquia se ve por SANGRIA Y LINEA VERTICAL, no
   por tarjetas anidadas: tres cajas metidas una dentro de otra dejan el
   contenido en un pasillo de cuatro dedos de ancho en un movil. */
.admin-branch { margin: 1rem 0 .4rem; }
.branch-title {
  display: flex; align-items: center; gap: .5rem;
  margin: 0 0 .5rem; font-size: 1rem; color: var(--green-600);
}
.pen-block {
  margin: .6rem 0 .6rem .5rem; padding-left: .8rem;
  border-left: 3px solid var(--cream-2);
}
.pen-block-head {
  display: flex; align-items: center; gap: .45rem; flex-wrap: wrap;
  margin-bottom: .4rem; font-size: .9rem;
}
/* La contrasena revelada, en la misma pastilla que los codigos del juego: si
   se lee igual que un codigo de corral, se copia igual de bien. */
.pw-pill { font-size: .8rem; }

/* ------------------------------------------------------------- EL BUZON

   Las cartas salen ABIERTAS y enteras, no como una lista de asuntos. El porque
   esta en ui/mailPanel.js: un buzon de este juego tiene cuatro cartas, y la
   que importa es justo la que explica algo que te ha pasado. */
.mail-intro { margin-bottom: .7rem; }
.mail-intro strong { display: block; font-size: 1rem; color: var(--green-600); }
.mail-intro small { font-size: var(--ms-small); color: var(--ink-soft); }

.mail-card {
  background: #fffdf7;
  border: 2px solid var(--ms-line);
  /* Canto verde: una carta del corral. La roja lo cambia mas abajo. */
  border-left: 6px solid var(--ms-green);
  box-shadow: 3px 3px 0 rgba(26, 20, 18, .16);
  padding: .7rem .8rem;
  margin-bottom: .8rem;
}
/* Sin abrir: el canto superior dorado. Es el unico adorno, y desaparece en
   cuanto se lee, que es lo que tiene que hacer un aviso. */
.mail-card.fresh { border-top: 4px solid var(--ms-gold); }
.mail-card.taken { border-left-color: var(--ms-fire); }

.mail-head {
  display: flex; align-items: baseline; gap: .5rem;
  margin-bottom: .15rem;
}
.mail-head strong { flex: 1; font-size: 1rem; color: var(--ms-green-dk); }
.mail-card.taken .mail-head strong { color: var(--ms-fire); }
.mail-when { font-size: var(--ms-small); color: var(--ink-soft); white-space: nowrap; }
.mail-from { font-size: var(--ms-small); color: var(--ink-soft); margin-bottom: .5rem; }

/* Lo que se quito, antes del motivo: "retirar la recompensa" no dice nada y
   "-26 XP" si. Los dos numeros en una linea y nada mas en ella. */
.mail-taken {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  background: #f7e4da; border: 1px solid var(--ms-fire);
  padding: .35rem .55rem; margin-bottom: .5rem;
  font-size: var(--ms-small);
}
.mail-taken span { flex: 1; color: var(--ms-ink-soft); }
.mail-taken b { color: var(--ms-fire); font-size: var(--ms-body); }

.mail-body { margin: 0; font-size: var(--ms-body); line-height: 1.55; color: var(--ms-ink); }
.mail-foot { display: block; margin-top: .5rem; font-size: var(--ms-small); color: var(--ink-soft); }

/* El punto de cartas sin abrir vive ahora en el boton del buzon del HUD
   (`.hud-badge`): el buzon es lo unico que se quedo fuera del menu. */

/* ------------------------------------------------- el bano de casa

   El BANO GRANDE arriba y las barras debajo, no al reves. Es lo que hace que
   esto se sienta como cuidar a un bicho y no como rellenar un formulario: se
   abre el panel, te mira una oveja embarrada esperando el jabon, y solo despues
   se lee por que.

   Los dos medidores comparten estilos y se distinguen por su tramo (la clase
   `care-<tramo>`, que sale del servidor), asi que el color de la barra y el
   texto que hay al lado no pueden discrepar nunca. */

.bath-scene { margin-bottom: .6rem; }
.bath-canvas {
  display: block; width: 100%; height: auto;
  aspect-ratio: 560 / 300;
  border: 2px solid #b9c8ce; border-radius: var(--radius);
  background: #dde5e9;
  cursor: grab;
  /* Sin esto, arrastrar el dedo por la oveja hace scroll del panel en vez de
     enjabonarla — o sea que en el movil, que es donde se juega, el bano no
     funcionaria en absoluto. */
  touch-action: none;
  -webkit-user-select: none; user-select: none;
}
.bath-canvas:active { cursor: grabbing; }

.bath-status { margin-bottom: .7rem; }
.bath-hint {
  margin: 0 0 .45rem; text-align: center;
  font-size: .85rem; font-weight: 700; line-height: 1.35;
  color: var(--ink-soft);
}
.bath-hint.good { color: var(--green-700); }
.bath-hint.empty { color: var(--danger-dark); }

/* La barra de espuma. Solo sale mientras se enjabona: una barra llena parada en
   pantalla despues de aclarar no dice nada y encima confunde con las de abajo. */
.bath-lather {
  height: 10px; border-radius: 99px; background: #cfe3ec;
  overflow: hidden; margin: 0 auto .55rem; max-width: 320px;
}
.bath-lather i {
  display: block; height: 100%; border-radius: 99px;
  background: linear-gradient(90deg, #b0e2f5, #fffdf8);
  transition: width .12s linear;
}

.bath-tools { display: flex; gap: .6rem; justify-content: center; }
.bath-tool {
  display: flex; align-items: center; gap: .45rem;
  padding: .5rem .9rem; border-radius: 999px;
  border: 2px solid #cbd8de; background: #fffdf7;
  font-family: inherit; font-size: .85rem; font-weight: 800; color: var(--ink);
  cursor: pointer;
}
.bath-tool-icon { font-size: 1.25rem; line-height: 1; }
/* El que llevas en la mano se hunde. Es lo unico que distingue "elegido" de
   "disponible", y sin ello se acaba frotando con la ducha creyendo que es el
   jabon. */
.bath-tool.holding {
  border-color: var(--green-500);
  background: linear-gradient(160deg, #dff3fb, #b0e2f5);
  box-shadow: inset 0 2px 6px rgba(20, 60, 80, .18);
}
.bath-tool[disabled] { opacity: .45; cursor: not-allowed; }

.care-meters { display: flex; flex-direction: column; gap: .55rem; }
.care-meter {
  background: linear-gradient(120deg, #fffdf7, #f7f1e1);
  border: 2px solid #e2d9c1; border-radius: var(--radius);
  padding: .5rem .65rem;
}
.care-meter-head { display: flex; align-items: center; gap: .4rem; }
.care-meter-head strong { font-size: .92rem; flex: 1; }
.care-icon { font-size: 1.15rem; line-height: 1; }
.care-stage { font-size: .74rem; font-weight: 800; color: var(--ink-soft); }
.care-bar {
  height: 12px; border-radius: 99px; background: #ddd4bc;
  overflow: hidden; margin: .3rem 0 .2rem;
}
.care-bar i {
  display: block; height: 100%; border-radius: 99px;
  background: var(--green-400); transition: width .25s ease;
}
.care-meter small { font-size: .74rem; color: var(--ink-soft); }

/* Los tramos malos se ven de lejos: el color es lo primero que se lee. */
.care-dusty .care-bar i, .care-peckish .care-bar i { background: var(--gold); }
.care-dirty .care-bar i, .care-hungry .care-bar i { background: var(--mango); }
.care-filthy .care-bar i, .care-starving .care-bar i { background: var(--danger); }
.care-filthy, .care-starving { border-color: #e8b3aa; }
.care-filthy .care-stage, .care-starving .care-stage { color: var(--danger-dark); }

.care-actions { display: flex; gap: .6rem; margin-top: .7rem; }
.care-action { flex: 1; text-align: center; }
.care-btn { width: 100%; }
.care-action small { display: block; margin-top: .3rem; font-size: .72rem; color: var(--ink-soft); }
.care-action small.care-empty { color: var(--danger-dark); font-weight: 700; }
.care-note {
  margin: .8rem 0 0; font-size: .78rem; line-height: 1.4;
  color: var(--ink-soft); text-align: center;
}

/* El boton flotante que sale al acercarse a la caseta.

   Centrado abajo, entre el joystick y el salto: es el hueco que queda libre con
   las dos manos puestas. Entra con un rebotito, que es lo que hace que se note
   que ha APARECIDO — un boton que se materializa sin mas parece que estuvo
   siempre y no invita a pulsarlo.

   Y POR ENCIMA de la barra de escribir, que esta centrada abajo exactamente en
   el mismo sitio (ver `.chat-box`): a la misma altura se tapan el uno al otro
   justo cuando la gente coincide en la caseta, que es cuando mas se habla. */

/* El boton de cruzar una puerta.

   Mismo sitio y mismo gesto que el de la caseta -son la misma idea: "estas al
   lado de algo, puedes usarlo"- pero en madera en vez de en azul agua, para que
   se distingan de un vistazo cuando alguien tiene las dos cosas cerca. */

/* El mismo boton, cuando lo que hay delante es un solar sin dueno: ahi no se
   entra, se compra. Va dorado porque cuesta monedas, y eso tiene que verse
   ANTES de pulsar — es lo unico del mapa que gasta dinero. */

/* El cerrojo, arriba a la izquierda del todo: no es una accion del momento como
   las de abajo, es un interruptor del cuarto, y mezclarlo con los botones del
   pulgar haria que se pulsara sin querer.

   Cuando no se puede cerrar NO se esconde: se apaga y lo dice. Un boton que
   desaparece deja al jugador preguntandose si existio; uno apagado que pone
   "no puedes cerrar con visita" explica la regla sin ningun tutorial. */

/* --------------------------------------------------------------- tienda

   LA TIENDA TIENE QUE PARECER DEL MISMO JUEGO QUE EL CORRAL

   El corral es pixel art: `pixel.js` clava cada pixel a uno de los 60 colores
   de `PALETTE`, sin medias tintas. Esta ventana llevaba degradados, sombras
   difuminadas y pasteles de libreria — o sea, hacia lo contrario que el juego
   que la rodea, y ese choque es lo que se leia como interfaz prestada.

   Aqui todo es plano y de la paleta:

     - CERO `linear-gradient`. Color plano y ya.
     - Sombra DURA y desplazada (`3px 3px 0`), nunca difuminada. El pixel art
       no difumina; una sombra con blur delata el origen al instante.
     - Esquinas a escuadra (`border-radius: 0`), como los pixeles.
     - CUATRO tamanos de letra en toda la ventana, definidos abajo y
       reutilizados. Antes habia ocho, que es lo que sale cuando cada trozo se
       decide por separado.

   Todo cuelga de `.shop` (la clase la pone `shopPanel.js` sobre el cuerpo de
   la ventana) para no arrastrar al resto de la aplicacion, que sigue con su
   estilo. El dia que se quiera migrar otra pantalla, se copia el bloque.
   -------------------------------------------------------------------------- */

.shop {
  /* Todos de PALETTE. Si hace falta uno nuevo, sale de alli o no entra. */
  --sh-ink:      #3a2c22;  /* tinta, para bordes y texto fuerte */
  --sh-ink-soft: #6e645c;  /* gris calido, para texto secundario */
  --sh-line:     #a89578;  /* crema oscuro, el borde de reposo */
  --sh-paper:    #fffdf8;  /* la ficha */
  --sh-paper-2:  #f7f2e8;  /* fichas apagadas y bloques de fondo */
  --sh-sunk:     #e8dfc9;  /* huecos y marcos de icono */
  --sh-green:    #3d7a4f;
  --sh-green-lt: #4f9a5e;
  --sh-gold:     #f2b134;
  --sh-gold-dk:  #9c6437;

  /* La sombra dura, en un solo sitio. */
  --sh-drop:     3px 3px 0 rgba(58, 44, 34, .18);
  --sh-drop-up:  5px 5px 0 rgba(58, 44, 34, .24);

  /* Cuatro tamanos. Ni uno mas. */
  --sh-fs-head: 1rem;
  --sh-fs-name: .84rem;
  --sh-fs-meta: .74rem;
  --sh-fs-tiny: .64rem;
}

.shop small { font-size: var(--sh-fs-meta); color: var(--sh-ink-soft); }

/* --- botones dentro de la tienda ----------------------------------------- */

/*
 * Se pisan los de fuera a proposito: los generales llevan degradado y sombra
 * con blur, y aqui no pega ninguno de los dos.
 *
 * El hundido al pulsar (`translate(2px,2px)` con la sombra encogiendo a la vez)
 * es la unica animacion de la ventana, y esta porque hace falta: es la
 * confirmacion de que el dedo dio donde queria. El "hover levantita" que habia
 * antes no confirmaba nada.
 */
.shop .btn {
  border: 2px solid var(--sh-ink);
  border-radius: 0;
  background: var(--sh-green);
  color: var(--sh-paper);
  box-shadow: var(--sh-drop);
  transition: box-shadow .12s ease, transform .12s ease, background-color .12s ease;
}
.shop .btn:hover:not(:disabled) {
  filter: none; transform: none;
  background: var(--sh-green-lt);
  box-shadow: var(--sh-drop-up);
}
.shop .btn:active:not(:disabled) {
  transform: translate(2px, 2px);
  box-shadow: 1px 1px 0 rgba(58, 44, 34, .18);
}
.shop .btn:disabled { opacity: .4; filter: none; box-shadow: none; }

.shop .btn-gold { background: var(--sh-gold); color: var(--sh-ink); }
.shop .btn-gold:hover:not(:disabled) { background: #ffd977; }

.shop .btn-ghost { background: var(--sh-paper); color: var(--sh-ink); border-color: var(--sh-line); }
.shop .btn-ghost:hover:not(:disabled) { background: var(--sh-paper-2); border-color: var(--sh-ink); color: var(--sh-ink); }

/* --- etiquetas ----------------------------------------------------------- */

/*
 * Las `.tag` generales son pasteles de libreria (#dbeafe, #ede9fe...) y pildoras
 * de 999px. Aqui se reescriben con la paleta y a escuadra.
 */
.shop .tag {
  border-radius: 0;
  font-size: var(--sh-fs-tiny);
  letter-spacing: .03em;
  background: var(--sh-sunk);
  color: var(--sh-ink-soft);
  border: 2px solid var(--sh-line);
  padding: .1rem .45rem;
}
.shop .tag-green { background: #b2de96; color: #223e2c; border-color: var(--sh-green); }

/* El contador "x2" de las ayudas iba en azul, que no sale en ningun otro sitio. */
.shop .boost-have {
  border-radius: 0;
  background: var(--sh-sunk);
  color: var(--sh-ink);
  font-size: var(--sh-fs-tiny);
}

/*
 * El filete del canto izquierdo de las tarjetas.
 *
 * `.card::before` lo pinta con `--grad-green`, un degradado. Se queda el filete
 * -separa bien- pero de color plano.
 */
.shop .card::before { background: var(--sh-green); opacity: 1; width: 3px; }

/* --- bloques de fondo ---------------------------------------------------- */

.shop .card, .shop .info-box {
  background: var(--sh-paper-2);
  border: 2px solid var(--sh-line);
  border-radius: 0;
  box-shadow: none;
}
.shop .card h3 { font-size: var(--sh-fs-head); color: var(--sh-ink); margin: 0 0 .1rem; }

/* =========================== TIENDA: EDITOR DE AVATAR (26-sep-2026)

   Hansel pidio la tienda "como en Roblox": ves a tu oveja grande, eliges una
   parte (cabeza, cara...) y te vas probando cosas encima antes de comprar.
   Todo cuelga de `.modal-shop` (la ventana) y de `.sx` (su contenido).

   El criterio es el de misiones y los carteles: colores PLANOS de PALETTE,
   cero degradados, sombra DURA (`3px 3px 0`), esquinas a escuadra, cuatro
   tamanos de letra, y las cosas se HUNDEN al pulsarlas. El caracter de
   videojuego sale de los materiales del corral: madera oscura para el marco y
   la barra de compra (como un mostrador), pergamino para las fichas, oro para
   lo que cuesta y verde para lo que llevas puesto.

   Sin scroll de pagina en ningun movil: la ventana ocupa la pantalla entera y
   lo unico que se desplaza es la rejilla de fichas, por dentro.
   ------------------------------------------------------------------------- */

.modal-shop {
  /* Colores, todos entradas de PALETTE. */
  --sx-ink:      #3a2c22;  /* tinta calida                */
  --sx-ink-soft: #6e645c;  /* topo: texto secundario      */
  --sx-paper:    #f7f2e8;  /* crema: fichas               */
  --sx-paper-2:  #e8dfc9;  /* crema hundido: fondos       */
  --sx-line:     #a89578;  /* crema oscuro: filetes       */
  --sx-wood:     #7d5230;  /* madera                      */
  --sx-wood-dk:  #5d3a20;  /* madera oscura: marco, barra */
  --sx-gold:     #f2b134;  /* oro: lo que cuesta          */
  --sx-gold-lt:  #ffd977;  /* oro claro: probando         */
  --sx-green:    #3d7a4f;  /* cesped: lo puesto           */
  --sx-green-lt: #b2de96;  /* cesped palido               */
  --sx-gem:      #b0e2f5;  /* la gema, clara              */
  --sx-fire:     #c44a18;  /* fuego: no te llega          */
  --sx-rose:     #f19bb0;  /* rosa: aviso sobre madera    */

  /* Cuatro tamanos de letra, y no hay mas. */
  --sx-lead:  1rem;
  --sx-body:  .875rem;
  --sx-small: .75rem;
  --sx-tiny:  .625rem;

  --sx-drop: 3px 3px 0 var(--sx-ink);
}

/* ---- la ventana: grande en el PC, la pantalla entera en el movil */
.modal-backdrop.modal-shop { padding: 1rem; align-items: center; }
.modal-shop .modal {
  width: min(1100px, 100%);
  height: min(700px, 100%);
  max-height: none;
  border-radius: 0;
  border: 3px solid var(--sx-ink);
  box-shadow: 6px 6px 0 rgba(26, 20, 18, .55);
  background: var(--sx-paper-2);
  padding-bottom: 0;
}
.modal-shop .modal-head {
  background: var(--sx-wood-dk);
  border-bottom: 3px solid var(--sx-ink);
  box-shadow: none;
  padding: .4rem .5rem .4rem .9rem;
}
.modal-shop .modal-head::before { display: none; }
.modal-shop .modal-head h2 {
  color: var(--sx-gold-lt);
  font-size: var(--sx-lead); font-weight: 900;
  letter-spacing: .06em; text-transform: uppercase;
}
.modal-shop .modal-close {
  width: 36px; height: 36px; min-width: 36px; min-height: 36px;
  border-radius: 0;
  background: var(--sx-paper); color: var(--sx-ink);
  border: 2px solid var(--sx-ink);
  box-shadow: 2px 2px 0 rgba(26, 20, 18, .6);
  font-weight: 900;
}
.modal-shop .modal-close:active { transform: translate(2px, 2px); box-shadow: none; }
.modal-shop .modal-body { padding: 0; overflow: hidden; display: flex; }

/* ---- el reparto: la oveja a la izquierda, el catalogo a la derecha */
.sx {
  flex: 1; min-width: 0; min-height: 0;
  display: grid;
  grid-template-columns: minmax(250px, 40%) minmax(0, 1fr);
  gap: .7rem;
  padding: .7rem;
}
.sx-left { display: flex; flex-direction: column; gap: .6rem; min-height: 0; min-width: 0; }
.sx-right {
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
  background: var(--sx-paper);
  border: 3px solid var(--sx-ink);
  box-shadow: var(--sx-drop);
}

/* ---- el escenario */
.sx-stage {
  position: relative; flex: 1; min-height: 0;
  background: #b0e2f5;
  border: 3px solid var(--sx-ink);
  box-shadow: var(--sx-drop);
  overflow: hidden;
}
.sx-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.sx-pix { display: inline-grid; place-items: center; flex-shrink: 0; }
.sx-pix svg { width: 12px; height: 12px; display: block; }

.sx-purse { position: absolute; top: .45rem; left: .45rem; display: flex; gap: .35rem; flex-wrap: wrap; }
.sx-chip {
  display: inline-flex; align-items: center; gap: .3rem;
  background: var(--sx-paper); color: var(--sx-ink);
  border: 2px solid var(--sx-ink); box-shadow: 2px 2px 0 var(--sx-ink);
  padding: .1rem .45rem .1rem .25rem;
  font-size: var(--sx-small); font-weight: 900;
}
.sx-chip .sx-pix svg { width: 24px; height: 24px; }
/* La gema lleva su color hasta en el fondo de la ficha del saldo: es la
   moneda rara, y tiene que distinguirse de un vistazo. */
.sx-chip.is-gem { background: var(--sx-gem); }
.sx-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.sx-level {
  position: absolute; top: .45rem; right: .45rem;
  background: var(--sx-wood-dk); color: var(--sx-gold-lt);
  border: 2px solid var(--sx-ink);
  padding: .15rem .5rem;
  font-size: var(--sx-small); font-weight: 900;
}

/* Darle la vuelta: un boton de madera redondo como los golpes del corral. */
.sx-spin {
  position: absolute; right: .55rem; bottom: .55rem;
  width: 48px; height: 48px; padding: 0;
  display: grid; place-items: center;
  background: var(--sx-wood);
  border: 3px solid var(--sx-ink); border-radius: 50%;
  box-shadow: var(--sx-drop);
  cursor: pointer;
}
.sx-spin svg { width: 24px; height: 24px; display: block; }
.sx-spin:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--sx-ink); }

/* "¡Es tuyo!" al comprar: entra, se queda un momento y se va. Una vez. */
.sx-banner {
  position: absolute; left: 50%; top: 18%;
  transform: translateX(-50%);
  background: var(--sx-gold); color: var(--sx-ink);
  border: 3px solid var(--sx-ink); box-shadow: var(--sx-drop);
  padding: .3rem 1rem;
  font-size: var(--sx-lead); font-weight: 900; white-space: nowrap;
  opacity: 0; pointer-events: none;
}
.sx-banner.show { animation: sxBanner 1.9s ease both; }
@keyframes sxBanner {
  0%   { opacity: 0; transform: translate(-50%, 10px) scale(.92); }
  14%  { opacity: 1; transform: translate(-50%, 0) scale(1.06); }
  24%  { transform: translate(-50%, 0) scale(1); }
  80%  { opacity: 1; transform: translate(-50%, 0); }
  100% { opacity: 0; transform: translate(-50%, -12px); }
}

/* ---- la barra de lo probado: el mostrador bajo la oveja */
.sx-bar {
  display: flex; align-items: center; gap: .6rem;
  min-height: 60px;
  padding: .45rem .55rem .45rem .7rem;
  background: var(--sx-wood-dk); color: var(--sx-paper);
  border: 3px solid var(--sx-ink); box-shadow: var(--sx-drop);
}
.sx-bar-hint {
  display: flex; align-items: center; gap: .5rem;
  font-size: var(--sx-small); font-weight: 700; color: var(--sx-paper-2);
}
.sx-bar-hint .sx-pix svg { width: 24px; height: 24px; }
.sx-bar-sum { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .12rem; }
.sx-bar-sum strong { font-size: var(--sx-small); color: var(--sx-gold-lt); text-transform: uppercase; letter-spacing: .04em; }
.sx-bar-total { display: flex; flex-wrap: wrap; align-items: center; gap: .15rem .7rem; font-size: var(--sx-lead); font-weight: 900; }
.sx-bar-total .sx-pix svg { width: 24px; height: 24px; }
.sx-bar-warn { font-size: var(--sx-small); font-weight: 900; color: var(--sx-rose); }
.sx-bar-note { font-size: var(--sx-small); color: var(--sx-paper-2); }
.sx-bar-btns { display: flex; gap: .4rem; flex-shrink: 0; }

.sx-btn {
  display: inline-flex; align-items: center; gap: .35rem;
  min-height: 44px; padding: .35rem .7rem .35rem .45rem;
  border: 2px solid #1a1412; border-radius: 0;
  box-shadow: 2px 2px 0 #1a1412;
  font-size: var(--sx-body); font-weight: 900;
  cursor: pointer;
}
.sx-btn .sx-pix svg { width: 24px; height: 24px; }
.sx-btn:active:not(:disabled) { transform: translate(2px, 2px); box-shadow: none; }
.sx-btn-quiet { background: var(--sx-paper-2); color: var(--sx-ink); }
.sx-btn-buy { background: var(--sx-gold); color: var(--sx-ink); }
/* Armado ("¿Seguro? Pagar"): cambia de COLOR, no parpadea. */
.sx-btn-buy.armed { background: #6bb56e; }
.sx-btn:disabled { background: var(--sx-line); color: #48403a; cursor: not-allowed; }
.sx-btn:disabled .sx-pix { opacity: .55; }

/* ---- las categorias: iconos en una tabla de madera */
.sx-cats {
  display: flex; gap: .35rem; flex-shrink: 0;
  padding: .45rem;
  background: var(--sx-wood);
  border-bottom: 3px solid var(--sx-ink);
  overflow-x: auto; scrollbar-width: none;
}
.sx-cats::-webkit-scrollbar { display: none; }
.sx-cat {
  flex: 0 0 auto;
  width: 44px; height: 44px; padding: 0;
  display: grid; place-items: center;
  background: var(--sx-paper);
  border: 2px solid var(--sx-ink); border-radius: 0;
  box-shadow: 2px 2px 0 var(--sx-ink);
  cursor: pointer;
}
.sx-cat svg { width: 24px; height: 24px; display: block; }
/* La elegida se marca con COLOR, no hundida: hundida deja de alinear. */
.sx-cat.on { background: var(--sx-gold); }
.sx-cat:active { transform: translate(2px, 2px); box-shadow: none; }

.sx-head {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: .2rem .5rem;
  flex-shrink: 0;
  padding: .45rem .7rem .4rem;
  border-bottom: 2px solid var(--sx-line);
}
.sx-title { font-size: var(--sx-lead); font-weight: 900; color: var(--sx-ink); }
.sx-count {
  font-size: var(--sx-tiny); font-weight: 900;
  background: var(--sx-ink); color: var(--sx-paper);
  padding: .05rem .35rem;
}
.sx .sx-hint { font-size: var(--sx-small); color: var(--sx-ink-soft); }

/* ---- la rejilla: lo unico que se desplaza, con su barra a la vista */
.sx-grid {
  flex: 1; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
  gap: .6rem;
  align-content: start;
  padding: .6rem .6rem .8rem;
  scrollbar-width: auto;
  scrollbar-color: var(--sx-wood) var(--sx-paper-2);
}
.sx-grid::-webkit-scrollbar { width: 12px; }
.sx-grid::-webkit-scrollbar-track { background: var(--sx-paper-2); border-left: 2px solid var(--sx-line); }
.sx-grid::-webkit-scrollbar-thumb { background: var(--sx-wood); border: 2px solid var(--sx-ink); }
.sx-grid.sx-list { grid-template-columns: minmax(0, 1fr); }

.sx-note {
  grid-column: 1 / -1;
  background: var(--sx-paper-2);
  border: 2px solid var(--sx-line);
  padding: .45rem .6rem;
  font-size: var(--sx-small); color: var(--sx-ink);
}

/* ---- la ficha */
.sx-card {
  position: relative;
  display: flex; flex-direction: column; gap: .25rem;
  padding: 0 0 .4rem;
  background: var(--sx-paper); color: var(--sx-ink);
  border: 2px solid var(--sx-ink); border-radius: 0;
  box-shadow: 3px 3px 0 var(--sx-ink);
  font: inherit; text-align: center;
  cursor: pointer;
}
.sx-card:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--sx-ink); }
.sx-thumb {
  display: grid; place-items: center;
  height: 80px;
  border-bottom: 2px solid var(--sx-ink);
}
.sx-thumb canvas { width: 72px; height: 72px; display: block; }
.sx-tier {
  position: absolute; top: 0; left: 0;
  padding: .05rem .35rem;
  border-right: 2px solid var(--sx-ink); border-bottom: 2px solid var(--sx-ink);
  color: var(--sx-paper);
  font-size: var(--sx-tiny); font-weight: 900;
  letter-spacing: .04em; text-transform: uppercase;
}
.sx-name { padding: 0 .35rem; font-size: var(--sx-small); font-weight: 800; line-height: 1.2; }
/* `margin-top: auto`: el precio se va solo al fondo y la fila cuadra sin
   alturas minimas puestas a ojo. */
.sx-price { margin-top: auto; display: flex; justify-content: center; font-size: var(--sx-small); font-weight: 900; }
.sx-amount { display: inline-flex; align-items: center; gap: .25rem; }
.sx-price.short .sx-amount { color: var(--sx-fire); }
.sx-own { color: var(--sx-green); }
.sx-lock { display: inline-flex; align-items: center; gap: .25rem; color: var(--sx-ink-soft); font-size: var(--sx-small); font-weight: 900; }

/* Estados: puesto (verde y su marca), probando (oro y su cartel), bloqueado. */
.sx-badge:empty { display: none; }
.sx-badge {
  position: absolute; top: -7px; right: -7px;
  display: grid; place-items: center;
  min-width: 28px; height: 28px;
  background: var(--sx-paper);
  border: 2px solid var(--sx-ink); box-shadow: 2px 2px 0 var(--sx-ink);
}
.sx-badge svg { width: 24px; height: 24px; display: block; }
.sx-card[data-state="worn"] { background: var(--sx-green-lt); border-color: var(--sx-green); box-shadow: 3px 3px 0 var(--sx-green); }
.sx-card[data-state="worn"] .sx-thumb { border-bottom-color: var(--sx-green); }
.sx-card[data-state="trying"] { background: var(--sx-gold-lt); }
/* El cartel de "Probando" va DENTRO de la miniatura, abajo a la derecha:
   arriba pisaba la rareza en las fichas estrechas, y en el borde tapaba el
   nombre. */
.sx-card[data-state="trying"] .sx-badge {
  top: 52px; right: 4px; box-shadow: none;
  height: 22px; padding: 0 .35rem;
  background: var(--sx-gold);
  font-size: var(--sx-tiny); font-weight: 900; text-transform: uppercase; letter-spacing: .04em;
}
.sx-card[data-state="locked"] .sx-thumb canvas { opacity: .5; filter: grayscale(.7); }
.sx-card[data-state="locked"] .sx-name { color: var(--sx-ink-soft); }

/* La lana: la ficha es la oveja de ese color y una franja con el color puro. */
.sx-wool .sx-dot { height: 12px; margin: 0 .5rem; border: 2px solid var(--sx-ink); }

/* Las ayudas y la casa, a lo ancho, con el mismo marco que las fichas. */
.sx .boost-card { background: var(--sx-paper); border-color: var(--sx-ink); box-shadow: var(--sx-drop); }
.sx .boost-card.full { background: var(--sx-green-lt); border-color: var(--sx-green); }
.sx .boost-icon { background: var(--sx-paper-2); border-color: var(--sx-ink); font-size: 0; }
.sx .boost-icon svg { width: 36px; height: 36px; display: block; }
.sx .boost-action .btn { display: inline-flex; align-items: center; gap: .3rem; }

/* ---- movil: la pantalla entera, sin marco de ventana */
@media (max-width: 560px), (max-height: 500px) {
  .modal-backdrop.modal-shop { padding: 0; align-items: stretch; }
  .modal-shop .modal {
    width: 100%; height: 100%;
    border: 0; box-shadow: none;
    padding-bottom: var(--safe-bottom);
  }
  .modal-shop .modal-head { padding: .25rem .45rem .25rem .8rem; }
  .modal-shop .modal-close { width: 34px; height: 34px; min-width: 34px; min-height: 34px; }
  .sx { gap: .45rem; padding: .45rem calc(.45rem + var(--safe-right)) .45rem calc(.45rem + var(--safe-left)); }
  .sx-left { gap: .45rem; }
  .sx-grid { grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: .5rem; padding: .5rem; }
  .sx-thumb { height: 76px; }
  .sx-bar { min-height: 54px; padding: .35rem .45rem .35rem .55rem; }
  .sx-btn { min-height: 42px; padding: .3rem .55rem .3rem .35rem; }
}

/* Tumbado (844x390, 740x360): la oveja un poco mas estrecha, la barra en dos
   pisos si hace falta, y las categorias sin aire de sobra. */
@media (max-height: 500px) and (orientation: landscape) {
  .sx { grid-template-columns: minmax(0, 38%) minmax(0, 1fr); }
  .sx-cats { padding: .3rem; gap: .3rem; }
  .sx-cat { width: 40px; height: 40px; }
  .sx-head { padding: .3rem .6rem .25rem; }
  .sx-bar { flex-wrap: wrap; gap: .3rem .5rem; }
  .sx-bar-sum { flex: 1 1 60%; }
  .sx-btn { min-height: 38px; }
}

/* De pie: la oveja arriba, la barra, y el catalogo abajo. */
@media (max-width: 560px) and (orientation: portrait) {
  .sx { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
  .sx-stage { flex: 0 0 auto; height: 32dvh; min-height: 190px; }
}
/* ======================== FIN TIENDA: EDITOR DE AVATAR */

/* -------------------------------------------------------------- ranking */

.rank-list { display: flex; flex-direction: column; gap: .35rem; }
.rank-row {
  display: flex; align-items: center; gap: .6rem;
  background: #fffdf7; border-radius: var(--radius-sm); padding: .45rem .6rem;
  border: 1.5px solid #e9e0c9;
}
.rank-row.me { border-color: var(--green-400); background: #eef7f1; }
.rank-pos { font-weight: 800; width: 30px; text-align: center; color: var(--ink-soft); }
.rank-row.top1 .rank-pos { color: var(--gold); font-size: 1.15rem; }
.rank-row.top2 .rank-pos { color: #8f99a4; font-size: 1.05rem; }
.rank-row.top3 .rank-pos { color: #a76b3a; font-size: 1.05rem; }
.rank-name { flex: 1; font-weight: 600; min-width: 0; }
.rank-name small { display: block; }
.rank-lvl { font-weight: 800; color: var(--green-600); text-align: right; font-size: .88rem; }

/* ---------------------------------------------------------------- tablas */

.table-wrap { overflow-x: auto; border-radius: var(--radius-sm); }
table.data { width: 100%; border-collapse: collapse; font-size: .87rem; background: #fffdf7; }
table.data th, table.data td { padding: .5rem .6rem; text-align: left; border-bottom: 1px solid #eae2cd; white-space: nowrap; }
table.data th { background: #f0e9d8; font-size: .76rem; text-transform: uppercase; letter-spacing: .03em; color: var(--ink-soft); position: sticky; top: 0; }
table.data tr:last-child td { border-bottom: none; }
table.data tr.pending-row { background: #fdf6e3; }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: .5rem; margin-bottom: .9rem; }
.stat-box { background: #fffdf7; border-radius: var(--radius-sm); padding: .6rem; text-align: center; }
.stat-box b { display: block; font-size: 1.5rem; color: var(--green-600); line-height: 1.1; }
.stat-box span { font-size: .74rem; color: var(--ink-soft); }

/* ---------------------------------------------------------------- toasts */

.toasts {
  position: fixed; left: 50%; transform: translateX(-50%);
  top: calc(.7rem + var(--safe-top));
  z-index: 100; display: flex; flex-direction: column; gap: .4rem;
  width: min(400px, 92vw); pointer-events: none;
}
.toast {
  background: rgba(16, 36, 26, .94);
  color: var(--cream);
  padding: .6rem .85rem; border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md); font-size: .88rem; font-weight: 600;
  animation: slideDown .22s ease;
}
.toast.success { background: #1e6b43; }
.toast.error   { background: #a93a2c; }
/* Los de premio ('reward') ya no existen como caja: son avisos flotantes
   (ver `.announce` al final y ui/announce.js). */
@keyframes slideDown { from { opacity: 0; transform: translateY(-12px); } to { opacity: 1; transform: none; } }

/* ------------------------------------------------- racha, sonido y estado */

.streak-chip.hidden { display: none; }
/* La racha en peligro parpadea en teja: es el unico aviso que se da antes de
   perderla. A saltos (steps) y sin brillo difuminado. */
.streak-chip.risk {
  border-color: var(--ms-ink);
  animation: streak-pulse 1.6s steps(1) infinite;
}
@keyframes streak-pulse {
  0%, 100% { background: var(--ms-green-dk); color: #f9a825; }
  50%      { background: #c4503c; color: #fffdf8; }
}

.reconnect-banner {
  position: absolute; top: calc(.5rem + var(--safe-top)); left: 50%;
  transform: translate(-50%, -180%);
  display: flex; align-items: center; gap: .5rem;
  background: rgba(168, 58, 44, .94);
  border: 1px solid rgba(255, 255, 255, .22);
  color: #fff5f2;
  padding: .45rem .9rem; border-radius: 999px;
  font-size: .84rem; font-weight: 600; white-space: nowrap;
  box-shadow: var(--shadow-md);
  transition: transform .28s ease;
  pointer-events: none; z-index: 40;
}
.reconnect-banner.show { transform: translate(-50%, 0); }
.reconnect-banner .spinner {
  width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .35);
  border-top-color: #fff;
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* La tira de racha del panel de misiones vive ahora en "misiones: ventana compacta". */

/* --------------------------------------------------------------- tutorial */

/*
 * La capa entera no captura el raton: asi se puede seguir jugando y probar los
 * controles mientras se lee. Solo el bocadillo es interactivo.
 * (Hace falta ser explicito porque `.hud > *` pone pointer-events: auto.)
 */
.tutorial { position: fixed; inset: 0; z-index: 60; pointer-events: none; }
.tutorial.closing { animation: tut-out .26s ease forwards; }
@keyframes tut-out { to { opacity: 0; } }

/*
 * El foco.
 *
 * No es una capa negra con un agujero recortado: es una caja del tamano de lo
 * que se explica con una sombra gigantesca alrededor. Todo lo que queda fuera
 * de la caja sale oscuro y lo de dentro se ve limpio. Sin mascaras SVG, que dan
 * guerra en moviles viejos.
 */
.tut-spot {
  position: fixed; left: 0; top: 0; width: 0; height: 0;
  border-radius: 999px;
  box-shadow: 0 0 0 9999px rgba(6, 18, 12, .72);
  outline: 2px solid rgba(255, 255, 255, .55);
  outline-offset: -1px;
  transition: left .3s cubic-bezier(.3,.9,.3,1), top .3s cubic-bezier(.3,.9,.3,1),
              width .3s ease, height .3s ease;
}
/* Un paso sin objetivo: la sombra sigue, el borde del agujero no. */
.tutorial.no-spot .tut-spot { outline: none; transition: none; }

/* Mientras el foco se mueve entre pasos, el borde late para que se siga. */
.tut-spot::after {
  content: ''; position: absolute; inset: -6px;
  border-radius: inherit; border: 2px solid rgba(255, 255, 255, .3);
  animation: spot-pulse 1.8s ease-in-out infinite;
}
.tutorial.no-spot .tut-spot::after { display: none; }
@keyframes spot-pulse {
  0%, 100% { transform: scale(1);    opacity: .55; }
  50%      { transform: scale(1.07); opacity: .15; }
}

/* ------------------------------------------------------------- bocadillo */

.tut-bubble {
  position: fixed; left: 0; top: 0;
  width: min(330px, calc(100vw - 24px));
  pointer-events: auto;
  background: var(--panel-bg);
  border: 1px solid var(--cream-2);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: .85rem .95rem .7rem;
  transition: left .3s cubic-bezier(.3,.9,.3,1), top .3s cubic-bezier(.3,.9,.3,1);
  animation: tut-in .3s cubic-bezier(.2, .9, .3, 1.2);
}
@keyframes tut-in { from { opacity: 0; transform: scale(.94); } }

/*
 * La punta. Son dos triangulos superpuestos -uno del color del borde y otro del
 * fondo, un pixel por dentro- para que el bocadillo tenga borde tambien en la
 * punta y no parezca pegada.
 */
.tut-tail { position: absolute; width: 0; height: 0; margin-left: -9px; }
.tut-tail::before, .tut-tail::after {
  content: ''; position: absolute; width: 0; height: 0;
  border-left: 9px solid transparent; border-right: 9px solid transparent;
}
.tut-bubble.below .tut-tail { top: -10px; }
.tut-bubble.below .tut-tail::before { border-bottom: 10px solid var(--cream-2); }
.tut-bubble.below .tut-tail::after  { border-bottom: 10px solid var(--panel-bg); top: 1.5px; }

.tut-bubble.above .tut-tail { bottom: -10px; }
.tut-bubble.above .tut-tail::before { border-top: 10px solid var(--cream-2); }
.tut-bubble.above .tut-tail::after  { border-top: 10px solid var(--panel-bg); bottom: 1.5px; }

/* Sin objetivo no hay a quien apuntar. */
.tutorial.no-spot .tut-tail { display: none; }

.tut-head { display: flex; align-items: center; gap: .5rem; padding-right: 3rem; }
.tut-head h3 { margin: 0; font-size: 1rem; line-height: 1.2; }
.tut-icon { font-size: 1.5rem; line-height: 1; }
.tut-bubble p { margin: .45rem 0 0; font-size: .87rem; color: var(--ink-soft); line-height: 1.45; }

.tut-skip {
  position: absolute; top: .55rem; right: .7rem;
  background: none; border: none; cursor: pointer;
  font-size: .74rem; color: var(--ink-soft); text-decoration: underline;
}

.tut-foot {
  display: flex; align-items: center; gap: .6rem;
  margin-top: .75rem; padding-top: .55rem; border-top: 1px solid var(--cream-2);
}
.tut-dots { display: flex; gap: .3rem; }
.tut-dots i {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--cream-2); transition: background .2s ease, width .2s ease;
}
.tut-dots i.on { background: var(--green-500); width: 18px; border-radius: 999px; }
.tut-foot .btn { margin-left: auto; }

/* ------------------------------------------------------------------ arcade */

/*
 * El arcade no paga monedas, asi que lo que antes era el cartel del tope
 * diario ahora es el recordatorio de contra quien se juega: el corral.
 */
.arcade-note {
  display: flex; align-items: center; gap: .7rem;
  background: #fff6e2; border: 1px solid rgba(242, 177, 52, .55);
  border-radius: var(--radius-sm); padding: .6rem .8rem; margin-bottom: .8rem;
}
.arcade-note strong { display: block; font-size: .92rem; }
.arcade-note small { color: var(--ink-soft); line-height: 1.35; }
.arcade-note-icon { font-size: 1.5rem; line-height: 1; }

.arcade-card { padding: .8rem; }
.arcade-head { display: flex; align-items: center; gap: .7rem; margin-bottom: .7rem; }
.arcade-icon { font-size: 2rem; line-height: 1; }
.arcade-meta { flex: 1; min-width: 0; }
.arcade-meta h3 { margin: 0 0 .15rem; font-size: 1rem; }
.arcade-meta small { color: var(--ink-soft); line-height: 1.35; }

.arcade-skill {
  display: inline-block; margin-top: .3rem;
  font-size: .68rem; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  color: var(--ink-soft); background: var(--cream-2);
  border-radius: 999px; padding: .1rem .5rem;
}

/* Las dos cifras de la ficha: tu record y tu puesto en el corral. */
.arcade-stats {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: .4rem;
  background: var(--cream-2); border-radius: var(--radius-sm);
  padding: .5rem .4rem; margin-bottom: .7rem;
}
.arcade-stat { text-align: center; min-width: 0; }
.arcade-stat b { display: block; font-size: 1.1rem; color: var(--green-600); line-height: 1.2; }
.arcade-stat b.gold { color: #b3820c; }
.arcade-stat span {
  display: block; font-size: .68rem; color: var(--ink-soft);
  text-transform: uppercase; letter-spacing: .03em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.arcade-actions { gap: .45rem; }
.arcade-actions .btn-block { flex: 1; width: auto; }

.arcade-intro, .arcade-result, .arcade-top { text-align: center; padding: .5rem 0 .2rem; }
.arcade-icon-big { font-size: 3.4rem; line-height: 1; }
.arcade-intro h3, .arcade-result h3, .arcade-top h3 { margin: .4rem 0 .5rem; }
.arcade-intro p { color: var(--ink-soft); max-width: 24rem; margin: 0 auto; }
.arcade-target {
  display: inline-block; margin-top: .7rem;
  background: var(--cream-2); border-radius: 999px;
  padding: .3rem .85rem; font-weight: 700; font-size: .88rem; color: var(--ink-soft);
}

.arcade-final { display: flex; align-items: baseline; justify-content: center; gap: .4rem; margin: .3rem 0 .4rem; }
.arcade-final b { font-size: 2.4rem; color: var(--green-600); line-height: 1; }
.arcade-final span { color: var(--ink-soft); font-size: .9rem; }
.arcade-gain { font-weight: 700; color: var(--green-600); margin: 0 0 .6rem; }
.arcade-crown {
  display: inline-block; margin: 0 auto .7rem;
  background: var(--grad-gold); color: #4a3406;
  font-weight: 800; font-size: 1rem;
  padding: .35rem .9rem; border-radius: 999px;
}

/*
 * Top del corral.
 *
 * Es lo unico que reparte el arcade, asi que la fila propia va resaltada: lo
 * primero que busca cualquiera al abrir una tabla es donde esta el.
 */
.arcade-board-title { margin: 1rem 0 .5rem; font-size: .95rem; }
.arcade-board { text-align: left; display: flex; flex-direction: column; gap: .25rem; }
.arcade-row {
  display: flex; align-items: center; gap: .6rem;
  background: var(--cream-2); border-radius: var(--radius-sm);
  padding: .45rem .7rem; font-size: .92rem;
}
.arcade-row.me { background: #e8f6ec; box-shadow: inset 0 0 0 1.5px var(--green-500); font-weight: 700; }
.arcade-row.me.out { margin-top: .35rem; opacity: .9; }
.ar-pos { width: 1.7rem; text-align: center; font-weight: 800; color: var(--ink-soft); }
.arcade-row.me .ar-pos { color: var(--green-600); }
.ar-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ar-score { font-weight: 800; color: var(--green-600); white-space: nowrap; }

/*
 * La partida.
 *
 * `touch-action: none` es imprescindible: sin el, arrastrar el dedo para mover
 * el cesto hace que el navegador desplace la pagina y el juego no responde.
 */
.arcade-stage { display: flex; flex-direction: column; gap: .5rem; }
.arcade-bar {
  display: flex; align-items: center; gap: .5rem;
  font-size: .9rem;
}
.arcade-score {
  font-weight: 800; font-size: 1.2rem; color: var(--green-600);
  min-width: 2.5rem; text-align: right;
  transition: color .2s ease, transform .2s ease;
}
/* Al pasar el record propio, el marcador se enciende y no vuelve a apagarse. */
.arcade-score.record { color: #b3820c; transform: scale(1.12); }
/*
 * La chapa del objetivo: a quien hay que pasar, a la vista toda la partida.
 *
 * Sustituye a la vieja chapa del record propio: cuando no tienes a nadie
 * delante en el corral, el objetivo ES tu record, asi que la chapa antigua
 * sobraba.
 *
 * En un arcade que no paga monedas este es el marcador que de verdad importa.
 * Se queda dorada al conseguirlo y ya no vuelve atras: el resto de la partida
 * se juega con la ventaja puesta encima de la mesa.
 */
.arcade-target-chip {
  font-size: .74rem; font-weight: 700; color: var(--ink-soft);
  background: var(--cream-2); border-radius: 999px; padding: .12rem .5rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 10rem;
  transition: background .25s ease, color .25s ease;
}
.arcade-target-chip.done { background: var(--grad-gold); color: #4a3406; }
.arcade-passed { font-weight: 800; color: #b3820c; margin: 0 0 .4rem; }
.arcade-canvas {
  width: 100%;
  height: min(62vh, 460px);
  display: block;
  border-radius: var(--radius-sm);
  background: #8fd0f0;
  touch-action: none;
  cursor: pointer;
  box-shadow: inset 0 2px 10px rgba(0, 0, 0, .18);
}

/* ---------------------------------------------------- gira el telefono */

/*
 * Solo aparece en pantallas tactiles puestas en vertical. Se decide aqui y no
 * en JavaScript: el CSS reacciona al giro solo, sin estado que se desincronice.
 */
.rotate-hint { display: none; }

@media (orientation: portrait) and (pointer: coarse) {
  .rotate-hint {
    position: fixed; inset: 0; z-index: 90;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    gap: .5rem; padding: 2rem;
    text-align: center;
    background: linear-gradient(170deg, #16362a, #0d1f16);
    color: var(--cream);
  }
  .rotate-hint h3 { font-size: 1.25rem; margin: .4rem 0 0; }
  .rotate-hint p { font-size: .9rem; opacity: .8; max-width: 22rem; margin: 0; }
  .rotate-phone {
    font-size: 4.5rem; line-height: 1;
    animation: rotate-nudge 2.4s ease-in-out infinite;
  }
  @keyframes rotate-nudge {
    0%, 45%, 100% { transform: rotate(0); }
    65%, 90%      { transform: rotate(-90deg); }
  }
}

/* =========================================================================
   MOVIL  (ver la nota sobre `pointer: coarse` justo debajo)

   El corral se juega con las dos manos: pulgar izquierdo en el joystick,
   derecho en el salto. Todo lo demas tiene que apartarse de esas dos esquinas
   y, sobre todo, **dejar ver el prado**: en un movil la pantalla ya es
   pequena, y cada panel flotante es campo de juego que se pierde.

   Tres reglas que se siguen en todo este bloque:

    1. **nada por debajo de 46 px** en lo que haya que tocar. Es la medida a
       partir de la cual un dedo acierta sin mirar;
    2. **las esquinas de abajo son sagradas**: joystick a la izquierda, salto a
       la derecha, y nada mas ahi;
    3. **lo que se abre, se abre desde abajo**. Un panel pegado al borde
       inferior se alcanza con el pulgar; uno centrado, no.

   ---------------------------------------------------------------------------
   POR QUE `pointer: coarse` Y NO `max-width`
   ---------------------------------------------------------------------------
   Esto empezo siendo `@media (max-width: 720px)`, que es lo que se pone por
   costumbre. Y estaba MAL, de una forma que solo se ve al girar el telefono:

     un movil en horizontal mide 844 px de ancho.

   O sea que al ponerlo horizontal dejaba de considerarse movil y se le servia
   el diseno de escritorio: botones con texto, chat sin plegar, paneles
   centrados... y encima el joystick desaparecia, porque otra regla lo escondia
   "en pantallas grandes". Justo en la orientacion en la que se supone que hay
   que jugar.

   La medida buena no es el ancho sino **con que se toca**. `pointer: coarse`
   significa "el puntero principal es un dedo", y eso no cambia al girar el
   aparato. El `max-width` se queda solo como red para una ventana de
   escritorio muy estrecha.
   ========================================================================= */

@media (pointer: coarse), (max-width: 720px) {

  /* --- Fichas de arriba ------------------------------------------------- */

  .hud-top { max-width: 46vw; left: calc(.5rem + var(--safe-left)); gap: .3rem; }
  .xp-bar { width: 104px; }

  /* --- Buzon y menu ----------------------------------------------------- */
  /*
   * Con el dedo, solo el icono: el nombre ocupaba un tercio del ancho y tapaba
   * el corral. Cuadrados de 46 px, lo minimo que se acierta sin mirar.
   */
  .hud-btn span.label { display: none; }
  .hud-btn { width: var(--touch); height: var(--touch); padding: 0; }

  /* --- Controles -------------------------------------------------------- */

  .joystick {
    width: 118px; height: 118px;
    left: calc(1rem + var(--safe-left));
    bottom: calc(1rem + var(--safe-bottom));
  }
  .joystick .knob { width: 50px; height: 50px; margin: -25px 0 0 -25px; }

  /* El salto vuelve a su esquina natural: el podio ya no le estorba. */
  .jump-btn {
    right: calc(1.1rem + var(--safe-right));
    bottom: calc(1.6rem + var(--safe-bottom));
    width: 72px; height: 72px; font-size: 2rem;
  }

  /*
   * El podio se esconde.
   *
   * Es decoracion -el ranking de verdad esta a un toque en el boton 🏆- y
   * ocupaba justo la esquina donde va el pulgar derecho. En una pantalla de
   * movil ese sitio vale mas vacio.
   */
  .podium-box { display: none; }

  /* --- Chat ------------------------------------------------------------- */

  /*
   * Plegado se ve solo el boton 💬. Al tocarlo aparece el campo de texto y se
   * cierra al enviar: el corral se queda despejado casi todo el rato, que es
   * justo lo que queriamos al quitar el cuadro de mensajes.
   */
  .chat-box { width: auto; bottom: calc(1.2rem + var(--safe-bottom)); }
  .chat-box.collapsed .chat-input input,
  .chat-box.collapsed .chat-send { display: none; }
  .chat-box:not(.collapsed) { width: min(320px, 74vw); }

  .chat-toggle-mobile { display: inline-flex; }
  .chat-input button, .chat-toggle-mobile {
    min-width: 42px; min-height: 42px;
    justify-content: center;
  }
  .chat-input input { min-height: 42px; }

  /* --- Rueda de bailes: hoja inferior ----------------------------------- */
  /*
   * Salia por el lateral derecho, justo encima de los botones del menu. Ahora
   * sube desde abajo ocupando el ancho: se alcanza con el pulgar y las fichas
   * caben mas grandes.
   */
  .emote-dock {
    right: 0; left: 0; top: auto; bottom: 0;
    width: 100%;
    transform: translateY(110%);
    border-radius: var(--radius) var(--radius) 0 0;
    padding: .7rem .7rem calc(.7rem + var(--safe-bottom));
  }
  .emote-dock.open { transform: translateY(0); }
  .emote-grid { grid-template-columns: repeat(4, 1fr); max-height: 42vh; overscroll-behavior: contain; }
  .emote-chip { padding: .45rem .2rem; }

  /* --- Modales: hoja inferior ------------------------------------------- */
  /*
   * Un modal centrado en un movil deja franjas muertas arriba y abajo y pone
   * los botones en el centro de la pantalla, que es donde peor llega el
   * pulgar. Pegado abajo se usa con una mano.
   */
  .modal-backdrop { align-items: flex-end; padding: 0; }
  .modal {
    width: 100%;
    max-height: 92vh;
    border-radius: 18px 18px 0 0;
    padding-bottom: var(--safe-bottom);
    animation: sheet-up .26s cubic-bezier(.2, .9, .3, 1);
  }
  @keyframes sheet-up { from { transform: translateY(100%); } }
  /*
   * Agarradera: la pista visual de que esto es una hoja que se cierra.
   * En claro sobre la cabecera verde oscura, que si no no se ve.
   */
  .modal-head { position: relative; padding-top: 1.15rem; }
  .modal-head::before {
    content: '';
    position: absolute; top: .45rem; left: 50%; transform: translateX(-50%);
    width: 40px; height: 4px; border-radius: 99px;
    background: rgba(255, 255, 255, .45);
  }
  .modal-close { min-width: 40px; min-height: 40px; }
  .modal-body { overscroll-behavior: contain; }

  /* --- Paneles y formularios -------------------------------------------- */

  .role-picker { grid-template-columns: 1fr; }
  .tabs button { padding: .68rem .5rem; }
  .btn { padding: .74rem 1rem; }
  .btn-sm { padding: .5rem .8rem; }

  /* --- Portada y pantallas de panel ------------------------------------- */

  /*
   * Al enfocar un campo, el teclado del movil se come media pantalla y deja la
   * tarjeta cortada. El margen vertical FIJO (en vez del `margin: auto` que la
   * centra en pantalla grande) la ancla arriba y deja sitio para que el
   * navegador la desplace hasta el campo enfocado.
   *
   * OJO: este bloque tenia ademas `border-radius: 18px` y `top: 2%` para el
   * sol, y como es un media query ganaba siempre en movil — o sea que la
   * portada repintada solo se veia en pantalla grande. Si se toca el diseno de
   * arriba, hay que mirar aqui.
   */
  .auth-screen { padding: .75rem; }
  /*
   * `margin: auto` y NADA mas para colocarla. Dos trampas ya pisadas:
   * con `align-items: center` en el padre, un formulario mas alto que la
   * pantalla se corta por arriba y no hay forma de llegar; y con un margen
   * vertical FIJO vuelve el `stretch` del flex y la tarjeta se estira hasta
   * abajo dejando un palmo de crema vacia. `margin: auto` centra, no estira y
   * deja desplazarse a los dos lados cuando no cabe.
   */
  .auth-card { padding: 1.15rem 1rem 1.2rem; margin: auto; }

  /*
   * En una sola columna la ficha de rol se quedaba enorme y hueca: el emoji
   * solo en una linea y el texto debajo. En fila -icono a la izquierda, texto
   * a la derecha- ocupa la mitad de alto y se lee igual.
   */
  .role-option {
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas: "icono nombre" "icono pista";
    align-items: center;
    column-gap: .75rem;
    text-align: left;
    padding: .6rem .85rem;
  }
  .role-option .emoji  { grid-area: icono; font-size: 1.7rem; }
  .role-option strong  { grid-area: nombre; align-self: end; }
  .role-option small   { grid-area: pista;  align-self: start; }
  .auth-screen .tabs button { padding: .6rem .5rem; }
  .auth-logo .emoji { font-size: 2.6rem; }
  .auth-logo h1 { font-size: 1.5rem; }

  .screen-pad { padding: .75rem; padding-top: calc(.75rem + var(--safe-top)); }
  .top-bar { padding-left: calc(.8rem + var(--safe-left)); padding-right: calc(.8rem + var(--safe-right)); }
  .top-bar h2 { font-size: .95rem; }
  /* Tablas anchas: que se desplacen ellas y no la pantalla entera. */
  .modal-body table.data, .screen-inner table.data { display: block; overflow-x: auto; }

  /* --- Tutorial --------------------------------------------------------- */

  .tut-bubble { width: min(300px, calc(100vw - 20px)); padding: .7rem .8rem .6rem; }
  .tut-bubble p { font-size: .82rem; }
  .tut-head h3 { font-size: .94rem; }
  /* Area de toque decente sin agrandar el texto. */
  .tut-skip { padding: .5rem .6rem; margin: -.5rem -.6rem; }
  .reconnect-banner { font-size: .76rem; padding: .4rem .7rem; }
}

/* -------------------------------------------------------------------------
   MOVIL EN HORIZONTAL

   Aqui sobra ancho y falta alto: 350-400 px de alto contra 800 de ancho. La
   columna de botones del menu no cabe de pie, asi que se tumba en fila, y todo
   lo que se abra tiene que ser bajito o no se ve nada del juego.
   ------------------------------------------------------------------------- */

@media (max-height: 500px) and (orientation: landscape) {
  .hud-top { max-width: 40vw; }
  .player-chip .sub { display: none; }
  .xp-bar { width: 88px; }

  /*
   * Aqui el nombre del boton sobra SIEMPRE, tenga raton o dedo: con 350 px de
   * alto no hay sitio para nombres arriba. El saldo se aprieta un poco.
   */
  .hud-btn span.label { display: none; }
  .hud-btn { width: 42px; height: 42px; padding: 0; }
  .coin-chip, .gem-chip, .streak-chip { height: 32px; padding: 0 .5rem 0 .25rem; }

  .joystick { width: 96px; height: 96px; bottom: calc(.6rem + var(--safe-bottom)); }
  .joystick .knob { width: 42px; height: 42px; margin: -21px 0 0 -21px; }
  .jump-btn { width: 60px; height: 60px; font-size: 1.7rem; bottom: calc(.8rem + var(--safe-bottom)); }

  /* Centrado abajo, entre el joystick y el salto: ahi no estorba a ninguno. */
  .chat-box { bottom: calc(.7rem + var(--safe-bottom)); }
  .chat-box:not(.collapsed) { width: min(300px, 42vw); }

  .emote-grid { grid-template-columns: repeat(6, 1fr); max-height: 40vh; }
  .modal { max-height: 96vh; }
  .tut-bubble { width: min(340px, 46vw); }
}

/*
 * El joystick se esconde solo cuando hay un raton de verdad.
 *
 * Antes se escondia "en pantallas de mas de 720 px", y eso dejaba sin joystick
 * a cualquier telefono puesto en horizontal, que es mas ancho que eso. Ahora la
 * condicion es el puntero: con raton sobra (esta el teclado), con dedo hace
 * falta siempre, se ponga el telefono como se ponga.
 *
 * En un portatil tactil `pointer: fine` sigue siendo cierto -el raton es el
 * puntero principal-, asi que tampoco le estorba.
 */
@media (pointer: fine) {
  .joystick { display: none; }
  .joy-zone { display: none; }
}

/* =========================================================================
   BIBLIA

   Sigue el criterio del bloque de MISIONES, que es el que ya esta repintado:
   colores planos sacados de PALETTE, ni un degradado, sombras duras sin blur,
   esquinas rectas y CUATRO tamanos de letra.

   Una decision propia de esta pantalla, y la unica que se sale de "menos es
   mas": las palabras ya leidas se marcan con FONDO amarillo, no cambiandoles
   el color de la letra. Se probaron las dos. Con la letra dorada sobre crema
   no habia contraste para leer en voz alta desde un movil -que es justo lo que
   hay que hacer aqui- y ademas se leia como texto apagado, como si lo leido
   valiera menos. Con el fondo se lee como lo que es: un subrayador amarillo
   sobre una Biblia de papel, y la pagina se va llenando segun avanzas.
   ========================================================================= */

.bib,
.bib-reader {
  /* --- los cuatro tamanos, y no hay mas --------------------------------- */
  --bb-display: 1.6rem;   /* el "12 de 66" y el porcentaje        */
  --bb-lead:    1.12rem;  /* el texto biblico: se lee en voz alta */
  --bb-body:    .875rem;  /* nombres de libro y botones           */
  --bb-small:   .75rem;   /* metadatos                            */

  /* --- colores, todos entradas exactas de PALETTE ----------------------- */
  --bb-ink:      #1a1412;  /* tinta                     */
  --bb-ink-soft: #48403a;  /* topo oscuro               */
  --bb-line:     #a89578;  /* crema oscuro: los bordes  */
  --bb-paper:    #f7f2e8;  /* crema: el fondo           */
  --bb-paper-2:  #e8dfc9;  /* crema hundido             */
  --bb-green:    #3d7a4f;  /* cesped                    */
  --bb-green-dk: #223e2c;  /* cesped oscuro             */
  --bb-gold:     #f2b134;  /* oro: la palabra de ahora  */
  --bb-gold-lt:  #ffd977;  /* oro claro: lo ya leido    */
  --bb-fire:     #c44a18;  /* fuego: solo los avisos    */

  color: var(--bb-ink);
  font-size: var(--bb-body);
}

.bib-loading,
.bib-empty { padding: 2rem 1rem; text-align: center; color: var(--bb-ink-soft); }
.bib-empty code {
  display: inline-block;
  margin-top: .6rem;
  padding: .4rem .6rem;
  background: var(--bb-paper-2);
  border: 2px solid var(--bb-line);
  font-size: var(--bb-small);
}

/* --- El marcador de arriba ---------------------------------------------- */

.bib-total {
  background: var(--bb-green-dk);
  color: var(--bb-paper);
  border: 2px solid var(--bb-ink);
  box-shadow: 3px 3px 0 var(--bb-ink);
  padding: .9rem 1rem;
  margin-bottom: 1.2rem;
  text-align: center;
}
.bib-total-num { font-size: var(--bb-display); font-weight: 800; line-height: 1; }
.bib-total-lbl {
  font-size: var(--bb-small);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--bb-gold-lt);
  margin-bottom: .6rem;
}
/*
 * El color va explicito y no por `opacity`: la hoja de estilos tiene un
 * `small, .muted { color: var(--ink-soft) }` global (linea 115) que pisa lo que
 * herede este texto, y --ink-soft es un gris pensado para fondo claro. Sobre el
 * verde oscuro de aqui se quedaba en un gris apagado, casi ilegible. Le paso lo
 * mismo al panel de Misiones y se arreglo igual (ver `.daily-meta small`).
 */
.bib-total small {
  display: block;
  margin-top: .5rem;
  font-size: var(--bb-small);
  color: var(--bb-paper-2);
}

/* --- La barra de progreso, la misma en los dos sitios -------------------- */

.bib-bar {
  display: block;
  height: 10px;
  background: var(--bb-paper-2);
  border: 2px solid var(--bb-ink);
  overflow: hidden;
}
.bib-bar i {
  display: block;
  height: 100%;
  background: var(--bb-gold);
  transition: width .25s ease;
}
.bib-total .bib-bar { background: var(--bb-green); border-color: var(--bb-paper); }

/* --- La lista de libros -------------------------------------------------- */

.bib-section { margin-bottom: 1.4rem; }
.bib-section h3 {
  font-size: var(--bb-body);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--bb-ink-soft);
  border-bottom: 2px solid var(--bb-line);
  padding-bottom: .35rem;
  margin: 0 0 .7rem;
}

.bib-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: .55rem;
}

.bib-book {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas:
    "name meta"
    "bar  pct";
  align-items: center;
  gap: .3rem .5rem;
  padding: .6rem .7rem;
  background: var(--bb-paper);
  border: 2px solid var(--bb-ink);
  box-shadow: 3px 3px 0 var(--bb-line);
  border-radius: 0;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
  /* Solo la sombra y el fondo se mueven: nada se levanta ni se difumina. */
  transition: box-shadow .12s ease, background .12s ease, transform .12s ease;
}
.bib-book:hover { background: var(--bb-paper-2); box-shadow: 3px 3px 0 var(--bb-ink); }
/* Se HUNDE al pulsar: la sombra se acorta y la ficha baja lo mismo. */
.bib-book:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--bb-ink); }

.bib-book-name { grid-area: name; font-weight: 700; }
.bib-book-meta { grid-area: meta; font-size: var(--bb-small); color: var(--bb-ink-soft); }
.bib-book .bib-bar { grid-area: bar; }
.bib-book-pct { grid-area: pct; font-size: var(--bb-small); font-weight: 700; min-width: 2.6em; text-align: right; }

.bib-book.started { border-color: var(--bb-gold); }
.bib-book.done { background: var(--bb-green-dk); color: var(--bb-paper); }
.bib-book.done .bib-book-meta { color: var(--bb-gold-lt); }
.bib-book.done .bib-bar { background: var(--bb-green); border-color: var(--bb-paper); }

.bib-fuente { font-size: var(--bb-small); color: var(--bb-ink-soft); text-align: center; margin: 0; }

/* --- El lector ----------------------------------------------------------- */

.bib-reader {
  position: relative; /* el marco de los brillos de .bib-sparks */
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  gap: .6rem;
}

.bib-head { display: flex; align-items: center; gap: .7rem; }
.bib-head-title { flex: 1; line-height: 1.2; }
.bib-head-title strong { display: block; font-size: var(--bb-lead); }
.bib-head-title span { font-size: var(--bb-small); color: var(--bb-ink-soft); }
.bib-head-pct { font-size: var(--bb-display); font-weight: 800; line-height: 1; }

.bib-back {
  padding: .45rem .8rem;
  background: var(--bb-paper);
  border: 2px solid var(--bb-ink);
  box-shadow: 2px 2px 0 var(--bb-line);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
  border-radius: 0;
}
.bib-back:active { transform: translate(2px, 2px); box-shadow: 0 0 0 var(--bb-line); }

/* El texto: es lo unico que crece y lo unico que hace scroll. */
.bib-text {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  background: var(--bb-paper);
  border: 2px solid var(--bb-line);
  padding: .9rem 1rem;
  font-size: var(--bb-lead);
  line-height: 1.75;
}

.bib-verse { margin: 0 0 .55rem; }
.bib-verse b {
  font-size: var(--bb-small);
  color: var(--bb-ink-soft);
  vertical-align: super;
  margin-right: .25em;
  font-weight: 700;
}

/*
 * Las tres caras de una palabra.
 *
 * El box-decoration-break no es un adorno: sin el, una palabra subrayada que
 * cae justo en el salto de linea se parte y el fondo amarillo solo sale en el
 * primer trozo, con lo que parece que se leyo media palabra.
 */
.bib-text .w {
  padding: .05em .08em;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
.bib-text .w.leida { background: var(--bb-gold-lt); }
.bib-text .w.ahora { background: var(--bb-gold); font-weight: 700; }

/* --- El microfono -------------------------------------------------------- */

.bib-mic { display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; }
.bib-mic .btn {
  border-radius: 0;
  background: var(--bb-green);
  border: 2px solid var(--bb-ink);
  box-shadow: 3px 3px 0 var(--bb-ink);
}
.bib-mic .btn:hover:not(:disabled) {
  filter: none;
  transform: none;
  background: var(--bb-green-dk);
  box-shadow: 3px 3px 0 var(--bb-ink);
}
.bib-mic .btn:active:not(:disabled) { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--bb-ink); }
.bib-mic .bib-stop { background: var(--bb-fire); }
.bib-mic .bib-stop:hover:not(:disabled) { background: var(--bb-fire); }

.bib-state { font-size: var(--bb-small); color: var(--bb-ink-soft); }

/*
 * El punto que dice que el microfono esta abierto.
 *
 * Late despacio, y es el unico movimiento de toda la pantalla. Tiene trabajo
 * que hacer: "escuchando" escrito no se distingue de "escuchando" congelado
 * porque la pestana se quedo colgada, y aqui eso importa — si el reconocedor
 * se murio, el chico seguiria leyendo en voz alta para nadie.
 *
 * Parpadea a saltos (steps) y no con un desvanecido: el corral no difumina.
 */
.bib-state.on { color: var(--bb-green-dk); font-weight: 700; }
.bib-state.on::before {
  content: "";
  display: inline-block;
  width: .6em;
  height: .6em;
  margin-right: .45em;
  background: var(--bb-fire);
  animation: bib-latido 1.4s steps(2, end) infinite;
}
@keyframes bib-latido {
  0%, 50% { opacity: 1; }
  50.01%, 100% { opacity: .25; }
}

.bib-problem {
  flex-basis: 100%;
  margin: 0;
  padding: .55rem .7rem;
  background: var(--bb-paper-2);
  border-left: 4px solid var(--bb-fire);
  font-size: var(--bb-small);
  color: var(--bb-ink);
}


/* --- La meta del corral --------------------------------------------------- */

/*
 * Se distingue del marcador propio por el FONDO, no por el tamano: el de arriba
 * es verde oscuro y este es papel hundido. Son dos cosas del mismo rango -lo
 * tuyo y lo de todos- y hacer una mas grande que la otra diria que una importa
 * mas.
 */
.bib-pen {
  background: var(--bb-paper-2);
  border: 2px solid var(--bb-ink);
  box-shadow: 3px 3px 0 var(--bb-ink);
  padding: .75rem .9rem;
  margin-bottom: 1.2rem;
}
.bib-pen-head { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem; }
.bib-pen-head strong { font-size: var(--bb-body); }
.bib-pen-head span { font-size: var(--bb-body); font-weight: 700; }
/* Color explicito: si no, gana el "small, .muted" global y se apaga. */
.bib-pen-msg { margin: .5rem 0 0; font-size: var(--bb-small); color: var(--bb-ink-soft); }

/* Conseguida: oro, que es el color con el que este juego dice "esto ya es tuyo". */
.bib-pen.hecha { background: var(--bb-gold-lt); }
.bib-pen.hecha .bib-pen-msg { color: var(--bb-ink); font-weight: 700; }

/* --- El paso al capitulo siguiente --------------------------------------- */

/*
 * Ocupa el mismo sitio que el boton del microfono, y por eso comparten la
 * clase .bib-foot: al cerrar un capitulo, lo que hay bajo el texto deja de ser
 * "escuchando" y pasa a ser "sigue". Cambiar la franja entera en vez de meter
 * un boton nuevo mas abajo evita que el texto se mueva justo cuando el chico
 * esta mirando la ultima palabra que acaba de leer.
 */
.bib-next {
  display: flex;
  align-items: center;
  gap: .8rem;
  flex-wrap: wrap;
  padding: .7rem .8rem;
  background: var(--bb-paper-2);
  border: 2px solid var(--bb-ink);
  box-shadow: 3px 3px 0 var(--bb-ink);
}
.bib-next .btn {
  border-radius: 0;
  background: var(--bb-green);
  border: 2px solid var(--bb-ink);
  box-shadow: 3px 3px 0 var(--bb-ink);
}
.bib-next .btn:hover:not(:disabled) {
  filter: none;
  transform: none;
  background: var(--bb-green-dk);
  box-shadow: 3px 3px 0 var(--bb-ink);
}
.bib-next .btn:active:not(:disabled) { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--bb-ink); }

/* El ultimo capitulo se marca en oro: es el final del libro, no un paso mas. */
.bib-next.fin { background: var(--bb-gold-lt); }

/*
 * "Leer otra vez" (vuelta nueva a un libro terminado): el mismo boton en papel
 * en vez de verde. Es la segunda opcion; lo normal al acabar es volver.
 */
.bib-next .btn.bib-again { background: var(--bb-paper); color: var(--bb-ink); }
.bib-next .btn.bib-again:hover:not(:disabled) { background: var(--bb-paper-2); }

/* Las vueltas y la liga, bajo el marcador de libros: una linea mas, en negrita. */
.bib-total .bib-liga { display: block; margin-top: .35rem; font-weight: 700; }

/* Color explicito: si no, gana el "small, .muted" global y se apaga. */
.bib-next-msg { font-size: var(--bb-small); color: var(--bb-ink); font-weight: 700; }

/* --- Los brillos de terminar un libro ------------------------------------ */

/*
 * Estrellas de cuatro puntas, recortadas con clip-path sobre un color plano de
 * la paleta. Ni degradado ni desenfoque: un destello de pixel art es una cruz
 * con la cintura estrecha, y eso es exactamente lo que dibuja el poligono.
 *
 * La capa esta por encima del texto pero no recibe clics, y se borra entera a
 * los tres segundos desde el JS.
 */
.bib-sparks {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 3;
}

.bib-spark {
  position: absolute;
  display: block;
  clip-path: polygon(50% 0%, 58% 42%, 100% 50%, 58% 58%, 50% 100%, 42% 58%, 0% 50%, 42% 42%);
  opacity: 0;
  animation: bib-destello 1.5s ease-out forwards;
}

@keyframes bib-destello {
  0%   { opacity: 0; transform: scale(0) rotate(0deg); }
  30%  { opacity: 1; transform: scale(1) rotate(35deg); }
  100% { opacity: 0; transform: scale(.25) rotate(90deg); }
}

@media (max-width: 520px) {
  .bib-list { grid-template-columns: 1fr 1fr; }
  .bib-head-pct { font-size: var(--bb-lead); }
}

/* =========================================================================
   LA PESCA EN EL LAGO
   =========================================================================

   Esto esta escrito con el criterio de la casa, no con el de los botones de
   al lado: colores PLANOS de la paleta del juego, sombras DURAS y desplazadas
   sin difuminar, y cero degradados. Los `fab` de cuidar y de la puerta todavia
   llevan degradado y sombra borrosa -son de antes del repintado- y por eso
   este no los copia: se parece a ellos en la FORMA (misma posicion, misma
   pastilla, mismo gesto) que es lo que hace que se lean como la misma familia,
   y se distingue en el color, que es lo que hace que no se confundan cuando
   alguien tiene dos cosas cerca.

   La unica excepcion a "cero degradados" esta abajo del todo, en el metal de
   las dos rarezas cosmicas, y lleva su propia explicacion. */

/* El boton de pescar. Azul agua plano, para que se distinga del de la puerta
   (madera) y del de cuidar (azul cielo con degradado). */

/* La cinta de abajo: el aviso y la pregunta. No tapa el corral a proposito
   (ver el comentario de ui/pescaPanel.js). */
.pesca-cinta {
  position: fixed;
  left: 50%; transform: translateX(-50%);
  bottom: calc(1rem + var(--safe-bottom));
  z-index: 40;
  width: min(30rem, calc(100vw - 1.6rem));
  display: flex; flex-direction: column; align-items: center; gap: .5rem;
  pointer-events: none;
}
.pesca-cinta > * { pointer-events: auto; }

/* ---- El mordisco ------------------------------------------------------- */

.pesca-aviso {
  display: flex; flex-direction: column; align-items: center; gap: .1rem;
  padding: .6rem 1.2rem;
  background: rgba(20, 38, 28, .82);
  border: 2px solid #4f9a5e;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, .4);
  text-align: center;
  animation: pescaEntra .3s ease;
}
/* Cuando sale la pregunta, el aviso se encoge: sigue estando -para poder mirar
   que pez te juegas- pero deja de ser lo importante. */
.pesca-aviso.pesca-arriba { padding: .35rem 1rem; }
.pesca-aviso.pesca-arriba .pesca-grito { display: none; }

.pesca-grito {
  margin: 0;
  color: #fffdf8;
  font-size: 1rem; font-weight: 800; letter-spacing: .02em;
}
.pesca-pez {
  font-size: 1.35rem; font-weight: 900; letter-spacing: .01em;
  color: var(--tono);
}
/* La rareza, debajo del nombre.

   Va en CREMA y no en el color de la rareza, que era lo primero que se probo y
   no se leia: un "COSMICO ULTRAX" en dorado oscuro sobre un fondo verde muy
   oscuro son dos tonos con casi el mismo brillo, y a .72rem eso no es texto, es
   una mancha. El color ya lo lleva el nombre, que es el que tiene que cantar;
   esta linea solo tiene que poder LEERSE. */
.pesca-rareza {
  display: flex; align-items: baseline; gap: .45rem;
  font-size: .72rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase;
  color: #cdbfa3;
}
/* El peso, en el color del pez: es lo segundo que se mira despues del nombre. */
.pesca-kg {
  color: var(--tono);
  font-size: .92rem; font-weight: 900; letter-spacing: .01em;
  text-transform: none;
}

/* Del ultra epico para arriba, el nombre lleva luz detras. */
.pesca-luz, .pesca-metal {
  text-shadow: 0 0 10px var(--tono), 0 0 22px var(--tono);
}

/* Y los dos cosmicos, ademas, METAL.

   Es el unico degradado de toda la interfaz y lleva PARADAS DURAS: no es una
   rampa suave de un color a otro, son bandas planas que cruzan el texto. Asi
   hay reflejo -sin el no es metal, es un color fuerte- sin romper la regla de
   los colores planos. Con una rampa suave el nombre se lee como plastico, que
   es exactamente lo contrario de lo que Hansel pidio. */
.pesca-metal {
  background-image: repeating-linear-gradient(
    100deg,
    var(--tono) 0 14px,
    var(--reflejo) 14px 22px,
    var(--tono) 22px 40px
  );
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: pescaMetal 2.4s linear infinite;
}
@keyframes pescaMetal {
  from { background-position: 0 0; }
  to   { background-position: 220% 0; }
}

/* ---- La pregunta ------------------------------------------------------- */

.pesca-pregunta {
  width: 100%;
  padding: .75rem .8rem .6rem;
  background: rgba(20, 38, 28, .94);
  border: 2px solid #6bb56e;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, .4);
  animation: pescaEntra .25s ease;
}
.pesca-enunciado {
  margin: 0 0 .6rem;
  color: #f7f2e8;
  font-size: .95rem; font-weight: 700; line-height: 1.3;
}
.pesca-opciones { display: flex; flex-direction: column; gap: .35rem; }

.pesca-opcion {
  display: flex; align-items: center; gap: .55rem;
  /* Para que los brillitos de acertar se cuelguen de el. Se salen por fuera a
     proposito: no hay `overflow: hidden`, porque media estrella cortada en
     recto por el borde del boton se lee como un fallo de dibujo. */
  position: relative;
  width: 100%;
  padding: .5rem .6rem;
  background: #1d3a2a;
  border: 2px solid #4f9a5e;
  color: #f7f2e8;
  font-family: inherit; font-size: .9rem; font-weight: 600; text-align: left;
  cursor: pointer;
}
/* Nada de "hover levantita": lo que cambia es el borde y el fondo, que se
   asienta. Es lo mismo que hace un boton fisico. */
.pesca-opcion:hover:enabled { background: #244833; border-color: #6bb56e; }
.pesca-opcion:active:enabled { background: #16301f; }
.pesca-opcion[disabled] { cursor: default; }

.pesca-letra {
  flex: none;
  width: 1.45rem; height: 1.45rem;
  display: grid; place-items: center;
  background: #4f9a5e; color: #14261c;
  font-size: .8rem; font-weight: 900;
}
.pesca-texto { flex: 1; }

.pesca-opcion.pesca-buena { border-color: #8ecb7e; background: #244833; }
.pesca-opcion.pesca-buena .pesca-letra { background: #8ecb7e; }
.pesca-opcion.pesca-mala { border-color: #c44a18; }
.pesca-opcion.pesca-mala .pesca-letra { background: #c44a18; color: #f7f2e8; }

/* ---- Los brillitos de acertar ------------------------------------------

   Seis estrellas de cuatro puntas alrededor de la respuesta buena, de tamanos
   distintos y desfasadas. El reparto y el porque estan en ui/pescaPanel.js.

   La forma es un `clip-path` de ocho puntos con los lados RECTOS. Una estrella
   de lados curvos es la de cualquier libreria de iconos; con aristas es del
   mismo mundo que el corral, que esta dibujado a pixel.

   Los tres colores salen de la familia calida de PALETTE -crema, oro claro y
   oro- y son PLANOS: ni un degradado, ni una sombra difuminada. El brillo lo
   hace el contraste contra el verde oscuro del cuadro, no un halo.

   `pointer-events: none` porque el boton sigue debajo: una estrella que se
   coma un toque seria un premio que impide seguir jugando. */
.pesca-chispa {
  position: absolute;
  display: block;
  background: #ffe9a3;
  /* Los 38/62 son el grosor del brazo: mas juntos y la estrella es un hilo que
     no se ve a este tamano; mas separados deja de ser un destello y se
     convierte en un rombo. */
  clip-path: polygon(
    50% 0%, 62% 38%, 100% 50%, 62% 62%,
    50% 100%, 38% 62%, 0% 50%, 38% 38%
  );
  transform: scale(0);
  opacity: 0;
  pointer-events: none;
  animation: pescaChispa .7s steps(1, end) forwards;
}
/* Dos de las seis en oro y una en crema puro: con las seis del mismo color el
   puñado se lee como una sola forma recortada.

   `nth-of-type` y no `nth-child`: dentro del boton hay antes dos `span` (la
   letra y el texto), asi que contando hijos habria que empezar en el tercero y
   ese numero dejaria de ser verdad el dia que el boton tuviera una pieza mas.
   Contando `<i>`, las estrellas se numeran solas. */
.pesca-chispa:nth-of-type(2) { background: #ffd977; }
.pesca-chispa:nth-of-type(4) { background: #f9a825; }
.pesca-chispa:nth-of-type(6) { background: #fffdf8; }

/* Aparece, crece y se va. En ESCALONES, no en rampa: `steps(1, end)` hace que
   la estrella salte de un tamano al siguiente en vez de deslizarse entre ellos,
   que es como se mueve todo lo demas del juego —los sprites de la oveja van a
   diez o doce dibujos por segundo, no a sesenta—. Una estrella que crece suave
   al lado de una oveja que va a saltitos canta enseguida. */
@keyframes pescaChispa {
  0%   { transform: scale(0);   opacity: 0; }
  18%  { transform: scale(1.1); opacity: 1; }
  55%  { transform: scale(.75); opacity: 1; }
  85%  { transform: scale(.35); opacity: 1; }
  100% { transform: scale(0);   opacity: 0; }
}

/* El reloj de los 18 segundos. Lo mueve el navegador solo: JavaScript unicamente
   le dice cuanto dura. */
.pesca-barra {
  margin-top: .55rem;
  height: 5px;
  background: #16301f;
  border: 1px solid #3d7a4f;
}
.pesca-barra-dentro {
  display: block; height: 100%; width: 100%;
  background: #6bb56e;
  transform-origin: left center;
}
.pesca-barra-dentro.pesca-corriendo {
  animation: pescaReloj var(--duracion) linear forwards;
}
/* Los ultimos cinco segundos. No parpadea -parpadear mete prisa y encima
   distrae de leer- : cambia de color y ya. */
.pesca-barra-dentro.pesca-poco { background: #f26b1d; }
@keyframes pescaReloj {
  from { transform: scaleX(1); }
  to   { transform: scaleX(0); }
}

.pesca-veredicto {
  margin: 0;
  padding: .45rem .9rem;
  background: rgba(20, 38, 28, .94);
  border: 2px solid currentColor;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, .4);
  font-size: .92rem; font-weight: 800;
  animation: pescaEntra .22s ease;
}
.pesca-veredicto.bien { color: #8ecb7e; }
.pesca-veredicto.mal { color: #f19bb0; }

@keyframes pescaEntra {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* =========================================================================
   EL ALBUM DE PECES
   =========================================================================

   Paleta de CELESTES, que la pidio Hansel y ademas es la unica que tiene
   sentido aqui: el album es lo que sacas del lago. Los cinco tonos salen
   seguidos de la familia de agua de PALETTE (los mismos que pintan el lago del
   corral), mas un azul de tinta para el fondo — que hace aqui el mismo papel
   que el verde oscuro hace en los paneles del prado.

   Colores planos, bordes con presencia y sombras DURAS, como todo lo demas.
   El unico degradado es el metal de los dos cosmicos, y esta explicado donde
   aparece. */
.pz-panel {
  --tinta: #14283a;
  --caja: #1e3f5a;
  --linea: #2b5d8a;
  --clara: #3f9fd8;
  --brillo: #6fc3e8;
  --espuma: #b0e2f5;
  --crema: #f7f2e8;

  display: flex; flex-direction: column; gap: .55rem;
}

/* ---- La cabecera ------------------------------------------------------- */

.pz-resumen {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0 .8rem;
  align-items: center;
  padding: .8rem .9rem .7rem;
  background: var(--caja);
  border: 2px solid var(--clara);
  box-shadow: 4px 4px 0 var(--tinta);
}
/* El numero grande es el unico tamano de letra que se sale del resto, y esta
   asi porque es LA cifra del album: cuantas especies llevas. */
.pz-marcador { color: var(--espuma); font-weight: 900; line-height: 1; }
.pz-marcador strong { font-size: 2.4rem; }
.pz-marcador span { font-size: 1rem; color: var(--brillo); }

.pz-resumen-linea { margin: 0; color: var(--crema); font-size: .92rem; font-weight: 700; }
.pz-resumen-sub { margin: .15rem 0 0; color: var(--brillo); font-size: .78rem; }

.pz-barra {
  grid-column: 1 / -1;
  margin-top: .6rem;
  height: 6px;
  background: var(--tinta);
  border: 1px solid var(--linea);
}
.pz-barra i { display: block; height: 100%; background: var(--brillo); }

/* ---- Un escalon -------------------------------------------------------- */

.pz-escalon { display: flex; flex-direction: column; }

.pz-banda {
  display: flex; align-items: center; gap: .5rem;
  padding: .42rem .6rem;
  background: var(--caja);
  border: 2px solid var(--linea);
  border-bottom: 0;
  color: var(--crema);
  font-size: .85rem; font-weight: 800;
}
/* Un escalon COMPLETO se marca con su propio color en el borde, no con un
   icono: es lo unico de la lista que tiene que verse bajando deprisa. */
.pz-completo .pz-banda,
.pz-completo .pz-rejilla { border-color: var(--tono); }

.pz-punto { flex: none; width: .75rem; height: .75rem; background: var(--tono); }
.pz-titulo { flex: none; }
.pz-raro { flex: 1; color: var(--brillo); font-size: .7rem; font-weight: 600; }
.pz-cuenta { flex: none; color: var(--espuma); font-size: .82rem; }

.pz-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(6.2rem, 1fr));
  gap: .3rem;
  padding: .35rem;
  background: var(--tinta);
  border: 2px solid var(--linea);
}

/* ---- Una casilla ------------------------------------------------------- */

.pz-casilla {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-end;
  gap: .1rem;
  padding: .35rem .25rem .3rem;
  min-height: 6.4rem;
  background: var(--caja);
  border: 2px solid var(--linea);
  font-family: inherit;
}

/* La que falta: una interrogacion y nada mas. Ni nombre ni silueta — los dos
   gastarian a medias la sorpresa del mordisco. */
.pz-cerrada { justify-content: center; }
.pz-interrogacion {
  color: var(--linea);
  font-size: 2rem; font-weight: 900;
}

.pz-abierta { border-color: var(--tono); cursor: pointer; text-align: center; }
/* Nada de "hover levantita": lo que cambia es el fondo, que se asienta. */
.pz-abierta:hover { background: var(--linea); }
.pz-abierta:active { background: var(--tinta); }

.pz-img {
  width: 100%;
  height: 3.2rem;
  object-fit: contain;
  /* Son pixel art: al escalarlos hay que dejar el escalon, no difuminarlo. */
  image-rendering: pixelated;
}
.pz-nombre {
  color: var(--crema);
  font-size: .66rem; font-weight: 700; line-height: 1.1;
  /* Los nombres que puso Hansel a mano son de una sola palabra y muy largos
     (`CalamardoFishGuapo`), asi que no tienen por donde partirse solos y se
     salen de la casilla. Se les deja partir por cualquier letra: un nombre
     cortado en dos lineas se lee, y uno que se sale por los lados no. */
  overflow-wrap: anywhere;
}
.pz-kg { color: var(--espuma); font-size: .72rem; font-weight: 900; }
/* Cuantas veces lo has pescado, arriba a la derecha.

   Va anclado a la esquina y no en la fila del peso a proposito: el peso es un
   dato del pez y el contador es un dato TUYO, y mezclarlos en la misma linea
   hacia leer "1,14 kg x5" como si el pez pesara cinco veces eso. */
.pz-veces {
  position: absolute;
  top: 0; right: 0;
  padding: 0 .22rem;
  background: var(--tono); color: #14283a;
  font-size: .62rem; font-weight: 900;
}

/* Aqui vivia la pantalla de la oveja levantando el pez dentro del album: un
   lienzo con el agua de fondo, la ficha del pez y un boton de volver.

   Se fue el 11 de septiembre de 2026 y no por sobrar espacio. La postura le
   gusto a Hansel; el SITIO no: pulsar una casilla ya no abre nada, manda a tu
   oveja levantar el pez EN EL CORRAL y cierra el album (el porque, con sus
   palabras, esta en ui/pecesPanel.js). Una ventana que tapa el prado es lo
   contrario de ensenarle un pez a alguien.

   Si algun dia vuelve a hacer falta un visor dentro del album, esto estaba en
   `.pz-alzada`, `.pz-volver`, `.pz-escenario` y `.pz-ficha*`. */

/* ---- Los tres brillos, compartidos con el aviso del mordisco ----------- */

.pz-plano { color: var(--tono); }
.pz-luz { color: var(--tono); text-shadow: 0 0 8px var(--tono); }
/* El metal: bandas planas que cruzan el texto. Es el unico degradado de la
   interfaz y lleva paradas DURAS por eso mismo (ver `.pesca-metal`). */
.pz-metal {
  background-image: repeating-linear-gradient(
    100deg,
    var(--tono) 0 14px,
    var(--reflejo) 14px 22px,
    var(--tono) 22px 40px
  );
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: pescaMetal 2.4s linear infinite;
}
/* En una casilla, el metal solo tine el NOMBRE; el borde ya lleva el tono. */
.pz-casilla.pz-metal { color: inherit; background-image: none; animation: none; }
.pz-casilla.pz-metal .pz-nombre {
  background-image: repeating-linear-gradient(
    100deg,
    var(--tono) 0 10px,
    var(--reflejo) 10px 16px,
    var(--tono) 16px 28px
  );
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: pescaMetal 2.4s linear infinite;
}
.pz-casilla.pz-luz .pz-nombre { color: var(--tono); }

/*
 * Sin animaciones para quien las haya desactivado en su sistema.
 * Es un ajuste de accesibilidad real: hay gente a la que el movimiento
 * constante le produce mareo.
 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* =================================================================== decorar

   EL MODO DECORAR (ver ui/decorMode.js)

   Es un modo, no una ventana: el HUD se aparta, el cuarto se queda a la vista y
   abajo sube una bandeja con el catalogo, como el modo construir de los Sims.
   Sigue las reglas de siempre (colores de PALETTE en `--ms-*`, sombra dura sin
   difuminar, esquinas rectas, los cuatro tamanos de letra) y le suma dos cosas
   de videojuego: la franja oscura de cabecera con el saldo siempre a la vista,
   y fichas grandes con el mueble DIBUJADO, que es lo que se elige con los ojos.
   ========================================================================= */

/* El boton de entrar, debajo del cerrojo. Solo sale en tu propia casa. */

/* Decorando, fuera todo el HUD: el cuarto y la bandeja, nada mas. */
.game-screen.decor-mode .hud { display: none; }

.build { position: absolute; inset: 0; z-index: 30; pointer-events: none; }
.build-markers { position: absolute; inset: 0; overflow: hidden; }

/* ------------------------------------------------ los marcos sobre el cuarto */

.build-marker {
  position: absolute; left: 0; top: 0;
  pointer-events: auto; cursor: pointer;
  padding: 0;
  background: transparent;
  border: 2px dashed var(--ms-gold-lt);
  transition: opacity .2s, background-color .15s;
}
.build-marker:hover { background: rgba(255, 217, 119, .18); border-style: solid; }
.build-marker:focus-visible { outline: 3px solid var(--ms-paper); outline-offset: 2px; }

/* El nombre del sitio, colgado debajo del marco: se ve al pasar por encima. */
.build-marker-tag {
  position: absolute; left: 50%; top: calc(100% + 6px);
  transform: translateX(-50%);
  padding: .2rem .5rem;
  background: var(--ms-ink); color: var(--ms-paper);
  font-size: var(--ms-small); font-weight: 700; white-space: nowrap;
  opacity: 0; transition: opacity .15s;
  pointer-events: none;
}
.build-marker:hover .build-marker-tag { opacity: 1; }

/* El sitio que se decora: marco entero, en oro, con un latido de dos pasos
   (steps) como parpadea un cursor de juego, no un brillo que se difumina. */
.build-marker.is-on {
  border: 3px solid var(--ms-gold);
  box-shadow: 0 0 0 2px var(--ms-ink), inset 0 0 0 2px var(--ms-ink);
  background: transparent;
  animation: buildPulse 1.2s steps(2) infinite;
}
.build-marker.is-on .build-marker-tag { opacity: 1; }
/* Los demas se van del todo: `visibility` espera a que acabe el fundido. */
.build-marker.is-dim { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .2s, visibility 0s .2s; }
@keyframes buildPulse {
  from { border-color: var(--ms-gold); }
  to   { border-color: var(--ms-paper); }
}

/* ------------------------------------------------------------------ bandeja */

.build-tray {
  position: absolute; left: 0; right: 0; bottom: 0;
  pointer-events: auto;
  background: var(--ms-paper);
  border-top: 3px solid var(--ms-ink);
  padding-bottom: var(--safe-bottom, 0px);
  transform: translateY(100%);
  transition: transform .26s cubic-bezier(.2, .8, .2, 1);
  color: var(--ms-ink);
}
.build.is-in .build-tray { transform: none; }

/* La cabecera: franja oscura con el sitio, el saldo y la salida. */
.build-head {
  display: flex; align-items: center; gap: .6rem;
  padding: .5rem .75rem;
  background: var(--ms-green-dk);
  color: var(--ms-paper);
  border-bottom: 3px solid var(--ms-gold);
}
.build-title { display: flex; flex-direction: column; min-width: 0; flex: 1; line-height: 1.15; }
.build-title small {
  font-size: var(--ms-small); font-weight: 800;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--ms-gold-lt);
}
.build-title strong {
  font-size: var(--ms-lead); font-weight: 900;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.build-back {
  flex: none; width: 2.25rem; height: 2.25rem;
  display: grid; place-items: center;
  background: var(--ms-paper); border: 2px solid var(--ms-ink);
  box-shadow: 2px 2px 0 var(--ms-ink);
  cursor: pointer; padding: 0;
}
.build-back:active { transform: translate(2px, 2px); box-shadow: none; }
/* La flecha, hecha con dos bordes: sin emoji ni fuente de iconos. */
.build-chevron {
  width: .6rem; height: .6rem;
  border-left: 3px solid var(--ms-ink); border-bottom: 3px solid var(--ms-ink);
  transform: translateX(2px) rotate(45deg);
}

.build-coins {
  flex: none; display: flex; align-items: center; gap: .4rem;
  padding: .3rem .65rem;
  background: var(--ms-ink); border: 2px solid var(--ms-gold);
  font-size: var(--ms-body); font-weight: 900; color: var(--ms-gold-lt);
  font-variant-numeric: tabular-nums;
}

.build-done {
  flex: none;
  padding: .45rem 1rem;
  background: var(--ms-gold); color: var(--ms-ink);
  border: 2px solid var(--ms-ink); box-shadow: 3px 3px 0 var(--ms-ink);
  font: inherit; font-size: var(--ms-body); font-weight: 900;
  cursor: pointer;
}
.build-done:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ms-ink); }

/* La moneda: un circulo de oro plano con su filo, dibujado y no prestado. */
.build-coin {
  display: inline-block; flex: none;
  width: .95em; height: .95em; border-radius: 50%;
  background: var(--ms-gold);
  border: 2px solid var(--ms-ink);
  box-shadow: inset -2px -2px 0 rgba(26, 20, 18, .28);
  vertical-align: -.12em;
}

/* ------------------------------------------------------------------- fichas */

.build-strip {
  display: flex; gap: .7rem;
  overflow-x: auto; overscroll-behavior-x: contain;
  padding: .8rem .75rem .9rem;
  scroll-snap-type: x proximity;
  scrollbar-width: thin; scrollbar-color: var(--ms-line) transparent;
}

.build-tile {
  position: relative;
  flex: 0 0 auto; width: 7.5rem;
  display: flex; flex-direction: column; align-items: center; gap: .2rem;
  padding: .45rem .4rem .55rem;
  background: var(--ms-paper);
  border: 2px solid var(--ms-ink);
  box-shadow: 3px 3px 0 var(--ms-ink);
  font: inherit; color: inherit; text-align: center;
  cursor: pointer;
  scroll-snap-align: start;
  transition: background-color .12s;
}
.build-tile:hover { background: var(--ms-paper-2); }
.build-tile:active { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ms-ink); }
.build-tile:focus-visible { outline: 3px solid var(--ms-gold); outline-offset: 2px; }
/* La elegida: marco de oro por dentro. Es lo que esta puesto en el cuarto AHORA. */
.build-tile.is-on {
  background: var(--ms-gold-lt);
  box-shadow: inset 0 0 0 3px var(--ms-gold), 3px 3px 0 var(--ms-ink);
}

.build-thumb-wrap {
  position: relative;
  display: grid; place-items: center;
  width: 5.25rem; height: 5.25rem;
  background: var(--ms-paper-2);
  border: 1px solid var(--ms-line);
}
.build-tile.is-on .build-thumb-wrap { background: var(--ms-paper); }
.build-thumb { width: 100%; height: 100%; image-rendering: pixelated; }
.build-thumb-fish {
  position: absolute; left: 50%; top: 46%;
  width: 62%; transform: translate(-50%, -50%);
  image-rendering: pixelated;
}
/* Un sitio vacio y la opcion "Nada": sin dibujo que ensenar. */
.build-plus, .build-none { border-style: dashed; border-width: 2px; }
.build-plus::before, .build-none::before {
  font-size: var(--ms-display); font-weight: 900; color: var(--ms-line); line-height: 1;
}
.build-plus::before { content: '+'; }
.build-none::before { content: '\2013'; }

.build-tile-name {
  font-size: var(--ms-small); font-weight: 800; line-height: 1.2;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  min-height: 2.4em;
}
.build-tile-sub { font-size: var(--ms-small); color: var(--ms-ink-soft); }

.build-price {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: var(--ms-small); font-weight: 900;
  font-variant-numeric: tabular-nums;
}
.build-price.is-short { color: var(--ms-fire); }

.build-badge {
  position: absolute; top: .3rem; left: .3rem; z-index: 1;
  padding: .1rem .35rem;
  background: var(--ms-green); color: var(--ms-paper);
  border: 1px solid var(--ms-ink);
  font-size: var(--ms-small); font-weight: 800;
}
.build-badge.is-here { background: var(--ms-ink); color: var(--ms-gold-lt); }

/* -------------------------------------------------------- la barra de decidir */

.build-confirm {
  display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: .6rem;
  max-height: 0; overflow: hidden;
  padding: 0 .75rem;
  background: var(--ms-paper-2);
  transition: max-height .2s ease-out, padding .2s ease-out;
}
.build-confirm.is-open {
  max-height: 6rem;
  padding: .6rem .75rem;
  border-top: 2px solid var(--ms-ink);
}
.build-confirm.is-busy { opacity: .6; pointer-events: none; }
.build-confirm-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.build-confirm-text strong { font-size: var(--ms-body); font-weight: 900; }
.build-confirm-text small { font-size: var(--ms-small); color: var(--ms-ink-soft); }
.build-confirm-text small.is-short { color: var(--ms-fire); font-weight: 800; }

.build-btn {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .6rem 1rem;
  background: var(--ms-green); color: var(--ms-paper);
  border: 2px solid var(--ms-ink); box-shadow: 3px 3px 0 var(--ms-ink);
  font: inherit; font-size: var(--ms-body); font-weight: 900; white-space: nowrap;
  cursor: pointer;
}
.build-btn.is-buy { background: var(--ms-gold); color: var(--ms-ink); }
.build-btn.is-ghost { background: var(--ms-paper); color: var(--ms-ink); }
.build-btn:active:not(:disabled) { transform: translate(2px, 2px); box-shadow: 1px 1px 0 var(--ms-ink); }
.build-btn:disabled { opacity: .5; cursor: not-allowed; box-shadow: 3px 3px 0 var(--ms-line); }

/* En el movil la bandeja no puede comerse medio cuarto: fichas algo menores. */
@media (max-width: 560px) {
  .build-tile { width: 6.4rem; }
  .build-thumb-wrap { width: 4.5rem; height: 4.5rem; }
  .build-head { gap: .45rem; padding: .45rem .6rem; }
  .build-done { padding: .45rem .7rem; }
  .build-confirm { grid-template-columns: 1fr 1fr; }
  .build-confirm-text { grid-column: 1 / -1; }
  .build-btn { justify-content: center; }
  .build-confirm.is-open { max-height: 9rem; }
}

/* ============================================================ ranking semanal

   La cabecera de "Esta semana": tu puesto y tus puntos en grande, y cuando
   vuelve a cero. Colores planos de PALETTE y sombra dura, como las misiones.
   ========================================================================= */

.rank-scope {
  display: inline-flex; margin: .7rem 0 .2rem;
  border: 2px solid var(--ms-ink);
}
.rank-scope button {
  padding: .35rem .9rem;
  background: var(--ms-paper); color: var(--ms-ink);
  border: none; font: inherit; font-size: var(--ms-small); font-weight: 800;
  cursor: pointer;
}
.rank-scope button + button { border-left: 2px solid var(--ms-ink); }
.rank-scope button.on { background: var(--ms-green); color: var(--ms-paper); }

.week-head {
  display: grid; grid-template-columns: 1fr 1fr; gap: .6rem;
  margin: .6rem 0 .8rem; padding: .7rem .8rem;
  background: var(--ms-green-dk); color: var(--ms-paper);
  border: 2px solid var(--ms-ink); box-shadow: 3px 3px 0 var(--ms-ink);
}
.week-me { display: flex; flex-direction: column; line-height: 1.1; }
.week-me small {
  font-size: var(--ms-small); font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ms-gold-lt);
}
.week-me strong { font-size: var(--ms-display); font-weight: 900; font-variant-numeric: tabular-nums; }
.week-note { grid-column: 1 / -1; margin: 0; font-size: var(--ms-small); color: var(--ms-paper-2); }
.week-note b { color: var(--ms-gold-lt); }

/* Pestanas de carpeta, como las de las misiones. Van completas aqui porque no
   hay un `.tabs` general: cada pantalla repintada lleva las suyas. */
.rank-panel .tabs { display: flex; gap: 0; border-bottom: 2px solid var(--ms-ink); }
.rank-panel .tabs button {
  padding: .55rem 1.1rem;
  background: transparent; color: var(--ms-ink-soft);
  border: 2px solid transparent; border-bottom: none;
  font: inherit; font-size: var(--ms-body); font-weight: 800;
  cursor: pointer;
}
.rank-panel .tabs button.active {
  background: var(--ms-paper); color: var(--ms-ink);
  border-color: var(--ms-ink);
  margin-bottom: -2px; padding-bottom: calc(.55rem + 2px);
}

/* Las filas, a juego con la cabecera: esquinas rectas y sombra dura. Tu fila en
   oro claro, que se encuentra de un vistazo aunque vayas el doce. */
.rank-panel .rank-row {
  border-radius: 0;
  border: 2px solid var(--ms-ink);
  box-shadow: 2px 2px 0 var(--ms-ink);
  background: var(--ms-paper);
}
.rank-panel .rank-row.me { background: var(--ms-gold-lt); border-color: var(--ms-ink); }
.rank-panel .rank-lvl { color: var(--ms-green); }

/* =========================================================== carteles de accion

   Los botones de "estas al lado de algo" (ver ui/actionPlate.js): cruzar el
   porton, entrar a una casa, salir, reclamar un solar, cuidar y pescar abajo;
   el cerrojo y decorar arriba, en pequeno.

   Punto medio, que es lo que pidio Hansel. Antes eran pastillas con degradado,
   sombra borrosa y emoji ("se nota que es IA"); la segunda version se paso al
   otro lado, con linea de "donde estas", tecla E dibujada y ficha para el
   icono ("demasiado armado"). Se queda lo que hace que parezcan del juego -el
   icono pintado a mano, el contorno de tinta y la sombra dura- y nada mas.
   ========================================================================= */

.act {
  --act-bg: var(--ms-green);
  --act-fg: var(--ms-paper);
  position: absolute;
  display: flex; align-items: center; gap: .5rem;
  padding: .45rem .85rem .45rem .6rem;
  background: var(--act-bg); color: var(--act-fg);
  border: 2px solid var(--ms-ink);
  border-radius: 0;
  box-shadow: 3px 3px 0 var(--ms-ink);
  font-family: inherit; text-align: left;
  cursor: pointer;
  animation: actIn .2s ease-out;
}
.act.hidden { display: none; }
/* Pulsar lo hunde contra su sombra: el mismo gesto que el resto del juego. */
.act:active:not(:disabled) { translate: 2px 2px; box-shadow: 1px 1px 0 var(--ms-ink); }
.act:disabled, .act.blocked { opacity: .55; cursor: not-allowed; }
.act:focus-visible { outline: 3px solid var(--ms-gold-lt); outline-offset: 3px; }

/* Aparece subiendo un palmo. Va con `translate` (no `transform`) porque el
   centrado usa `transform` y las dos cosas no se pisan. */
@keyframes actIn {
  from { translate: 0 8px; opacity: 0; }
  to   { translate: 0 0; opacity: 1; }
}

/* El icono, suelto sobre el color. 24 px = dos pixeles por casilla de su
   rejilla de 12: en px y en multiplo de 12, o salen pixeles desiguales. */
.act-icon { flex: none; display: block; line-height: 0; }
.act-icon svg { width: 24px; height: 24px; display: block; }
/* Sobre los carteles oscuros el contorno de tinta del icono se funde con el
   fondo (el porton de madera sobre madera oscura casi no se veia). Un filo
   claro de UN pixel por los cuatro lados, sin difuminar, lo despega. */
.act-wood .act-icon svg, .act-deep .act-icon svg {
  filter: drop-shadow(1px 0 0 var(--ms-paper-2)) drop-shadow(-1px 0 0 var(--ms-paper-2))
          drop-shadow(0 1px 0 var(--ms-paper-2)) drop-shadow(0 -1px 0 var(--ms-paper-2));
}
.act .label { font-size: var(--ms-body); font-weight: 900; white-space: nowrap; }

/* El precio de un solar: moneda dibujada y el numero, en su chapita oscura. */
.act-price {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .05rem .4rem;
  background: var(--ms-ink); color: var(--ms-gold-lt);
  font-size: var(--ms-small); font-weight: 900; font-variant-numeric: tabular-nums;
}
.act-price.hidden { display: none; }
.act-coin {
  width: .8rem; height: .8rem; border-radius: 50%;
  background: var(--ms-gold); border: 2px solid var(--ms-gold-lt);
}

/* ---- los colores, por lo que hacen */
/* Madera OSCURA: la clara se perdia encima del suelo de tablas de las casas. */
.act-wood  { --act-bg: #4a2f18; --act-fg: var(--ms-paper); }
.act-gold  { --act-bg: var(--ms-gold); --act-fg: var(--ms-ink); }
.act-water { --act-bg: #3f9fd8; --act-fg: var(--ms-ink); }
.act-deep  { --act-bg: #2b5d8a; --act-fg: var(--ms-paper); }

/* ---- donde va cada uno */

/* Los del momento, abajo al centro: el hueco que dejan las dos manos puestas,
   y por encima de la barra de escribir (ver `.chat-box`). */
.care-fab, .door-fab, .pesca-fab, .valla-fab {
  left: 50%; transform: translateX(-50%);
  bottom: calc(4.6rem + var(--safe-bottom));
}

/* Los interruptores del cuarto, arriba y en pequeno, uno a cada lado del
   centro: no son acciones del momento y no deben estar bajo el pulgar. */
.act-sm { gap: .4rem; padding: .3rem .65rem .3rem .45rem; }
.act-sm .label { font-size: var(--ms-small); }
.latch-fab { top: calc(4.4rem + var(--safe-top, 0px)); right: calc(50% + 5px); }
.decor-fab { top: calc(4.4rem + var(--safe-top, 0px)); left: calc(50% + 5px); }

/* ================================================================ misiones: ventana compacta

   26-sep-2026. Hansel: "se ve grande y no se entiende; la ventana de misiones
   tiene que ser mas pequena en celular, no de pantalla completa". Lo que lo
   hacia ilegible, medido en las capturas (preview/misiones-antes/):
    - una sola tarjeta (el formulario del versiculo) llenaba la pantalla;
    - cada tarjeta repetia etiqueta "Pendiente", explicacion, nota y un boton
      verde a lo ancho: todo pesaba lo mismo y no habia por donde empezar;
    - emoji del sistema en cada mision y en la racha.

   Ahora: ventana con margen (se ve el corral), una FILA por mision (dibujo,
   titulo, fichas de recompensa, un verbo), la racha y el contador en una
   franja arriba, y lo que se consulta (versiculo, metas) plegado. Mismo idioma
   que el 25-ago: colores de PALETTE, sombra dura sin blur, esquinas a cero, y
   las cosas se HUNDEN al pulsarlas.
   ========================================================================= */

/* Los cuatro tamanos del panel. Se redefinen SOLO dentro de esta ventana: los
   de `:root` los usan tambien el buzon y la bandeja del pastor. */
.modal-missions {
  --ms-display: 1.5rem;
  --ms-lead: 1rem;
  --ms-body: .875rem;
  --ms-small: .75rem;
}

/* ---- el marco: la ventana entera al estilo del panel, no el verde con degradado */
.modal-backdrop.modal-missions {
  /* Tinta (#1a1412) al 45 %, y sin desenfoque: la ventana ya no tapa la
     pantalla y lo que se ve alrededor tiene que ser el corral, no una mancha. */
  background: rgba(26, 20, 18, .45);
  backdrop-filter: none;
}
.modal-missions .modal {
  width: min(720px, 100%);
  border-radius: 0;
  border: 2px solid var(--ms-ink);
  box-shadow: 4px 4px 0 var(--ms-ink);
  background: var(--ms-paper);
}
.modal-missions .modal-head {
  background: var(--ms-green-dk);
  box-shadow: none;
  border-bottom: 2px solid var(--ms-ink);
  padding: .45rem .5rem .45rem .85rem;
}
.modal-missions .modal-head::before { display: none; }
.modal-missions .modal-head h2 {
  font-size: var(--ms-body); font-weight: 800;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ms-gold-lt);
}
.modal-missions .modal-close {
  width: 30px; height: 30px; min-width: 30px; min-height: 30px;
  border-radius: 0; background: var(--ms-green);
  border: 2px solid var(--ms-ink); box-shadow: 2px 2px 0 var(--ms-ink);
  color: var(--ms-paper); font-size: .9rem;
}
.modal-missions .modal-close:active { transform: translate(2px, 2px); box-shadow: none; }
.modal-missions .modal-body { padding: .6rem .75rem .8rem; }

/* El levantita de `.btn:hover` se colaba por debajo del repintado. */
.mission-panel .btn:hover:not(:disabled) {
  transform: none; filter: none; box-shadow: 3px 3px 0 var(--ms-ink);
}
.mission-panel .tabs button { padding: .35rem .8rem; font-size: var(--ms-body); font-weight: 800; }
.mission-panel .tabs button.active { padding-bottom: calc(.35rem + 2px); }

/* Los dibujos de pixelIcons.js: cuadrados y a multiplo de 12 cuando se puede. */
.px-ico { display: inline-grid; place-items: center; flex: none; width: 16px; height: 16px; }
.px-ico svg { width: 100%; height: 100%; display: block; }

/* ---- la franja de arriba: cuantas llevas y la racha, lado a lado */
.ms-hud {
  display: grid; gap: .5rem;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  margin: .6rem 0 .5rem;
}
.mission-panel .daily-header { margin: 0; padding: .4rem .6rem; gap: .6rem; }
.mission-panel .daily-count { width: 42px; height: 42px; }
.mission-panel .daily-count b { font-size: var(--ms-display); }
.mission-panel .daily-meta { flex: 1; min-width: 0; }
.mission-panel .daily-meta strong { font-size: var(--ms-body); font-weight: 800; }
.mission-panel .daily-meta small { display: block; font-size: var(--ms-small); }
.mission-panel .progress-strip { margin: .25rem 0; gap: 3px; }
.mission-panel .progress-strip i { height: 6px; border-color: var(--ms-ink); }

/* La racha. Canto de color a la izquierda: gris sin empezar, oro viva, fuego
   en peligro. El fondo solo cambia en peligro, que es la cara que hace volver. */
.mission-panel .streak-banner {
  display: flex; align-items: center; gap: .55rem;
  margin: 0; padding: .4rem .6rem;
  background: var(--ms-paper);
  border: 2px solid var(--ms-ink); border-left: 6px solid var(--ms-line);
  border-radius: 0; box-shadow: 3px 3px 0 var(--ms-ink);
  color: var(--ms-ink);
}
.mission-panel .streak-banner.on { border-left-color: var(--ms-gold); }
/* #f7e4da: el mismo tinte de fuego que ya usa la nota retirada del pastor. */
.mission-panel .streak-banner.risk { border-left-color: var(--ms-fire); background: #f7e4da; }
.mission-panel .streak-fire { width: 24px; height: 24px; }
.streak-txt { flex: 1; min-width: 0; }
.mission-panel .streak-banner strong { display: block; font-size: var(--ms-body); font-weight: 800; }
.mission-panel .streak-banner.risk strong { color: var(--ms-fire); }
.streak-line { display: flex; align-items: center; gap: .4rem; margin-top: .15rem; }
.mission-panel .streak-banner small { font-size: var(--ms-small); color: var(--ms-ink-soft); }
.streak-pips { display: flex; gap: 2px; flex: none; }
.streak-pips i { width: 9px; height: 9px; background: var(--ms-paper-2); border: 1px solid var(--ms-ink); }
.streak-pips i.on { background: var(--ms-gold); }
.mission-panel .streak-banner .streak-shields {
  display: inline-flex; align-items: center; gap: .2rem; margin-left: auto;
  font-size: var(--ms-small); font-weight: 800; color: var(--ms-ink);
  background: none; border: 0; padding: 0; border-radius: 0;
}
.mission-panel .streak-banner .streak-best {
  margin-left: .3rem; font-size: var(--ms-small); font-weight: 700;
  color: var(--ms-ink-soft); background: none; padding: 0; border-radius: 0;
}

/* ---- el versiculo, cerrado, es una linea */
.mission-panel .verse-card { padding: .5rem .75rem; margin-bottom: .55rem; }
.mission-panel .verse-card[open] { padding-bottom: .75rem; }
.mission-panel .verse-card:not([open]) > .verse-head { margin-bottom: 0; }

/* ---- la lista: una fila por mision */
.mission-list {
  display: grid; gap: .45rem;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
}
.mission-panel .ms-row {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center;
  padding: 0; margin: 0;
  background: var(--ms-paper);
  border: 2px solid var(--ms-ink); border-left: 5px solid var(--ms-green);
  box-shadow: 2px 2px 0 var(--ms-ink);
}
/* Abierta, ocupa todo el ancho: el formulario necesita sitio para escribir. */
.mission-panel .ms-row.open { grid-column: 1 / -1; }
.mission-panel .ms-row:active { transform: none; box-shadow: 2px 2px 0 var(--ms-ink); }
.mission-panel .ms-row.ready { border-left-color: var(--ms-gold); background: #fff6dd; }
.mission-panel .ms-row.done { border-left-color: var(--ms-gold); background: var(--ms-paper-2); }
.mission-panel .ms-row.done .ms-title { color: var(--ms-ink-soft); }

.ms-main {
  display: flex; align-items: center; gap: .55rem; min-width: 0;
  padding: .4rem .3rem .4rem .5rem;
  background: none; border: 0; font: inherit; color: var(--ms-ink);
  text-align: left; cursor: pointer;
}
/* La flecha de "esto se abre", la misma que la del versiculo. */
.ms-main::after {
  content: ''; flex: none; margin-left: auto;
  width: .4rem; height: .4rem;
  border-right: 2px solid var(--ms-line); border-bottom: 2px solid var(--ms-line);
  transform: rotate(45deg) translate(-2px, -2px);
}
.ms-row.open .ms-main::after { transform: rotate(-135deg) translate(-2px, -2px); }
.mission-panel .ms-row .mission-icon { width: 24px; height: 24px; font-size: inherit; }
.mission-panel .ms-row.done .mission-icon { opacity: .6; }
.ms-txt { display: flex; flex-direction: column; gap: .12rem; min-width: 0; }
.ms-title {
  font-size: var(--ms-body); font-weight: 800; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ms-sub {
  display: flex; align-items: center; gap: .4rem; flex-wrap: wrap;
  font-size: var(--ms-small); font-weight: 700; color: var(--ms-ink-soft);
}
.ms-sub-ready { color: var(--ms-ink); }
.ms-sub-done .px-ico { width: 12px; height: 12px; }
.ms-dim { font-weight: 600; }
.ms-reward { display: inline-flex; gap: .45rem; }
.ms-chip { display: inline-flex; align-items: center; gap: .18rem; color: var(--ms-ink); }
.ms-chip .px-ico { width: 12px; height: 12px; }
.ms-chip b { font-weight: 800; }
.ms-row.done .ms-chip { color: var(--ms-ink-soft); }

.mission-panel .ms-row .mission-action { margin: 0; padding: 0 .5rem 0 .2rem; }
.mission-panel .ms-btn {
  min-width: 4.8rem; padding: .42rem .7rem;
  font-size: var(--ms-small); font-weight: 800; line-height: 1.1;
  box-shadow: 2px 2px 0 var(--ms-ink);
}
.mission-panel .ms-btn:hover:not(:disabled) { box-shadow: 2px 2px 0 var(--ms-ink); }
.mission-panel .ms-btn:active:not(:disabled) { transform: translate(2px, 2px); box-shadow: none; }
.mission-panel .ms-write { background: var(--ms-paper); color: var(--ms-ink); }

/* El reloj en marcha ocupa el sitio del boton; la barra corre por el pie. */
.mission-panel .ms-row .timer-value {
  display: inline-block; min-width: 4.8rem; text-align: center;
  font-size: var(--ms-body); font-weight: 800; font-variant-numeric: tabular-nums;
  color: var(--ms-gold-lt); background: var(--ms-green-dk);
  border: 2px solid var(--ms-ink); padding: .3rem .4rem;
}
.mission-panel .ms-row .timer-track {
  position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  border: 0; background: var(--ms-paper-2);
}

/* Lo que se abre al tocar la fila. */
.ms-more { display: none; grid-column: 1 / -1; padding: 0 .65rem .65rem; }
.ms-row.open .ms-more { display: block; }
.ms-prompt { margin: 0 0 .4rem; font-size: var(--ms-body); line-height: 1.4; color: var(--ms-ink); }
.mission-panel .ms-more .mission-note { margin: .35rem 0; padding: .3rem .5rem; font-size: var(--ms-small); }
.mission-panel .ms-more .mission-verse { margin: .35rem 0; }
.ms-form .field { margin: .45rem 0 0; }
.ms-form .field span { font-size: var(--ms-small); }
.ms-form textarea, .ms-form input { font-size: var(--ms-body); }
.mission-panel .ms-send { margin-top: .55rem; }
.mission-panel .ms-row .pastor-note { grid-column: 1 / -1; margin: 0 .5rem .5rem; padding: .45rem .55rem; }
.mission-panel .pn-icon { width: 20px; height: 20px; }

/* ---- lo del corral, plegado al final */
.ms-extras { display: grid; gap: .45rem; margin-top: .6rem; }
.mission-panel .ms-fold { margin: 0; padding: .45rem .65rem; box-shadow: 2px 2px 0 var(--ms-ink); }
.ms-fold > summary { list-style: none; cursor: pointer; }
.ms-fold > summary::-webkit-details-marker { display: none; }
.mission-panel .ms-fold .pg-head,
.mission-panel .ms-fold.bg-head,
.mission-panel .ms-fold > .bg-head { margin-bottom: 0; align-items: center; }
.mission-panel .ms-fold .pg-head strong,
.mission-panel .ms-fold .bg-head strong { font-size: var(--ms-body); }
.mission-panel .ms-fold .pg-count,
.mission-panel .ms-fold .bg-count { font-size: var(--ms-body); }
.mission-panel .ms-fold .pg-bar { height: 8px; margin-top: .3rem; }
.mission-panel .ms-fold:not([open]) .pg-head small,
.mission-panel .ms-fold:not([open]) .bg-head small { display: none; }
.mission-panel .ms-fold[open] > summary { margin-bottom: .4rem; }
.mission-panel .ms-fold .bg-notches { height: 14px; }
.mission-panel .ms-fold .pg-count::after,
.mission-panel .ms-fold .bg-count::after {
  content: ''; display: inline-block; margin-left: .45rem; vertical-align: middle;
  width: .4rem; height: .4rem;
  border-right: 2px solid var(--ms-ink-soft); border-bottom: 2px solid var(--ms-ink-soft);
  transform: rotate(45deg) translate(-2px, -2px);
}
.mission-panel .ms-fold[open] .pg-count::after,
.mission-panel .ms-fold[open] .bg-count::after { transform: rotate(-135deg) translate(-2px, -2px); }

/* ---- desafios del lider: la misma tarjeta, mas apretada */
.mission-panel .ms-weekly { padding: .55rem .7rem .65rem; }
.mission-panel .ms-weekly .card-head { gap: .5rem; margin-bottom: .25rem; }
.mission-panel .ms-weekly h3 { font-size: var(--ms-body); }
.mission-panel .ms-weekly p { font-size: var(--ms-body); margin: .2rem 0 .4rem; }
.mission-panel .ms-weekly .mission-icon { width: 20px; height: 20px; }
.mission-panel .ms-weekly + .ms-weekly { margin-top: .5rem; }
.mission-panel .due-note { display: inline-flex; align-items: center; gap: .3rem; }
.mission-panel .due-note .px-ico { width: 12px; height: 12px; }

/* El versiculo como `details`: la cabecera es lo que se toca para abrirlo. */
.verse-card > summary { list-style: none; cursor: pointer; }
.verse-card > summary::-webkit-details-marker { display: none; }
.verse-card > summary::after {
  content: '';
  flex: none; align-self: center;
  width: .5rem; height: .5rem; margin-left: .2rem;
  border-right: 2px solid var(--ms-gold-lt); border-bottom: 2px solid var(--ms-gold-lt);
  transform: rotate(45deg) translate(-2px, -2px);
}
.verse-card[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
/* Cerrado, la cita sale en la misma linea: se sabe que versiculo es sin abrirlo. */
.verse-peek { display: none; font-size: var(--ms-small); font-weight: 800; color: var(--ms-paper); }
.verse-card:not([open]) .verse-peek { display: inline; }

/* ---- telefono: estrecho de pie o bajo tumbado (misma condicion que `compact()`) */
@media (max-width: 560px), (max-height: 500px) {
  .modal-missions {
    --ms-display: 1.25rem;
    --ms-lead: .875rem;
    --ms-body: .8125rem;  /* 13 px */
    --ms-small: .75rem;   /* 12 px */
  }
  /* VENTANA, no pantalla entera: margen alrededor para que se vea el corral. */
  .modal-backdrop.modal-missions {
    padding: calc(10px + var(--safe-top)) 12px calc(10px + var(--safe-bottom));
  }
  .modal-missions .modal { max-height: 100%; }
  .modal-missions .modal-head { padding: .3rem .4rem .3rem .75rem; }
  .modal-missions .modal-close { width: 28px; height: 28px; min-width: 28px; min-height: 28px; }
  .modal-missions .modal-body { padding: .5rem .6rem .7rem; }
  .mission-panel .tabs button { padding: .3rem .7rem; }
  .mission-panel .tabs button.active { padding-bottom: calc(.3rem + 2px); }
  .ms-hud { margin: .5rem 0 .45rem; gap: .45rem; }
  .mission-panel .daily-count { width: 36px; height: 36px; }
  .mission-panel .verse-card { padding: .4rem .65rem; margin-bottom: .45rem; }
  .mission-panel .verse-text { font-size: var(--ms-body); }
  .mission-panel .streak-banner .streak-best { display: none; }
  .ms-main { padding-top: .3rem; padding-bottom: .3rem; }
}

/* Tumbado: ancho de sobra y alto justo. Ventana centrada con el corral a los
   lados, y las filas en dos columnas: las seis misiones caben sin bajar. */
@media (max-height: 500px) and (orientation: landscape) {
  .modal-missions .modal { width: min(680px, calc(100% - 3rem)); }
  .modal-missions .modal-head { padding-top: .2rem; padding-bottom: .2rem; }
  .mission-list { grid-template-columns: 1fr 1fr; gap: .4rem; }
}


/* ================================================================ el lobo

   La espada y la cabecera de la pregunta. Lo demas de la pregunta es la cinta
   de la pesca tal cual (ver ui/loboPanel.js): mismas opciones, misma barra.

   La espada es REDONDA, como la pidio Hansel ("un circulo con una espadita"),
   y como el salto y la patada, que son los otros golpes del juego. Pero con
   las reglas de los carteles: color plano, borde de tinta con presencia y
   sombra dura desplazada. Oro dentro del circulo de los atriles y celeste en el
   de oracion: los dos colores de los circulos del suelo. */
.lobo-espada {
  position: absolute;
  left: 50%; transform: translateX(-50%);
  bottom: calc(4.4rem + var(--safe-bottom));
  width: 72px; height: 72px;
  display: grid; place-items: center;
  padding: 0;
  background: var(--ms-gold);
  border: 3px solid var(--ms-ink);
  border-radius: 50%;
  box-shadow: 3px 3px 0 var(--ms-ink);
  cursor: pointer;
  touch-action: none;
  animation: actIn .2s ease-out;
}
.lobo-espada.hidden { display: none; }
.lobo-espada.lobo-oracion { background: #6fc3e8; }
/* 36 px: multiplo de 12, o los pixeles del icono salen desiguales. */
.lobo-espada svg { width: 36px; height: 36px; display: block; }
.lobo-espada:active { translate: 2px 2px; box-shadow: 1px 1px 0 var(--ms-ink); }
.lobo-espada:focus-visible { outline: 3px solid var(--ms-gold-lt); outline-offset: 3px; }

/* Encima de la pregunta: desde donde se ataca y que pasa si aciertas. */
.lobo-sitio {
  display: flex; align-items: baseline; gap: .6rem;
  padding: .35rem .9rem;
  background: rgba(20, 38, 28, .94);
  border: 2px solid var(--ms-gold);
  box-shadow: 3px 3px 0 rgba(0, 0, 0, .4);
  color: #f7f2e8;
  font-size: var(--ms-small); font-weight: 700;
  animation: pescaEntra .22s ease;
}
.lobo-sitio strong { color: var(--ms-gold); font-size: var(--ms-body); font-weight: 900; }
.lobo-sitio.lobo-oracion { border-color: #6fc3e8; }
.lobo-sitio.lobo-oracion strong { color: #b0e2f5; }

/* Los botones de cada evento del panel: activar, y al lado, acabar ya. */
.evento-card { margin-bottom: .8rem; }
.evento-botones { margin-top: .7rem; flex-wrap: wrap; gap: .5rem; }

/* =========================================================================
   MASCOTAS (ui/petsPanel.js) — 26-sep-2026

   Hecho con el criterio de .claude/skills/criterio-humano desde la primera
   linea, para no tener que repintarlo despues como las misiones:
     - colores planos, todos de PALETTE (los tokens --ms-* de arriba, mas el
       azul del agua para la gema y el verde del prado para el escenario);
     - ni un degradado ni una sombra con blur: la profundidad es la sombra dura
       de 3 px, igual que las tarjetas de misiones;
     - cuatro tamanos de letra, los de --ms-*, y ninguno mas;
     - iconos pixel de pixelIcons.js (huella, cuenco, gema, candado), nunca
       emoji, y los dibujos de las mascotas son sus sprites de verdad.
   El unico movimiento es el hundido del boton al pulsar y la mascota grande
   respirando: los dos dicen algo (que el dedo dio, que el bicho esta vivo).
   ========================================================================= */

/* --- la ventana, plana ---------------------------------------------------- */
.modal-pets .modal {
  width: min(900px, 100%);
  background: var(--ms-paper);
  border: 3px solid var(--ms-ink);
  border-radius: 0;
  box-shadow: 4px 4px 0 var(--ms-ink);
  color: var(--ms-ink);
}
.modal-pets .modal-head {
  background: var(--ms-green-dk);
  box-shadow: none;
  border-bottom: 3px solid var(--ms-ink);
  padding: .55rem .8rem;
}
.modal-pets .modal-head h2 { font-size: var(--ms-lead); letter-spacing: .02em; }
.modal-pets .modal-close {
  border-radius: 0;
  background: transparent;
  border: 2px solid var(--ms-paper);
  width: 32px; height: 32px;
}
.modal-pets .modal-body { padding: .8rem .9rem 1rem; }
.pet-loading { font-size: var(--ms-body); }

/* --- la tuya, arriba ------------------------------------------------------ */
.pet-hero {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: .9rem;
  align-items: stretch;
  padding: .7rem;
  margin-bottom: .9rem;
  background: var(--ms-paper-2);
  border: 2px solid var(--ms-ink);
  box-shadow: 3px 3px 0 var(--ms-ink);
}
/* El escenario: un trozo de prado liso, del verde del corral. La mascota pisa
   el borde de abajo, como en el juego; nada de centrarla en el aire. */
.pet-stage {
  width: 150px;
  min-height: 112px;
  display: flex; align-items: flex-end; justify-content: center;
  background: #4f9a5e;
  border: 2px solid var(--ms-ink);
  overflow: hidden;
}
.pet-stage .pet-sprite { display: block; margin-bottom: -8px; }
.pet-stage-paw { align-self: center; opacity: .5; }
.pet-stage-paw svg { width: 48px; height: 48px; }
.pet-hero.is-hungry .pet-stage { background: #3d7a4f; }

.pet-hero-info { display: flex; flex-direction: column; gap: .45rem; min-width: 0; }
.pet-hero-top { display: flex; align-items: center; justify-content: space-between; gap: .6rem; }
.pet-hero h3 { margin: 0; font-size: var(--ms-lead); }
.pet-note, .pet-streak, .pet-why {
  margin: 0;
  font-size: var(--ms-small);
  color: var(--ms-ink-soft);
  line-height: 1.4;
}
.pet-why { color: var(--ms-fire); font-weight: 700; }

.pet-icon { display: inline-grid; place-items: center; flex: none; }
.pet-icon svg { width: 24px; height: 24px; display: block; }

.pet-purse {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .2rem .55rem .2rem .3rem;
  background: var(--ms-paper);
  border: 2px solid var(--ms-ink);
  font-size: var(--ms-small);
  align-self: flex-start;
}
.pet-purse strong { font-size: var(--ms-body); }

/* La barriga: una barra plana de tres tramos, como las del bano. */
.pet-belly { display: flex; flex-direction: column; gap: .2rem; }
.pet-belly small { font-size: var(--ms-small); font-weight: 700; }
.pet-belly-bar {
  height: 12px;
  background: var(--ms-paper);
  border: 2px solid var(--ms-ink);
}
.pet-belly-bar i { display: block; height: 100%; background: var(--ms-green-lt); }
.pet-belly-peckish .pet-belly-bar i { background: var(--ms-gold); }
.pet-belly-hungry small { color: var(--ms-fire); }

.pet-feed { display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; }
.pet-food { display: inline-flex; align-items: center; gap: .3rem; font-size: var(--ms-small); }
.pet-food strong { font-size: var(--ms-body); }

/* --- botones ---------------------------------------------------------------- */
.pet-btn {
  font: inherit;
  font-size: var(--ms-small);
  font-weight: 800;
  padding: .4rem .75rem;
  background: var(--ms-gold-lt);
  color: var(--ms-ink);
  border: 2px solid var(--ms-ink);
  border-radius: 0;
  box-shadow: 2px 2px 0 var(--ms-ink);
  cursor: pointer;
}
.pet-btn-feed { background: var(--ms-green-lt); }
.pet-btn:active:not(:disabled) { translate: 2px 2px; box-shadow: 0 0 0 var(--ms-ink); }
.pet-btn:focus-visible, .pet-link:focus-visible { outline: 3px solid var(--ms-gold); outline-offset: 2px; }
.pet-btn:disabled {
  background: var(--ms-paper-2);
  color: var(--ms-ink-soft);
  box-shadow: none;
  cursor: not-allowed;
}
.pet-link {
  font: inherit; font-size: var(--ms-small); font-weight: 700;
  background: none; border: 0; padding: .2rem 0;
  color: var(--ms-ink-soft); text-decoration: underline; cursor: pointer;
}

/* --- la rejilla de las quince -------------------------------------------- */
.pet-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
  gap: .6rem;
}
.pet-card {
  display: flex; flex-direction: column; align-items: center; gap: .35rem;
  padding: .45rem .45rem .55rem;
  background: var(--ms-paper);
  border: 2px solid var(--ms-ink);
  box-shadow: 3px 3px 0 var(--ms-ink);
  text-align: center;
}
/* La que llevas: el borde y la sombra en oro. Sin brillo ni pulso: se nota
   igual y no distrae de las demas. */
.pet-card.is-worn { border-color: var(--ms-gold); box-shadow: 3px 3px 0 var(--ms-gold); background: #ffe9a3; }
.pet-card.is-owned .pet-art { background: #4f9a5e; }
.pet-art {
  width: 100%;
  height: 74px;
  display: flex; align-items: flex-end; justify-content: center;
  background: #6bb56e;
  border: 2px solid var(--ms-ink);
  overflow: hidden;
}
.pet-art .pet-sprite { display: block; margin-bottom: -6px; }
/* Con candado se ve igual el dibujo -la que aun no tienes es la que hace
   volver-, pero apagado sobre un prado de noche. */
.pet-card.is-locked .pet-art { background: #4a3d6b; }
.pet-card.is-locked .pet-art .pet-sprite { opacity: .45; }
.pet-name { font-size: var(--ms-body); line-height: 1.2; }
.pet-foot { display: flex; align-items: center; justify-content: center; gap: .45rem; flex-wrap: wrap; }
.pet-price { display: inline-flex; align-items: center; gap: .15rem; font-size: var(--ms-body); }
.pet-price .pet-icon svg { width: 24px; height: 24px; }
.pet-lock { display: inline-flex; align-items: center; gap: .3rem; font-size: var(--ms-small); font-weight: 700; color: var(--ms-ink-soft); }
.pet-tag {
  font-size: var(--ms-small); font-weight: 800;
  padding: .15rem .45rem;
  background: var(--ms-gold-lt);
  border: 2px solid var(--ms-ink);
}
.pet-rules {
  margin: .9rem 0 0;
  font-size: var(--ms-small);
  color: var(--ms-ink-soft);
  line-height: 1.45;
}

/* --- movil: pantalla entera ---------------------------------------------- */
@media (max-width: 560px), (max-height: 500px) {
  .modal-backdrop.modal-pets { padding: 0; align-items: stretch; }
  .modal-pets .modal {
    width: 100%; max-width: none;
    height: 100%; max-height: none;
    border: 0; box-shadow: none;
    padding-bottom: 0;
  }
  .modal-pets .modal-head { padding: .35rem .5rem .35rem .8rem; }
  .modal-pets .modal-head::before { display: none; }
  .modal-pets .modal-close { min-width: 34px; min-height: 34px; width: 34px; height: 34px; }
  .modal-pets .modal-body { padding: .6rem .7rem calc(.9rem + var(--safe-bottom)); }
  .pet-stage { width: 112px; min-height: 96px; height: 96px; align-self: start; }
  /* El dibujo viene ampliado x4; aqui se queda en x3 (75 %), que sigue siendo
     un numero entero de pixeles de pantalla por pixel de arte. */
  .pet-stage .pet-sprite {
    transform: scale(.75); transform-origin: 50% 100%;
    image-rendering: pixelated; margin-bottom: -6px;
  }
  .pet-grid { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: .5rem; }
  .pet-art { height: 66px; }
}

/* Tumbado (844x390): la tuya a la izquierda, fija, y la rejilla a su lado con
   su propio scroll. En una columna, la cabecera se comia la mitad de los 390 px
   de alto y de la rejilla se veia una fila. */
@media (max-height: 500px) and (orientation: landscape) {
  .modal-pets .modal-body {
    display: grid;
    grid-template-columns: 250px 1fr;
    grid-template-rows: 1fr auto;
    gap: 0 .8rem;
    overflow: hidden;
  }
  .pet-hero {
    grid-column: 1; grid-row: 1 / span 2;
    grid-template-columns: 1fr;
    align-content: start;
    margin: 0;
    overflow-y: auto;
  }
  .pet-stage { width: 100%; min-height: 84px; height: 84px; }
  .pet-grid { grid-column: 2; grid-row: 1; overflow-y: auto; align-content: start; padding: 0 4px 4px 0; }
  .pet-rules { grid-column: 2; grid-row: 2; margin-top: .5rem; }
}

/* =========================================================================
   MENU A PANTALLA COMPLETA  (26-sep-2026, ui/gameMenu.js + ui/menuScenes.js)

   Hansel: "todas las opciones en el menu, menos el buzon", "de pantalla
   completa tipo Pokemon GO pero vertical y mejorado", "que no sea monotono" y
   "sin barra de scroll, bien hecho en horizontal, que se adecue a todo".

   Tres escalones, y cada uno se ve distinto a proposito:
     1. Las GRANDES (Misiones, Biblia, Tienda, Mascotas): una escena con la
        oveja del jugador haciendo lo que se hace ahi, sobre papel.
     2. Las SECUNDARIAS: ficha de papel con su icono pixel sobre un cuadro de
        color propio. Cada una con su color: nada de fila de botones iguales.
     3. ABAJO, discretos y en madera oscura: Sonido, Pantalla, Ayuda y Salir.

   El criterio es el de misiones y los carteles: colores planos de PALETTE,
   contorno de tinta, sombra DURA sin blur, esquinas a cero, se hunden al
   pulsar. Cuatro tamanos de letra (las variables --gm-t*), y no hay mas.

   SIN SCROLL: nada aqui lleva `overflow: auto`. El reparto cambia por
   proporcion -columnas tumbado, filas de pie- y las piezas se encogen para
   caber (`min-height: 0` en todo lo que es flex/grid, o se desbordan).

   Va AL FINAL del archivo a proposito: los bloques responsive de arriba ya
   deshicieron un repintado una vez (ver la memoria "interfaz a medio
   repintar"); aqui abajo no los tiene detras.
   ========================================================================= */

.game-menu {
  --gm-ink: #1a1412;      /* tinta */
  --gm-soft: #48403a;     /* topo oscuro */
  --gm-paper: #f7f2e8;    /* crema */
  --gm-paper-2: #e8dfc9;  /* crema hundido */
  --gm-wood: #6f4622;     /* madera oscura */
  --gm-wood-dk: #4a2f18;  /* la madera de los carteles de accion */
  --gm-green-dk: #223e2c; /* cesped oscuro: el fondo del panel */
  --gm-gold: #f2b134;     /* oro */
  --gm-gold-lt: #ffd977;  /* oro claro */
  --gm-red: #c4503c;      /* teja clara */

  --gm-t1: 1.375rem;  /* el titulo */
  --gm-t2: 1.0625rem; /* el nombre de las grandes */
  --gm-t3: .875rem;   /* el nombre de las secundarias y el saldo */
  --gm-t4: .75rem;    /* lineas vivas y la fila de abajo */
  --gm-gap: .75rem;

  position: absolute; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  padding: calc(1rem + var(--safe-top)) calc(1rem + var(--safe-right))
           calc(1rem + var(--safe-bottom)) calc(1rem + var(--safe-left));
  /* El corral se sigue viendo detras, apagado: el menu es una pausa, no otra
     pantalla. Tinta plana con transparencia, sin desenfoque. */
  background: rgba(26, 20, 18, .62);
  color: var(--gm-ink);
  opacity: 0; visibility: hidden;
  transition: opacity .2s ease, visibility 0s linear .2s;
}
.game-menu.open { opacity: 1; visibility: visible; transition: opacity .2s ease; }

.gm-panel {
  position: relative;
  width: 100%; height: 100%;
  max-width: 1040px; max-height: 640px;
  display: flex; flex-direction: column;
  background: var(--gm-green-dk);
  border: 3px solid var(--gm-ink);
  box-shadow: 6px 6px 0 var(--gm-ink);
  /* Sube desde abajo al abrirse: el gesto de "desplegar" que pidio Hansel. */
  translate: 0 36px;
  transition: translate .34s cubic-bezier(.2, .9, .3, 1);
}
.game-menu.open .gm-panel { translate: 0 0; }

/* ---- cabecera: un tablon de madera con el titulo, el saldo y la X */
.gm-head {
  flex: none;
  display: flex; align-items: center; gap: .6rem;
  padding: .5rem .6rem .5rem .8rem;
  background: var(--gm-wood);
  border-bottom: 3px solid var(--gm-ink);
}
.gm-title { display: flex; align-items: center; gap: .45rem; margin-right: auto; color: var(--gm-paper); }
.gm-title i { display: block; line-height: 0; }
.gm-title svg {
  width: 24px; height: 24px; display: block;
  filter: drop-shadow(1px 0 0 var(--gm-paper-2)) drop-shadow(-1px 0 0 var(--gm-paper-2))
          drop-shadow(0 1px 0 var(--gm-paper-2)) drop-shadow(0 -1px 0 var(--gm-paper-2));
}
.gm-title b { font-size: var(--gm-t1); font-weight: 900; letter-spacing: .02em; text-shadow: 2px 2px 0 var(--gm-ink); }

.gm-purse { display: flex; gap: .4rem; }
.gm-chip {
  display: inline-flex; align-items: center; gap: .3rem;
  height: 32px; padding: 0 .6rem 0 .3rem;
  background: var(--gm-ink);
  font-size: var(--gm-t3); font-weight: 900; font-variant-numeric: tabular-nums;
}
.gm-chip i { display: block; line-height: 0; }
.gm-chip svg { width: 24px; height: 24px; display: block; }
.gm-chip-coin { color: var(--gm-gold-lt); }
.gm-chip-gem { color: #9fd8f2; }

.gm-close {
  flex: none; width: 40px; height: 40px; padding: 0;
  display: grid; place-items: center;
  background: var(--gm-red);
  border: 2px solid var(--gm-ink); border-radius: 0;
  box-shadow: 3px 3px 0 var(--gm-ink);
  cursor: pointer;
}
.gm-close svg { width: 24px; height: 24px; display: block; }
.gm-close:active { translate: 2px 2px; box-shadow: 1px 1px 0 var(--gm-ink); }
.gm-close:focus-visible { outline: 3px solid var(--gm-gold-lt); outline-offset: 2px; }

/* ---- el reparto: grandes a la izquierda, el resto a la derecha */
.gm-body {
  flex: 1; min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  gap: var(--gm-gap);
  padding: var(--gm-gap);
}
.gm-main {
  min-height: 0;
  display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr;
  gap: var(--gm-gap);
}
.gm-side { min-height: 0; display: flex; flex-direction: column; gap: var(--gm-gap); }
/* Dos filas; las columnas salen de cuantas haya (`data-n` lo pone gameMenu.js:
   5 o 6 van en 3 columnas, 7 u 8 en 4). Si una fila queda corta, sus fichas se
   estiran: se lee como reparto, no como hueco. */
.gm-more {
  --cols: 3;
  flex: 1; min-height: 0;
  display: flex; flex-wrap: wrap; align-content: stretch;
  gap: var(--gm-gap);
}
.gm-more[data-n="7"], .gm-more[data-n="8"] { --cols: 4; }
.gm-more[data-n="1"], .gm-more[data-n="2"], .gm-more[data-n="3"], .gm-more[data-n="4"] { --cols: 2; }
.gm-foot { flex: none; display: flex; gap: .5rem; }

/* ---- lo comun a todas las entradas */
/* Sin `padding` ni `color` aqui a proposito: con este selector (dos clases)
   pisarian los de cada tipo de entrada, que solo llevan una. */
.game-menu .menu-item {
  position: relative;
  margin: 0;
  font: inherit; text-align: left;
  border: 3px solid var(--gm-ink); border-radius: 0;
  cursor: pointer;
}
.game-menu .menu-item:focus-visible { outline: 3px solid var(--gm-gold-lt); outline-offset: 2px; }

/* ---- 1. las grandes */
.gm-card {
  min-width: 0; min-height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
  padding: 0;
  background: var(--gm-paper); color: var(--gm-ink);
  box-shadow: 4px 4px 0 var(--gm-ink);
}
/* Se hunde contra su sombra: el mismo gesto que el resto del juego. */
.gm-card:active { translate: 3px 3px; box-shadow: 1px 1px 0 var(--gm-ink); }
.gm-scene {
  position: relative; display: block;
  flex: 1; min-height: 0;
  overflow: hidden;
  border-bottom: 3px solid var(--gm-ink);
}
/* Anclado abajo a la izquierda, en pixel entero: centrado con translate(-50%)
   caeria a medio pixel y la rejilla se emborronaria. */
.gm-scene canvas { position: absolute; left: 0; bottom: 0; display: block; image-rendering: pixelated; }
.gm-card-foot {
  flex: none;
  display: flex; align-items: baseline; column-gap: .5rem;
  padding: .35rem .6rem .4rem;
  white-space: nowrap;
}
.gm-card .gm-label { flex: none; font-size: var(--gm-t2); font-weight: 900; line-height: 1.15; }
/* En una linea con el nombre; si no cabe, se corta con puntos suspensivos en
   vez de saltar de linea (un pie mas alto que el de al lado descuadra las
   escenas de la fila). */
.gm-sub { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: var(--gm-t4); font-weight: 700; color: var(--gm-soft); }
.gm-sub[hidden] { display: none; }

/* ---- 2. las secundarias */
.gm-tile {
  flex: 1 1 calc(100% / var(--cols, 3) - var(--gm-gap));
  min-width: 0; min-height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;
  padding: 0;
  background: var(--gm-paper); color: var(--gm-ink);
  box-shadow: 3px 3px 0 var(--gm-ink);
}
.gm-tile:active { translate: 2px 2px; box-shadow: 1px 1px 0 var(--gm-ink); }
/*
 * Cada secundaria es una tarjeta pequena, como las grandes pero sin escena: un
 * bloque de su color con el icono en medio, y su nombre en la tira de papel.
 * Asi se leen de la misma familia y la diferencia es de TAMANO, no de estilo.
 * El filo oscuro de abajo (sombra interior dura, sin blur) es el "suelo" del
 * bloque, el mismo que tienen las escenas.
 */
.gm-tile .gm-ico {
  flex: 1; min-height: 0;
  display: grid; place-items: center;
  background: var(--tint, var(--gm-paper-2));
  border-bottom: 3px solid var(--gm-ink);
  box-shadow: inset 0 -6px 0 rgba(26, 20, 18, .16);
}
/* 48 px = cuatro pixeles por casilla de la rejilla de 12. */
.gm-tile .gm-ico svg { width: 48px; height: 48px; display: block; }
.gm-tile .gm-label {
  flex: none;
  padding: .3rem .4rem .35rem;
  font-size: var(--gm-t3); font-weight: 900; text-align: center; line-height: 1.1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* El color de cada una, de PALETTE, elegido para que su icono resalte encima. */
.gm-tile[data-id="juegos"]  { --tint: #9fd8f2; } /* agua clara bajo el mando lila */
.gm-tile[data-id="peces"]   { --tint: #ffd977; } /* oro claro bajo el pez azul */
.gm-tile[data-id="logros"]  { --tint: #3d7a4f; } /* cesped bajo la medalla de oro */
.gm-tile[data-id="ranking"] { --tint: #282242; } /* noche bajo la copa */
.gm-tile[data-id="emotes"]  { --tint: #f19bb0; } /* rosa claro bajo las notas */
.gm-tile[data-id="pastor"]  { --tint: #6bb56e; } /* cesped claro bajo el cayado */
.gm-tile[data-id="admin"]   { --tint: #e8dfc9; } /* crema bajo el escudo */
.gm-tile[data-id="mapa"]    { --tint: #a58fd0; } /* lila bajo el mapa */

/* ---- 3. abajo, discretos */
.game-menu .gm-foot-btn {
  flex: 1 1 0; min-width: 0;
  display: flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .45rem .4rem;
  background: var(--gm-wood-dk); color: var(--gm-paper);
  box-shadow: 3px 3px 0 var(--gm-ink);
}
.game-menu .gm-foot-btn { border-width: 2px; }
.gm-foot-btn:active { translate: 2px 2px; box-shadow: 1px 1px 0 var(--gm-ink); }
.gm-foot-btn .gm-ico { flex: none; line-height: 0; }
/* Sobre madera oscura el contorno del icono se funde: filo claro de 1 px. */
.gm-foot-btn .gm-ico svg {
  width: 24px; height: 24px; display: block;
  filter: drop-shadow(1px 0 0 var(--gm-paper-2)) drop-shadow(-1px 0 0 var(--gm-paper-2))
          drop-shadow(0 1px 0 var(--gm-paper-2)) drop-shadow(0 -1px 0 var(--gm-paper-2));
}
.gm-foot-btn .gm-label { font-size: var(--gm-t4); font-weight: 900; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Salir en rosa oscuro de PALETTE: se distingue sin gritar. */
.gm-foot-btn[data-id="salir"] { background: #7d4046; }

/* ---- el sonido: ocupa el sitio de las entradas, con su "Listo" para volver */
.gm-sound {
  display: none;
  flex: 1; min-height: 0;
  align-items: center; justify-content: center;
  padding: var(--gm-gap);
}
.gm-panel.show-sound .gm-body { display: none; }
.gm-panel.show-sound .gm-sound { display: flex; }
.gm-sound-card {
  width: min(480px, 100%);
  padding: .9rem 1rem 1rem;
  background: var(--gm-paper);
  border: 3px solid var(--gm-ink);
  box-shadow: 4px 4px 0 var(--gm-ink);
  animation: gmIn .26s cubic-bezier(.2, .9, .3, 1) backwards;
}
.gm-sound-head { display: flex; align-items: center; gap: .5rem; margin-bottom: .3rem; }
.gm-sound-head i { line-height: 0; }
.gm-sound-head svg { width: 36px; height: 36px; display: block; }
.gm-sound-head b { font-size: var(--gm-t1); font-weight: 900; }

.gm-vol {
  display: grid; grid-template-columns: 5rem minmax(0, 1fr) 3.2rem;
  align-items: center; gap: .6rem;
  margin: .55rem 0;
}
.gm-vol-name { font-size: var(--gm-t3); font-weight: 900; }
.gm-vol-out { font-size: var(--gm-t3); font-weight: 900; text-align: right; font-variant-numeric: tabular-nums; }
.gm-sound.is-muted .gm-vol { opacity: .45; }

/*
 * La barra de volumen. La parte llena y la vacia son DOS colores planos con el
 * corte en seco (dos paradas en el mismo punto): se ve como dos tramos, no
 * como un degradado. Firefox pinta el tramo lleno solo (`-moz-range-progress`).
 */
.gm-vol input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 30px; margin: 0;
  background: transparent; cursor: pointer;
}
.gm-vol input[type="range"]::-webkit-slider-runnable-track {
  height: 14px;
  border: 2px solid var(--gm-ink);
  background: linear-gradient(to right, var(--gm-gold) var(--fill, 50%), var(--gm-paper-2) var(--fill, 50%));
}
.gm-vol input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 20px; height: 28px; margin-top: -9px;
  background: var(--gm-wood-dk);
  border: 2px solid var(--gm-ink);
  box-shadow: 2px 2px 0 var(--gm-ink);
}
.gm-vol input[type="range"]::-moz-range-track {
  height: 10px; background: var(--gm-paper-2); border: 2px solid var(--gm-ink);
}
.gm-vol input[type="range"]::-moz-range-progress { height: 10px; background: var(--gm-gold); border: 2px solid var(--gm-ink); }
.gm-vol input[type="range"]::-moz-range-thumb {
  width: 16px; height: 24px; border-radius: 0;
  background: var(--gm-wood-dk); border: 2px solid var(--gm-ink);
}
.gm-vol input[type="range"]:focus-visible { outline: 3px solid var(--gm-gold); outline-offset: 3px; }

.gm-sound-foot { display: flex; gap: .6rem; margin-top: .9rem; }
.gm-mute, .gm-done {
  display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  min-height: 44px; padding: 0 .9rem;
  font: inherit; font-size: var(--gm-t3); font-weight: 900;
  border: 2px solid var(--gm-ink); border-radius: 0;
  box-shadow: 3px 3px 0 var(--gm-ink);
  cursor: pointer;
}
.gm-mute { flex: 1; background: var(--gm-wood-dk); color: var(--gm-paper); }
.gm-mute i { line-height: 0; }
.gm-mute svg {
  width: 24px; height: 24px; display: block;
  filter: drop-shadow(1px 0 0 var(--gm-paper-2)) drop-shadow(-1px 0 0 var(--gm-paper-2))
          drop-shadow(0 1px 0 var(--gm-paper-2)) drop-shadow(0 -1px 0 var(--gm-paper-2));
}
.gm-mute.on { background: var(--gm-red); }
.gm-done { background: var(--gm-gold); color: var(--gm-ink); min-width: 6.5rem; }
.gm-mute:active, .gm-done:active { translate: 2px 2px; box-shadow: 1px 1px 0 var(--gm-ink); }

/* ---- la entrada: suben un palmo y aparecen, una detras de otra
   (`backwards` y no `both`: con `both` el final de la animacion se quedaria
   pisando el `translate` del :active y ya no se hundirian al pulsarlas) */
.game-menu.open .gm-card,
.game-menu.open .gm-tile,
.game-menu.open .gm-foot-btn {
  animation: gmIn .34s cubic-bezier(.2, .9, .3, 1) backwards;
  animation-delay: calc(var(--i, 8) * 35ms + 60ms);
}
@keyframes gmIn {
  from { opacity: 0; translate: 0 14px; }
  to   { opacity: 1; translate: 0 0; }
}

/* ---- DE PIE: filas en vez de columnas. Las grandes arriba, el resto debajo,
   y el nombre de las grandes encima de su linea viva (de lado no cabe). */
@media (orientation: portrait) {
  .gm-body {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1.45fr) minmax(0, 1fr);
  }
  .gm-card-foot { flex-direction: column; align-items: flex-start; }
  .gm-sub { max-width: 100%; }
}

/* ---- PANTALLA GRANDE: con 640 px de alto, dos filas de fichas salen como
   columnas altas y huecas; en tres filas quedan casi cuadradas. */
@media (min-height: 600px) and (min-width: 900px) and (orientation: landscape) {
  .gm-more { --cols: 2; }
  .gm-more[data-n="7"], .gm-more[data-n="8"] { --cols: 3; }
}

/* ---- EN EL MOVIL: de borde a borde, como una pantalla del juego. */
@media (max-height: 500px), (max-width: 560px) {
  .game-menu { padding: 0; }
  .gm-panel {
    max-width: none; max-height: none;
    border: 0; box-shadow: none;
    padding: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left);
  }
}

/* ---- MOVIL TUMBADO: 360-400 px de alto. Todo mas junto y mas bajo. */
@media (max-height: 500px) and (orientation: landscape) {
  .game-menu {
    --gm-t1: 1.125rem;
    --gm-t2: .9375rem;
    --gm-t3: .8125rem;
    --gm-gap: .5rem;
  }
  .gm-head { padding: .3rem .5rem .3rem .7rem; gap: .5rem; }
  .gm-close { width: 36px; height: 36px; }
  .gm-chip { height: 28px; }
  .gm-card-foot { padding: .2rem .5rem .25rem; }
  .gm-tile .gm-ico svg { width: 36px; height: 36px; }
  .gm-tile .gm-label { padding: .2rem .3rem .25rem; }
  /* La fila de abajo: icono encima del nombre, que en fila no cabe. */
  .game-menu .gm-foot-btn { flex-direction: column; gap: .1rem; padding: .25rem .2rem .2rem; }
}

/* ---- DE PIE Y ESTRECHO: la fila de abajo, con el icono encima del nombre. */
@media (max-width: 420px) and (orientation: portrait) {
  .game-menu .gm-foot-btn { flex-direction: column; gap: .15rem; padding: .35rem .2rem .3rem; }
}

@media (prefers-reduced-motion: reduce) {
  .game-menu, .gm-panel { transition: none; }
  .game-menu.open .gm-card, .game-menu.open .gm-tile, .game-menu.open .gm-foot-btn,
  .gm-sound-card { animation: none; }
}

/* =========================================================================
   AVISOS FLOTANTES  (ui/announce.js)

   Letra blanca con borde de tinta, sin caja. Nace un poco por debajo del
   centro, sube despacio y se apaga ANTES del tercio de arriba, que es donde
   salen el globo de la nube ("Mi amada oveja") y la barra del lobo.

   El borde es un anillo de sombras DURAS (sin blur) de 2 y 3 px, mas una
   sombra caida de 4 px: se lee sobre la hierba, el agua y la noche.
   ========================================================================= */

.announce-layer { position: fixed; inset: 0; z-index: 110; pointer-events: none; overflow: hidden; }
/* Se ancla por ARRIBA: el nuevo nace con su primera linea en el mismo sitio y
   crece hacia abajo, asi que, subiendo todos igual, basta con que el de delante
   haya subido SU alto para que el nuevo quepa debajo (ver `start` en
   announce.js). Anclado por el centro o por abajo, uno de dos lineas pisaba al
   anterior: se vio en la captura. */
.announce {
  position: absolute; left: 50%; top: 56%;
  width: max-content; max-width: min(88vw, 34rem);
  transform: translate(-50%, 0);
  text-align: center; text-wrap: balance;
  color: #fffdf8;
  font-size: clamp(1.0625rem, .7rem + 1.4vw, 1.625rem);
  font-weight: 900; line-height: 1.2; letter-spacing: .01em;
  text-shadow:
    -2px -2px 0 #1a1412, 0 -3px 0 #1a1412, 2px -2px 0 #1a1412,
    -3px 0 0 #1a1412, 3px 0 0 #1a1412,
    -2px 2px 0 #1a1412, 0 3px 0 #1a1412, 2px 2px 0 #1a1412,
    -1px -3px 0 #1a1412, 1px -3px 0 #1a1412, -3px 1px 0 #1a1412, 3px 1px 0 #1a1412,
    0 5px 0 #1a1412;
  /* Sube a velocidad CONSTANTE (lineal): asi uno nunca alcanza al de delante. */
  animation: announceRise 4.4s linear forwards;
}
.announce.is-waiting { display: none; }
@keyframes announceRise {
  0%   { opacity: 0; translate: 0 10px; scale: .9; }
  6%   { opacity: 1; translate: 0 calc(var(--rise, -100px) * .06); scale: 1.05; }
  11%  { scale: 1; translate: 0 calc(var(--rise, -100px) * .11); }
  60%  { opacity: 1; }
  100% { opacity: 0; translate: 0 var(--rise, -100px); scale: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .announce { animation-name: announceFade; }
  @keyframes announceFade { 0%, 100% { opacity: 0; } 8%, 70% { opacity: 1; } }
}
