// Сайт · Главная — 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 (
{/* NAV — шапка сайта */} {/* Выпадающее мобильное меню */} {isMobile && menuOpen && (
{navItems.map((x) => ( { if (x.onClick) { e.preventDefault(); x.onClick(); } setMenuOpen(false); }} style={{ padding: '16px 18px', color: 'inherit', textDecoration: 'none', borderTop: '1px solid rgba(26,26,30,0.12)', }}>{x.l} ))}
)} {/* HERO */}
● ai-команда на связи

Целое агентство.{' '} За подписку.

Стратеги, копирайтеры, дизайнеры, аналитики — теперь это одна AI-команда. Та же работа, та же логика — кратно дешевле.
{window.MagnetBtn ? scrollToId('pricing')}>запустить → : null} {window.MagnetBtn ? scrollToId('philosophy')} style={{ background: 'transparent', color: 'var(--ink)', border: '2px solid var(--ink)' }}> как это работает : null}
{/* Бегущая лента */} {window.Marquee && ( )} {/* О нас */}
{window.Philosophy && }
{/* Витрина тарифов */} {window.Pricing && } {/* FAQ */} {window.Faq && } {/* Контакты */} {window.Contacts && }
); } window.AppHome = AppHome;