import React, { useEffect, useRef } from 'react'; // Single-file, GH Pages–friendly, no external asset imports. // Upgrades: // - Parallax XYZ layer stack reacting to mouse with depth mapping. // - 3D non-rotating "artifact core" with pointer tilt only. // - Glyphy, ultra-light typographic system using Lexend (200/300) + Montserrat. // - Accessible, reduced-motion-safe; no runtime state hooks. // - Self-tests kept & expanded; no external images. export default function Hero() { const orbRef = useRef(null); const layersRef = useRef([]); const rafRef = useRef(0); const mouseRef = useRef({ x: 0, y: 0 }); // Compute tilt for the core (no perpetual rotation) useEffect(() => { const onMove = (e) => { mouseRef.current.x = e.clientX; mouseRef.current.y = e.clientY; }; window.addEventListener('mousemove', onMove, { passive: true }); return () => window.removeEventListener('mousemove', onMove); }, []); // Animation loop to apply both tilt and parallax (rAF to coalesce) useEffect(() => { let running = true; const loop = () => { if (!running) return; const { innerWidth: w = 1, innerHeight: h = 1 } = window; const { x, y } = mouseRef.current; // Core tilt if (orbRef.current) { const { rx, ry } = computeTilt(x, y, w, h, 18); orbRef.current.style.transform = `rotateX(${rx}deg) rotateY(${ry}deg)`; } // Parallax on each layer const nx = (x / w - 0.5) * 2; // [-1,1] const ny = (y / h - 0.5) * 2; // [-1,1] for (const el of layersRef.current) { if (!el) continue; const depth = Number(el.dataset.depth || 0); // Smaller movement for deeper layers const dx = -nx * depth * 10; // px const dy = -ny * depth * 10; // px const dz = depth * 40; // px into screen el.style.transform = `translate3d(${dx}px, ${dy}px, ${-dz}px)`; } rafRef.current = requestAnimationFrame(loop); }; // Respect reduced motion const mq = window.matchMedia('(prefers-reduced-motion: reduce)'); if (mq.matches) return; // do not animate rafRef.current = requestAnimationFrame(loop); return () => { running = false; cancelAnimationFrame(rafRef.current); }; }, []); // Helper to attach refs for layers const layerRef = (i) => (el) => (layersRef.current[i] = el); return (
Immersive, intelligent, and autonomous systems