/* ==========================================================================
   Digiradix — motion layer.
   Loaded after style.css. Holds every @keyframes plus the animation utility
   classes and the richer hover/scroll treatments. Split out from style.css so
   the base design system stays readable and this can be dropped or swapped
   wholesale without touching component styles.

   Everything here is transform/opacity/filter driven (compositor-friendly) and
   the whole file is disabled by the prefers-reduced-motion block at the bottom.
   ========================================================================== */

/* ---- Keyframe library --------------------------------------------------- */
@keyframes fade-up      { from { opacity:0; transform:translateY(28px); } to { opacity:1; transform:none; } }
@keyframes fade-in      { from { opacity:0; } to { opacity:1; } }
@keyframes scale-in     { from { opacity:0; transform:scale(.9); }  to { opacity:1; transform:none; } }
@keyframes slide-left   { from { opacity:0; transform:translateX(40px); } to { opacity:1; transform:none; } }
@keyframes slide-right  { from { opacity:0; transform:translateX(-40px); } to { opacity:1; transform:none; } }

@keyframes float-y      { 0%,100% { transform:translateY(0); }      50% { transform:translateY(-14px); } }
@keyframes float-x      { 0%,100% { transform:translate(0,0); }     50% { transform:translate(12px,-10px); } }
@keyframes pulse-ring   { 0% { transform:scale(.9); opacity:.7; }   70% { transform:scale(1.6); opacity:0; } 100% { opacity:0; } }
@keyframes spin-slow    { to { transform:rotate(360deg); } }
@keyframes orbit        { from { transform:rotate(0deg); } to { transform:rotate(360deg); } }
@keyframes gradient-drift { 0%,100% { background-position:0% 50%; } 50% { background-position:100% 50%; } }
@keyframes shimmer      { 0% { transform:translateX(-100%); } 100% { transform:translateX(200%); } }
@keyframes marquee      { from { transform:translateX(0); } to { transform:translateX(-50%); } }
@keyframes blink-caret  { 0%,100% { opacity:1; } 50% { opacity:0; } }
@keyframes bob          { 0%,100% { transform:translateY(0); } 50% { transform:translateY(-5px); } }
@keyframes draw-line    { from { transform:scaleX(0); } to { transform:scaleX(1); } }
@keyframes rise-fade    { from { opacity:0; transform:translateY(14px) scale(.97); } to { opacity:1; transform:none; } }

/* ---- Entrance utilities -------------------------------------------------- */
.anim-fade-up   { animation:fade-up   var(--dur-reveal) var(--ease-out) both; }
.anim-fade-in   { animation:fade-in   var(--dur-slower) var(--ease-out) both; }
.anim-scale-in  { animation:scale-in  var(--dur-slower) var(--ease-spring) both; }
.anim-float     { animation:float-y   7s  ease-in-out infinite; }
.anim-float-slow{ animation:float-x   11s ease-in-out infinite; }
.anim-spin-slow { animation:spin-slow 28s linear infinite; }

/* Hero entrance chain — each element declares its own beat via --d. */
.hero-in { animation:rise-fade var(--dur-reveal) var(--ease-out) both; animation-delay:var(--d,0ms); }

/* ---- Ambient hero backdrop ---------------------------------------------- */
/* Two blurred colour orbs drifting behind the hero, plus a fine grain overlay.
   Injected by motion.js so no page markup changes were needed. */
.hero-aura { position:relative; isolation:isolate; overflow:hidden; }
.hero-aura > .aura {
  position:absolute; z-index:-2; border-radius:50%;
  filter:blur(80px); opacity:.5; pointer-events:none;
}
.hero-aura > .aura-1 {
  width:44vw; height:44vw; max-width:620px; max-height:620px;
  top:-18%; right:-10%;
  background:radial-gradient(circle, rgba(29,78,216,.40), transparent 68%);
  animation:float-x 16s ease-in-out infinite;
}
.hero-aura > .aura-2 {
  width:38vw; height:38vw; max-width:520px; max-height:520px;
  bottom:-24%; left:-12%;
  background:radial-gradient(circle, rgba(245,158,11,.34), transparent 68%);
  animation:float-y 20s ease-in-out infinite;
}
.hero-aura > .aura-3 {
  width:26vw; height:26vw; max-width:360px; max-height:360px;
  top:38%; left:44%;
  background:radial-gradient(circle, rgba(13,148,136,.20), transparent 68%);
  animation:float-x 24s ease-in-out infinite reverse;
}
/* ---- Abstract line art (injected by motion.js) --------------------------
   Sweeping curves, concentric arcs and straight rules in the brand colours.
   The curves draw themselves in via stroke-dashoffset; the whole layer then
   drifts very slowly so the hero never looks completely static. */
.hero-lines {
  position:absolute; inset:0; z-index:-2;
  width:100%; height:100%; pointer-events:none;
  animation:float-x 30s ease-in-out infinite;
}
.hl-curve, .hl-ring, .hl-rule { fill:none; vector-effect:non-scaling-stroke; }
.hl-curve { stroke:rgba(29,78,216,.28); stroke-width:1.5; }
.hl-ring  { stroke:rgba(29,78,216,.14); stroke-width:1; }
.hl-rule  { stroke:rgba(29,78,216,.10); stroke-width:1; }
.hl-warm  { stroke:rgba(245,158,11,.34); }

/* Curves draw in. The dash length is a generous constant rather than a
   measured pathLength — it only needs to exceed the longest path. */
@keyframes draw-stroke { from { stroke-dashoffset:3200; } to { stroke-dashoffset:0; } }
.hl-curve {
  stroke-dasharray:3200; stroke-dashoffset:3200;
  animation:draw-stroke 3s var(--ease-out) forwards;
}
.hl-c0 { animation-delay:.20s; }
.hl-c1 { animation-delay:.45s; }
.hl-c2 { animation-delay:.70s; }

/* Rings fade up and breathe. */
@keyframes ring-in { from { opacity:0; transform:scale(.82); } to { opacity:1; transform:none; } }
.hl-ring {
  transform-box:fill-box; transform-origin:center;
  opacity:0; animation:ring-in 1.6s var(--ease-out) forwards;
}
.hl-ring:nth-of-type(2n) { animation-delay:.5s; }
.hl-ring:nth-of-type(3n) { animation-delay:.8s; }
.hl-rule { opacity:0; animation:fade-in 2s var(--ease-out) .9s forwards; }

/* Dark bands need brighter strokes to register at all. */
.on-dark .hl-curve, .bg-dark .hl-curve { stroke:rgba(147,197,253,.34); }
.on-dark .hl-ring,  .bg-dark .hl-ring  { stroke:rgba(147,197,253,.18); }
.on-dark .hl-rule,  .bg-dark .hl-rule  { stroke:rgba(147,197,253,.12); }
.on-dark .hl-warm,  .bg-dark .hl-warm  { stroke:rgba(245,158,11,.42); }

/* Imageless hero gets real vertical presence so the backdrop can breathe.
   The container is a column so the trust bar can sit at the foot of the hero
   while the headline block stays optically centred above it. */
.hero-feature { display:flex; align-items:center; min-height:min(80vh, 760px); }
.hero-feature > .container { width:100%; }

/* Trust band: its own section between the hero and the page body. */
.trust-band .trust-label { color:var(--color-ink-muted); }

/* Grain: a tiny inline SVG turbulence, tiled. Adds the "printed" texture that
   keeps large flat light areas from looking cheap. */
.grain::after {
  content:''; position:absolute; inset:0; z-index:-1; pointer-events:none;
  opacity:.032; mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---- Gradient / animated text ------------------------------------------- */
.text-gradient {
  background:var(--gradient-text); background-size:200% auto;
  -webkit-background-clip:text; background-clip:text; color:transparent;
  animation:gradient-drift 8s var(--ease-smooth) infinite;
}

/* Eyebrow gets a rule that draws itself in when revealed. */
.eyebrow { position:relative; }
.eyebrow::after {
  content:''; position:absolute; left:0; bottom:-6px; height:2px; width:100%;
  background:currentColor; opacity:.35; border-radius:2px;
  transform:scaleX(0); transform-origin:left;
  transition:transform var(--dur-slower) var(--ease-out) 120ms;
}
.is-in .eyebrow::after, .eyebrow.is-in::after { transform:scaleX(1); }

/* ---- Underline sweep for prose links ------------------------------------ */
.prose a, .link-underline {
  position:relative; box-shadow:none;
  background-image:linear-gradient(var(--color-accent), var(--color-accent));
  background-size:0% 2px; background-position:0 100%; background-repeat:no-repeat;
  transition:background-size var(--dur-slow) var(--ease-out), color var(--dur) var(--ease);
}
.prose a:hover, .link-underline:hover { background-size:100% 2px; color:var(--color-accent); }

/* ---- Nav / dropdown ------------------------------------------------------ */
.dropdown { transform:translateX(-50%) translateY(10px) scale(.98); }
.nav-item:hover .dropdown, .nav-item:focus-within .dropdown {
  transform:translateX(-50%) translateY(6px) scale(1);
  transition:opacity var(--dur) var(--ease), transform var(--dur-slow) var(--ease-spring), visibility var(--dur);
}
/* Each mega-menu column fades up in sequence while the panel opens. */
.dropdown-mega .dd-service { opacity:0; transform:translateY(10px); transition:opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out); }
.nav-item:hover .dropdown-mega .dd-service,
.nav-item:focus-within .dropdown-mega .dd-service { opacity:1; transform:none; }
.dropdown-mega .dd-service:nth-child(1) { transition-delay:40ms; }
.dropdown-mega .dd-service:nth-child(2) { transition-delay:80ms; }
.dropdown-mega .dd-service:nth-child(3) { transition-delay:120ms; }
.dropdown-mega .dd-service:nth-child(4) { transition-delay:160ms; }
.dropdown-mega .dd-service:nth-child(5) { transition-delay:200ms; }
.dropdown-mega .dd-subs a { transition:background var(--dur) var(--ease), color var(--dur) var(--ease), transform var(--dur) var(--ease-out); }
.dropdown-mega .dd-subs a:hover { transform:translateX(4px); }

/* Mobile nav links cascade in when the panel opens. */
.mobile-nav.is-open .mobile-nav-links > * { animation:slide-left var(--dur-slow) var(--ease-out) both; }
.mobile-nav.is-open .mobile-nav-links > *:nth-child(1) { animation-delay:60ms; }
.mobile-nav.is-open .mobile-nav-links > *:nth-child(2) { animation-delay:100ms; }
.mobile-nav.is-open .mobile-nav-links > *:nth-child(3) { animation-delay:140ms; }
.mobile-nav.is-open .mobile-nav-links > *:nth-child(4) { animation-delay:180ms; }
.mobile-nav.is-open .mobile-nav-links > *:nth-child(5) { animation-delay:220ms; }
.mobile-nav.is-open .mobile-nav-links > *:nth-child(n+6) { animation-delay:260ms; }

/* ---- Cards / lists ------------------------------------------------------- */
/* Whole-card link wrappers get the same lift as .card. */
a.card { display:block; }
a.card:hover .link-arrow svg { transform:translateX(5px); }

/* Check-list ticks pop in one after another. */
.check-list li { transition:transform var(--dur) var(--ease-out); }
.check-list li:hover { transform:translateX(4px); }
.is-in .check-list .tick { animation:scale-in var(--dur-slow) var(--ease-spring) both; }
.is-in .check-list li:nth-child(1) .tick { animation-delay:60ms; }
.is-in .check-list li:nth-child(2) .tick { animation-delay:120ms; }
.is-in .check-list li:nth-child(3) .tick { animation-delay:180ms; }
.is-in .check-list li:nth-child(4) .tick { animation-delay:240ms; }
.is-in .check-list li:nth-child(5) .tick { animation-delay:300ms; }
.is-in .check-list li:nth-child(n+6) .tick { animation-delay:360ms; }

/* Numerals: solid; subtle lift on card hover. */
.numeral { transition:color var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease-spring); }
.card:hover .numeral { color:var(--color-accent-hover); transform:translateY(-2px); }

/* Pills lift slightly. */
.pill { transition:transform var(--dur) var(--ease-spring), box-shadow var(--dur) var(--ease); }
.pill:hover { transform:translateY(-1px); box-shadow:var(--shadow-sm); }

/* ---- Image placeholders: shimmer sweep ---------------------------------- */
.img-ph { position:relative; overflow:hidden; transition:transform var(--dur-slow) var(--ease-out), box-shadow var(--dur-slow) var(--ease); }
.img-ph::after {
  content:''; position:absolute; top:0; bottom:0; left:0; width:60%;
  background:linear-gradient(100deg, transparent, rgba(255,255,255,.6), transparent);
  animation:shimmer 3.4s var(--ease-smooth) infinite; pointer-events:none;
}
/* Real artwork gets the same hover zoom as the placeholder it replaced. The
   scale is clipped by .card-flush's overflow:hidden, so the image grows inside
   the card frame rather than past it. */
.img-media { transition:transform var(--dur-slow) var(--ease-out); }
.card:hover .img-ph,
.card:hover .img-media { transform:scale(1.02); }

/* ---- Trust bar marquee --------------------------------------------------- */
/* width/min-width guard: the track inside is `width:max-content`, so without
   these the marquee blows out any flex or grid parent it sits in. */
.marquee { overflow:hidden; width:100%; min-width:0; max-width:100%;
           -webkit-mask-image:linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
           mask-image:linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent); }
.logo-row { min-width:0; max-width:100%; }
.marquee-track { display:flex; width:max-content; gap:var(--space-8); animation:marquee 34s linear infinite; }
.marquee:hover .marquee-track { animation-play-state:paused; }

/* ---- Feature grid entrance ----------------------------------------------
   The chip pops in as its item reveals. Deliberately NO animation-fill-mode:
   a filled animation keeps applying its final transform and would then beat
   the .feature:hover transform, killing the hover state. Without fill the
   element simply returns to its base rule when the animation ends. */
@keyframes chip-pop { from { transform:scale(.8); opacity:0; } to { transform:none; opacity:1; } }
.feature.is-in .icon-chip { animation:chip-pop var(--dur-slow) var(--ease-spring); animation-delay:var(--d,0ms); }

/* ---- Stat counters ------------------------------------------------------- */
.stat-num { transition:transform var(--dur-slow) var(--ease-spring); display:inline-block; }
.stat-num:hover { transform:translateY(-3px); }

/* ---- FAQ ----------------------------------------------------------------- */
.faq details { transition:background var(--dur) var(--ease); }
.faq summary { transition:color var(--dur) var(--ease), padding-left var(--dur) var(--ease-out); }
.faq summary:hover { color:var(--color-accent); padding-left:var(--space-2); }
.faq details[open] .faq-body { animation:fade-up var(--dur-slow) var(--ease-out) both; }
.faq summary .marker { transition:transform var(--dur-slow) var(--ease-spring); }
.faq details[open] summary .marker { transform:rotate(180deg); }

/* ---- Footer -------------------------------------------------------------- */
.footer-col a { display:inline-block; transition:color var(--dur) var(--ease), transform var(--dur) var(--ease-out); }
.footer-col a:hover { transform:translateX(4px); }

/* ---- WhatsApp float: breathing pulse ring ------------------------------- */
.wa-float { animation:bob 3.2s ease-in-out infinite; }
.wa-float::after {
  content:''; position:absolute; inset:0; border-radius:inherit;
  border:2px solid var(--color-teal); animation:pulse-ring 2.6s var(--ease-out) infinite;
}
.wa-float:hover { transform:translateY(-3px) scale(1.06); box-shadow:var(--glow-teal); }

/* ---- Magnetic buttons (offset set by motion.js) -------------------------- */
.magnetic { transition:transform var(--dur-slow) var(--ease-spring); }
.magnetic.is-pulled { transition:transform 120ms var(--ease-out); }

/* Sections are separated by their background colour alone — no divider rules.
   (An earlier hairline `.band-line::before` was removed: bands already differ
   in background, so the extra line just cut the page into visible strips.)
   `is-in` is still applied to every <section> by motion.js — it drives the
   eyebrow underline and check-list tick animations, so keep that observer. */

/* ---- Reduced motion: kill everything ------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *,*::before,*::after {
    animation:none!important;
    transition-duration:.01ms!important;
    scroll-behavior:auto!important;
  }
  .reveal, .hero-in, .split-word > span { opacity:1!important; transform:none!important; filter:none!important; }
  .hero-aura > .aura, .grain::after, .img-ph::after, .wa-float::after { display:none!important; }
  /* Keep the line art visible but static — it is the hero's only visual now,
     so hiding it would leave an empty band. Just stop it moving/drawing. */
  .hl-curve { stroke-dasharray:none!important; stroke-dashoffset:0!important; }
  .hl-ring, .hl-rule { opacity:1!important; transform:none!important; }
  .hero-lines { animation:none!important; }
  .dropdown-mega .dd-service { opacity:1!important; transform:none!important; }
  .marquee-track { animation:none!important; }
}
