/* ==========================================================================
   Blue Lily micro-interactions — every page.

     cursor glow      a soft pool of blue light that follows the pointer
     buttons          magnetic pull, a liquid glow that tracks the pointer
                      inside the button, a ripple on press
     icons            line icons draw themselves in (home sections)
     dividers         a flowing line of light between light sections (home)
     counters         true counts, counted up once, with a progress wave

   Desktop pointer effects are switched on by js/micro.js only when the
   device has a fine pointer and motion is not reduced; without it, none of
   this changes how a page looks or works.
   ========================================================================== */

/* ------------------------------------------------------- cursor glow --- */
.cursor-glow {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 95;               /* over content, under the header (100) */
  width: 420px;
  height: 420px;
  margin: -210px 0 0 -210px;
  border-radius: 50%;
  pointer-events: none;
  /* Deliberately faint: over white it is a tint, over navy a glow. Its peak
     alpha keeps every text colour on the site well inside its contrast
     margin. */
  background: radial-gradient(closest-side, rgba(77, 168, 255, .09), rgba(139, 92, 246, .04) 55%, transparent);
  opacity: 0;
  transition: opacity .6s ease;
  will-change: transform;
}
.cursor-glow.is-on { opacity: 1; }

/* ----------------------------------------------------------- buttons --- */
/* Liquid glow: a light that sits where the pointer is inside the button.
   The two custom properties are written on the button alone, so only the
   button and its own pseudo-elements restyle. */
.btn.is-magnetic::after {
  content: '';
  position: absolute;
  z-index: 0;
  left: var(--mx, 50%);
  top: var(--my, 50%);
  width: 140%;
  aspect-ratio: 1;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  background: radial-gradient(closest-side, rgba(255, 255, 255, .26), transparent);
  opacity: 0;
  transition: opacity .35s ease;
  pointer-events: none;
}
.btn.is-magnetic:hover::after { opacity: 1; }
/* the magnetic pull uses `translate`, so it composes with any transform a
   button already carries instead of replacing it */
.btn.is-magnetic { transition-property: translate, box-shadow, background-color, border-color, color; transition-duration: .35s; }

.btn-ripple {
  position: absolute;
  z-index: 0;
  width: 12px;
  height: 12px;
  margin: -6px 0 0 -6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .45);
  pointer-events: none;
  animation: btn-ripple .65s cubic-bezier(.22, .61, .36, 1) forwards;
}
/* on light, outlined buttons a white ripple would vanish */
.btn--secondary .btn-ripple, .v2-btn--secondary .btn-ripple, .btn--ghost .btn-ripple {
  background: rgba(37, 99, 235, .22);
}
@keyframes btn-ripple {
  from { transform: scale(1); opacity: 1; }
  to   { transform: scale(26); opacity: 0; }
}

/* ------------------------------------------------------ icons draw --- */
/* micro.js sets pathLength="1" on each shape of a marked icon and adds
   .draw-ready; the stroke then draws when its section is revealed. Without
   the script the icon is simply drawn. */
.draw-ready :is(path, circle, rect, line, polyline) {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 1.1s cubic-bezier(.65, 0, .35, 1) var(--draw-delay, 0s);
}
.v2-group.is-in .draw-ready :is(path, circle, rect, line, polyline),
.draw-ready.is-drawn :is(path, circle, rect, line, polyline) { stroke-dashoffset: 0; }
/* a small pulse when a card that holds an icon is hovered */
@media (hover: hover) {
  :is(.v2-ai-card, .v2-stage, .v2-step):hover :is(.v2-ai-card__icon, .v2-stage__icon, .v2-step__bloom) svg {
    animation: icon-pulse .7s ease;
  }
}
@keyframes icon-pulse {
  40% { transform: scale(1.14); }
  100% { transform: scale(1); }
}

/* ---------------------------------------------------- flowing divider --- */
/* Light sections that meet another light section share a flowing line of
   light instead of a plain border. The highlight is a transform on a
   pseudo-element, so it costs nothing to run. */
.v2:is(.v2--warm, .v2--white, .v2--mist, .v2--blue)::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 0;
  z-index: 1;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(37, 99, 235, .18) 20%,
                              rgba(139, 92, 246, .16) 80%, transparent);
  pointer-events: none;
}
.v2:is(.v2--warm, .v2--white, .v2--mist, .v2--blue)::after {
  content: '';
  position: absolute;
  left: 0; top: -1px;
  z-index: 1;
  width: 28%;
  height: 3px;
  border-radius: 3px;
  background: linear-gradient(90deg, transparent, rgba(77, 168, 255, .7), rgba(139, 92, 246, .5), transparent);
  pointer-events: none;
  animation: divider-flow 9s cubic-bezier(.45, 0, .55, 1) infinite;
}
@keyframes divider-flow {
  from { transform: translate3d(-100%, 0, 0); }
  to   { transform: translate3d(460%, 0, 0); }
}
.js .v2:not(.is-live)::after { animation-play-state: paused; }

/* The hero's facts row gets the same line in place of its border. */
.hf-facts { position: relative; border-top: 0; }
.hf-facts::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: linear-gradient(90deg, rgba(147, 197, 253, .45), rgba(139, 92, 246, .35) 60%, transparent);
}

/* ---------------------------------------------------------- counters --- */
.v2-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-5);
  margin: var(--space-8) 0 0;
  padding: 0;
}
.v2-stats > div { min-width: 0; display: flex; flex-direction: column; }
.v2-stats dt {
  order: 2;
  margin: 0;
  font-size: var(--text-sm);
  line-height: 1.45;
  color: #C9D8EE;
}
.v2-stats dd { margin: 0; }
.v2-stat__num {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.4rem + 2vw, 2.8rem);
  font-weight: 700;
  line-height: 1;
  color: #FFFFFF;
  font-variant-numeric: tabular-nums;
}
.v2-stat__wave { display: block; width: 64px; height: 10px; margin: 8px 0 8px; overflow: visible; }
.v2-stat__wave path {
  fill: none;
  stroke: #4DA8FF;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
}
.js .v2-stat__wave path { stroke-dashoffset: 1; transition: stroke-dashoffset 1.2s ease .9s; }
.js .v2-stats.is-in .v2-stat__wave path { stroke-dashoffset: 0; }

/* ---------------------------------------------------- laptop tier ---- */
/* 1025–1280px: the full composition, a little lighter. */
@media (min-width: 1025px) and (max-width: 1280px) {
  /* the hero's travelling lights are the page's signature motion and stay
     at every width; two circles are not what makes this tier heavy */
  .v2-orbit__petals { display: none; }
  .petal-field--hero .petal:nth-child(n + 11) { display: none; }
  .v2-rise:nth-child(n + 5) { display: none; }
  .cursor-glow { width: 340px; height: 340px; margin: -170px 0 0 -170px; }
}

/* ------------------------------------------------------- responsive --- */
@media (max-width: 1024px) {
  .v2-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (hover: none), (pointer: coarse) {
  .cursor-glow { display: none; }
}

/* --------------------------------------------------- reduced motion --- */
@media (prefers-reduced-motion: reduce) {
  .cursor-glow, .btn-ripple { display: none; }
  .btn.is-magnetic { translate: none !important; }
  .draw-ready :is(path, circle, rect, line, polyline) { stroke-dashoffset: 0 !important; transition: none !important; }
  .v2::after { animation: none !important; display: none; }
  .js .v2-stat__wave path { stroke-dashoffset: 0 !important; transition: none !important; }
}
