"use client"; import { useId, type ReactNode } from "react"; import { motion, useReducedMotion } from "motion/react"; type LiquidCanvasProps = { children?: ReactNode; className?: string; /** Blobs alternate between these two colours. */ colors?: [string, string]; background?: string; /** 1 is the default pace; 2 is twice as fast. */ speed?: number; }; // Position (%), size (px), path (px) and seconds per loop of each blob. const BLOBS = [ { left: 15, top: 25, size: 130, x: [0, 90, 30, 0], y: [0, 40, -30, 0], d: 13 }, { left: 55, top: 15, size: 110, x: [0, -70, 20, 0], y: [0, 60, 90, 0], d: 11 }, { left: 35, top: 55, size: 150, x: [0, 60, -50, 0], y: [0, -50, 10, 0], d: 15 }, { left: 70, top: 55, size: 100, x: [0, -90, -30, 0], y: [0, -30, 40, 0], d: 12 }, { left: 5, top: 65, size: 90, x: [0, 70, 120, 0], y: [0, -60, 10, 0], d: 14 }, { left: 80, top: 20, size: 80, x: [0, -40, -110, 0], y: [0, 70, 20, 0], d: 10 }, ]; /* LiquidCanvas: colour blobs drift and melt into each other like liquid, using an SVG goo filter. */ export function LiquidCanvas({ children, className = "", colors = ["#a78bfa", "#f472b6"], background = "#08070f", speed = 1, }: LiquidCanvasProps) { const reduce = useReducedMotion(); const filterId = `goo-${useId().replace(/[^a-zA-Z0-9-]/g, "")}`; return (