/* ===========================================================================
   motion.css — unified motion layer
   Loaded LAST so it can trim/override the earlier redesign stylesheets.

   Three jobs:
     1. give scroll-linked effects (hero parallax, nav shrink) their styles
     2. enforce a motion budget — infinite animations pause off-screen
     3. retire ambient loops that cost paint and add nothing
   Easing/duration tokens match globals.css:
     --ease-out cubic-bezier(.16,1,.3,1) · 200ms interaction / 400ms reveal / 700ms hero
   ========================================================================= */

:root{
  --mx-ease: cubic-bezier(.16,1,.3,1);
  --mx-dur-ui: .2s;
  --mx-dur-reveal: .4s;
  --mx-dur-hero: .7s;
}

/* ---------------------------------------------------------------------------
   1 · HERO PARALLAX
   motion.js lifts the section's background onto this layer so it can be
   transformed on the compositor instead of repainting background-position.
   ------------------------------------------------------------------------- */
.mx-hero-bg{
  position:absolute; inset:-6% 0 0; z-index:0;
  background-position:center center; background-size:cover; background-repeat:no-repeat;
  will-change:transform, opacity;
  transform:translate3d(0,0,0);
  pointer-events:none;
}
.mx-parallax-host{ background-image:none !important; }

/* ---------------------------------------------------------------------------
   1b · HERO SCRUB VIDEO
   Sits where the background image was, under the gradient overlays (which are
   z-index:1) and the copy (z-index:10). Hidden until motion.js decides the
   client should have it — until then the poster/background image shows.
   ------------------------------------------------------------------------- */
.ni-hero-video{
  position:absolute; top:0; left:0; bottom:0; z-index:0;
  /* Wider than the hero and anchored left, so the tractor — centred in the
     clip — lands right of centre and clears the headline. object-fit moves
     the *window*, not the subject, so anchoring left pushes the subject right. */
  width:136%; height:100%;
  object-fit:cover;
  object-position:left center;
  pointer-events:none;
  opacity:0;                        /* revealed once the first frame is ready */
  transition:opacity .45s var(--mx-ease);
  display:none;
}
.ni-hero.mx-scrub .ni-hero-video{ display:block; }
.ni-hero.mx-scrub-ready .ni-hero-video{ opacity:1; }
/* With the video running, the still background underneath is redundant */
.ni-hero.mx-scrub-ready{ background-image:none; }

/* Between 900px and ~1200px there's less room beside the copy — ease the
   subject further right still. (Below 900px the video never loads.) */
@media (max-width:1200px){
  .ni-hero-video{ width:150%; }
}

/* ---------------------------------------------------------------------------
   2 · NAV — condense past the hero, hide on scroll-down, return on scroll-up
   ------------------------------------------------------------------------- */
.hnav{
  transition:transform .28s var(--mx-ease),
             height .28s var(--mx-ease),
             background-color .28s var(--mx-ease),
             box-shadow .28s var(--mx-ease);
  will-change:transform;
}
.hnav.mx-compact{ height:56px; box-shadow:0 6px 24px rgba(0,0,0,.22); }
.hnav.mx-compact .hbrand img,
.hnav.mx-compact .hbrand .badge img{ transform:scale(.85); transition:transform .28s var(--mx-ease); }
.hnav.mx-compact .hnav-links{ transform:scale(.96); transition:transform .28s var(--mx-ease); }
.hnav.mx-hidden{ transform:translateY(-102%); }

/* Never hide the bar while a menu or modal is open. */
.hmenu.open ~ .hnav,
body.mx-lock .hnav{ transform:none !important; }

/* ---------------------------------------------------------------------------
   3 · NUMBER ROLL — EMI figures settle instead of snapping
   ------------------------------------------------------------------------- */
.mx-rolling{ font-variant-numeric:tabular-nums; }
.emi-big, .eb b, .eval{ font-variant-numeric:tabular-nums; }
.eval.mx-bump{ animation:mxBump .28s var(--mx-ease); }
@keyframes mxBump{ 50%{ transform:translateY(-2px); } }

/* ---------------------------------------------------------------------------
   4 · COMPARE — flash the cells that actually changed
   ------------------------------------------------------------------------- */
.mx-flash{ animation:mxFlash .6s var(--mx-ease); }
@keyframes mxFlash{
  0%  { background:rgba(244,180,0,.28); box-shadow:inset 0 0 0 1px rgba(244,180,0,.5); }
  100%{ background:transparent;         box-shadow:inset 0 0 0 1px transparent; }
}
/* the winning badge slides rather than teleports between columns */
.cm-best-badge{ transition:transform .32s var(--mx-ease), opacity var(--mx-dur-ui) linear; }

/* ---------------------------------------------------------------------------
   5 · MOTION BUDGET
   Anything off-screen stops animating. This is the single biggest win —
   the home page ran 43 concurrent infinite animations before this.
   ------------------------------------------------------------------------- */
.mx-paused,
.mx-paused *{ animation-play-state:paused !important; }

/* ---------------------------------------------------------------------------
   6 · RETIRED AMBIENT LOOPS
   Each of these is an always-on repaint with no narrative payoff.
   ------------------------------------------------------------------------- */
.parts-fresh .grain,
.section.soil .grain,
.section.soil-deep .grain{ animation:none !important; }

/* showcase: keep the hover shine and the centre-card glow, drop the rest.
   The three aura blobs are 80px-blur radial gradients being transformed
   forever — the most expensive paint on the page for an effect nobody can
   consciously see. Dust is thinned from 26 particles to 8 in motion.js. */
.scx-aura b.a1,
.scx-aura b.a2,
.scx-aura b.a3{ animation:none !important; }
.scx-card.is-center .scx-media image-slot{ animation:none !important; }

/* hero dust: 5 motes → 3 */
.phero-dust i:nth-child(4),
.phero-dust i:nth-child(5){ display:none; }

/* ---------------------------------------------------------------------------
   7 · STAGGERED REVEALS
   motion.js sets --mx-i per grid child; one rule turns it into a cascade.
   ------------------------------------------------------------------------- */
.fx[style*="--mx-i"]{ transition-delay:calc(var(--mx-i) * 80ms); }

/* ---------------------------------------------------------------------------
   8 · REDUCED MOTION — master guard
   13 of the 25 legacy stylesheets had no reduced-motion block. This closes
   the gap for all of them at once.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
  .mx-hero-bg{ transform:none !important; opacity:1 !important; }
  /* Keep the still hero rather than a scroll-driven video */
  .ni-hero-video{ display:none !important; }
  .ni-hero.mx-scrub-ready{ background-image:url("assets/hero-scrub-poster.jpg?v=5"); }
  .hnav.mx-hidden{ transform:none; }
  .fx{ opacity:1 !important; transform:none !important; }
}
