/* ============================================================
   animations.css — Animaciones profesionales para historialclinico
   Importar DESPUÉS de all.min.css en todas las páginas
   ============================================================ */

/* === ACCESIBILIDAD: desactiva motion para usuarios que lo requieran === */
@media (prefers-reduced-motion: reduce) {
    .main-content,
    .stat-card,
    .modal.show .modal-dialog,
    .table tbody tr.row-animating,
    .swal2-popup,
    .login-card,
    .btn-ripple,
    .ripple-effect {
        animation: none !important;
        opacity: 1 !important;
        transform: none !important;
    }
}

/* ============================================================
   KEYFRAMES
   ============================================================ */

@keyframes contentEntrance {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes cardEntrance {
    from { opacity: 0; transform: translateY(20px) scale(0.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes modalEntrance {
    from { opacity: 0; transform: scale(0.94) translateY(-10px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
}

@keyframes rowSlideIn {
    from { opacity: 0; transform: translateX(-8px); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes btnRipple {
    to { transform: scale(4); opacity: 0; }
}

@keyframes navIconPulse {
    0%   { transform: scale(1); }
    50%  { transform: scale(1.18); }
    100% { transform: scale(1); }
}

@keyframes loginCardEntrance {
    from { opacity: 0; transform: translateY(30px) scale(0.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes skeletonShimmer {
    0%   { background-position: -400px 0; }
    100% { background-position: 400px 0; }
}

@keyframes toastSlideIn {
    from { opacity: 0; transform: translateX(60px); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes swalEntrance {
    from { opacity: 0; transform: scale(0.88); }
    to   { opacity: 1; transform: scale(1); }
}

@keyframes btnSpinner {
    to { transform: translate(-50%, -50%) rotate(360deg); }
}

/* ============================================================
   ENTRADA DE PÁGINA — .main-content
   CSS-only, dispara automáticamente en cada carga de página.
   No interfiere con transition: margin-left del sidebar (son
   propiedades independientes).
   ============================================================ */
.main-content {
    animation: contentEntrance 0.45s cubic-bezier(0.4, 0, 0.2, 1) both;
}

/* ============================================================
   STAT CARDS — stagger de entrada en dashboard
   opacity: 0 en base + forwards fill-mode garantizan que las
   cards empiecen invisibles y queden visibles al terminar.
   ============================================================ */
.stat-card {
    opacity: 0;
    animation: cardEntrance 0.4s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

.stat-card:nth-child(1) { animation-delay: 0.05s; }
.stat-card:nth-child(2) { animation-delay: 0.15s; }
.stat-card:nth-child(3) { animation-delay: 0.25s; }
.stat-card:nth-child(4) { animation-delay: 0.35s; }

/* ============================================================
   MODALES — scale + fade al abrirse
   Bootstrap añade .show al abrir. Apuntamos a .modal-dialog
   (no a .modal-content) para evitar conflictos con estilos
   inline de modales específicos (sessionExpiredModal, etc.)
   Excluimos #sessionExpiredModal porque su animación interfiere
   con el focus trap cuando se apila sobre otro modal abierto.
   ============================================================ */
.modal.show:not(#sessionExpiredModal) .modal-dialog {
    animation: modalEntrance 0.28s cubic-bezier(0.34, 1.4, 0.64, 1) both;
}

/* ============================================================
   DATATABLE ROWS — stagger de entrada por filas
   La clase .row-animating la agrega JS via drawCallback.
   --row-index es una CSS custom property también inyectada por JS.
   ============================================================ */
.table tbody tr.row-animating {
    opacity: 0;
    animation: rowSlideIn 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
    animation-delay: calc(var(--row-index, 0) * 40ms);
}

/* ============================================================
   RIPPLE EN BOTONES
   overflow: hidden es necesario para recortar el ripple circular.
   Bootstrap 5 no incluye overflow: hidden en .btn por defecto.
   ============================================================ */
.btn,
.btn-custom {
    overflow: hidden;
}

/* Ripple sobre fondos de color (botones primarios, danger, etc.) */
.btn-ripple {
    position: absolute;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.35);
    transform: scale(0);
    animation: btnRipple 0.55s linear;
    pointer-events: none;
}

/* Ripple sobre nav-links (fondo claro — usa tinte azul) */
.ripple-effect {
    position: absolute;
    border-radius: 50%;
    background: rgba(0, 102, 204, 0.15);
    transform: scale(0);
    animation: btnRipple 0.5s linear;
    pointer-events: none;
}

/* ============================================================
   NAV ICON — micro-animación en hover
   ============================================================ */
.nav-link:hover .nav-icon {
    animation: navIconPulse 0.3s ease;
}

/* ============================================================
   SWEETALERT2 — override de animaciones de entrada
   Solo aplicar la animación custom a popups que NO están
   cerrándose. La clase .swal2-hide la añade Swal al cerrar y
   debe poder ejecutar su animación nativa de salida sin que
   nuestro CSS la sobrescriba con !important — de lo contrario
   el popup queda visible aunque el backdrop desaparezca.
   ============================================================ */
.swal2-popup.swal2-toast:not(.swal2-hide) {
    animation: toastSlideIn 0.3s cubic-bezier(0.34, 1.2, 0.64, 1) both !important;
}

.swal2-popup:not(.swal2-toast):not(.swal2-hide) {
    animation: swalEntrance 0.3s cubic-bezier(0.34, 1.3, 0.64, 1) both !important;
}

/* ============================================================
   LOGIN PAGE
   ============================================================ */
.login-card {
    animation: loginCardEntrance 0.5s cubic-bezier(0.34, 1.2, 0.64, 1) both;
}

/* Estado de carga del botón submit — activar con clase .loading desde JS */
.btn.loading {
    position: relative;
    color: transparent !important;
    pointer-events: none;
}

.btn.loading::after {
    content: '';
    position: absolute;
    width: 18px;
    height: 18px;
    border: 2px solid rgba(255, 255, 255, 0.4);
    border-top-color: #fff;
    border-radius: 50%;
    animation: btnSpinner 0.7s linear infinite;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

/* ============================================================
   SKELETON SCREENS — para estados de carga en modales
   Usar clases .skeleton-line y .skeleton-block en el HTML
   que se inyecte mientras los datos cargan.
   ============================================================ */
.skeleton-line,
.skeleton-block {
    background: linear-gradient(
        90deg,
        #f0f4f8 25%,
        #e2e8f0 50%,
        #f0f4f8 75%
    );
    background-size: 800px 100%;
    animation: skeletonShimmer 1.4s infinite linear;
    border-radius: 6px;
}

.skeleton-line {
    height: 14px;
    margin-bottom: 10px;
}

.skeleton-line.skeleton-title {
    height: 20px;
    width: 60%;
    margin-bottom: 16px;
}

.skeleton-line.skeleton-short {
    width: 40%;
}

.skeleton-block {
    border-radius: 10px;
    height: 80px;
    margin-bottom: 12px;
}
