diff --git a/apps/web/src/components/landing/hero-splash.tsx b/apps/web/src/components/landing/hero-splash.tsx index 828eca6..7de8df8 100644 --- a/apps/web/src/components/landing/hero-splash.tsx +++ b/apps/web/src/components/landing/hero-splash.tsx @@ -3,7 +3,7 @@ import Link from "next/link"; import { motion, useReducedMotion } from "framer-motion"; import { ChevronDown, LayoutGrid, Smartphone, Wrench, Info } from "lucide-react"; -import { useState } from "react"; +import { useRef, useState } from "react"; const navButtons = [ { label: "Portfolio", href: "/products", Icon: LayoutGrid, corner: "left-4 top-6 sm:left-6 sm:top-24 lg:left-8 lg:top-32" }, @@ -75,6 +75,8 @@ export function HeroSplash({ onEnter, sectionRef }: { onEnter: () => void; secti const prefersReduced = useReducedMotion(); const animate = !prefersReduced; const [entering, setEntering] = useState(false); + const dispRef = useRef(null); + const turbRef = useRef(null); const handleEnter = () => { if (entering) return; @@ -82,7 +84,24 @@ export function HeroSplash({ onEnter, sectionRef }: { onEnter: () => void; secti onEnter(); return; } - setEntering(true); // the wave plays, then onEnter fires on completion + setEntering(true); + // Real water refraction: ramp the displacement scale up and back down while + // the turbulence drifts, so the logo ripples like a disturbed liquid surface. + const DURATION = 1200; + const MAX_SCALE = 40; + const start = performance.now(); + const tick = (now: number) => { + const t = Math.min(1, (now - start) / DURATION); + const env = Math.sin(Math.PI * t); // 0 -> 1 -> 0 + if (dispRef.current) dispRef.current.setAttribute("scale", String(env * MAX_SCALE)); + if (turbRef.current) { + const f = 0.008 + t * 0.02; + turbRef.current.setAttribute("baseFrequency", `${f.toFixed(4)} ${(f * 1.3).toFixed(4)}`); + } + if (t < 1) requestAnimationFrame(tick); + else onEnter(); + }; + requestAnimationFrame(tick); }; return ( @@ -91,33 +110,27 @@ export function HeroSplash({ onEnter, sectionRef }: { onEnter: () => void; secti aria-label="Such Software" className="relative z-10 flex min-h-[100svh] w-full max-w-7xl flex-col items-center justify-center overflow-hidden px-4 py-12 text-center" > - {/* Click-to-enter Cherenkov wave: a watery blur wash + expanding ripples */} + {/* Click-to-enter: soft Cherenkov wash. The ripple itself is the SVG water + filter refracting the logo (driven by handleEnter's rAF loop). */} {entering && ( - <> -