* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
button, a, label, [role="button"] { touch-action: manipulation; }
:root {
  --bg-a: #f2ecff;
  --bg-b: #ffeef4;
  --surface: #ffffff;
  --surface-soft: #f7f4ff;
  --primary: #7c5cf0;
  --primary-dark: #6842e0;
  --mint: #1fa572;
  --mint-soft: #d9f7e8;
  --peach: #e0384f;
  --peach-soft: #ffe2e6;
  --sun: #b8860b;
  --sun-soft: #fef3d5;
  --ink: #211f2e;
  --ink-soft: #55536a;
  --border: #e4defa;
  --radius-lg: 24px;
  --radius-md: 18px;
  --shadow-soft: 0 8px 28px rgba(90, 70, 160, .14);
  /* Real height of #pickComposer, kept in sync from JS (syncComposerHeight)
     so whatever reserves room for it is always exactly right — including
     the safe-area inset on notched phones — instead of a guessed constant
     that can fall short and let the composer cover real content. */
  --composer-h: 88px;
}

/* ---------- Temas de temporada (Halloween / Navidad) ----------
   Re-pintan las mismas variables que ya usa toda la app (botones, chips,
   fondos, bordes…), así que con solo esto cambian en cascada sin tocar
   cada regla una por una. El tema activo lo pone app.js poniendo
   data-season en <html> según lo que diga el admin (ver /api/public/me).
   Es un atributo aparte de data-theme a propósito: el admin ya usa
   data-theme para claro/oscuro, y no deben pisarse. */
:root[data-season="halloween"] {
  --bg-a: #2d1b4e;
  --bg-b: #140d1f;
  --surface-soft: #ffe9cf;
  --primary: #ff7f11;
  --primary-dark: #d9660a;
  --mint: #39b54a;
  --mint-soft: #d8f5dc;
  --peach: #b4132e;
  --peach-soft: #ffd9df;
  --sun: #ffb703;
  --sun-soft: #fff1cf;
  --border: #d9b98f;
}
:root[data-season="christmas"] {
  --bg-a: #fdf0f0;
  --bg-b: #effaf0;
  --surface-soft: #f3faf5;
  --primary: #c21807;
  --primary-dark: #8e1104;
  --mint: #0f8a4b;
  --mint-soft: #d8f5df;
  --peach: #a01830;
  --peach-soft: #ffe1e1;
  --sun: #d4a017;
  --sun-soft: #fff3d1;
  --border: #f0d9d9;
}
/* Insignia de temporada junto al logo — solo decorativa, no estorba el
   click del botón (va encima, pointer-events:none). */
.brand-home-btn { position: relative; }
.brand-home-btn::after {
  content: "";
  position: absolute;
  top: -8px;
  left: -4px;
  font-size: 18px;
  pointer-events: none;
}
:root[data-season="halloween"] .brand-home-btn::after { content: "🎃"; animation: seasonBadgeBounce 1.8s ease-in-out infinite; }
:root[data-season="christmas"] .brand-home-btn::after { content: "🎅"; animation: seasonBadgeBounce 1.8s ease-in-out infinite; }
@keyframes seasonBadgeBounce {
  0%, 100% { transform: translateY(0) rotate(-6deg); }
  50% { transform: translateY(-3px) rotate(6deg); }
}

/* Calabaza brillante en los botones principales — y en Navidad, un borde
   que titila entre rojo y verde en vez del morado fijo de siempre. */
:root[data-season="halloween"] .btn-primary,
:root[data-season="halloween"] #pickSubmit,
:root[data-season="halloween"] .live-chat-send {
  box-shadow: 0 0 0 2px #ffb703, 0 0 16px rgba(255, 127, 17, .65);
}
:root[data-season="christmas"] .btn-primary,
:root[data-season="christmas"] #pickSubmit,
:root[data-season="christmas"] .live-chat-send {
  animation: christmasTwinkleBorder 2.4s ease-in-out infinite;
}
@keyframes christmasTwinkleBorder {
  0%, 100% { box-shadow: 0 0 0 2px #c21807, 0 0 12px rgba(194, 24, 7, .55); }
  50% { box-shadow: 0 0 0 2px #0f8a4b, 0 0 12px rgba(15, 138, 75, .55); }
}

/* Telaraña en la esquina de cada tarjeta/modal — puro CSS, sin imágenes.
   En Navidad, en cambio, una guirnalda de lucecitas justo debajo del
   header, titilando una por una. */
:root[data-season="halloween"] .modal-card::before,
:root[data-season="halloween"] .avail-modal-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 46px;
  height: 46px;
  pointer-events: none;
  background:
    radial-gradient(circle at 0 0, transparent 8px, rgba(180, 19, 46, .35) 8.5px 9px, transparent 9.5px),
    radial-gradient(circle at 0 0, transparent 18px, rgba(180, 19, 46, .35) 18.5px 19px, transparent 19.5px),
    radial-gradient(circle at 0 0, transparent 30px, rgba(180, 19, 46, .35) 30.5px 31px, transparent 31.5px),
    linear-gradient(135deg, rgba(180, 19, 46, .35) 0 1px, transparent 1px);
  clip-path: polygon(0 0, 100% 0, 0 100%);
}
.modal-card, .avail-modal-card { position: relative; }

/* flex-wrap solo en Navidad: los hijos de siempre (logo, acciones) caben
   de sobra en una sola línea, así que no se mueven — la guirnalda nueva es
   la única que, al llevar flex-basis:100%, se ve forzada a su propia
   línea debajo, en vez de superponerse encima del contenido de abajo. */
:root[data-season="christmas"] .topbar { flex-wrap: wrap; }
:root[data-season="christmas"] .topbar::after {
  content: "🎄 ✨ 🎁 ✨ 🎄 ✨ 🎁 ✨ 🎄 ✨ 🎁 ✨";
  display: block;
  width: 100%;
  flex-basis: 100%;
  margin-top: 4px;
  font-size: 11px;
  letter-spacing: 6px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  opacity: .8;
  animation: christmasLightsTwinkle 2s ease-in-out infinite;
}
@keyframes christmasLightsTwinkle {
  0%, 100% { opacity: .5; }
  50% { opacity: 1; }
}

html, body {
  margin: 0;
  width: 100%;
  min-height: 100%;
  /* Red de seguridad contra cualquier elemento que se pase del ancho de
     pantalla (una tabla, un número largo, etc.) — en vez de que el
     navegador achique TODA la página con zoom para que entre, simplemente
     recorta lo que sobra. Los scrolls horizontales que sí son a propósito
     (el carrusel de cartones, el tablero maestro) tienen su propio
     overflow-x:auto y siguen funcionando igual, no dependen de esto. */
  overflow-x: hidden;
  font-family: "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
  font-size: 19px;
  color: var(--ink);
  background: linear-gradient(160deg, var(--bg-a), var(--bg-b));
  line-height: 1.5;
}
.hidden { display: none !important; }
button, input, textarea { font-family: inherit; }

.wrap {
  max-width: 560px;
  margin: 0 auto;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  padding-top: calc(12px + env(safe-area-inset-top, 0px));
}
.brand-icon {
  width: 42px; height: 42px;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  border: 2px solid var(--primary);
  border-radius: 12px;
  overflow: hidden;
}
.brand-icon img { width: 100%; height: 100%; object-fit: cover; }
.brand-name { height: 48px; width: auto; display: block; }
.brand-home-btn {
  display: flex;
  align-items: center;
  gap: 12px;
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
}
.brand-home-btn:active { opacity: .8; }
.topbar-actions { margin-left: auto; position: relative; display: flex; align-items: center; gap: 8px; }
.icon-btn.subscribed, .topbar-menu-item.subscribed { color: var(--mint); }
/* Resalta "Activar notificaciones" mientras sigan apagadas (primera vez,
   o las desactivó) — para que no pase desapercibido en el menú. */
.icon-btn.needs-attention, .topbar-menu-item.needs-attention {
  color: var(--primary);
  animation: pushBellPulse 1.4s ease-in-out infinite;
}
@keyframes pushBellPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(124, 92, 240, .45); }
  50% { box-shadow: 0 0 0 6px rgba(124, 92, 240, 0); }
}
/* ---------- Menú desplegable del topbar ---------- */
.topbar-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 210;
  min-width: 220px;
  background: var(--surface);
  border-radius: var(--radius-md);
  box-shadow: 0 14px 34px rgba(0, 0, 0, .22);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  animation: topbarMenuIn .18s ease both;
}
@keyframes topbarMenuIn {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
.topbar-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  border: none;
  background: none;
  color: var(--ink);
  font-size: 14.5px;
  font-weight: 700;
  text-align: left;
  padding: 10px 12px;
  border-radius: 10px;
  cursor: pointer;
}
.topbar-menu-item:active { background: var(--surface-soft); }
.topbar-menu-item svg { width: 19px; height: 19px; flex: none; }

.screen-area {
  flex: 1;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 6px 12px 16px;
}

.push-toast {
  position: fixed;
  top: calc(16px + env(safe-area-inset-top, 0px));
  left: 50%;
  transform: translateX(-50%);
  width: 92%;
  max-width: 480px;
  background: var(--ink);
  color: #fff;
  padding: 14px 22px;
  border-radius: 14px;
  font-size: 16px;
  font-weight: 700;
  text-align: center;
  box-shadow: 0 10px 30px rgba(0,0,0,.28);
  z-index: 100;
  animation: pushIn .4s cubic-bezier(.34,1.56,.64,1) both;
}
.push-toast.out { animation: pushOut .25s ease both; }
@keyframes pushIn {
  from { opacity: 0; transform: translate(-50%, -18px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}
@keyframes pushOut {
  from { opacity: 1; transform: translate(-50%, 0); }
  to { opacity: 0; transform: translate(-50%, -10px); }
}

/* Stack of "so-and-so bought N cartones" toasts — capped at two, purple,
   oldest one pushed out (with its own exit animation) to make room for a
   new one instead of piling up. */
.conn-banner {
  position: fixed;
  top: env(safe-area-inset-top, 0px);
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 480px;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: linear-gradient(135deg, #d97706, #b45309);
  color: #fff;
  font-size: 13px;
  font-weight: 800;
  padding: 8px 14px;
  box-shadow: 0 4px 14px rgba(0,0,0,.25);
  border-radius: 0 0 14px 14px;
  animation: connBannerIn .3s ease both;
}
@keyframes connBannerIn {
  from { opacity: 0; transform: translate(-50%, -100%); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

/* Banner de "instalar la app" — como un push notification: entra
   empujando desde la izquierda, chiquito y pegado a esa esquina, no una
   franja de ancho completo. Se quita solo a los 15s (ver dismissBar en
   app.js), o antes si lo cierran a mano — en ambos casos con el mismo
   empuje hacia la izquierda de salida en vez de simplemente desaparecer. */
.install-bar {
  position: fixed;
  left: 8px;
  bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  width: 230px;
  max-width: calc(100% - 16px);
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--surface);
  color: var(--ink);
  padding: 12px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, .22);
  border-radius: 14px;
  animation: installBarIn .32s cubic-bezier(.22, 1, .36, 1) both;
}
.install-bar.leaving { animation: installBarOut .28s ease both; }
@keyframes installBarIn {
  from { opacity: 0; transform: translateX(-130%); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes installBarOut {
  from { opacity: 1; transform: translateX(0); }
  to { opacity: 0; transform: translateX(-130%); }
}
.install-bar-row { display: flex; align-items: center; gap: 10px; padding-right: 18px; }
.install-bar-icon { width: 38px; height: 38px; border-radius: 10px; flex: none; object-fit: cover; }
.install-bar-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.install-bar-text strong { font-size: 13.5px; }
.install-bar-text span { font-size: 11.5px; color: var(--ink-soft); }
.install-bar-link { margin-top: 3px; font-size: 11.5px; font-weight: 700; color: var(--primary-dark); }
.install-bar-btn {
  width: 100%;
  border: none;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  color: #fff;
  font-weight: 800;
  font-size: 13px;
  padding: 9px 16px;
  border-radius: 999px;
  cursor: pointer;
}
.install-bar-close {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 24px;
  height: 24px;
  border: none;
  background: none;
  color: var(--ink-soft);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.purchase-announcements {
  position: fixed;
  top: calc(16px + env(safe-area-inset-top, 0px));
  left: 50%;
  transform: translateX(-50%);
  width: 92%;
  max-width: 480px;
  z-index: 99;
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
}
.purchase-toast {
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  color: #fff;
  padding: 12px 20px;
  border-radius: 14px;
  font-size: 15px;
  font-weight: 700;
  text-align: center;
  box-shadow: 0 10px 26px rgba(124, 92, 240, .4);
  animation: purchaseToastIn .4s cubic-bezier(.34,1.56,.64,1) both;
}
.purchase-toast.out { animation: purchaseToastOut .25s ease both; }
@keyframes purchaseToastIn {
  from { opacity: 0; transform: translateY(-16px) scale(.95); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes purchaseToastOut {
  from { opacity: 1; transform: translateY(0) scale(1); }
  to { opacity: 0; transform: translateY(-10px) scale(.95); }
}

/* Gift promo celebration — centered, self-dismissing, with confetti. */
.gift-celebration {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 200;
  pointer-events: none;
  background: rgba(33, 31, 46, 0);
  transition: background .3s ease;
}
.gift-celebration.show { background: rgba(33, 31, 46, .4); }
.gift-celebration-card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 30px 26px;
  text-align: center;
  max-width: 320px;
  box-shadow: 0 24px 60px rgba(0,0,0,.35);
  transform: scale(.6);
  opacity: 0;
  transition: transform .4s cubic-bezier(.34,1.56,.64,1), opacity .3s ease;
}
.gift-celebration.show .gift-celebration-card { transform: scale(1); opacity: 1; }
.gift-celebration.hide .gift-celebration-card { transform: scale(.85); opacity: 0; }
.gift-celebration-icon {
  width: 64px;
  height: 64px;
  margin: 0 auto 14px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  color: #fff;
  font-size: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.gift-celebration-title {
  font-size: 24px;
  font-weight: 900;
  color: var(--ink);
  margin-bottom: 6px;
}
.gift-celebration-text {
  font-size: 16px;
  font-weight: 600;
  color: var(--ink-soft);
}
.confetti-piece {
  position: absolute;
  top: -20px;
  width: 8px;
  height: 14px;
  border-radius: 2px;
  opacity: .95;
  animation: confettiFall linear forwards;
}
@keyframes confettiFall {
  0% { transform: translateY(0) translateX(0) rotate(0deg); opacity: 1; }
  100% { transform: translateY(115vh) translateX(var(--drift)) rotate(var(--rot)); opacity: .25; }
}


.step {
  width: 100%;
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 22px 18px;
  box-shadow: var(--shadow-soft);
  animation: stepIn .35s cubic-bezier(.21,1.02,.73,1) both;
}
.step.leaving {
  animation: stepOut .16s ease both;
}
@keyframes stepIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } }
@keyframes stepOut { from { opacity: 1; transform: translateY(0) scale(1); } to { opacity: 0; transform: translateY(-10px) scale(.97); } }

.welcome-image {
  display: block;
  width: 100%;
  max-width: 260px;
  max-height: 260px;
  object-fit: contain;
  border-radius: 12px;
  margin: 0 auto 18px;
  animation: popBounce .5s cubic-bezier(.34,1.56,.64,1) both;
}

.welcome-promo { text-align: center; margin: 0 0 18px; }
.welcome-price { font-size: 26px; font-weight: 800; color: var(--ink); }
.welcome-price span { color: var(--primary-dark); }
.welcome-offers { display: flex; flex-direction: column; align-items: center; gap: 8px; margin-top: 8px; }
.welcome-offer {
  display: inline-block;
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 16px;
  font-weight: 800;
  color: var(--primary-dark);
  background: var(--surface-soft);
  border: 2px solid var(--border);
}
.welcome-offer.gift { background: #ece5fd; border-color: #d9caf9; }

.sold-widget {
  background: var(--surface-soft);
  border-radius: var(--radius-lg);
  padding: 18px 20px;
  margin: 0 0 22px;
  animation: popBounce .5s cubic-bezier(.34,1.56,.64,1) both;
  animation-delay: .1s;
  opacity: 0;
}
.sold-widget-top { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.sold-widget-icon {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: #ece5fd;
  color: var(--primary-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 19px;
  flex-shrink: 0;
}
.sold-widget-text { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.sold-widget-label { font-weight: 700; font-size: 17px; color: var(--ink); }
.sold-widget-sub { font-size: 13.5px; font-weight: 600; color: var(--ink-soft); }
.sold-widget-pct-wrap { position: relative; flex-shrink: 0; }
.sold-widget-pct {
  display: block;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  color: #fff;
  font-weight: 800;
  font-size: 16px;
  padding: 6px 16px;
  border-radius: 999px;
  box-shadow: 0 6px 14px rgba(124, 92, 240, .35);
}
.sold-widget-spark {
  position: absolute;
  top: -9px;
  right: -9px;
  width: 17px;
  height: 17px;
  fill: #f5b301;
  filter: drop-shadow(0 0 4px rgba(245, 179, 1, .7));
  animation: sparkTwinkle 1.9s ease-in-out infinite;
  pointer-events: none;
}
.sold-widget-spark.small {
  top: auto;
  right: auto;
  bottom: -6px;
  left: -6px;
  width: 11px;
  height: 11px;
  animation-delay: .95s;
}
@keyframes sparkTwinkle {
  0%, 100% { transform: scale(.3) rotate(0deg); opacity: 0; }
  50% { transform: scale(1) rotate(90deg); opacity: 1; }
}
/* A soft highlight sweeps across the pill every few seconds. */
.sold-widget-pct { position: relative; overflow: hidden; }
.sold-widget-pct::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: -60%;
  width: 40%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .45), transparent);
  transform: skewX(-20deg);
  animation: pctSheen 3.2s ease-in-out infinite;
}
@keyframes pctSheen {
  0%, 55% { left: -60%; }
  100% { left: 130%; }
}
@media (prefers-reduced-motion: reduce) {
  .sold-widget-spark, .sold-widget-pct::after { animation: none; opacity: 0; }
}
.sold-widget-bar {
  height: 14px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
}
.sold-widget-bar-fill {
  height: 100%;
  border-radius: 999px;
  width: 0%;
  background-color: var(--primary-dark);
  background-image:
    repeating-linear-gradient(135deg, rgba(255, 255, 255, .2) 0 10px, rgba(255, 255, 255, 0) 10px 20px),
    linear-gradient(90deg, var(--primary), var(--primary-dark));
  /* One stripe period is 28.28px along x (20px / cos 45deg) — the tile is
     exactly that size so the slide below loops with no visible jump. */
  background-size: 28.28px 28.28px, 100% 100%;
  animation: soldStripesSlide .9s linear infinite;
  transition: width .6s ease;
}
@keyframes soldStripesSlide {
  from { background-position: 0 0, 0 0; }
  to { background-position: 28.28px 0, 0 0; }
}
@media (prefers-reduced-motion: reduce) {
  .sold-widget-bar-fill { animation: none; }
}

@keyframes popBounce {
  from { opacity: 0; transform: scale(.8); }
  to { opacity: 1; transform: scale(1); }
}

.nogame-anim {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: 10px;
  margin: 12px 0 30px;
  height: 56px;
}
.nogame-ball {
  width: 42px;
  height: 42px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 17px;
  color: #fff;
  flex-shrink: 0;
  box-shadow: 0 10px 20px rgba(124, 92, 240, .3);
  animation: nogameBounce 1.5s infinite cubic-bezier(.45, 0, .55, 1);
}
.nogame-ball-1, .nogame-ball-2, .nogame-ball-3, .nogame-ball-4, .nogame-ball-5 {
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
}
.nogame-ball-1 { animation-delay: 0s; }
.nogame-ball-2 { animation-delay: .12s; }
.nogame-ball-3 { animation-delay: .24s; }
.nogame-ball-4 { animation-delay: .36s; }
.nogame-ball-5 { animation-delay: .48s; }
@keyframes nogameBounce {
  0%, 60%, 100% { transform: translateY(0) scale(1); }
  30% { transform: translateY(-20px) scale(1.08); }
}

.step-title {
  font-size: 28px;
  font-weight: 800;
  margin: 0 0 10px;
  line-height: 1.2;
  color: var(--ink);
}
.step-text {
  font-size: 19px;
  color: var(--ink-soft);
  margin: 0 0 12px;
}
.step-hint {
  font-size: 16px;
  color: var(--ink-soft);
  background: var(--surface-soft);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  margin: 0;
}
.step-hint strong { color: var(--primary-dark); font-size: 18px; }

.available-box {
  background: var(--surface-soft);
  border: 2px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px;
  margin: 0 0 12px;
}
.available-label {
  font-size: 16px;
  font-weight: 700;
  color: var(--ink-soft);
}
/* Floats over the list's top-right corner — takes no space of its own, so
   the rows underneath sit exactly where they would without it. */
.available-box { position: relative; }
.available-head {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 2;
}
.avail-btn {
  flex-shrink: 0;
  border: none;
  border-radius: 999px;
  padding: 8px 14px;
  font-size: 14px;
  font-weight: 800;
  color: #fff;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  box-shadow: 0 6px 14px rgba(124, 92, 240, .3);
  cursor: pointer;
}
.avail-btn:active { transform: scale(.96); }

.avail-modal-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 12px;
}
.avail-modal-title {
  margin: 0;
  font-size: 22px;
  font-weight: 800;
  color: var(--primary-dark);
}
.modal-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.logout-link-btn {
  flex: none;
  border: none;
  background: none;
  color: var(--peach);
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  padding: 4px;
}
.avail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(58px, 1fr));
  gap: 8px;
  overflow-y: auto;
  min-height: 0;
  max-height: 52dvh;
  padding: 2px;
}
.avail-hint { margin: -6px 0 0; font-size: 15px; color: var(--ink-soft); }
.sound-toggle-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 15px;
  font-weight: 600;
  text-align: left;
}
.sound-toggle-row input { width: 20px; height: 20px; accent-color: var(--primary); }
.sound-volume-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 15px;
  font-weight: 600;
  text-align: left;
}
.sound-volume-row input { width: 100%; accent-color: var(--primary); }
.sound-settings-btn.muted { color: var(--peach); }
.avail-chip {
  padding: 9px 0;
  border-radius: 12px;
  background: var(--surface-soft);
  border: 2px solid var(--border);
  font-size: 16px;
  font-weight: 800;
  color: var(--ink);
  font-family: inherit;
  cursor: pointer;
  transition: transform .1s ease, background .15s ease, border-color .15s ease;
}
.avail-chip:active { transform: scale(.94); }
.avail-chip.selected {
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  border-color: var(--primary-dark);
  color: #fff;
}
.avail-modal-card .btn-big { margin-bottom: 0; }
.avail-empty { grid-column: 1 / -1; color: var(--ink-soft); font-weight: 700; padding: 18px 0; }

#realCardsList {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 22px 8px;
  overflow-y: auto;
  min-height: 0;
  max-height: 60dvh;
  padding: 20px 2px 2px;
}
.real-card-empty { grid-column: 1 / -1; color: var(--ink-soft); font-weight: 600; padding: 10px 0; }

.real-cards-unpaid-note {
  background: var(--sun-soft, #fef3d5);
  border: 1.5px solid var(--sun-border, #f0dca2);
  color: #8a6d1f;
  font-size: 13px;
  font-weight: 700;
  padding: 8px 12px;
  border-radius: 12px;
  margin: 0 0 10px;
  text-align: center;
}
.real-card-item { display: flex; flex-direction: column; gap: 3px; align-items: center; position: relative; }
/* Cartón añadido a mano (de un amigo/familiar) — amarillo en vez de morado,
   para distinguirlo de un vistazo de los cartones propios del jugador. */
.real-card-item.extra-card .real-card-label {
  background: linear-gradient(135deg, #f2b93d, var(--sun));
}
.real-card-item.extra-card .real-card-table-wrap {
  border-color: var(--sun);
  box-shadow: 0 4px 10px rgba(184, 134, 11, .25);
}
.real-card-item.extra-card .real-card-grid th {
  background: linear-gradient(135deg, #f2b93d, var(--sun));
}
.real-card-label {
  margin: 0;
  font-size: 11px;
  font-weight: 800;
  color: #fff;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  padding: 3px 12px;
  border-radius: 999px;
}
/* Deja hueco para que el badge flotante no tape el título cuando el
   cartón está cerca de ganar. */
.real-card-item.close-1 .real-card-label,
.real-card-item.close-2 .real-card-label {
  margin-bottom: 14px;
}
.real-card-grid {
  width: 100%;
  position: relative;
}
.real-card-table-wrap {
  background: linear-gradient(160deg, var(--surface), var(--surface-soft));
  border: 1.5px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 4px 10px rgba(90, 70, 160, .12);
}
.real-card-grid table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.real-card-grid th {
  width: 20%;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  color: #fff;
  font-size: 11px;
  font-weight: 800;
  padding: 3px 0;
}
.real-card-grid td {
  width: 20%;
  height: 26px;
  text-align: center;
  vertical-align: middle;
  font-size: 12px;
  font-weight: 700;
  padding: 0;
  border: 1px solid var(--border);
  color: var(--ink);
}
.real-card-grid td.free {
  background: var(--mint-soft);
  color: var(--mint);
  font-size: 16px;
  font-weight: 800;
}
/* Celda de la figura actual: fondo amarillo entero, sin borde. */
.real-card-grid td.in-pattern:not(.free) {
  background: var(--sun-soft);
  position: relative;
}
/* Marcado pero fuera de la figura: gris, no compite visualmente con lo que
   sí hace falta para completar el bingo. */
.real-card-grid td.marked:not(.free):not(.in-pattern) {
  background: #9a98a8;
  color: #fff;
}
/* Marcado Y dentro de la figura: se queda el fondo amarillo, y el número
   anotado aparece como un círculo encima — como un sello de bingo real. */
.real-card-grid td.marked.in-pattern:not(.free) {
  color: #fff;
}
.real-card-grid td.marked.in-pattern:not(.free)::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 72%;
  height: 72%;
  transform: translate(-50%, -50%);
  background: var(--primary);
  border-radius: 50%;
  box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
  z-index: 0;
}
/* A positioned ::before always paints over plain inline text regardless of
   source order — the number needs its own stacking context, explicitly
   above the circle, or the circle covers it. */
.real-card-grid td .cell-num {
  position: relative;
  z-index: 1;
}
.real-card-grid td.just-marked {
  position: relative;
  z-index: 1;
  animation: cellMarkPop .6s cubic-bezier(.34, 1.56, .64, 1) both;
}
/* La celda exacta que hace falta para ganar (cuando "falta 1") titila
   fuerte — distinto del amarillo fijo de in-pattern, para que salte a la
   vista justo el número que se está esperando, no toda la figura. La
   misma bolita titila también en el tablero maestro (ver abajo). */
@keyframes neededBlink {
  0%, 100% { background: var(--peach); color: #fff; box-shadow: 0 0 0 0 rgba(224, 56, 79, .55); }
  50% { background: #fff6d8; color: var(--ink); box-shadow: 0 0 0 4px rgba(224, 56, 79, 0); }
}
.real-card-grid td.needed-blink {
  position: relative;
  z-index: 1;
  animation: neededBlink .8s ease-in-out infinite;
}
@keyframes cellMarkPop {
  0% { transform: scale(.3) rotate(-25deg); background: var(--sun); box-shadow: 0 0 0 0 var(--sun-soft); }
  45% { transform: scale(1.35) rotate(8deg); background: var(--sun); box-shadow: 0 0 0 6px var(--sun-soft); }
  75% { transform: scale(.92) rotate(-3deg); }
  100% { transform: scale(1) rotate(0deg); box-shadow: 0 0 0 0 transparent; }
}
.real-card-item.bingo .real-card-table-wrap {
  animation: bingoPulse 1s ease-in-out infinite;
}
.real-card-bingo-banner {
  margin: 4px 0 0;
  font-size: 15px;
  font-weight: 900;
  color: var(--peach);
  text-align: center;
}
.claim-bingo-btn {
  /* OJO: nunca reusar la animación badgeWiggle acá — esa trae un
     translateX(-50%) pensado para un badge con position:absolute;
     left:50%. Aplicado a este botón (normal, en el flujo) lo corre medio
     ancho propio hacia la izquierda y queda "cortado". */
  box-sizing: border-box;
  width: 100%;
  max-width: 100%;
  margin-top: 6px;
  padding: 8px 10px;
  border: none;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 800;
  color: #fff;
  background: linear-gradient(135deg, var(--peach), #b01f38);
  box-shadow: 0 4px 12px rgba(224, 56, 79, .4);
  cursor: pointer;
  animation: claimBtnPulse 1.6s ease-in-out infinite;
}
.claim-bingo-btn:active { transform: scale(.95); }
.claim-bingo-btn:disabled {
  background: var(--mint);
  box-shadow: none;
  animation: none;
  opacity: .9;
  cursor: default;
}
@keyframes claimBtnPulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.04); }
}
@keyframes bingoPulse {
  0%, 100% { box-shadow: 0 4px 10px rgba(90, 70, 160, .12); }
  50% { box-shadow: 0 0 0 4px var(--sun-soft), 0 4px 14px rgba(90, 70, 160, .2); }
}
.real-card-item.close-2 .real-card-table-wrap {
  animation: closeCallPulse 1.1s ease-in-out infinite;
}
.real-card-item.close-1 .real-card-table-wrap {
  animation: closeCallPulseUrgent 1.1s ease-in-out infinite;
}
/* Flota pegado arriba de ESA tarjeta puntual, con una flechita abajo que
   la señala directamente — no es solo un texto suelto cerca del cartón. */
.real-card-badge {
  position: absolute;
  top: -15px;
  left: 50%;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 5px 13px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 800;
  color: #fff;
  white-space: nowrap;
  background: linear-gradient(135deg, var(--sun), #e0a500);
  box-shadow: 0 4px 10px rgba(184, 134, 11, .35);
  animation: badgePop .45s cubic-bezier(.34, 1.56, .64, 1) both, badgeWiggle 1.6s ease-in-out .45s infinite;
}
.real-card-badge::after {
  content: '';
  position: absolute;
  bottom: -5px;
  left: 50%;
  transform: translateX(-50%);
  width: 0;
  height: 0;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-top: 6px solid #e0a500;
}
.real-card-badge.urgent {
  background: linear-gradient(135deg, var(--peach), #b01f38);
  box-shadow: 0 4px 10px rgba(224, 56, 79, .4);
  font-size: 13.5px;
}
.real-card-badge.urgent::after { border-top-color: #b01f38; }
.real-card-badge.suspended {
  background: linear-gradient(135deg, #8a8a8a, #5f5f5f);
  box-shadow: 0 4px 10px rgba(0, 0, 0, .25);
  animation: none;
}
.real-card-badge.suspended::after { border-top-color: #5f5f5f; }
.real-card-item.suspended { opacity: .6; filter: grayscale(.5); }
.real-card-item.suspended .real-card-table-wrap { animation: none !important; }
@keyframes badgePop {
  0% { transform: translateX(-50%) scale(0); opacity: 0; }
  70% { transform: translateX(-50%) scale(1.18); opacity: 1; }
  100% { transform: translateX(-50%) scale(1); }
}
@keyframes badgeWiggle {
  0%, 100% { transform: translateX(-50%) rotate(0deg); }
  25% { transform: translateX(-50%) rotate(-5deg); }
  75% { transform: translateX(-50%) rotate(5deg); }
}
@keyframes closeCallPulse {
  0%, 100% { box-shadow: 0 4px 10px rgba(90, 70, 160, .12); }
  50% { box-shadow: 0 0 0 3px var(--sun-soft); }
}
@keyframes closeCallPulseUrgent {
  0%, 100% { box-shadow: 0 4px 10px rgba(90, 70, 160, .12); }
  50% { box-shadow: 0 0 0 3px var(--peach-soft); }
}
.board-rows {
  overflow-y: auto;
  font-size: 14px;
  line-height: 1.4;
  font-weight: 700;
  color: var(--ink);
}
.board-row {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  margin: 0;
  padding: 2px 0;
}
.board-n {
  flex: none;
  font-weight: 800;
}
.board-badge {
  flex: none;
  max-width: 65%;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.board-badge.paid { background: var(--mint-soft); color: #0d7a53; }
.board-badge.reserved { background: var(--sun-soft); color: var(--sun); }
.board-badge.gift { background: #ece5fd; color: var(--primary-dark); }

.gift-promo-hint {
  display: flex;
  align-items: center;
  gap: 8px;
  background: linear-gradient(120deg, #ece5fd, #f6ecff, #ece5fd);
  background-size: 220% 100%;
  color: var(--primary-dark);
  border: 2px solid #d9caf9;
  border-radius: var(--radius-md);
  padding: 9px 12px;
  font-size: 13px;
  font-weight: 700;
  margin: 0 0 8px;
  animation: giftHintGlow 2.2s ease-in-out infinite, giftHintShimmer 3.5s linear infinite;
}
.gift-promo-icon {
  flex: none;
  font-size: 16px;
  color: var(--primary);
  animation: giftHintBounce 1.1s ease-in-out infinite;
}
@keyframes giftHintGlow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(124, 92, 240, .38); }
  50% { box-shadow: 0 0 0 7px rgba(124, 92, 240, 0); }
}
@keyframes giftHintShimmer {
  0% { background-position: 0% 0; }
  100% { background-position: 220% 0; }
}

.sale-paused-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  background: #fdeeee;
  color: #8a1424;
  border: 2px solid #f6b9c1;
  border-radius: var(--radius-md);
  padding: 9px 12px;
  font-size: 13px;
  font-weight: 700;
  margin: 0 0 8px;
}
.sale-paused-banner i { flex: none; font-size: 15px; }
@keyframes giftHintBounce {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  25% { transform: translateY(-3px) rotate(-8deg); }
  50% { transform: translateY(0) rotate(0deg); }
  75% { transform: translateY(-2px) rotate(6deg); }
}
.available-empty {
  font-size: 17px;
  color: var(--ink-soft);
  text-align: center;
  padding: 10px 0;
}

.pick-chat-log {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 10px;
}
.pick-chat-log:empty { margin-bottom: 0; }
.chat-msg {
  background: #ece5fd;
  border: 2px solid #d9caf9;
  border-radius: var(--radius-md);
  padding: 14px 16px;
  font-size: 18px;
  color: var(--primary-dark);
  animation: stepIn .3s cubic-bezier(.21,1.02,.73,1) both;
}
.chat-msg .who {
  display: block;
  font-size: 13px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--primary);
  margin-bottom: 4px;
}
.op-copy-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding: 10px 12px;
  background: rgba(255, 255, 255, .55);
  border: 1.5px solid #d9caf9;
  border-radius: var(--radius-sm, 10px);
}
.op-copy-text {
  flex: 1;
  white-space: pre-line;
  font-size: 14px;
  line-height: 1.5;
  color: var(--primary-dark);
}
.typing-dots { display: inline-flex; gap: 4px; align-items: center; height: 20px; }
.typing-dots span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--primary);
  animation: typingBounce 1.2s infinite ease-in-out both;
}
.typing-dots span:nth-child(1) { animation-delay: -.28s; }
.typing-dots span:nth-child(2) { animation-delay: -.14s; }
@keyframes typingBounce {
  0%, 80%, 100% { transform: scale(.6); opacity: .5; }
  40% { transform: scale(1); opacity: 1; }
}
.chat-msg-pinned {
  position: sticky;
  top: 6px;
  z-index: 2;
  box-shadow: 0 3px 10px rgba(107, 79, 15, .16);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 3px;
  padding: 5px 8px;
  border-color: #f0dca2;
  background: var(--sun-soft);
}
.pinned-title {
  font-weight: 800;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: #a5791c;
}
.pinned-credit {
  font-weight: 800;
  font-size: 11px;
  color: #0d7a53;
  align-self: flex-end;
  text-align: right;
}
.pinned-numbers {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
}
.pinned-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  padding: 1px 6px;
  border-radius: 999px;
  background: #fff;
  border: 1.5px solid #f0dca2;
  font-weight: 800;
  font-size: 12px;
  color: #6b4f0f;
  transition: transform .45s cubic-bezier(.34, 1.56, .64, 1), opacity .3s ease;
}
.pinned-chip-gift {
  border-color: var(--primary);
  background: #ece5fd;
  color: var(--primary-dark);
}
.pinned-chip-paid {
  border-color: var(--mint);
  background: var(--mint-soft);
  color: #0d7a53;
}
.pinned-chip-paid::after {
  content: '✓';
  position: absolute;
  top: -6px;
  right: -6px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--mint);
  color: #fff;
  font-size: 9px;
  font-weight: 900;
  line-height: 13px;
  text-align: center;
}
.pinned-chip-pending {
  border-color: var(--sun);
  background: var(--sun-soft);
  color: #6b4f0f;
}
.pinned-chip-pending::after {
  content: '⏳';
  position: absolute;
  top: -7px;
  right: -6px;
  font-size: 10px;
  line-height: 1;
}
.pinned-chip-enter {
  opacity: 0;
  transform: scale(0) rotate(-25deg);
}
/* Floating clone that flies from its row in the numbers list down into the
   pinned card — big, tumbling and unmissable, instead of a quiet instant
   jump. Driven by the Web Animations API in JS, not a CSS transition, so no
   rule here for transform/opacity timing — visuals only. */
.flying-chip {
  position: fixed;
  z-index: 90;
  margin: 0;
  min-width: 34px;
  padding: 4px 10px;
  font-size: 16px;
  pointer-events: none;
  box-shadow: 0 6px 20px rgba(107, 79, 15, .45);
}
.pinned-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
}
.pinned-timer {
  font-variant-numeric: tabular-nums;
  font-weight: 800;
  font-size: 13px;
  color: #a5791c;
}
.pinned-timer:empty { display: none; }
.pinned-timer.urgent { color: var(--peach); }
.pinned-pay-group {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
}
.pinned-amount {
  font-weight: 800;
  font-size: 13px;
  color: var(--ink);
  white-space: nowrap;
}
.pinned-continue-btn {
  border: none;
  border-radius: 999px;
  padding: 9px 20px;
  font-size: 15px;
  font-weight: 800;
  color: #fff;
  background: linear-gradient(135deg, #ff9d45, #f5720f);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  box-shadow: 0 4px 14px rgba(245, 114, 15, .45);
  transition: transform .15s ease, box-shadow .15s ease;
  animation: pinnedPayAttention 1.4s ease-in-out infinite;
}
.pinned-continue-btn:hover { transform: translateY(-1px) scale(1.04); box-shadow: 0 6px 18px rgba(245, 114, 15, .55); }
.pinned-continue-btn:active { transform: translateY(0) scale(.97); }
@keyframes pinnedPayAttention {
  0%, 100% { transform: scale(1); box-shadow: 0 4px 14px rgba(245, 114, 15, .45); }
  50% { transform: scale(1.06); box-shadow: 0 6px 20px rgba(245, 114, 15, .65); }
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 12px;
}
.field span { font-size: 16px; font-weight: 700; color: var(--ink-soft); }

.method-link {
  align-self: center;
  margin-top: 10px;
  padding: 6px 4px;
  border: none;
  background: none;
  color: var(--ink-soft);
  font-size: 13.5px;
  font-weight: 700;
  text-decoration: underline;
  cursor: pointer;
}
.method-link:hover { color: var(--primary-dark); }
.field input {
  width: 100%;
  padding: 16px 18px;
  border: 2px solid var(--border);
  border-radius: var(--radius-md);
  font-size: 22px;
  outline: none;
  background: var(--surface-soft);
  transition: border-color .15s ease;
}
.field input:focus { border-color: var(--primary); }

.file-input-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
}
.file-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 26px 16px;
  border: 2px dashed var(--primary);
  border-radius: var(--radius-md);
  background: var(--surface-soft);
  cursor: pointer;
  text-align: center;
  transition: background .15s ease, border-color .15s ease;
}
.file-drop:hover { background: #efeaff; }
.file-drop.has-file {
  border-style: solid;
  border-color: var(--mint);
  background: var(--mint-soft);
}
.file-drop-icon { font-size: 38px; }
.file-drop-text {
  font-size: 16px;
  font-weight: 700;
  color: var(--ink-soft);
  word-break: break-all;
}
.file-drop.has-file .file-drop-text { color: #0d7a53; }

.step-pick {
  padding-top: 10px;
  padding-bottom: calc(var(--composer-h, 88px) + 16px);
  display: flex;
  flex-direction: column;
  height: calc(100dvh - 22px);
  overflow-y: auto;
}
.step-pick .step-title {
  font-size: 19px;
  margin: 0 0 8px;
}
/* The available-cartones list claims whatever room is left after the title,
   hint and chat log (with the pinned "apartados" card) take theirs — it
   fills the screen when there's little else showing, and shrinks on its own
   as the chat above it grows, no JS math needed. The chat log itself always
   shows its full content (never clipped or shrunk) — if it and the title
   ever take up more than the screen between them, this whole step scrolls
   as a unit instead (see overflow-y above), which still can't grow past its
   fixed height, so the composer fixed at the bottom never covers anything. */
.step-pick .available-box {
  flex: 1 1 auto;
  min-height: 190px;
  display: flex;
  flex-direction: column;
}
.step-pick .available-label { flex: 0 0 auto; }
.step-pick .board-rows {
  flex: 1 1 auto;
  min-height: 0;
}
.step-pick > .step-title,
.step-pick > #giftPromoHint,
.step-pick > #pickError,
.step-pick #pickChatLog { flex: 0 0 auto; }

.chat-composer {
  position: fixed;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 560px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  background: var(--surface);
  border-top: 2px solid var(--border);
  box-shadow: 0 -6px 20px rgba(90, 70, 160, .12);
  z-index: 50;
}
.chat-input {
  flex: 1;
  min-width: 0;
  padding: 13px 18px;
  border-radius: 999px;
  border: 2px solid var(--border);
  background: var(--surface-soft);
  font-size: 18px;
  outline: none;
  transition: border-color .15s ease;
}
.chat-input:focus { border-color: var(--primary); }
.chat-input.paused,
.chat-input.paused:disabled {
  background: #ffe4e8;
  border-color: #f3b3bd;
  color: #a5233a;
  -webkit-text-fill-color: #a5233a;
  opacity: 1;
}
.chat-input.paused::placeholder { color: #c0566a; opacity: 1; font-weight: 800; }
.chat-input.paused {
  text-align: center;
  animation: pausedPulse 1.6s ease-in-out infinite;
}
@keyframes pausedPulse {
  0%, 100% { background: #ffe4e8; box-shadow: 0 0 0 0 rgba(224, 56, 79, 0); }
  50% { background: #ffcfd6; box-shadow: 0 0 0 6px rgba(224, 56, 79, .18); }
}
.chat-send-btn {
  width: 50px;
  height: 50px;
  flex-shrink: 0;
  border-radius: 50%;
  border: none;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  color: #fff;
  font-size: 20px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 6px 16px rgba(124, 92, 240, .35);
  transition: transform .15s ease, opacity .15s ease;
}
.chat-send-btn:active { transform: scale(.94); }
.chat-send-btn:disabled { opacity: .5; cursor: default; }

.btn-big {
  width: 100%;
  padding: 16px;
  border-radius: var(--radius-md);
  border: none;
  font-size: 21px;
  font-weight: 800;
  cursor: pointer;
  margin-bottom: 10px;
  transition: transform .15s ease, box-shadow .15s ease;
}
.btn-big:hover { transform: translateY(-1px); }
.btn-big:active { transform: translateY(0) scale(.98); }
.btn-big:disabled { opacity: .6; cursor: default; transform: none; }
.btn-primary {
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  color: #fff;
  box-shadow: 0 10px 24px rgba(124, 92, 240, .38);
}
.btn-primary:disabled {
  background: #c7c5d1;
  color: #8a889a;
  box-shadow: none;
  opacity: 1;
}

/* Draws the eye to "Ya pagué, reportar" as soon as it becomes clickable,
   so it's obvious the client still has to press it after choosing a photo
   or typing a reference — nothing gets reported on its own. */
#paySubmit:not(:disabled) {
  animation: paySubmitAttention 1.4s ease-in-out infinite;
}
@keyframes paySubmitAttention {
  0%, 100% { transform: scale(1); box-shadow: 0 10px 24px rgba(124, 92, 240, .38); }
  50% { transform: scale(1.035); box-shadow: 0 12px 30px rgba(124, 92, 240, .55); }
}
.btn-ghost {
  background: var(--surface-soft);
  color: var(--ink-soft);
  border: 2px solid var(--border);
}
.btn-cancel {
  background: var(--peach-soft);
  color: #8a1424;
  border: 2px solid #f6b9c1;
}
.btn-close-small {
  display: block;
  margin: 6px auto 0;
  padding: 8px 22px;
  border-radius: 999px;
  border: 1.5px solid #f6b9c1;
  background: var(--peach-soft);
  color: #8a1424;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}
.btn-close-small:active { transform: scale(.96); }
.real-cards-modal-actions {
  display: flex;
  gap: 10px;
  margin-top: 6px;
}
.real-cards-modal-actions .btn-close-small { margin: 0; flex: 1; }
.btn-close-small-primary {
  border-color: var(--primary-dark);
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  color: #fff;
}

/* ---------- Dashboard de juego en vivo (pantalla completa) ---------- */
/* Columna flex con cada franja (bola, tablero, cartones, chat) una debajo
   de la otra — en vez de forzar que todo entre en una sola pantalla
   (lo que termina "achicando con zoom" en celulares chicos), si no entra
   completo esta pantalla se desplaza verticalmente como cualquier otra. */
#stepGameDashboard {
  /* Con el logo visible arriba, el alto real que queda lo decide el propio
     flex del layout (.wrap/.screen-area) — por eso ya no se fuerza un
     100dvh fijo acá, solo se ocupa lo que sobre y nunca más que eso. */
  align-self: stretch;
  width: 100%;
  min-height: 0;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 10px 14px calc(8px + env(safe-area-inset-bottom, 0px));
  gap: 6px;
  background: linear-gradient(180deg, #f1ebfd, #ddcefa);
}
.game-dashboard-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
}
.game-dashboard-head .step-title { margin: 0; font-size: 19px; }
.live-online-count {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12.5px;
  font-weight: 800;
  color: var(--mint);
  background: var(--mint-soft);
  padding: 4px 10px;
  border-radius: 999px;
  border: none;
  cursor: pointer;
}
.online-modal-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 50vh;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.online-modal-list li {
  padding: 8px 12px;
  border-radius: 10px;
  background: var(--surface-soft);
  font-weight: 700;
  font-size: 14px;
  color: var(--ink);
}
.online-modal-list .online-modal-empty {
  color: var(--ink-soft);
  font-weight: 500;
  font-style: italic;
  background: none;
  text-align: center;
}
.icon-btn {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: linear-gradient(135deg, var(--surface), var(--surface-soft));
  box-shadow: 0 2px 6px rgba(90, 70, 160, .15), inset 0 0 0 1.5px var(--border);
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.icon-btn:active { transform: scale(.94); }
.icon-btn svg { width: 18px; height: 18px; flex: none; }

/* Chat en vivo del tablero — ya no es una burbuja flotante que hay que
   abrir: vive siempre visible, debajo de los cartones, como una franja
   más de la pantalla (con su propia altura fija y scroll interno para los
   mensajes, para no comerse el espacio de los cartones). Sigue siendo
   opt-in — "Unirse" en vez de mensajes/micrófono hasta que lo pidan. */
.live-chat-panel {
  flex: 0 0 auto;
  width: 100%;
  background: var(--surface);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-soft);
  display: flex;
  flex-direction: column;
  height: 280px;
  overflow: hidden;
}
.live-chat-panel-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 8px 14px;
  background: var(--surface-soft);
  font-weight: 700;
  font-size: 14px;
}
.live-chat-participants { font-weight: 600; font-size: 12.5px; color: var(--ink-soft); }
.live-chat-join-prompt {
  padding: 18px 16px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.live-chat-join-prompt p { margin: 0; color: var(--ink-soft); font-size: 14.5px; }
.live-chat-body {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
}
.live-chat-messages {
  flex: 1;
  min-height: 60px;
  overflow-y: auto;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.live-chat-msg { font-size: 14px; line-height: 1.3; word-break: break-word; }
.live-chat-msg .live-chat-msg-name { font-weight: 700; color: var(--primary-dark); margin-right: 4px; }
.live-chat-msg.own .live-chat-msg-name { color: var(--mint); }
.live-chat-msg-system { font-size: 12.5px; color: var(--ink-soft); text-align: center; }
.live-chat-form {
  flex: 0 0 auto;
  display: flex;
  gap: 8px;
  padding: 8px 10px;
  border-top: 1px solid var(--border);
}
.live-chat-form input {
  flex: 1;
  min-width: 0;
  border: 1.5px solid var(--border);
  border-radius: 20px;
  padding: 9px 14px;
  font-size: 14.5px;
  background: var(--surface-soft);
  color: var(--ink);
}
.live-chat-form input:focus { outline: none; border-color: var(--primary); }
.live-chat-send {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: var(--primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.live-chat-send svg { width: 17px; height: 17px; }
.live-chat-leave {
  flex: 0 0 auto;
  margin: 0 10px 10px;
  border: none;
  background: none;
  color: var(--peach);
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
  padding: 4px;
}
.live-chat-mic {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: var(--surface-soft);
  color: var(--ink-soft);
  box-shadow: inset 0 0 0 1.5px var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.live-chat-mic svg { width: 18px; height: 18px; }
.live-chat-mic.recording {
  background: var(--peach);
  color: #fff;
  box-shadow: 0 0 0 0 rgba(224, 56, 79, .5);
  animation: micRecordPulse 1s ease-in-out infinite;
}
@keyframes micRecordPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(224, 56, 79, .5); }
  50% { box-shadow: 0 0 0 7px rgba(224, 56, 79, 0); }
}
.live-chat-recording-hint {
  margin: 0 10px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--peach);
}
/* Nota de voz estilo WhatsApp — botón play redondo + línea de progreso +
   duración, en vez del <audio controls> nativo (feo y distinto en cada
   navegador). El <audio> real nunca se inserta en el DOM, solo vive en JS
   (buildVoiceNoteNode) — no hace falta mostrarlo para que funcione. */
.voice-note {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  padding: 5px 12px 5px 5px;
  border-radius: 999px;
  background: var(--surface-soft);
  box-shadow: inset 0 0 0 1.5px var(--border);
  max-width: 230px;
}
.live-chat-msg.own .voice-note { background: var(--mint-soft); }
.voice-note-play {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: none;
  background: var(--primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font-size: 12px;
}
.voice-note-play svg { width: 14px; height: 14px; }
.live-chat-msg.own .voice-note-play { background: var(--mint); }
.voice-note-track {
  flex: 1;
  min-width: 50px;
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  position: relative;
  cursor: pointer;
}
.voice-note-fill {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 0%;
  border-radius: 2px;
  background: var(--primary);
}
.live-chat-msg.own .voice-note-fill { background: var(--mint); }
.voice-note-fill::after {
  content: '';
  position: absolute;
  right: -4px;
  top: 50%;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: inherit;
  transform: translateY(-50%);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
}
.voice-note-time {
  flex: none;
  min-width: 30px;
  text-align: right;
  font-size: 11px;
  font-weight: 700;
  color: var(--ink-soft);
}
.live-chat-emoji-btn {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: none;
  background: var(--surface-soft);
  box-shadow: inset 0 0 0 1.5px var(--border);
  font-size: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.live-chat-emoji-panel {
  flex: 0 0 auto;
  max-height: 150px;
  overflow-y: auto;
  padding: 8px 10px 2px;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 2px;
  border-top: 1px solid var(--border);
}
.live-chat-emoji-panel button {
  border: none;
  background: none;
  font-size: 21px;
  line-height: 1;
  padding: 5px 0;
  border-radius: 8px;
  cursor: pointer;
}
.live-chat-emoji-panel button:active { background: var(--surface-soft); }

/* Bola actual + historial reciente + mini-vista de la figura, todo en una
   fila arriba del tablero — de un vistazo, sin tener que buscar. */
.live-call-row {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  overflow-x: auto;
}
.live-current-ball {
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  /* Esfera 3D: brillo arriba-izquierda, oscuro abajo-derecha, más un filo
     de luz/sombra por dentro para que se note el relieve. */
  background: radial-gradient(circle at 32% 28%, #b39bfb, var(--primary) 55%, var(--primary-dark) 100%);
  color: #fff;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8px 20px rgba(124, 92, 240, .45), inset 0 -5px 8px rgba(0, 0, 0, .22), inset 0 3px 6px rgba(255, 255, 255, .4);
}
.live-current-ball-letter { font-size: 11px; font-weight: 800; letter-spacing: .5px; opacity: .85; }
.live-current-ball-num { font-size: 18px; font-weight: 900; line-height: 1; }
.live-recent-balls {
  flex: 1;
  display: flex;
  gap: 6px;
  overflow-x: auto;
  min-width: 0;
}
.live-recent-ball {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  font-size: 12px;
  font-weight: 800;
  color: #fff;
  box-shadow: 0 3px 8px rgba(124, 92, 240, .3);
}
.live-pattern-preview {
  flex: none;
  text-align: center;
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  border: none;
  border-radius: 12px;
  padding: 6px 8px;
  box-shadow: 0 4px 10px rgba(90, 70, 160, .25);
}
.live-pattern-preview-title {
  margin: 0 0 4px;
  font-size: 10.5px;
  font-weight: 800;
  color: #fff;
  opacity: .85;
  text-transform: uppercase;
  letter-spacing: .4px;
}
.live-pattern-list {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  max-width: 140px;
}
.live-pattern-item { flex: none; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.live-pattern-item-name {
  font-size: 7px;
  font-weight: 700;
  color: rgba(255, 255, 255, .8);
  max-width: 34px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.live-pattern-mini-grid {
  display: grid;
  grid-template-columns: repeat(5, 7px);
  grid-template-rows: repeat(5, 7px);
  gap: 2px;
}
.live-pattern-mini-cell { background: rgba(255, 255, 255, .25); border-radius: 2px; }
.live-pattern-mini-cell.on { background: linear-gradient(135deg, var(--sun), #e0a500); }
.live-pattern-mini-cell.center { background: linear-gradient(135deg, var(--mint), #16895f); }

/* Tablero completo 1-75 por columna B-I-N-G-O, como el de un salón de
   bingo real — se ve de un vistazo qué ya salió. */
/* Una fila por letra (B/I/N/G/O), sus 15 números en horizontal — mucho más
   bajo que 15 filas apiladas, y se puede desplazar de lado si no entran
   todas en el ancho de la pantalla. */
.live-master-board {
  flex: 0 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  overflow: hidden;
  background: var(--bg-a);
  border-radius: 14px;
  padding: 6px 5px;
}
.master-board-row {
  display: flex;
  align-items: center;
  gap: 4px;
}
.master-board-row-head {
  flex: none;
  width: 18px;
  text-align: center;
  font-weight: 800;
  font-size: 11px;
  color: #fff;
  padding: 2px 0;
  border-radius: 5px;
  background: var(--primary);
}
.master-board-row-cells {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(15, 1fr);
  gap: 2px;
  overflow-x: auto;
}
.master-board-cell {
  /* Ancho y alto iguales (no un height fijo contra un ancho de columna
     distinto) — así el círculo de "called" sale redondo de verdad, no
     ovalado/aplastado. Con 15 columnas angostas esto da una celda chica,
     no el problema de antes con 5 columnas anchas. */
  aspect-ratio: 1;
  width: 100%;
  max-width: 20px;
  max-height: 20px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 8px;
  font-weight: 700;
  border-radius: 4px;
  background: #fff;
  color: var(--primary-dark);
}
.master-board-cell.called {
  background: linear-gradient(135deg, var(--primary), var(--primary-dark));
  color: #fff;
  border-radius: 50%;
  box-shadow: 0 2px 6px rgba(124, 92, 240, .35);
}
/* Esta bolita, si sale, le da bingo a algún cartón en vista — titila igual
   que la celda que la espera en el cartón (ver neededBlink arriba). */
.master-board-cell.needed-blink {
  animation: neededBlink .8s ease-in-out infinite;
  border-radius: 50%;
}

.my-cards-nav {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--primary);
  border-radius: 12px;
  padding: 7px 10px 7px 14px;
}
.my-cards-nav h2 { margin: 0; font-size: 15px; color: #fff; }
.my-cards-count { font-size: 13px; font-weight: 700; opacity: .8; }
.my-cards-nav-arrows { display: flex; gap: 8px; }
.my-cards-nav .icon-btn {
  background: rgba(255, 255, 255, .18);
  box-shadow: none;
  color: #d9d4ea;
}

/* ---------- Añadir cartón de otra persona ---------- */
.add-card-section { display: flex; flex-direction: column; gap: 6px; }
.add-card-label { font-size: 13.5px; font-weight: 700; color: var(--ink-soft); }
.add-card-row { display: flex; gap: 8px; }
.add-card-row input {
  flex: 1;
  min-width: 0;
  padding: 11px 14px;
  border: 2px solid var(--border);
  border-radius: var(--radius-md);
  font-size: 16px;
  outline: none;
  background: var(--surface-soft);
  transition: border-color .15s ease;
}
.add-card-row input:focus { border-color: var(--primary); }
.add-card-row .btn-close-small { flex: none; margin: 0; white-space: nowrap; }
.add-card-extra-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  max-height: 30dvh;
  overflow-y: auto;
}
.add-card-extra-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px 6px 12px;
  border-radius: 999px;
  background: var(--mint-soft);
  border: 1.5px solid var(--mint);
  font-size: 13px;
  font-weight: 800;
  color: #0d7a53;
}
.add-card-extra-chip button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: none;
  background: rgba(0, 0, 0, .12);
  color: inherit;
  cursor: pointer;
  padding: 0;
}
.add-card-extra-chip svg { width: 11px; height: 11px; }

/* Tres cartones a la vez, en fila horizontal con scroll — las flechitas de
   arriba avanzan/retroceden una pantalla. */
.real-cards-dashboard-grid {
  /* flex-grow en 0: antes era 1 y esta zona se estiraba para tragarse
     todo el espacio vertical sobrante de #stepGameDashboard, empujando
     el chat (que va justo después) hasta pegarlo al fondo de la
     pantalla. min-height sigue siendo el piso real para flexbox. */
  flex: 0 1 260px;
  /* Antes 220px: un cartón con el banner "¡BINGO!" + el botón de avisar
     necesita más alto que uno normal — con 220px, flexbox lo achicaba
     (overflow-y:hidden de antes) y el botón quedaba recortado/tapado
     detrás del chat de abajo. min-height es un piso real para flexbox
     (no se puede achicar más que esto), así que ahora siempre entra
     completo sin necesidad de recortar nada. */
  min-height: 320px;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  overflow-x: auto;
  overflow-y: auto;
  scroll-snap-type: x mandatory;
  padding: 18px 2px 6px;
}
.real-cards-dashboard-grid .real-card-item {
  flex: none;
  width: 31%;
  min-width: 150px;
  scroll-snap-align: start;
}

.numbers-box {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 20px;
}
.numbers-box span {
  background: var(--surface-soft);
  border: 2px solid var(--border);
  border-radius: 14px;
  padding: 10px 16px;
  font-size: 22px;
  font-weight: 800;
  color: var(--primary-dark);
}

.total-box {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: var(--surface-soft);
  border-radius: var(--radius-md);
  padding: 16px 18px;
  margin-bottom: 22px;
  font-size: 18px;
}
.total-box strong { font-size: 26px; color: var(--primary-dark); }

/* Same box as a real error (#payError) — used for the "still owes X"
   partial-payment notice too, just recolored so it doesn't read as
   something wrong. */
.error-box.partial {
  background: var(--mint-soft);
  border-color: #a8e8cb;
  color: #0d7a53;
}

.timer-box {
  text-align: center;
  background: var(--surface-soft);
  border-radius: var(--radius-md);
  padding: 18px;
  margin-bottom: 20px;
}
.timer-label { display: block; font-size: 16px; color: var(--ink-soft); margin-bottom: 6px; font-weight: 700; }
.timer-display {
  font-size: 48px;
  font-weight: 900;
  color: var(--primary-dark);
  letter-spacing: 2px;
  font-variant-numeric: tabular-nums;
}
.timer-display.urgent { color: var(--peach); animation: pulse 1s infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }

.info-box {
  background: var(--sun-soft);
  border: 2px solid #f0dca2;
  border-radius: var(--radius-md);
  padding: 14px 16px;
  margin-bottom: 20px;
  font-size: 17px;
  color: #6b4f0f;
}
.payinfo-title {
  font-weight: 700;
  margin-bottom: 6px;
}
.payinfo-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 7px 0;
  border-top: 1px solid #e9d69c;
}
.payinfo-row:first-of-type { border-top: none; }
.payinfo-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.payinfo-label {
  font-size: 12.5px;
  font-weight: 700;
  color: #9a7c2c;
  text-transform: uppercase;
  letter-spacing: .3px;
}
.payinfo-value {
  font-size: 16.5px;
  font-weight: 700;
  color: #6b4f0f;
  word-break: break-word;
}
.payinfo-copy-btn {
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 10px;
  border: none;
  background: #fff;
  color: #9a7c2c;
  font-size: 15px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(0,0,0,.08);
  transition: background .15s ease, color .15s ease;
}
.payinfo-copy-btn:active { transform: scale(.94); }
.payinfo-copy-btn.copied {
  background: #dff3e4;
  color: #1c8a4b;
}

.error-box {
  background: var(--peach-soft);
  border: 2px solid #f6b9c1;
  color: #8a1424;
  border-radius: var(--radius-md);
  padding: 14px 16px;
  margin-bottom: 18px;
  font-size: 17px;
  font-weight: 600;
}

@media (max-width: 420px) {
  html, body { font-size: 18px; }
  /* Longhand on purpose, no bottom: a shorthand here would reset
     .step-pick's composer-clearance padding-bottom back down on every
     phone-width screen, since this rule comes later in the file. */
  .step { padding-top: 24px; padding-left: 18px; padding-right: 18px; }
  .step-title { font-size: 26px; }
  .timer-display { font-size: 40px; }
}

.modal-overlay {
  position: fixed;
  top: 0;
  left: 50%;
  right: 0;
  bottom: 0;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  margin: 0;
  background: rgba(33, 31, 46, .55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 200;
  animation: pushIn .25s ease both;
}
.modal-card-anim {
  width: 100%;
  max-width: 400px;
  max-height: 80vh;
  max-height: 80dvh;
  animation: popBounce .4s cubic-bezier(.34,1.56,.64,1) both;
}
.modal-card {
  width: 100%;
  max-height: 80vh;
  max-height: 80dvh;
  overflow-y: auto;
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: 30px 26px;
  text-align: center;
  box-shadow: 0 20px 50px rgba(0,0,0,.3);
}
.modal-icon { font-size: 44px; margin-bottom: 8px; }
.modal-title {
  font-size: 24px;
  font-weight: 800;
  color: var(--peach);
  margin: 0 0 12px;
}
.modal-text {
  font-size: 19px;
  color: var(--ink);
  margin: 0 0 24px;
  line-height: 1.5;
}
.modal-actions {
  display: flex;
  gap: 10px;
}
.modal-actions .btn-big {
  margin-bottom: 0;
}

.preloader {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(160deg, var(--bg-a), var(--bg-b));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  z-index: 999;
  transition: opacity .3s ease;
}
.preloader.fade-out { opacity: 0; pointer-events: none; }
.preloader-spinner { font-size: 46px; color: var(--primary); }
.preloader-text { font-size: 17px; font-weight: 700; color: var(--ink-soft); }

.blocked-overlay {
  z-index: 1000;
  background: linear-gradient(160deg, #2a1414, #1a0d0d);
  padding: 0 32px;
  text-align: center;
}
.blocked-overlay .preloader-spinner { color: #ef5350; }
.blocked-overlay .preloader-text { color: #f3d4d4; font-size: 16px; line-height: 1.5; }

.title-icon {
  color: var(--mint);
  margin-right: 10px;
}

.board-icon { margin-left: 4px; }
.board-icon.paid { color: var(--mint); }
.board-icon.pending { color: var(--sun); }

.btn-big i {
  margin-right: 8px;
}
