/* ==========================================================
   Juegos de Salón — estilos base compartidos por todos los juegos
   Tono: fiesta nocturna, neón, distendido. Mobile-first.
   ========================================================== */
/* The fonts, served from here (#851): Google's own woff2 files and unicode ranges for
   `family=Bangers&family=Nunito:wght@400;700;900`, the latin subset (Spanish, English, Portuguese
   and German, ß included) and latin-ext (names with other accents), which the browser fetches
   only when a page shows one of its characters. Nunito is one variable file for every weight,
   declared at 400, 700 and 900 as Google declared it, so an 800 still draws as the 900 it always
   was. License: ../fonts/OFL.txt. The pages preload nunito-latin.woff2 (fonts-preload.test.mjs). */
@font-face { font-family: 'Bangers'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/bangers-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Bangers'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/bangers-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Nunito'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/nunito-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Nunito'; font-style: normal; font-weight: 400; font-display: swap; src: url('../fonts/nunito-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Nunito'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/nunito-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Nunito'; font-style: normal; font-weight: 700; font-display: swap; src: url('../fonts/nunito-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Nunito'; font-style: normal; font-weight: 900; font-display: swap; src: url('../fonts/nunito-latin-ext.woff2') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Nunito'; font-style: normal; font-weight: 900; font-display: swap; src: url('../fonts/nunito-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

:root {
  --bg1: #150726;
  --bg2: #2a0a4a;
  --bg3: #0b1e3f;
  --pink: #ff2e88;
  --pink-deep: #c2185b;
  --yellow: #ffd23f;
  --cyan: #2ee6d6;
  --lime: #9dff3a;
  --orange: #ff7a1a;
  --purple: #8a4dff;
  --ink: #ffffff;
  --muted: rgba(255, 255, 255, 0.72);
  --glass: rgba(255, 255, 255, 0.08);
  --glass-border: rgba(255, 255, 255, 0.16);
  --card: #fffdf7;
  --card-ink: #1a1a1a;
  --red: #e0243c;
  --radius: 22px;
  --font-display: 'Bangers', 'Impact', 'Arial Black', sans-serif;
  --font-body: 'Nunito', system-ui, -apple-system, sans-serif;
  /* Cifras que el jugador lee o compara: en Bangers el 1 y el 7 son casi el mismo trazo */
  --font-num: 'Nunito', system-ui, -apple-system, sans-serif;
  /* El fondo de la app, sobre --bg1: también lo toma la capa del dado al irse (D-235) */
  --fondo:
    radial-gradient(1200px 600px at 10% -10%, rgba(255, 46, 136, 0.35), transparent 60%),
    radial-gradient(900px 500px at 110% 10%, rgba(46, 230, 214, 0.22), transparent 60%),
    radial-gradient(800px 600px at 50% 120%, rgba(138, 77, 255, 0.35), transparent 60%),
    linear-gradient(160deg, var(--bg1), var(--bg2) 55%, var(--bg3));
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
/* El `overscroll-behavior` del viewport se toma de <html>; desde <body> solo se propaga si
   <html> vale `auto`, y de esa propagación no conviene depender: donde no ocurre, tirar hacia
   abajo desde arriba dispara el "deslizar para actualizar" de Chrome y se lleva el gesto
   puesto —y con él la partida, porque recarga la página (D-86)—. Va en los dos. */
html, body { margin: 0; min-height: 100%; overscroll-behavior: none; }
/* Lab flag no-double-tap-zoom (#1045): quick taps in a game never zoom the page on iPhone; pinch zoom still works */
html.no-dtz, html.no-dtz body, html.no-dtz button, html.no-dtz a, html.no-dtz [role="button"] { touch-action: manipulation; }

body {
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--bg1);
  background-image: var(--fondo);
  background-attachment: fixed;
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
  min-height: 100dvh;
  padding-top: var(--safe-top);
  padding-bottom: var(--safe-bottom);
}

/* Partículas / confeti de fondo animado */
.bg-sparkles {
  position: fixed; inset: 0; pointer-events: none; z-index: 0; overflow: hidden;
}
.bg-sparkles span {
  position: absolute; display: block; border-radius: 50%;
  background: var(--yellow); opacity: 0.35;
  animation: floatUp linear infinite;
}
@keyframes floatUp {
  from { transform: translateY(110vh) rotate(0deg); }
  to   { transform: translateY(-10vh) rotate(720deg); }
}

.app {
  position: relative; z-index: 1;
  max-width: 560px; margin: 0 auto; padding: 16px 18px 32px;
  /* `svh` y no `dvh`: el alto chico, el que queda cuando el navegador muestra toda su interfaz.
     `dvh` es el de este instante y puede ser el grande —en un Android con la app instalada
     medimos dvh 1016 y svh 960—, así que al dimensionar con él la pantalla se arma 56 px más
     larga que lo que se ve y lo que se apoya abajo, la barra de apostar de Dudo, queda fuera:
     alcanzable deslizando, pero fuera (D-77). Con `svh` puede sobrar un poco de fondo abajo,
     que no se ve porque el `body` sigue pintando `100dvh`; lo que nunca pasa es que falte.
     Las muescas se descuentan porque el `body` ya las reservó con su padding (D-75). */
  min-height: 100vh;   /* respaldo: un navegador que no entienda `svh` se queda con el alto de siempre */
  min-height: calc(100svh - var(--safe-top) - var(--safe-bottom));
  display: flex; flex-direction: column;
}

/* --- Tipografía --- */
.display {
  font-family: var(--font-display);
  letter-spacing: 0.04em;
  line-height: 0.95;
  text-transform: uppercase;
  margin: 0;
  text-shadow: 0 4px 0 rgba(0, 0, 0, 0.35), 0 0 24px rgba(255, 46, 136, 0.45);
}
.display--xl { font-size: clamp(2.6rem, 12vw, 4.4rem); }
.display--lg { font-size: clamp(2rem, 9vw, 3.2rem); }
.display--md { font-size: clamp(1.5rem, 6.5vw, 2.2rem); }
.display--sm { font-size: clamp(1.2rem, 5vw, 1.6rem); }
/*
 * El degradado se pinta dentro de la caja del texto, y con line-height 0.95 los acentos sobre
 * mayúscula quedan fuera: la Ó de SALÓN y la Ã de SALÃO salían cortadas, y en alemán se perdían
 * las diéresis de casi cada título (Ä, Ö, Ü). El relleno arriba agranda la caja pintada y el
 * margen negativo deja el título donde estaba (D-191).
 */
.rainbow {
  padding-top: 0.2em; margin-top: -0.2em;
  background: linear-gradient(90deg, var(--yellow), var(--pink), var(--cyan), var(--lime), var(--yellow));
  background-size: 300% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: shimmer 6s linear infinite;
  text-shadow: none;
  filter: drop-shadow(0 4px 0 rgba(0, 0, 0, 0.35));
}
@keyframes shimmer { to { background-position: 300% 0; } }

p { line-height: 1.5; margin: 0 0 12px; }
.muted { color: var(--muted); }
.center { text-align: center; }
.lead { font-size: 1.1rem; font-weight: 700; }

/* --- Botones --- */
.btn {
  appearance: none; border: 0; cursor: pointer;
  font-family: var(--font-display); font-size: 1.45rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: #fff;
  padding: 16px 24px; border-radius: 999px;
  background: linear-gradient(180deg, var(--pink), var(--pink-deep));
  box-shadow: 0 6px 0 #7a0f3a, 0 12px 24px rgba(255, 46, 136, 0.35);
  transition: transform 0.08s ease, box-shadow 0.08s ease, filter 0.2s;
  width: 100%; display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  text-align: center; text-decoration: none; user-select: none; min-height: 60px;
}
.btn:active { transform: translateY(4px); box-shadow: 0 2px 0 #7a0f3a, 0 6px 12px rgba(255, 46, 136, 0.35); }
.btn:disabled { filter: grayscale(0.6) brightness(0.7); cursor: not-allowed; box-shadow: none; transform: none; }
.btn--yellow { background: linear-gradient(180deg, var(--yellow), var(--orange)); color: #3a1200; box-shadow: 0 6px 0 #9a4a00, 0 12px 24px rgba(255, 210, 63, 0.35); }
.btn--yellow:active { box-shadow: 0 2px 0 #9a4a00, 0 6px 12px rgba(255, 210, 63, 0.35); }
.btn--cyan { background: linear-gradient(180deg, var(--cyan), #14a89b); color: #03302c; box-shadow: 0 6px 0 #0b5f57, 0 12px 24px rgba(46, 230, 214, 0.35); }
.btn--cyan:active { box-shadow: 0 2px 0 #0b5f57, 0 6px 12px rgba(46, 230, 214, 0.35); }
.btn--ghost {
  background: var(--glass); border: 2px solid var(--glass-border); box-shadow: none; color: var(--ink);
  font-size: 1.15rem; min-height: 50px; padding: 12px 18px;
}
.btn--ghost:active { transform: translateY(2px); box-shadow: none; }
.btn--sm { font-size: 1.05rem; min-height: 44px; padding: 10px 16px; width: auto; }
/* The way out under "couldn't open the room" (U-37, tryRoom in transport/errors.js) */
.btn.room-local { margin: 4px 0 18px; }
.btn-row { display: flex; gap: 10px; }
.btn-row .btn { flex: 1; }
.stack { display: flex; flex-direction: column; gap: 12px; }

/* --- Aire entre el tablero y sus botones (D-309, U-11) ---
   Todo tablero de juego lleva data-tablero: el primer botón de abajo queda a --aire-tablero de su
   borde, en todos los juegos igual. Lo que ya separa se descuenta: el gap del contenedor
   (--gap-contenedor; el .stack, 12 px) y el relleno de la barra de botones de abajo (--aire-ya, que
   declara el juego en su tablero). Gana sobre el margen propio del juego (!important): es la
   medida de todos. Cada captura de los guiones lo mide (tools/e2e/spacing-common.mjs), y look.mjs
   lo informa. */
:root { --aire-tablero: 28px; }
.stack { --gap-contenedor: 12px; }
[data-tablero] { margin-bottom: max(0px, calc(var(--aire-tablero) - var(--gap-contenedor, 0px) - var(--aire-ya, 0px))) !important; }
[data-tablero] [data-tablero] { margin-bottom: 0 !important; } /* uno dentro de otro: el aire lo pone el de afuera */

/* --- Tarjetas de vidrio --- */
.panel {
  background: var(--glass); border: 1px solid var(--glass-border);
  border-radius: var(--radius); padding: 18px;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
}
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 999px; font-weight: 800; font-size: 0.95rem;
  background: rgba(255, 255, 255, 0.12); border: 1px solid var(--glass-border);
}
.chip--hot { background: var(--pink); border-color: transparent; }
.chip--gold { background: var(--yellow); color: #3a1200; border-color: transparent; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }

/* --- Panel desplegable --- */
details.panel summary { cursor: pointer; font-weight: 900; font-size: 1.05rem; list-style: none; display: flex; justify-content: space-between; align-items: center; }
details.panel summary::after { content: '▾'; font-size: 1.3rem; transition: transform 0.2s; }
details.panel[open] summary::after { transform: rotate(180deg); }
details.panel[open] summary { margin-bottom: 12px; }
details.panel summary::-webkit-details-marker { display: none; }

/* --- Cabecera compartida --- */
.topbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 14px; }
/*
 * A 320 px el nombre del juego no cabe siempre en la barra ("⚓ Batalla Naval", y en alemán
 * "🪢 Galgenmännchen"): partía el chip en dos líneas y arrastraba a "‹ Menú". El menú no se
 * achica y el chip se corta con "…": el nombre entero está en el título de la pantalla (D-191).
 */
.topbar .tools { min-width: 0; }
.topbar .tools > :not(.chip) { flex: none; }
.topbar .tools .chip { display: block; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar .back {
  flex: none; white-space: nowrap;
  color: var(--ink); text-decoration: none; font-weight: 900; font-size: 1rem;
  background: var(--glass); border: 1px solid var(--glass-border); border-radius: 999px; padding: 8px 14px;
}

/* --- Animaciones reutilizables --- */
@keyframes pop { 0% { transform: scale(0.6); opacity: 0; } 70% { transform: scale(1.08); opacity: 1; } 100% { transform: scale(1); } }
@keyframes wiggle { 0%, 100% { transform: rotate(-3deg); } 50% { transform: rotate(3deg); } }
@keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
@keyframes slideUp { from { transform: translateY(30px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@keyframes shake { 10%, 90% { transform: translateX(-2px); } 20%, 80% { transform: translateX(4px); } 30%, 50%, 70% { transform: translateX(-6px); } 40%, 60% { transform: translateX(6px); } }
.pop { animation: pop 0.45s cubic-bezier(0.2, 0.9, 0.3, 1.4) both; }
.wiggle { animation: wiggle 1.2s ease-in-out infinite; display: inline-block; }
.bounce { animation: bounce 1.4s ease-in-out infinite; display: inline-block; }
.slide-up { animation: slideUp 0.35s ease-out both; }
.shake { animation: shake 0.6s both; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}

/* Confeti (canvas) */
#confetti { position: fixed; inset: 0; pointer-events: none; z-index: 50; }

/* --- Toggle de idioma (D-231): bandera y código en cada botón, siempre --- */
.lang-toggle {
  display: inline-flex; gap: 4px; padding: 4px; border-radius: 999px;
  background: var(--glass); border: 1px solid var(--glass-border);
}
.lang-toggle button {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border: 0; cursor: pointer; border-radius: 999px; padding: 7px 12px;
  min-height: 44px; /* C-8: un dedo cabe, como en todos los botones */
  font: 900 0.9rem var(--font-body); line-height: 1; color: var(--muted); background: transparent;
  transition: background 0.15s, color 0.15s, transform 0.1s;
}
.lang-toggle .flag { font-size: 1.1em; }
.lang-toggle button.on { background: var(--yellow); color: #3a1200; transform: scale(1.04); }
.lang-toggle button:active { transform: scale(0.96); }
/*
 * Con cuatro idiomas el toggle en línea mide unos 290 px y, en una barra de arriba que lo lleva
 * junto al sonido (Rankings, Uno al día), empuja los botones redondos fuera de la pantalla. En un
 * celular angosto la bandera no se esconde (antes sí, D-231): sube encima del código, y el toggle
 * queda del ancho que tenía con el código solo. Si igual no cabe, los botones redondos bajan a una
 * segunda línea antes que salirse. La portada lo lleva en su propio bloque (.portada-barra, C-17).
 */
@media (max-width: 440px) {
  .lang-toggle:has(> :nth-child(4)) button { flex-direction: column; gap: 2px; padding: 4px 9px; font-size: 0.72rem; }
  .lang-toggle:has(> :nth-child(4)) .flag { font-size: 1.25rem; }
}
.topbar .tools:has(> #lang-slot) { flex-wrap: wrap; justify-content: flex-end; }

/* --- Botones redondos de la barra de arriba (sonido, rankings, compartir) --- */
.sound-toggle, .icon-btn {
  border: 1px solid var(--glass-border); background: var(--glass); color: var(--ink);
  width: 44px; height: 44px; border-radius: 999px; font-size: 1.25rem; cursor: pointer; display: grid; place-items: center;
  transition: transform 0.1s; text-decoration: none;
}
.sound-toggle:active, .icon-btn:active { transform: scale(0.92); }
.topbar .tools { display: flex; gap: 8px; align-items: center; }

/* --- Transición entre turnos (overlay compartido: salud / pásale el celular) --- */
.handoff {
  position: fixed; inset: 0; z-index: 30; display: grid; place-items: center; padding: 24px;
  background:
    radial-gradient(700px 500px at 50% 20%, rgba(255, 46, 136, 0.45), transparent 65%),
    radial-gradient(600px 500px at 50% 110%, rgba(46, 230, 214, 0.35), transparent 60%),
    linear-gradient(160deg, var(--bg1), var(--bg2) 60%, var(--bg3));
  animation: fadeIn 0.25s ease-out both; text-align: center;
  /* En un celular bajo (320 × 568) el veredicto con su dato y el pase no caben: se desplaza, y el
     botón de seguir se alcanza (U-11) */
  overflow-y: auto; overscroll-behavior: contain;
}
.handoff.leaving { animation: fadeOut 0.3s ease-in both; pointer-events: none; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
.handoff .stage { width: 100%; max-width: 480px; display: grid; gap: 14px; justify-items: center; }
.handoff .stage.pop { animation: pop 0.45s cubic-bezier(0.2, 0.9, 0.3, 1.4) both; }
.cheers { font-size: 5.5rem; line-height: 1; display: flex; gap: 0; }
.cheers span { display: inline-block; }
.cheers .l { animation: clinkL 0.9s cubic-bezier(0.3, 1.4, 0.5, 1) infinite; transform-origin: bottom right; }
.cheers .r { animation: clinkR 0.9s cubic-bezier(0.3, 1.4, 0.5, 1) infinite; transform-origin: bottom left; }
@keyframes clinkL { 0%, 100% { transform: rotate(-18deg) translateX(-6px); } 45% { transform: rotate(10deg) translateX(6px); } }
@keyframes clinkR { 0%, 100% { transform: rotate(18deg) translateX(6px) scaleX(-1); } 45% { transform: rotate(-10deg) translateX(-6px) scaleX(-1); } }
.handoff .title { font-family: var(--font-display); font-size: clamp(2.6rem, 14vw, 4.2rem); letter-spacing: 0.04em; text-shadow: 0 4px 0 rgba(0,0,0,0.35), 0 0 30px rgba(255, 210, 63, 0.6); line-height: 0.95; }
.handoff .title.gold { color: var(--yellow); }
.handoff .drinkers { margin: 0; }
.handoff .drinkers .chip { font-size: 1.2rem; padding: 10px 18px; }
.handoff .hint { color: var(--muted); font-weight: 800; font-size: 0.9rem; }
.handoff .phone { font-size: 4.5rem; line-height: 1; animation: passPhone 1.4s ease-in-out infinite; }
@keyframes passPhone { 0%, 100% { transform: translateX(-14px) rotate(-8deg); } 50% { transform: translateX(14px) rotate(8deg); } }
.handoff .next-name { font-family: var(--font-display); font-size: clamp(3rem, 16vw, 4.8rem); color: var(--cyan); letter-spacing: 0.04em; text-shadow: 0 5px 0 rgba(0,0,0,0.4), 0 0 36px rgba(46, 230, 214, 0.7); line-height: 0.95; }
.handoff .btn { max-width: 420px; }

/* --- Pantalla opaca compartida: "pásale el celular", toca para ver (modo un celular) --- */
.cover {
  position: fixed; inset: 0; z-index: 35; display: grid; place-items: center; text-align: center; padding: 24px;
  background: linear-gradient(160deg, var(--bg1), var(--bg2) 60%, var(--bg3)); animation: fadeIn 0.2s both;
}
.cover .big { font-family: var(--font-display); font-size: clamp(2.2rem, 12vw, 3.6rem); color: var(--cyan); letter-spacing: 0.04em; text-shadow: 0 5px 0 rgba(0,0,0,0.4); }
.cover .eye { font-size: 4rem; animation: bounce 1.6s infinite; }


/* --- Chat de sala compartido (canon C-15): burbuja + hoja inferior --- */
/* Vive fuera de las pantallas del juego y por debajo de .handoff (z-index 30),
   así el veredicto de una jugada siempre lo tapa. */
.chat { position: fixed; inset: 0; z-index: 20; pointer-events: none; --kb: 0px; }
.chat > * { pointer-events: auto; }
/* The bubble lives in a strip of its own at the bottom: with the chat on, every room screen ends
   above it, so it never covers the last button of a bar (¡CALZO!, ¡A JUGAR!, Revancha). */
body.chat-on .screen.active { padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px)); }

.chat-fab {
  position: absolute; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  width: 54px; height: 54px; border-radius: 50%; border: 2px solid var(--glass-border);
  background: linear-gradient(180deg, rgba(138, 77, 255, 0.95), rgba(42, 10, 74, 0.95));
  color: var(--ink); font-size: 1.5rem; cursor: pointer; box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5);
  display: grid; place-items: center; animation: pop 0.3s cubic-bezier(0.2, 0.9, 0.3, 1.4) both;
}
.chat-fab:active { transform: scale(0.94); }
.chat-fab.has-unread { border-color: var(--pink); box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5), 0 0 18px rgba(255, 46, 136, 0.6); }
.chat-badge {
  position: absolute; top: -3px; right: -3px; min-width: 22px; height: 22px; padding: 0 5px;
  border-radius: 999px; background: var(--pink); color: #fff; font: 900 0.72rem var(--font-body);
  display: grid; place-items: center; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}

/* Etiqueta que se asoma al lado de la burbuja con el mensaje recién llegado. Deja pasar los
   toques: lo que está debajo ("Revancha", el tablero) hace lo suyo; solo la burbuja abre el chat (dilema #48). */
.chat > .chat-peek { pointer-events: none; }
.chat-peek {
  position: absolute; right: 74px; bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  max-width: min(64vw, 260px); min-height: 54px;
  display: flex; flex-direction: column; justify-content: center; gap: 1px; text-align: left;
  padding: 8px 12px; border-radius: 16px 16px 4px 16px;
  background: linear-gradient(180deg, rgba(42, 10, 74, 0.97), rgba(21, 7, 38, 0.97));
  border: 2px solid var(--glass-border); box-shadow: 0 8px 22px rgba(0, 0, 0, 0.5);
  color: var(--ink); font-family: var(--font-body);
}
.chat-peek .who { font-size: 0.66rem; font-weight: 900; text-transform: uppercase; letter-spacing: 0.07em; }
/* Un mensaje largo se corta en dos líneas: la etiqueta es un aviso, no el chat */
.chat-peek .txt { font-size: 0.85rem; font-weight: 700; line-height: 1.25; overflow: hidden; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.chat-peek.in { animation: peekIn 0.28s cubic-bezier(0.2, 0.9, 0.3, 1.4) both; }
.chat-peek.leaving { animation: peekOut 0.28s ease-in both; }
@keyframes peekIn { from { opacity: 0; transform: translateX(16px) scale(0.92); } to { opacity: 1; transform: none; } }
@keyframes peekOut { to { opacity: 0; transform: translateX(10px) scale(0.96); } }
/* El mismo aviso para lectores de pantalla: siempre presente (una región viva que aparece no se anuncia) */
.chat > .chat-live {
  position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0);
  clip-path: inset(50%); white-space: nowrap; pointer-events: none;
}

.chat-sheet { position: absolute; inset: 0; display: grid; align-items: end; }
.chat-scrim { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.55); animation: fadeIn 0.2s both; }
.chat-panel {
  position: relative; width: 100%; max-width: 560px; margin: 0 auto;
  height: min(62dvh, 520px); display: grid; grid-template-rows: auto 1fr auto;
  border-radius: 22px 22px 0 0; border: 2px solid var(--glass-border); border-bottom: 0;
  background: linear-gradient(180deg, rgba(42, 10, 74, 0.985), rgba(21, 7, 38, 0.99));
  box-shadow: 0 -10px 40px rgba(0, 0, 0, 0.6);
  transform: translateY(calc(-1 * var(--kb))); transition: transform 0.15s ease-out;
  animation: slideUp 0.25s ease-out both;
}
.chat-head { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px 6px; border-bottom: 1px solid var(--glass-border); }
.chat-head b { font-family: var(--font-display); font-size: 1.3rem; letter-spacing: 0.05em; }
.chat-x { border: 0; background: transparent; color: var(--muted); font-size: 1.2rem; width: 44px; height: 44px; cursor: pointer; }
.chat-list { overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 10px 12px; display: flex; flex-direction: column; gap: 7px; }
/* Los mensajes se apoyan abajo, pegados al campo de texto, como en cualquier chat */
.chat-list > :first-child { margin-top: auto; }
.chat-empty { color: var(--muted); font-weight: 800; text-align: center; margin: auto 0; font-size: 0.9rem; }
.chat-msg {
  max-width: 84%; align-self: flex-start; padding: 7px 11px; border-radius: 14px;
  background: var(--glass); border: 1px solid var(--glass-border); animation: pop 0.2s ease-out both;
}
.chat-msg.mine { align-self: flex-end; background: rgba(46, 230, 214, 0.16); border-color: rgba(46, 230, 214, 0.4); }
.chat-msg.grouped { margin-top: -4px; }
.chat-msg .who { display: block; font-size: 0.68rem; font-weight: 900; text-transform: uppercase; letter-spacing: 0.07em; margin-bottom: 1px; }
.chat-msg .txt { font-size: 0.92rem; font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; }
.chat-form { display: grid; grid-template-columns: 1fr auto; gap: 8px; padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--glass-border); }
/* 16px exactos: con menos, iOS hace zoom al enfocar el campo */
.chat-form input { width: 100%; font: 700 16px var(--font-body); color: var(--ink); background: rgba(0, 0, 0, 0.35); border: 2px solid transparent; border-radius: 999px; padding: 11px 16px; outline: none; }
.chat-form input:focus { border-color: var(--cyan); }
.chat-form input::placeholder { color: rgba(255, 255, 255, 0.35); }
.chat-send { width: 48px; height: 48px; border-radius: 50%; border: 0; background: var(--cyan); color: #03302c; font-size: 1.2rem; cursor: pointer; }
.chat-send:active { transform: scale(0.94); }

/* Un emoji casi negro (〰️) sobre el fondo morado: contorno claro, el mismo emoji (ui.js, EMOJI_OSCUROS) */
.emoji-claro { filter: drop-shadow(0 0 1px #fff) drop-shadow(0 0 1px #fff) drop-shadow(0 0 5px rgba(255, 255, 255, 0.55)); }

/*
 * En alemán las palabras compuestas son largas y no caben en una columna angosta: se cortan
 * con guion, según el diccionario del navegador (necesita el lang del <html>, que pone
 * setLang), y si igual no caben se parten antes que desbordar la pantalla (D-191).
 */
html:lang(de) body { -webkit-hyphens: auto; hyphens: auto; overflow-wrap: break-word; }

/* --- Un idioma en el laboratorio (D-191, assets/js/labs-idioma.js) --- */
.labs-tabs { position: fixed; left: 0; top: 46%; z-index: 40; display: grid; gap: 6px; }
.labs-tab {
  width: 34px; height: 44px; display: grid; place-items: center; font-size: 1.1rem; text-decoration: none;
  border: 1px solid rgba(255, 122, 26, 0.6); border-left: 0; border-radius: 0 14px 14px 0; cursor: pointer;
  background: rgba(42, 10, 74, 0.92); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45); color: var(--ink);
}
.labs-tab:active { transform: scale(0.94); }
.labs-capa {
  position: fixed; inset: 0; z-index: 60; display: grid; place-items: end center;
  background: rgba(10, 2, 20, 0.6); padding: 12px 12px calc(12px + env(safe-area-inset-bottom, 0px));
}
.labs-caja {
  width: 100%; max-width: 480px; max-height: calc(100svh - 24px); overflow-y: auto;
  background: linear-gradient(180deg, rgba(42, 10, 74, 0.99), rgba(21, 7, 38, 0.99)); animation: slideUp 0.25s ease-out both;
}
.labs-caja h2 { margin: 0; }
/* Behind flag('keyboard-lift'): the layer ends where the iOS keyboard starts, so Send stays above it */
.labs-capa.sigue-teclado { padding-bottom: calc(12px + max(var(--kb, 0px), env(safe-area-inset-bottom, 0px))); }
.labs-capa.sigue-teclado .labs-caja { max-height: calc(100svh - 24px - var(--kb, 0px)); }
/* With the page pinned behind it, scrolling the card never carries over */
.fondo-fijo .labs-caja { overscroll-behavior: contain; }
.labs-texto, .labs-nombre {
  width: 100%; font: 700 16px/1.4 var(--font-body); color: var(--ink); background: rgba(0, 0, 0, 0.3);
  border: 2px solid transparent; border-radius: 14px; padding: 12px 14px; outline: none;
}
.labs-texto { resize: vertical; }
.labs-texto:focus, .labs-nombre:focus { border-color: var(--cyan); }
.labs-error { color: var(--pink); font-weight: 800; min-height: 1em; }
.labs-error:empty { display: none; }
.labs-aviso { margin: 0; font-weight: 800; line-height: 1.5; }
.topbar .labs-bicho { flex: none; border-color: rgba(255, 122, 26, 0.6); font-size: 1.1rem; }

/* The inbox at the end of the experience (D-345, U-38): a quiet link, below everything */
.buzon-pie { margin-top: 18px; text-align: center; }
.buzon-pie > .panel { text-align: start; }
.buzon-link { background: none; border: 0; color: var(--muted); font: 700 0.85rem var(--font-body); text-decoration: underline; cursor: pointer; min-height: 44px; padding: 0 8px; }
.buzon-tipos { display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; }
@media (min-width: 440px) { .buzon-tipos { grid-template-columns: repeat(4, auto); justify-content: start; } }
.buzon-tipo {
  font: 800 0.8rem var(--font-body); color: var(--ink); background: rgba(0, 0, 0, 0.3); cursor: pointer;
  border: 2px solid transparent; border-radius: 999px; padding: 6px 8px; min-height: 44px; white-space: nowrap;
}
.buzon-tipo[aria-pressed="true"] { border-color: var(--cyan); background: rgba(0, 229, 255, 0.15); }
.footer-buzon { display: inline-block; }

/* Mientras los textos del idioma elegido no están puestos, no se pinta nada (D-194) */
html.i18n-pendiente body { visibility: hidden; }

/* --- La hoja de abajo (D-223, D-232): pasos y avisos sobre el morado oscuro de la hoja del chat
   (.chat-panel). Sobre el fondo de la app, un blanco encandila (lo pidió el dueño al ver el
   diseño). La usan los avisos de La Copa y el globo de agregar a inicio de la portada. */
.hoja-capa { position: fixed; inset: 0; z-index: 60; display: grid; align-items: end; overscroll-behavior: contain; }
.hoja-fondo { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.55); animation: fadeIn 0.2s both; }
.hoja {
  position: relative; width: 100%; max-width: 560px; margin: 0 auto; box-sizing: border-box;
  max-height: 88dvh; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; gap: 12px;
  padding: 10px 20px calc(22px + var(--safe-bottom));
  border-radius: 22px 22px 0 0; border: 2px solid var(--glass-border); border-bottom: 0;
  background: linear-gradient(180deg, rgba(42, 10, 74, 0.985), rgba(21, 7, 38, 0.99));
  box-shadow: 0 -10px 40px rgba(0, 0, 0, 0.6); animation: slideUp 0.25s ease-out both;
}
.hoja-asa { align-self: center; width: 44px; height: 5px; border-radius: 999px; background: rgba(255, 255, 255, 0.3); }
.hoja h2 { font-family: var(--font-display); font-weight: 400; font-size: 1.7rem; letter-spacing: 0.04em; color: var(--yellow); margin: 0; }
.hoja p { margin: 0; line-height: 1.45; }
.hoja-paso { display: grid; grid-template-columns: 32px 1fr 44px; gap: 12px; align-items: center; }
.hoja-paso small { display: block; margin-top: 2px; }
.hoja-num { width: 32px; height: 32px; border-radius: 999px; background: var(--pink); color: #fff; font-weight: 900; display: grid; place-items: center; }
.hoja-icono { width: 44px; height: 44px; border-radius: 12px; background: rgba(255, 255, 255, 0.1); display: grid; place-items: center; font-size: 1.3rem; color: #fff; font-weight: 900; }
.hoja-link, .hoja-caja { background: rgba(255, 255, 255, 0.08); border-radius: 14px; padding: 12px 14px; overflow-wrap: anywhere; }
.hoja .btn-row { flex-wrap: wrap; }
/* Cada botón mide lo que su texto en una línea: si los dos no caben lado a lado, el segundo baja
   entero en vez de partir la palabra ("YA LA / AGREGUÉ", "BE-SCHEID"; U-17) */
.hoja .btn-row .btn { flex: 1 0 auto; width: auto; max-width: 100%; -webkit-hyphens: manual; hyphens: manual; }

/* --- La hoja de compartir de la portada: el video arriba (su miniatura con ▶ hasta que lo tocan)
   y dos opciones con el mismo dibujo que los modos de cada juego (.mode): título, nota y › */
.hoja-video { position: relative; width: 100%; aspect-ratio: 16 / 9; border-radius: 16px; overflow: hidden; background: #000;
  box-shadow: 0 0 0 2px var(--glass-border), 0 12px 30px rgba(0, 0, 0, 0.45); }
.hoja-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
/* The vertical Short (D-410): as tall as the screen allows, centered, under its two tabs */
.hoja-video--vertical { aspect-ratio: 9 / 16; width: auto; height: min(46dvh, 520px); max-width: 100%; margin: 0 auto; flex-shrink: 0; }
.hoja-pestanas { display: flex; gap: 6px; padding: 4px; border-radius: 999px; background: var(--glass); border: 2px solid var(--glass-border); }
.hoja-pestana { flex: 1; min-height: 44px; border: 0; border-radius: 999px; background: none; color: var(--muted);
  font-family: var(--font-body); font-weight: 900; font-size: 0.95rem; cursor: pointer; }
.hoja-pestana.on { background: linear-gradient(180deg, var(--yellow), #ff9a1a); color: #3a1200; }
.hoja-pestana:focus-visible { outline: 3px solid var(--cyan); outline-offset: 2px; }
.hoja .opcion { flex-shrink: 0; display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 10px; text-align: left; width: 100%;
  background: var(--glass); border: 2px solid var(--glass-border); border-radius: var(--radius); padding: 12px 16px; min-height: 44px;
  color: var(--ink); cursor: pointer; font-family: var(--font-body); transition: transform 0.1s; }
.hoja .opcion:active { transform: scale(0.98); }
.hoja .opcion b { display: block; font-family: var(--font-display); font-weight: 400; font-size: 1.3rem; letter-spacing: 0.04em; text-transform: uppercase; }
.hoja .opcion small { color: var(--muted); font-weight: 700; }
.hoja .opcion .go { font-family: var(--font-display); font-size: 2rem; color: var(--yellow); }

/* --- El globo de agregar a inicio (D-232): flota sobre el pie de la portada, con el ícono de la
   app, y se va con la ✕ para siempre. El borde dorado es el de La Copa: invita, no avisa. */
.globo-instalar {
  position: fixed; z-index: 50; left: 12px; right: 12px; bottom: calc(12px + var(--safe-bottom));
  max-width: 520px; margin: 0 auto; box-sizing: border-box;
  display: grid; grid-template-columns: 48px 1fr; align-items: center; gap: 10px 12px;
  padding: 12px; border-radius: 20px;
  border: 2px solid rgba(255, 210, 63, 0.55);
  background: linear-gradient(135deg, #3a0e62, #1a082e);
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.55), 0 0 24px rgba(255, 210, 63, 0.18);
  animation: globoSube 0.45s cubic-bezier(0.2, 0.9, 0.3, 1.2) both;
  transition: transform 0.25s, opacity 0.25s;
}
.globo-instalar.fuera { transform: translateY(24px); opacity: 0; }
.globo-icono { width: 48px; height: 48px; border-radius: 12px; display: block; }
.globo-texto { display: flex; flex-direction: column; gap: 2px; min-width: 0; line-height: 1.3; padding-right: 30px; }
.globo-texto b { font-weight: 900; }
.globo-texto span { color: var(--muted); font-size: 0.88rem; font-weight: 700; }
.globo-agregar { white-space: nowrap; grid-column: 1 / -1; }
.globo-cerrar {
  position: absolute; top: 2px; right: 2px; width: 44px; height: 44px; border: 0; border-radius: 999px;
  background: none; color: var(--muted); font: 900 1rem var(--font-body); cursor: pointer;
}
.globo-cerrar:active { transform: scale(0.9); }
/* En un celular el botón va en su propia fila, de borde a borde; con espacio, al lado del texto */
@media (min-width: 480px) {
  .globo-instalar { grid-template-columns: 48px 1fr auto; padding-right: 48px; }
  .globo-texto { padding-right: 0; }
  .globo-agregar { grid-column: auto; }
}
@keyframes globoSube { from { transform: translateY(110%); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .globo-instalar { animation: fadeIn 0.2s both; } }
/* Mientras está, el pie de la página sube sobre él: al final de la lista no tapa nada */
body:has(> .globo-instalar) main.app { padding-bottom: 170px; }

/* --- El dado de Juego al azar (D-188), que también tira Uno al día (D-230) desde cualquier página.
   La página del juego repite la capa al llegar (llegada.js, D-237), así el cambio no se ve --- */
body.azar-abierto { overflow: hidden; }
.azar-capa {
  position: fixed; inset: 0; z-index: 100; display: grid; place-content: center; justify-items: center; gap: calc(min(38vw, 150px) * 0.55 + 20px);
  background: radial-gradient(circle at 50% 45%, rgba(40, 12, 70, 0.9), rgba(10, 3, 20, 0.97));
  animation: fadeIn 0.3s ease-out both; cursor: pointer;
  outline: none;
}
.azar-escena { --lado: min(38vw, 150px); width: var(--lado); height: var(--lado); position: relative; }
.azar-salto { position: absolute; inset: 0; will-change: transform; }
/* El lienzo mide el doble que el dado: así cabe entero cuando gira de esquina */
.azar-lienzo { position: absolute; width: 200%; height: 200%; left: -50%; top: -50%; }
.azar-sin-3d { position: absolute; inset: 0; display: grid; place-items: center; font-size: calc(var(--lado) * 0.8); animation: pop 0.4s ease-out both; }
.azar-sombra {
  position: absolute; left: 8%; right: 8%; bottom: calc(var(--lado) * -0.42); height: 18%; border-radius: 50%;
  background: radial-gradient(ellipse, rgba(0, 0, 0, 0.75), transparent 70%); opacity: 0;
}
.azar-capa.listo .azar-escena { animation: azarLatido 0.7s cubic-bezier(0.3, 0, 0.3, 1); }
@keyframes azarLatido { 45% { transform: scale(1.07); } }
.azar-nombre { min-height: 4.6em; text-align: center; display: grid; gap: 4px; padding: 0 16px; }
.azar-nombre small { color: var(--muted); font-weight: 800; font-size: 1rem; }
.azar-nombre b { font: 400 clamp(2rem, 9vw, 2.8rem) var(--font-display); letter-spacing: 0.04em; color: var(--yellow); line-height: 1.05; }
.azar-capa.listo .azar-nombre > * { animation: pop 0.4s ease-out both; }
.azar-capa.listo .azar-nombre b { animation-delay: 0.08s; }
/* Al llegar al juego, la misma escena, quieta (`.velo`): se desvanece cuando el juego está dibujado */
/* `visible`: en inglés, portugués o alemán el body espera oculto sus textos (D-194), y el dado no */
.azar-capa.velo { animation: none; cursor: default; pointer-events: none; transition: opacity 0.45s ease-in-out; visibility: visible; }
.azar-capa.velo .azar-sombra { opacity: 0.6; }
.azar-capa.velo .azar-sin-3d { animation: none; }
.azar-capa.velo .azar-escena { transition: transform 0.45s ease-in; }
.azar-capa.velo.saliendo { opacity: 0; }
.azar-capa.velo.saliendo .azar-escena { transform: scale(0.85); }

/* Uno al día (D-230): la tarjeta bajo el resultado */
.uad-tarjeta { display: grid; gap: 8px; text-align: center; border-color: rgba(255, 122, 26, 0.5); background: linear-gradient(160deg, rgba(255, 122, 26, 0.16), rgba(255, 46, 136, 0.12)); }
.uad-racha { margin: 0; font: 400 1.7rem/1.1 var(--font-display); letter-spacing: 0.04em; color: var(--yellow); }
.uad-acciones { display: grid; gap: 10px; margin-top: 4px; }
.uad-red { display: grid; gap: 10px; }
.uad-red:empty, .uad-arriba:empty { display: none; }
.uad-arriba { text-align: left; }
.uad-duelo { margin: 4px 0 0; font: 400 1.35rem/1.15 var(--font-display); letter-spacing: 0.04em; color: var(--yellow); }
.uad-comodin { margin: 0; font-weight: 800; color: var(--cyan); }
.uad-invitar { display: grid; gap: 8px; text-align: center; }
/* Los interruptores de las hojas (los avisos de La Copa y de Uno al día) */
.hoja-switch { display: flex; justify-content: space-between; align-items: center; gap: 14px; min-height: 56px; padding-bottom: 10px; border-bottom: 1px solid rgba(255, 255, 255, 0.12); cursor: pointer; }
.hoja-switch span { display: flex; flex-direction: column; gap: 2px; }
.hoja-switch input { appearance: none; flex: none; width: 52px; height: 32px; border-radius: 999px; background: rgba(255, 255, 255, 0.2); position: relative; cursor: pointer; transition: background 0.15s; margin: 0; }
.hoja-switch input::after { content: ''; position: absolute; left: 3px; top: 3px; width: 26px; height: 26px; border-radius: 999px; background: #fff; transition: transform 0.15s; }
.hoja-switch input:checked { background: var(--pink); }
.hoja-switch input:checked::after { transform: translateX(20px); }
.hoja-switch input:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.uad-horas { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.uad-horas .btn { min-width: 0; font-size: 0.9rem; padding: 10px 4px; line-height: 1.15; }
.uad-oferta, .uad-avisos { display: grid; gap: 10px; text-align: center; }
.uad-hora { display: grid; gap: 8px; margin-bottom: 8px; }
/* "Repetir el de hoy": el mismo enlace discreto de La Copa (cup/style.css), también en los juegos de grupo */
.uad-tarjeta .link-btn, #uad-hoy .link-btn { background: none; border: 0; color: var(--muted); font: 700 0.85rem var(--font-body); text-decoration: underline; cursor: pointer; min-height: 44px; margin: 0 auto; display: block; }
/* The exits of an end screen (C-19, fin.js): two quiet buttons side by side, compact so they fit
   above the fold at 320 px in every language (C-8) */
.fin-salidas .btn { min-width: 0; font-size: 0.95rem; padding: 8px 10px; line-height: 1.15; gap: 6px; }

/* Cuenta regresiva antes de jugar (D-105), de assets/js/cuenta-regresiva.js: La Copa y el laboratorio */
.cuenta {
  position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  background: rgba(20, 8, 40, 0.88); backdrop-filter: blur(4px); color: var(--ink);
}
.cuenta-juego { margin: 0; font-size: 1.2rem; opacity: .8; }
.cuenta-num { font-family: var(--font-display, inherit); font-size: clamp(5rem, 30vw, 9rem); font-weight: 800; line-height: 1; color: var(--yellow, #ffd23f); text-align: center; }
.cuenta-num.late { animation: cuenta-late .9s ease-out both; }
.cuenta.ya .cuenta-num { font-size: clamp(3rem, 16vw, 5.5rem); }
.cuenta.ya { animation: cuenta-fuera .9s ease-in forwards; pointer-events: none; }
@keyframes cuenta-late { 0% { transform: scale(1.6); opacity: 0; } 25% { transform: scale(1); opacity: 1; } 100% { transform: scale(.85); opacity: .9; } }
@keyframes cuenta-fuera { 0%, 45% { opacity: 1; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .cuenta-num.late { animation: none; } }
/* --- The site's footer: the home page's, and the one site-footer.js puts on the screens outside a game --- */
.pie-sitio { margin-top: 28px; text-align: center; color: var(--muted); font-size: 0.85rem; }
.footer-msg { min-height: 3.2em; font-size: 1rem; line-height: 1.5; color: var(--ink); opacity: 0.9; transition: opacity 0.5s ease, transform 0.5s ease; font-weight: 700; }
.footer-msg.out { opacity: 0; transform: translateY(6px); }
/* The footer's options. One alone is a quiet link; two or more (today the inbox and the coffee)
   become a quiet grid of two columns, outlined and unfilled, so they read as the site's corner and
   not as more game cards. A new option is one more child. */
.footer-links { margin: 1em 0; }
.footer-links.tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; max-width: 380px; margin: 0 auto 1em; }
.footer-links.tiles::before {
  content: '🎲'; content: '🎲' / ''; grid-column: 1 / -1; display: flex; align-items: center; gap: 10px; margin: 6px 0 8px; font-size: 0.9rem; opacity: 0.55;
  background: linear-gradient(var(--glass-border), var(--glass-border)) left center / calc(50% - 18px) 1px no-repeat,
  linear-gradient(var(--glass-border), var(--glass-border)) right center / calc(50% - 18px) 1px no-repeat;
  justify-content: center;
}
.footer-links.tiles > * {
  display: flex; align-items: center; justify-content: center; min-height: 48px; padding: 6px 10px; margin: 0;
  border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 14px; background: none;
  color: var(--muted); font: 700 0.8rem/1.25 var(--font-body); text-decoration: none; text-align: center; text-wrap: balance;
}
.footer-links.tiles > *:active { background: rgba(255, 255, 255, 0.05); }
.footer-links.tiles > :is(#btn-apoyo-portada, .op-apoyo) { border-color: rgba(255, 210, 63, 0.3); }
.footer-links.tiles > :last-child:nth-child(odd) { grid-column: 1 / -1; }
/* The sunset, chosen from twelve variants in /labs/footer/: the page ends in a glow of the site's own purple and pink, the
   phrase in white, and each option on frosted glass with its color circle above the label */
footer.atardecer { margin: 0 -18px -32px; padding: 28px 18px 32px; background: linear-gradient(180deg, transparent, rgba(138, 77, 255, 0.28) 45%, rgba(255, 46, 136, 0.32)); }
footer.atardecer .footer-msg { color: var(--ink); opacity: 1; font-weight: 800; font-size: 1.04rem; }
footer.atardecer .footer-links.tiles::before { content: none; }
footer.atardecer .footer-links.tiles { margin-top: 18px; }
footer.atardecer .footer-links.tiles > * { flex-direction: column; gap: 4px; min-height: 64px; border: 0; background: rgba(255, 255, 255, 0.1); color: var(--ink); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
footer.atardecer .footer-links.tiles > *:active { background: rgba(255, 255, 255, 0.18); }
/* The circle only on the tiles: if the coffee link never loads, the inbox stays a plain centered link */
footer.atardecer .tiles .ic { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%; background: rgba(157, 255, 58, 0.35); }
footer.atardecer .tiles :is(#btn-buzon-portada, .op-buzon) .ic { background: rgba(46, 230, 214, 0.35); }
footer.atardecer .tiles :is(#btn-apoyo-portada, .op-apoyo) .ic { background: rgba(255, 122, 26, 0.5); }
footer.atardecer > .muted { color: rgba(255, 255, 255, 0.8); }
