// 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 });