/* ============================================================================
   exotic — css/kit/motion.css · MERIDIAN choreography
   ----------------------------------------------------------------------------
   ANIMATION STORYBOARD (page load — js/kit/motion.js casts the elements)

      0ms   meridian draws across the top      scaleX 0 → 1 · 700ms · emph
    120ms   chrome fades in (rail / topbar)    opacity · 300ms
    200ms   headline + hero rise               y 10px → 0 · 500ms
    300ms   rail cards rise                    (staggered 70ms)
    380ms   sections / rows rise               (staggered 40ms · first 8)
    550ms   hero number settles                blur 7px → 0 · 550ms
    700ms   chart line draws                   dashoffset 1 → 0 · 900ms

   All timing lives HERE and in js/kit/motion.js TIMING. Motion is light arriving:
   nothing bounces, everything eases out (--ease-emph). With JS off nothing is
   hidden (rules are gated on html.mo-on, set by motion.js). Reduced motion
   kills the whole board.
   ========================================================================== */

/* ---- THE MERIDIAN — a 2px horizon of the day's light across the very top
   of every page (app AND landing). Injected by js/kit/motion.js; based here so
   every page that runs the choreography also styles the element. ---- */
.meridian{position:fixed;top:0;left:0;right:0;height:2px;z-index:300;pointer-events:none;overflow:hidden}
/* the breathe rides the compositor: a doubled-width gradient child translates,
   instead of background-position repainting a strip on every page forever (FX17) */
.meridian::before{content:"";position:absolute;inset:0;width:220%;background:var(--grad);
  animation:mer-breathe 14s var(--ease-inout,ease-in-out) infinite alternate;will-change:transform}
@keyframes mer-breathe{from{transform:translateX(0)}to{transform:translateX(-54.5%)}}

/* ---- the meridian's entrance: light crosses the world once, then breathes */
.mo-on .meridian{
  transform-origin:left center;
  animation:mo-mer-draw .7s var(--ease-emph,cubic-bezier(.16,1,.3,1)) both}
.mo-on .meridian::before{animation-delay:.7s}
@keyframes mo-mer-draw{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* ---- rise: the interface comes up into the light ---- */
.mo-on [data-mo]{
  animation:mo-rise .5s var(--ease-emph,cubic-bezier(.16,1,.3,1)) both;
  animation-delay:var(--mo-d,200ms)}
@keyframes mo-rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

/* ---- fade: children arriving inside an already-rising container (metric
   cells) — opacity only, so parent and child never compound transforms ---- */
.mo-on [data-mo-fade]{
  animation:mo-fade .4s var(--ease-out,cubic-bezier(.2,.8,.2,1)) both;
  animation-delay:var(--mo-d,380ms)}
@keyframes mo-fade{from{opacity:0}to{opacity:1}}

/* ---- settle: the one number you came for sharpens into focus ---- */
.mo-on [data-mo-settle]{
  animation:mo-settle .55s var(--ease-out,cubic-bezier(.2,.8,.2,1)) both;
  animation-delay:var(--mo-d,550ms)}
@keyframes mo-settle{from{opacity:0;filter:blur(7px)}60%{opacity:1}to{opacity:1;filter:blur(0)}}

/* ---- chart reveal — daylight sweeps the chart in, left to right ----
   (A dash-based line draw fights vector-effect:non-scaling-stroke on these
   stretched viewBoxes, so the whole svg wipes instead.) Every (re)render
   sweeps quickly; ONLY the boot render waits for its slot in the storyboard
   (html.mo-boot is present for the first moments, removed by js/kit/motion.js). */
.mo-on .chart-wrap>svg,.mo-on .px-chart>svg,.mo-on .px-vol>svg{
  animation:mo-wipe .9s var(--ease-emph,cubic-bezier(.16,1,.3,1)) both}
.mo-on.mo-boot .chart-wrap>svg,.mo-on.mo-boot .px-chart>svg,.mo-on.mo-boot .px-vol>svg{animation-delay:.7s}
/* live re-renders (typing a TP/SL, dragging a line) repaint in place —
   px-chart.js flags them; only a genuinely new view earns the wipe */
.mo-on .px-chart.no-wipe>svg,.mo-on .px-vol.no-wipe>svg{animation:none}
@keyframes mo-wipe{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}

/* ---- reduced motion: the board goes dark, content is simply there ---- */
@media (prefers-reduced-motion:reduce){
  .mo-on [data-mo],.mo-on [data-mo-settle],.mo-on [data-mo-fade],.mo-on .meridian,.meridian::before,
  .mo-on .chart-wrap>svg,.mo-on .px-chart>svg,.mo-on .px-vol>svg{animation:none}
}

/* notch: the meridian thread rides just below the status bar in app mode */
.meridian{ top:env(safe-area-inset-top, 0px); }
