/* global React, gsap */ /* eslint-disable */ // Watercolor pink butterflies + flowers + atmosphere // Animations driven entirely by GSAP (ScrollTrigger + timelines) const { useEffect, useMemo, useRef } = React; /* ============================================================ Watercolor butterfly SVG ============================================================ */ function ButterflySVG({ variant = 1, size = 90 }) { const id = useMemo(() => "bf" + Math.random().toString(36).slice(2, 8), []); const palettes = [ { a: "#ffd2e0", b: "#ff9bbf", c: "#e25b8a", d: "#7a2d4a" }, { a: "#ffe1ec", b: "#f8a7c4", c: "#d65a85", d: "#4a1d33" }, { a: "#fbc6da", b: "#e88aae", c: "#b53d6a", d: "#3a1326" }, { a: "#ffeaf2", b: "#f4b0cb", c: "#cf6f95", d: "#5a223c" }, { a: "#f7b8d2", b: "#e87aad", c: "#a93668", d: "#2c0f1d" }, ]; const p = palettes[(variant - 1) % palettes.length]; return ( ); } /* ============================================================ Watercolor flower SVG ============================================================ */ function FlowerSVG({ variant = 1 }) { const id = useMemo(() => "fl" + Math.random().toString(36).slice(2, 8), []); const configs = [ { petals: 6, outerR: 42, innerR: 22, pColor: "#ffd2e0", cColor: "#ff9bbf", stemColor: "#c87890" }, { petals: 5, outerR: 38, innerR: 20, pColor: "#ffe0ec", cColor: "#f8b4cc", stemColor: "#d4809a" }, { petals: 8, outerR: 35, innerR: 18, pColor: "#ffcad8", cColor: "#f09ab8", stemColor: "#b8607a" }, ]; const c = configs[(variant - 1) % configs.length]; const petals = Array.from({ length: c.petals }, (_, i) => { const angle = (i / c.petals) * Math.PI * 2; const cx = Math.cos(angle) * c.innerR * 1.6; const cy = Math.sin(angle) * c.innerR * 1.6; return { cx, cy, angle }; }); return ( ); } /* ============================================================ Static butterflies — entrance with GSAP, gentle float loop ============================================================ */ function StaticButterflies({ items }) { const refs = useRef([]); useEffect(() => { if (typeof gsap === "undefined") return; refs.current.forEach((el, i) => { if (!el) return; const item = items[i]; const delay = item.delay || 0; // Entrance gsap.fromTo(el, { opacity: 0, scale: 0.4, y: 30 }, { opacity: item.opacity ?? 0.92, scale: 1, y: 0, duration: 1.4, delay: delay + 0.3, ease: "back.out(1.4)" } ); // Continuous gentle float gsap.to(el, { y: "random(-14, 14)", x: "random(-8, 8)", rotation: `random(-6, 6)`, duration: "random(3.5, 5.5)", repeat: -1, yoyo: true, ease: "sine.inOut", delay: delay, }); // Wing flutter: animate scaleX of `.wings` children const wings = el.querySelectorAll(".wings"); if (wings.length) { gsap.to(wings, { scaleX: 0.55, duration: 0.32, repeat: -1, yoyo: true, ease: "sine.inOut", stagger: 0.05, transformOrigin: "center center", }); } }); }, [items]); return ( <> {items.map((item, i) => (
(refs.current[i] = el)} style={{ top: item.top, left: item.left, right: item.right, bottom: item.bottom, width: item.size, height: item.size, opacity: 0, transform: `rotate(${item.rot || 0}deg)`, }} >
))} ); } /* ============================================================ Flying butterflies — GSAP-driven sinusoidal flight path ============================================================ */ function FlyingButterflies({ count = 2 }) { const containerRef = useRef(null); useEffect(() => { if (typeof gsap === "undefined") return; const container = containerRef.current; if (!container) return; const elements = container.querySelectorAll(".fly-x"); elements.forEach((el, i) => { const delay = i * 8 + Math.random() * 4; const dur = 22 + Math.random() * 12; const yBase = 5 + Math.random() * 55; // % from top // Reset to start position gsap.set(el, { x: "-12vw", y: `${yBase}vh`, opacity: 0 }); // Flight timeline — cross-screen with sinusoidal vertical drift const tl = gsap.timeline({ repeat: -1, delay }); tl.to(el, { x: "112vw", duration: dur, ease: "none", }); tl.to(el, { opacity: 0.9, duration: 1.2 }, 0); tl.to(el, { opacity: 0, duration: 1.5 }, dur - 1.5); // Sinusoidal vertical wobble layered on top gsap.to(el, { y: `+=${15 + Math.random() * 20}`, duration: dur / 4, repeat: -1, yoyo: true, ease: "sine.inOut", delay, }); // Wing flutter const wings = el.querySelectorAll(".wings"); if (wings.length) { gsap.to(wings, { scaleX: 0.5, duration: 0.28, repeat: -1, yoyo: true, ease: "sine.inOut", stagger: 0.06, transformOrigin: "center center", }); } }); }, [count]); return (
{Array.from({ length: count }, (_, i) => (
))}
); } /* ============================================================ Particles — GSAP stagger float-up ============================================================ */ function Particles({ count = 28 }) { const containerRef = useRef(null); const particles = useMemo(() => { return Array.from({ length: count }, (_, i) => ({ id: i, left: `${Math.random() * 98}%`, size: 3 + Math.random() * 5, delay: Math.random() * 12, dur: 8 + Math.random() * 14, drift: (Math.random() - 0.5) * 60, })); }, [count]); useEffect(() => { if (typeof gsap === "undefined") return; const container = containerRef.current; if (!container) return; const els = container.querySelectorAll(".particle"); els.forEach((el, i) => { const p = particles[i]; if (!p) return; gsap.set(el, { y: 20, opacity: 0 }); gsap.to(el, { y: -(window.innerHeight * 1.1), x: p.drift, opacity: keyframeOpacity, duration: p.dur, delay: p.delay, repeat: -1, ease: "none", onStart() { gsap.set(el, { opacity: 0, y: 20 }); }, onRepeat() { gsap.set(el, { opacity: 0, y: 20, x: (Math.random() - 0.5) * 60 }); }, }); // Fade in and out within the travel gsap.to(el, { keyframes: [ { opacity: 0, duration: 0 }, { opacity: 0.9, duration: p.dur * 0.18 }, { opacity: 0.7, duration: p.dur * 0.64 }, { opacity: 0, duration: p.dur * 0.18 }, ], delay: p.delay, repeat: -1, duration: p.dur, ease: "none", }); }); }, [particles]); return (
{particles.map((p) => (
))}
); } // Dummy ref for opacity — GSAP keyframes object handles it inline const keyframeOpacity = undefined; /* ============================================================ Flowers — GSAP sway ============================================================ */ function Flowers({ items }) { const refs = useRef([]); useEffect(() => { if (typeof gsap === "undefined") return; refs.current.forEach((el, i) => { if (!el) return; const item = items[i]; // Entrance gsap.fromTo(el, { opacity: 0, scale: 0.5, y: 20 }, { opacity: item.opacity ?? 0.85, scale: 1, y: 0, duration: 1.6, delay: (item.delay || 0) + 0.2, ease: "back.out(1.6)" } ); // Gentle sway with GSAP (smoother than CSS keyframe) gsap.to(el, { rotation: 4, duration: 3 + Math.random() * 3, repeat: -1, yoyo: true, ease: "sine.inOut", transformOrigin: "bottom center", delay: item.delay || 0, startAt: { rotation: -4 }, }); }); }, [items]); return ( <> {items.map((item, i) => (
(refs.current[i] = el)} style={{ top: item.top, left: item.left, right: item.right, bottom: item.bottom, width: item.size, height: item.size, opacity: 0, }} >
))} ); }