// App — root component, Tweaks wiring, scroll behaviour const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "heroVariant": "video-scroll", "accent": "premium", "gallery": "grid", "particlesOn": true }/*EDITMODE-END*/; const TG_SUPPORT_URL = "https://t.me/modelcoresupport"; const CONTACT_EMAIL = "aimodelcore@gmail.com"; const ACCENT_TO_ATTR = { premium:"premium", mint:"mint", violet:"violet", magenta:"magenta", mono:"mono" }; // tweaks-panel.jsx и sections.jsx экспортируют только через window — отдельные Babel-файлы не видят чужие const. const { useTweaks, TweaksPanel, TweakSection, TweakRadio, TweakToggle, Icon, Hero, Problems, Showcase, ConsistencyCompare, UseCases, Modules, Founder, Testimonials, GetStarted, ForWho, TgChannel, FaqList, FinalCTA, Footer, Lightbox, TG_CHANNEL_URL, FORM_ENDPOINT, } = window; function App() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); const [openPersona, setOpenPersona] = React.useState(null); const personaTriggerRef = React.useRef(null); const [headerVisible, setHeaderVisible] = React.useState(false); const handleOpenPersona = (p, el) => { personaTriggerRef.current = el ?? null; setOpenPersona(p); }; // Apply accent attribute to document root React.useEffect(() => { document.documentElement.setAttribute("data-accent", ACCENT_TO_ATTR[t.accent] || "premium"); }, [t.accent]); // Scroll progress + sticky header + background shift (--bg-n 0–160) React.useEffect(() => { let lastY = 0; const SCROLL_DELTA = 6; const bar = document.getElementById("scrollProg"); const onScroll = () => { const doc = document.documentElement; const max = doc.scrollHeight - doc.clientHeight; const y = window.scrollY; if (bar) bar.style.width = ((y / Math.max(1,max)) * 100).toFixed(2) + "%"; const p = max > 0 ? y / max : 0; const n = Math.round(160 * Math.sin(p * Math.PI)); document.documentElement.style.setProperty("--bg-n", String(n)); if (y < 120) { setHeaderVisible(false); } else if (y < lastY - SCROLL_DELTA) { setHeaderVisible(true); } else if (y > lastY + SCROLL_DELTA) { setHeaderVisible(false); } lastY = y; }; window.addEventListener("scroll", onScroll, { passive: true }); onScroll(); return () => window.removeEventListener("scroll", onScroll); }, []); // Reveal-on-scroll React.useEffect(() => { const els = document.querySelectorAll(".reveal"); const io = new IntersectionObserver((entries) => { entries.forEach(e => { if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); } }); }, { threshold: 0.12, rootMargin: "0px 0px -60px 0px" }); els.forEach(el => io.observe(el)); return () => io.disconnect(); }, []); const openTG = () => window.open(TG_CHANNEL_URL, "_blank", "noopener"); return ( <>
MODELCORE Телеграм