/* ==========================================================================
   ASBO motion layer (2026-10-10)
   Subtle, fast animations across the portal. Everything is switched off for
   people who ask their OS for reduced motion. Content is only hidden for a
   reveal when motion.js is running (html.motion-on), so nothing can get stuck
   invisible if the script fails.
   ========================================================================== */
:root {
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);
  --dur-1: .16s;
  --dur-2: .32s;
  --dur-3: .6s;
}

@keyframes m-fade-up   { from { opacity: 0; transform: translate3d(0, 14px, 0); } to { opacity: 1; transform: none; } }
@keyframes m-fade-in   { from { opacity: 0; } to { opacity: 1; } }
@keyframes m-scale-in  { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }
@keyframes m-slide-down{ from { opacity: 0; transform: translate3d(0, -8px, 0); } to { opacity: 1; transform: none; } }
@keyframes m-slide-left{ from { opacity: 0; transform: translate3d(-12px, 0, 0); } to { opacity: 1; transform: none; } }
@keyframes m-shake     { 10%, 90% { transform: translateX(-1px); } 20%, 80% { transform: translateX(2px); } 30%, 50%, 70% { transform: translateX(-4px); } 40%, 60% { transform: translateX(4px); } }
@keyframes m-pop       { 0% { transform: scale(1); } 40% { transform: scale(1.06); } 100% { transform: scale(1); } }
@keyframes m-shimmer   { from { background-position: -400px 0; } to { background-position: 400px 0; } }
@keyframes m-progress  { 0% { transform: scaleX(0); } 20% { transform: scaleX(.35); } 60% { transform: scaleX(.7); } 100% { transform: scaleX(.92); } }
@keyframes m-kenburns  { from { transform: scale(1.04); } to { transform: scale(1.12) translate3d(-1%, -1%, 0); } }
@keyframes m-float     { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }

/* ---- page entrance --------------------------------------------------------- */
html.motion-on .heading-content-box,
html.motion-on .topbar-title { animation: m-fade-up var(--dur-3) var(--ease-out) backwards; }
html.motion-on .topbar-title { animation-name: m-slide-left; }

/* reveal-on-scroll: motion.js adds .m-reveal, then .m-in when visible */
html.motion-on .m-reveal { opacity: 0; transform: translate3d(0, 16px, 0); }
html.motion-on .m-reveal.m-in {
  opacity: 1; transform: none;
  transition: opacity var(--dur-3) var(--ease-out), transform var(--dur-3) var(--ease-out);
  transition-delay: var(--m-delay, 0ms);
}

/* ---- sidebar ---------------------------------------------------------------- */
html.motion-on .side-menu > li { animation: m-slide-left .45s var(--ease-out) backwards; }
html.motion-on .side-menu > li:nth-child(1) { animation-delay: .03s; }
html.motion-on .side-menu > li:nth-child(2) { animation-delay: .06s; }
html.motion-on .side-menu > li:nth-child(3) { animation-delay: .09s; }
html.motion-on .side-menu > li:nth-child(4) { animation-delay: .12s; }
html.motion-on .side-menu > li:nth-child(5) { animation-delay: .15s; }
html.motion-on .side-menu > li:nth-child(6) { animation-delay: .18s; }
html.motion-on .side-menu > li:nth-child(7) { animation-delay: .21s; }
html.motion-on .side-menu > li:nth-child(n+8) { animation-delay: .24s; }
.side-menu > li > a { transition: background-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out); }
.side-menu > li:not(.active) > a:hover { transform: translateX(3px); }
.side-menu > li > a img, .side-menu > li > a .nav-fa { transition: transform var(--dur-2) var(--ease-spring); }
.side-menu > li > a:hover img, .side-menu > li > a:hover .nav-fa { transform: scale(1.12); }
.side-user { transition: box-shadow var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out); }
.side-user:hover { box-shadow: var(--shadow); }
.su-dot { animation: m-pulse-dot 2.4s ease-in-out infinite; }
@keyframes m-pulse-dot { 0%, 100% { box-shadow: 0 0 0 0 rgba(27, 138, 74, .45); } 50% { box-shadow: 0 0 0 4px rgba(27, 138, 74, 0); } }

/* ---- cards & list rows: lift on hover ---------------------------------------- */
.dash-card, .kpi, .pf-card, .sec-card, .setting-updatebox, .user-project > li, .pk-list li, .rc-box {
  transition: transform var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
.kpi:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
/* list rows: no transform (rows can hold fixed-position popups) */
.user-project > li:hover { box-shadow: var(--shadow); border-color: var(--asbo-blue-200) !important; }
.dash-card:hover, .pf-card:hover, .sec-card:hover, .setting-updatebox:hover { box-shadow: var(--shadow); }
.pk-list li:hover { background: var(--canvas); }
.kpi-icon, .sec-ic, .rt-ic { transition: transform var(--dur-2) var(--ease-spring); }
.kpi:hover .kpi-icon, .sec-card:hover .sec-ic, .report-btn:hover .rt-ic { transform: scale(1.08) rotate(-4deg); }

/* ---- buttons ---------------------------------------------------------------- */
.btn-box, .btn-submt-user, .upload-btn, .sec-btn-light, .choosebtn button, .report-btn, .level-choice button,
.btn-auth, .btn-passkey, .search-box button, .tu-btn, .su-logout, .icon-btn {
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-2) var(--ease-out),
              background-color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.btn-box:hover:not(:disabled):not(.disabled), .btn-submt-user:hover, .upload-btn:hover { transform: translateY(-1px); box-shadow: 0 6px 16px rgba(31, 143, 203, .22); }
.btn-box:active:not(:disabled), .btn-submt-user:active, .upload-btn:active, .sec-btn-light:active,
.report-btn:active, .level-choice button:active, .choosebtn button:active, .icon-btn:active, .su-logout:active { transform: scale(.97); }
.report-btn.active, .level-choice button.active { animation: m-pop .32s var(--ease-out); }

/* ripple (motion.js adds a span.m-ripple on press) */
.m-ripple-host { position: relative; overflow: hidden; }
.m-ripple { position: absolute; border-radius: 50%; pointer-events: none; transform: scale(0); opacity: .35;
  background: currentColor; animation: m-ripple .55s var(--ease-out) forwards; }
@keyframes m-ripple { to { transform: scale(2.6); opacity: 0; } }

/* ---- form fields ------------------------------------------------------------ */
.user-input, .form-control, .sec-input, .af-input input {
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), background-color var(--dur-2) var(--ease-out);
}
.has-error input, .has-error textarea, .has-error select,
input[aria-invalid="true"].m-shake, textarea[aria-invalid="true"].m-shake { animation: m-shake .4s var(--ease-out); }
.field-error:not(:empty), .af-error:not(:empty), .error-message:not(:empty) { animation: m-slide-down .25s var(--ease-out); }

/* ---- alerts, dropdowns, popups ---------------------------------------------- */
.alert, .sec-banner, .auth-alert, .sec-msg:not(.d-none) { animation: m-slide-down .4s var(--ease-out) backwards; }
.dropdown-menu.show { animation: m-scale-in .18s var(--ease-out); transform-origin: top right; }
.modal.show .modal-dialog, .popup.active .popup__content, .popup.show .popup__content { animation: m-scale-in .25s var(--ease-out); }
details[open] > :not(summary) { animation: m-fade-up .3s var(--ease-out); }

/* ---- photo grids: gentle image fade-in as they load (cheap, no layout work) -- */
html.motion-on img.m-img { opacity: 0; transition: opacity .4s var(--ease-out); }
html.motion-on img.m-img.m-loaded { opacity: 1; }

/* ---- skeleton shimmer helper (for loading states) ---------------------------- */
.m-skeleton { background: linear-gradient(90deg, var(--line-2) 0, #fff 120px, var(--line-2) 240px) var(--line-2);
  background-size: 800px 100%; animation: m-shimmer 1.2s linear infinite; border-radius: 8px; }

/* ---- top progress bar while a page is loading --------------------------------- */
#m-progress { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 99999; pointer-events: none;
  background: linear-gradient(90deg, var(--asbo-blue-400), var(--asbo-blue-600));
  transform-origin: left; transform: scaleX(0); opacity: 0; transition: opacity .3s ease; }
#m-progress.on { opacity: 1; animation: m-progress 6s var(--ease-out) forwards; }
#m-progress.done { opacity: 0; transform: scaleX(1); animation: none; transition: transform .2s ease, opacity .35s ease .15s; }

/* ---- QR + recovery codes ------------------------------------------------------ */
.tf-qr { animation: m-scale-in .5s var(--ease-out) backwards; }
.rc-codes li { animation: m-fade-up .4s var(--ease-out) backwards; }
.rc-codes li:nth-child(2n) { animation-delay: .04s; }
.rc-codes li:nth-child(n+3) { animation-delay: .08s; }
.rc-codes li:nth-child(n+5) { animation-delay: .12s; }
.rc-codes li:nth-child(n+7) { animation-delay: .16s; }
.rc-codes li:nth-child(n+9) { animation-delay: .2s; }

/* ---- sign-in pages ----------------------------------------------------------- */
.auth-brand { isolation: isolate; }
.auth-brand .ab-bg { position: absolute; inset: 0; z-index: -1; background: var(--hero) center / cover no-repeat;
  animation: m-kenburns 24s ease-in-out infinite alternate; }
.auth-body .ab-logo { animation: m-fade-in .8s var(--ease-out) backwards; }
.auth-body .ab-copy h1 { animation: m-fade-up .8s var(--ease-out) .1s backwards; }
.auth-body .ab-copy p { animation: m-fade-up .8s var(--ease-out) .2s backwards; }
.auth-body .ab-points li { animation: m-slide-left .6s var(--ease-out) backwards; }
.auth-body .ab-points li:nth-child(1) { animation-delay: .35s; }
.auth-body .ab-points li:nth-child(2) { animation-delay: .45s; }
.auth-body .ab-points li:nth-child(3) { animation-delay: .55s; }
.auth-body .ab-points i { transition: transform var(--dur-2) var(--ease-spring), background-color var(--dur-2); }
.auth-body .ab-points li:hover i { transform: scale(1.1); background: rgba(255, 255, 255, .2); }
.auth-body .auth-card > * { animation: m-fade-up .6s var(--ease-out) backwards; }
.auth-body .auth-card > *:nth-child(2) { animation-delay: .06s; }
.auth-body .auth-card > *:nth-child(3) { animation-delay: .12s; }
.auth-body .auth-card > *:nth-child(4) { animation-delay: .18s; }
.auth-body .auth-card > *:nth-child(n+5) { animation-delay: .24s; }
.auth-body .ac-icon { animation: m-float 4s ease-in-out infinite; }
.btn-auth:hover:not(:disabled), .btn-passkey:hover:not(:disabled) { transform: translateY(-1px); }
.btn-passkey i { transition: transform .4s var(--ease-spring); }
.btn-passkey:hover i { transform: scale(1.15); }

/* ---- reduced motion: switch it all off ---------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; transition-delay: 0s !important; scroll-behavior: auto !important; }
  html.motion-on .m-reveal { opacity: 1 !important; transform: none !important; }
  html.motion-on img.m-img { opacity: 1 !important; }
  .auth-brand .ab-bg { animation: none !important; }
}
