// ZAO "FC" — Chemical products for wood protection const { useState, useEffect, useMemo, useRef } = React; const Icon = ({ path, size = 20, ...rest }) => ( {path} ); const I = { spark: <>, arrowRight: <>, check: , x: <>, plus: <>, minus: , compass: <>, target: <>, map: <>, layers: <>, zap: , dollar: <>, users: <>, briefcase: <>, mic: <>, building: <>, dot: , clock: <>, calendar: <>, mail: <>, moon: , sun: <>, sliders: <>, menu: <>, truck: <>, package: <>, shield: <>, calculator: <>, chevronDown: , }; // ----- CSS переменные для лесной темы ----- const surfaceAltLight = "#F0F7EE"; const surfaceAltDark = "#1A2E1E"; // ----- Цветовая тема: ЛЕСНАЯ (forest) ----- const colorTheme = { primary: "from-emerald-600 to-green-600", secondary: "from-emerald-700 to-green-600", gradient: "from-emerald-600 via-green-600 to-emerald-500", gradientBg: "from-emerald-100 to-green-100", gradientBgDark: "from-emerald-500/20 to-green-500/20", button: "bg-gradient-to-r from-emerald-700 to-green-700", buttonHover: "hover:bg-gradient-to-l from-emerald-700 to-green-700", text: "text-emerald-600", textHover: "text-emerald-700", light: "from-emerald-50 to-green-50", dark: "from-emerald-900/30 to-green-900/30", badge: "from-emerald-500 to-green-500", card: "from-emerald-800 via-green-800 to-emerald-700", accent: "from-emerald-900 via-green-900 to-emerald-800", }; // ----- Компонент для обновления CSS переменных ----- function ThemeStyleUpdater({ dark }) { React.useEffect(() => { const root = document.documentElement; if (!dark) { root.style.setProperty("--surface-alt", surfaceAltLight); } else { root.style.setProperty("--surface-alt", surfaceAltDark); } }, [dark]); return null; } // ---------- Header ---------- function Header({ t, lang, onSetLang, dark, onSetDark }) { const [scrolled, setScrolled] = useState(false); const [menuOpen, setMenuOpen] = useState(false); const drawerRef = useRef(null); const hamburgerRef = useRef(null); const firstLinkRef = useRef(null); useEffect(() => { const on = () => setScrolled(window.scrollY > 20); window.addEventListener("scroll", on, { passive: true }); return () => window.removeEventListener("scroll", on); }, []); useEffect(() => { if (!menuOpen) return; const onKey = (e) => { if (e.key === "Escape") setMenuOpen(false); }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [menuOpen]); useEffect(() => { if (!menuOpen) return; const onClick = (e) => { if ( drawerRef.current && !drawerRef.current.contains(e.target) && hamburgerRef.current && !hamburgerRef.current.contains(e.target) ) { setMenuOpen(false); } }; document.addEventListener("mousedown", onClick); document.addEventListener("touchstart", onClick); return () => { document.removeEventListener("mousedown", onClick); document.removeEventListener("touchstart", onClick); }; }, [menuOpen]); useEffect(() => { if (menuOpen && firstLinkRef.current) { firstLinkRef.current.focus(); } }, [menuOpen]); useEffect(() => { const mql = window.matchMedia("(min-width: 768px)"); const onChange = (e) => { if (e.matches) setMenuOpen(false); }; if (mql.addEventListener) mql.addEventListener("change", onChange); else mql.addListener(onChange); return () => { if (mql.removeEventListener) mql.removeEventListener("change", onChange); else mql.removeListener(onChange); }; }, []); const closeDrawer = () => setMenuOpen(false); const toggleTheme = () => onSetDark(!dark); return (
ЗАО «ФК» ЗАО «ФК»
{["ru", "en"].map(l => ( ))}
{t.navCta}
); } // ---------- Hero ---------- function Hero({ t }) { return (
{t.hero.badge}

{t.hero.h1pre}{" "} {t.hero.h1post}

{t.hero.lead}

{t.hero.meta.map((m, i) => (
{m}
))}
); } // ---------- Products ---------- function Products({ t, onOpenDetails }) { return (

{t.products.eyebrow}

{t.products.title}

{t.products.sub}

{t.products.items.map((p, i) => (

{p.name}

{p.shortDesc}

{p.tu}
{p.certificateLabel}

{p.price}

))}
); } // ---------- Product Details ---------- function ProductDetails({ t, activeTab, setActiveTab, isOpen, setIsOpen, lang }) { const tabs = t.productDetails.tabs; const currentTab = tabs.find(tab => tab.id === activeTab); const closeDetails = () => { setIsOpen(false); setActiveTab(undefined); }; if (!isOpen || activeTab === undefined || !currentTab) { return (

{t.productDetails.eyebrow}

{t.productDetails.title}

{t.productDetails.sub}

{lang === 'ru' ? 'Нажмите "Подробнее" на карточке товара, чтобы увидеть характеристики' : 'Click "More details" on a product card to see specifications'}

); } const content = currentTab.content; return (

{t.productDetails.eyebrow}

{t.productDetails.title}

{t.productDetails.sub}

{currentTab.name}

Состав: {content.composition}

Область применения: {content.application}

Расход: {content.consumption}

Фасовка: {content.packaging}

Срок годности: {content.shelfLife}

Условия хранения: {content.storage}

Преимущества: {content.advantages}

); } // ---------- Calculator ---------- function Calculator({ t }) { const [selectedProduct, setSelectedProduct] = useState(t.products.items[0]?.name || ""); const [area, setArea] = useState(""); const [treatmentType, setTreatmentType] = useState("planed"); const [fireGroup, setFireGroup] = useState("I"); const [khfMethod, setKhfMethod] = useState("surface"); const [f403Method, setF403Method] = useState("transport"); const [result, setResult] = useState(0); const [resultUnit, setResultUnit] = useState("кг"); const [dryResult, setDryResult] = useState(0); // только для Фоскон-Кострома-Плюс const getNumericArea = () => { if (area === "" || area === null || area === undefined) return 0; const num = parseFloat(area); return isNaN(num) ? 0 : num; }; React.useEffect(() => { const numericArea = getNumericArea(); let calculated = 0; let unit = "кг"; let calculatedDry = 0; if (numericArea === 0) { setResult(0); setResultUnit("—"); setDryResult(0); return; } switch (selectedProduct) { case "Фоскон-Кострома-Плюс": // Расход раствора if (fireGroup === "I") { calculated = numericArea * 500; // г/м² раствора } else { calculated = numericArea * 300; // г/м² раствора } unit = "кг (раствор)"; calculated = calculated / 1000; // Расход сухого порошка (30% от раствора) calculatedDry = calculated * 0.30; break; case "Фоскон 403": if (f403Method === "transport") { calculated = numericArea * 0.25; } else { calculated = numericArea * 0.75; } unit = "кг (на м³)"; break; case "ХМ-32": if (khfMethod === "surface") { if (treatmentType === "planed") { calculated = numericArea * 450; } else { calculated = numericArea * 750; } unit = "кг"; calculated = calculated / 1000; } else if (khfMethod === "soaking") { calculated = numericArea * 6; unit = "кг (на м³)"; } else { calculated = numericArea * 14; unit = "кг (на м³)"; } break; case "ХФ": if (khfMethod === "surface") { if (treatmentType === "planed") { calculated = numericArea * 450; } else { calculated = numericArea * 750; } unit = "кг"; calculated = calculated / 1000; } else if (khfMethod === "soaking") { calculated = numericArea * 6; unit = "кг (на м³)"; } else { calculated = numericArea * 12; unit = "кг (на м³)"; } break; default: calculated = numericArea * 0.2; unit = "кг"; } setResult(Math.round(calculated * 10) / 10); setResultUnit(unit); setDryResult(Math.round(calculatedDry * 10) / 10); }, [selectedProduct, area, treatmentType, fireGroup, khfMethod, f403Method]); const productOptions = t.products.items.map(p => p.name); const isFireProtect = selectedProduct === "Фоскон-Кострома-Плюс"; const isF403 = selectedProduct === "Фоскон 403"; const isDeepBioprotect = selectedProduct === "ХМ-32"; const isKhf = selectedProduct === "ХФ"; const showVolume = isF403 || (isKhf && khfMethod !== "surface") || (isDeepBioprotect && khfMethod !== "surface"); // Количество мешков (для сухого порошка) const bagsNeeded = isFireProtect && dryResult > 0 ? Math.ceil(dryResult / 30) : 0; return (

{t.calculator.eyebrow}

{t.calculator.title}

{t.calculator.sub}

{ const val = e.target.value; if (val === "" || /^\d*\.?\d*$/.test(val)) { setArea(val); } }} placeholder="0" className="w-full p-3 rounded-xl bg-[var(--surface-alt)] border border-[var(--border)] text-[var(--fg)] focus:outline-none focus:ring-2 focus:ring-emerald-500" />

Можно оставить пустым или ввести 0

{/* Выбор способа нанесения для ХМ-32 и ХФ */} {(isDeepBioprotect || isKhf) && (
)} {/* Выбор типа обработки для Фоскон 403 */} {isF403 && (
)} {/* Выбор типа древесины для поверхностного нанесения */} {((isDeepBioprotect || isKhf) && khfMethod === "surface") && (
)} {/* Выбор группы огнезащиты для Фоскон-Кострома-Плюс */} {isFireProtect && (
)} {/* Дополнительная информация */} {isF403 && f403Method === "transport" && (

🚚 Транспортный антисептик: 250 г/м³ (одна обработка).

)} {isF403 && f403Method === "capital" && (

🛡️ Капитальная защита: 750 г/м³ (2-3 слоя).

)} {isFireProtect && (

💡 Расход сухого порошка — 30% от расхода раствора. Мешки по 30 кг.

)}

{t.calculator.resultLabel}

{getNumericArea() === 0 ? "—" : `${result} ${resultUnit}`}

{isFireProtect && dryResult > 0 && ( <>

Сухой порошок

{dryResult} кг {bagsNeeded > 0 && ( (≈ {bagsNeeded} {bagsNeeded === 1 ? ' мешок' : bagsNeeded >= 2 && bagsNeeded <= 4 ? ' мешка' : ' мешков'} по 30 кг) )}

)}

* Расчёт ориентировочный

); } // ---------- Advantages ---------- function Advantages({ t }) { const icons = [I.shield, I.building, I.check, I.truck]; return (

{t.advantages.eyebrow}

{t.advantages.title}

{t.advantages.sub}

{t.advantages.items.map((a, i) => (

{a.title}

{a.description}

))}
); } // ---------- How to Order ---------- function HowToOrder({ t }) { return (

{t.order.eyebrow}

{t.order.title}

{t.order.sub}

{t.order.steps.map((s, i) => (
{i + 1}

{s.title}

{s.description}

))}
); } // ---------- About Company ---------- function AboutCompany({ t }) { return (

{t.about.eyebrow}

{t.about.title}

{t.about.description}

{t.about.stats.map((s, i) => (
{s.value}
{s.label}
))}
🏭

{t.about.cardTitle}

{t.about.cardText}

{t.about.emailLabel}
{t.about.email}
); } // ---------- Not This ---------- function NotThis({ t }) { return (

{t.notThis.eyebrow}

{t.notThis.title}

{t.notThis.items.map((it, i) => (

{it.title}

{it.description}

))}
); } // ---------- FAQ ---------- function FAQ({ t }) { const [open, setOpen] = useState(0); return (

{t.faq.eyebrow}

{t.faq.title}

{t.faq.items.map((it, i) => { const isOpen = open === i; return (
{isOpen && (

{it.a}

)}
); })}
); } // ---------- Final CTA ---------- function FinalCTA({ t }) { const [formSent, setFormSent] = useState(false); const handleSubmit = async (e) => { e.preventDefault(); const form = e.target; const formData = new FormData(form); const response = await fetch('/send.php', { method: 'POST', body: formData }); if (response.ok) { setFormSent(true); // Отправка события в Яндекс.Метрику (счётчик 109592018) if (typeof ym !== 'undefined') { ym(109592018, 'reachGoal', 'form_submit'); } } }; if (formSent) { return (

Спасибо за заявку!

Мы свяжемся с вами в ближайшее время.

); } return (
1 запрос · 24ч ответ

{t.cta.title}

{t.cta.sub}

* Согласие требуется в соответствии с Федеральным законом № 152-ФЗ «О персональных данных»

{t.cta.small}

); } // ---------- Footer ---------- function Footer({ t }) { return ( ); } // ---------- App ---------- function App() { const [lang, setLang] = useState(() => { try { const saved = localStorage.getItem("landing-lang"); if (saved === "ru" || saved === "en") return saved; } catch (e) {} return "ru"; }); const [dark, setDark] = useState(() => { try { const saved = localStorage.getItem("landing-dark"); if (saved === "true" || saved === "false") return saved === "true"; } catch (e) {} return true; }); const [activeDetailsTab, setActiveDetailsTab] = useState(undefined); const [detailsOpen, setDetailsOpen] = useState(false); const t = useMemo(() => window.DATA[lang], [lang]); React.useEffect(() => { document.documentElement.classList.toggle("dark", dark); document.documentElement.setAttribute("lang", lang); }, [dark, lang]); React.useEffect(() => { try { localStorage.setItem("landing-lang", lang); } catch (e) {} try { localStorage.setItem("landing-dark", String(dark)); } catch (e) {} }, [lang, dark]); const handleOpenDetails = (productId) => { setActiveDetailsTab(productId); setDetailsOpen(true); setTimeout(() => { const detailsSection = document.getElementById("details"); if (detailsSection) { const offset = 80; const elementPosition = detailsSection.getBoundingClientRect().top + window.pageYOffset; window.scrollTo({ top: elementPosition - offset, behavior: "smooth" }); } }, 50); }; if (!t) return
Loading...
; return ( <>