/* ===========================================================================
   Motion — page transitions, scroll reveals, modal in/out, loading bar.

   Everything here is gated on .js-motion, which motion.js adds to <html>
   immediately. If scripts fail or are blocked, no rule applies and all
   content stays visible — nothing is ever left hidden by CSS alone.
   =========================================================================== */

:root {
  --m-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --m-fast: 180ms;
  --m-base: 380ms;
  --m-slow: 560ms;
}

/* ----------------------------------------------------------- loading bar */

#pageBar {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  width: 0;
  background: linear-gradient(90deg, #1F7FD4, #3D9BE9 60%, #8FC8F5);
  box-shadow: 0 0 12px rgba(31, 127, 212, 0.75);
  z-index: 9999;
  opacity: 0;
  border-radius: 0 3px 3px 0;
  transition: width 260ms ease, opacity 300ms ease;
  pointer-events: none;
}
#pageBar.on { opacity: 1; }

/* ------------------------------------------------------------ page enter */

/* Opacity only on the wrapper — a transform here would make any open modal
   (which is position: fixed) resolve against the wrapper instead of the
   viewport for the duration of the animation. */
.js-motion .page,
.js-motion .admin-shell,
.js-motion .login-wrap {
  animation: m-page-in var(--m-base) var(--m-ease) both;
}
/* Starts partly visible for the same reason as the dialogs above. */
@keyframes m-page-in {
  from { opacity: 0.25; }
  to   { opacity: 1; }
}

@keyframes m-rise-in {
  from { opacity: 0.3; transform: translateY(18px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------ login screen */

.js-motion .login-wrap { position: relative; overflow: hidden; }

/* Slow-drifting light behind the card. */
.js-motion .login-wrap::before,
.js-motion .login-wrap::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  filter: blur(60px);
}
.js-motion .login-wrap::before {
  width: 46vw; height: 46vw; min-width: 380px; min-height: 380px;
  top: -14%; left: -10%;
  background: radial-gradient(circle, rgba(31, 127, 212, 0.55), rgba(31, 127, 212, 0) 70%);
  animation: m-drift-a 19s ease-in-out infinite alternate;
}
.js-motion .login-wrap::after {
  width: 38vw; height: 38vw; min-width: 300px; min-height: 300px;
  bottom: -16%; right: -8%;
  background: radial-gradient(circle, rgba(61, 155, 233, 0.4), rgba(61, 155, 233, 0) 70%);
  animation: m-drift-b 23s ease-in-out infinite alternate;
}
@keyframes m-drift-a {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(7vw, 6vh, 0) scale(1.14); }
}
@keyframes m-drift-b {
  from { transform: translate3d(0, 0, 0) scale(1.08); }
  to   { transform: translate3d(-6vw, -7vh, 0) scale(1); }
}

.js-motion .login-card {
  position: relative;
  z-index: 1;
  animation: m-card-in 560ms var(--m-ease) both;
}
@keyframes m-card-in {
  from { opacity: 0.25; transform: translateY(26px) scale(0.97); }
  to   { opacity: 1; transform: none; }
}

/* Card contents cascade in behind the card itself. */
.js-motion .login-card > *,
.js-motion .login-card form > div,
.js-motion .login-card form > button {
  animation: m-rise-in 440ms var(--m-ease) both;
}
.js-motion .login-card > *:nth-child(1) { animation-delay: 180ms; }
.js-motion .login-card > *:nth-child(2) { animation-delay: 240ms; }
.js-motion .login-card > *:nth-child(3) { animation-delay: 290ms; }
.js-motion .login-card > *:nth-child(4) { animation-delay: 335ms; }
.js-motion .login-card > *:nth-child(5) { animation-delay: 375ms; }
.js-motion .login-card form > div:nth-child(2) { animation-delay: 380ms; }
.js-motion .login-card form > div:nth-child(3) { animation-delay: 430ms; }
.js-motion .login-card form > button { animation-delay: 480ms; }

.js-motion .login-card .brand img { transition: transform 300ms var(--m-ease); }
.js-motion .login-card:hover .brand img { transform: scale(1.03); }

.js-motion .login-card input {
  transition: border-color 170ms ease, box-shadow 220ms ease, background 170ms ease;
}
.js-motion .login-card input:focus {
  outline: none;
  border-color: #1F7FD4;
  box-shadow: 0 0 0 4px rgba(31, 127, 212, 0.15);
}

/* Wrong password: shake the message rather than just showing it. */
.js-motion .login-card .flash.err { animation: m-shake 460ms ease both; }
@keyframes m-shake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(3px); }
  30%, 50%, 70% { transform: translateX(-5px); }
  40%, 60% { transform: translateX(5px); }
}

/* Submitting state on any button that opts in. */
.js-motion .btn.is-loading { pointer-events: none; opacity: 0.9; }
.js-motion .btn.is-loading::after {
  content: '';
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, 0.45);
  border-top-color: #fff;
  border-radius: 50%;
  animation: m-spin 700ms linear infinite;
}
@keyframes m-spin { to { transform: rotate(360deg); } }

/* ------------------------------------------------------------- page exit */

.js-motion.is-leaving body {
  opacity: 0.38;
  transition: opacity 240ms ease;
}

/* --------------------------------------------------------- scroll reveal */

.js-motion [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--m-slow) var(--m-ease),
              transform var(--m-slow) var(--m-ease);
  transition-delay: var(--m-delay, 0ms);
}
/* transform: none (not translateY(0)) so no containing block is left behind */
.js-motion [data-reveal].in {
  opacity: 1;
  transform: none;
}

/* ------------------------------------------------------ modals & overlays */

/* Entry animations never start from opacity: 0. If an animation is ever
   throttled or fails to advance, the worst case is a slightly faded, slightly
   offset dialog — never an invisible one. */
.js-motion .amodal.open,
.js-motion .pmodal.open,
.js-motion .lightbox.open,
.js-motion .cert-lightbox.open {
  animation: m-fade-in var(--m-fast) ease both;
}
@keyframes m-fade-in {
  from { opacity: 0.45; }
  to   { opacity: 1; }
}

.js-motion .pmodal.open .pmodal-box,
.js-motion .lightbox.open img,
.js-motion .cert-lightbox.open img,
.js-motion .dr-pop:not([hidden]) {
  animation: m-pop-in 240ms var(--m-ease) both;
}
@keyframes m-pop-in {
  from { opacity: 0.5; transform: translateY(12px) scale(0.985); }
  to   { opacity: 1; transform: none; }
}

/* Closing state is applied by motion.js so the overlay can animate out
   before display flips back to none. */
.js-motion .amodal.closing,
.js-motion .pmodal.closing,
.js-motion .lightbox.closing,
.js-motion .cert-lightbox.closing {
  display: flex !important;
  pointer-events: none;
  animation: m-fade-out var(--m-fast) ease both;
}
@keyframes m-fade-out {
  to { opacity: 0; }
}
.js-motion .amodal.closing .amodal-box,
.js-motion .pmodal.closing .pmodal-box,
.js-motion .lightbox.closing img,
.js-motion .cert-lightbox.closing img {
  animation: m-pop-out var(--m-fast) ease both;
}
@keyframes m-pop-out {
  to { opacity: 0; transform: translateY(8px) scale(0.985); }
}

/* -------------------------------------------------------- image fade-ins */

/* Never the slideshow slides: .m-loaded would out-specify
   .hero-slideshow .hero-slide.active and hold every slide on screen. */
.js-motion img.m-img:not(.hero-slide) {
  opacity: 0;
  transition: opacity 500ms ease;
}
.js-motion img.m-img.m-loaded:not(.hero-slide) { opacity: 1; }

/* ------------------------------------------------------- interaction feel */

.js-motion .btn,
.js-motion .tabbtn,
.js-motion .df-chip,
.js-motion .tbtn,
.js-motion .dr-trigger {
  transition: background 160ms ease, border-color 160ms ease, color 160ms ease,
              transform 160ms var(--m-ease), box-shadow 160ms ease;
}
.js-motion .btn:active,
.js-motion .tbtn:active,
.js-motion .dr-trigger:active { transform: translateY(1px) scale(0.985); }

.js-motion .kpi,
.js-motion .ql,
.js-motion .thumb-card,
.js-motion .hero-card {
  transition: transform 200ms var(--m-ease), box-shadow 200ms ease,
              border-color 200ms ease;
}
.js-motion .kpi:hover { transform: translateY(-3px); box-shadow: 0 12px 26px rgba(10, 37, 69, 0.09); }

.js-motion .side-nav a { transition: color 160ms ease, background 160ms ease, padding-left 160ms var(--m-ease); }
.js-motion .side-nav a:hover { padding-left: 24px; }

/* Sidebar links stagger in on load. */
.js-motion .side-nav a {
  animation: m-slide-in 420ms var(--m-ease) both;
  animation-delay: calc(var(--i, 0) * 28ms + 80ms);
}
@keyframes m-slide-in {
  from { opacity: 0.35; transform: translateX(-10px); }
  to   { opacity: 1; transform: none; }
}

/* ------------------------------------------------------- reduced motion */

@media (prefers-reduced-motion: reduce) {
  .js-motion [data-reveal],
  .js-motion [data-reveal].in {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .js-motion .login-wrap::before,
  .js-motion .login-wrap::after { display: none; }
  .js-motion .login-card > *,
  .js-motion .login-card form > div,
  .js-motion .login-card form > button,
  .js-motion .login-card .flash.err,
  .js-motion .btn.is-loading::after,
  .js-motion .page,
  .js-motion .admin-shell,
  .js-motion .login-wrap,
  .js-motion .login-card,
  .js-motion .side-nav a,
  .js-motion .amodal.open,
  .js-motion .pmodal.open,
  .js-motion .lightbox.open,
  .js-motion .cert-lightbox.open,
  .js-motion .dr-pop:not([hidden]),
  .js-motion .pmodal.open .pmodal-box,
  .js-motion .lightbox.open img,
  .js-motion .cert-lightbox.open img {
    animation: none !important;
  }
  .js-motion .amodal.closing,
  .js-motion .pmodal.closing,
  .js-motion .lightbox.closing,
  .js-motion .cert-lightbox.closing { display: none !important; }
  .js-motion.is-leaving body { opacity: 1; transition: none; }
  .js-motion img.m-img { opacity: 1; transition: none; }
  #pageBar { display: none; }
  .js-motion .side-nav a:hover { padding-left: 20px; }
}
