/* ═══════════════════════════════════════════════════════════════════════
   modales.css — que NINGUNA ventana se salga de la pantalla

   Por qué existe este archivo: cada página traía su propio CSS del modal,
   y casi todas usaban `max-height: 86vh` / `90vh`. En un celular 100vh es
   MÁS ALTO que lo que realmente se ve (la barra del navegador y las barras
   del sistema se comen una franja), así que la ventana quedaba con la
   cabecera o el pie fuera de la pantalla: «sobresalida por arriba y por
   abajo». Además el fondo (`overlay`) no reservaba el hueco de la hora ni de
   los botones de Android ◀ ○ ▢.

   Acá se arregla UNA sola vez para todas las familias de modales:
     · el fondo se centra y reserva las barras del sistema (safe-area);
     · la caja nunca mide más que el alto REAL de la pantalla (--vh-real,
       que _head.ejs mide con visualViewport; dvh/100vh son el respaldo);
     · la cabecera y el pie quedan a la vista y solo se desliza el contenido.

   Los selectores llevan `body` delante a propósito: así le ganan a los
   estilos que cada página escribe en su propio <style> (que va DESPUÉS de
   _head.ejs) sin tener que tocar 15 plantillas ni usar !important.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 0) Cuánto aire se deja arriba y abajo ─────────────────────────────
   `--aire-modal` se declara en <html> para que la Caja lo herede sin
   importar cuán hondo esté dentro del fondo, y así el alto máximo y el
   relleno del fondo siempre usan el MISMO número (aire simétrico exacto). */
html { --aire-modal: 16px; }
@media (min-width: 700px) { html { --aire-modal: 20px; } }

/* ── 1) El fondo del modal ─────────────────────────────────────────────
   Centrado y con aire: 16px arriba/abajo/lados + el hueco real del
   teléfono (hora, notch, botones ◀ ○ ▢ o barra de gestos). */
body .modal-overlay,
body .recarga-modal-overlay,
body .checkout-result-overlay,
body .confirm-overlay {
  align-items: center;
  justify-content: center;
  /* ── FONDO OPACO ──────────────────────────────────────────────────────
     Antes era semitransparente (la página se veía apenas detrás). El problema
     no era «verla»: en el celular, con el teclado abierto, esa parte de atrás
     se puede deslizar y por entre las teclas se veía MOVERSE. Con el fondo
     opaco no se ve absolutamente nada detrás de la ventana, así que no hay
     nada que pueda «moverse» a la vista. Es el mismo criterio del reproductor
     de videos, que ya quedó bien con fondo negro.
     (Puesto acá, con `body` adelante, le gana al fondo semitransparente que
     cada página declara en su propio <style>.) */
  background: #0a0a0e;
  padding: var(--aire-modal, 16px);
  padding: calc(var(--aire-modal, 16px) + var(--sat, env(safe-area-inset-top, 0px)))
           calc(var(--aire-modal, 16px) + env(safe-area-inset-right, 0px))
           calc(var(--aire-modal, 16px) + env(safe-area-inset-bottom, 0px))
           calc(var(--aire-modal, 16px) + env(safe-area-inset-left, 0px));
  /* Si algo no cupiera igual, el fondo se puede desplazar: nunca queda
     contenido inalcanzable fuera de la pantalla. */
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* ── 2) La caja: nunca más alta que la pantalla visible ────────────────
   `--vh-real` lo publica _head.ejs con el alto REAL medido (visualViewport),
   que es menor que 100vh cuando la barra del navegador se come una franja;
   se le restan los insets del sistema y el aire del fondo (2 × aire).
   Se listan también las familias con nombre propio (.modal-producto,
   .rmodal-box, .wr-modal…): la página del producto trae su propia regla
   `.modal.modal-producto` (dos clases) y sin nombrarla acá le ganaba. */
body .modal,
body .modal.modal-producto,
body .recarga-modal,
body .wr-modal,
body .checkout-result-modal,
body .confirm-box,
body .rmodal-box {
  max-height: calc(100vh - var(--aire-modal, 16px) * 2);
  max-height: calc(100dvh - var(--aire-modal, 16px) * 2);
  max-height: calc(var(--vh-real, 100vh) - var(--aire-modal, 16px) * 2);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  /* `margin:auto` en vez de confiar solo en el centrado del flex: si una
     ventana llegara a ser más alta que la pantalla, arriba y abajo quedan
     alcanzables al deslizar (con align-items:center el borde de arriba se
     pierde: es el clásico recorte del flexbox). */
  margin: auto;
}
/* Los insets del sistema, solo donde el navegador los entiende. Va aparte
   para no invalidar el max-height de arriba en navegadores que no los
   soportan (una declaración inválida borraría las anteriores). */
@supports (padding: var(--sat, var(--sat, env(safe-area-inset-top, 0px)))) {
  body .modal,
  body .modal.modal-producto,
  body .recarga-modal,
  body .wr-modal,
  body .checkout-result-modal,
  body .confirm-box,
  body .rmodal-box {
    max-height: calc(var(--vh-real, 100vh) - var(--aire-modal, 16px) * 2
                     - var(--sat, env(safe-area-inset-top, 0px)) - env(safe-area-inset-bottom, 0px));
  }
}

/* ── 3) Cabecera y pie siempre a la vista ──────────────────────────────
   Se quedan pegados arriba y abajo de la ventana mientras el contenido del
   medio se desliza. Ojo: los modales que ya usan flex + cuerpo deslizable
   (el de producto, el de recarga de wallet, la aceptación de términos)
   tienen selectores más específicos y conservan su propio esquema. */
body .modal > .modal-header,
body .modal > form > .modal-header {
  position: sticky;
  top: 0;
  z-index: 3;
  flex-shrink: 0;
  background: var(--card);
}
body .modal > .modal-footer,
body .modal > form > .modal-footer {
  position: sticky;
  bottom: 0;
  z-index: 3;
  flex-shrink: 0;
  background: var(--card);
}

/* ── 4) El cuerpo es el que se desplaza ─────────────────────────────── */
body .modal > .modal-body,
body .modal > form > .modal-body {
  min-height: 0;
}

/* ── 5) En pantallas anchas el aire sube a 20px ───────────────────────
   Lo hace la media query de `--aire-modal` (arriba): así el relleno del
   fondo y el alto máximo de la caja suben juntos, sin descuadrarse. */

/* ── 5) LA VENTANA SE PEGA A LO QUE SE VE, Y ATRÁS SE PINTA TODO ────────
   Las dos cosas que hay que resolver a la vez cuando aparece el teclado en el
   celular (Android deja DESPLAZAR la parte visible de la página, el «visual
   viewport»; el alto real es menor que la ventana):

     a) La ventana NO puede moverse: tiene que quedar pegada a la franja que de
        verdad se ve. Si se ancla a la ventana completa, cuando uno arrastra el
        dedo se va con el fondo (y el cursor de escritura se sale de su lugar).
        Por eso el fondo mide la ALTURA REAL (`--vh-real`) y arranca donde
        empieza lo visible (`--vv-top`), que son los datos que publica _head.ejs
        midiendo con visualViewport.

     b) La franja que tapa el teclado (que el navegador sigue pintando, y que se
        ve por entre las teclas porque son semitransparentes) NO puede dejar ver
        la página: se pinta con una SOMBRA enorme alrededor del fondo del modal.
        Al ser un color PLANO, aunque se desplace no se nota ningún movimiento
        —era exactamente lo que pasaba cuando esa franja mostraba el contenido
        del panel moviéndose. */
body .modal-overlay,
body .recarga-modal-overlay,
body .checkout-result-overlay,
body .confirm-overlay {
  box-sizing: border-box;
  top: var(--vv-top, 0px);
  bottom: auto;
  height: var(--vh-real, 100dvh);
  /* El mismo color plano alrededor: así la franja que tapa el teclado queda
     idéntica al resto del fondo (antes se notaba una diferencia de tono). */
  box-shadow: 0 0 0 100vmax #0a0a0e;
}

/* ── 6) LO DE ATRÁS NO SE MUEVE MIENTRAS HAY UNA VENTANA ABIERTA ──────
   Este era el «se desliza el fondo»: al deslizar el dedo dentro del
   formulario, si la ventana ya llegó al final del scroll, el sobrante se le
   pasaba a la PÁGINA de atrás (scroll chaining) y se veía moverse todo: los
   textos de atrás, la barra de arriba y los botones flotantes.
   Dos frenos, sin JavaScript:
     · `overscroll-behavior: contain` → el scroll no se contagia al padre;
     · mientras una ventana está abierta, la página de atrás no scrollea
       (`:has`, que entienden los navegadores actuales; donde no, la regla
       simplemente no aplica y todo sigue funcionando igual que antes).
   El scroll vive DENTRO de la ventana (la caja ya tiene overflow-y:auto). */
body .modal-overlay,
body .recarga-modal-overlay,
body .checkout-result-overlay,
body .confirm-overlay,
body .modal,
body .modal.modal-producto,
body .recarga-modal,
body .wr-modal,
body .checkout-result-modal,
body .confirm-box,
body .rmodal-box {
  overscroll-behavior: contain;
}
html:has(.modal-overlay.show),
html:has(.recarga-modal-overlay.show),
html:has(.checkout-result-overlay.open),
html:has(.confirm-overlay.show),
html:has(.modal.show) {
  overflow: hidden;
}
html:has(.modal-overlay.show) body,
html:has(.recarga-modal-overlay.show) body,
html:has(.checkout-result-overlay.open) body,
html:has(.confirm-overlay.show) body,
html:has(.modal.show) body {
  overflow: hidden;
}

/* ── 7) CON EL TECLADO ABIERTO LA VENTANA SE ANCLA ARRIBA ──────────────
   Al salir el teclado, la pantalla visible se achica y el nodo se vuelve a
   medir varias veces mientras el teclado termina de subir. Con la caja
   centrada, cada una de esas medidas la volvía a centrar en un alto distinto:
   la ventana daba un saltito hacia arriba (el «se mueve cuando abro el
   teclado»). Anclada arriba, el borde de arriba NO se mueve: lo único que
   cambia es el alto disponible, y la caja se hace más baja. Los campos siguen
   a la vista porque _head.ejs desliza el contenido DENTRO de la ventana
   (la caja tiene su propio scroll). Al cerrar el teclado vuelve a centrarse. */
html.kb-con-ventana body .modal-overlay,
html.kb-con-ventana body .recarga-modal-overlay,
html.kb-con-ventana body .checkout-result-overlay,
html.kb-con-ventana body .confirm-overlay {
  align-items: flex-start;
}
/* Y la caja tiene que soltar su `margin: auto` (el de la regla 2): con márgenes
   automáticos verticales, la caja se centra sola y «align-items» no alcanza.
   Con los márgenes en cero, arriba queda pegada y no se mueve más. */
html.kb-con-ventana body .modal-overlay > *,
html.kb-con-ventana body .recarga-modal-overlay > *,
html.kb-con-ventana body .checkout-result-overlay > *,
html.kb-con-ventana body .confirm-overlay > * {
  margin-top: 0;
  margin-bottom: 0;
}
/* Todos los cierres redondos/cuadrados usan el mismo centro geométrico. Un
   SVG inline se apoya sobre la línea base y, sin flex, la ✕ bajaba unos px. */
body .modal-close,
body .v-x,
body .qr-close,
body .qr-scan-close,
body .lap-x,
body .rmodal-x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  line-height: 1;
}
body button.modal-close > svg.ico:first-child,
body button.v-x > svg.ico:first-child,
body button.qr-close > svg.ico:first-child,
body button.qr-scan-close > svg.ico:first-child,
body button.lap-x > svg.ico:first-child,
body button.rmodal-x > svg.ico:first-child {
  display: block;
  margin: 0 !important;
}

/* ── 9) LA ✕ DE CERRAR, UN POCO MÁS CÓMODA EN EL CELULAR ──────────────
   Con el mouse se apunta fino y 16 px alcanzan; con el dedo, no. Solo en
   pantallas de celular (o táctiles) se agranda un poco el icono y su zona de
   toque. No cambia nada en la computadora ni en el resto del diseño: la ✕
   sigue siendo discreta, nada más que se puede tocar sin pelearla. */
@media (max-width: 700px), (pointer: coarse) {
  body .modal-overlay .x,
  body .modal .x,
  body .modal-overlay .modal-close,
  body .modal .modal-close,
  body .v-overlay .v-x,
  body .confirm-overlay .x,
  body .checkout-result-overlay .x,
  body .recarga-modal-overlay .x {
    font-size: 20px;
    line-height: 1;
    min-width: 32px;
    min-height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}
/* ── 10) QUE LA VENTANA ENTRE CON SUAVIDAD (como «Mi Equipo») ─────────
   Hasta acá las ventanas aparecían de golpe. La pantalla de Mi Equipo traía
   una animación cortita (0.25 s: aparece, crece un poco y se acomoda) y por eso
   se siente más fluida. Se copia para TODAS las ventanas de la app.
   · Si el teléfono tiene «reducir animaciones» puesto, no se anima nada. */
@keyframes ventanaEntra {
  from { opacity: 0; transform: scale(0.96) translateY(10px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
body .modal,
body .modal.modal-producto,
body .recarga-modal,
body .wr-modal,
body .checkout-result-modal,
body .confirm-box,
body .rmodal-box {
  animation: ventanaEntra 0.22s ease-out;
}
@media (prefers-reduced-motion: reduce) {
  body .modal,
  body .modal.modal-producto,
  body .recarga-modal,
  body .wr-modal,
  body .checkout-result-modal,
  body .confirm-box,
  body .rmodal-box { animation: none; }
}

/* ── 11) EL CAMPO ENFOCADO SE MARCA MEJOR ─────────────────────────────
   Mi Equipo resalta el campo activo con el borde violeta MÁS un halo suave
   (2 px). Acá se hace lo mismo en todas las ventanas: se ve enseguida cuál
   estás llenando, sobre todo en el celular donde el campo es chico. */
body .modal-overlay input:focus,
body .modal-overlay select:focus,
body .modal-overlay textarea:focus,
body .modal input:focus,
body .modal select:focus,
body .modal textarea:focus,
body .recarga-modal-overlay input:focus,
body .recarga-modal-overlay select:focus,
body .checkout-result-overlay input:focus,
body .confirm-overlay input:focus {
  border-color: var(--purple);
  box-shadow: 0 0 0 2px var(--purple-20);
  outline: none;
}
