/* global React */ const { useState, useEffect, useRef } = React; // ========================================================= // Top Nav // ========================================================= function Nav({ onBook, bookLabel = "Book a discovery call", showAffiliates = true }) { const [condensed, setCondensed] = useState(false); // Condense the sticky header into a slim bar once the user scrolls off // the very top โ reclaims vertical space while reading. useEffect(() => { const onScroll = () => setCondensed(window.scrollY > 60); window.addEventListener("scroll", onScroll, { passive: true }); onScroll(); return () => window.removeEventListener("scroll", onScroll); }, []); return ( ); } function ArrowGlyph() { return ( ); } function StarGlyph() { return ( ); } function WhatsAppGlyph() { return ( ); } // ========================================================= // Sticky bottom CTA โ appears after scrolling past hero // ========================================================= function StickyCTA({ onBook, bookLabel = "Book a call" }) { const [on, setOn] = useState(false); useEffect(() => { const onScroll = () => { const y = window.scrollY; const h = window.innerHeight; const doc = document.documentElement.scrollHeight; // Wait until the actual hero is past, not just one viewport of scroll. // This matters on mobile, where the hero is taller than the viewport, // and the avail bar at the bottom of the hero would get covered by // the sticky CTA if we triggered on viewport-height alone. const hero = document.getElementById("top"); const heroBottom = hero ? hero.getBoundingClientRect().bottom + y : h * 0.9; setOn(y > heroBottom - 40 && y < doc - h * 1.4); }; window.addEventListener("scroll", onScroll, { passive: true }); onScroll(); return () => window.removeEventListener("scroll", onScroll); }, []); return (