/* ═══════════════════════════════════════════════════════
   MIRLXS — Sistema de feedback y animaciones compartidas
   Toasts, loaders/spinners, pull-to-refresh, keyframes globales.
   Fuente única de estos 4 sistemas — importado en index.html
   e inscripcion/index.html, mismo criterio que nav.css.
   ═══════════════════════════════════════════════════════ */

/* ── Timing compartido ──────────────────────────────────
   Curva usada por bottom sheets, pantallas y paneles colapsables
   en toda la app (antes repetida como literal en 7 archivos CSS). */
:root {
  --ease-sheet: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ── Keyframes ───────────────────────────────────────── */
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes fadeIn { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: translateY(0); } }
@keyframes fadeOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-5px); } }
@keyframes popBounce {
  0% { transform: scale(0.5); opacity: 0; }
  60% { transform: scale(1.15); opacity: 1; }
  80% { transform: scale(0.95); }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes skeletonShimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
@keyframes fadeInBtn { from { opacity: 0; } to { opacity: 1; } }
@keyframes smoothSlideUp {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: none; }
}
/* Antes referenciada por #loading-overlay.fade-in sin estar definida en ningún archivo (no-op silencioso desde el commit inicial de global.css) — mismo shape que fadeInBtn */
@keyframes overlayFadeIn { from { opacity: 0; } to { opacity: 1; } }
/* Único valor real en uso hoy (.btn-pulse en inscripcion.css); la copia de home.css estaba definida pero sin ningún selector que la usara */
@keyframes pulseBtn {
  0%, 100% { box-shadow: 0 0 0 0 var(--brand-zero); border-color: var(--brand-pulse); }
  50% { box-shadow: 0 0 24px 8px var(--brand-40); border-color: var(--brand-strong); }
}
/* Genérica — usada hoy por 3 modales distintos (#modal-contacto, #modal-eliminar-cuenta, #modal-wp-comprobante) en ui.css */
@keyframes slideUpModal {
  from { transform: translateY(100%); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}

/* ── Loaders / spinners ──────────────────────────────── */
.spinner {
  width: 40px; height: 40px; border: 4px solid var(--border);
  border-top-color: var(--brand); border-radius: 50%;
  animation: spin 0.8s cubic-bezier(0.6, 0.2, 0.4, 0.8) infinite;
  margin: 0 auto 16px;
}
.btn-spinner {
  display: inline-block; width: 18px; height: 18px;
  border: 0px solid var(--white-40); border-top-color: var(--white);
  border-radius: 50%; animation: spin 0.8s linear infinite;
  vertical-align: middle; margin-right: 8px; margin-top: -2px;
}
.loader { text-align: center; padding: 40px 20px; color: var(--muted); }

#loading-overlay {
  position: fixed; inset: 0; background: var(--bg); z-index: 9999;
  display: flex; align-items: center; justify-content: center;
  transition: opacity 0.4s ease, visibility 0.4s ease;
}
#loading-overlay.fade-out { opacity: 0; visibility: hidden; }
#loading-overlay.fade-in { animation: overlayFadeIn 0.35s ease both; }

/* Wrapper de contenido del loader de pantalla completa — unificado desde
   css/login.css (.loading-card) e inscripcion.css (.loading-inner, eliminada). */
.loading-card { padding: 32px 48px; text-align: center; min-height: 130px; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.loading-card .spinner { margin: 0 auto 16px; flex-shrink: 0; }
.loading-card p { color: var(--neutral-light); font-size: 0.88rem; font-weight: 600; margin: 0; min-height: 24px; transition: opacity 0.3s ease; }
.loading-logo { display: none; }
@media (max-width: 600px) {
  .loading-logo { opacity: 0; }
  #loading-overlay .spinner { opacity: 0; }
  #loading-msg { opacity: 0; visibility: hidden; }
  #loading-overlay { background: var(--bg); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .loading-card { background: transparent; border-radius: 0; padding: 32px; box-shadow: none; border: none; width: 100%; max-width: 100%; }
  .loading-logo { display: block; opacity: 1; width: 88px; height: 88px; border-radius: 50%; object-fit: cover; object-position: center top; margin: 0 auto 28px; filter: drop-shadow(0 4px 16px var(--brand-20)); }
}

/* ── Toast / snackbar ────────────────────────────────── */
.app-toast { position:fixed; bottom:28px; left:50%; transform:translateX(-50%) translateY(20px); background:var(--surface); border:1px solid var(--border-light); border-radius:12px; padding:10px 18px; font-size:0.82rem; font-weight:700; color:var(--text); box-shadow:0 6px 24px var(--black-md); z-index:9999; opacity:0; transition:opacity 0.25s ease, transform 0.25s ease; pointer-events:none; max-width:calc(100% - 32px); text-align:center; }
.app-toast.visible { opacity:1; transform:translateX(-50%) translateY(0); }
.app-toast.app-toast-ok { border-color:var(--success); color:var(--success-dark); background:var(--green-light); }
.app-toast.app-toast-error { border-color:var(--danger); color:var(--danger); background:var(--danger-bg); }

/* ── Pull-to-refresh (Mis reservas) ──────────────────────
   Antes 100% inline en index.html — extraído a clases para
   cumplir la regla de "sin estilos inline repetidos". Los
   valores de opacity/transform durante el arrastre se calculan
   por frame en js/home.js y siguen escribiéndose inline (no son
   togglables por clase); solo el on/off de la transición y la
   estructura estática pasan a clases. */
.ptr-indicator {
  position: fixed; left: 50%; top: 70px; z-index: 950;
  opacity: 0; transform: translate(-50%,-50px) scale(0.7);
  transition: opacity 0.25s ease, transform 0.25s ease;
  pointer-events: none;
}
.ptr-indicator.ptr-sin-transicion { transition: none; }
.ptr-indicator-inner {
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--surface); box-shadow: var(--card-shadow);
  display: flex; align-items: center; justify-content: center;
}
.ptr-spinner { width: 20px; height: 20px; border-width: 3px; margin: 0; animation: none; }

/* ── Dark mode ───────────────────────────────────────── */
@media (prefers-color-scheme: dark) {
  .loading-card { border-color: var(--dk-skeleton-base); }
  .loading-card p { color: var(--dk-text-muted); }
}

/* ── CTA Footer fijo ───────────────────────── */
.cta-footer {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  padding: 12px var(--space-screen) calc(env(safe-area-inset-bottom, 0px) + 12px);
  background: var(--bg);
  border-top: 0.5px solid var(--border-light);
}
.cta-footer-spacer { height: 80px; }

/* ── CTA Footer fijo (flujo de reserva) ── */
.cta-footer-fixed {
  position: fixed;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100%;
  max-width: 523px;
  padding: 12px var(--space-screen) calc(env(safe-area-inset-bottom, 0px) + 12px);
  background: var(--bg);
  z-index: 100;
}
/* .card tiene backdrop-filter (var(--card-blur)), y backdrop-filter distinto de "none"
   convierte al elemento en containing block de sus descendientes position:fixed
   (los degrada a comportarse como position:absolute). En mobile ya se neutraliza
   de forma global en el override de .card en ui.css (@media max-width:600px) —
   este selector sigue siendo necesario para ancho de escritorio (>600px), donde
   .card conserva su backdrop-filter completo, para todas las pantallas que usan
   .cta-footer-fixed, sin tocar el backdrop-filter de .card en el resto de la app. */
#s2 .card, #s3a .card, #s3b .card, #s3c .card, #s4 .card, #s-pago .card, #s6 .card, #s-home .card { backdrop-filter: none; -webkit-backdrop-filter: none; }
