/* Speak Emoji. Estetica iOS: los emojis son los nativos del sistema, sin una sola imagen. */

.juego {
  --celda: 4;            /* columnas, lo pisa cada breakpoint */
  --hueco: 4vw;
  --sombra: light-dark(rgba(43, 36, 112, .13), rgba(0, 0, 0, .5));
  background: var(--bg);
}

/* Toda la superficie de juego: nada de zoom por doble toque, nada de menu por
   pulsacion larga, nada de tirar para recargar. Un nene hace las tres cosas sin
   proponerselo y cualquiera de ellas lo saca del juego. */
.juego, .juego * {
  /* ponytail-keep: manipulation y no pan-y. Segun la norma cualquier valor distinto de
     auto ya saca el zoom por doble toque, pero Safari de iOS no lo cumple: con pan-y el
     doble toque accidental entre los iconos seguia agrandando toda la pagina, y volver
     atras es dificil. manipulation si lo saca. Deja el pellizco, que es lo que pan-y
     cubria, asi que ese lo frena a mano gesturestart en juego.js. */
  touch-action: manipulation;
  -webkit-touch-callout: none;
  -webkit-user-select: none; user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.juego { overscroll-behavior: none; }

/* ── Botones de arriba ─────────────────────────────────────────────── */
.eb-barra {
  /* La barra del sitio tambien es sticky en top:0 y mide unos 50 px, asi que con top:0
     los controles se pegaban DEBAJO y quedaban tapados. Su alto no es un numero fijo:
     sale del padding y crece con el safe-area al instalar la pagina, por eso juego.js lo
     mide y lo deja en --nav-alto. En modo nino la barra del sitio no esta y vale cero. */
  position: sticky; top: var(--nav-alto, 0px); z-index: 6;
  display: flex; align-items: center; gap: .6rem;
  padding: .7rem max(20px, 4vw);
  pointer-events: none;
}
.eb-barra > * { pointer-events: auto; }
.eb-barra .eb-der { margin-left: auto; display: flex; gap: .6rem; }

.eb-btn {
  width: 2.9rem; height: 2.9rem; flex: none; padding: 0;
  display: block; text-align: center;
  font-size: 1.45rem; line-height: 1;
  border: 0; border-radius: 50%; cursor: pointer;
  color: var(--fg);
  background: light-dark(rgba(255, 255, 255, .72), rgba(255, 255, 255, .1));
  -webkit-backdrop-filter: blur(14px) saturate(1.6);
  backdrop-filter: blur(14px) saturate(1.6);
  box-shadow: 0 2px 10px var(--sombra), inset 0 0 0 1px light-dark(rgba(255, 255, 255, .8), rgba(255, 255, 255, .14));
  transition: transform .18s cubic-bezier(.34, 1.7, .5, 1), box-shadow .18s;
}
.eb-btn:hover { transform: scale(1.08); }
.eb-btn:active { transform: scale(.9); }
/* ponytail-keep: el contenido va en un span y el flex va en el span, no en el button.
   En Safari 16 de iPadOS un nodo de texto suelto adentro de un button con display grid
   se vuelve un item anonimo que el motor no centra, y los iconos salian corridos
   arriba a la izquierda del circulo. En Chrome y Safari nuevos se veia bien. */
.eb-btn > span { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; }
/* Naranja contra el indigo del sitio: es el unico boton que el adulto tiene que
   encontrar rapido, y el nene lo puede tocar sin romper nada. */
.eb-btn-mas {
  font-size: 1.7rem; font-weight: 300;
  color: #fff;
  background: linear-gradient(160deg, #ff9c4f, #f06f16);
  box-shadow: 0 3px 14px rgba(240, 111, 22, .45), inset 0 0 0 1px rgba(255, 255, 255, .38);
}
.eb-btn-mas > span { padding-bottom: .08em; }

/* ── La grilla ─────────────────────────────────────────────────────── */
.eb-tablero { padding: 0 max(20px, 4vw) 4rem; }

/* El espacio vacio entre categorias es toda la separacion: sin titulos, sin lineas. */
.eb-cat { display: grid; grid-template-columns: repeat(var(--celda), 1fr); gap: var(--hueco); }
.eb-cat + .eb-cat { margin-top: calc(var(--hueco) * 2.2); }

.eb-emoji {
  aspect-ratio: 1; width: 100%;
  border: 0; padding: 0; background: none; cursor: pointer;
  display: grid; place-items: center;
  /* El tamano sale de la propia celda, asi no hay que recalcular nada por breakpoint. */
  container-type: size;
  font-size: 2.6rem;   /* respaldo para navegadores sin unidades de contenedor */
  line-height: 1;
  transition: transform .2s cubic-bezier(.34, 1.7, .5, 1), filter .2s;
  filter: drop-shadow(0 2px 4px var(--sombra));
}
.eb-emoji > span { font-size: 66cqh; line-height: 1; }
.eb-emoji:hover { transform: scale(1.12) rotate(-3deg); filter: drop-shadow(0 6px 12px var(--sombra)); }
.eb-emoji:active { transform: scale(.86); }
.eb-emoji.eb-volando { opacity: 0; }

/* Levantado para reordenar. Sin transicion, porque sigue al dedo cuadro a cuadro, y sin
   recibir eventos, para que elementFromPoint encuentre el icono que esta abajo. */
.eb-emoji.eb-alzado {
  position: relative; z-index: 3;
  transition: none; pointer-events: none;
  filter: drop-shadow(0 14px 22px rgba(0, 0, 0, .5));
}

@media (min-width: 620px)  { .juego { --celda: 6; --hueco: 1.9rem; } }
@media (min-width: 1040px) { .juego { --celda: 8; } .eb-tablero { max-width: 1180px; margin: 0 auto; } }

/* ── El emoji grande ───────────────────────────────────────────────── */
.eb-escena {
  position: fixed; inset: 0; z-index: 40;
  display: grid; place-items: center;
  visibility: hidden;
  /* ponytail-keep: lo que entra y sale es el filtro, no la opacidad del panel. Con
     opacity el efecto aparecia de golpe, porque el backdrop-filter se aplica completo
     desde el primer cuadro y lo unico que se desvanecia era la capa ya filtrada.
     Interpolando blur y brightness, la grilla se va desenfocando de verdad. */
  -webkit-backdrop-filter: blur(0px) brightness(1) saturate(1);
  backdrop-filter: blur(0px) brightness(1) saturate(1);
  /* Cada direccion con la duracion y la curva de su vuelo: la de salida vive en la regla
     base y la de entrada en .eb-viva, que es la que manda al agregar la clase. Asi el
     fondo termina de aclararse justo cuando el emoji toca su casillero. */
  transition: backdrop-filter .62s cubic-bezier(.5, 0, .7, .5),
              -webkit-backdrop-filter .62s cubic-bezier(.5, 0, .7, .5), visibility .62s;
}
.eb-escena.eb-viva {
  visibility: visible;
  transition: backdrop-filter .72s cubic-bezier(.22, .61, .36, 1),
              -webkit-backdrop-filter .72s cubic-bezier(.22, .61, .36, 1), visibility .72s;
  /* Se distingue lo que hay atras a proposito: el nene reconoce de donde salio el emoji. */
  -webkit-backdrop-filter: blur(9px) brightness(.78) saturate(1.1);
  backdrop-filter: blur(9px) brightness(.78) saturate(1.1);
}
/* Que el emoji no se apague junto con el panel cuando la visibilidad cambia. */
.eb-grande { visibility: visible; }
.eb-grande {
  position: fixed; inset: 0; display: grid; place-items: center;
  line-height: 1; will-change: transform; pointer-events: none;
}
/* El hijo pivotea sobre su propio centro, que el padre ya puso en el medio. */
.eb-cara {
  line-height: 1; display: block;
  filter: drop-shadow(0 14px 30px rgba(0, 0, 0, .4));
  /* El glifo es lo unico que recibe el toque: el panel de atras sigue transparente a los
     eventos, asi que tocar afuera no hace nada y tocar el emoji lo suelta. */
  pointer-events: auto; touch-action: none; cursor: grab;
}
/* Mientras lee, respira y nada mas. La sacudida de la llegada es la que hace el
   efecto; si ademas se mueve todo el tiempo, se vuelve ruido. Sin rotacion ni 3D. */
.eb-cara.eb-baila { animation: eb-respira 2.2s ease-in-out infinite; }
@keyframes eb-respira {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.045); }
}

/* ── Paneles del + y de la banderita ───────────────────────────────── */
.eb-panel {
  position: absolute; top: 3.9rem; z-index: 8;
  max-height: min(64vh, 30rem); overflow-y: auto; overscroll-behavior: contain;
  padding: .85rem; border-radius: 1.25rem;
  background: light-dark(rgba(255, 255, 255, .86), rgba(30, 26, 48, .88));
  -webkit-backdrop-filter: blur(26px) saturate(1.8);
  backdrop-filter: blur(26px) saturate(1.8);
  box-shadow: 0 12px 40px var(--sombra), inset 0 0 0 1px light-dark(rgba(255, 255, 255, .9), rgba(255, 255, 255, .12));
  animation: eb-entra .24s cubic-bezier(.34, 1.5, .5, 1);
}
@keyframes eb-entra { from { opacity: 0; transform: translateY(-10px) scale(.94); } }
/* Siete categorias en fila no entran en un celular: grilla de cuatro y que baje. */
.eb-panel-cats {
  right: max(20px, 4vw); width: min(15rem, 82vw);
  display: grid; grid-template-columns: repeat(4, 1fr); gap: .35rem;
}
.eb-panel-idiomas { left: max(20px, 4vw); width: min(20rem, 82vw); display: grid; grid-template-columns: repeat(auto-fill, minmax(2.9rem, 1fr)); gap: .35rem; }

.eb-opcion {
  border: 0; background: none; cursor: pointer; border-radius: .9rem;
  padding: .5rem .35rem; font-size: 1.8rem; line-height: 1.1;
  display: grid; place-items: center; gap: .15rem;
  transition: transform .18s cubic-bezier(.34, 1.7, .5, 1), background .18s;
}
.eb-opcion:hover { background: light-dark(rgba(58, 47, 143, .1), rgba(255, 255, 255, .1)); transform: scale(1.1); }
.eb-opcion.eb-crecida { transform: scale(1.28); }
/* Apagado gris, encendido a todo color. Va SOLO en las categorias: en el panel de
   banderas hay una sola elegida, asi que grisar las no elegidas dejaba el mundo entero
   en blanco y negro. Ahi la elegida se marca con un aro, no apagando las demas. */
.eb-panel-cats .eb-opcion[aria-pressed="false"] { filter: grayscale(1) opacity(.42); }
.eb-panel-idiomas .eb-opcion[aria-pressed="true"] {
  background: light-dark(rgba(58, 47, 143, .14), rgba(169, 178, 240, .2));
  box-shadow: inset 0 0 0 2px var(--accent);
}

/* ── Modo niño ─────────────────────────────────────────────────────── */
/* En modo nino se esconde todo lo del sitio y el selector de idioma, pero el mas se
   queda: cambiar de categoria es parte del juego y no saca a nadie de la pagina. */
.eb-solo-juego .nav-sitio,
.eb-solo-juego .pie,
.eb-solo-juego .eb-btn-idioma { display: none; }
/* El credito de los sonidos vive dentro de .pie, asi que en modo nene desaparece con
   todo el pie: la licencia se cumple en la pagina, no en la cara del que juega. */
.pie-creditos { margin: .4rem 0 0; font-size: .8rem; opacity: .72; }
.eb-solo-juego .eb-tablero { padding-top: .5rem; }
/* Instalado en la pantalla de inicio, la pagina arranca debajo de la hora y la senial. En
   modo nino no esta la barra del sitio que hacia de colchon, asi que los controles se
   metian abajo del reloj. */
.eb-solo-juego .eb-barra { padding-top: calc(.7rem + env(safe-area-inset-top, 0px)); }
@media (display-mode: standalone) {
  .nav-sitio .nav-caja { padding-top: calc(.55rem + env(safe-area-inset-top, 0px)); }
}
.eb-tablero { padding-bottom: calc(4rem + env(safe-area-inset-bottom, 0px)); }
.eb-solo-juego .eb-btn-pantalla { opacity: .28; }
.eb-solo-juego .eb-btn-pantalla:hover { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .eb-emoji, .eb-btn, .eb-opcion { transition-duration: .01ms; }
  .eb-cara.eb-baila { animation-duration: 4s; }
  .eb-panel { animation: none; }
}

/* ── El globo ──────────────────────────────────────────────────────── */
.eb-globo {
  display: block; width: 100%; height: min(64vh, 94vw); margin: 1vh auto 0;
  touch-action: none; cursor: grab;
  opacity: 0; transition: opacity 1.4s ease;
  filter: drop-shadow(0 10px 26px var(--sombra));
}
.eb-globo.eb-listo { opacity: 1; }
.eb-globo:active { cursor: grabbing; }
.eb-mar { fill: light-dark(#7fc9ea, #2a5f80); }
.eb-brillo { fill: #fff; opacity: .17; pointer-events: none; }
.eb-borde { fill: none; stroke: light-dark(rgba(0,0,0,.16), rgba(0,0,0,.45)); stroke-width: .016; pointer-events: none; }
/* La camara vive en user units del viewBox, con el origen en el centro del globo. */
.eb-globo g { transform-box: view-box; transform-origin: 0 0; transition: transform .9s cubic-bezier(.3,0,.2,1); }
.eb-tierra {
  cursor: pointer; stroke-width: .012; stroke-linejoin: round;
  transition: fill .7s ease, filter .25s ease, opacity .55s ease;
}
/* ponytail-keep: los paises entran y la silueta se va CRUZANDOSE, no cambiando en el mismo
   cuadro. El salto seco entre una cosa y la otra en medio del acercamiento era lo que se
   veia como parpadeo. La silueta deja de calcularse recien cuando ya es invisible. */
.eb-tierra[data-pais] { opacity: 0; }
.eb-globo.eb-cerca .eb-tierra[data-pais] { opacity: 1; }
.eb-bloque.eb-tapado { opacity: 0; }
/* Se enciende mientras su bandera esta en el aire. */
.eb-tierra.eb-tocado { filter: brightness(1.32) saturate(1.35); }
.eb-tierra:hover { filter: brightness(1.12); }
.eb-rotulo { font-size: .2px; pointer-events: none; transition: opacity .35s; }
.eb-globo.eb-cerca .eb-rotulo { opacity: 0 !important; }

.eb-volumen { pointer-events: none; }
.eb-bandera {
  font-size: .052px; cursor: pointer;
  opacity: 0; transition: opacity .45s ease, font-size .45s cubic-bezier(.3,1.5,.5,1);
}
.eb-bandera.eb-puesta { opacity: 1; font-size: .07px; }
.eb-bandera.eb-volando { opacity: 0; }

/* Se van tarde y despacio: primero se los ve crecer con el zoom y recien despues se apagan. */
.eb-brillo, .eb-borde, .eb-volumen { transition: opacity .7s ease .45s; }
/* ponytail-keep: de cerca se apaga SOLO lo que hace de pelota. El agua se queda: al
   apagarla tambien, entre celda y celda del mar asomaba el fondo blanco de la pagina y
   el mapa parpadeaba mientras giraba. */
.eb-globo.eb-cerca .eb-brillo,
.eb-globo.eb-cerca .eb-borde,
.eb-globo.eb-cerca .eb-volumen { opacity: 0; }

/* Punteada y fina: una linea llena sobre un relleno que tambien lleva contorno se veia
   doble y sucia. Asi se lee como frontera de mapa y perdona los pixeles de diferencia. */
/* De cerca cada pais tiene su propio color, asi que la frontera es el borde entre dos
   tonos y no hace falta una linea aparte. El relleno casi no se dilata para que esos
   bordes caigan donde van. */
/* Con cada pais en su color, la frontera ya la hace el cambio de tono: la linea solo
   tiene que separar, no marcar. Un hilo claro en vez de uno negro, que ademas cierra las
   costuras entre anillos vecinos. */
/* Las fronteras son solo del continente que se esta mirando. Los de al lado quedan como
   bloques de un color, que es lo que son a esa distancia. */
.eb-globo.eb-cerca .eb-tierra[data-pais] {
  stroke-width: .0032;
  stroke: light-dark(rgba(0, 0, 0, .16), rgba(0, 0, 0, .3));
}

/* Sin modo de mezcla: es caro y casi no se veia. Un velo claro y listo. */
/* Cinco tonos muy cercanos: desenfocados dejan de ser celdas y quedan como agua. */
.eb-ola, .eb-agua { pointer-events: none; }
.eb-agua { transition: opacity .8s ease; }
.eb-globo.eb-cerca .eb-agua { opacity: 0; }
.eb-ola { opacity: .5; }
.eb-ola-0 { fill: light-dark(#8ed2f1, #2d6485); }
.eb-ola-1 { fill: light-dark(#63b5e0, #1b506f); }
.eb-ola-2 { fill: light-dark(#a8e0f8, #3f7ea4); }
.eb-ola-3 { fill: light-dark(#79c4e9, #27607f); }
.eb-ola-4 { fill: light-dark(#56ace0, #174a68); }

/* De cerca el mapa ocupa lo que haya. El viewBox se adapta desde JS, asi que lo que sobra
   a los costados es mapa y no margen. */
.eb-globo.eb-cerca { height: calc(100dvh - 12rem); }
.eb-solo-juego .eb-globo.eb-cerca { height: calc(100dvh - 6rem); }
.eb-esfera { transform-box: view-box; transform-origin: 0 0; transition: transform .9s cubic-bezier(.3,0,.2,1); }

/* Three.js: la textura y el volumen viven en la GPU. Los botones conservan los
   emojis nativos y su nitidez, sin rasterizarlos a cada cuadro del planeta. */
.eb-planeta {
  position: relative; width: 100%; height: min(64vh, 94vw); margin: 1vh auto 0;
  overflow: hidden; cursor: grab; opacity: 0; isolation: isolate;
  transition: opacity .7s ease;
}
.eb-planeta.eb-listo { opacity: 1; }
.eb-planeta:active { cursor: grabbing; }
.juego .eb-planeta, .juego .eb-planeta * { touch-action: none; }
.eb-planeta > canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.eb-planeta.eb-cerca { height: calc(100dvh - 12rem); }
.eb-solo-juego .eb-planeta.eb-cerca { height: calc(100dvh - 6rem); }
.eb-etiquetas { position: absolute; inset: 0; pointer-events: none; }
.eb-marca {
  position: absolute; left: 0; top: 0; width: 32px; height: 32px;
  padding: 0; border: 0; background: none; font: 25px/1 sans-serif;
  cursor: pointer; pointer-events: auto; will-change: transform;
}
.eb-marca > span { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; }
.eb-marca[data-onu] { font-size: 28px; }
.eb-marca[hidden] { display: none; }
.eb-marca.eb-volando { opacity: 0; }
.eb-marca:focus-visible { outline: 2px solid #fff; border-radius: 5px; background: #2b2470; }
.eb-marca:hover > span { transform: scale(1.15); }
.eb-cargando { text-align: center; padding: 5rem 1rem; color: var(--fg); }
/* Barra sin porcentaje: no se sabe cuanto falta, solo que sigue trabajando. */
.eb-barra-carga {
  display: block; width: min(14rem, 60%); height: 6px; margin: 1.1rem auto 0;
  border-radius: 3px; overflow: hidden;
  background: light-dark(rgba(43, 36, 112, .13), rgba(255, 255, 255, .12));
}
.eb-barra-carga::after {
  content: ""; display: block; height: 100%; width: 42%; border-radius: 3px;
  background: var(--acento, #e8873a);
  animation: eb-cargando 1.15s cubic-bezier(.5, 0, .5, 1) infinite;
}
@keyframes eb-cargando {
  from { transform: translateX(-110%); }
  to { transform: translateX(250%); }
}
@media (prefers-reduced-motion: reduce) {
  .eb-barra-carga::after { animation: none; width: 100%; opacity: .5; }
}
.eb-reintentar { display: block; margin: 3rem auto; border-radius: 1rem; padding: 1rem; font: inherit; cursor: pointer; }
@media (prefers-reduced-motion: reduce) { .eb-planeta { transition: none; } }
