:root {
  --bg: #14110e;
  --panel: #1e1a16;
  --panel2: #2a241e;
  --text: #f3ece3;
  --muted: #b3a493;
  --accent: #c4a36a;
  --light: #e6d3a8;
  --dark: #8a5a32;
  --sel: #e8d090;
  --move: rgba(196, 163, 106, .35);
  --cap: rgba(255, 90, 70, .5);
  --white-p: #f7f1e6;
  --black-p: #3a2218;
  --ring: #d4af37;
  --online: #7eb0d6;
  --accent-rgb: 196, 163, 106;
}
* { box-sizing: border-box; }
html, body {
  margin: 0; height: 100%; overflow: hidden;
  background:
    radial-gradient(900px 480px at 18% -8%, rgba(var(--accent-rgb), .1), transparent 52%),
    var(--bg);
  color: var(--text);
  font-family: "Segoe UI", "Helvetica Neue", system-ui, sans-serif;
  /* --- Cosas que sólo pasan en el NAVEGADOR del celular, no en la app --- */

  /* 1) "Tirar para recargar". En Chrome de Android, arrastrar hacia abajo
        recarga la página. Arrastrando una ficha cerca del borde superior se
        disparaba sin querer y se perdía la partida en curso. Con
        overscroll-behavior:none el gesto deja de existir dentro del juego. */
  overscroll-behavior: none;

  /* 2) Zoom por doble toque. Tocar dos casillas rápido se interpretaba como
        doble toque y el navegador hacía zoom, dejando el tablero cortado.
        "manipulation" conserva el desplazamiento y el pellizco para ampliar,
        pero quita ese doble toque. */
  touch-action: manipulation;

  /* 3) El recuadro gris que Android dibuja sobre lo que se toca: en un
        tablero se ve como un parpadeo raro sobre las casillas. */
  -webkit-tap-highlight-color: transparent;
}
.app {
  display: grid; grid-template-columns: 280px minmax(0, 1fr); overflow: hidden;
  /* Antes esto era height:100vh/100dvh. En algunos WebView de Android esas
     unidades se calculan mal y quedan más cortas que la pantalla real,
     dejando una franja vacía (negra) abajo de todo. position:fixed+inset:0
     es la misma técnica que ya usa el tablero a pantalla completa (ahí sí
     llena bien la pantalla), así que se unifica acá también. */
  position: fixed;
  inset: 0;
  /* Espacio para el notch / Dynamic Island y la barra inferior de iOS.
     box-sizing:border-box (regla global de arriba) hace que este padding
     se reste del alto fijo en vez de sumarse: no agranda el documento,
     sólo empuja el contenido hacia adentro para que nada quede tapado. */
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
@media (max-width: 900px) {
  .app { grid-template-columns: 1fr; }
  /* En una sola columna, .side (menú/análisis/etc.) y .board-wrap (tablero)
     quedan apilados uno debajo del otro. Si el contenido de arriba es más
     alto que la pantalla (por ejemplo Análisis, con resumen + gráfico +
     lista de jugadas), overflow:hidden bloqueaba cualquier scroll y el
     tablero de abajo quedaba inalcanzable — no es que desapareciera, es
     que no había forma de bajar hasta él. En pantalla completa de juego
     esto no aplica porque el tablero pasa a position:fixed y se escapa de
     este contenedor igual. */
  .app { overflow-y: auto; }
}

/* Barra de anuncio fija abajo de todo, visible en cualquier pantalla del
   menú en móvil. En escritorio no se usa (el layout de dos columnas ya
   tiene su propio ad-banner dentro del tablero). */
.ad-bar-global { display: none; }
@media (max-width: 900px) {
  .app { padding-bottom: calc(52px + env(safe-area-inset-bottom)); }
  .ad-bar-global {
    display: flex; align-items: center; justify-content: center;
    position: fixed; left: 0; right: 0; bottom: 0;
    height: 52px; padding-bottom: env(safe-area-inset-bottom);
    background: var(--panel); border-top: 1px solid rgba(var(--accent-rgb), .18);
    color: var(--muted); font-size: .68rem; letter-spacing: .04em;
    text-transform: uppercase; z-index: 900;
  }
  /* Durante la partida a pantalla completa la barra de anuncio propia del
     tablero (#ad-banner) ya reserva ese lugar, así que la global se apaga
     para no duplicarla. */
  body.mobile-game-fullscreen .app { padding-bottom: 0; }
  body.mobile-game-fullscreen .ad-bar-global { display: none; }
}
h1 {
  margin: 0; font-size: 1.35rem; font-weight: 600;
  font-family: Georgia, "Palatino Linotype", Palatino, "Times New Roman", serif;
  letter-spacing: .02em;
}
h1 span { color: var(--accent); font-style: italic; font-weight: 500; }
.side {
  height: 100%;
  background: var(--bg);
  padding: 14px 12px 24px;
  overflow-y: scroll;
  /* La barra de desplazamiento de este panel aparece justo al lado del
     tablero. Al mostrarse y ocultarse cambiaba el ancho útil, el contenido
     se reacomodaba y volvía a cambiar de alto: ese ciclo es el desplazamiento
     y el parpadeo. Reservando su espacio siempre, deja de oscilar. */
  scrollbar-gutter: stable;
  border-right: 1px solid rgba(var(--accent-rgb), .16);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.side h2 { margin: 16px 0 8px; font-size: .78rem; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
/* Llena lo que sobre en cada pantalla del menú (login, menú, cuenta,
   torneos, etc.): flex:1 hace que crezca según cuánto hueco quede en cada
   una, en vez de tener un tamaño fijo que en unas pantallas sobre y en
   otras falte. min-height evita que desaparezca del todo en las pantallas
   más largas que ya casi no dejan hueco. */
.ad-fill {
  display: flex; align-items: center; justify-content: center;
  flex: 1 1 auto; min-height: 90px; margin-top: 4px;
  background: var(--panel2); border: 1px solid rgba(255,255,255,.08); border-radius: 8px;
  color: var(--muted); font-size: .75rem; letter-spacing: .04em; text-transform: uppercase;
  opacity: .92;
}
.side-top { margin-bottom: 8px; }
.side-actions { display: flex; gap: 8px; margin: 8px 0; }
.side-actions button { margin-top: 0; }
.choice { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.choice button {
  margin: 0; background: var(--panel2); color: var(--text);
  font-weight: 650; font-size: .76rem; padding: 8px 6px;
}
.choice button.on { background: var(--accent); color: #12200a; }
.row-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.row-btns button { margin-top: 8px; }
.sr { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.panel { background: var(--panel); border-radius: 12px; padding: 14px; }
.panel h2 { margin: 0 0 10px; font-size: .95rem; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; }
label { display: block; font-size: .82rem; color: var(--muted); margin: 8px 0 4px; }
select, button, input { width: 100%; border: 0; border-radius: 8px; padding: 9px 10px; font: inherit; }
select, input { background: var(--panel2); color: var(--text); }
button { background: var(--accent); color: #1a140c; font-weight: 650; cursor: pointer; }
.side details {
  margin: 0;
  background: var(--panel);
  border: 1px solid rgba(var(--accent-rgb), .2);
  border-radius: 10px;
  padding: 0;
}
.side details > summary {
  cursor: pointer; color: var(--text); font-size: .78rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; list-style: none;
  padding: 11px 12px;
}
.side details > summary::-webkit-details-marker { display: none; }
.side details > summary::after { content: " ▾"; float: right; color: var(--accent); }
.side details[open] > summary { color: var(--accent); border-bottom: 1px solid rgba(var(--accent-rgb), .14); }
.side details .box { padding: 12px; display: flex; flex-direction: column; gap: 8px; }
.side-view { display: none; flex-direction: column; gap: 10px; animation: slidein .22s ease; }
.side-view.on { display: flex; }
@keyframes slidein { from { transform: translateX(18px); opacity: .4; } to { transform: none; opacity: 1; } }
.card { background: var(--panel); border: 1px solid rgba(var(--accent-rgb), .2); border-radius: 12px; padding: 12px; display: flex; flex-direction: column; gap: 12px; }
body.ready #back-menu { display: block !important; }
.card h3 { margin: 0 0 8px; font-size: .85rem; color: var(--accent); }
.aoe-menu { display: flex; flex-direction: column; gap: 10px; padding: 8px 2px 16px; }
.home-hero {
  display: flex; align-items: center; gap: 12px;
  padding: 8px 4px 14px; margin-bottom: 2px;
}
.home-hero img {
  width: 56px; height: 56px; border-radius: 14px;
  box-shadow: 0 6px 16px rgba(0,0,0,.35);
}
.home-title {
  margin: 0; font-size: 1.32rem; font-weight: 650;
  font-family: Georgia, "Palatino Linotype", Palatino, serif;
}
.home-title span { color: var(--accent); font-style: italic; }
.home-lead { margin: 4px 0 0; color: var(--muted); font-size: .82rem; }
.home-hero .aoe-kicker { text-align: left; margin: 0 0 2px; }
.aoe-kicker {
  margin: 4px 0 8px; text-align: center; font-size: .72rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--accent);
}
.aoe-btn {
  margin: 0; padding: 12px 14px; font-size: .92rem; font-weight: 650;
  letter-spacing: .03em;
  color: var(--text);
  background: linear-gradient(180deg, rgba(255,255,255,.04), transparent 40%), var(--panel2);
  border: 1px solid rgba(var(--accent-rgb), .38);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.08), 0 8px 18px rgba(0,0,0,.18);
  border-radius: 12px;
}
.aoe-btn:hover { filter: brightness(1.12); border-color: var(--accent); color: var(--text); }
.ghost-piece {
  /* Los !important de acá NO son un parche perezoso, hacen falta: el clon
     que se arrastra lleva las clases "piece" y "ghost-piece" a la vez, y
     ".piece" define position:relative y margin:13% tanto más abajo en este
     archivo (línea ~273) como en themes.css, que se carga después. Al tener
     las dos la misma especificidad, ganaba ".piece" y el clon quedaba
     position:relative — o sea, colocado al final del documento (debajo del
     tablero) en vez de seguir al dedo, que es lo que hacía que pareciera
     una ficha duplicada suelta. */
  position: fixed !important;
  pointer-events: none; z-index: 20; border-radius: 50%;
  /* margin:0 por el mismo motivo: el 13% de ".piece" se calcula sobre el
     ancho del padre, y al ser fixed el padre pasa a ser la pantalla entera,
     así que se convertía en decenas de píxeles de desvío. */
  margin: 0 !important;
  /* Ojo: acá NO va "inset/top/left con !important". startDrag posiciona la
     ficha con estilos en línea (style.left / style.top), y una regla
     !important de la hoja de estilos les ganaría, dejando la ficha clavada
     en un rincón. */
  box-sizing: border-box;
  /* Más marcada que antes: que se sienta "levantada" de la mesa mientras
     se arrastra con el dedo o el mouse. */
  box-shadow: 0 10px 22px rgba(0,0,0,.5), 0 2px 4px rgba(0,0,0,.35);
  opacity: .9;
}
.piece.flying { transition: transform .42s ease-in-out; z-index: 5; }
button.ghost { background: var(--panel2); color: var(--text); font-weight: 600; margin-top: 0; }
button.online { background: var(--online); color: #071018; }
button:hover { filter: brightness(1.06); }
/* Antes esta ocultación dependía de @media (max-width:900px) o de la
   clase native-app. Si esa medición de ancho falla en el WebView (ya nos
   pasó con el modo pantalla completa), ninguna de las dos reglas de abajo
   se aplica y el tablero queda visible SIEMPRE, en cualquier pantalla.
   Esta regla no depende de ninguna medición: arranca puesta directo en el
   HTML (<body class="board-hidden">, antes de que corra un solo script) y
   sólo la saca app.js cuando de verdad hay que mostrar el tablero. Con
   !important gana pase lo que pase con las demás reglas de abajo. */
/* El tablero arranca SIEMPRE oculto y sólo se muestra cuando app.js agrega
   body.board-active (hay partida en curso o análisis). Antes era al revés
   (visible por defecto, y había que ocultarlo), y eso tenía un problema:
   si cualquier cosa fallaba —un archivo viejo cacheado, un error de JS, una
   medición de ancho rara en el WebView— el tablero quedaba visible en el
   menú. Con esta forma, el peor caso posible es que el tablero no aparezca,
   nunca que aparezca cuando no corresponde.
   Se mantienen board-hidden/partida-en-curso por compatibilidad. */
.board-arena {
  display: none;
  grid-column: 2;
  grid-row: 1;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  align-items: stretch;
  flex-direction: row;
}
body.board-active .board-arena,
body.partida-en-curso .board-arena,
body.web-board-always .board-arena { display: flex; }
.board-wrap { display: none; }
body.board-active .board-wrap,
body.partida-en-curso .board-wrap,
body.web-board-always .board-wrap { display: flex; }
body.board-hidden:not(.web-board-always) .board-wrap,
body.board-hidden:not(.web-board-always) .board-arena { display: none !important; }
.board-wrap {
  flex: 1 1 0;
  flex-direction: column; align-items: center;
  width: 100%;
  padding: 6px 8px; height: 100%; max-height: 100%;
  overflow: hidden; min-width: 0; min-height: 0;
  touch-action: manipulation;
}
#board-stage {
  flex: 1 1 auto;
  min-height: 0; min-width: 0;
  width: 100%;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
/* Alturas reservadas: sin esto, cada cambio de texto movía el tablero
   hacia arriba y hacia abajo. */
.clocks { flex: 0 0 auto; }
.result { flex: 0 0 auto; height: 1.6em; overflow: hidden; }
.status { flex: 0 0 auto; height: 1.5em; overflow: hidden; }
.ad-banner { flex: 0 0 auto; }
#back-menu { display: none; }
.stack { display: flex; flex-direction: column; gap: 8px; }
.stack button, .stack input, .stack select { margin: 0; width: 100%; }
.clocks { width: min(100%, 640px); display: flex; justify-content: space-between; gap: 8px; margin: 0 0 6px; flex: 0 0 auto; }
.board {
  display: grid;
  grid-template-columns: repeat(var(--n, 8), 1fr);
  grid-template-rows: repeat(var(--n, 8), 1fr);
  aspect-ratio: 1 / 1;
  box-sizing: border-box;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  flex: 0 0 auto;
  /* Necesario para que las flechas del análisis (position:absolute) se
     posicionen respecto del tablero y no de la ventana. */
  position: relative;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 12px 40px rgba(0,0,0,.4);
  user-select: none;
}
.sq { position: relative; }
.sq.l { background: var(--light); }
.sq.d { background: var(--dark); }
/* Flechas del análisis, superpuestas al tablero.
   ANTES eran position:relative dentro de la rejilla del tablero: al ser un
   hijo más del grid, el SVG ocupaba espacio propio y empujaba las casillas,
   que quedaban aplastadas contra el borde de abajo mientras la flecha se
   estiraba enorme por el resto. Con position:absolute sale del flujo y se
   dibuja ENCIMA sin alterar una sola casilla. */
.an-arrow-svg {
  pointer-events: none;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 5;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,.5));
}
.sq.sel { outline: 3px solid var(--sel); outline-offset: -3px; }
.sq.hint::after { content: ""; position: absolute; width: 28%; height: 28%; border-radius: 50%; background: var(--move); left: 36%; top: 36%; }
.sq.cap::after { content: ""; position: absolute; inset: 8%; border: 4px solid var(--cap); border-radius: 50%; }
/* Resalta origen y destino de la última jugada, igual en local, vs. IA, y
   online. Un tono neutro y semitransparente para no confundirse con la
   selección activa (.sel, más marcada) ni con los puntos de jugada. */
.sq.last { box-shadow: inset 0 0 0 999px rgba(255, 214, 0, .28); }
/* Numeración oficial de la casilla (la misma que el historial de jugadas),
   chica y discreta en la esquina, como en un diagrama impreso. Sólo en
   casillas jugables. En pantallas muy chicas se opta por ocultarla más
   abajo, para no competir con las fichas. */
.sq.d[data-num]::before {
  content: attr(data-num);
  position: absolute; top: 2px; left: 4px;
  font-size: 0.6em; line-height: 1; font-weight: 600;
  color: var(--light); opacity: .45; pointer-events: none; z-index: 1;
}
.piece { position: relative; }
/* Rebote + desvanecido al capturar, en vez del corte seco anterior. */
.piece.captured {
  transition: transform .3s cubic-bezier(.34, 1.56, .64, 1), opacity .3s ease-out;
  transform: scale(.15) rotate(35deg);
  opacity: 0;
  pointer-events: none;
}
/* Destello al coronar: un "pop" breve sobre la corona recién aparecida. */
@keyframes coronaPop {
  0% { transform: scale(.2); opacity: 0; filter: drop-shadow(0 0 0 var(--gold, #d4af37)); }
  55% { transform: scale(1.5); opacity: 1; filter: drop-shadow(0 0 6px var(--gold, #d4af37)); }
  100% { transform: scale(1); opacity: 1; filter: drop-shadow(0 0 0 transparent); }
}
.crown-pop { animation: coronaPop .55s ease-out; }
.clocks { width: min(100%, 720px); }
.clock {
  flex: 1; background: var(--panel); border-radius: 8px; padding: 6px 10px;
  display: flex; justify-content: space-between; align-items: center;
}
.clock.active { outline: 2px solid var(--accent); }
.clock.low { outline: 2px solid #e8515b; }
.clock .who { font-size: .8rem; color: var(--muted); }
.clock .time { font-variant-numeric: tabular-nums; font-size: 1.1rem; font-weight: 700; }
.result {
  margin-top: 10px; text-align: center; font-size: 1.15rem; font-weight: 800;
  letter-spacing: .04em;
}
.result.win-a { color: #d7e8b0; }
.result.win-b { color: #c9c9c9; }
.result.draw { color: #f0d27a; }
.status { margin-top: 8px; text-align: center; color: var(--muted); }
.log { max-height: 220px; overflow: auto; font-size: .82rem; color: var(--muted); line-height: 1.45; }
.badge { display: inline-block; background: var(--panel2); padding: 2px 8px; border-radius: 999px; font-size: .75rem; }
.badge.on { background: #1e3a24; color: #9be59b; }
.badge.off { background: #3a2222; color: #f0a0a0; }
.stats { font-size: .9rem; line-height: 1.6; }
.room { font-size: 1.4rem; letter-spacing: .2em; text-align: center; font-weight: 700; margin: 8px 0; }
.hint-text { font-size: .78rem; color: var(--muted); margin-top: 10px; line-height: 1.45; }
.menu { position: fixed; inset: 0; z-index: 20; display: flex; align-items: center; justify-content: center; background: rgba(8,6,4,.72); }
.menu.hidden { display: none; }
.menu-card { width: min(420px, 92vw); background: var(--panel); border-radius: 16px; padding: 22px; box-shadow: 0 20px 50px rgba(0,0,0,.45); }
.menu-card h1 { margin: 0 0 6px; }
.menu-card p { color: var(--muted); margin: 0 0 16px; }
.xpbar { height: 8px; background: var(--panel2); border-radius: 99px; overflow: hidden; margin-top: 6px; }
.xpbar > span { display: block; height: 100%; background: var(--accent); width: 0; }
.profile-line { font-size: .88rem; color: var(--muted); }
.coins {
  display: inline-flex; align-items: center; gap: 6px;
  background: #3a2e14; color: #f3d27a; font-weight: 800;
  border-radius: 999px; padding: 4px 10px; font-size: .9rem;
  box-shadow: inset 0 0 0 1px #c9a44a;
}
.app.locked { display: none; }
.admin-card { width: min(1100px, 96vw); max-height: 90vh; overflow: auto; }
/* Alta de cuenta.
   ANTES: seis campos en UNA fila (grid de 6 columnas) y sin etiquetas: cada
   campo quedaba de ~90 px, los textos de ayuda se cortaban y no se entendía
   cuál era cuál. Ahora van apilados, con etiqueta arriba de cada uno. */
.admin-create {
  display: grid; grid-template-columns: 1fr; gap: 10px; margin: 12px 0;
  padding: 12px; border-radius: 8px;
  background: var(--panel2);
  border: 1px solid rgba(var(--accent-rgb), .18);
}
.admin-create input, .admin-create select { width: 100%; }
.admin-create label {
  display: block; margin-bottom: 3px;
  font-size: .7rem; color: var(--muted);
  text-transform: uppercase; letter-spacing: .05em;
}
/* De 700 px para arriba, los campos cortos comparten fila (pero de a dos,
   no de a seis). */
@media (min-width: 700px) {
  .admin-create { grid-template-columns: 1fr 1fr; }
  .admin-create .full { grid-column: 1 / -1; }
}
.admin-table-wrap { overflow: auto; margin: 12px 0; }
.admin-table { width: 100%; border-collapse: collapse; font-size: .82rem; }
.admin-table th, .admin-table td { border-bottom: 1px solid #3a3a42; padding: 6px; text-align: left; }
.admin-table input { width: 72px; padding: 4px; }
button.tiny { width: auto; display: inline-block; margin: 2px; padding: 5px 8px; font-size: .72rem; }
body.partida-en-curso .ad-fill,
body.partida-en-curso .desk-ads { display: none !important; }
body.partida-en-curso #ad-banner {
  min-height: 40px; max-height: 50px; margin-bottom: 4px; opacity: .8;
}
.ad-banner {
  width: min(100%, 728px); min-height: 50px; max-height: 70px; margin-bottom: 8px;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel2); border: 1px solid rgba(255,255,255,.08); border-radius: 8px;
  font-size: .8rem; opacity: .92;
}
.ad-banner a, .ad-popup-card a { color: var(--text); font-weight: 700; }
.ad-banner img, .ad-popup-card img { max-width: 100%; max-height: 90px; display: block; }
.ad-popup {
  position: fixed; inset: 0; z-index: 1100;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.32);
}
.ad-popup[data-kind="rewarded"] { background: rgba(0,0,0,.28); }
.ad-popup.hidden { display: none; }
.ad-popup-card {
  width: min(420px, 90vw); background: var(--panel); border-radius: 14px;
  padding: 28px 16px 16px; position: relative; text-align: center;
}
.ad-close {
  position: absolute; top: 6px; right: 8px; width: auto; padding: 4px 10px;
  background: var(--panel2); color: var(--text); margin: 0;
}

/* --- Modal de fin de partida (gana/pierde/empata) ------------------------
   z-index por encima de .board-wrap en pantalla completa (1000), así se ve
   siempre, tanto en escritorio como en la app a pantalla completa. */
.endgame-modal {
  position: fixed; inset: 0; z-index: 1200;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0,0,0,.55);
  padding: 16px;
}
.endgame-modal.hidden { display: none; }
.endgame-modal-card {
  width: min(360px, 92vw); background: var(--panel); border-radius: 14px;
  padding: 22px 18px 18px; text-align: center;
  box-shadow: 0 20px 60px rgba(0,0,0,.5);
}
.endgame-modal-card h2 { margin: 0 0 6px; font-size: 1.15rem; }
.endgame-modal-card p { margin: 0 0 16px; color: var(--muted); font-size: .82rem; min-height: 1.2em; }
.endgame-modal-ad {
  width: 250px; height: 250px; max-width: 100%; margin: 0 auto 18px;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel2); border: 1px solid rgba(255,255,255,.08); border-radius: 8px;
  font-size: .8rem; opacity: .92;
}
.endgame-modal-ad img { max-width: 100%; max-height: 100%; object-fit: contain; }
/* Los botones del final estaban pegados uno contra otro: era fácil tocar
   "Volver al menú" queriendo tocar "Analizar". Ahora van en columna con
   separación real y todos del mismo ancho. */
.endgame-actions {
  display: flex; flex-direction: column; gap: 10px; margin-top: 4px;
}
.endgame-actions button { margin: 0; width: 100%; }
#endgame-modal-close { margin: 0; width: 100%; }
.endgame-reward {
  border-color: #4caf82;
  color: #d8ffe9;
  background: linear-gradient(180deg, #16613f, #0d3d28);
}
.endgame-reward:disabled { opacity: .75; }
/* Monedas ganadas en la partida. */
.endgame-coins {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  margin: 0 0 14px; padding: 8px 12px; border-radius: 999px;
  background: rgba(var(--accent-rgb), .12);
  border: 1px solid rgba(var(--accent-rgb), .35);
  color: var(--accent); font-weight: 800; font-size: .9rem;
}
.endgame-coins i { font-style: normal; }

/* --- PWA: aviso de sin conexión e instalación ---------------------------
   Ambos siguen el mismo lenguaje que .aoe-btn: degradado azul, borde
   dorado, bisel superior y esquina de 4px. Sin esto desentonaban con el
   resto del menú. --------------------------------------------------------- */
.offline {
  /* Fijo, no sticky: .app mide 100vh, así que en el flujo normal
     empujaría el diseño y provocaría scroll. */
  position: fixed;
  top: env(safe-area-inset-top);
  left: 50%;
  transform: translateX(-50%);
  z-index: 70;
  max-width: 92vw;
  padding: 6px 16px;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: .72rem;
  font-weight: 700;
  text-align: center;
  color: #fff8d6;
  background: linear-gradient(180deg, #1a4a86, #0d2d58);
  border: 1px solid #d4b44a;
  border-top: 0;
  border-radius: 0 0 4px 4px;
  box-shadow: inset 0 -1px 0 rgba(255, 255, 255, .12), 0 2px 0 #081628;
}

.install {
  /* Hay una regla global "select, button, input { width: 100% }". Sin
     anularla, este botón fijo ocupaba el ancho entero de la pantalla. */
  position: fixed;
  right: calc(12px + env(safe-area-inset-right));
  bottom: calc(12px + env(safe-area-inset-bottom));
  z-index: 60;
  width: auto;
  max-width: 46vw;
  margin: 0;
  padding: 9px 14px;
  font-size: .74rem;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: #fff8d6;
  background: linear-gradient(180deg, #1a4a86, #0d2d58);
  border: 1px solid #d4b44a;
  border-radius: 4px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12), 0 2px 0 #081628;
  cursor: pointer;
  opacity: .9;
}
.install:hover { opacity: 1; filter: brightness(1.12); border-color: #ffe27a; color: #fff; }

/* Un atributo hidden nunca debe quedar pisado por reglas de layout. */
[hidden] { display: none !important; }

/* =========================================================================
   Paneles laterales — mismo lenguaje que .aoe-btn: azul con borde dorado,
   bisel superior y esquinas de 4px. Reemplazan a las listas de selects
   apiladas, que ocupaban toda la altura y no dejaban ver la jerarquía.
   ========================================================================= */

.panel {
  margin-bottom: 10px;
  background: linear-gradient(180deg, var(--panel2), var(--panel));
  border: 1px solid rgba(var(--accent-rgb), .38);
  border-radius: 4px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .07), 0 2px 0 var(--bg);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.panel-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; padding-bottom: 8px;
  border-bottom: 1px solid rgba(var(--accent-rgb), .22);
}
.panel-title {
  font-size: .82rem; font-weight: 800; letter-spacing: .14em;
  text-transform: uppercase; color: var(--accent);
}
.panel-tag {
  font-size: .7rem; color: var(--muted); text-align: right;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.fieldset { display: flex; flex-direction: column; gap: 6px; }
.fieldset-label {
  font-size: .68rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--muted);
}
.fieldset-hint { margin: 0; font-size: .72rem; color: var(--muted); line-height: 1.35; }
/* Con .chips de 2 columnas dentro, cada celda quedaba en 54px. En la barra
   lateral se apila; sólo se divide si hay ancho de sobra. */
.grid-2 { display: flex; flex-direction: column; gap: 12px; }
@media (min-width: 1500px) {
  .grid-2 { display: grid; grid-template-columns: 1fr 1fr; align-items: start; }
}

/* Fichas de selección: dos columnas por defecto, con la etiqueta de tamaño
   en una segunda línea para que el nombre no se corte. */
.chips { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; }
/* 4 columnas dejaban celdas de 54px para textos de 52px: cualquier fuente
   o idioma distinto lo rompía. Dos columnas es lo que entra de verdad. */
.chips.cols-4 { grid-template-columns: 1fr 1fr; }
.chips.cols-2 { grid-template-columns: 1fr 1fr; }
.chips button {
  margin: 0; width: 100%;
  padding: 7px 6px;
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  font-size: .72rem; font-weight: 700; line-height: 1.15;
  color: var(--text);
  background: var(--panel);
  border: 1px solid rgba(var(--accent-rgb), .22);
  border-radius: 3px;
  cursor: pointer;
}
.chips button i { font-style: normal; font-size: .62rem; opacity: .6; }
.chips button:hover { border-color: rgba(var(--accent-rgb), .55); color: var(--text); }
.chips button.on {
  color: var(--bg); background: var(--accent);
  border-color: var(--accent); font-weight: 800;
}

/* Botón compacto para filas con varias acciones */
.aoe-btn.slim, .ghost.slim {
  width: auto; margin: 0; padding: 7px 12px;
  font-size: .7rem; letter-spacing: .05em; white-space: nowrap;
}

/* --- Torneos --- */
.tourney-list { display: flex; flex-direction: column; gap: 6px; }
.tourney-item {
  /* En una barra de 280px sólo quedan 232px útiles. Texto y botones en la
     misma fila no entran: el Mundial dejaba 87px para el título y se
     superponía. Se apila en vertical. */
  display: flex; flex-direction: column; align-items: stretch; gap: 8px;
  padding: 10px;
  background: var(--panel);
  border: 1px solid rgba(var(--accent-rgb), .2);
  border-radius: 3px;
}
.tourney-item.premium { border-color: rgba(255, 210, 0, .42); }
.tourney-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tourney-info b { font-size: .8rem; color: var(--text); }
.tourney-info span { font-size: .68rem; color: var(--muted); line-height: 1.3; }
.tourney-actions { display: flex; gap: 6px; }
.tourney-actions > * { flex: 1 1 0; }
.tourney-item > .aoe-btn.slim,
.tourney-item > .ghost.slim { width: 100%; }
.tag-premium {
  display: inline-block; margin-left: 5px; padding: 1px 6px;
  background: var(--accent); color: #081528;
  border-radius: 999px; font-size: .58rem; font-weight: 800;
  letter-spacing: .08em; text-transform: uppercase; vertical-align: middle;
}

/* --- Cuenta --- */
.profile-block { font-size: .84rem; line-height: 1.6; }
/* Tarjeta de "ver anuncio y ganar monedas".
   ANTES: display:flex en una fila, con el texto y el botón lado a lado y sin
   permitir salto de línea. En la columna del menú (280 px) no entraban los
   dos, así que el botón se montaba encima del texto y quedaba ilegible.
   Ahora van uno debajo del otro: el texto explica, el botón ocupa todo el
   ancho y no puede pisarse con nada. */
.premium-card {
  display: flex; flex-direction: column; align-items: stretch; gap: 9px;
  padding: 11px;
  background: rgba(255, 210, 0, .07);
  border: 1px solid rgba(255, 210, 0, .32);
  border-radius: 6px;
}
.premium-text {
  font-size: .76rem; color: var(--light); line-height: 1.4; min-width: 0;
}
.premium-card button { width: 100%; margin: 0; white-space: normal; }

/* --- Secciones plegables: lo secundario deja de ocupar sitio --- */
.fold {
  background: var(--panel);
  border: 1px solid rgba(var(--accent-rgb), .18);
  border-radius: 3px;
}
.fold > summary {
  cursor: pointer; list-style: none; padding: 8px 10px;
  font-size: .7rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--muted);
}
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::after { content: " ▾"; opacity: .55; }
.fold[open] > summary::after { content: " ▴"; }
.fold > summary:hover { color: var(--accent); }
.fold > *:not(summary) { padding: 0 10px 10px; }
.fold .log { max-height: 180px; }

.build-stamp {
  flex: 0 0 auto; text-align: center; font-size: .62rem;
  color: var(--muted); opacity: .5; letter-spacing: .06em;
}

/* =========================================================================
   Contador por jugada. Aparece sólo en el reloj de quien tiene el turno.
   Su función es antiabandono: avisar de que hace rato que nadie mueve.
   ========================================================================= */
.movebar {
  display: flex; align-items: center; gap: 6px;
  min-width: 62px;
}
.movebar-num {
  font-variant-numeric: tabular-nums;
  font-size: .78rem; font-weight: 800;
  color: var(--muted); min-width: 2ch; text-align: right;
}
.movebar-track {
  flex: 1 1 auto; height: 4px; min-width: 28px;
  background: rgba(255, 255, 255, .12);
  border-radius: 999px; overflow: hidden;
}
.movebar-track > i {
  display: block; height: 100%; width: 100%;
  background: var(--accent);
  /* La transición es lineal y corta: si fuera suave, el número y la barra
     se verían desincronizados. */
  transition: width .2s linear, background-color .2s linear;
}
/* Escalado de urgencia */
.movebar.warn .movebar-num { color: #ffc766; }
.movebar.warn .movebar-track > i { background: #ffa733; }
.movebar.danger .movebar-num { color: #ff8a80; }
.movebar.danger .movebar-track > i { background: #e8515b; }
.movebar.over .movebar-num { color: #ff8a80; }
.clock.urge { outline: 2px solid #e8515b; animation: pulseClock 1s ease-in-out infinite; }
@keyframes pulseClock {
  0%, 100% { box-shadow: 0 0 0 0 rgba(232, 81, 91, .5); }
  50%      { box-shadow: 0 0 0 6px rgba(232, 81, 91, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .clock.urge { animation: none; }
}

/* Casilla ya recorrida dentro de una captura en curso. Sin esta marca no se
   ve por dónde va la ruta cuando hay varias posibles. */
.sq.step::before {
  content: ""; position: absolute; inset: 18%;
  border: 2px dashed var(--accent); border-radius: 50%; opacity: .55;
}

/* =========================================================================
   Análisis de partida
   ========================================================================= */
.an-progress { display: flex; flex-direction: column; gap: 6px; }
.an-bar { height: 6px; background: rgba(255,255,255,.12); border-radius: 999px; overflow: hidden; }
.an-bar > i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .15s linear; }

.an-summary { display: flex; flex-direction: column; gap: 2px; font-size: .74rem; }
.an-row { display: grid; grid-template-columns: 1fr auto auto; gap: 8px; padding: 4px 6px; border-radius: 3px; }
.an-row b { min-width: 3.2ch; text-align: right; font-variant-numeric: tabular-nums; }
.an-row:nth-child(even) { background: rgba(255,255,255,.04); }
.an-row.an-head { color: var(--muted); font-size: .66rem; text-transform: uppercase; letter-spacing: .08em; }
.an-row.an-head b { color: var(--accent); }

.an-graph { background: var(--panel); border: 1px solid rgba(var(--accent-rgb), .18); border-radius: 3px; padding: 6px; }

/* La lista puede tener cien jugadas: se limita el alto y se desplaza sola. */
.an-moves { max-height: 260px; overflow-y: auto; scrollbar-gutter: stable; display: flex; flex-direction: column; gap: 2px; }
.an-move {
  width: 100%; margin: 0; display: grid;
  grid-template-columns: 2.4ch 1fr auto; gap: 6px; align-items: baseline;
  padding: 5px 7px; text-align: left; font-size: .72rem;
  background: var(--panel); border: 1px solid transparent; border-radius: 3px;
  color: var(--text); cursor: pointer;
}
.an-move:hover { border-color: rgba(255,226,122,.4); }
.an-move.on { border-color: var(--accent); background: var(--panel2); }
.an-n { color: var(--muted); font-variant-numeric: tabular-nums; }
.an-sq { font-weight: 700; font-variant-numeric: tabular-nums; }
.an-tag { font-size: .64rem; }
.an-best { grid-column: 1 / -1; font-size: .64rem; color: var(--muted); }

/* --- Publicidad: dos espacios en escritorio ------------------------------
   1) Banner horizontal bajo el tablero (#ad-banner), ya existente.
   2) Rectángulo en la barra lateral (#ad-side), al final del panel.
   Ninguno se superpone al tablero ni desplaza los controles.
   El intersticial entre partidas queda sólo para móvil: en escritorio
   interrumpe demasiado y espanta al jugador serio. */
.ad-side {
  margin-top: auto;
  padding: 8px;
  background: var(--panel);
  border: 1px solid rgba(var(--accent-rgb), .18);
  border-radius: 3px;
  display: flex; flex-direction: column; gap: 6px;
}
.ad-side .ad-note {
  font-size: .58rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); opacity: .7;
}
#ad-side-body { min-height: 200px; display: flex; align-items: center; justify-content: center; }
#ad-side-body img, #ad-side-body a { max-width: 100%; }
/* En pantallas bajas o estrechas estorba más de lo que aporta. */
@media (max-width: 900px) {
  .ad-side { display: none !important; }
}

/* --- Formulario de creación de torneos (panel admin) ---
   ANTES: "repeat(auto-fit, minmax(150px, 1fr))", o sea todos los campos que
   entraran metidos en la misma fila. Con quince campos, en una pantalla ancha
   quedaban seis o siete por renglón de 150 px: las etiquetas se cortaban, se
   pisaban entre sí y no se sabía a qué campo correspondía cada una.
   Ahora es una sola columna en el celular y DOS como máximo en la
   computadora, con cada etiqueta pegada a su campo. */
.admin-create-wide {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
  align-items: start;
  padding: 14px;
  border-radius: 8px;
  background: var(--panel2);
  border: 1px solid rgba(var(--accent-rgb), .18);
}
@media (min-width: 760px) {
  .admin-create-wide { grid-template-columns: 1fr 1fr; column-gap: 18px; }
}
/* Cada campo con su etiqueta, apilados: label arriba, control abajo. */
.admin-create-wide > label {
  display: block; margin: 0 0 -6px;
  font-size: .7rem; color: var(--muted);
  text-transform: uppercase; letter-spacing: .05em; font-weight: 700;
}
.admin-create-wide input,
.admin-create-wide select { width: 100%; margin: 0; }
.admin-create-wide .admin-check {
  display: flex; align-items: center; gap: 8px; font-size: .78rem;
}
.admin-create-wide .admin-check input { width: auto; }
/* Los bloques anchos (duración, premios, restricciones) ocupan la fila entera
   para que sus tres campitos no compitan con otra columna al lado. */
.admin-create-wide .ev-duracion,
.admin-create-wide .ev-premios,
.admin-create-wide .ev-medallas,
.admin-create-wide .fieldset-hint,
.admin-create-wide button { grid-column: 1 / -1; }
/* Separador visual entre grupos de campos. */
.admin-create-wide > label.grupo {
  grid-column: 1 / -1;
  margin-top: 8px; padding-top: 12px;
  border-top: 1px solid rgba(255,255,255,.1);
  color: var(--accent); font-size: .74rem;
}

/* --- Tarjetas de mundial (panel Torneos) --- */
.world-item { flex-direction: column; align-items: stretch; }
.world-item .tourney-info { gap: 3px; }
.ev-stage { font-size: .62rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; }
.ev-dates, .ev-req, .ev-prize, .ev-players { font-size: .68rem; color: var(--muted); }
.ev-prize { color: var(--accent); font-weight: 700; }
.ev-registered { color: #4caf82; font-size: .74rem; font-weight: 700; }
.ev-blocked { color: #e8944a; font-size: .68rem; }
.ev-champ { color: var(--accent); font-weight: 800; font-size: .8rem; }

/* --- Indicador de final resuelto (tabla generada en el navegador) --- */
.endgame-tag {
  text-align: center; font-size: .72rem; font-weight: 700;
  padding: 3px 0; letter-spacing: .02em;
}
.endgame-tag.win  { color: #4caf82; }
.endgame-tag.draw { color: #e8c05a; }
.endgame-tag.loss { color: #e8515b; }
.an-final { font-size: .64rem; color: var(--accent); }

/* --- Panel de estadísticas del admin --- */
.stats-cards {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 6px; margin: 8px 0;
}
.stat-card {
  background: var(--panel); border: 1px solid rgba(var(--accent-rgb), .18); border-radius: 4px;
  padding: 8px; text-align: center; display: flex; flex-direction: column; gap: 2px;
}
.stat-card b { font-size: 1.1rem; color: var(--accent); font-variant-numeric: tabular-nums; }
.stat-card span { font-size: .62rem; color: var(--muted); text-transform: uppercase; letter-spacing: .03em; }
.stats-charts {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 10px; margin: 10px 0;
}
.stats-chart-box {
  background: var(--panel); border: 1px solid rgba(var(--accent-rgb), .12); border-radius: 4px; padding: 8px;
  display: flex; flex-direction: column; gap: 4px;
}
.stats-variants { margin: 10px 0; }
.admin-search {
  width: 100%; margin-bottom: 8px; padding: 7px 10px;
  background: var(--panel); border: 1px solid rgba(var(--accent-rgb), .25); border-radius: 3px;
  color: var(--text); font-size: .8rem;
}

/* --- Ranking (panel Torneos) --- */
.rank-row {
  display: grid; grid-template-columns: 2.4em 1fr auto auto;
  gap: 8px; align-items: center; font-size: .74rem;
}
.rank-pos { color: var(--muted); font-variant-numeric: tabular-nums; }
.rank-elo { font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.rank-rec { font-size: .64rem; color: var(--muted); }
.rank-me { border-color: var(--accent); background: var(--panel2); }

/* --- Pestañas del panel de administrador --- */
.admin-tabs { margin-bottom: 10px; }
.admin-tab-panel.hidden { display: none; }

/* PARTIDA A PANTALLA COMPLETA EN CELULAR (TODAS LAS MODALIDADES)
   La clase se añade únicamente cuando existe una partida online y la ventana
   es de tamaño móvil. El menú queda completamente fuera del flujo y el tablero
   pasa a ser la única pantalla de juego. */
.mobile-game-actions { display: none; gap: 8px; width: min(100%, 640px); margin: 0 0 8px; }
body.partida-en-curso .mobile-game-actions:not([hidden]) { display: flex; }
@media (max-width: 900px) {
  body.mobile-game-fullscreen .app { display: block; padding: 0; }
  body.mobile-game-fullscreen .side { display: none !important; }
  body.mobile-game-fullscreen .board-wrap {
    display: flex !important;
    position: fixed;
    inset: 0;
    z-index: 1000;
    width: 100vw;
    height: 100dvh;
    max-width: none;
    max-height: none;
    padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);
    background: var(--bg);
  }
  /* Publicidad arriba de todo. */
  body.mobile-game-fullscreen #ad-banner {
    display: flex !important; align-items: center; justify-content: center;
    order: -2; flex: 0 0 auto; width: 100%; height: 52px;
    background: var(--panel); border-bottom: 1px solid rgba(var(--accent-rgb), .18);
    color: var(--muted); font-size: .68rem; letter-spacing: .04em; text-transform: uppercase;
    margin: 0 0 8px;
  }
  /* Relojes justo debajo de la publicidad. */
  body.mobile-game-fullscreen .clocks { order: -1; margin: 0 auto 6px; padding: 0 8px; }
  /* Tablero en el medio: se le pone un tope más chico (no 100% del alto
     disponible) y márgenes a los costados, para que se vea un tablero de
     tamaño natural y no estirado de borde a borde. */
  body.mobile-game-fullscreen #board-stage {
    /* Menos relleno a los costados para que el tablero pueda crecer: antes
       20px por lado le comían casi el 10% del ancho útil. */
    order: 0; flex: 1 1 auto; min-height: 0; padding: 4px 6px 8px;
  }
  /* Tablero MÁS GRANDE. El truco para que no se deforme es que el ancho y el
     alto usen exactamente la misma expresión min(): así siempre es un
     cuadrado perfecto, y el min() elige el límite que se alcance primero
     (el ancho en pantallas angostas, el alto en pantallas bajas). Antes era
     84vw/54vh; ahora 96vw/64vh, que en un celular típico agranda el tablero
     cerca de un 15% sin que se salga ni se estire. */
  body.mobile-game-fullscreen .board {
    width: min(96vw, 64vh);
    height: min(96vw, 64vh);
    max-width: 96vw;
    max-height: 64vh;
  }
  /* #status justo debajo del tablero. */
  body.mobile-game-fullscreen #status { order: 1; }
  /* Empate / Abandonar, siempre abajo de todo. */
  body.mobile-game-fullscreen .mobile-game-actions {
    display: flex;
    order: 2;
    gap: 8px;
    width: min(100%, 640px);
    flex: 0 0 auto;
    margin: 6px auto 0;
    padding: 0 8px;
  }
  body.mobile-game-fullscreen .mobile-game-actions button { margin: 0; flex: 1 1 0; }
  body.mobile-game-fullscreen #build-stamp,
  body.mobile-game-fullscreen #result,
  body.mobile-game-fullscreen #endgame-tag { display: none !important; }
  /* #status SIGUE visible (compacto): ahí aparece el aviso de "varias
     capturas terminan ahí, elegí el camino pulsando las casillas" cuando
     hay más de una opción. Ocultarlo (como antes) dejaba esa instrucción
     invisible y parecía que el juego no dejaba elegir. */
  body.mobile-game-fullscreen #status {
    flex: 0 0 auto; font-size: .68rem; text-align: center;
    margin: 0 0 4px; height: auto; opacity: .85;
  }
}

/* ===========================================================================
   PANTALLA DE ANÁLISIS EN CELULAR
   El tablero pasa a ocupar la mitad de arriba (fijo, siempre a la vista) y el
   panel de análisis queda abajo con scroll propio. Antes todo iba apilado en
   la misma columna: el tablero quedaba chico y había que bajar hasta el final
   para verlo, justo lo contrario de lo que hace falta al repasar jugadas.
   =========================================================================== */

/* Cartel con el veredicto de la jugada que se está viendo. */
.an-now {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px;
  padding: 9px 11px; border-radius: 8px;
  background: var(--panel2); border: 1px solid rgba(var(--accent-rgb), .22);
}
.an-now-n {
  min-width: 1.8em; text-align: center; font-variant-numeric: tabular-nums;
  font-size: .7rem; color: var(--muted);
}
.an-now-mv { font-weight: 800; font-size: .95rem; letter-spacing: .02em; }
.an-now-tag { font-weight: 700; font-size: .78rem; }
.an-now-best {
  flex: 1 0 100%; font-size: .72rem; color: var(--muted);
}

/* Referencia de colores de las flechas del tablero. */
.an-legend {
  display: flex; flex-wrap: wrap; gap: 4px 14px;
  font-size: .66rem; color: var(--muted); padding: 0 2px;
}
.an-legend span { display: inline-flex; align-items: center; gap: 5px; }
.an-legend i {
  width: 16px; height: 3px; border-radius: 2px; display: inline-block;
}
.an-legend i.dash {
  background: none !important;
  border-top: 3px dashed #34d15c; height: 0;
}

@media (max-width: 900px) {
  body.mobile-analysis .app { display: block; padding: 0; overflow: hidden; }

  /* Tablero fijo en la mitad de arriba. */
  body.mobile-analysis .board-wrap {
    display: flex !important;
    position: fixed;
    top: 0; left: 0; right: 0;
    height: 52vh;
    z-index: 850;
    padding: env(safe-area-inset-top) 6px 4px;
    background: var(--bg);
    border-bottom: 1px solid rgba(var(--accent-rgb), .18);
  }
  /* Durante el análisis no hacen falta relojes, resultado ni publicidad
     dentro del tablero: el espacio se lo lleva entero el tablero. */
  body.mobile-analysis .clocks,
  body.mobile-analysis #ad-banner,
  body.mobile-analysis #result,
  body.mobile-analysis #build-stamp,
  body.mobile-analysis #endgame-tag,
  body.mobile-analysis .mobile-game-actions { display: none !important; }
  body.mobile-analysis #board-stage {
    flex: 1 1 auto; min-height: 0; padding: 2px 0 0;
  }
  /* Ancho y alto con la MISMA expresión, igual que en la partida a pantalla
     completa. Antes acá sólo se fijaba el ancho y el alto seguía viniendo del
     "height:100%" de la regla base, así que el tablero se estiraba o aplastaba
     según lo que midiera el contenedor en vez de quedar cuadrado. */
  body.mobile-analysis .board {
    width: min(92vw, 44vh);
    height: min(92vw, 44vh);
    max-width: 92vw;
    max-height: 44vh;
    margin: 0 auto;
  }
  /* El turno queda como una línea fina al pie del tablero. */
  body.mobile-analysis #status {
    flex: 0 0 auto; font-size: .66rem; color: var(--muted);
    padding: 2px 0 0; text-align: center;
  }

  /* Panel de análisis: la mitad de abajo, con scroll propio. */
  body.mobile-analysis .side {
    position: fixed;
    top: 52vh; bottom: 0; left: 0; right: 0;
    z-index: 851;
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    /* "contain" en vez de "none": el panel se desplaza normalmente, pero al
       llegar al final el rebote NO se transmite a la página de atrás. */
    overscroll-behavior: contain;
    padding: 8px 10px calc(14px + env(safe-area-inset-bottom));
    background: var(--bg);
  }
  /* El hueco de publicidad que rellena el menú no tiene sentido acá: se
     comería el espacio de la lista de jugadas. */
  /* El relleno elástico del menú no va (se comería la lista de jugadas),
     pero la barra fija de abajo SÍ se mantiene: es un espacio de anuncio
     que no le quita lugar al contenido porque el panel ya reserva su
     altura con el padding-bottom de abajo. */
  body.mobile-analysis .ad-fill { display: none !important; }
  body.mobile-analysis .ad-bar-global { display: flex !important; }
  body.mobile-analysis .side { padding-bottom: calc(66px + env(safe-area-inset-bottom)); }

  /* La lista de jugadas ya vive dentro de un panel con scroll, así que no
     necesita su propia altura máxima: que crezca y se desplace todo junto. */
  body.mobile-analysis .an-moves { max-height: 36vh; overflow-y: auto; }

  /* El veredicto de la jugada actual queda CLAVADO arriba del panel: es el
     dato que se está mirando al pasar de jugada ("qué jugué y cuál era la
     mejor"), así que no puede perderse al desplazar la lista. */
  body.mobile-analysis #an-now {
    position: sticky; top: 0; z-index: 3;
    margin: 0 0 4px;
  }

  /* Botones de navegación pegados debajo del veredicto.
     ANTES tenían "flex: 1" con 12px de relleno: como .row-btns permite salto
     de línea, los cuatro no entraban en un renglón y se acomodaban en una
     cuadrícula de 2x2 gigante que se comía media pantalla y empujaba la lista
     de jugadas fuera de la vista.
     La causa real: .row-btns es "grid-template-columns: 1fr 1fr", o sea DOS
     columnas fijas, así que cuatro botones siempre iban a caer en 2x2. Acá se
     pasa a cuatro columnas y se saca el margen superior de cada botón. */
  body.mobile-analysis #an-nav {
    position: sticky; top: 42px; z-index: 2;
    background: var(--bg); padding: 5px 0; margin: 0 0 2px;
    grid-template-columns: repeat(4, 1fr);
  }
  body.mobile-analysis #an-nav button {
    margin-top: 0; padding: 9px 2px; font-size: .95rem; min-width: 0;
  }
  /* Los de errores son tres: ◀ | contador | ▶ */
  body.mobile-analysis #an-err-nav {
    grid-template-columns: auto 1fr auto;
    align-items: center;
  }
  body.mobile-analysis #an-err-nav button { margin-top: 0; padding: 8px 10px; }
}

/* ===========================================================================
   HUD del jugador (cabecera del menú): nombre, Elo y monedas siempre a la
   vista. Antes sólo se veía el Elo suelto y el nombre debajo, y las monedas
   había que ir a buscarlas a la pantalla de Cuenta.
   =========================================================================== */
.hud {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; flex-wrap: wrap; margin-top: 2px;
}
.hud-name {
  font-size: .88rem; font-weight: 700; color: var(--text);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.hud-stats { display: flex; align-items: center; gap: 6px; }
.hud-chip {
  display: inline-flex; align-items: center; gap: 5px;
  border-radius: 999px; padding: 4px 10px;
  font-size: .82rem; font-weight: 800; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
/* Elo: mismo aspecto dorado que tenía antes. */
.hud-elo {
  background: #3a2e14; color: #f3d27a;
  box-shadow: inset 0 0 0 1px #c9a44a;
}
.hud-elo.up { color: #9be8b8; box-shadow: inset 0 0 0 1px #4caf82; }
.hud-elo.down { color: #f0a9ad; box-shadow: inset 0 0 0 1px #a4525a; }
/* Monedas: se diferencian del Elo para no confundirlos de un vistazo. */
.hud-coins {
  background: var(--panel2); color: var(--accent);
  box-shadow: inset 0 0 0 1px rgba(var(--accent-rgb), .45);
}
.hud-coins i { font-style: normal; font-size: .88em; }

/* Contador de gente sobre cada botón de modalidad (pantalla En línea). */
.chip-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.5em; height: 1.5em; margin-left: 6px; padding: 0 4px;
  border-radius: 999px; font-size: .68rem; font-weight: 800;
  background: var(--panel2); color: var(--muted);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.14);
}
/* Verde = hay alguien esperando rival ahí: entrás y arranca en el acto. */
#online-variant-choice button.hay-espera .chip-count {
  background: #16613f; color: #d8ffe9;
  box-shadow: inset 0 0 0 1px #4caf82;
}
#online-variant-choice button.hay-espera {
  border-color: #4caf82;
}

/* Duración del torneo (días / horas / minutos) en el panel de administrador. */
.ev-duracion { display: flex; gap: 8px; }
.ev-duracion span { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.ev-duracion input { width: 100%; }
.ev-duracion i {
  font-style: normal; font-size: .66rem; color: var(--muted);
  text-transform: uppercase; letter-spacing: .06em;
}

/* Premios en monedas del podio (panel de administrador). */
.ev-premios { display: flex; gap: 8px; }
.ev-premios span { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.ev-premios input { width: 100%; }
.ev-premios i {
  font-style: normal; font-size: .68rem; color: var(--muted);
  letter-spacing: .04em;
}

/* Tiempo fijo de las partidas en línea (ya no es un selector). */
.online-clock-fixed {
  margin: 0; padding: 9px 12px; border-radius: 8px;
  background: var(--panel2); border: 1px solid rgba(var(--accent-rgb), .22);
  color: var(--text); font-weight: 700; font-size: .88rem; text-align: center;
}

/* Restricción por medallas al crear un torneo (panel de administrador). */
.ev-medallas { display: flex; flex-direction: column; gap: 6px; }
.ev-check {
  display: flex; align-items: center; gap: 8px;
  font-size: .8rem; color: var(--text); cursor: pointer;
}
.ev-check input { width: auto; margin: 0; }
.ev-min-medals { display: flex; align-items: center; gap: 8px; }
.ev-min-medals input { width: 5em; }
.ev-min-medals i { font-style: normal; font-size: .7rem; color: var(--muted); }

/* Medallero del jugador (pantalla Cuenta). */
.medallero { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.medalla {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 9px; border-radius: 999px; font-size: .72rem; font-weight: 700;
  background: var(--panel2); box-shadow: inset 0 0 0 1px rgba(255,255,255,.12);
}
.medalla.oro { box-shadow: inset 0 0 0 1px #d4af37; color: #f3d27a; }
.medalla.plata { box-shadow: inset 0 0 0 1px #b8c0c8; color: #dde3e8; }
.medalla.bronce { box-shadow: inset 0 0 0 1px #b07a4a; color: #e4b98f; }

/* Historial de partidas (pantalla Cuenta). */
.hist-list { display: flex; flex-direction: column; gap: 5px; margin-top: 4px; }
.hist-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas: "res vs num" "meta meta fecha";
  gap: 2px 8px;
  padding: 8px 10px; border-radius: 8px;
  background: var(--panel2);
  border-left: 3px solid var(--muted);
  font-size: .78rem;
}
.hist-row.h-win { border-left-color: #4caf82; }
.hist-row.h-draw { border-left-color: #c9a44a; }
.hist-row.h-loss { border-left-color: #a4525a; }
.hist-res { grid-area: res; font-weight: 800; }
.h-win .hist-res { color: #9be8b8; }
.h-draw .hist-res { color: #f3d27a; }
.h-loss .hist-res { color: #f0a9ad; }
.hist-vs { grid-area: vs; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hist-meta { grid-area: meta; color: var(--muted); font-size: .68rem; }
.hist-num { grid-area: num; display: flex; gap: 7px; font-size: .72rem; }
.hist-elo { color: var(--accent); }
.hist-coin { color: #f3d27a; }
.hist-fecha { grid-area: fecha; color: var(--muted); font-size: .66rem; text-align: right; }

/* ===========================================================================
   FICHA DEL JUGADOR (pantalla Cuenta)
   Cada dato en su tarjeta, con nombre arriba y explicación abajo. Antes era
   un párrafo con números sueltos que no se entendían.
   =========================================================================== */
.perfil-nombre {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-bottom: 10px;
}
.perfil-nombre b { font-size: 1.05rem; }
.perfil-nombre span {
  font-size: .72rem; color: var(--accent); font-weight: 700;
  padding: 2px 8px; border-radius: 999px;
  background: rgba(var(--accent-rgb), .12);
}
.perfil-datos { display: flex; flex-direction: column; gap: 7px; }
.dato {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas: "tit val" "exp exp";
  gap: 1px 10px;
  padding: 9px 11px; border-radius: 8px;
  background: var(--panel2);
}
.dato-tit {
  grid-area: tit; font-size: .72rem; color: var(--muted);
  text-transform: uppercase; letter-spacing: .05em; font-weight: 700;
}
.dato-tit i { font-style: normal; font-weight: 800; }
.dato-tit i.sube { color: #9be8b8; }
.dato-tit i.baja { color: #f0a9ad; }
.dato-val {
  grid-area: val; font-size: 1.02rem; font-weight: 800;
  color: var(--text); font-variant-numeric: tabular-nums;
}
.dato-exp {
  grid-area: exp; font-size: .68rem; color: var(--muted); line-height: 1.35;
}

/* ===========================================================================
   MODO VISUAL — accesible para quien no lee
   ---------------------------------------------------------------------------
   Se activa con el botón del ojo (👁) de la barra superior. Agrega dibujos a
   todas las opciones y agranda todo lo que se toca. NO quita ninguna
   modalidad ni ninguna función: es una capa encima de lo que ya existe.

   Las medidas siguen lo recomendado en accesibilidad:
   - Objetivos táctiles de 56 px o más (el mínimo habitual es 44).
   - Separación generosa: los elementos apretados hacen que se toque el de al
     lado sin querer, y eso perjudica a todos, no sólo a quien tiene
     dificultades motrices.
   - Contraste alto y bordes visibles: nada de botones "fantasma" sin borde,
     que no se leen como botones si no se sabe de antemano que lo son.
   - Nunca sólo color: el estado activo se marca con borde grueso + fondo +
     una marca ✓, para que funcione en blanco y negro y al sol.
   =========================================================================== */

/* El interruptor, siempre visible en la barra de arriba. */
.visual-toggle.on {
  background: rgba(var(--accent-rgb), .2);
  border-color: var(--accent); color: var(--accent);
}

/* --- El pictograma dentro de cada botón --- */
.vico {
  font-size: 1.15rem; line-height: 1;
  /* Los emoji de bandera no existen en algunas fuentes de Android viejo; la
     pila de respaldo evita que se vea el cuadrito de "carácter faltante". */
  font-family: "Noto Color Emoji", "Segoe UI Emoji", "Apple Color Emoji", sans-serif;
}
/* Tamaño del tablero (8×8, 10×10) como dato aparte y legible. */
.vtam {
  display: block; width: 100%;
  font-size: .62rem; color: var(--muted); font-variant-numeric: tabular-nums;
}

body.modo-visual .vico { font-size: 1.9rem; display: block; margin: 0 auto 2px; }
body.modo-visual .vtam { font-size: .72rem; font-weight: 700; }

/* --- Botones grandes --- */
body.modo-visual .aoe-btn {
  min-height: 68px; font-size: 1.05rem; font-weight: 800;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; padding: 12px 14px; margin-bottom: 12px;
  border-width: 2px;
}
body.modo-visual .aoe-btn .vico { font-size: 2.1rem; }

/* --- Opciones (rival, modalidad, dificultad) --- */
body.modo-visual .choice button,
body.modo-visual .chips button {
  min-height: 76px; padding: 10px 8px;
  font-size: .82rem; font-weight: 700; line-height: 1.15;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  border-width: 2px; border-radius: 12px;
}
body.modo-visual .chips { gap: 10px; }
body.modo-visual .choice { gap: 10px; }

/* Estado elegido: NO se distingue sólo por color. Lleva borde grueso, fondo
   propio y una marca ✓ arriba a la derecha, así se ve en blanco y negro,
   con daltonismo y con la pantalla al sol. */
body.modo-visual .choice button.on,
body.modo-visual .chips button.on {
  position: relative;
  border-color: var(--accent); border-width: 3px;
  background: rgba(var(--accent-rgb), .18);
  box-shadow: 0 0 0 2px rgba(var(--accent-rgb), .25);
}
body.modo-visual .choice button.on::after,
body.modo-visual .chips button.on::after {
  content: "✓";
  position: absolute; top: 3px; right: 6px;
  font-size: .9rem; font-weight: 900; color: var(--accent);
}

/* La dificultad en estrellas se lee mejor grande y dorada. */
body.modo-visual #diff-choice .vico {
  font-size: 1.25rem; color: #f3d27a; letter-spacing: -1px;
}

/* --- Textos y campos más grandes en general --- */
body.modo-visual .fieldset-label { font-size: .82rem; font-weight: 800; }
body.modo-visual .fieldset-hint { font-size: .76rem; line-height: 1.4; }
body.modo-visual input,
body.modo-visual select { min-height: 52px; font-size: 1rem; }
body.modo-visual .ghost { min-height: 52px; font-size: .92rem; border-width: 2px; }
/* El interruptor del ojo no crece con el resto: tiene que quedar chico en la
   barra para no empujar el título fuera de pantalla. */
body.modo-visual .visual-toggle { min-height: 40px; font-size: 1.3rem; }

/* --- Tarjetas de la ficha del jugador, más legibles --- */
body.modo-visual .dato-val { font-size: 1.2rem; }
body.modo-visual .dato-exp { font-size: .76rem; }

/* --- Historial: más aire entre filas --- */
body.modo-visual .hist-row { padding: 12px; font-size: .86rem; }

/* Salto a los errores dentro del análisis. */
.an-errores { align-items: center; gap: 8px; }
.an-errores button { flex: 0 0 auto; min-width: 62px; }
.an-errores button:disabled { opacity: .35; }
.an-err-count {
  flex: 1; text-align: center;
  font-size: .72rem; font-weight: 700; color: var(--muted);
}
body.modo-visual .an-errores button { min-width: 80px; }

/* Apartado "Información" de la partida. */
.info-fila {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 10px; padding: 5px 0;
  border-bottom: 1px solid rgba(255,255,255,.07);
  font-size: .8rem;
}
.info-fila:last-of-type { border-bottom: none; }
.info-fila span { color: var(--muted); }
.info-fila b { font-variant-numeric: tabular-nums; }

/* Botón de cambio de vista: ahora lleva una palabra, no un ícono suelto. */
.visual-toggle {
  font-size: .8rem; font-weight: 700; letter-spacing: .02em;
  padding: 7px 12px; min-width: 0; min-height: 38px;
}

/* ===========================================================================
   PANEL DE ESCRITORIO (menú principal en pantallas anchas)
   ---------------------------------------------------------------------------
   Ocupa la columna grande, que antes quedaba completamente vacía mientras el
   menú se apretaba en los 280 px de la barra lateral. Sólo existe de 901 px
   para arriba: en el celular el menú sigue en su única columna.
   =========================================================================== */
.maint-banner {
  position: sticky; top: 0; z-index: 40;
  display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: center;
  justify-content: center;
  padding: 10px 14px;
  background: #16325c;
  color: #eaf4ff;
  font-size: .92rem;
  text-align: center;
}
.maint-banner[hidden] { display: none !important; }
body.mantenimiento #find,
body.mantenimiento #create,
body.mantenimiento #join { opacity: .55; pointer-events: none; }
.brand-lockup { display: flex; align-items: center; gap: 10px; }
.brand-logo {
  width: 44px; height: 44px; border-radius: 10px; object-fit: cover;
  box-shadow: 0 4px 12px rgba(0,0,0,.35);
}
.conn-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
#online-people { font-variant-numeric: tabular-nums; }
.board-rail {
  display: none;
  min-width: 0;
  border: 1px dashed rgba(var(--accent-rgb), .28);
  border-radius: 8px;
  background: rgba(255,255,255,.03);
  color: var(--muted);
  font-size: .7rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  align-items: center;
  justify-content: center;
  padding: 8px;
  overflow: hidden;
}
.board-rail img, .board-rail a { max-width: 100%; display: block; }
.match-overlay {
  position: absolute; inset: 0; z-index: 20;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px;
  background: rgba(8, 18, 36, .55);
  color: #fff; font-weight: 700;
}
.board-wrap { position: relative; }
.match-clock {
  width: 54px; height: 54px;
  border: 4px solid rgba(255,255,255,.25);
  border-top-color: #7ec8ff;
  border-radius: 50%;
  animation: match-spin .9s linear infinite;
}
@keyframes match-spin { to { transform: rotate(360deg); } }
body.web-board-always .board-wrap,
body.board-active .board-wrap {
  flex: 1 1 auto;
  min-width: 0;
}
@media (min-width: 1100px) {
  body.web-board-always .board-arena {
    gap: 10px;
    padding: 6px 8px;
  }
  body.web-board-always .board-rail {
    display: flex;
    flex: 0 0 132px;
    width: 132px;
  }
}
@media (max-width: 900px) {
  .board-arena { grid-column: 1; }
  .board-rail { display: none !important; }
}

.desk-home { display: none; }

@media (min-width: 901px) {
  body.home-desktop .desk-home {
    /* Misma celda de la rejilla que el tablero: nunca se ven los dos a la vez
       (en el menú no hay partida, así que el tablero está oculto). */
    grid-column: 2; grid-row: 1;
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 20px;
    padding: 28px 26px;
    overflow-y: auto;
    align-content: start;
  }

  .desk-main { min-width: 0; }
  .desk-hero { display: flex; align-items: center; gap: 16px; margin-bottom: 22px; }
  .desk-hero img {
    width: 72px; height: 72px; border-radius: 18px;
    box-shadow: 0 10px 24px rgba(0,0,0,.35);
  }
  .desk-title {
    margin: 0 0 4px; font-size: 2.15rem; font-weight: 650; letter-spacing: .01em;
    font-family: Georgia, "Palatino Linotype", Palatino, serif;
  }
  .desk-title span { color: var(--accent); font-style: italic; font-weight: 500; }
  .desk-sub { margin: 0; color: var(--muted); font-size: .98rem; }

  /* Las opciones, en fichas grandes de dos columnas. */
  body.home-desktop .desk-menu-slot .aoe-menu {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 14px;
    max-width: none;
  }
  body.home-desktop .desk-menu-slot .aoe-kicker,
  body.home-desktop .desk-menu-slot .home-hero { display: none; }
  body.home-desktop .desk-menu-slot .aoe-btn {
    margin: 0;
    min-height: 104px;
    font-size: 1.05rem;
    border-width: 2px;
    border-radius: 10px;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 6px;
    transition: transform .12s ease, box-shadow .12s ease;
  }
  body.home-desktop .desk-menu-slot .aoe-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(0,0,0,.35);
  }
  /* En vista sencilla, el dibujo manda. */
  body.home-desktop.modo-visual .desk-menu-slot .aoe-btn { min-height: 132px; }
  body.home-desktop.modo-visual .desk-menu-slot .vico { font-size: 2.6rem; }

  /* Franja lateral de publicidad: espacio propio, sin quitarle sitio al menú. */
  .desk-ads { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
  .desk-ad {
    min-height: 250px;
    display: flex; align-items: center; justify-content: center;
    border: 1px dashed rgba(var(--accent-rgb), .3);
    border-radius: 8px;
    background: rgba(255,255,255,.03);
    color: var(--muted); font-size: .74rem;
    letter-spacing: .12em; text-transform: uppercase;
  }
  .desk-ad img { max-width: 100%; height: auto; display: block; }

  /* La barra lateral, mostrando la Cuenta, con más aire. */
  body.home-desktop .side { padding: 16px 14px; }
}

/* En pantallas angostas el panel no existe: el menú vuelve a su columna. */
@media (max-width: 900px) {
  .desk-home { display: none !important; }
}

/* Subtítulos dentro de las pestañas del panel de administrador. */
.admin-sub {
  margin: 22px 0 8px; padding-top: 14px;
  border-top: 1px solid rgba(255,255,255,.1);
  font-size: .9rem; color: var(--accent);
}

/* ============================================================================
   MOBILE LOADING OVERLAY - Spinner para búsqueda de rival en línea (móvil)
   ============================================================================ */
.mobile-loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 9999;
  backdrop-filter: blur(4px);
}

.mobile-loading-overlay.hidden {
  display: none !important;
}

.mobile-loading-spinner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}

.spinner-circle {
  width: 60px;
  height: 60px;
  border: 4px solid rgba(255, 255, 255, 0.2);
  border-top-color: #7ec8ff;
  border-radius: 50%;
  animation: mobile-spin 1s linear infinite;
}

@keyframes mobile-spin {
  to {
    transform: rotate(360deg);
  }
}

.spinner-text {
  color: #fff;
  font-size: 16px;
  font-weight: 500;
  text-align: center;
  margin: 0;
  letter-spacing: 0.5px;
  animation: pulse-text 1.5s ease-in-out infinite;
}

@keyframes pulse-text {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.6;
  }
}

/* En escritorio el overlay del tablero ya cubre la búsqueda.
   El layout móvil del menú entra por debajo de 900px. */
@media (min-width: 901px) {
  .mobile-loading-overlay {
    display: none !important;
  }
}

body.buscando-rival {
  overflow: hidden;
}
