import { useCallback, useEffect, useRef, useState } from "react"; interface WelcomeSplashProps { onEnter: () => void; } const MATRIX_CHARS = "01アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+[]{};:?/\\|~`"; const prefersReducedMotion = typeof window !== "undefined" ? window.matchMedia("(prefers-reduced-motion: reduce)").matches : false; export default function WelcomeSplash({ onEnter }: WelcomeSplashProps) { const canvasRef = useRef(null); const rafRef = useRef(0); const [showWelcome, setShowWelcome] = useState(true); const [exiting, setExiting] = useState(false); const handleEnter = useCallback(() => { setExiting(true); setTimeout(onEnter, prefersReducedMotion ? 0 : 700); }, [onEnter]); useEffect(() => { const timer = setTimeout(() => setShowWelcome(true), prefersReducedMotion ? 0 : 6000); return () => clearTimeout(timer); }, []); useEffect(() => { if (prefersReducedMotion) { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; canvas.width = window.innerWidth; canvas.height = window.innerHeight; ctx.fillStyle = "rgba(0, 0, 0, 0.85)"; ctx.fillRect(0, 0, canvas.width, canvas.height); return; } const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; let width = window.innerWidth; let height = window.innerHeight; canvas.width = width; canvas.height = height; const fontSize = width > 1200 ? 20 : width > 768 ? 18 : 14; const columns = Math.floor(width / fontSize); const drops: number[] = []; for (let i = 0; i < columns; i++) { drops[i] = Math.random() * -(height / fontSize); } function draw() { ctx!.fillStyle = "rgba(0, 0, 0, 0.07)"; ctx!.fillRect(0, 0, width, height); ctx!.font = `${fontSize}px "Courier New", monospace`; ctx!.textAlign = "center"; for (let i = 0; i < drops.length; i++) { const char = MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)]; const intensity = Math.min(0.6 + (drops[i] / (height / fontSize)) * 0.4, 1); const g = Math.floor(100 + 155 * intensity); ctx!.fillStyle = `rgba(40, ${g}, 60, 0.9)`; ctx!.shadowBlur = 6; ctx!.shadowColor = "#0f0"; const x = i * fontSize + fontSize / 2; const y = drops[i] * fontSize; ctx!.fillText(char, x, y); ctx!.shadowBlur = 0; drops[i] += 0.7 + Math.random() * 1.4; if (drops[i] * fontSize > height && Math.random() > 0.96) { drops[i] = 0; } } } function animate() { draw(); rafRef.current = requestAnimationFrame(animate); } animate(); function onResize() { width = window.innerWidth; height = window.innerHeight; canvas!.width = width; canvas!.height = height; } window.addEventListener("resize", onResize); return () => { cancelAnimationFrame(rafRef.current); window.removeEventListener("resize", onResize); }; }, []); return (

OmniAI

The future with OmniAI

{showWelcome && ( )}
); }