/* ===========================================================
   Window motion — application-wide

   Every surface that appears, disappears or is navigated to
   uses the same open/close pair, so the app behaves like one
   set of windows rather than a series of hard cuts.

   Loaded on every page, after the page's own stylesheets.
   Rules that override styles injected at runtime (AppNotice
   builds its own <style> tag, which lands after our <link>s)
   are qualified with body/html so they win on specificity
   rather than on order.
   =========================================================== */

@keyframes rdWinOpen {
    from { opacity: 0; transform: scale(.955) translateY(10px); }
    to   { opacity: 1; transform: scale(1) translateY(0); }
}

@keyframes rdWinClose {
    from { opacity: 1; transform: scale(1) translateY(0); }
    to   { opacity: 0; transform: scale(.97) translateY(-6px); }
}

@keyframes rdFadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes rdToastIn {
    from { opacity: 0; transform: translateY(14px) scale(.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes rdPanelIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: none; }
}

/* Easing shared by everything, so nothing feels like a different app. */
:root {
    --rd-ease-out: cubic-bezier(.16, 1, .3, 1);
    --rd-ease-in: cubic-bezier(.4, 0, 1, 1);
}

/* --- modal backdrops ---------------------------------------------------
   Every overlay in the app is listed. The page-specific ones (.cp-overlay
   on the dashboard, .confirm-overlay on payslips) define their own
   show class locally, so they have to be named rather than inherited. */
.modal-overlay.show,
.modal-overlay.active,
.ps-modal-overlay.show,
.cp-overlay.show,
.confirm-overlay.show,
body .rd-notice-overlay {
    animation: rdFadeIn .2s ease-out both;
}

/* The audit log drawer is deliberately absent from these rules. It already
   slides itself with
       #auditPanelDrawer      { transform: translateX(100%); transition: transform .28s }
       #auditPanelDrawer.open { transform: translateX(0) }
   and an `animation: ... both` on top of that pins the final keyframe
   permanently, which overrode the transition and left the drawer stuck open
   -- it could be opened but never closed. Its own transition is the motion. */

/* --- modal windows ----------------------------------------------------- */
.modal-overlay.show > .modal,
.modal-overlay.show > .modal-content,
.modal-overlay.active > .modal,
.modal-overlay.active > .modal-content,
.ps-modal-overlay.show > .ps-modal,
.cp-overlay.show > *,
.confirm-overlay.show > *,
body .rd-notice-overlay .rd-notice-window {
    transform-origin: center;
    animation: rdWinOpen .28s var(--rd-ease-out) both;
}



/* --- toasts ------------------------------------------------------------ */
.toast.show { animation: rdToastIn .26s var(--rd-ease-out) both; }

/* --- notification popup (display is toggled inline) -------------------- */
#notif-popup {
    transform-origin: top right;
    animation: rdWinOpen .22s var(--rd-ease-out) both;
}

/* --- settings tab panels ----------------------------------------------- */
.set-panel.active { animation: rdPanelIn .24s var(--rd-ease-out) both; }

/* --- payslip accordions ------------------------------------------------ */
.ps-year.open > .ps-year-body,
.ps-month.open > .ps-month-body { animation: rdPanelIn .2s var(--rd-ease-out) both; }

/* --- page shell -------------------------------------------------------- */
/* The signed-in shell opens on load and closes before navigating away. The
   sidebar is deliberately excluded: it is the frame, and animating it on
   every page change reads as flicker rather than motion. */
.main-content { animation: rdWinOpen .3s var(--rd-ease-out) both; }

body.is-leaving .main-content { animation: rdWinClose .18s var(--rd-ease-in) both; }

/* --- buttons ----------------------------------------------------------- */
/* Press feedback everywhere, including buttons drawn at runtime. */
button,
.btn,
.text-action-btn,
.nav-item,
.set-tab,
.tab {
    transition: transform .14s var(--rd-ease-out), filter .14s ease, background-color .14s ease;
}

button:active:not(:disabled),
.btn:active:not(:disabled),
.text-action-btn:active:not(:disabled),
.set-tab:active,
.tab:active { transform: scale(.975); }

.nav-item:active { transform: scale(.99); }

button:disabled, .btn:disabled { transform: none !important; }

/* Anything a person can drag or scroll inside must not be scaled by a
   press, or the content shifts under the pointer mid-gesture. */
.ps-row:active,
input:active,
select:active,
textarea:active { transform: none; }


/* ===========================================================
   Closing
   -----------------------------------------------------------
   The app closes a dialog by removing its show/active class,
   which sets display:none in the same frame -- there is no
   gap for an animation to play in. motion.js spots that
   removal, puts .rd-closing on the element to hold it visible,
   and takes it off when the animation ends.
   =========================================================== */

.modal-overlay.rd-closing,
.ps-modal-overlay.rd-closing,
.cp-overlay.rd-closing,
.confirm-overlay.rd-closing {
    display: flex !important;
    animation: rdFadeOut .18s var(--rd-ease-in) both;
    pointer-events: none;
}

.modal-overlay.rd-closing > .modal,
.modal-overlay.rd-closing > .modal-content,
.ps-modal-overlay.rd-closing > .ps-modal,
.cp-overlay.rd-closing > *,
.confirm-overlay.rd-closing > * {
    animation: rdWinClose .18s var(--rd-ease-in) both;
}

.rd-notice-overlay.rd-closing { animation: rdFadeOut .18s var(--rd-ease-in) both; pointer-events: none; }
.rd-notice-overlay.rd-closing .rd-notice-window { animation: rdWinClose .18s var(--rd-ease-in) both; }

.toast.rd-closing { display: block !important; animation: rdToastOut .2s var(--rd-ease-in) both; }

@keyframes rdFadeOut {
    from { opacity: 1; }
    to   { opacity: 0; }
}

@keyframes rdToastOut {
    from { opacity: 1; transform: translateY(0) scale(1); }
    to   { opacity: 0; transform: translateY(10px) scale(.97); }
}

/* ===========================================================
   In-page views
   -----------------------------------------------------------
   Half this app never changes URL: "Process Payroll", "Back to
   Payroll", "Back to Dates" and the report drill-downs just
   swap one container for another. Those are navigations to the
   person using it, so they animate like one.

   Display flips from none to visible, which restarts a CSS
   animation on its own -- no script needed here.
   =========================================================== */

#payrollMainView,
#submittedAttendancesView,
#submittedListView,
#submittedDetailView,
#ftSubmittedView,
#ftSubmittedListView,
#ftSubmittedDetailView,
#globalDeductionsView,
#ftDeductionsView,
#directoryView,
#empDetail,
#eventsListView,
#eventDetailView,
#prListView,
#prDetailView,
#ftListView,
#ftDetailView,
#arListView,
#arDetailView,
#summaryDeductionDetail,
.rpt-detail-view.active {
    animation: rdViewIn .26s var(--rd-ease-out) both;
}

@keyframes rdViewIn {
    from { opacity: 0; transform: translateY(8px) scale(.99); }
    to   { opacity: 1; transform: none; }
}

/* ===========================================================
   Accordion rows
   -----------------------------------------------------------
   Year and month bars reveal table rows. A transform on a
   <tr> is unreliable across engines, so these fade instead of
   sliding -- enough to read as motion without risking a
   mis-laid-out table.
   =========================================================== */

tr.rd-revealed { animation: rdRowIn .22s ease-out both; }

@keyframes rdRowIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* --- respect the system preference ------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .modal-overlay.show,
    .modal-overlay.active,
    .ps-modal-overlay.show,
    .cp-overlay.show,
    .confirm-overlay.show,
    .cp-overlay.show > *,
    .confirm-overlay.show > *,
    body .rd-notice-overlay,
    .modal-overlay.show > .modal,
    .modal-overlay.show > .modal-content,
    .modal-overlay.active > .modal,
    .modal-overlay.active > .modal-content,
    .ps-modal-overlay.show > .ps-modal,
    body .rd-notice-overlay .rd-notice-window,
    .toast.show,
    #notif-popup,
    .set-panel.active,
    .ps-year.open > .ps-year-body,
    .ps-month.open > .ps-month-body,
    .main-content,
    body.is-leaving .main-content,
    .rd-closing,
    .rd-closing > *,
    tr.rd-revealed,
    #payrollMainView, #submittedAttendancesView, #submittedListView,
    #submittedDetailView, #ftSubmittedView, #ftSubmittedListView,
    #ftSubmittedDetailView, #globalDeductionsView, #ftDeductionsView,
    #directoryView, #empDetail, #eventsListView, #eventDetailView,
    #prListView, #prDetailView, #ftListView, #ftDetailView,
    #arListView, #arDetailView, #summaryDeductionDetail,
    .rpt-detail-view.active {
        animation: none !important;
    }

    button, .btn, .text-action-btn, .nav-item, .set-tab, .tab { transition: none; }
    button:active, .btn:active, .text-action-btn:active { transform: none; }
}
