"use client"; /** Confetti helper that respects prefers-reduced-motion. */ export function prefersReducedMotion(): boolean { if (typeof window === "undefined" || !window.matchMedia) return false; return window.matchMedia("(prefers-reduced-motion: reduce)").matches; } export async function celebrate(intensity: "normal" | "big" = "normal"): Promise { if (prefersReducedMotion()) return; try { const confetti = (await import("canvas-confetti")).default; // Muted, low-saturation palette to match the calmer design. const colors = ["#aac6da", "#7ea6c2", "#5c88a8", "#e4e9f0", "#ffffff", "#cfd8e3"]; const count = intensity === "big" ? 130 : 60; confetti({ particleCount: count, spread: intensity === "big" ? 110 : 75, startVelocity: intensity === "big" ? 48 : 38, origin: { y: 0.65 }, colors, scalar: 0.95, disableForReducedMotion: true, }); if (intensity === "big") { setTimeout(() => { confetti({ particleCount: 45, angle: 60, spread: 55, origin: { x: 0, y: 0.75 }, colors }); confetti({ particleCount: 45, angle: 120, spread: 55, origin: { x: 1, y: 0.75 }, colors }); }, 180); } } catch { /* confetti is a nice-to-have */ } } export function burstAt(x: number, y: number): void { if (prefersReducedMotion()) return; void (async () => { try { const confetti = (await import("canvas-confetti")).default; confetti({ particleCount: 40, spread: 55, startVelocity: 26, origin: { x: x / window.innerWidth, y: y / window.innerHeight }, colors: ["#7ea6c2", "#aac6da", "#cfd8e3", "#ffffff"], disableForReducedMotion: true, }); } catch { /* ignore */ } })(); }