// components-nav.jsx — Top nav (static, sits over the hero painting) // + left vertical screen-progress nav. // // The top nav is NOT sticky — it scrolls away with the hero so it never // creates a colour seam against the painted screen backgrounds. Once it // scrolls out of view, the vertical ScreenNav on the left side takes // over as the persistent way to jump between screens. function Logo({ name, en }) { return ( {name} {en} ); } function Nav({ copy }) { const links = copy.nav.links || []; const hrefs = copy.nav.linkHrefs || []; return ( ); } /* ───────────────────────────────────────────────────────────── ScreenNav — vertical screen-progress nav on the left edge. Watches which screen is in view via IntersectionObserver and highlights the active item. Shows three items at a time: prev / active / next. Hidden on small screens. ───────────────────────────────────────────────────────────── */ function ScreenNav({ copy }) { const items = React.useMemo(() => [ { id: "screen-hero", num: copy.screens.hero.num, label: copy.screens.hero.label }, { id: "screen-world", num: copy.screens.world.num, label: copy.screens.world.label }, { id: "screen-characters", num: copy.screens.characters.num, label: copy.screens.characters.label }, { id: "screen-objects", num: copy.screens.objects.num, label: copy.screens.objects.label }, { id: "screen-events", num: copy.screens.events.num, label: copy.screens.events.label }, { id: "screen-writing", num: copy.screens.writing.num, label: copy.screens.writing.label }, { id: "screen-faq", num: copy.screens.faq.num, label: copy.screens.faq.label }, ], [copy]); const [active, setActive] = React.useState(0); const [visible, setVisible] = React.useState(false); // Observe each screen; pick the one with the largest intersection. React.useEffect(() => { const ratios = new Array(items.length).fill(0); const els = items.map((it) => document.getElementById(it.id)).filter(Boolean); const io = new IntersectionObserver((entries) => { entries.forEach((e) => { const idx = items.findIndex((it) => it.id === e.target.id); if (idx >= 0) ratios[idx] = e.intersectionRatio; }); let best = 0, bestR = -1; for (let i = 0; i < ratios.length; i++) { if (ratios[i] > bestR) { bestR = ratios[i]; best = i; } } setActive(best); // Hide while screen 1 (hero) is dominant; top nav covers that. setVisible(best > 0 || ratios[0] < 0.6); }, { threshold: [0, 0.25, 0.5, 0.75, 1] }); els.forEach((el) => io.observe(el)); return () => io.disconnect(); }, [items]); return ( ); } Object.assign(window, { Logo, Nav, ScreenNav });