/* ==========================================================================
   animations.css — tasteful motion polish layer
   --------------------------------------------------------------------------
   Loaded AFTER styles.css (and review.css on the quiz page) so it can augment
   and override transitions cleanly. All motion is opt-in: every animation /
   non-trivial transition is wrapped in @media (prefers-reduced-motion:
   no-preference), and there is an explicit reduce block at the bottom that
   neutralises anything that might still move.

   Curves + durations follow the existing system: short (140–300ms),
   ease-out for entrances, and the spacing/colour tokens (--space-*, --accent,
   etc.) are reused — no new colours introduced.
   ========================================================================== */

:root {
  --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --dur-fast: 140ms;
  --dur: 200ms;
  --dur-slow: 280ms;
}

@media (prefers-reduced-motion: no-preference) {

  /* ---- Keyframes -------------------------------------------------------- */

  @keyframes fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  @keyframes fade-up {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
  }

  @keyframes sheet-up {
    from { transform: translateY(100%); }
    to   { transform: translateY(0); }
  }

  @keyframes pop-in {
    0%   { opacity: 0; transform: scale(0.96) translateY(6px); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
  }

  @keyframes correct-pulse {
    0%   { transform: scale(1); }
    40%  { transform: scale(1.035); }
    100% { transform: scale(1); }
  }

  @keyframes wrong-shake {
    0%, 100% { transform: translateX(0); }
    20%      { transform: translateX(-5px); }
    40%      { transform: translateX(5px); }
    60%      { transform: translateX(-3px); }
    80%      { transform: translateX(3px); }
  }

  /* ---- Page / section entrance ----------------------------------------- */
  /* The main column gently fades + lifts on load. One-shot, runs once. */
  .container {
    animation: fade-up var(--dur-slow) var(--ease-out) both;
  }

  /* The page header settles a touch after the column, for a layered feel. */
  .page-header {
    animation: fade-up var(--dur-slow) var(--ease-out) both;
    animation-delay: 40ms;
  }

  /* ---- Staggered list / card reveals ----------------------------------- */
  /* Cards and list rows fade-up in sequence. Containers that render their
     children up-front (.topics grid, weak-spot list, summary grids) get a
     short cascade. Delays are capped so long lists don't feel sluggish. */
  .topics > .topic-card,
  .weak-spot-list > .weak-spot,
  .progress-summary-grid > .progress-summary-card {
    animation: fade-up var(--dur) var(--ease-out) both;
  }
  .topics > .topic-card:nth-child(1),
  .weak-spot-list > .weak-spot:nth-child(1),
  .progress-summary-grid > .progress-summary-card:nth-child(1) { animation-delay: 30ms; }
  .topics > .topic-card:nth-child(2),
  .weak-spot-list > .weak-spot:nth-child(2),
  .progress-summary-grid > .progress-summary-card:nth-child(2) { animation-delay: 70ms; }
  .topics > .topic-card:nth-child(3),
  .weak-spot-list > .weak-spot:nth-child(3),
  .progress-summary-grid > .progress-summary-card:nth-child(3) { animation-delay: 110ms; }
  .topics > .topic-card:nth-child(4),
  .weak-spot-list > .weak-spot:nth-child(4),
  .progress-summary-grid > .progress-summary-card:nth-child(4) { animation-delay: 150ms; }
  .topics > .topic-card:nth-child(5),
  .weak-spot-list > .weak-spot:nth-child(5),
  .progress-summary-grid > .progress-summary-card:nth-child(5) { animation-delay: 190ms; }
  .topics > .topic-card:nth-child(n + 6),
  .weak-spot-list > .weak-spot:nth-child(n + 6),
  .progress-summary-grid > .progress-summary-card:nth-child(n + 6) { animation-delay: 220ms; }

  /* Scroll-in reveal hook (set by js/animations.js IntersectionObserver). */
  .reveal-on-scroll {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity var(--dur-slow) var(--ease-out),
                transform var(--dur-slow) var(--ease-out);
    will-change: opacity, transform;
  }
  .reveal-on-scroll.is-revealed {
    opacity: 1;
    transform: translateY(0);
  }

  /* ---- Daily challenge / streak callout -------------------------------- */
  .daily-challenge {
    animation: pop-in var(--dur-slow) var(--ease-out) both;
    animation-delay: 80ms;
  }
  .streak-chip {
    animation: fade-in var(--dur-slow) var(--ease-out) both;
    animation-delay: 120ms;
  }

  /* ---- Buttons: smoother, springier press feedback --------------------- */
  /* Augments the base .btn transition with a snappier active scale so taps
     feel responsive without bouncing. */
  .btn { transition: filter var(--dur-fast) ease,
                     transform var(--dur-fast) var(--ease-out),
                     border-color var(--dur-fast) ease,
                     box-shadow var(--dur-fast) ease; }
  .btn:hover { box-shadow: 0 4px 14px rgba(47, 109, 246, 0.18); }
  .btn:active { transform: translateY(0) scale(0.97); }
  .btn.secondary:hover { box-shadow: none; }
  .btn:disabled:hover { box-shadow: none; }

  /* ---- Options: clearer hover + answer feedback ------------------------ */
  .option {
    transition: background var(--dur-fast) ease,
                border-color var(--dur-fast) ease,
                transform var(--dur-fast) var(--ease-out);
  }
  .option:hover:not(:disabled) { transform: translateY(-1px); }
  .option:active:not(:disabled) { transform: translateY(0) scale(0.99); }

  /* The correct option gives a quick confidence pulse; the chosen-wrong
     option shakes. These classes are added by quiz.js after grading. */
  .option.correct { animation: correct-pulse 360ms var(--ease-out); }
  .option.wrong   { animation: wrong-shake 360ms var(--ease-out); }

  /* Feedback panel slides + fades in when inserted after answering. */
  .feedback {
    animation: fade-up var(--dur) var(--ease-out) both;
  }
  .feedback.correct { animation: pop-in var(--dur) var(--ease-spring) both; }

  /* Explanation block (revealed after answering) eases in. */
  .explanation {
    animation: fade-up var(--dur) var(--ease-out) both;
  }

  /* ---- Progress bar fill: add a subtle sheen as it grows --------------- */
  /* The width transition already lives in review.css; here we just make the
     easing match the system curve. */
  .quiz-progress-fill {
    transition: width var(--dur-slow) var(--ease-out);
  }

  /* ---- Modal / launcher / onboarding entrances ------------------------- */
  /* These nodes are created fresh on open, so a plain CSS animation on mount
     plays every time the panel appears — no JS changes needed. */
  .study-backdrop,
  .onboard-overlay,
  .sidebar-backdrop:not([hidden]) {
    animation: fade-in var(--dur) ease both;
  }
  .study-panel {
    animation: sheet-up var(--dur-slow) var(--ease-out) both;
  }
  .onboard-overlay > * {
    animation: pop-in var(--dur-slow) var(--ease-out) both;
  }

  /* ---- Summary / review cards on the results screen -------------------- */
  .summary-card,
  .review-empty {
    animation: pop-in var(--dur-slow) var(--ease-out) both;
  }

  /* Account chip lift already exists; add a soft shadow for depth. */
  .account-chip:hover { box-shadow: var(--shadow); }

  /* ---- Sidebar drawer + nav: visual easing only ------------------------ */
  /* sidebar.js toggles `.is-open` and the backdrop's [hidden]; we only retune
     the easing curve here and never touch the open/close logic. */
  .app-sidebar {
    transition: transform var(--dur-slow) var(--ease-out);
  }
  .sidebar-backdrop {
    transition: opacity var(--dur) ease;
  }
  /* Nav rows gain a gentle hover slide + the toggle a springier press. */
  .sidebar-link {
    transition: background var(--dur-fast) ease,
                transform var(--dur-fast) var(--ease-out);
  }
  .sidebar-link:hover { transform: translateX(2px); }
  .sidebar-toggle {
    transition: filter var(--dur-fast) ease,
                transform var(--dur-fast) var(--ease-out),
                box-shadow var(--dur-fast) ease;
  }
  .sidebar-toggle:active { transform: translateY(0) scale(0.96); }
}

/* ==========================================================================
   Reduced motion: hard stop. Anything animated above is neutralised so the
   experience is fully static for users who ask for it. Width/colour state
   changes still apply, just without movement.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .container,
  .page-header,
  .topics > .topic-card,
  .weak-spot-list > .weak-spot,
  .progress-summary-grid > .progress-summary-card,
  .daily-challenge,
  .streak-chip,
  .option.correct,
  .option.wrong,
  .feedback,
  .feedback.correct,
  .explanation,
  .study-backdrop,
  .study-panel,
  .onboard-overlay,
  .onboard-overlay > *,
  .sidebar-backdrop,
  .summary-card,
  .review-empty {
    animation: none !important;
  }
  .reveal-on-scroll {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .option:hover:not(:disabled),
  .option:active:not(:disabled),
  .btn:active,
  .sidebar-link:hover,
  .sidebar-toggle:active { transform: none; }
}
