/* ════════════════════════════════════════════════════════════════════════
   AiXXXart FX layer — additive enhancement styles only.
   Loaded after style.css. Every rule is scoped to .fx-on / .fx-tilt /
   .fx-cards, which fx.js adds only when motion is allowed, so the resting
   look without JS (or with prefers-reduced-motion) is byte-identical.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Hero WebGL nebula canvas ── */
.fx-hero-canvas {
  position: absolute;
  inset: 0;
  z-index: 1;            /* above blurred orbs, below .hero-content (z:2) */
  pointer-events: none;
  opacity: 0.9;
}

/* ── Hero title char spans (split by fx.js) ──
   background-clip:text doesn't paint through transformed child spans, so
   each char carries its own gradient. Per-char negative animation-delay
   (set by fx.js) makes the existing gradient-shift flow across letters. */
.fx-on .hero-title { white-space: nowrap; background: none; animation: none; }
.fx-on .hero-title .fx-ch {
  display: inline-block;
  will-change: transform;
  background: linear-gradient(135deg, var(--accent1) 0%, var(--accent2) 50%, var(--accent3) 100%);
  background-size: 200% auto;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: gradient-shift 4s linear infinite;
}

/* ── Gallery cards ──
   fx.js takes over the entry animation (GSAP batch stagger), and on fine
   pointers it owns the transform for 3D tilt, so transform is removed from
   the CSS transition to keep per-frame updates unsmoothed. */
.fx-cards .gallery-item { animation: none; }

.fx-tilt .gallery-item {
  transition: box-shadow var(--transition), border-color var(--transition);
  will-change: transform;
}

/* Cursor spotlight that follows the mouse across a card */
.fx-tilt .gallery-item::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.35s ease;
  background: radial-gradient(
    460px circle at var(--fx-x, 50%) var(--fx-y, 50%),
    rgba(177, 79, 255, 0.16),
    rgba(79, 216, 255, 0.07) 42%,
    transparent 68%
  );
}
.fx-tilt .gallery-item:hover::after { opacity: 1; }

/* ── Inline elements that GSAP scales need a box ── */
.fx-on .count-badge { display: inline-block; }
.fx-on .star { display: inline-block; }

/* ── CTA shine sweep ── */
.fx-on .cta-btn { position: relative; overflow: hidden; }
.fx-on .cta-btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: -75%;
  width: 50%;
  height: 100%;
  background: linear-gradient(105deg, transparent, rgba(255, 255, 255, 0.35), transparent);
  transform: skewX(-20deg);
  animation: fx-shine 5.5s ease-in-out infinite;
  pointer-events: none;
}
@keyframes fx-shine {
  0%, 72%   { left: -75%; }
  88%, 100% { left: 125%; }
}

/* ── FAB press feedback ──
   `scale` is an individual transform property: it composes with the
   existing transform/animation instead of overriding them. */
.fx-on .fab-upload,
.fx-on .fab-chat,
.fx-on .fab-custom { transition-property: transform, box-shadow, scale; transition-duration: 0.2s, 0.2s, 0.15s; }
.fx-on .fab-upload:active,
.fx-on .fab-chat:active,
.fx-on .fab-custom:active { scale: 0.92; }

/* ── Lightbox ── */
.fx-on .lb-stage { will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  .fx-on .cta-btn::before { animation: none; }
}
