/* ============================================================================
   motion.css — the site's animation layer.

   Rules this follows:
   • Motion carries meaning: things enter from where they came from, and the
     eye is led down the page in the order you should read it.
   • Nothing important waits on an animation. Content is visible by default and
     only animates when JS confirms it can observe it (see motion.js), so a
     failed script can never leave a blank page.
   • Every effect is disabled under prefers-reduced-motion.
   ========================================================================= */

:root {
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 160ms;
  --dur: 320ms;
  --dur-slow: 620ms;
}

/* ── Page entrance ────────────────────────────────────────────────────────
   The shell fades up once on load. Staggered children follow. */
[data-motion] .m-in {
  opacity: 0;
  transform: translateY(14px);
}
[data-motion] .m-in.m-shown {
  opacity: 1;
  transform: none;
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}
/* Stagger: each child leaves a beat after the one before it. */
[data-motion] .m-stagger > * { opacity: 0; transform: translateY(12px); }
[data-motion] .m-stagger.m-shown > * {
  opacity: 1; transform: none;
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}
[data-motion] .m-stagger.m-shown > *:nth-child(1) { transition-delay: 0ms; }
[data-motion] .m-stagger.m-shown > *:nth-child(2) { transition-delay: 60ms; }
[data-motion] .m-stagger.m-shown > *:nth-child(3) { transition-delay: 120ms; }
[data-motion] .m-stagger.m-shown > *:nth-child(4) { transition-delay: 180ms; }
[data-motion] .m-stagger.m-shown > *:nth-child(5) { transition-delay: 240ms; }
[data-motion] .m-stagger.m-shown > *:nth-child(6) { transition-delay: 300ms; }
[data-motion] .m-stagger.m-shown > *:nth-child(n+7) { transition-delay: 340ms; }

/* Sideways variants for content that belongs to one edge. */
[data-motion] .m-in-left  { transform: translateX(-18px); }
[data-motion] .m-in-right { transform: translateX(18px); }
[data-motion] .m-in-left.m-shown,
[data-motion] .m-in-right.m-shown { transform: none; }

/* Scale-in for things that "appear" rather than arrive (cards, modals). */
[data-motion] .m-pop { opacity: 0; transform: scale(0.97); }
[data-motion] .m-pop.m-shown {
  opacity: 1; transform: none;
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}

/* ── Interaction ──────────────────────────────────────────────────────────
   Lift on hover, settle on press. Applied to the shared card/button classes
   so pages get it without opting in. */
.m-lift { transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur) var(--ease-out), border-color var(--dur-fast) ease; }
.m-lift:hover { transform: translateY(-3px); }
.m-lift:active { transform: translateY(-1px); }

button, .btn, a.btn, .quick-card, .lvl-card, .chip, .seg button, .lvl-tab, .qnav-dot, .subj, .plan {
  transition: background-color var(--dur-fast) ease, border-color var(--dur-fast) ease,
              color var(--dur-fast) ease, transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur) var(--ease-out), opacity var(--dur-fast) ease;
}
button:active, .btn:active { transform: translateY(1px); }

/* ── Count-up numbers ─────────────────────────────────────────────────────
   Stats animate from 0 so a dashboard feels alive when it loads. */
.m-count { font-variant-numeric: tabular-nums; }

/* ── Skeletons ────────────────────────────────────────────────────────────
   Shown while real content loads, instead of an empty box. */
.m-skel {
  border-radius: 8px;
  background: linear-gradient(90deg, var(--surface) 25%, var(--surface-2) 37%, var(--surface) 63%);
  background-size: 400% 100%;
  animation: m-shimmer 1.4s ease-in-out infinite;
  color: transparent !important;
  pointer-events: none;
}
@keyframes m-shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ── Attention ────────────────────────────────────────────────────────────
   A single, reusable "look here" pulse. Used sparingly. */
.m-pulse { animation: m-pulse 2.4s var(--ease-in-out) infinite; }
@keyframes m-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--gold) 32%, transparent); }
  50% { box-shadow: 0 0 0 10px color-mix(in srgb, var(--gold) 0%, transparent); }
}

/* Value changed — flash once so the eye catches it. */
.m-flash { animation: m-flash 700ms var(--ease-out); }
@keyframes m-flash {
  0% { background-color: color-mix(in srgb, var(--gold) 22%, transparent); }
  100% { background-color: transparent; }
}

/* ── Section transitions inside an app view ───────────────────────────────
   Setup → generating → exam → results should feel like one flow. */
.m-swap { animation: m-swap var(--dur-slow) var(--ease-out); }
@keyframes m-swap {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* ── Respect the user ─────────────────────────────────────────────────────
   Everything above collapses to "just show it". */
@media (prefers-reduced-motion: reduce) {
  [data-motion] .m-in,
  [data-motion] .m-in-left,
  [data-motion] .m-in-right,
  [data-motion] .m-pop,
  [data-motion] .m-stagger > * {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .m-lift:hover, button:active, .btn:active { transform: none; }
  .m-skel, .m-pulse, .m-flash, .m-swap { animation: none; }
  .m-skel { background: var(--surface-2); }
}

/* ── Reading rule ─────────────────────────────────────────────────────────
   A pen line across the top of a long page, filling as you read down it.
   motion.js appends the element and hides it on pages short enough to have
   nothing to report, so a two-screen page never grows a progress bar. */
.m-rule {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 400;
  pointer-events: none;
  background: transparent;
}

/* Gold, and the same 3px seam the landing page draws, so a student who scrolls
   the landing page and then an app page sees one bar and not two products.
   The pen was the obvious choice and is the wrong one: this rule lies on the
   ink ground, and the pen only ever touches paper. */
.m-rule i {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: var(--gradient-brand);
  box-shadow: 0 0 14px color-mix(in srgb, var(--gold) 60%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .m-rule { display: none; }
}
