/* ==========================================================================
   MAXILLA — Animations
   Keyframes, scroll-reveal primitives and the animated SVG icon system.
   GSAP handles scroll-linked motion; this file owns ambient + CSS-only motion.
   ========================================================================== */

/* ---------- KEYFRAMES ---------- */
@keyframes meshDrift {
  0%   { transform: translate3d(0,0,0) scale(1); }
  50%  { transform: translate3d(-3%, 2%, 0) scale(1.08); }
  100% { transform: translate3d(2%, -3%, 0) scale(1.04); }
}
@keyframes breathe {
  0%, 100% { opacity: .55; transform: scale(.94); }
  50%      { opacity: 1;   transform: scale(1.06); }
}
@keyframes spinSlow { to { transform: rotate(360deg); } }
@keyframes pulseDot {
  0%, 100% { box-shadow: 0 0 0 0 rgba(34,181,201,.55); }
  60%      { box-shadow: 0 0 0 7px rgba(34,181,201,0); }
}
@keyframes railRun {
  0%   { transform: translateY(-100%); }
  100% { transform: translateY(250%); }
}
@keyframes scanSweep {
  0%   { top: -20%; opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { top: 105%; opacity: 0; }
}
@keyframes drawerIn {
  to { opacity: 1; transform: none; }
}
@keyframes floatY {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-14px); }
}
@keyframes floatYSm {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-8px); }
}
@keyframes shimmer {
  0%   { background-position: -180% 0; }
  100% { background-position: 180% 0; }
}
@keyframes drawStroke { to { stroke-dashoffset: 0; } }
@keyframes toothSparkle {
  0%, 100% { opacity: 0; transform: scale(.5) rotate(0deg); }
  40%      { opacity: 1; transform: scale(1) rotate(25deg); }
  70%      { opacity: .4; transform: scale(.85) rotate(45deg); }
}
@keyframes marqueeX {
  from { transform: translate3d(0,0,0); }
  to   { transform: translate3d(-50%,0,0); }
}
@keyframes ecgPulse {
  0%   { stroke-dashoffset: 400; }
  100% { stroke-dashoffset: -400; }
}
@keyframes ringPing {
  0%   { transform: scale(.7); opacity: .8; }
  100% { transform: scale(1.9); opacity: 0; }
}

/* ---------- AMBIENT HELPERS ---------- */
.float      { animation: floatY 6.5s var(--ease-inout) infinite; }
.float--sm  { animation: floatYSm 5s var(--ease-inout) infinite; }
.float--d1  { animation-delay: -1.6s; }
.float--d2  { animation-delay: -3.2s; }
.float--d3  { animation-delay: -4.4s; }

.marquee--css .marquee__track { animation: marqueeX 34s linear infinite; }
.marquee--css:hover .marquee__track { animation-play-state: paused; }
.marquee--rev .marquee__track { animation-direction: reverse; }
.marquee--slow .marquee__track { animation-duration: 56s; }

/* ---------- SCROLL REVEAL (CSS fallback + GSAP-driven) ----------
   Elements start hidden only when JS is present (html.js), so the page
   remains fully readable if scripts fail to load. */
html.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 34px, 0);
  transition: opacity .9s var(--ease-out), transform .9s var(--ease-out);
  will-change: opacity, transform;
}
html.js [data-reveal="left"]  { transform: translate3d(-42px, 0, 0); }
html.js [data-reveal="right"] { transform: translate3d(42px, 0, 0); }
html.js [data-reveal="scale"] { transform: scale(.92); }
html.js [data-reveal="blur"]  { filter: blur(12px); transform: translate3d(0, 22px, 0); }
html.js [data-reveal="clip"]  { clip-path: inset(0 0 100% 0); transform: none; opacity: 1; }

html.js [data-reveal].is-in {
  opacity: 1;
  transform: none;
  filter: none;
  clip-path: inset(0 0 0 0);
}

/* Stagger children */
html.js [data-stagger] > * {
  opacity: 0;
  transform: translate3d(0, 30px, 0);
  transition: opacity .78s var(--ease-out), transform .78s var(--ease-out);
}
html.js [data-stagger].is-in > * { opacity: 1; transform: none; }
html.js [data-stagger].is-in > *:nth-child(1) { transition-delay: .00s; }
html.js [data-stagger].is-in > *:nth-child(2) { transition-delay: .07s; }
html.js [data-stagger].is-in > *:nth-child(3) { transition-delay: .14s; }
html.js [data-stagger].is-in > *:nth-child(4) { transition-delay: .21s; }
html.js [data-stagger].is-in > *:nth-child(5) { transition-delay: .28s; }
html.js [data-stagger].is-in > *:nth-child(6) { transition-delay: .35s; }
html.js [data-stagger].is-in > *:nth-child(7) { transition-delay: .42s; }
html.js [data-stagger].is-in > *:nth-child(8) { transition-delay: .49s; }
html.js [data-stagger].is-in > *:nth-child(9) { transition-delay: .56s; }
html.js [data-stagger].is-in > *:nth-child(10){ transition-delay: .63s; }

/* Split-text line reveal (used on the hero + section headings) */
html.js .split-line { display: block; overflow: hidden; }
html.js .split-line > span {
  display: block;
  transform: translate3d(0, 108%, 0);
  transition: transform 1.05s var(--ease-out);
}
html.js .is-in .split-line > span,
html.js .split-line.is-in > span { transform: none; }
html.js .split-line:nth-child(2) > span { transition-delay: .1s; }
html.js .split-line:nth-child(3) > span { transition-delay: .2s; }
html.js .split-line:nth-child(4) > span { transition-delay: .3s; }

/* On narrow screens a horizontal slide-in pushes elements past the viewport
   edge, which widens the document and produces a stray sideways scroll.
   Reveal vertically instead — same effect, no overflow. */
@media (max-width: 900px) {
  html.js [data-reveal="left"],
  html.js [data-reveal="right"] { transform: translate3d(0, 30px, 0); }
}

/* Image mask reveal */
html.js [data-img-reveal] { position: relative; overflow: hidden; }
html.js [data-img-reveal]::after {
  content: ""; position: absolute; inset: 0; z-index: 3;
  background: var(--grad-brand);
  transform-origin: right;
  transition: transform 1.1s var(--ease-inout);
}
html.js [data-img-reveal].is-in::after { transform: scaleX(0); }

/* Counter shimmer while animating */
.counting {
  background: linear-gradient(100deg, var(--navy) 30%, var(--teal-400) 50%, var(--navy) 70%);
  background-size: 200% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: shimmer 1.6s linear infinite;
}

/* ---------- ANIMATED ICON SYSTEM ----------
   Every icon is a hand-built SVG (no generic icon font). Strokes draw
   themselves in on reveal, and accent parts animate on hover. */
.ic { display: block; overflow: visible; }
.ic path, .ic circle, .ic ellipse, .ic line, .ic polyline, .ic rect, .ic polygon {
  vector-effect: non-scaling-stroke;
}

/* draw-in: paths animate their dash offset when the parent enters view */
html.js .ic--draw [data-draw] {
  stroke-dasharray: var(--len, 260);
  stroke-dashoffset: var(--len, 260);
}
html.js .is-in .ic--draw [data-draw],
html.js .ic--draw.is-in [data-draw] {
  animation: drawStroke 1.5s var(--ease-out) forwards;
}
html.js .is-in .ic--draw [data-draw]:nth-child(2) { animation-delay: .12s; }
html.js .is-in .ic--draw [data-draw]:nth-child(3) { animation-delay: .24s; }
html.js .is-in .ic--draw [data-draw]:nth-child(4) { animation-delay: .36s; }

/* hover behaviours, driven by the container */
.ic [data-spark] { transform-origin: center; opacity: 0; }
.svc:hover .ic [data-spark],
.step:hover .ic [data-spark],
.flow-card:hover .ic [data-spark],
.mega__item:hover .ic [data-spark] { animation: toothSparkle 1.5s var(--ease-inout) infinite; }
.ic [data-spark]:nth-of-type(2) { animation-delay: .35s !important; }
.ic [data-spark]:nth-of-type(3) { animation-delay: .7s !important; }

.ic [data-pulse] { transform-origin: center; transform-box: fill-box; }
.svc:hover .ic [data-pulse],
.stat:hover .ic [data-pulse],
.tech__cell:hover .ic [data-pulse] { animation: breathe 1.7s var(--ease-inout) infinite; }

.ic [data-ecg] { stroke-dasharray: 30 370; }
.svc:hover .ic [data-ecg],
.tech__cell:hover .ic [data-ecg] { animation: ecgPulse 2.6s linear infinite; }

.ic [data-lift] { transition: transform .55s var(--ease-spring); }
.svc:hover .ic [data-lift],
.mega__item:hover .ic [data-lift] { transform: translateY(-2.4px); }

.ic [data-rot] { transform-origin: center; transform-box: fill-box; transition: transform .7s var(--ease-spring); }
.svc:hover .ic [data-rot],
.step:hover .ic [data-rot] { transform: rotate(22deg); }

/* Scroll-driven icon spin used on the workflow rail */
.ic--scroll-spin { transition: transform .1s linear; }

/* ---------- MOTION PREFERENCES ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  html.js [data-reveal],
  html.js [data-stagger] > *,
  html.js .split-line > span {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    clip-path: none !important;
  }
  html.js [data-img-reveal]::after { display: none; }
  /* Without this the strokes would sit at full dash offset — i.e. invisible. */
  html.js .ic--draw [data-draw] {
    stroke-dasharray: none !important;
    stroke-dashoffset: 0 !important;
  }
  .hero__mesh, .stage__ring, .stage__glow, .band__scan, .float, .float--sm { animation: none !important; }
  .marquee--css .marquee__track { animation: none !important; }
}

/* ---------- PRINT ----------
   Scroll-reveal leaves elements at opacity 0 until they enter the viewport,
   which would print entire sections blank. Force everything visible on paper. */
@media print {
  html.js [data-reveal],
  html.js [data-stagger] > *,
  html.js .split-line > span,
  html.js .ic--draw [data-draw] {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    clip-path: none !important;
    stroke-dashoffset: 0 !important;
  }
  html.js [data-img-reveal]::after { display: none !important; }
  .loader, .cursor, .cursor-dot, .noise, .fab-stack, .drawer { display: none !important; }
  .nav { position: static !important; }
  .hero { min-height: auto !important; }
  .media img, .svc__bg img { opacity: 1 !important; transform: none !important; }
}
