/* ══════════════════════════════════════════════════════════
   native.css — capa de "sensación de app nativa" (Android/Chrome)
   Se carga al final: solo agrega movimiento y comportamiento táctil,
   no redefine el diseño de ningún módulo. Todo respeta
   prefers-reduced-motion (ver bloque final).
═══════════════════════════════════════════════════════════ */

/* ── 1. Transición direccional entre vistas ──────────────────
   navigateTo() (app.js) marca <html data-vt="forward|back|fade"> según
   la profundidad de la vista origen y destino:
     forward → la vista nueva entra desde la derecha (push)
     back    → la vista actual sale hacia la derecha (pop)
     fade    → mismo nivel (ej. entre módulos): fundido corto
   Topbar y navbar inferior tienen su propio nombre de transición para
   quedarse quietos mientras el contenido se desliza. */
.topbar     { view-transition-name: topbar; }
.bottom-nav { view-transition-name: bottom-nav; }

::view-transition-group(topbar),
::view-transition-group(bottom-nav) {
  animation: none;
}

html[data-vt] ::view-transition-old(root),
html[data-vt] ::view-transition-new(root) {
  mix-blend-mode: normal;
}

html[data-vt="forward"]::view-transition-old(root) {
  animation: vtShiftOutLeft .34s cubic-bezier(.32,.72,0,1) both;
}
html[data-vt="forward"]::view-transition-new(root) {
  animation: vtSlideInRight .34s cubic-bezier(.32,.72,0,1) both;
  box-shadow: -10px 0 28px rgba(0,0,0,.14);
  z-index: 2;
}

html[data-vt="back"]::view-transition-old(root) {
  animation: vtSlideOutRight .3s cubic-bezier(.32,.72,0,1) both;
  box-shadow: -10px 0 28px rgba(0,0,0,.14);
  z-index: 2;
}
html[data-vt="back"]::view-transition-new(root) {
  animation: vtShiftInLeft .3s cubic-bezier(.32,.72,0,1) both;
}

html[data-vt="fade"]::view-transition-old(root) {
  animation: vtFadeOut .16s ease both;
}
html[data-vt="fade"]::view-transition-new(root) {
  animation: vtFadeIn .2s ease both;
}

@keyframes vtSlideInRight  { from { transform: translateX(100%); } to { transform: translateX(0); } }
@keyframes vtSlideOutRight { from { transform: translateX(0); }    to { transform: translateX(100%); } }
@keyframes vtShiftOutLeft  { from { transform: translateX(0); opacity: 1; }       to { transform: translateX(-22%); opacity: .55; } }
@keyframes vtShiftInLeft   { from { transform: translateX(-22%); opacity: .55; }   to { transform: translateX(0); opacity: 1; } }
@keyframes vtFadeOut { from { opacity: 1; } to { opacity: 0; } }
@keyframes vtFadeIn  { from { opacity: 0; } to { opacity: 1; } }

/* ── 2. Feedback táctil global ───────────────────────────────
   Se usa la propiedad individual "scale" (no "transform") para no pisar
   transforms que cada componente ya define, y :where() para que tenga
   especificidad 0: cualquier :active propio de un componente gana. */
html {
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior-y: none; /* sin rebote/glow ni pull-to-refresh del navegador */
}
/* Solo en html: en body (que es contenedor de scroll por el overflow de
   html) cortaba el encadenamiento de la rueda del mouse en escritorio. */

:where(button, a[href], summary, label[for], [role="button"], [onclick], .bn-item):not(:disabled) {
  touch-action: manipulation; /* sin retardo de toque ni zoom por doble toque */
}

:where(button, a[href], summary, [role="button"], [onclick]):not(:disabled, input, select, textarea, [class*="overlay"]):active {
  scale: .97;
  opacity: .88;
}

/* Superficies grandes: hundimiento más sutil */
:where(.viaje-card, .passenger-row, .user-card-header, .dash-viaje-card, .dash-comp-card):active {
  scale: .985;
  opacity: .92;
}

:where(button, a[href], summary, [role="button"], [onclick]) {
  transition: scale .14s cubic-bezier(.2,.8,.2,1), opacity .14s ease;
}

/* La UI de la app no se selecciona al mantener presionado (los datos y
   campos de texto sí: no se toca ni body ni los contenedores de contenido). */
:where(button, summary, .topbar, .bottom-nav, .breadcrumb-bar, .bn-item,
       .modulo-item, .fab, .fab-sos, .viaje-card-overlay, .usuarios-tab,
       .informes-tab-btn, .informes-range-chip) {
  -webkit-user-select: none;
  user-select: none;
}
:where(input, textarea, select, [contenteditable="true"]) {
  -webkit-user-select: text;
  user-select: text;
}

/* ── 3. <dialog>: entrada y salida animadas ──────────────────
   "overlay" + "display" con allow-discrete permiten animar también el
   cierre (Chrome/Edge 117+). Se usan propiedades individuales
   (opacity/translate/scale) para no chocar con transforms de los modales. */
dialog {
  opacity: 0;
  translate: 0 16px;
  scale: .97;
  transition:
    opacity .2s ease,
    translate .26s cubic-bezier(.32,.72,0,1),
    scale .26s cubic-bezier(.32,.72,0,1),
    overlay .26s allow-discrete,
    display .26s allow-discrete;
}
dialog[open] {
  opacity: 1;
  translate: 0 0;
  scale: 1;
}
@starting-style {
  dialog[open] {
    opacity: 0;
    translate: 0 16px;
    scale: .97;
  }
}

dialog::backdrop {
  opacity: 0;
  transition:
    opacity .24s ease,
    overlay .24s allow-discrete,
    display .24s allow-discrete;
}
dialog[open]::backdrop { opacity: 1; }
@starting-style {
  dialog[open]::backdrop { opacity: 0; }
}

/* Reemplazan a las animaciones de entrada que ya traían algunos modales
   (si no, la entrada se animaría dos veces). */
.legal-fecha-modal[open],
.modal-sos[open] .modal-sos-card { animation: none; }
.modal-sos::backdrop { animation: none; }

/* Sheet de módulos: mientras se arrastra con el dedo no debe haber
   transición (la maneja modulos-menu.js con estilos en línea). */
.modulos-sheet.arrastrando { transition: none; }

/* ── 4. Entrada escalonada de listas ─────────────────────────
   Solo opacity + translate (propiedad individual) y fill "backwards":
   al terminar no queda ningún valor retenido que pise hover/active. */
@keyframes listItemIn {
  from { opacity: 0; translate: 0 10px; }
}

:is(#passenger-list, #viajes-list, #historico-list, #users-list,
    #users-reservas-list, #recibos-cont, #mov-list, #facturas-lista,
    #marangatu-lista, #activity-log-list) > * {
  animation: listItemIn .32s cubic-bezier(.2,.8,.2,1) backwards;
  animation-delay: 280ms; /* del 9.º en adelante: aparecen juntos */
}
:is(#passenger-list, #viajes-list, #historico-list, #users-list,
    #users-reservas-list, #recibos-cont, #mov-list, #facturas-lista,
    #marangatu-lista, #activity-log-list) > :nth-child(1) { animation-delay: 0ms; }
:is(#passenger-list, #viajes-list, #historico-list, #users-list,
    #users-reservas-list, #recibos-cont, #mov-list, #facturas-lista,
    #marangatu-lista, #activity-log-list) > :nth-child(2) { animation-delay: 35ms; }
:is(#passenger-list, #viajes-list, #historico-list, #users-list,
    #users-reservas-list, #recibos-cont, #mov-list, #facturas-lista,
    #marangatu-lista, #activity-log-list) > :nth-child(3) { animation-delay: 70ms; }
:is(#passenger-list, #viajes-list, #historico-list, #users-list,
    #users-reservas-list, #recibos-cont, #mov-list, #facturas-lista,
    #marangatu-lista, #activity-log-list) > :nth-child(4) { animation-delay: 105ms; }
:is(#passenger-list, #viajes-list, #historico-list, #users-list,
    #users-reservas-list, #recibos-cont, #mov-list, #facturas-lista,
    #marangatu-lista, #activity-log-list) > :nth-child(5) { animation-delay: 140ms; }
:is(#passenger-list, #viajes-list, #historico-list, #users-list,
    #users-reservas-list, #recibos-cont, #mov-list, #facturas-lista,
    #marangatu-lista, #activity-log-list) > :nth-child(6) { animation-delay: 175ms; }
:is(#passenger-list, #viajes-list, #historico-list, #users-list,
    #users-reservas-list, #recibos-cont, #mov-list, #facturas-lista,
    #marangatu-lista, #activity-log-list) > :nth-child(7) { animation-delay: 210ms; }
:is(#passenger-list, #viajes-list, #historico-list, #users-list,
    #users-reservas-list, #recibos-cont, #mov-list, #facturas-lista,
    #marangatu-lista, #activity-log-list) > :nth-child(8) { animation-delay: 245ms; }

/* Las tarjetas de viaje ya traen su propio animation (skeleton/updating) */
#viajes-list > .viaje-card-skel { animation: none; }

/* ── Reduced motion: sin movimiento, solo cambios de estado ── */
@media (prefers-reduced-motion: reduce) {
  html[data-vt]::view-transition-old(root),
  html[data-vt]::view-transition-new(root) {
    animation: none !important;
  }
  :where(button, a[href], summary, [role="button"], [onclick]):active,
  :where(.viaje-card, .passenger-row, .user-card-header,
         .dash-viaje-card, .dash-comp-card):active {
    scale: 1;
  }
  dialog, dialog::backdrop {
    transition: none;
    translate: 0 0;
    scale: 1;
  }
  :is(#passenger-list, #viajes-list, #historico-list, #users-list,
      #users-reservas-list, #recibos-cont, #mov-list, #facturas-lista,
      #marangatu-lista, #activity-log-list) > * {
    animation: none;
  }
}

/* ══════════════════════════════════════════════════════════
   Segunda tanda
═══════════════════════════════════════════════════════════ */

/* ── 8a. Indicador deslizante en tabs ────────────────────────
   js/native-ux.js inserta <span.tab-indicator> y lo mueve hasta la tab
   activa. El estilo "activo" propio de cada tab se apaga para que solo se
   vea el indicador. */
.tab-slider-host { position: relative; }

.tab-indicator {
  position: absolute;
  left: 0;
  pointer-events: none;
  opacity: 0;
  transition: translate .3s cubic-bezier(.32,.72,0,1), width .3s cubic-bezier(.32,.72,0,1);
}
.tab-indicator.listo { opacity: 1; }

/* Variante subrayado (Informes, Facturas) */
.informes-tabs.tab-slider-host .tab-indicator {
  bottom: -1px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px 2px 0 0;
}
.informes-tabs.tab-slider-host .informes-tab-btn.active { border-bottom-color: transparent; }
.informes-tabs.tab-slider-host .informes-tab-btn { transition: color .2s ease; }

/* Variante píldora (Usuarios) */
.usuarios-tabs.tab-slider-host .tab-indicator {
  top: .3rem;
  bottom: .3rem;
  background: var(--row-bg);
  border-radius: 9px;
  box-shadow: 0 2px 8px var(--shadow-soft);
}
.usuarios-tabs.tab-slider-host .usuarios-tab { position: relative; z-index: 1; }
.usuarios-tabs.tab-slider-host .usuarios-tab.active { background: transparent; box-shadow: none; }

/* ── 8b. Botón guardar: spinner mientras guarda ─────────────── */
.btn-save.btn-cargando { position: relative; pointer-events: none; }
.btn-save.btn-cargando::before {
  content: "";
  width: 14px; height: 14px;
  flex-shrink: 0;
  border: 2px solid rgba(255,255,255,.45);
  border-top-color: #fff;
  border-radius: 50%;
  animation: btnSpin .7s linear infinite;
}
@keyframes btnSpin { to { rotate: 360deg; } }

/* ── 6. Pull-to-refresh ──────────────────────────────────────
   Indicador circular que baja desde debajo del topbar. */
.ptr {
  position: fixed;
  top: 76px;
  left: 50%;
  margin-left: -19px;
  width: 38px; height: 38px;
  z-index: 90;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--surface, var(--bg));
  color: var(--accent);
  box-shadow: var(--shadow-md);
  pointer-events: none;
  opacity: 0;
  translate: 0 -44px;
  transition: translate .28s cubic-bezier(.32,.72,0,1), opacity .2s ease;
}
.ptr.arrastrando { transition: none; }
.ptr svg { rotate: var(--ptr-rot, 0deg); }
.ptr.cargando svg { animation: btnSpin .8s linear infinite; }

/* ── Skeleton de filas (reemplaza "Cargando…" en texto) ─────── */
.skel-lista { display: flex; flex-direction: column; gap: .6rem; }
.skel-fila {
  display: flex; align-items: center; gap: .8rem;
  padding: .85rem 1.1rem;
  background: var(--row-bg, var(--surface));
  border: 1px solid var(--border);
  border-radius: 14px;
}
.skel-circulo { width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0; }
.skel-lineas { flex: 1; display: flex; flex-direction: column; gap: .5rem; }
.skel-linea { height: 11px; border-radius: 6px; }

/* ── Toasts: entrada y salida ───────────────────────────────── */
.app-toast {
  position: fixed;
  left: 50%;
  bottom: calc(6rem + env(safe-area-inset-bottom, 0px));
  translate: -50% 0;
  z-index: 400;
  color: #fff;
  padding: .65rem 1.1rem;
  border-radius: 10px;
  font-size: .85rem;
  box-shadow: var(--shadow-md);
  max-width: calc(100vw - 2rem);
  text-align: center;
  background: var(--accent);
  animation: toastIn .3s cubic-bezier(.32,.72,0,1) both;
}
.app-toast {
  display: flex;
  align-items: center;
  gap: .6rem;
  text-align: left;
  line-height: 1.3;
}
.app-toast-ico { display: flex; flex-shrink: 0; }
.app-toast.success { background: var(--accent); }
.app-toast.error   { background: var(--danger); }
.app-toast.warning { background: #b7791f; }
.app-toast.info    { background: #3b5bdb; }

/* Confirmación propia (confirmar() en native-ux.js) */
.confirm-modal { width: min(380px, calc(100vw - 2.4rem)); }
.legal-fecha-modal-confirmar.confirm-peligro { background: var(--danger); }
.legal-fecha-modal-confirmar.confirm-peligro:hover { background: var(--danger); filter: brightness(.92); }
.app-toast.saliendo { animation: toastOut .22s ease-in both; }
@keyframes toastIn  { from { opacity: 0; translate: -50% 16px; scale: .96; } }
@keyframes toastOut { to   { opacity: 0; translate: -50% 10px; scale: .97; } }

@media (prefers-reduced-motion: reduce) {
  .tab-indicator, .ptr { transition: none; }
  .btn-save.btn-cargando::before, .ptr.cargando svg { animation-duration: 1.6s; }
  .app-toast, .app-toast.saliendo { animation: none; }
}
