/* =========================================================
   SEPTIM LABS — motion system
   Three layers: ambient (always-on) · reactive (input) · scroll-coupled
   Drop into any v3 page after site.css.
   ========================================================= */

/* ─── tokens ─────────────────────────────────────────── */
:root{
  --m-ease: cubic-bezier(.16,1,.3,1);
  --m-ease-out: cubic-bezier(.22,.61,.36,1);
  --m-spring: cubic-bezier(.34,1.56,.64,1);
  --m-fast: 180ms;
  --m-med: 320ms;
  --m-slow: 600ms;
  --m-heartbeat: 2.4s;       /* global pulse cadence */
}
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{ animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important; }
}

/* ─── 1. AMBIENT (always-on) ─────────────────────────── */

/* heartbeat — sync all pulses */
@keyframes m-heartbeat{ 0%,100%{opacity:.55;transform:scale(1)} 50%{opacity:1;transform:scale(1.15)} }
.m-pulse{ animation: m-heartbeat var(--m-heartbeat) ease-in-out infinite; }

/* breathing radial wash (heroes) */
@keyframes m-breathe{ 0%,100%{opacity:.55;filter:blur(0)} 50%{opacity:1;filter:blur(2px)} }
.m-breathe{ animation: m-breathe 7s ease-in-out infinite; }

/* drifting grid (subtle parallax of bg lines) */
@keyframes m-drift{ from{background-position:0 0,0 0} to{background-position:48px 48px,48px 48px} }
.m-grid{ animation: m-drift 60s linear infinite; }

/* slow rotate (heptagon mark, radar) */
@keyframes m-spin-slow{ to{transform:rotate(360deg)} }
.m-spin-slow{ animation: m-spin-slow 90s linear infinite; transform-origin:center; }

/* digit flicker — call on numeric spans, fires every ~10s */
@keyframes m-flicker{ 0%,93%,100%{opacity:1} 94%{opacity:.4} 95%{opacity:1} 96%{opacity:.6} 97%{opacity:1} }
.m-flicker{ animation: m-flicker 11s steps(1,end) infinite; }

/* status dot pulse (ring expand) */
@keyframes m-ring{ 0%{box-shadow:0 0 0 0 currentColor} 70%{box-shadow:0 0 0 8px transparent} 100%{box-shadow:0 0 0 0 transparent} }
.m-ring{ animation: m-ring var(--m-heartbeat) ease-out infinite; }

/* particle drift — attach to small dots inside heroes */
@keyframes m-float{ 0%,100%{transform:translate(0,0)} 33%{transform:translate(8px,-12px)} 66%{transform:translate(-6px,6px)} }
.m-float{ animation: m-float 16s ease-in-out infinite; }

/* horizontal ticker baseline */
@keyframes m-ticker{ from{transform:translateX(0)} to{transform:translateX(-50%)} }
.m-ticker{ animation: m-ticker 38s linear infinite; will-change:transform; }
.m-ticker-pause:hover .m-ticker{ animation-play-state: paused; }

/* sweep beam (radar, scanline) */
@keyframes m-sweep{ from{transform:rotate(0)} to{transform:rotate(360deg)} }
.m-sweep{ animation: m-sweep 8s linear infinite; transform-origin:center; }

/* trace border — perimeter ant-line on price/feature cards */
@keyframes m-trace{ from{stroke-dashoffset:1000} to{stroke-dashoffset:0} }

/* ─── 2. REACTIVE (input-driven) ──────────────────────── */

/* lift card on hover with accent glow */
.m-lift{ transition: transform var(--m-med) var(--m-ease), box-shadow var(--m-med) var(--m-ease), border-color var(--m-fast); will-change:transform; }
.m-lift:hover{ transform:translateY(-3px); border-color:var(--p); box-shadow:0 12px 36px -12px var(--p-glow), 0 0 0 1px color-mix(in srgb, var(--p) 30%, transparent); }

/* cursor-following sheen — uses --mx,--my (0..100) set by JS */
.m-sheen{ position:relative; isolation:isolate; }
.m-sheen::before{
  content:""; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  background: radial-gradient(280px circle at var(--mx,50%) var(--my,50%), color-mix(in srgb, var(--p) 14%, transparent), transparent 60%);
  opacity:0; transition: opacity var(--m-med) var(--m-ease); z-index:0;
}
.m-sheen > *{ position:relative; z-index:1; }
.m-sheen:hover::before{ opacity:1; }

/* button — fill from cursor, arrow eject */
.m-btn{ position:relative; overflow:hidden; transition: transform var(--m-fast) var(--m-spring), box-shadow var(--m-med) var(--m-ease); }
.m-btn::before{
  content:""; position:absolute; inset:0;
  background: radial-gradient(120px circle at var(--mx,50%) var(--my,50%), color-mix(in srgb, var(--p) 25%, transparent), transparent 60%);
  opacity:0; transition: opacity var(--m-med) var(--m-ease);
}
.m-btn:hover{ transform:translateY(-1px); box-shadow:0 8px 24px -6px var(--p-glow); }
.m-btn:hover::before{ opacity:1; }
.m-btn:active{ transform:translateY(0) scale(.98); }
.m-btn .arr,.m-btn span.arr{ display:inline-block; transition: transform var(--m-fast) var(--m-spring); }
.m-btn:hover .arr{ transform: translateX(4px); }

/* tab/filter — ink fill */
.m-tab{ position:relative; overflow:hidden; transition: color var(--m-fast); }
.m-tab::before{
  content:""; position:absolute; inset:0; background:var(--p); transform:scaleX(0); transform-origin:left;
  transition: transform var(--m-med) var(--m-ease); z-index:-1; opacity:.12;
}
.m-tab:hover::before{ transform:scaleX(1); }
.m-tab.active::before{ transform:scaleX(1); opacity:.18; }

/* ticker price digits — roll on hover */
.m-roll{ display:inline-flex; overflow:hidden; vertical-align:baseline; }
.m-roll > span{ display:block; transition: transform var(--m-med) var(--m-ease); }
.m-roll:hover > span{ transform: translateY(-100%); }
.m-roll > span::after{ content: attr(data-after); display:block; }

/* table row scanline */
.m-row{ position:relative; transition: background var(--m-fast); }
.m-row::after{
  content:""; position:absolute; left:0; right:0; top:0; height:1px;
  background: linear-gradient(90deg, transparent, var(--p), transparent);
  opacity:0; transition: opacity var(--m-fast);
}
.m-row:hover::after{ opacity:.5; animation: m-scan 1.4s var(--m-ease) infinite; }
@keyframes m-scan{ 0%{top:0;opacity:.5} 100%{top:100%;opacity:0} }

/* magnetize (cursor pulls element) — JS sets --dx,--dy in px */
.m-mag{ transition: transform var(--m-fast) var(--m-ease); transform: translate(var(--dx,0), var(--dy,0)); }

/* count-up wrapper — sets --to via JS, animates 0..to via CSS counter */
.m-count{ font-variant-numeric: tabular-nums; }

/* ─── 3. SCROLL-COUPLED ──────────────────────────────── */

/* fade/rise on enter */
.m-rise{ opacity:0; transform: translateY(20px); transition: opacity var(--m-slow) var(--m-ease), transform var(--m-slow) var(--m-ease); }
.m-rise.in{ opacity:1; transform:translateY(0); }

/* eyebrow wipe-in */
.m-wipe{ clip-path: inset(0 100% 0 0); transition: clip-path var(--m-slow) var(--m-ease); }
.m-wipe.in{ clip-path: inset(0 0 0 0); }

/* hero parallax target — JS sets --sy in px */
.m-parallax{ transform: translateY(calc(var(--sy,0) * 1px)); }

/* scroll-velocity ticker speed multiplier — JS sets --vel */
.m-ticker.m-ticker-velo{ animation-duration: calc(38s / max(.5, var(--vel,1))); }
