// Сайт · Главная — Hero, бегущая лента, «О нас» и Витрина тарифов. // Каталог теперь — отдельная страница «Сайт - Каталог.html»; кнопки // витрины ссылаются туда напрямую. function AppHome() { const palette = { '--bg': '#f5ead4', '--ink': '#1a1a1e', '--accent': '#c96848', '--sub': '#e8ddc4', }; const isMobile = window.useIsMobile ? window.useIsMobile() : false; const [menuOpen, setMenuOpen] = React.useState(false); // На мобиле шапка ниже (бургер-кнопка), на десктопе — как было. const NAV_H = isMobile ? 72 : 96; const SECTION_H = `calc(100vh - ${NAV_H}px)`; const sidePad = isMobile ? 18 : 32; const scrollToId = (id) => { const el = document.getElementById(id); if (!el) return; const y = el.getBoundingClientRect().top + window.pageYOffset - NAV_H; window.scrollTo({ top: y, behavior: 'smooth' }); }; const scrollTop = () => window.scrollTo({ top: 0, behavior: 'smooth' }); const navItems = [ { l: 'услуги', onClick: () => scrollToId('pricing') }, { l: 'о нас', onClick: () => scrollToId('philosophy') }, { l: 'faq', onClick: () => scrollToId('faq') }, { l: 'контакты', onClick: () => scrollToId('contacts') }, { l: 'войти', href: '/login' }, ]; // Скролл к секции при заходе по якорю (/#pricing, /#faq и т.п.). // Секции (Pricing/Faq/Contacts) монтирует babel-standalone асинхронно, поэтому // браузер обрабатывает якорь когда #root ещё пустой и остаётся вверху. // Здесь ждём появления элемента ретраями и скроллим один раз на загрузку. React.useEffect(() => { const hash = window.location.hash; const id = hash && hash.length > 1 ? hash.slice(1) : ''; let cancelled = false; let timer = null; // Если пользователь сам начал прокручивать/взаимодействовать — отменяем // авто-скролл (программный smooth-scroll этих событий не вызывает). const userBail = () => { cancelled = true; }; if (id) { window.addEventListener('wheel', userBail, { passive: true }); window.addEventListener('touchstart', userBail, { passive: true }); window.addEventListener('keydown', userBail); let attempts = 0; const attempt = () => { if (cancelled) return; if (document.getElementById(id)) { scrollToId(id); return; } // нашли → скролл один раз и стоп if (attempts < 30) { attempts += 1; timer = setTimeout(attempt, 100); } // ~3с ожидания }; attempt(); } // Опционально: клик по якорю, когда пользователь уже на главной. const onHashChange = () => { const h = window.location.hash; if (h && h.length > 1) scrollToId(h.slice(1)); }; window.addEventListener('hashchange', onHashChange); return () => { cancelled = true; if (timer) clearTimeout(timer); window.removeEventListener('wheel', userBail); window.removeEventListener('touchstart', userBail); window.removeEventListener('keydown', userBail); window.removeEventListener('hashchange', onHashChange); }; }, []); return (