/* =============================================================================
   FUTURISTIC EFFECTS LAYER
   Cross-cutting utility classes driven by js/effects.js: magnetic pull,
   3D tilt, glitch-text, scanline texture, holographic hover accents, scroll
   parallax. Loads LAST so it can safely layer on top of every component/
   section above without specificity fights.
   Depends on: tokens.css, base/motion.css (glitch-shift-1/2, scanline-drift,
   holographic-sweep keyframes).
   ============================================================================= */

/* --- Magnetic buttons -------------------------------------------------------
   Wraps a .btn so the pull transform lives on a separate element and never
   fights the button's own :hover transform (translateY). -------------------- */
.magnetic {
  display: inline-block;
  transform: translate3d(var(--magnet-x, 0px), var(--magnet-y, 0px), 0);
  transition: transform var(--transition-magnetic);
}

.magnetic.is-tracking {
  transition: none;
}

/* --- 3D tilt wrappers ---------------------------------------------------------
   Each [data-tilt] element is a dedicated wrapper placed AROUND an existing
   component root, so the rotate transform never collides with that
   component's own hover-lift or idle-float animation. ------------------------ */
[data-tilt] {
  transform: perspective(900px) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
  transition: transform var(--transition-tilt);
  will-change: transform;
}

/* Below 1280px the services diagram collapses to a stacked list (see
   services.css) and .services__node-float becomes display:contents — this
   wrapper must do the same so it doesn't introduce an extra box into that
   layout. */
@media (max-width: 1279px) {
  .services__node-tilt {
    display: contents;
  }
}

/* .workflow__card is normally a direct flex child of .workflow (flex: 1);
   wrapping it means the wrapper must carry that same flex sizing instead. */
.workflow__card-tilt {
  flex: 1;
  min-width: 0;
}

/* --- Glitch heading effect -----------------------------------------------------
   RGB-channel-split via two pseudo-elements sharing the real text through
   data-text (populated by effects.js at init from the element's own text
   content, so it can never drift out of sync with hand-edited copy). One-
   shot jitter on hover/focus only — not a looping animation. ----------------- */
.glitch-text {
  position: relative;
  display: inline-block;
}

.glitch-text::before,
.glitch-text::after {
  content: attr(data-text);
  position: absolute;
  inset: 0;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

.glitch-text::before {
  color: var(--color-glow-strong);
  clip-path: inset(0 0 55% 0);
}

.glitch-text::after {
  color: var(--color-accent-strong);
  clip-path: inset(55% 0 0 0);
}

.glitch-text:hover::before,
.glitch-text:focus-visible::before {
  opacity: 0.85;
  animation: glitch-shift-1 0.35s steps(2, end) 1;
}

.glitch-text:hover::after,
.glitch-text:focus-visible::after {
  opacity: 0.85;
  animation: glitch-shift-2 0.35s steps(2, end) 1;
}

/* --- Scanline texture -----------------------------------------------------------
   Subtle repeating-line overlay, opt-in via .has-scanline, on two already-
   positioned containers — no extra DOM needed. Frozen to a static frame
   under prefers-reduced-motion by the existing global animation killswitch
   in motion.css (animation-duration: 0.01ms !important). --------------------- */
.hero__visual.has-scanline::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-size: 100% 4px;
  background-image: repeating-linear-gradient(0deg, var(--color-scanline) 0px, transparent 1px, transparent 3px);
  animation: scanline-drift 6s linear infinite;
}

.platform__panel.has-scanline::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background-size: 100% 4px;
  background-image: repeating-linear-gradient(0deg, oklch(74% 0.17 210 / 0.06) 0px, transparent 1px, transparent 3px);
  animation: scanline-drift 6s linear infinite;
}

/* --- Holographic hover accent ---------------------------------------------------
   A top-edge gradient stripe (mirrors the existing pattern already used by
   .ai-assistant__panel::before) rather than a border-image trick, so it
   never touches either panel's own border-color/background transitions. ----- */
.platform__panel::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  background: var(--gradient-holographic);
  background-size: 200% 100%;
  opacity: 0.55;
  pointer-events: none;
}

.services__node::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background: var(--gradient-holographic);
  background-size: 200% 100%;
  opacity: 0.5;
  pointer-events: none;
}

.platform__panel:hover::before,
.platform__panel:focus-within::before,
.services__node:hover::before,
.services__node:focus-within::before {
  opacity: 1;
  animation: holographic-sweep 2.5s linear infinite;
}

/* --- Scroll parallax -------------------------------------------------------------
   Only ever applied (see index.html) to elements free of any competing
   transform — e.g. never the how-it-works dots, which already animate their
   own transform via float-a/float-b. ------------------------------------------ */
[data-parallax] {
  transform: translate3d(0, var(--parallax-y, 0px), 0);
}
