/* global React */ const { useState, useEffect, useRef } = React; // ========================================================= // Top Nav // ========================================================= function Nav({ onBook }) { return ( ); } function ArrowGlyph() { return ( ); } // ========================================================= // Sticky bottom CTA — appears after scrolling past hero // ========================================================= function StickyCTA({ onBook }) { const [on, setOn] = useState(false); useEffect(() => { const onScroll = () => { const y = window.scrollY; const h = window.innerHeight; // appear after hero + first proof section, hide near footer const doc = document.documentElement.scrollHeight; setOn(y > h * 0.9 && y < doc - h * 1.4); }; window.addEventListener("scroll", onScroll, { passive: true }); onScroll(); return () => window.removeEventListener("scroll", onScroll); }, []); return (
Jay
Talk to Jay directly 30-min discovery · no pitch
); } // ========================================================= // Reveal-on-scroll wrapper // ========================================================= function Reveal({ children, as = "div", delay = 0, ...rest }) { const ref = useRef(null); useEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { setTimeout(() => el.classList.add("is-in"), delay); io.disconnect(); } }, { threshold: 0.15 } ); io.observe(el); return () => io.disconnect(); }, [delay]); const Tag = as; return ( {children} ); } Object.assign(window, { Nav, StickyCTA, Reveal, ArrowGlyph });