diff --git a/src/components/layout/Footer.tsx b/src/components/layout/Footer.tsx index 443bd72..b5c2c15 100644 --- a/src/components/layout/Footer.tsx +++ b/src/components/layout/Footer.tsx @@ -20,16 +20,16 @@ const NAV = [ ], }, { - title: 'Platform', + title: 'Spend', color: '#FF2E88', // pink links: [ - { label: 'Why Now', href: '#why-now' }, + { label: 'The Difference', href: '#difference' }, { label: 'How It Works', href: '#how-it-works' }, { label: 'The Loop', href: '#the-loop' }, ], }, { - title: 'Company', + title: 'Live', color: '#8B3DFF', // purple links: [ { label: 'The Vision', href: '#the-vision' }, diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index cd751ff..aaddee5 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -11,18 +11,39 @@ const CREAM = '#FFFDF5'; /* Scroll distance (px) before the bar solidifies into the sticky sticker. */ const STICK_AFTER = 500; -const NAV_LINKS = [ - { label: 'Earn', href: '#how-it-works', color: '#C8FF37' }, // lime - { label: 'Spend', href: '#difference', color: '#FF2E88' }, // pink - { label: 'Live', href: '#the-vision', color: '#8B3DFF' }, // purple - { label: 'Why Now', href: '#why-now', color: GOLD }, +/* The page's 15 sections split into three ordered acts. Each nav tab jumps to + the start of its act, and the scroll-spy highlights whichever act you're in + (any section in `sections` lights that tab). Keep `sections` in page order. */ +const NAV_GROUPS = [ + { + label: 'Earn', + color: '#C8FF37', // lime + target: '#the-why', + sections: ['intro', 'the-why', 'difference', 'the-problem', 'the-shift'], + }, + { + label: 'Spend', + color: '#FF2E88', // pink + target: '#lyts', + sections: ['lyts', 'one-day', 'feelings', 'the-loop', 'why-now'], + }, + { + label: 'Live', + color: '#8B3DFF', // purple + target: '#how-it-works', + sections: ['how-it-works', 'old-vs-new', 'the-vision', 'our-belief', 'the-promise'], + }, ]; +/** Map a section id → the index of the act (nav group) that owns it. */ +const groupForSection = (id: string) => + NAV_GROUPS.findIndex((g) => g.sections.includes(id)); + export default function Header() { const [mobileOpen, setMobileOpen] = useState(false); const [hidden, setHidden] = useState(false); const [stuck, setStuck] = useState(false); - const [activeHash, setActiveHash] = useState(''); + const [activeGroup, setActiveGroup] = useState(-1); const mobileMenuRef = useRef(null); const lastScrollYRef = useRef(0); @@ -45,9 +66,9 @@ export default function Header() { return () => window.removeEventListener('scroll', onScroll); }, []); - // Lightweight scroll-spy so the current section's nav link lights up. + // Scroll-spy across every section → highlight whichever act (group) it's in. useEffect(() => { - const ids = NAV_LINKS.map((l) => l.href.replace('#', '')); + const ids = NAV_GROUPS.flatMap((g) => g.sections); const targets = ids .map((id) => document.getElementById(id)) .filter((el): el is HTMLElement => !!el); @@ -58,7 +79,7 @@ export default function Header() { const visible = entries .filter((e) => e.isIntersecting) .sort((a, b) => b.intersectionRatio - a.intersectionRatio)[0]; - if (visible) setActiveHash(`#${visible.target.id}`); + if (visible) setActiveGroup(groupForSection(visible.target.id)); }, { rootMargin: '-45% 0px -45% 0px', threshold: [0, 0.25, 0.5] }, ); @@ -86,7 +107,20 @@ export default function Header() { return () => { document.body.style.overflow = ''; }; }, [mobileOpen]); - const isActive = (href: string) => href === activeHash; + const isActive = (i: number) => i === activeGroup; + + /* Lenis smooth-scroll owns the page, so a native hash jump gets overridden + for far-away targets (that's why "Live" appeared dead). Drive the scroll + through Lenis directly, offsetting for the fixed header. */ + const handleNavClick = (e: React.MouseEvent, target: string) => { + const el = document.querySelector(target) as HTMLElement | null; + if (!el) return; // let the browser handle it if the section isn't mounted + e.preventDefault(); + setMobileOpen(false); + const lenis = (window as unknown as { lenis?: { scrollTo: (t: HTMLElement, o?: object) => void } }).lenis; + if (lenis?.scrollTo) lenis.scrollTo(el, { offset: -90, duration: 1.2 }); + else el.scrollIntoView({ behavior: 'smooth' }); + }; return (
@@ -140,11 +174,11 @@ export default function Header() {