diff --git a/apps/web/src/app/globals.css b/apps/web/src/app/globals.css index 24b8456..86c13e0 100644 --- a/apps/web/src/app/globals.css +++ b/apps/web/src/app/globals.css @@ -234,6 +234,11 @@ @keyframes splash-zoom { 0% { transform: scale(1); } 50% { transform: scale(1.06); } 100% { transform: scale(1.14); } } .splash-zoom { animation: splash-zoom 0.8s ease-in-out forwards; } +/* Click-to-enter Cherenkov wash (was framer-motion; now CSS so the splash ships no + JS animation library). */ +@keyframes splash-wash { 0% { opacity: 0; } 50% { opacity: 0.9; } 100% { opacity: 0; } } +.splash-wash { animation: splash-wash 0.8s ease-in-out forwards; } + /* Tiny terminal inside the nebula monitor: type "such" once, backspace, then a blinking caret on the left. width via steps() is the typewriter; border-right is the caret. */ .nebula-term { @@ -247,10 +252,12 @@ border-right: 1.5px solid currentColor; /* type "such", hold, backspace (nebula-type, once); blink a finite number of times (nebula-caret); then fade the whole thing out so it stops being distracting. */ + /* blink ~7 times first (so you catch it even when the splash is skipped on refresh), + then type "such", hold, backspace, blink a few more, and fade away. */ animation: - nebula-type 3s steps(4, end) forwards, - nebula-caret 0.8s steps(1, end) 10, - nebula-term-out 0.6s ease-in 7.4s forwards; + nebula-type 3s steps(4, end) 5.6s forwards, + nebula-caret 0.8s steps(1, end) 17, + nebula-term-out 0.6s ease-in 13s forwards; } @keyframes nebula-type { 0% { width: 0; } diff --git a/apps/web/src/components/landing/hero-splash.tsx b/apps/web/src/components/landing/hero-splash.tsx index 9ef31f4..ecc1451 100644 --- a/apps/web/src/components/landing/hero-splash.tsx +++ b/apps/web/src/components/landing/hero-splash.tsx @@ -1,7 +1,6 @@ "use client"; import Link from "next/link"; -import { motion, useReducedMotion } from "framer-motion"; import { ChevronDown, LayoutGrid, Smartphone, Wrench, Info } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { SPLASH_LOGO_SRC } from "./splash-logo-data"; @@ -19,7 +18,6 @@ const navButtons = [ // tagline text is hidden, leaving the logo as the only large element). export function HeroSplash({ onEnter, sectionRef, leaving }: { onEnter: () => void; sectionRef?: any; leaving?: boolean }) { - const prefersReduced = useReducedMotion(); const [entering, setEntering] = useState(false); const [fadeOut, setFadeOut] = useState(false); const dispRef = useRef(null); @@ -35,7 +33,7 @@ export function HeroSplash({ onEnter, sectionRef, leaving }: { onEnter: () => vo const handleEnter = () => { if (entering) return; - if (prefersReduced) { + if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) { onEnter(); return; } @@ -75,13 +73,10 @@ export function HeroSplash({ onEnter, sectionRef, leaving }: { onEnter: () => vo {/* Click-to-enter: soft Cherenkov wash. The ripple itself is the SVG water filter refracting the logo (driven by handleEnter's rAF loop). */} {entering && ( -