// VOELKER.AI — App entry with Tweaks
const { useEffect: useEffectApp } = React;
const DEFAULTS = /*EDITMODE-BEGIN*/{
"accent": "#FF08F5",
"theme": "dark",
"density": "comfortable",
"heroLayout": "split"
}/*EDITMODE-END*/;
const ACCENT_OPTIONS = [
"#FF08F5",
"#FF6A1A",
"#7B5CFF",
"#22D3A8",
];
function App() {
const [t, setTweak] = useTweaks(DEFAULTS);
useEffectApp(() => {
const root = document.documentElement;
root.style.setProperty("--accent", t.accent);
// recompute soft tints from accent
const hex = t.accent.replace("#", "");
const r = parseInt(hex.substring(0,2), 16);
const g = parseInt(hex.substring(2,4), 16);
const b = parseInt(hex.substring(4,6), 16);
root.style.setProperty("--accent-glow", `rgba(${r}, ${g}, ${b}, 0.45)`);
root.style.setProperty("--accent-soft", `rgba(${r}, ${g}, ${b}, 0.12)`);
root.style.setProperty("--accent-line", `rgba(${r}, ${g}, ${b}, 0.28)`);
root.setAttribute("data-theme", t.theme);
root.setAttribute("data-density", t.density);
document.body.setAttribute("data-hero", t.heroLayout);
}, [t]);
// Scroll reveal — bulletproof scroll-based check (no IO throttling issues)
useEffectApp(() => {
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
if (mq.matches) return;
const groups = [
".section-head",
".service",
".stat",
".step",
".usecase > div",
".keynote-item",
".testimonial",
".faq-item",
".contact .channels .ch",
".form",
];
const els = [];
groups.forEach((sel) => {
document.querySelectorAll(sel).forEach((el, i) => {
el.setAttribute("data-reveal", "");
el.style.setProperty("--reveal-delay", Math.min(i, 5) * 70 + "ms");
els.push(el);
});
});
let ticking = false;
function reveal() {
ticking = false;
const trigger = window.innerHeight - 60;
for (let i = els.length - 1; i >= 0; i--) {
const el = els[i];
if (el.getBoundingClientRect().top < trigger) {
el.classList.add("in-view");
els.splice(i, 1);
}
}
if (els.length === 0) {
window.removeEventListener("scroll", onScroll);
window.removeEventListener("resize", onScroll);
}
}
function onScroll() {
if (!ticking) {
ticking = true;
requestAnimationFrame(reveal);
}
}
reveal(); // initial pass for above-the-fold
window.addEventListener("scroll", onScroll, { passive: true });
window.addEventListener("resize", onScroll);
// Safety net: nothing should stay hidden if scripts/scroll misbehave
const safety = setTimeout(() => {
els.slice().forEach((el) => el.classList.add("in-view"));
}, 4000);
return () => {
window.removeEventListener("scroll", onScroll);
window.removeEventListener("resize", onScroll);
clearTimeout(safety);
};
}, []);
return (
<>
setTweak("accent", v)}
/>
setTweak("theme", v)}
/>
setTweak("density", v)}
/>
setTweak("heroLayout", v)}
/>
>
);
}
ReactDOM.createRoot(document.getElementById("root")).render();