// Helper: useInView hook (shared) const useInView = (threshold = 0.2) => { const ref = React.useRef(null); const [inView, setInView] = React.useState(false); React.useEffect(() => { if (!ref.current) return; const obs = new IntersectionObserver(([e]) => { if (e.isIntersecting) setInView(true); }, { threshold }); obs.observe(ref.current); return () => obs.disconnect(); }, [threshold]); return [ref, inView]; }; // Generic Bubble for sections beyond hero const Bubble = ({ side, text, time, status }) => { const isAgent = side === 'agent'; return (