/* TABLEAU — App root + reveal-on-scroll + tweaks panel + focus bar */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"anchor": "accent",
"density": "default",
"photo": "raw",
"displayFont": "Cormorant Garamond"
}/*EDITMODE-END*/;
function App() {
const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
const [focus, setFocus] = React.useState(null);
React.useEffect(() => {
document.body.dataset.anchor = t.anchor;
document.body.dataset.density = t.density;
document.body.dataset.photo = t.photo;
document.documentElement.style.setProperty('--display', `"${t.displayFont}", Georgia, serif`);
}, [t]);
React.useEffect(() => {
const els = document.querySelectorAll('.reveal');
const io = new IntersectionObserver((entries) => {
entries.forEach(e => { if (e.isIntersecting) e.target.classList.add('in'); });
}, { threshold: 0.12 });
els.forEach(el => io.observe(el));
return () => io.disconnect();
}, []);
React.useEffect(() => {
const map = {
'top': { label: 'Reading', name: 'Intro', meta: 'Est. 2025 · Roeselare' },
'works': { label: 'Reading', name: 'Works', meta: '01 / 04' },
'customize': { label: 'Reading', name: 'Customize', meta: '02 / 04' },
'atelier': { label: 'Reading', name: 'Atelier', meta: '03 / 04' },
'contact': { label: 'Reading', name: 'Contact', meta: '04 / 04' },
};
const ids = Object.keys(map);
const onScroll = () => {
let current = 'top';
for (const id of ids) {
const el = document.getElementById(id);
if (!el) continue;
const r = el.getBoundingClientRect();
if (r.top < window.innerHeight * 0.55) current = id;
}
const isTop = window.scrollY < 200;
setFocus(isTop ? null : map[current]);
};
window.addEventListener('scroll', onScroll, { passive: true });
onScroll();
return () => window.removeEventListener('scroll', onScroll);
}, []);
return (
<>